About Me

My photo
I know the last digit of PI

Saturday, February 23, 2019

Cloning bigger HDD with LVM into smaller SSD

HDDtoSSD

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:

  1. Analyze the existing partition table
  2. Backup MBR and partition table
  3. Shrink the LVM
  4. Resizing the partition
  5. Copying the MBR and partition table
  6. 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:

  1. Bootstrap - 446 bytes.
  2. Partition table - 64 bytes
  3. 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.

No comments: