LVM Migration to smaller disk

By Tait Clarridge, Tue 20 October 2009, Category Linux

linux, lvm

Recently I purchased an SSD (OCZ Agility 60GB) to put into my Asus EEEPC-1000HE and wanted to migrate everything from my default 160GB drive to the new SSD. This required resizing of the LVM prior to copying the partitions across to the SSD.

It is also very important that your logical volumes you wish to resize and migrate aren't filled with more data than the destination drive will hold!

For example my root LV (called lv_root) had 9GB in use so it was alright for me to resize and transfer to the new system.

Also, you will probably need to remove your swap LV (if your swap is configured as an LV), there will be an example of how to do that.

Required Items:

Now you can create the LiveUSB or LiveCD of Fedora. Do this now!

Have all the above items? Lets get started.

IMPORTANT: You need to create a full backup of data on your drive, or at least copy the important files to a safe location. Do not forget to do this, if the LVM resizing fails you will be without all your data!

So, after you backup your system you need to install the new drive.

I used a USB SATA / IDE adapter that can handle both formats in 3.5" and 2.5" sizes, it can be found on TigerDirect's website here.

My instructions are going to be for my EEEPC-1000HE so if you have any questions, leave a comment.

My guess is that if you are using a desktop system, you will need to use the SATA connection that your original drive was using for the new one and use a secondary connection for your old hard drive.

Throughout this how-to you will see [root@host ~]# , this is the command prompt and yours may be different, simply enter the commands in your terminal as they appear after the prompt.

Step One: Install the smaller hard drive in the EEEPC

This is a pretty straightforward step, unplug your machine and remove the battery. Open up the bottom access panel and unplug and remove the old hard drive. Remove the old hard drive from the tray and replace it with the smaller drive, now you can place it back into the machine.

Step Two: Plug in the old hard drive into the USB to SATA adaptor (or another SATA port)

This is another straightforward step, since I was using a USB adapter I had to plug in the necessary cables into my drive (they were included in the adapter kit).

IMPORTANT: Do not plug this into the computer yet if booting off a USB drive (required for EEEPC).

Step Three: Boot into Fedora Live (either off of a USB or CDROM as described in the required section).

You may be required to set some BIOS options to allow USB booting (if using this method). In the case of my EEEPC I had to plug in the USB drive containing the Fedora Live system then access the BIOS and set the hard drive boot options to have "usb: removable drive" at the top.

Now you can start up your machine and it should boot into the Live system

Step Four: (if required) Plug in the original hard drive using the USB adapter after Live system has booted

This is done after booting the system to ensure that there are no conflicts with USB devices to boot off of in the BIOS.

Step Five: Find the drive names for your system to use in the migration process

You will need to make sure the drives aren't mounted anywhere, this is shown below. There are a few ways you can do this, but the easiest way is to fire up a terminal and become the superuser (root):

In the terminal:

[liveuser@host ~]$ su -
[root@host ~]# mount

