Resizing an ext3 partition using LVM2 on Debian

Last time, so long ago it isn't even funny, I walked through the process of migrating data from an old hard drive to a new, bigger hard drive, with the help of some LVM2 magic. In that case the partitions---more accurately logical volumes (LVs)---stayed intact, floating on top of the LVM2 mapping layer as physical volumes (PVs) were shuffled around beneath them. The ext3 file systems remained the same size they had been before the move in spite of the extra available disk space.

After making sure that things are backed up, and prior to starting this exercise, we will acquaint ourselves with the lay of the land. First, we see what file systems are currently mounted, limiting the output to only those of ext3 type with -t ext3.

# mount -t ext3
/dev/mapper/vg_elaine-lv_root on / type ext3 (rw,errors=remount-ro)
/dev/md1 on /boot type ext3 (rw)
/dev/mapper/vg_elaine-lv_home on /home type ext3 (rw)
/dev/mapper/vg_elaine-lv_tmp on /tmp type ext3 (rw)
/dev/mapper/vg_elaine-lv_usr on /usr type ext3 (rw)
/dev/mapper/vg_elaine-lv_var on /var type ext3 (rw)

Next, to demonstrate why an upgrade is desirable, we output the amount of disk free space (df), in byte-oriented form (-h as in "for humans"), of only ext3 file systems (-t ext3).

# df -h -t ext3
Filesystem            Size  Used Avail Use% Mounted on
                      496M  137M  334M  30% /
/dev/md1              130M   13M  110M  11% /boot
                       35G   20G   14G  59% /home
                      496M   19M  452M   4% /tmp
                      5.3G  543M  4.5G  11% /usr
                     1008M  153M  805M  16% /var

Note that the /home system is nearly two thirds full, and in absolute terms is unsuitable as a resource for scheduled backups of large sub-trees, which is what it is now needed for.

The pvscan command shows that the RAID set used as the foundation of this volume group (VG) has quit a bit of room that has not yet been allocated to any LVs.

# pvscan
  PV /dev/md2   VG vg_elaine   lvm2 [232.75 GB / 189.40 GB free]
  Total: 1 [232.75 GB] / in use: 1 [232.75 GB] / in no VG: 0 [0   ]
# lvscan
  ACTIVE            '/dev/vg_elaine/lv_root' [512.00 MB] inherit
  ACTIVE            '/dev/vg_elaine/lv_swap' [1.00 GB] inherit
  ACTIVE            '/dev/vg_elaine/lv_tmp' [512.00 MB] inherit
  ACTIVE            '/dev/vg_elaine/lv_var' [1.00 GB] inherit
  ACTIVE            '/dev/vg_elaine/lv_usr' [5.35 GB] inherit
  ACTIVE            '/dev/vg_elaine/lv_home' [35.00 GB] inherit

The plan is to take 150 GB of the available 190-ish GB and use it to make lv_home bigger. I will leave the rest alone for now in anticipation of the day when lv_root or perhaps lv_usr needs a little boost.

Three of the tools in the LVM2 suite seem to be interconnected somehow. They are lvresize, lvreduce and lvextend. From what I can tell, the latter pair are just the two operations that are possible with the first, and so I will use lvextend so that there is marginally less chance of doing damage.

The easy part

Making the LV bigger is very quick, and very easy.

# lvextend -L +150G /dev/vg_elaine/lv_home
  Extending logical volume lv_home to 185.00 GB
  Logical volume lv_home successfully resized

To verify, we can check like this.

# lvdisplay /dev/vg_elaine/lv_home
  --- Logical volume ---
  LV Name                /dev/vg_elaine/lv_home
  VG Name                vg_elaine
  LV UUID                OeNy9W-6MRf-BIGj-GJHE-gjRZ-Efps-oLch1U
  LV Write Access        read/write
  LV Status              available
  # open                 1
  LV Size                185.00 GB (sure enough, the volume has grown)
  Current LE             47360
  Segments               1
  Allocation             inherit
  Read ahead sectors     0
  Block device           253:5

But the file system itself is still relatively small.

# df -h /home
Filesystem            Size  Used Avail Use% Mounted on
                       35G   20G   14G  59% /home

The hard part

Now it's time to make the file system bigger. While there is some information around that suggests that online resizing (i.e. resizing without first unmounting) is possible with ext3 under the 2.6 kernel, I would consider that brash at best.

The command we're about to use is resize2fs. The manpage claims that if the size parameter is omitted, it will grow the file system to completely fill the underlying device. Therefore the only parameters will be the device and the -p option to show progress.

Incidentally, resize2fs requires that you perform a consistency check on the file system so that it is marked "clean" prior to resizing it. This is not specified in the manpage, but if you try skipping this step, you'll be reminded.

The whole process is supposed to happen in four, closely spaced operations: 1) unmount the file system; check it; 3) resize it; and 4) remount it. If #3 breaks, I don't know whether there will be any alternative to wiping the device, creating a new file system from scratch, and restoring the /home subtree from the backup, but I am fully prepared to do that if this goose flies south.

In order to unmount /home, I will first have to release it by performing an NFS unexport as follows.

# exportfs -u ClientIP:/home

Here goes.

# umount /home

# e2fsck -f /dev/mapper/vg_elaine-lv_home
e2fsck 1.40-WIP (14-Nov-2006)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
home: 3166/4587520 files (2.7% non-contiguous), 5131561/9175040 blocks

# resize2fs -p /dev/mapper/vg_elaine-lv_home
resize2fs 1.40-WIP (14-Nov-2006)
Resizing the filesystem on /dev/mapper/vg_elaine-lv_home to 48496640 (4k) blocks.
Begin pass 1 (max = 1200)
The filesystem on /dev/mapper/vg_elaine-lv_home is now 48496640 blocks long.

# mount /home

Everything looks good. Let's see what df says.

# df -h /home
Filesystem            Size  Used Avail Use% Mounted on
                      183G   20G  154G  12% /home

No twitching, or hiccups. No smell of smoke. I think it's safe to unclench.

The tool versions used above are as follows.

# cat /etc/debian_version
# lvm version
  LVM version:     2.02.07 (2006-07-17)
  Library version: 1.02.08 (2006-07-17)
  Driver version:  4.7.0
# uname -r
# df --version
df (GNU coreutils) 5.97
# resize2fs
resize2fs 1.40-WIP (14-Nov-2006)