Recently, the forkit.org server started running out of space on /home and /var. This isn't really a problem, for we use LVM, the Logical Volume Manager on marvin. LVM allows us to dynamically change the size of partitions. We currently have 2 147GB SCSI Ultra320 disks in a RAID1 configuration (mirrored). 15GB of that 147GB is unallocated. I wanted to add 10GB to /home and 2GB to /var. Given our historical usage patterns, this should allow us to live for another year or so before we need to look into more disk space, and leaves us 3GB for "emergency" expansions.

So, marvin is a production server. Obviously, since it is a hobby-machine, there are now SLAs or such, but a fair number of people depend on it for webhosting and email and the like. We try to minimize downtime as much as possible. I initially thought that I would be able to do the partition resizing without any downtime. The ext3 filesystem (which is what we use) supports online resizing, which should mean that I can resize the partition (using LVM), and the filesystem (using resize2fs) without needing to unmount on reboot the server. A Good Thing!

The typical mechanism to add 2GB to the /var partition would be:

# lvresize -L +2G /dev/mapper/vg-lv_var
# resize2fs /dev/mapper/vg-lv_var

I was able to do the lvresize portion - growing the partition. However, when I attempted to resize the filesystem, resize2fs complained:

# resize2fs /dev/mapper/vg-lv_var
resize2fs 1.40-WIP (14-Nov-2006)
Filesystem at /dev/mapper/vg-lv_var is mounted on /var; on-line resizing required
resize2fs: Filesystem does not support online resizing

Well, after a bit of Googling, it appears that our ext3 partition was created long enough ago that the default mkfs configuration did not include support for online resizing. Specifically, the resize_inode option was not set. Well, bummer. There is apparently a script out there that will set that option, but requires that the filesystem be offline when running. That doesn't really help us here, as the point is to avoid taking /var offline, which is a somewhat difficult thing to do on a running system, and even more difficult to do on a system that is remotely hosted.

So what is the solution? Well, as I just alluded to, we'll need to unmount /home and /var. /home can be done while the system is up, we just need to be careful to stop services like mail delivery and cron. /var is much more difficult to unmount. Lots of things need /var to run. You are much better served by booting into Single User Mode for doing work on the /var partition. Single User Mode isn't really a great option for us, as marvin is hosted in Louisville, KY, and I'm in Schenectady, NY. Luckily, Jeff (another marvin owner/operator) lives in Louisville, and can go in to get physical access if needed. This is our fallback.

The actual solution is to reboot marvin, force a fsck and insert the resizing commands into the boot sequence before non-root partitions are mounted.

To force the fsck is simple. First, create a file '/forcefsck'. This tells the boot system (on Debian systems at least) that a filesystem check should be run during the next boot. By default, this check won't fix errors automatically. This is fine for systems where you can sit there during boot, but colocated systems without network consoles like marvin should probably be set to automatically fix the errors. Do this by setting FSCKFIX=yes in /etc/rcS.d/S30checkfs.sh.

The next part, resizing the filesystems, requires writing a script to do the resize, and scheduling the script to run after the check of the filesystems, and before the mounting. This can be done by making a script called /etc/rcS.d/S32resize-disks. The scripts in /etc/rcS.d/ are run before the runlevel-dependent scripts, and basically initialize the system. The filesystems will be checked at any number after '30', and they are mounted by script S35mountall.sh. So using the number '32' insures the resize will happen after the check, and before the mounting.

> cat S32resize-disks
#!/bin/sh
PATH=/sbin:/bin
LOGFILE=/var/log/fsck/resize
logsave -as $LOGFILE resize2fs /dev/mapper/vg0-lv_var
logsave -as $LOGFILE resize2fs /dev/mapper/vg0-lv_home

The logsave prefix to the resize2fs command causes the output to be saved to the specified logfile, and stored in memory until /var is mounted.

Now, just reboot and hope! It took marvin approximately 30 minutes to do the reboot, fsck and resize. After boot, just remove the S32resize-disks script (don't need it to run on subsequent reboots). The /forcefsck file should have been removed automatically.

Enjoy your new space!