Moving a LUKS encrypted LVM with dd and sfdisk

Recently I ran into the following issue:

I had a 500GB harddrive and with 4 primary partitions and I had run out of space. Time to upgrade of a 750GB harddrive. I had done this plenty times before, from a 160GB to a 320GB to a 500GB drive just in this laptop. But after the last upgrade I added a 100GB LUKS encrypted LVM for some work related files. This had pushed my partition count to 3 primary and 1 extended with the LUKS LVM at the end of the disk.

After mirroring the old 500GB drive to the new 750GB drive I expected to just move the LUKS LVM to the end of the disk and expand the in between partitions. As it turns out libparted and therefore gparted do not support moving LVMs and certainly not LUKS LVMs.

Doing a bit of googeling around didnt get me any further but confirm that there was no easy tool for the job. So I took to superuser.com which got me a bit further by suggesting to dd the partition content to the new location, delete the old partition and create a new one at the new location.

Here is a quick walkthrough:

First make sure you make a backup. I mirrored my drive:

sudo dd if=/dev/sda of=/dev/sdb bs=32M

then note the current locations and sizes of your partitions:

sudo sfdisk -d /dev/sda

this will give you:

# partition table of /dev/sda
unit: sectors

/dev/sda1 : start=       63, size=404414577, Id= 7, bootable
/dev/sda2 : start=404414701, size=223806179, Id= 5
/dev/sda3 : start=628220880, size=143806320, Id= 7
/dev/sda4 : start=772027200, size=204800400, Id=83
/dev/sda5 : start=404414703, size=  8799777, Id=82
/dev/sda6 : start=413214543, size=  1451457, Id=83
/dev/sda7 : start=455731983, size=172488897, Id=83
/dev/sda8 : start=414666752, size= 41064448, Id=83

make sure you take a backup copy of this, put it on a thumbdrive or a pastebin or a floppy(?) or all of the above.

Next we will need to calculate the new start location of your partition. For this we will take the size of the drive in bytes and divide it by the size of a sector(512 bytes)

user@box:~$ sudo fdisk -l /dev/sda

Disk /dev/sda: 750.2 GB, 750156374016 bytes
255 heads, 63 sectors/track, 91201 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
.
.
.

so in this case 750156374016 bytes / 512 bytes = 1465149168 sectors

so we now subtract the size of the partition we want to move from the total number of sectors to get the new start location. 1465149168 - 204800400 = 1260348768. Now lets dump and edit the partition table to the new values and set that file aside until later.

user@box:~$ sudo sfdisk -d /dev/sda > partition.dump
user@box:~$ nano partition.dump
# partition table of /dev/sda
unit: sectors

/dev/sda1 : start=       63, size=404414577, Id= 7, bootable
/dev/sda2 : start=404414701, size=223806179, Id= 5
/dev/sda3 : start=628220880, size=143806320, Id= 7
/dev/sda4 : start=1260348768, size=204800400, Id=83
/dev/sda5 : start=404414703, size=  8799777, Id=82
/dev/sda6 : start=413214543, size=  1451457, Id=83
/dev/sda7 : start=455731983, size=172488897, Id=83
/dev/sda8 : start=414666752, size= 41064448, Id=83

Now that we have the new start location of our partition, lets construct a dd command that will copy sector-for-sector from the original location to the new location.

user@box:~$ sudo dd if=/dev/sda of=/dev/sda bs=512 \
            skip=BEGIN_OLD_SDA4 count=SIZE_SDA4 seek=BEGIN_NEW_SDA4

user@box:~$ sudo dd if=/dev/sda of=/dev/sda bs=512 skip=772027200 \
            count=204800400 seek=1260348768

In the above command we copy from a location on /dev/sda to a location on /dev/sda. We set our blocksize to 512, which is the size of each sector, we start reading at block 772027200(start of the old location), we intend to copy 204800400 blocks to the seek location(new start of partition) at 1260348768

After the copy has finished(it'll take a few hours), the only thing left to do is to commit to the new partition table. Take your updates partition.dump and execute the following.

user@box:~$ sudo sfdisk --force /dev/sda < partiton.dump

at this point you should have your partition moved from your old location to the new location. I hope this help someone and thanks to ceving from superuser for the pointers