Linux: Volume Management

I’ve run into issues where the drive runs out of space and have to add a new one and move the data. Most of the time it scares me. I am going to documents steps for my own reference.

Volume management creates a layer of abstraction over physical storage, allowing us to create logical volumes. LVM creates logical volumes which can be extended and reduced, making it possible to add capacity or to remove capacity from a volume wherein the hardware storage configuration is hidden from the software. This will allows us to migrate a volume to a larger drives as it runs out of space.  The underlying physical storage unit of an LVM logical volume is a block devices such as a partition or whole disk. You can span disks, migrate between disks and resize on the fly. LVM maps data in logical extents to physical extents on disk.

I am going to expand a volume onto a larger disk by creating a logical volume on one disk, move it to a larger disk and remove the small disk. Visual below shows the steps:

First we will create partition, pv, vg, lv and create a file that will fill up the first drive.

[root@localhost ~]# lsblk
 NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
 fd0           2:0    1    4K  0 disk
 sda           8:0    0   15G  0 disk
 ├─sda1        8:1    0    1G  0 part /boot
 └─sda2        8:2    0   14G  0 part
   ├─cl-root 253:0    0 12.5G  0 lvm  /
   └─cl-swap 253:1    0  1.5G  0 lvm  [SWAP]
 sdb           8:16   0   20G  0 disk
 sdc           8:32   0   40G  0 disk
 sr0          11:0    1 1024M  0 rom

Currently, two disks 1)sdb 20GB and 2) sdc 40 GB. We will create lvm volume on 20G disk, fill up data and migrate it 40GB disk.

  1. On the physical volume sdb, create a partition using fidisk.
[root@localhost ~]# fdisk /dev/sdb
 Welcome to fdisk (util-linux 2.23.2).

hanges will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0x4c29bd14.

The device presents a logical sector size that is smaller than
the physical sector size. Aligning to a physical sector (or optimal
I/O) size boundary is recommended, or performance may be impacted.

Command (m for help): n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): ^C

[root@localhost ~]# fdisk /dev/sdb
 Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0xba3c5f20.

The device presents a logical sector size that is smaller than
the physical sector size. Aligning to a physical sector (or optimal
I/O) size boundary is recommended, or performance may be impacted.

Command (m for help): n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-41943039, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-41943039, default 41943039):
Using default value 41943039
Partition 1 of type Linux and of size 20 GiB is set

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

2) Create PV (physical volume)

[root@localhost ~]# pvcreate /dev/sdb1
   Physical volume "/dev/sdb1" successfully created.

pvscan to scan for physical volume (PV)

[root@localhost ~]# pvscan 
   PV /dev/sda2   VG cl              lvm2 [14.00 GiB / 0    free]
   PV /dev/sdb1                      lvm2 [20.00 GiB]
   Total: 2 [34.00 GiB] / in use: 1 [14.00 GiB] / in no VG: 1 [20.00 GiB]

You can also use pvdisplay which will show in details.

root@localhost ~]# pvdisplay
   --- Physical volume ---
   PV Name               /dev/sda2
   VG Name               cl
   PV Size               14.00 GiB / not usable 3.00 MiB
   Allocatable           yes (but full)
   PE Size               4.00 MiB
   Total PE              3583
   Free PE               0
   Allocated PE          3583
   PV UUID               1LayY5-cuk1-lCt5-T79u-7rw1-nHjN-0CFekY
 "/dev/sdb1" is a new physical volume of "20.00 GiB"
   --- NEW Physical volume ---
   PV Name               /dev/sdb1
   VG Name
   PV Size               20.00 GiB
   Allocatable           NO
   PE Size               0
   Total PE              0
   Free PE               0
   Allocated PE          0
   PV UUID               oGgBUf-iHAW-NtAz-kTdW-tfC0-wvRx-NoumMk

3) Create VG (volume group) and give it a name.

[root@localhost ~]# vgcreate your_vg /dev/sdb1
   Volume group "your_vg" successfully created
 [root@localhost ~]# vgscan
   Reading volume groups from cache.
   Found volume group "your_vg" using metadata type lvm2
   Found volume group "cl" using metadata type lvm2
 [root@localhost ~]# vgdisplay
   --- Volume group ---
   VG Name               your_vg
   System ID
   Format                lvm2
   Metadata Areas        1
   Metadata Sequence No  1
   VG Access             read/write
   VG Status             resizable
   MAX LV                0
   Cur LV                0
   Open LV               0
   Max PV                0
   Cur PV                1
   Act PV                1
   VG Size               20.00 GiB
   PE Size               4.00 MiB
   Total PE              5119
   Alloc PE / Size       0 / 0
   Free  PE / Size       5119 / 20.00 GiB
   VG UUID               6emZe9-uGE6-aGz4-3gE4-4gON-c5ZO-UsPaqt
 --- Volume group ---
   VG Name               cl
   System ID
   Format                lvm2
   Metadata Areas        1
   Metadata Sequence No  3
   VG Access             read/write
   VG Status             resizable
   MAX LV                0
   Cur LV                2
   Open LV               2
   Max PV                0
   Cur PV                1
   Act PV                1
   VG Size               14.00 GiB
   PE Size               4.00 MiB
   Total PE              3583
   Alloc PE / Size       3583 / 14.00 GiB
   Free  PE / Size       0 / 0
   VG UUID               7oDICk-mlgR-cmUJ-lffq-OwHH-4f7g-81UIdI

