Recently I made an upgraded to one of my servers so I swapped a regular HDD with SSD. Unfortunately the HDD is 500GB but the SSD is 480GB, so the out-of-the-box cloning software won’t work. I tried using gparted
and other free software with nice GUI but ended doing the job using the command line. I used ubuntu live cd
My original HDD is /dev/sde
and the new empty SSD is /dev/sdb
Overview of the steps:
- Analyze the existing partition table
- Backup MBR and partition table
- Shrink the LVM
- Resizing the partition
- Copying the MBR and partition table
- Copying the partitions
Analyze the existing partition table
root@ubunto:/# parted /dev/sde unit s print
Model: HGST HTS 725050A7E630 (scsi)
Disk /dev/sde: 976773168s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 2048s 7999487s 7997440s primary ext2 boot
2 8001534s 976771071s 968769538s extended
5 8001536s 976771071s 968769536s logical lvm
So there is one primary partition for booting and one extended partition containing the LVM. Obviously it is not possible to move the extended partition directly without resizing it.
root@ubunto:/# lvm pvdisplay --map
--- Physical volume ---
PV Name /dev/sde5
VG Name vg0-11a111
PV Size 460.00 GiB / not usable 3.00 MiB
Allocatable yes
PE Size 4.00 MiB
Total PE 107519
Free PE 1280
Allocated PE 106239
PV UUID AAAAAA-bbbb-cccc-dddd-eeee-ffff-ggggg
--- Physical Segments ---
Physical extent 0 to 105564:
Logical volume /dev/vg0-11a111/root
Logical extents 0 to 105564
Physical extent 105565 to 107518:
Logical volume /dev/vg0-11a111/swap
Logical extents 0 to 1953
So the are two two logical volumes (/root
and /swap
). The only way to make space here is to shrink /root
. It will also create a free space between /root
and /swap
, so /swap
needs to be moved.
Backup MBR and partition table
Backup the partition table with following command:
sfdisk -d /dev/sde > part_table
It can always be restored later with:
sfdisk /dev/sde < part_table
The content of the part_table is
label: dos
label-id: 0xaaaaaaa
device: /dev/sde
unit: sectors
/dev/sde1 : start= 2048, size= 7997440, type=83, bootable
/dev/sde2 : start= 8001534, size= 968769538, type=5
/dev/sde5 : start= 8001536, size= 968769536, type=8e
The MBR (Master Boot Record) contains:
- Bootstrap - 446 bytes.
- Partition table - 64 bytes
- Signature - 2 bytes
So basically only the first 446 bytes needs to be backuped (the partition table is already contained in the part_table
file). However it is always good to have the entire MBR. Creating a sde_mbr.bak
file:
dd if=/dev/sde of=/tmp/sde_mbr.bak bs=512 count=1
It can later be restored by:
dd if=/tmp/sde_mbr.bak of=/dev/sde bs=446 count=1
or with partition table and signature
dd if=/tmp/sde_mbr.bak of=/dev/sde bs=512 count=1
Shrink the LVM
Before shrinking the volume should have enough free space.
Resizing the LVM volume with:
lvresize --resizefs --size 420G /dev/vg0-11a111/root
Now the information from pvdisplay
looks like:
root@ubunto:/# lvm pvdisplay --map
--- Physical volume ---
PV Name /dev/sde5
VG Name vg0-11a111
PV Size 460.00 GiB / not usable 3.00 MiB
Allocatable yes
PE Size 4.00 MiB
Total PE 107519
Free PE 1280
Allocated PE 106239
PV UUID AAAAAA-bbbb-cccc-dddd-eeee-ffff-ggggg
--- Physical Segments ---
Physical extent 0 to 104284:
Logical volume /dev/vg0-11a111/root
Logical extents 0 to 104284
Physical extent 104285 to 105564:
FREE
Physical extent 105565 to 107518:
Logical volume /dev/vg0-11a111/swap
Logical extents 0 to 1953
There is free space between LV /root
and LV /swap
, so the /swap
should be moved wiht commnad line pvmove --alloc anywhere /dev/sde5:aaa-bbb /dev/sde5:ccc-ddd
, where the aaa-bbb
are the source physical extend and ccc-ddd
are destination physical extend. It is better that ccc
is equal to the end of the previous LV plus some space for safety.
pvmove --alloc anywhere /dev/sde5:105565-107518 /dev/sde5:104400-106353
After the move the pvdisplay
looks like:
root@ubunto:/# lvm pvdisplay --map
--- Physical volume ---
PV Name /dev/sde5
VG Name vg0-11a111
PV Size 460.00 GiB / not usable 3.00 MiB
Allocatable yes
PE Size 4.00 MiB
Total PE 107519
Free PE 1280
Allocated PE 106239
PV UUID AAAAAA-bbbb-cccc-dddd-eeee-ffff-ggggg
--- Physical Segments ---
Physical extent 0 to 104284:
Logical volume /dev/vg0-11a111/root
Logical extents 0 to 104284
Physical extent 104285 to 104399:
FREE
Physical extent 104400 to 106353:
Logical volume /dev/vg0-11a111/swap
Logical extents 0 to 1953
Physical extent 106354 to 107518:
FREE
Now the last step is to resize the physical volume (note is 430G = 420GB for /root
and 8G for /swap
)
pvresize --setphysicalvolumesize 430G /dev/sde5
However the sde2
partition table is still having the original size, so it also needs to be resized.
root@ubunto:/# parted /dev/sde unit s print
Model: HGST HTS 725050A7E630 (scsi)
Disk /dev/sde: 976773168s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 2048s 7999487s 7997440s primary ext2 boot
2 8001534s 976771071s 968769538s extended
5 8001536s 976771071s 968769536s logical lvm
This can be achieved with cfdisk
application with console UI - by setting the size of the sde5
to 431GB and sde2
to 432GB.
Alternatively it can be done by altering part_table
file. Each sector is 512 bytes, so 431 GB = 903872512 sectors. The end file should look like:
label: dos
label-id: 0xaaaaaaa
device: /dev/sde
unit: sectors
/dev/sde1 : start= 2048, size= 7997440, type=83, bootable
/dev/sde2 : start= 8001534, size= 903872512, type=5
/dev/sde5 : start= 8001536, size= 903872510, type=8e
The partition table could be overriten with:
sfdisk /dev/sde < part_table
Confirming the change by
parted /dev/sde unit s print
Model: HGST HTS 725050A7E630 (scsi)
Disk /dev/sde: 976773168s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 2048s 7999487s 7997440s primary ext2 boot
2 8001534s 903872512s 903872512s extended
5 8001536s 903872512s 903872510s logical lvm
Copying the MBR
Next step is to copy the MBR (bootstrap + partition table)
dd if=/dev/sde of=/dev/sdb bs=512 count=1
Alternatively partition_file
could be used:
sfdisk /dev/sda < part_table
or directly without using a file
sfdisk -d /dev/sde | sfdisk /dev/sda
Copying the partitions
Final step is to copy the actual data from the partitions. Since dd
doesn’t have any progress indicator, the pv
utility comes in handy. It is not part of the ubuntu live cd, so it must be installed
apt install pv
Finally the following commands will copy the partitions data:
dd if=/dev/sde1 | pv | dd of=/dev/sdb1
dd if=/dev/sde5 | pv | dd of=/dev/sdb5
Alternative to steps 5 and 6 are to copy the entire disk.
First find out the number of sectors of the SSD
root@ubunto:/# parted /dev/sde unit s print
Model: ATA SanDisk SDSSDA48 (scsi)
Disk /dev/sdb: 937703088s
Sector size (logical/physical): 512B/512B
...
Then copy the entire disk
dd if=/dev/sde bs=512 count=937703088 | pv | dd=of/dev/sdb
Written with StackEdit.