It is possible that what I am going to tell next can be done in other ways, but I am really sure that it will be very useful for many people. Have you ever thought how to reduce a virtual disk on VMware, KVM, Xen, etc. with a Linux filesystem created inside?
If the virtual disk just contains a filesystem such as ext3, ext4, btrfs, etc., the solution is easy: use any partition tool like GParted, shrink the partition or partitions and copy them to another virtual disk smaller.
But what happens if that virtual disk has a filesystem over a Logical Volume (LV)? The solution is not trivial, since partion tools do not support Logical Volume Management (LVM).
Then I am going to explain my solution. For my tests, I will use a CentOS 5.5 virtual machine under VMware vSphere, with a virtual disk of 64 GB (sda). That virtual disk will have two partitions: sda1 (107 MB) and sda2 (63,88 GB).
[root@centos ~]# fdisk -l
Disco /dev/sda: 68.7 GB, 68719476736 bytes
255 heads, 63 sectors/track, 8354 cylinders
Unidades = cilindros de 16065 * 512 = 8225280 bytes
Disposit. Inicio Comienzo Fin Bloques Id Sistema
/dev/sda1 * 1 13 104391 83 Linux
/dev/sda2 14 8354 66999082+ 8e Linux LVM
The second partition (sda2) will have two LVs, LogVol00 (data area) and LogVol01 (swap).
[root@centos ~]# lvs
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
LogVol00 VolGroup00 -wi-ao 62,88G
LogVol01 VolGroup00 -wi-ao 1,00G
My goal will be to decrease the size of the virtual disk from 64 GB to 19 GB.
In order to be able to resize the ext3 filesystem, LV, VG (Volume Group), PV (Physical Volume) and sda2 partition, you must boot the computer in rescue mode (using for example a Live CD).
boot: linux rescue
During the boot process, we will not mount the existing Linux installation and skip directly to the command shell. Then, we have to activate all known volume groups in the system and check the filesystem to rule out possible errors on it.
sh-3.2# lvm vgchange -a y
sh-3.2# e2fsck -f /dev/VolGroup00/LogVol00
Afterwards, first we must resize the filesystem from 62,88 GB to 16 GB and then, the LV.
sh-3.2# resize2fs /dev/VolGroup00/LogVol00 16G
sh-3.2# lvm lvresize --size 16G /dev/VolGroup00/LogVol00
Because we have reduced the LogVol00 size, now there is a gap between both volumes and it is better that we remove LogVol01 and recreate it again.
sh-3.2# lvm lvremove /dev/VolGroup00/LogVol01
sh-3.2# lvm lvcreate --size 1G --name LogVol01 VolGroup00
sh-3.2# mkswap /dev/VolGroup00/LogVol01
Next step is to decrease the size of the PV. We need 16 GB for the data area and 1 GB for the swap.
sh-3.2# lvm pvresize /dev/sda2 --setphysicalvolumesize 17G
/dev/sda2: cannot resize to 511 extens as 544 are allocated.
0 physical volume(s) resized / 1 physical volume(s) not resized
We can see that we must fit correctly that space... it is easy, a simple rule of three (17*544/511).
sh-3.2# lvm pvresize /dev/sda2 --setphysicalvolumesize 17.03G
Physical volume "/dev/sda2" changed
1 physical volume(s) resized / 0 physical volume(s) not resized
And finally, we have to resize that sda2 partition. To calculate the end sector, first we must take a look at the partition map in sectors (one sector is 512 bytes), get the starting point of the sda2 partition (208845s), add it the size of the PV (35651584s) and also add a security margin of around 64 MB (131072s).
sh-3.2# lvm pvs --units s
PV VG Fmt Attr PSize PFree
/dev/sda2 VolGroup00 lvm2 a- 35651584S 0S
sh-3.2# parted /dev/sda unit s print
Disk /dev/sda: 134217727s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 63s 208844s 208782s primary ext3 boot
2 208845s 134207009s 133998165s primary lvm
Now we can resize the partition: 208845 + 35651584 + 131072 = 35991501.
sh-3.2# parted /dev/sda rm 2
sh-3.2# parted /dev/sda mkpart primary 208845s 35991501s
sh-3.2# parted /dev/sda set 2 lvm on
sh-3.2# parted /dev/sda print
Disk /dev/sda: 68.7GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 32.3kB 107MB 107MB primary ext3 boot
2 107MB 18.4GB 18.3GB primary lvm
It is necessary check again the filesystem to see that all is right.
sh-3.2# e2fsck -f /dev/VolGroup00/LogVol00
Now we have to add a second virtual disk (19 GB) to the system and copy the data from sda to sdb.
sh-3.2# dd if=/dev/sda of=/dev/sdb bs=1M &
When the task is complete, we must turn off the virtual machine, delete the first virtual disk (64 GB) and put the second (19 GB) as primary for the next boot.
Then we will finish starting the virtual machine.