Reduce One LVM Partition and Increase Another Safely in Linux

Problem Overview

  • When storage in one logical volume becomes insufficient (for example, /var or /home filling up), but another logical volume in the same volume group still has unused space, we may want to reduce that LV and transfer the freed space to the volume that needs growth.

  • This process needs to be planned carefully because shrinking an LV, especially on a live system it can lead to data loss if it is not supported by the filesystem or if the steps are performed incorrectly.

Prerequisites

Before starting, make sure the following conditions are met:

  • Backup of the LV for which we are going to reduce
  • No active process is running in that particular mount point
  • You have validated the current usage and target size carefully

Solution

  • Check the current size and usage of /data using lsblk and df -h

    • [root@pythonlinuxhub ~]# lsblk
      NAME             MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
      sda                8:0    0   20G  0 disk
      ├─sda1             8:1    0    1G  0 part /boot
      └─sda2             8:2    0   19G  0 part
        ├─rhel_10-root 253:0    0   17G  0 lvm  /
        └─rhel_10-swap 253:1    0    2G  0 lvm  [SWAP]
      sdb                8:16   0    6G  0 disk
      ├─sdb1             8:17   0    1G  0 part
      │ └─rhel_10-home 253:2    0 1020M  0 lvm  /home
      └─sdb2             8:18   0    2G  0 part
        └─rhel_10-data 253:3    0    2G  0 lvm  /data
      sr0               11:0    1 1024M  0 rom
      [root@pythonlinuxhub ~]# df -h /data /home
      Filesystem                Size  Used Avail Use% Mounted on
      /dev/mapper/rhel_10-data  2.0G   47M  1.9G   3% /data
      /dev/mapper/rhel_10-home  956M   48M  909M   5% /home
  • Verify VG and LV details using pvs, vgs, and lvs to confirm capacity

    • [root@pythonlinuxhub ~]# pvs
        PV         VG      Fmt  Attr PSize    PFree
        /dev/sda2  rhel_10 lvm2 a--   <19.00g    0
        /dev/sdb1  rhel_10 lvm2 a--  1020.00m    0
        /dev/sdb2  rhel_10 lvm2 a--    <2.00g    0
      [root@pythonlinuxhub ~]# vgs
        VG      #PV #LV #SN Attr   VSize   VFree
        rhel_10   3   4   0 wz--n- <21.99g    0
      [root@pythonlinuxhub ~]# lvs
        LV   VG      Attr       LSize    Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
        data rhel_10 -wi-ao----   <2.00g
        home rhel_10 -wi-ao---- 1020.00m
        root rhel_10 -wi-ao----  <17.00g
        swap rhel_10 -wi-ao----    2.00g
  • Take a full backup of the /data directory to another storage location and stop applications/services using /data

  • Unmount /data

    • [root@pythonlinuxhub ~]# umount /dev/mapper/rhel_10-data
  • Remove the existing LV for /data (after confirming backup integrity)

    • [root@pythonlinuxhub ~]# lvremove /dev/rhel_10/data
      Do you really want to remove active logical volume rhel_10/data? [y/n]: y
        Logical volume "data" successfully removed.
  • Create a new LV for /data with a smaller size

    • [root@pythonlinuxhub ~]# lvcreate -L 1.5GB -n data rhel_10
      WARNING: xfs signature detected on /dev/rhel_10/data at offset 0. Wipe it? [y/n]: y
        Wiping xfs signature on /dev/rhel_10/data.
        Logical volume "data" created.
  • Create the filesystem (XFS format, since shrink is not supported)

    • [root@pythonlinuxhub ~]# mkfs.xfs /dev/rhel_10/data
      meta-data=/dev/rhel_10/data      isize=512    agcount=4, agsize=98304 blks
               =                       sectsz=512   attr=2, projid32bit=1
               =                       crc=1        finobt=1, sparse=1, rmapbt=0
               =                       reflink=1    bigtime=1 inobtcount=1 nrext64=0
      data     =                       bsize=4096   blocks=393216, imaxpct=25
               =                       sunit=0      swidth=0 blks
      naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
      log      =internal log           bsize=4096   blocks=16384, version=2
               =                       sectsz=512   sunit=0 blks, lazy-count=1
      realtime =none                   extsz=4096   blocks=0, rtextents=0
  • Mount the new LV back on /data

    • [root@pythonlinuxhub ~]# mount /dev/rhel_10/data
  • Restore the backed-up data into /data

  • Validate using df -h, pvs, vgs, and lvs. The VG should now show free space

    • [root@pythonlinuxhub ~]# df -h /home /data
      Filesystem                Size  Used Avail Use% Mounted on
      /dev/mapper/rhel_10-home  956M   48M  909M   5% /home
      /dev/mapper/rhel_10-data  1.5G   43M  1.4G   3% /data
      [root@pythonlinuxhub ~]# pvs
        PV         VG      Fmt  Attr PSize    PFree
        /dev/sda2  rhel_10 lvm2 a--   <19.00g      0
        /dev/sdb1  rhel_10 lvm2 a--  1020.00m      0
        /dev/sdb2  rhel_10 lvm2 a--    <2.00g 508.00m
      [root@pythonlinuxhub ~]# vgs
        VG      #PV #LV #SN Attr   VSize   VFree
        rhel_10   3   4   0 wz--n- <21.99g 508.00m
      [root@pythonlinuxhub ~]# lvs
        LV   VG      Attr       LSize    Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
        data rhel_10 -wi-ao----    1.50g
        home rhel_10 -wi-ao---- 1020.00m
        root rhel_10 -wi-ao----  <17.00g
        swap rhel_10 -wi-ao----    2.00g
  • Ensure a correct /etc/fstab entry is present for persistence

  • Extend the /home LV using the free space available in the VG

    • [root@pythonlinuxhub ~]# lvextend -l +100%FREE /dev/rhel_10/home
        Size of logical volume rhel_10/home changed from 1020.00 MiB (255 extents) to 1.49 GiB (382 extents).
        Logical volume rhel_10/home successfully resized.
  • Grow the /home filesystem online

    • [root@pythonlinuxhub ~]# xfs_growfs /home
      meta-data=/dev/mapper/rhel_10-home isize=512    agcount=4, agsize=65280 blks
               =                       sectsz=512   attr=2, projid32bit=1
               =                       crc=1        finobt=1, sparse=1, rmapbt=0
               =                       reflink=1    bigtime=1 inobtcount=1 nrext64=0
      data     =                       bsize=4096   blocks=261120, imaxpct=25
               =                       sunit=0      swidth=0 blks
      naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
      log      =internal log           bsize=4096   blocks=16384, version=2
               =                       sectsz=512   sunit=0 blks, lazy-count=1
      realtime =none                   extsz=4096   blocks=0, rtextents=0
      data blocks changed from 261120 to 391168
  • Validate again using df -h, pvs, vgs, and lvs

    • [root@pythonlinuxhub ~]# df -h /home /data
      Filesystem                Size  Used Avail Use% Mounted on
      /dev/mapper/rhel_10-home  1.5G   52M  1.4G   4% /home
      /dev/mapper/rhel_10-data  1.5G   43M  1.4G   3% /data
      [root@pythonlinuxhub ~]# pvs
        PV         VG      Fmt  Attr PSize    PFree
        /dev/sda2  rhel_10 lvm2 a--   <19.00g    0
        /dev/sdb1  rhel_10 lvm2 a--  1020.00m    0
        /dev/sdb2  rhel_10 lvm2 a--    <2.00g    0
      [root@pythonlinuxhub ~]#
      [root@pythonlinuxhub ~]# vgs
        VG      #PV #LV #SN Attr   VSize   VFree
        rhel_10   3   4   0 wz--n- <21.99g    0
      [root@pythonlinuxhub ~]#
      [root@pythonlinuxhub ~]# lvs
        LV   VG      Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
        data rhel_10 -wi-ao----   1.50g
        home rhel_10 -wi-ao----   1.49g
        root rhel_10 -wi-ao---- <17.00g
        swap rhel_10 -wi-ao----   2.00g
      [root@pythonlinuxhub ~]# lsblk
      NAME             MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
      sda                8:0    0   20G  0 disk
      ├─sda1             8:1    0    1G  0 part /boot
      └─sda2             8:2    0   19G  0 part
        ├─rhel_10-root 253:0    0   17G  0 lvm  /
        └─rhel_10-swap 253:1    0    2G  0 lvm  [SWAP]
      sdb                8:16   0    6G  0 disk
      ├─sdb1             8:17   0    1G  0 part
      │ └─rhel_10-home 253:2    0  1.5G  0 lvm  /home
      └─sdb2             8:18   0    2G  0 part
        ├─rhel_10-home 253:2    0  1.5G  0 lvm  /home
        └─rhel_10-data 253:3    0  1.5G  0 lvm  /data
      sr0               11:0    1 1024M  0 rom

Note:

  • XFS cannot be shrunk, that’s why we recreate the LV instead
  • Do not perform this procedure without a verified backup
  • Never do this on /, /var, or /boot

Shaik Mohammed Faruk

Software Engineer sharing practical tutorials and insights on Linux, Python, SQL, and modern technologies.

Read more About Me

0 0 votes
Article Rating
guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
trackback

[…] Reduce One LVM Partition and Increase Another Safely in Linux […]

Thanks for your interest!

Content for this is getting ready and will be published soon.

1
0
Would love your thoughts, please comment.x
()
x