Resize Your Existing FreeBSD Root Partition/Slice Safely Without Re-Installing

There comes a time when your FreeBSD root partition is just too small to be of any use. You've already moved /var, /usr, and /tmp to separate disks and there just isn't anything else you can delete. The problem being that you initially created the partition to be too small when FreeBSD was first setup.

There are some guides out there that suggest to backup and start over. Others will tell you to use a dump and restore method. All that is too complicated and too much work for us lazy system administrators. Fortunately with recent versions of FreeBSD (9.0 and above) there is a handy little tool called "gpart".

Requirements

  • FreeBSD 9.0 or later (if you have a lesser version, you might be able to get away with using a 9.x live CD)
  • FreeBSD 9.x or later boot-only media. (ISO or flash image)
  • Extra or unused space on the drive where the root partition is stored.
  • A backup of your most precious files stored on this system
  • This guide assumes you are using a single non-RAID IDE/SATA or SCSI disk. Device names may be different and extra drivers may need to be loaded for other types of disks.
  • Preparation

    First, create a backup of every important item stored on this system. Don't skip this step! The extra time and effort you spend creating a backup will be worth it when something goes wrong. If this system is a virtual machine, take a snapshot. Just make sure you have a backup of your stuff before you continue.

    Make Some Room

    Before we can expand the root partition (or slice) on our FreeBSD system we need some room to grow. More than likely if you have already moved your /usr and /var partitions to separate disks, you are going to have some extra unused space on the drive. If you have not done this, now is the time to do so since we need the extra room. The best way to do this is to use the dump and restore method. I won't cover that here, but there are many articles written on the Internet that explain it clearly.

    Once you have determined that you have plenty of extra space, lets go ahead and do some re-arranging. Take for example the following disk:

    gpart show ada0s1
    =>       0  71119692  ada0s1  BSD  (33G)
                   0   1048576      1  freebsd-ufs  (512M)
       1048576   2029408      2  freebsd-swap  (990M)
       3077984   3110912      4  freebsd-ufs  (1.5G)
       6188896   1048576      5  freebsd-ufs  (512M)
       7237472  63882220      6  freebsd-ufs  (30G)

    Our OLD /var and /usr slices used to be on 4 and 6. Currently /tmp is on 5 and our swap space is on 2. That means we can delete slices 4 and 6 because they are no longer in use, those have been moved to another disk.

    Before you do anything, confirm it:

    df -h
    Filesystem                           Size    Used   Avail Capacity  Mounted on
    /dev/ad0s1a                          512M    256M    256M    50%    /
    devfs                                1.0k    1.0k      0B   100%    /dev
    /dev/ad0s1e                           512M    2.1M    510M     0%    /tmp
    /dev/da0s1d                          193G     31G    147G    17%    /usr
    /dev/ad1s1d                          116G     15G     91G    14%    /var

    Notice that in this example slices 4(d) and 6(f) on the block device "ada0s1" are not mounted and therefore not in use. Make sure you check /etc/fstab too just to be sure.

    Go ahead and delete the un-used slices:

    gpart delete -i 4 ada0s1
    gpart delete -i 6 ada0s1

    The above commands should return a conformation stating that the selected slice was deleted (for example "ada0s1p4 deleted"). Now when we look at the disk again we will have two areas of free space:

    gpart show ada0s1
    =>       0  71119692  ada0s1  BSD  (33G)
                   0   1048576      1  freebsd-ufs  (512M)
       1048576   2029408      2  freebsd-swap  (990M)
       3077984   3110912      - free -  (1.5G)
       6188896   1048576      5  freebsd-ufs  (512M)
       7237472  63882220     - free -  (30G)

    Even though we have some free space, it's not very useful in it's current location and layout. Notice how our swap and /tmp slices are blocking the way to grow the root partition. We need to do some additional re-arranging. Ideally I would move the /tmp and swap to a separate disk. You could also create a new /tmp and swap at the end of the drive.

    Assuming you will use a new disk, you first need to partition it. In this example, the new disk has been identified as /dev/da1. You can look at "/var/run/dmesg.boot" for information about what devices have been detected. Issue the following command to initialize the disk as a GPT type disk.

    gpart create -s gpt da1

    The result should be something like "da1 created".

    Next create and format the new partition for /tmp:

    gpart add -s 5G -t freebsd-ufs da1
    newfs /dev/da1p1

    Make sure it's mountable and finally set the correct permissions:

    mkdir /mnt/tmpnew
    mount /dev/da1p1 /mnt/tmpnew
    chmod 1777 /mnt/tmpnew

    This is only a 10 GB disk so lets just use the rest of the drive for swap by omitting the "-s" parameter:

    gpart add -t freebsd-swap da1

    The above commands should have return something like "da1p1 added". The next step is to modify /etc/fstab and update the device names for swap and /tmp. Using FreeBSD's easy editor (edit /etc/fstab), open up the file and make the changes according to your setup. In the example below I simply commented out the old devices and added in the new ones.

    # Device Mountpoint FStype Options Dump Pass#
    /dev/da1p2 none swap sw 0 0
    #/dev/ad0s1b none swap sw 0 0
    /dev/ad0s1a / ufs rw 1 1
    /dev/da1p1 /tmp ufs rw 2 2
    #/dev/ad0s1e /tmp ufs rw 2 2
    /dev/da0s1d /usr ufs rw 2 2
    /dev/ad1s1d /var ufs rw 2 2
    /dev/acd0 /cdrom cd9660 ro,noauto 0 0

    Reboot your system and hope it comes back! This is why we make backups.

    99% of the time the system should boot up normally without any problem. If it does not, boot into single user mode and review the /etc/fstab file. Revert back to the old values and start over if necessary.

    It's time to delete the old swap and /tmp slices. In our case they are slices 2 and 5:

    gpart delete -i 2 ada0s1
    gpart delete -i 5 ada0s1

    Now we have lots of free space with room to grow

    Re-size the Root Partition

    With plenty of free space available, it's now possible to expand the size of the root partition:

    gpart show ada0s1
    =>       0  71119692  ada0s1  BSD  (33G)
                   0   1048576      1  freebsd-ufs  (512M)
       1048576   63882220     - free -  (32.5G)

    In order to re-size the root partition we need to boot into a FreeBSD Live CD environment. Create your live media using the image you downloaded and boot the system to it. Select "Live CD" when asked and you'll be dropped into a shell prompt. Use the gpart tool to re-size the root partition to the maximum size by omitting the "-s" parameter:

    gpart resize -i 1 ada0s1

    The root partition has now been expanded to fill the whole drive:

    gpart show ada0s1
    =>       0  71119692     ada0s1  BSD  (33G)
             0  71119692     1  freebsd-ufs  (33G)

    Next use the "growfs" tool to expand the UFS filesystem. Again you can omit the size parameter to have it automatically use all available space:

    growfs /dev/ada0s1

    Type "Yes" to proceed when asked, after which you'll see some output stating the locations of some new super block backups. Once complete reboot your system normally.

    Mission Complete

    When your system comes back (hopefully), use "gpart show" to verify the new partition layouts and sizes. You'll see that your root file system is larger and has more free space:

    gpart show
    =>       63  419430337  da0  MBR  (200G)
             63  419424957    1  freebsd  [active]  (200G)
      419425020       5380       - free -  (2.6M)

    =>        0  419424957  da0s1  BSD  (200G)
              0  419424957      4  freebsd-ufs  (200G)

    =>      34  20971453  da1  GPT  (10G)
            34  10485760    1  freebsd-ufs  (5.0G)
      10485794  10485693    2  freebsd-swap  (5G)

    =>      63  71184249  ada0  MBR  (33G)
            63  71184249     1  freebsd  [active]  (33G)
      20971440        80        - free -  (40k)

    =>       0  71184249  ada0s1  BSD  (33G)
             0  71184249       1  freebsd-ufs  (33G)

    More free space.

    df -h
    Filesystem                           Size    Used   Avail Capacity  Mounted on
    /dev/ad0s1a                          33G    575M    32.5G     1%    /
    devfs                                1.0k    1.0k      0B   100%    /dev
    /dev/da1p1                           4.9G    2.1M    4.5G     0%    /tmp
    /dev/da0s1d                          193G     31G    147G    17%    /usr
    /dev/ad1s1d                          116G     15G     91G    14%    /var
    Pacy
    Powered by Pacy