If there is anything that shows /dev/sdb1 (old hard drive) or your volume groups (they shouldn't be mounted in a live system), unmount them with:

[root@host ~]# umount /dev/sdb1
# Or for volume group
[root@host ~]# umount /dev/vg_yourvg-lv_yourlv

Now lets list the disks

[root@host ~]# fdisk -l
Disk /dev/sda: 60.0GB, xxxxxxxxxxxxx bytes
xxx heads, xx sectors/track, xxxxx cylinders
Units = cylinders of xxxxx * xxx = xxxxxxxx bytes
Disk identifier: xxxxxxxx

 Disk /dev/sda doesn't contain a valid partition table

# (this is normal if the disk is new)

Disk /dev/sdb: 160.0GB, xxxxxxxxxxxxxx bytes
xxx heads, xx sectors/track, xxxxx cylinders
Units = cylinders of xxxxxxx * xxx = xxxxxxxxxxxxx bytes
Disk identifier: xxxxxxxxxxxx

  Device  Boot   Start   End   Blocks   Id    System
/dev/sdb1  *     x       xx    xxxxxx   83   Linux
/dev/sdb2        xx      xxxxx xxxxxxxx 8e   Linux LVM

(It may also show a bunch of devices called /dev/dm-0, /dev/dm-1, /dev/dm-2 with messages saying "Disk /dev/dm-x doesn't contain a valid partition table. This is normal, just ignore these for the purposes if this post)

So our values for the rest of this howto are: New disk: /dev/sda Old disk: /dev/sdb

Step Six: Create partition layout on new HDD

Since we now have the drive names, we can go ahead and partition the new disk to have the two partitions (your disk setup might be different, mine had /boot on the first partition and the LVM on the second partition).

EDIT from the future: I'm showing fdisk here, but you can do the same thing with any partition editing (I prefer parted these days)

[root@host ~]# fdisk /dev/sda

Command (m for help): o
Building a new DOS disklabel with disk identifier xxxxxxxxxxxx
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

### If you get a warning about invalid flags, those are OK too.

Command (m for help): n
Command action
  e   extended
  p   primary partition (1-4)
p (this is my input)
Partition number (1-4): 1
First cylinder (1-xxxx, default 1): 1
### I chose 250 MB for extra kernel installs/preupgrade
Last cylinder, +cylinders or +size{K,M,G} (1-xxx, default xxx): +250M

Command (m for help): n
Command action
   e    extended
   p    primary partition (1-4)
Partition number (1-4): 2
### Pressing enter through these should make it the rest of the disk
First cylinder (xx-xxxx, default xxx): <press enter>
Using default value xxx
Last cylinder, +cylinders or +size{K,M,G} (xx-xxxx, default xxxx): <press enter>
Using default value xxxx

Command (m for help): t
Partition number (1-4): 2
Hex code (type L to list codes): 8e
Changed system partition 2 to 8e (Linux LVM)

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

Your partitions are now ready for some data!

Step Seven: Copy the boot partition from the old drive to the new drive and resize it

[root@host ~]# e2fsck -f /dev/sdb1
<Output of e2fsck snipped>
[root@host ~]# dd if=/dev/sdb1 of=/dev/sda1
<Output of dd snipped>
[root@host ~]# e2fsck -f /dev/sda1
<Output of e2fsck snipped>
[root@host ~]# resize2fs /dev/sda1
<Output of resize2fs snipped>

The resize2fs output should say that it successfully resized the filesystem to a certain amount of blocks.

Step Eight: Gather information on your LVM structure

For this step, you need to make note of what your logical volumes, volume groups, and physical volumes are called.

In this how to mine are as follows:

The columns shown below are the only ones you should be concerned with.

[root@host ~]# lvs
LV            VG                  LSize
lv_root     vg_taitsstuff      144.xxG
lv_swap     vg_taitsstuff      4.xG

So this shows my current logical volume setup where:

lv_root is located on vg_taitsstuff and is 144.xxG in size lv_swap is located on vg_taitstuff and is 4.xG in size

Now we can look at the information for the volume groups:

The columns that have been omitted are unimportant at this point.

[root@host ~]# vgs
VG              #PV  #LV  #SN  VSize VFree
vg_taitsstuff  1        2      0    148.xxG   0

This means that:

vg_taitstuff is 148.xxG in size with no free space located on ONE physical volume and contains TWO logical volumes.

So finally lets take a look at the physical volumes: Again, the omitted columns aren't important to us right now.

[root@host ~]# pvs
PV             VG               PSize    PFree
/dev/sdb2  vg_taitsstuff   148.xxG    0

So this means that the only LVM physical volume I have is on /dev/sdb2 and is the same size as the volume group (since it is the only one there).

The things you need to remember are: The name of the swap logical volume (mine: lv_swap) The name of the physical volume (mine: /dev/sdb2)

Step Nine: Remove SWAP logical volume

I was having issues with resizing due to the placement of my SWAP logical volume, so what I did was remove it (it will be recreated later with the information from the above section).

So, lets turn the swap off and remove it:

[root@host ~]# swapoff -v /dev/vg_taitsstuff/lv_swap
[root@host ~]# lvremove /dev/vg_taitsstuff/lv_swap

Step Ten: Resize ROOT logical volume

Since I have only one logical volume for my system (other than the swap we just deleted) this is relatively straightforward, if you have multiple partitions I am not able to help you at the moment.

[root@host ~]# e2fsck -f /dev/vg_taitsstuff/lv_root
# 50G was chosen so it was smaller than the size of the HDD, noobish I know.
[root@host ~]# resize2fs -p /dev/vg_taittstuff/lv_root 50G
[root@host ~]# lvreduce --size 50G vg_taitsstuff/lv_root --test
# If there were any errors in the test, do not issue the next command
[root@host ~]# lvreduce --size 50G vg_taitsstuff/lv_root

Step Eleven: Resize the physical volume

Now we can resize the volume so it will fit in our new partition on the new disk.

[root@host ~]# pvresize --setphysicalvolumesize 55G /dev/sdb2

This should complete successfully. The reason why I chose 55G was that it was greater than the filesystem size we set in Step 10 and less than the new hard drive size (60 GB)

Step Twelve: Copy the old partition to the new drive

Some people may argue that I am taking a round about way to do this, I did it this way because it made sense at the time. I tried migrating the volume groups without success so I did it this way.

[root@host ~]# dd if=/dev/sdb2 of=/dev/sda2

This will take a while depending on the size, also it may tell you that it ran out of space, this should be alright because it will already be finished writing the physical volume that we resized in the previous step.

Step Thirteen: Physically disconnect the old drive

Step Fourteen: Resize the PV on the new drive

This step is so we can get full use of our LVM partition.

[root@host ~]# pvresize /dev/sda2

Step Fifteen: Resize the logical volume and filesystem on the new drive and create the new swap logical volume

[root@host ~]# lvextend /dev/vg_taitsstuff/lv_root /dev/sda2
# 4GB here is the size of the swap partition I want
[root@host ~]# lvreduce --size -4G vg_taitsstuff/lv_root
[root@host ~]# lvcreate --name lv_swap vg_taitsstuff
# There are a lot of these filesystem checks, some may say too many, but lets be safe
[root@host ~]# e2fsck -f /dev/vg_taitsstuff/lv_root
[root@host ~]# resize2fs /dev/vg_taitsstuff/lv_root
# Lets bring back that swap LV
[root@host ~]# mkswap /dev/vg_taitsstuff/lv_swap

Step Seventeen: Reinstall GRUB on the new drive

We need to activate the vg, mount the partitions, and reinstall grub.

[root@host ~]# mkdir -p /mnt/temp/boot
[root@host ~]# vgchange -a y
[root@host ~]# mount /dev/sda1 /mnt/temp/boot
[root@host ~]# mount /dev/vg_taitsstuff/lv_root /mnt/temp
[root@host ~]# grub-install --root-directory=/mnt/temp /dev/sda

Step Eighteen: Reboot

Now that everything has reinstalled and been resized, it is time for a reboot! If your grub menu is just a prompt, not to worry.

Just enter the following commands in the grub prompt (grub>)

grub> kernel /
grub> initrd /

If you do not know the kernel version off hand, you can press tab twice after entering kernel and a forward slash and it will show the available versions. The same goes for the ramdisk (initrd), just make sure that the ramdisk version and the kernel version are the same.

Once you login to your system just run "grub-install /dev/sda" as root and things should be back to normal.

Remember. MAKE SURE YOU HAVE BACKED UP EVERYTHING. My instructions may not work for your setup so you should have a full backup (I did a "dd" of my entire disk to a file before I started resizing to an external hard drive while booted from a Live USB).