Moving the swapfiles to a dedicated partition in Snow Leopard

Solution 1:

NOTE: See (also) a corrected/improved answer in the question itself.


Following solution worked for me:

Open a terminal and backup com.apple.dynamic_pager.plist which you're going to change in a second:

$ cd /System/Library/LaunchDaemons
$ sudo cp com.apple.dynamic_pager.plist{,_bak}

convert binary plist to xml:

$ sudo plutil -convert xml1 com.apple.dynamic_pager.plist

and open it with your favorite text editor

$ sudo vim com.apple.dynamic_pager.plist

it'll look something like this:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 <plist version="1.0">
 4 <dict>
 5     <key>EnableTransactions</key>
 6     <true/>
 7     <key>HopefullyExitsLast</key>
 8     <true/>
 9     <key>Label</key>
10     <string>com.apple.dynamic_pager</string>
11     <key>OnDemand</key>
12     <false/>
13     <key>ProgramArguments</key>
14     <array>
15         <string>/sbin/dynamic_pager</string>
16         <string>-F</string>
17         <string>/private/var/vm/swapfile</string>
18     </array>
19 </dict>
20 </plist>

In line 17 modify /private/var/vm/swapfile (e.g. /Volumes/partition2/swapfile), save and close your editor (":x" will do both in vim).

convert the plist file back to binary:

$ sudo plutil -convert binary1 com.apple.dynamic_pager.plist

After rebooting your Mac you should find the swapfiles in the directory you specified.

If you run into any problems you can restore the backup you created in the first step with:

$ cd /System/Library/LaunchDaemons
$ sudo cp com.apple.dynamic_pager.plist{_bak,}

Solution 2:

I've adopted this idea and taken it a bit further by addressing the growth and reclamation strategies.

Details at http://www.crypticide.com/dropsafe/article/3848 ; I would post a link to the "dynamicpagerwrapper" GoogleCode project page, but the blog tells me that I don't have enough reputation points...

Solution 3:

just a question: why not just editing the .plist file adding wait4path, instead of using the intermediate dynamic_pager_init ?

something like this:

EDIT: as explained in the comment by e.James and my following comment, the immediately following XML block is not good, both because there's an error (missing &&) and because only the first argument of the array ProgramArguments it's parsed as the program to run!

but.. (scroll down)

 ...
13     <key>ProgramArguments</key>
14     <array>
15         <string>/bin/wait4path</string>
16         <string>/Volumes/Swap/</string>
17         <string>/sbin/dynamic_pager</string>
18         <string>-F</string>
19         <string>/Volumes/Swap/.vm/swapfile</string>
20     </array>
 ...

end of the wrong xml block


this XML block should work instead:

   ...
    13     <key>ProgramArguments</key>
    14     <array>
    15         <string>/bin/bash</string>
    16         <string>-c</string>
    17         <string>/bin/wait4path /Volumes/Swap/ &amp;&amp; /sbin/dynamic_pager -F /Volumes/Swap/.vm/swapfile</string>
    18     </array>
     ...

please keep in mind that i still had not enough time to safely try this setting, but i tried to run various other shell commands launched in the same way, and everything should work as expected

How it works:

base: executing wait4path /path && command means that command is run only if wait4path ends and exits without errors, and this happens only when /path is an available path, so we can safely tell dynamic_pager to use that volume for swapfiles

1) as written in launchd.plist manpage, the keys Program and ProgramArguments are mapped to an execvp call, that means that everything but the first string in the array is treated as an argument for the first string in the array, the program to run;

2) as written in bash manpage, there is a bash -c <string> option to run the string passed as commands

1+2 = 3) what happens using this command line in a launchd plist ??

/bin/bash -c "wait4path /Volumes/Swap/ && /sbin/dynamic_pager -F /Volumes/Swap/.vm/swapfile"

/bin/bash is the program to run, -c is the first argument and the double quoted string is the second argument

I guess it should work exactly as your solution, without the intermediate script: launchd will start the service, that will wait for the given path and then launch dynamic_pager..

Please note that:
* the string that you want to execute should be double quoted if you run bash -c in Terminal, but it's not double quoted in the plist file! (i guess because it's already declared as a string with the proper tag)
* the two & in the string must be changed to &amp; in the plist file

PS: as always, proceed at your own risk, i take no responsibility for problems you may have using this setting !

thanks for sharing your work with us