Saturday, May 2, 2009

Resizing storage LUNs in Linux on the fly

I'm in the office working today and I figured out the best way (for me, anyway) to resize SAN LUNs without rebooting the server. I figured that I should document it.

To paraphase Linus, Only wimps use internal wikis: _real_ men just document their important stuff on blogs, and let the rest of the world aggregate it ;-)


Alright, the background first. Suppose I've got a SAN storage array, and I've created a LUN (essentially a disk segment) that I've presented to my server. Because I'm intelligent and plan ahead, I'm using LVM to manage it.

Lets say I make 50GB for "data". I make my physical volume on the device (in this case, /dev/sdb1), I create a volume group for it, vgData, and I create a logical volume inside of that one, lvData. I can now make an ext3 filesystem on /dev/vgData/lvData, and mount it to /mnt/data. I run "df -h" and it shows just under 50GB free. Awesome.

Now, I want to expand my 50GB drive. I need another 10GB, so I log into the console on the SAN storage box, and I resize the "data" virtual disk by 10GB. It's now sitting at 60GB. Step 1 complete.

Now, if the world were sane, you could do "fdisk -l /dev/sdb" and see the free space. But it isn't, and you can't. It will still happily report the old size. There are all sorts of google results for changing that, but I've found that none of them will actually do it until you perform the following steps.

Unmount /mnt/data:

# umount /mnt/data

Make the volume group unaccessible:

# vgchange -a n vgData

Unless you perform that last step, the lvm2-monitor service keeps the /dev/sdb1 device open, which means everything that we're going to perform next won't matter. You *HAVE* to stop all access to that disk (at least with the current CentOS kernel).

Now that the filesystem is unmounted and the device isn't in use, issue this command:

# echo "1" > /sys/class/scsi_device/$host:$channel:$id:$lun/device/rescan

where $host:$channel:$id:$lun are whatever combination of scsi path you have to your device. Mine was 2:0:0:0 since it was the first (zero'th?) disk on the 2nd controller. If you do an ls in /sys/class/scsi_device you'll see what is available on your system, and to my knowledge, rescanning the wrong controller won't hurt it, so if you screw up, it's not tragic.

Now if you have done things right, you should be able to run the fdisk -l /dev/sdb and see the new size reflected. Horray!

I fdisk'd in and added a 2nd partition (/dev/sdb2), ran pvcreate on it, extended the volume group on it, used lvextend, and then made it available with vgchange. [Edit] As anonymous mentioned in the comments, pvextend should also work at this point, though I haven't tested it yet. There's no reason it shouldn't.[/Edit] I finally mounted /dev/vgData/lvData and used resize2fs to grow it online. Now a "df -h" returns the "right" number, without ever having to reboot the machine.

Maybe in the future it will be possible to do it while the filesystem is "live", but for now, I'm using this technique since it's better than rebooting.

And if I'm wrong and you CAN do it with a live FS, please let me know. I'm very interested in a better way.