05 January 2011

Adding Swap Space in FreeBSD

While it shouldn't occur too frequently, it is likely at some point as a
sysadmin, you will need to add additional swap space to a box.  At that
time, your options will be to use a free disk partition with suitable
space or to create a swapfile on an existing filesystem.  The following
details both partition and swapfile with the host info below:
        HOST:           beastie
        PROMPT:         beastie [0]
        OS:             FreeBSD 8.1
PARTITION:  If you already have a free partition that isn't being used
for anything else, adding it as swap space is trivial:
        beastie [0] /sbin/swapon /dev/da2s1a
Since I don't have any free partitions on a configured disk, I need to
create one on an available disk.  I check to see what disks the OS can
see via 'gpart' (check 'dmesg' for hosts prior to FreeBSD 7.0):
        beastie [0] /sbin/gpart show | /usr/bin/grep '=>'
        =>      63  21493647  da0  MBR  (10G)
        =>      63  21495726  da1  MBR  (10G)
        =>       0  21478842  da0s1  BSD  (10G)
        =>       0  21478842  da1s1  BSD  (10G)
        =>     32  1048544  da2  MBR  (512M)
        =>     32  1048544  da3  MBR  (512M)
I already know I'm not using 'da2' and from the above 'gpart' doesn't
show any slices for it, so we can use it to set up 'da2' for our new
swap partition:
        beastie [0] /bin/dd if=/dev/zero of=/dev/da2 bs=512 count=32
        32+0 records in
        32+0 records out
        16384 bytes transferred in 0.017235 secs (950621 bytes/sec)
        beastie [0] /sbin/fdisk -BI /dev/da2
        ******* Working on device /dev/da2 *******
        fdisk: invalid fdisk partition table found
        fdisk: Class not found
        beastie [0] /sbin/bsdlabel -w da2s1
        beastie [0] /sbin/bsdlabel -A da2s1
        # /dev/da2s1:
        type: unknown
        disk: amnesiac
        label:
        flags:
        bytes/sector: 512
        sectors/track: 32
        tracks/cylinder: 64
        sectors/cylinder: 2048
        cylinders: 511
        sectors/unit: 1048544
        rpm: 3600
        interleave: 1
        trackskew: 0
        cylinderskew: 0
        headswitch: 0           # milliseconds
        track-to-track seek: 0  # milliseconds
        drivedata: 0

        8 partitions:
        #        size   offset    fstype   [fsize bsize bps/cpg]
          a:  1048528       16    unused        0     0
          c:  1048544        0    unused        0     0         # "raw" part, don't edit
In the first command above, we've used 'dd' to destroy the boot block
and partition data on 'da2', then re-initialized the disk with 'fdisk'
in the second command.  This set up slice 1 (s1).  The errors from
'fdisk' are normal, simply telling you that before initializing 'da2',
fdisk couldn't read a valid partition table.  The "Class" error is because
'geom_mbr' isn't loaded, which can be safely ignored.  Following that,
the third command writes a generic partition table to 'da2s1' and the
fourth is simply verifying such.  The following adds the new partition
as swap space and shows the configured swap space before and after adding
'da2s1a':
        beastie [0] /sbin/swapon /dev/da2s1a

    before adding:

        beastie [0] /usr/sbin/swapinfo
        Device          1K-blocks     Used    Avail Capacity
        /dev/da0s1b       1048576        0  1048576     0%

    after adding:

        beastie [0] /usr/sbin/swapinfo
        Device          1K-blocks     Used    Avail Capacity
        /dev/da0s1b       1048576        0  1048576     0%
        /dev/da2s1a        524264        0   524264     0%
        Total             1572840        0  1572840     0%
To retain the freshly added space through a system reboot, add 'da2s1a'
to /etc/fstab as seen below:
        beastie [0] /usr/bin/grep swap /etc/fstab
        /dev/da0s1b           none          swap    sw        0       0
        /dev/da2s1a           none          swap    sw        0       0
SWAPFILE:  For the second option, locate an out of the way place on a
filesystem with adequate space for the swap file.  For our purposes,
we'll use '/opt/swapfile' for a new 512 MB swap file.  Below simply
checks to make sure that it doesn't already exist after ensuring the
directory exists:
        beastie [0] [ ! -d /opt ] && /bin/mkdir /opt
        beastie [0] /bin/ls /opt/swapfile
        ls: /opt/swapfile: No such file or directory
Now, use 'dd' to create '/opt/swapfile' with a size of 512 MB:
        beastie [1] /bin/dd if=/dev/zero of=/opt/swapfile bs=1k count=512k
        524288+0 records in
        524288+0 records out
        536870912 bytes transferred in 13.871350 secs (38703580 bytes/sec)
        beastie [0] /usr/bin/du -sh /opt/swapfile
        512M    /opt/swapfile
        beastie [0] /bin/chown root:wheel /opt/swapfile
        beastie [0] /bin/chmod 600 /opt/swapfile
After file creation, we've verified the file and size and updated it
with appropriate permissions.  The next step is use 'mdconfig' to create
a block device for '/opt/swapfile' and verify the device's creation:
        beastie [0] /sbin/mdconfig -l
        beastie [0] /sbin/mdconfig -a -t vnode -f /opt/swapfile -u 0
        beastie [0] /sbin/mdconfig -l
        md0   
Like with a swap partition, we can use 'swapon' to add block device
'/dev/md0' as usable swap space:
        beastie [0] /sbin/swapon /dev/md0
        beastie [0] /usr/sbin/swapinfo
        Device          1K-blocks     Used    Avail Capacity
        /dev/da0s1b       1048576        0  1048576     0%
        /dev/da2s1a        524264        0   524264     0%
        /dev/md0           524288        0   524288     0%
        Total             2097128        0  2097128     0%
To retain the swap file through a system reboot, update '/etc/rc.conf':
        beastie [0] /usr/bin/grep swapfile /etc/rc.conf
        swapfile="/opt/swapfile"

see also:
    Adding Swap Space in Solaris
    Adding Swap Space in Linux