Saturday, September 16, 2017

Resize Physical Partition on LVM




Resizing physical LVM partition is a bit painful and requires few steps:
1) Resize the physical partition
2) Resize the physical volume
3) Resize the logical volume
4) Resize the filesystem (e.g. ext4 filesystem)

Take this example: assuming the primary partitions have been filled up to 4, if the total HD capacity is expanded from 100 GB to 150 GB, there will be no way to attach more partition to the LVM group: 

Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1026047      512000   83  Linux      (488 MiB)
/dev/sda2         1026048    41943039    20458496   8e  Linux LVM  (19.5 GiB)
/dev/sda3        41943040    83886079    20971520   8e  Linux LVM  (20 GiB)
/dev/sda4        83886080   209715199    62914560   8e  Linux LVM  (60 GiB) 

If we want to resize /dev/sda4 from 60 GB to 100 GB or max available new space, usually we can perform it with standard "parted" utility.

But on LVM, this throws error "Could not detect file system"

# parted /dev/sda
GNU Parted 2.1
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print free                                                      
Model: VMware Virtual disk (scsi)
Disk /dev/sda: 150GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End       Size    Type     File system  Flags
        32.3kB  1049kB    1016kB           Free Space
 1      1049kB  525MB     524MB   primary  ext4         boot
 2      525MB   21.5GB    20.9GB  primary               lvm
 3      21.5GB  42.9GB    21.5GB  primary               lvm
 4      42.9GB  107.37GB  64.4GB  primary               lvm

(parted)                                                  
(parted) resize 4 42.9GB 100GB
WARNING: you are attempting to use parted to operate on (resize) a file system.
parted's file system manipulation code is not as robust as what you'll find in
dedicated, file-system-specific packages like e2fsprogs.  We recommend
you use parted only to manipulate partition tables, whenever possible.
Support for performing most operations on most types of file systems
will be removed in an upcoming release.
Error: Could not detect file system.
(parted) check 4                                                         
WARNING: you are attempting to use parted to operate on (check) a file system.
parted's file system manipulation code is not as robust as what you'll find in
dedicated, file-system-specific packages like e2fsprogs.  We recommend
you use parted only to manipulate partition tables, whenever possible.
Support for performing most operations on most types of file systems
will be removed in an upcoming release.
Error: Could not detect file system.   
(parted) quit                                                            
#

So, here is the tricky part where we need to use fdisk to delete and re-create back the partition.

It may sounds scary when performing deletion, but if we do it "right" by re-creating it with exactly the same parameters on the "start sector" and "partition type", we should not lose any data when doing the "delete and create"

Follow the below steps to perform the resize.

If you execute the commands thru ssh, it is strongly recommended that you use "screen" session to prevent your active process from getting terminated by the disconnected shell during network interruption. Or else unrecoverable corruption may occur when the ssh session gets disconnected by network issues.

For more info about "screen", you can search some tutorials on internet with keywords like "linux screen session"

- http://aperiodic.net/screen/quick_reference
- https://www.howtoforge.com/linux_screen
- https://www.rackaid.com/blog/linux-screen-tutorial-and-how-to/
- https://www.linode.com/docs/networking/ssh/using-gnu-screen-to-manage-persistent-terminal-sessions


Step 1: Resize the physical partition


Before start doing any modification on the partition, ensure the existing filesystem to be resized has been unmounted first.

Start fdisk and use command 'u' to switch to sector mode.

IMPORTANT:

- Don't forget use command 'u' to switch to sector mode
- Don't perform write or commit ('w') during deletion and creation of the partition
- Only perform write or commit ('w') after the partition has been re-created correctly on the "start sector" and "partition type (8e)"
- If you feel that you do something wrong in the middle and want to redo from beginning, press ctrl-C and rerun "fdisk" (as long as you do not perform write or commit "w", there should be nothing change against your harddisk partitions)

(i) Start fdisk and use command 'u' to switch to sector mode.


# fdisk /dev/sda

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): u
Changing display/entry units to sectors

(ii) Write down the start sector and partition id on /dev/sda4 (or better copy the whole line to somewhere on notepad before start deleting it)


Command (m for help): p

Disk /dev/sda: 150.3 GB, 150323855360 bytes
64 heads, 32 sectors/track, 143360 cylinders, total 293601280 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00076ede

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1026047      512000   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2         1026048    41943039    20458496   8e  Linux LVM
Partition 2 does not end on cylinder boundary.
/dev/sda3        41943040    83886079    20971520   8e  Linux LVM
/dev/sda4        83886080   209715199    62914560   8e  Linux LVM

