]> git.saurik.com Git - apple/system_cmds.git/blobdiff - dynamic_pager.tproj/dynamic_pager.c
system_cmds-854.11.2.tar.gz
[apple/system_cmds.git] / dynamic_pager.tproj / dynamic_pager.c
index e4d1cdab1f0d1f35cfc545b34a328896f3c77b77..deb9379c191e80c31b9b4738e0d600b5664b7621 100644 (file)
-/* File created by Chris Youngworth, Apple Computer 2/11/99 */
-
-
 #define mig_external
 
-#include <mach/port.h>
-#include <mach/mach_error.h>
-#include <mach/mach_traps.h>
-#include <mach/mach.h>
-#ifndef MACH_BSD
-#define MACH_BSD
-#endif
-#include <mach/bootstrap.h>
-#include <mach/mach_syscalls.h>
-#include <mach/mig_errors.h>
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/mman.h>
+#include <sys/mount.h>
 #include <sys/stat.h>
 #include <sys/sysctl.h>
-#include <sys/gmon.h>
-#include <errno.h>
-#include <kvm.h>
-#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <nlist.h>
-#include <ctype.h>
 #include <unistd.h> 
-#include <paths.h>
-
-#include <default_pager/default_pager_types.h>
-#include <default_pager_alerts_server.h>
-#include <backing_store_alerts.h>
-#include <backing_store_triggers_server.h>
-
-int    debug = 0;
-int    file_count = 0;
-int    low_water = 0;
-int    hi_water = 0;
-int    local_hi_water = 0;
-int    size  = 20000000;
-int    priority = 0;
-int    options = 0;
-char   fileroot[512];
-
-
-/* global parameters for application notification option */
-mach_port_t    trigger_port = MACH_PORT_NULL;
-mach_port_t    notify_port = MACH_PORT_NULL;
-int            notify_high = 0;
-int            bs_recovery;
+#include <dirent.h>
 
 /*
-void   setprof __P((struct kvmvars *kvp, int state));
-void   dumpstate __P((struct kvmvars *kvp));
-void   reset __P((struct kvmvars *kvp));
-*/
-
-
-
-mach_msg_return_t
-server_alert_loop(
-    mach_msg_size_t max_size,
-    mach_port_t rcv_name,
-    mach_msg_options_t options)
-{
-    mig_reply_error_t *bufRequest = 0, *bufReply = 0;
-    register mach_msg_return_t mr;
-    register kern_return_t kr;
-
-    if ((kr = vm_allocate(mach_task_self(),
-                     (vm_address_t *)&bufRequest,
-                     max_size + MAX_TRAILER_SIZE,
-                     TRUE)) != KERN_SUCCESS)
-      return kr;
-    if ((kr = vm_protect(mach_task_self(),
-                     (vm_address_t)bufRequest,
-                     max_size + MAX_TRAILER_SIZE,
-                    FALSE, VM_PROT_ALL)) != KERN_SUCCESS)
-      return kr;
-    mlock(bufRequest, max_size + MAX_TRAILER_SIZE);
-    if ((kr = vm_allocate(mach_task_self(),
-                     (vm_address_t *)&bufReply,
-                     max_size + MAX_TRAILER_SIZE,
-                     TRUE)) != KERN_SUCCESS)
-      return kr;
-    if ((kr = vm_protect(mach_task_self(),
-                     (vm_address_t)bufReply,
-                     max_size + MAX_TRAILER_SIZE,
-                    FALSE, VM_PROT_ALL)) != KERN_SUCCESS)
-      return kr;
-    mlock(bufReply, max_size + MAX_TRAILER_SIZE);
-    while(TRUE) {
-       mr = mach_msg_overwrite_trap(&bufRequest->Head, MACH_RCV_MSG|options,
-                                 0, max_size, rcv_name,
-                                 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL,
-                                 (mach_msg_header_t *) 0, 0);
-        if (mr == MACH_MSG_SUCCESS) {
-           /* we have a request message */
-
-           if(!(default_pager_alerts_server(
-                               &bufRequest->Head, &bufReply->Head)))
-               backing_store_triggers_server(
-                               &bufRequest->Head, &bufReply->Head);
-
-           if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
-               bufReply->RetCode != KERN_SUCCESS) {
-               if (bufReply->RetCode == MIG_NO_REPLY)
-                /*
-                 * This return code is a little tricky--
-                 * it appears that the demux routine found an
-                 * error of some sort, but since that error
-                 * would not normally get returned either to
-                 * the local user or the remote one, we pretend it's
-                 * ok.
-                 */
-
-               bufRequest->Head.msgh_remote_port = MACH_PORT_NULL;
-               mach_msg_destroy(&bufRequest->Head);
-              continue;
-           }
-
-           if (bufReply->Head.msgh_remote_port == MACH_PORT_NULL) {
-              /* no reply port, so destroy the reply */
-              if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)
-                  mach_msg_destroy(&bufReply->Head);
-          } else {
-               break;
-          }
-       } else {
-          break;
-       }   
-    } 
-
-    (void)vm_deallocate(mach_task_self(),
-                    (vm_address_t) bufRequest,
-                    max_size + MAX_TRAILER_SIZE);
-    (void)vm_deallocate(mach_task_self(),
-                    (vm_address_t) bufReply,
-                    max_size + MAX_TRAILER_SIZE);
-    return KERN_FAILURE;
-
-}       
-
-
-kern_return_t
-backing_store_triggers(dynamic_pager, hi_wat, flags, port)
-               mach_port_t     dynamic_pager;
-               int             hi_wat;
-               int             flags;
-               mach_port_t     port;
+ * We don't exit with a non-zero status anywhere here for 2 reasons:
+ * - the kernel can continue to create swapfiles in "/private/var/vm/swapfile<index>"
+ * - we want this job to run only once at boot and exit regardless of whether:
+ *     -- it could clean up the swap directory
+ *     -- it could set the prefix for the swapfile name.
+ */
+
+static void
+clean_swap_directory(const char *path)
 {
-       if((hi_wat + size) > low_water) 
-               return KERN_FAILURE; /* let ipc system clean up port */
-
-       /* If there was a previous registration, throw it away */
-       if (notify_port != MACH_PORT_NULL) {
-               mach_port_deallocate(mach_task_self(), notify_port);
-               notify_port = MACH_PORT_NULL;
+       DIR *dir;
+       struct dirent *entry;
+       char buf[1024];
+
+       dir = opendir(path);
+       if (dir == NULL) {
+               fprintf(stderr,"dynamic_pager: cannot open swap directory %s\n", path);
+               exit(0);
        }
 
-       notify_port = port;
-       notify_high = hi_wat;
-       if(hi_water < notify_high) {
-               local_hi_water = notify_high;
-       } else {
-               local_hi_water = hi_water;
-       }
-       if(notify_high > hi_water) {
-               default_pager_space_alert(trigger_port, HI_WAT_ALERT);
-       }
-       return KERN_SUCCESS;
-}
-
-
-kern_return_t
-default_pager_space_alert(alert_port, flags)
-       mach_port_t     alert_port;
-       int     flags;
-{
-       char subfile[512];
-       FILE *file_ptr;
-       off_t   filesize = size;
-       int     error;
-       kern_return_t   ret;
-
-       if(flags & HI_WAT_ALERT) {
-/* printf("HI WAT ALERT!!\n"); */
-               file_count++;
-               sprintf(subfile, "%s%d", fileroot, file_count);
-               file_ptr = fopen(subfile, "w+");
-               fchmod(fileno(file_ptr), (mode_t)01600);
-               error = fcntl(fileno(file_ptr), F_SETSIZE, &filesize);
-               if(error) {
-                       error = ftruncate(fileno(file_ptr), (off_t)size);
-               }
-               fclose(file_ptr);
-               if(error == -1) {
-                       unlink(subfile);
-                       file_count--;
-                       local_hi_water = local_hi_water>>2;
-                       if(notify_high >= (local_hi_water)) {
-                               if(notify_port != MACH_PORT_NULL) {
-                                       /* notify monitoring app of */
-                                       /* backing store shortage  */
-                                       backing_store_alert(notify_port,
-                                                               HI_WAT_ALERT);
-                                       mach_port_deallocate(mach_task_self(), 
-                                                               notify_port);
-                                       notify_port = MACH_PORT_NULL;
-                                       notify_high = 0;
-                               }
-                       }
-                       macx_triggers(local_hi_water, 
-                               low_water, HI_WAT_ALERT, alert_port);
-               } else {
-                       if(hi_water < notify_high) {
-                               if(local_hi_water < notify_high) {
-                                  bs_recovery = notify_high - local_hi_water;
-                               }
-                               local_hi_water = notify_high;
-                       } else {
-                               if(local_hi_water < hi_water) {
-                                  bs_recovery = hi_water - local_hi_water;
-                               }
-                               local_hi_water = hi_water;
-                       }
-                       ret = macx_swapon(subfile, flags, size, priority);
-                       if(ret) {
-                               unlink(subfile);
-                               file_count--;
-                               local_hi_water = local_hi_water>>2;
-                               if(notify_high >= (local_hi_water)) {
-                                       if(notify_port != MACH_PORT_NULL) {
-                                               /* notify monitoring app of */
-                                               /* backing store shortage  */
-                                               backing_store_alert(
-                                                       notify_port,
-                                                       HI_WAT_ALERT);
-                                               mach_port_deallocate(
-                                                       mach_task_self(), 
-                                                       notify_port);
-                                               notify_port = MACH_PORT_NULL;
-                                               notify_high = 0;
-                                       }
-                               }
-                               macx_triggers(local_hi_water, 
-                                       low_water, HI_WAT_ALERT, alert_port);
-                       } else if(bs_recovery <= size) {
-                               if((bs_recovery != 0) && (notify_port)) {
-                                       backing_store_alert(notify_port,
-                                                               LO_WAT_ALERT);
-                                       mach_port_deallocate(mach_task_self(), 
-                                                               notify_port);
-                                       notify_port = MACH_PORT_NULL;
-                                       notify_high = 0;
-                                       bs_recovery = 0;
-                               }
-                       } else 
-                               bs_recovery = bs_recovery-size;
+       while ((entry = readdir(dir)) != NULL) {
+               if (entry->d_namlen>= 4 && strncmp(entry->d_name, "swap", 4) == 0) {
+                       snprintf(buf, sizeof buf, "%s/%s", path, entry->d_name);
+                       unlink(buf);
                }
-       
-               macx_triggers(local_hi_water, 
-                       low_water, HI_WAT_ALERT, alert_port);
        }
-       if(flags & LO_WAT_ALERT) {
-/* Turn into a logged message printf("LO WAT ALERT!!\n"); */
-               sprintf(subfile, "%s%d", fileroot, file_count);
-               if(hi_water < notify_high) {
-                       local_hi_water = notify_high;
-               } else {
-                       local_hi_water = hi_water;
-               }
-               if((bs_recovery != 0) && (notify_port != MACH_PORT_NULL)) {
-                       backing_store_alert(notify_port, LO_WAT_ALERT);
-                       mach_port_deallocate(mach_task_self(), notify_port);
-                       notify_port = MACH_PORT_NULL;
-                       notify_high = 0;
-                       bs_recovery = 0;
-               }
-               if(macx_swapoff(subfile, flags) == 0) {
-                       unlink(subfile);
-                       file_count--;
-               }
-               macx_triggers(local_hi_water, low_water, LO_WAT_ALERT, alert_port);
-       }
-       return KERN_SUCCESS;
-}
 
-void
-wait_on_paging_trigger(trigger_port)
-       mach_port_t     trigger_port;
-{
-       kern_return_t   result;
-       result = server_alert_loop(4096, trigger_port, MACH_MSG_OPTION_NONE);
-       if (result != KERN_SUCCESS) {
-            fprintf(stderr, "dynamic_pager: default pager alert failed\n");
-            exit(1);
-       }
-       exit(0);
+       closedir(dir);
 }
 
-void
-paging_setup(flags, size, priority, low, high)
-       int     flags;
-       int     size;
-       int     priority;
-       int     low;
-       int     high;
-{
-       off_t           filesize = size;
-       char            subfile[512];
-       FILE            *file_ptr;
-       int             error;
-
-       file_count = 0;
-       sprintf(subfile, "%s%d", fileroot, file_count);
-       file_ptr = fopen(subfile, "w+");
-       fchmod(fileno(file_ptr), (mode_t)01600);
-       error = fcntl(fileno(file_ptr), F_SETSIZE, &filesize);
-       if(error) {
-       error = ftruncate(fileno(file_ptr), (off_t)size);
-       }
-       fclose(file_ptr);
-        
-       macx_swapon(subfile, flags, size, priority);
-       if(hi_water) {
-               mach_msg_type_name_t    poly;
-
-               daemon(0,0);
-
-               if (mach_port_allocate(mach_task_self(), 
-                               MACH_PORT_RIGHT_RECEIVE, 
-                               &trigger_port) != KERN_SUCCESS)  {
-                       fprintf(stderr,"allocation of trigger port failed\n");
-                       exit(1);
-               }
-               /* create a send right on our local port */
-               mach_port_extract_right(mach_task_self(), trigger_port,
-                       MACH_MSG_TYPE_MAKE_SEND, &trigger_port, &poly);
-               macx_triggers(high, low, HI_WAT_ALERT, trigger_port);
-               if(low) {
-                       macx_triggers(high, 
-                               low, LO_WAT_ALERT, trigger_port);
-               }
-               /* register control port for applications wishing to */
-               /* get backing store notifications or change dynamic */
-               /* pager settings. */
-               set_dp_control_port(mach_host_self(), trigger_port);
-               wait_on_paging_trigger(trigger_port); 
-       }
-        exit(0);
-}
 int
 main(int argc, char **argv)
 {
-       extern char *optarg;
-       extern int optind;
-       char default_filename[] = "/private/var/vm/swapfile";
        int ch;
+       static char tmp[1024];
+       struct statfs sfs;
+       char *q;
+       char fileroot[512];
 
        seteuid(getuid());
-       strcpy(fileroot, default_filename);
+       fileroot[0] = '\0';
 
-       while ((ch = getopt(argc, argv, "F:L:H:S:P:O:")) != EOF) {
+       while ((ch = getopt(argc, argv, "F:")) != EOF) {
                switch((char)ch) {
 
                case 'F':
                        strncpy(fileroot, optarg, 500);
                        break;
 
-               case 'L':
-                       low_water = atoi(optarg);
-                       break;
-               case 'H':
-                       hi_water = atoi(optarg);
-                       break;
-               case 'S':
-                       size = atoi(optarg);
-                       break;
-               case 'P':
-                       priority = atoi(optarg);
-                       break;
-
                default:
                        (void)fprintf(stderr,
-                           "usage: dynamic_pager [-F filename] [-L low water alert trigger] [-H high water alert trigger] [-S file size] [-P priority]\n");
-                       exit(1);
+                           "usage: dynamic_pager [-F filename]\n");
+                       exit(0);
                }
        }
-       local_hi_water = hi_water;
-       if((low_water != 0) && (low_water <= (size + hi_water))) {
-               (void)fprintf(stderr,  "usage: low water trigger must be larger than size + hi_water\n"); 
-               exit(1);
+
+       /*
+        * set vm.swapfileprefix if a fileroot was passed from the command
+        * line, otherwise get the value from the kernel
+        */
+       if (fileroot[0] != '\0') {
+               if (sysctlbyname("vm.swapfileprefix", NULL, 0, fileroot, sizeof(fileroot)) == -1) {
+                       perror("Failed to set swapfile name prefix");
+               }
+       } else {
+               size_t fileroot_len = sizeof(fileroot);
+               if (sysctlbyname("vm.swapfileprefix", fileroot, &fileroot_len, NULL, 0) == -1) {
+                       perror("Failed to get swapfile name prefix");
+                       /*
+                        * can't continue without a fileroot
+                        */
+                       return (0);
+               }
        }
-       argc -= optind;
-       argv += optind;
-       paging_setup(0, size, priority, low_water, hi_water);
+
+       /*
+        * get rid of the filename at the end of the swap file specification
+        * we only want the portion of the pathname that should already exist
+        */
+       strcpy(tmp, fileroot);
+       if ((q = strrchr(tmp, '/')))
+               *q = 0;
+
+       /*
+        * Remove all files in the swap directory.
+        */
+       clean_swap_directory(tmp);
+
+       if (statfs(tmp, &sfs) == -1) {
+               /*
+                * Setup the swap directory.
+                */
+
+               if (mkdir(tmp, 0755) == -1) {
+                       (void)fprintf(stderr, "dynamic_pager: cannot create swap directory %s\n", tmp);
+               }
+       }
+
+       chown(tmp, 0, 0);
+
        return (0);
 }