4) Create logical volume which will take all of the available space in the volume group.

root@localhost ~]# lvcreate -l 100%VG -n your_lv your_vg
   Logical volume "your_lv" created.
 [root@localhost ~]# lvscan
   ACTIVE            '/dev/your_vg/your_lv' [20.00 GiB] inherit
   ACTIVE            '/dev/cl/swap' [1.50 GiB] inherit
   ACTIVE            '/dev/cl/root' [12.50 GiB] inherit
 [root@localhost ~]# lvdisplay
   --- Logical volume ---
   LV Path                /dev/your_vg/your_lv
   LV Name                your_lv
   VG Name                your_vg
   LV UUID                30L7kM-5wgo-g9YR-Ozmf-nUom-2Yko-aoX8So
   LV Write Access        read/write
   LV Creation host, time localhost.localdomain, 2020-01-20 13:28:46 -0500
   LV Status              available
   # open                 0
   LV Size                20.00 GiB
   Current LE             5119
   Segments               1
   Allocation             inherit
   Read ahead sectors     auto
 currently set to     8192
 Block device           253:2 

5) Create a File system

mke2fs 1.42.9 (28-Dec-2013)
 Discarding device blocks: done
 Filesystem label=
 OS type: Linux
 Block size=4096 (log=2)
 Fragment size=4096 (log=2)
 Stride=0 blocks, Stripe width=0 blocks
 1310720 inodes, 5241856 blocks
 262092 blocks (5.00%) reserved for the super user
 First data block=0
 Maximum filesystem blocks=2153775104
 160 block groups
 32768 blocks per group, 32768 fragments per group
 8192 inodes per group
 Superblock backups stored on blocks:
         32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
         4096000
 Allocating group tables: done
 Writing inode tables: done
 Creating journal (32768 blocks): done
 Writing superblocks and filesystem accounting information: done

6) Mount the file system
Create a folder

[root@localhost ~]# mkdir /mnt/lvm-disk
 mout the file system
 [root@localhost ~]# mount /dev/mapper/your_vg-your_lv /mnt/lvm-disk/
 Check space
 [root@localhost lvm-disk]# df -h .
 Filesystem                   Size  Used Avail Use% Mounted on
 /dev/mapper/your_vg-your_lv   20G   45M   19G   1% /mnt/lvm-disk

7) Allocate space, create 19GB file

mke2fs 1.42.9 (28-Dec-2013)
 Discarding device blocks: done
 Filesystem label=
 OS type: Linux
 Block size=4096 (log=2)
 Fragment size=4096 (log=2)
 Stride=0 blocks, Stripe width=0 blocks
 1310720 inodes, 5241856 blocks
 262092 blocks (5.00%) reserved for the super user
 First data block=0
 Maximum filesystem blocks=2153775104
 160 block groups
 32768 blocks per group, 32768 fragments per group
 8192 inodes per group
 Superblock backups stored on blocks:
         32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
         4096000
 Allocating group tables: done
 Writing inode tables: done
 Creating journal (32768 blocks): done
 Writing superblocks and filesystem accounting information: done

This drive has no more space, so we are going to attach a new disk and move this file to sdbc of 40GB size.

1) Create a partition and save it.

sdc                   8:32   0   40G  0 disk
[root@localhost lvm-disk]# fdisk /dev/sdc
 Welcome to fdisk (util-linux 2.23.2).
 Changes will remain in memory only, until you decide to write them.
 Be careful before using the write command.
 Device does not contain a recognized partition table
 Building a new DOS disklabel with disk identifier 0x3a620a56.
 The device presents a logical sector size that is smaller than
 the physical sector size. Aligning to a physical sector (or optimal
 I/O) size boundary is recommended, or performance may be impacted.
 Command (m for help): n
 Partition type:
    p   primary (0 primary, 0 extended, 4 free)
    e   extended
 Select (default p): p
 Partition number (1-4, default 1):
 First sector (2048-83886079, default 2048):
 Using default value 2048
 Last sector, +sectors or +size{K,M,G} (2048-83886079, default 83886079):
 Using default value 83886079
 Partition 1 of type Linux and of size 40 GiB is set
 Command (m for help): w
 The partition table has been altered!
 Calling ioctl() to re-read partition table.
 Syncing disks.

