How to Move /usr Directory Contents to a Separate LVM Logical Volume

This post describes how to move the contents of /usr directory to a separate LVM Logical Volume (LV). In the following example, the contents of the standard Linux directory /usr, residing beneath the root (/) filesystem of an Oracle Linux 7 (OL) system already using LVM, is moved to a dedicated filesystem on an LVM Logical Volume (LV). Though based on CentOS/RHEL 7, the procedure should similarly work for other releases e.g. CentOS/RHEL 8.

Given the disruptive nature of the procedure, it should only be performed within Linux Rescue Mode.

1. Calculate current /usr directory disk space usage. For example:

# du -sh /usr

2. Check for available space:

# vgdisplay
# fdisk -l

If insufficient space exists within the existing system VG to accommodate a new /usr e.g. LV lv_usr, grow the VG accordingly.

3. Add a new disk or partition to the system, then initialise for use by LVM. For example:

# pvcreate /dev/sda1

4. Create/Extend a volume group:

# vgcreate vg_newVolumeName /dev/sda1
# vgextend vg /dev/sda1

5. Display Volume Group attributes and check the space available Free PE / Size:

# vgdisplay vg_VolumeName

6. Create a logical volume in vg_newVolumeName. The following creates a new 6Gb LV lv_usr within VG (adjust the size accordingly with your needs. In this case we are using 6GB as an example):

# lvcreate -L 6G --name lv_usr vg_newVolumeName

7. Create a new filesystem for LV lv_usr:

# mkfs.xfs /dev/mapper/vg_newVolumeName-lv_usr

8. Mount new LV lv_usr to a temporary directory and copy contents of /usr into it. For example:

# mkdir /tmp/usrtmp
# mount /dev/mapper/vg_newVolumeName-lv_usr /tmp/usrtmp
# rsync -avz /usr/ /tmp/usrtmp/

9. Verify the contents of LV lv_usr matches that of the /usr directory:

# diff /usr/ /tmp/usrtmp/
# ls -la /usr/
# ls -la /tmp/usrtmp/
# du /usr/
# du /tmp/usrtmp/

10. Configure the system to permanently mount LV lv_usr. Use the blkid command to identify the UUID of the new filesystem atop LV lv_usr. For example:

# blkid

Take a note for the output. Add a new mount entry to file /etc/fstab.

# vi /etc/fstab
UUID=[uuid of lv_usr]   /usr   xfs   defaults     0 0

11. Restore SELinux Context:

# restorecon -vvFR /usr

12. Add the new VG/LV names to /etc/default/grub:

# vi /etc/default/grub
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rd.lvm.lv=rhel/usrlv rhgb quiet"

13. Regenerate the GRUB2 configuration:

For Legacy based machines:

# grub2-mkconfig -o /boot/grub2/grub.cfg

For UEFI based machines:

# grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg

14. Rebuild the initial RAM disk image file:

# cp /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.$(date +%m-%d-%H%M%S).bak
# dracut -v -f /boot/initramfs-$(uname -r).img $(uname -r)

15. Reboot the system and verify all services and applications operate correctly.

16. Once verified to work correctly, boot the system into rescue mode and remove the original /usr content.