+
+ if (variable_sized) {
+ static char tmp[1024];
+ struct statfs sfs;
+ char *q;
+ int i;
+ int mib[4];
+ size_t len;
+ unsigned int size;
+ u_int64_t memsize;
+ u_int64_t fs_limit;
+
+ /*
+ * 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/4 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
+ */
+
+ /*
+ * 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;
+
+ if (statfs(tmp, &sfs) != -1) {
+ /*
+ * limit the maximum size of a swap file to 1/4 the free
+ * space available on the filesystem where the swap files
+ * are to reside
+ */
+ fs_limit = ((u_int64_t)sfs.f_bfree * (u_int64_t)sfs.f_bsize) / 4;
+
+ } else {
+ (void)fprintf(stderr, "usage: swap directory must exist\n");
+ exit(1);
+ }
+ 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 > 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 (size >= memsize)
+ break;
+
+ if (i) {
+ /*
+ * make the first 2 files the same size
+ */
+ size = size * 2;
+ }
+ max_valid++;
+ }
+ if (max_valid >= MAX_LIMITS)
+ max_valid = MAX_LIMITS - 1;
+
+ hi_water = HI_WATER_DEFAULT;
+ }