X-Git-Url: https://git.saurik.com/apple/system_cmds.git/blobdiff_plain/1c51fdde6f257ffe2a1b92d1a783dab947211e95..d52496fdbb8dd3d53ac142500a42d06f3720ea6c:/dynamic_pager.tproj/dynamic_pager.c diff --git a/dynamic_pager.tproj/dynamic_pager.c b/dynamic_pager.tproj/dynamic_pager.c index 30375b2..deb9379 100644 --- a/dynamic_pager.tproj/dynamic_pager.c +++ b/dynamic_pager.tproj/dynamic_pager.c @@ -1,369 +1,114 @@ -/* File created by Chris Youngworth, Apple Computer 2/11/99 */ - - #define mig_external -#include -#include -#include -#include -#ifndef MACH_BSD -#define MACH_BSD -#endif -#include -#include -#include -#include -#include -#include +#include #include #include -#include -#include -#include -#include #include #include #include -#include -#include #include -#include - -#include -#include -#include -#include - -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 = NULL; -mach_port_t notify_port = NULL; -int notify_high = 0; -int bs_recovery; +#include /* -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" + * - 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 */ - notify_port = port; - notify_high = hi_wat; - if(hi_water < notify_high) { - local_hi_water = notify_high; - } else { - local_hi_water = hi_water; + 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); } - 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; - - 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); - 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) { - /* notify monitoring app of */ - /* backing store shortage */ - backing_store_alert(notify_port, - HI_WAT_ALERT); - mach_port_deallocate(mach_task_self(), - notify_port); - notify_high = 0; - notify_port = 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; - } - macx_swapon(subfile, flags, size, priority); - 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_high = 0; - notify_port = NULL; - - 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)) { - backing_store_alert(notify_port, LO_WAT_ALERT); - mach_port_deallocate(mach_task_self(), notify_port); - notify_high = 0; - notify_port = NULL; - - 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; - - file_count = 0; - sprintf(subfile, "%s%d", fileroot, file_count); - file_ptr = fopen(subfile, "w+"); - fchmod(fileno(file_ptr), (mode_t)01600); - fcntl(fileno(file_ptr), F_SETSIZE, &filesize); - 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); + } + } + + /* + * 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); + } } - argc -= optind; - argv += optind; - paging_setup(0, size, priority, low_water, hi_water); + + chown(tmp, 0, 0); + return (0); }