Command (m for help):


After this, keep in mind that the partition layout before and after must look like this:

Before:
/dev/sda4        83886080   209715199    62914560   8e  Linux LVM

After:
/dev/sda4        83886080   [new value]  [new value] 8e  Linux LVM

(iii) Now, here we go: delete and recreate the partition with the start sector that we had noted it down previously

Delete the /dev/sda4:

Command (m for help): d
Partition number (1-4): 4
Command (m for help): 

Once it is deleted, the /dev/sda4 should be gone now:

Command (m for help): p

Disk /dev/sda: 150.3 GB, 150323855360 bytes
64 heads, 32 sectors/track, 143360 cylinders, total 293601280 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00076ede

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1026047      512000   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2         1026048    41943039    20458496   8e  Linux LVM
Partition 2 does not end on cylinder boundary.
/dev/sda3        41943040    83886079    20971520   8e  Linux LVM

Command (m for help):

Create back the /dev/sda4:

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Selected partition 4
First sector (32-293601279, default 32): 83886080
Last sector, +sectors or +size{K,M,G} (83886080-293601279, default 293601279):
Using default value 293601279

Command (m for help):


Once it is created back, the /dev/sda4 would be visible again with the new parameter on the "End", "Blocks", and "Id":

Command (m for help): p

Disk /dev/sda: 150.3 GB, 150323855360 bytes
64 heads, 32 sectors/track, 143360 cylinders, total 293601280 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00076ede

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1026047      512000   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2         1026048    41943039    20458496   8e  Linux LVM
Partition 2 does not end on cylinder boundary.
/dev/sda3        41943040    83886079    20971520   8e  Linux LVM
/dev/sda4        83886080   293601279   104857600   83  Linux

Command (m for help):


Change back the partition id from 83 to 8e

Command (m for help): t
Partition number (1-4): 4
Hex code (type L to list codes): 8e

Command (m for help):

(iv) Double-check the "recreated" new partition and ensure all are the same except the size that has changed on the "End" sector and "Block" sector


Command (m for help): p

Disk /dev/sda: 150.3 GB, 150323855360 bytes
64 heads, 32 sectors/track, 143360 cylinders, total 293601280 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00076ede

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1026047      512000   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2         1026048    41943039    20458496   8e  Linux LVM
Partition 2 does not end on cylinder boundary.
/dev/sda3        41943040    83886079    20971520   8e  Linux LVM
/dev/sda4        83886080   293601279   104857600   8e  Linux

Command (m for help):

Verify all are correct with respect to the previous partition layout, except the "End" and "Blocks" column:

Before:
/dev/sda4        83886080   209715199    62914560   8e  Linux LVM

After:
/dev/sda4        83886080   293601279    104857600  8e  Linux LVM

(v) Once it looks ok, then commit

Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.
#

(vi) Perform "partprobe" or reboot to refresh the partition table

# partprobe
# init 6


Step 2: Resize the physical volume


If all sub-steps on step #1 have been done successfully, the following and next step will be very simple.

To resize the LVM's physical volume, run "pvresize". This will automatically resize the physical volume to the maximum allocated physical partition

# pvresize /dev/sda4
  Physical volume "/dev/sda4" changed
  1 physical volume(s) resized / 0 physical volume(s) not resized


Step 3: Resize the logical volume


Use this simple command to resize the logical volume:

# lvresize -l +100%FREE /dev/vg00/lvol4


Step 4: Resize the filesystem


For ext4 filesystem, use this command:

# resize2fs -p /dev/mapper/vg00-lvol4

If it complains to run e2fsck, then execute this command:

# e2fsck -ff /dev/mapper/vg00-lvol4


Done, remount and verify the newly resized filesystem


What a nice solution. If you are a programmer savvy, you can also make a script or app to perform string parsing to those text outputs and provide interaction thru UI or CLI.

Linux and open source give freedom to everyone who possesses knowledge and capabilities to leverage their skills and competencies in solving problem and delivering solutions.

Unlike proprietary software like Microsoft or Apple who rely on trade secret to disclose its limitation, in open source world everything is transparent and customizable. The only things can limit the freedom of software is the hardware and infrastructure. Free software, means freedom of software. Open source, means open society :)