2) Create a Physical Volume (PV)

[root@localhost ~]# pvcreate /dev/sdc1

3) Extend the volume group (VG) to include this PV (sdc1)

[root@localhost ~]# vgextend your_vg /dev/sdc1
   Volume group "your_vg" successfully extended

4) Move data from one physical volume to another
Set the name, your volume group slash your logical volume, then specify which physical volume to move off of and which one to move the data onto.

[root@localhost ~]# pvmove -n your_vg/your_lv /dev/sdb1 /dev/sdc1
   /dev/sdb1: Moved: 0.06%
   /dev/sdb1: Moved: 3.63%
   /dev/sdb1: Moved: 7.44%
   /dev/sdb1: Moved: 11.29%
   /dev/sdb1: Moved: 15.14%
   /dev/sdb1: Moved: 18.87%
   /dev/sdb1: Moved: 22.72%
   /dev/sdb1: Moved: 26.47%
   /dev/sdb1: Moved: 30.30%
   /dev/sdb1: Moved: 34.09%
   /dev/sdb1: Moved: 38.00%
   /dev/sdb1: Moved: 41.90%
   /dev/sdb1: Moved: 45.83%
   /dev/sdb1: Moved: 49.52%
   /dev/sdb1: Moved: 53.39%
   /dev/sdb1: Moved: 57.24%
   /dev/sdb1: Moved: 61.13%
   /dev/sdb1: Moved: 64.95%
   /dev/sdb1: Moved: 68.70%
   /dev/sdb1: Moved: 72.46%
   /dev/sdb1: Moved: 76.25%
   /dev/sdb1: Moved: 80.00%
   /dev/sdb1: Moved: 83.94%
   /dev/sdb1: Moved: 87.75%
   /dev/sdb1: Moved: 91.50%
   /dev/sdb1: Moved: 95.29%
   /dev/sdb1: Moved: 99.26%
   /dev/sdb1: Moved: 100.00%

5) Once the data has been moved from one physical volume to another,
Remove old physical volume from the volume group.

[root@localhost ~]# vgreduce your_vg /dev/sdb1
   Removed "/dev/sdb1" from volume group "your_vg"

6) Remove the old physical volume from the physical disk.

[root@localhost ~]# pvremove /dev/sdb1
   Labels on physical volume "/dev/sdb1" successfully wiped.

7) Extend the logical volume to take up all of the space of the new drive.

[root@localhost ~]# lvextend -l 100%VG /dev/mapper/your_vg-your_lv
   Size of logical volume your_vg/your_lv changed from 20.00 GiB (5119 extents) to 40.00 GiB (10239 extents).
   Logical volume your_vg/your_lv successfully resized.

8) Extend the size of the file system to take up the space available in the logical volume, we will need to unmount it. Run e2fsck on the local volume to check everything is ok.

[root@localhost ~]# e2fsck /dev/mapper/your_vg-your_lv
 e2fsck 1.42.9 (28-Dec-2013)
 /dev/mapper/your_vg-your_lv: clean, 12/1310720 files, 4764995/5241856 blocks
 check everthing is ok.
 [root@localhost ~]# e2fsck -f /dev/mapper/your_vg-your_lv
 e2fsck 1.42.9 (28-Dec-2013)
 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
 /dev/mapper/your_vg-your_lv: 12/1310720 files (0.0% non-contiguous), 4764995/5241856 blocks
[root@localhost ~]# resize2fs /dev/mapper/your_vg-your_lv
 resize2fs 1.42.9 (28-Dec-2013)
 Resizing the filesystem on /dev/mapper/your_vg-your_lv to 10484736 (4k) blocks.
 The filesystem on /dev/mapper/your_vg-your_lv is now 10484736 blocks long.
 mount it back
 [root@localhost ~]# mount /dev/mapper/your_vg-your_lv /mnt/lvm-disk/
 [root@localhost ~]# df -h
 Filesystem                   Size  Used Avail Use% Mounted on
 /dev/mapper/cl-root           13G  950M   12G   8% /
 devtmpfs                     446M     0  446M   0% /dev
 tmpfs                        457M     0  457M   0% /dev/shm
 tmpfs                        457M  6.1M  451M   2% /run
 tmpfs                        457M     0  457M   0% /sys/fs/cgroup
 /dev/sda1                   1014M  138M  877M  14% /boot
 tmpfs                         92M     0   92M   0% /run/user/0
 /dev/mapper/your_vg-your_lv   40G   18G   20G  48% /mnt/lvm-disk
 

File system has more space and resides on larger disk.