+
+ /*
+ * 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 TARGET_OS_EMBEDDED
+ paging_mode = get_paging_mode();
+ paging_mode_length = sizeof(paging_mode);
+
+ switch (paging_mode) {
+ case VM_PAGING_MODE_DISABLED:
+ /* Paging disabled; nothing to do here so exit */
+ exit(EXIT_SUCCESS);
+
+ case VM_PAGING_MODE_FREEZE:
+ /* Freeze mode; one swap file of fixed size, so enable and override defaults if set */
+ err = sysctlbyname(VM_FREEZE_SYSCTL, NULL, 0, &paging_mode, paging_mode_length);
+ if (err < 0) {
+ (void)fprintf(stderr, "dynamic_pager: cannot set %s\n", VM_FREEZE_SYSCTL);
+ exit(EXIT_FAILURE);
+ }
+ variable_sized = 0;
+ limits[0].size = FREEZE_FIXED_SWAP_SIZE;
+ break;
+
+ case VM_PAGING_MODE_DYNAMIC:
+ /* Dynamic paging selected; proceed normally */
+ break;
+
+ default:
+ /* Invalid option */
+ (void)fprintf(stderr, "dynamic_pager: invalid paging_mode %d\n", paging_mode);
+ exit(EXIT_FAILURE);
+ }
+#endif
+
+ 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);
+ exit(EXIT_FAILURE);
+ }
+ }
+ chown(tmp, 0, 0);
+
+ if (variable_sized) {
+ int i;
+ int mib[4];
+ size_t len;
+ unsigned int size;
+ u_int64_t memsize;
+ u_int64_t fs_limit = 0;
+
+ /*
+ * if we get here, then none of the following options were specified... -L, H, or -S
+ * drop into a new mode that scales the size of the swap file based on how much free
+ * space is left on the volume being used for swap and the amount of physical ram
+ * installed on the system...
+ * basically, we'll pick a maximum size that doesn't exceed the following limits...
+ * 1/8 the remaining free space of the swap volume
+ * the size of phsyical ram
+ * MAXIMUM_SIZE - currently set to 1 Gbyte...
+ * once we have the maximum, we'll create a list of sizes and low_water limits
+ * we'll start with 2 files of MINIMUM_SIZE - currently 64 Mbytes...
+ * subsequent entries will double in size up to the calculated maximum... the low_water
+ * limit will be the sum of the current file size and the previous file size for each entry...
+ * as we add or delete files, we'll use the current file_count as an index into this
+ * table... if it's beyond the table size, we'll use the last entry
+ * the table entry will determine the size of the file to be created and the new low_water mark...
+ * the high_water mark is set to HI_WATER_DEFAULT which must be smaller than MINIMUM_SIZE...
+ * currently it is set to 40,000,000 to match the size being requested by the application
+ * monitoring low space conditions... having it set to the same size keeps us from creating
+ * an additional swap file when it really isn't necessary
+ */
+
+ if (statfs(tmp, &sfs) == -1) {
+ /*
+ * We really can't get filesystem status,
+ * so let's not limit the swap files...
+ */
+ fs_limit = (u_int64_t) -1;
+ }
+
+ if (fs_limit != (u_int64_t) -1) {
+ /*
+ * Limit the maximum size of a swap file to 1/8 the free
+ * space available on the filesystem where the swap files
+ * are to reside. This will allow us to allocate and
+ * deallocate in finer increments on systems without much
+ * free space.
+ */
+ fs_limit = ((u_int64_t)sfs.f_bfree * (u_int64_t)sfs.f_bsize) / 8;
+ }
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_MEMSIZE;
+ len = sizeof(u_int64_t);
+
+ if (sysctl(mib, 2, &memsize, &len, NULL, 0) < 0) {
+ /*
+ * if the sysctl fails for some reason
+ * use the starting size as the default
+ */
+ memsize = MINIMUM_SIZE;
+ }
+ if (memsize > fs_limit)
+ /*
+ * clip based on filesystem space available
+ */
+ memsize = fs_limit;
+
+ /*
+ * further limit the maximum size of a swap file
+ */
+ if (memsize <= MINIMUM_SIZE) {
+ (void)fprintf(stderr, "dynamic_pager: Need more space on the disk to enable swapping.\n");
+ sleep(30);
+ goto retry;
+ } else if (memsize <= (MINIMUM_SIZE*2)) {
+ (void)fprintf(stderr, "dynamic_pager: Activating emergency swap file immediately.\n");
+ flags |= USE_EMERGENCY_SWAP_FILE_FIRST;
+ } else if (memsize > MAXIMUM_SIZE) {
+ memsize = MAXIMUM_SIZE;
+ }
+
+ size = MINIMUM_SIZE;
+
+ /*
+ * start small and work our way up to the maximum
+ * sized allowed... this way, we don't tie up too
+ * much disk space if we never do any real paging
+ */
+ for (max_valid = 0, i = 0; i < MAX_LIMITS; i++) {
+ limits[i].size = size;
+
+ if (i == 0)
+ limits[i].low_water = size * 2;
+ else {
+ if ((limits[i - 1].size / 2) > HI_WATER_DEFAULT)
+ limits[i].low_water = size + (limits[i - 1].size / 2);
+ else
+ limits[i].low_water = size + limits[i - 1].size;
+ }
+
+ if (i) {
+ /*
+ * make the first 2 files the same size
+ */
+ size = size * 2;
+ if (size > memsize)
+ break;
+ }
+ max_valid++;
+ }
+ if (max_valid >= MAX_LIMITS)
+ max_valid = MAX_LIMITS - 1;
+
+ hi_water = HI_WATER_DEFAULT;
+ }