Move linux root partition to another disk
May 3, 2016
Context: Almost 3 years ago, I bought a Latitude E7440 laptop from Dell to replace my old eeePC. As shipped, it featured a 500Go HDD and an empty mSATA port that I quickly filled with a SSD. Back in the time, to avoid EFI issues, I dedicated the full SSD to Windows. But now that I almost only use Fedora, I looked into how to migrate my linux partition from the HDD to the SSD.
Intro
DISCLAIMER Moving partition around is kind of risky. In the worst case the whole disk’s data can become unusable. Ensure that you backed-up all your data and always think twice before you hit
ENTER
.
This case
This process can be time consuming - it took me something like 10 or 12h overall. Think bout doing a fresh install cannot do the job before starting anything ;)
Partition state and target
Tools that you can use : fdisk -l /dev/[id]
, lsblk
, blkid
.
Here is the layout before any changes
$> lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 465,8G 0 disk # 500Go HDD
├─sda1 8:1 0 200M 0 part /boot/efi # . Linux EFI boot partition
├─sda2 8:2 0 500M 0 part /boot # . Linux kernel and images
├─sda3 8:3 0 50G 0 part / # . Linux root filesystem
├─sda4 8:4 0 7,8G 0 part [SWAP]
├─sda5 8:5 0 97,7G 0 part /home # . Linux /home
└─sda6 8:6 0 309,7G 0 part /STK # . Shared NTFS storage
sdb 8:16 0 232,9G 0 disk # 250Go SSD
├─sdb1 8:17 0 300M 0 part # . Windows emergency boot
├─sdb2 8:18 0 99M 0 part # . Windows EFI boot
├─sdb3 8:19 0 128M 0 part # . Windows stuff
├─sdb4 8:20 0 231,9G 0 part # . Windows to shrink
└─sdb5 8:21 0 450M 0 part # . Diag partition
Goal
The goal is to merge /
and /home
into a new partiton on the SSD by shrinking sdb4
.
Prepare the filesystems
1. Shrink the windows partition
Windows can do that with the disk manager, but sometime unmovable files got in the way. Better use gparted, worked flawlessly. When you’re done, use the empty space to create an new ext4
partition. It should look like that:
sdb 8:16 0 232,9G 0 disk
├─sdb1 8:17 0 300M 0 part
├─sdb2 8:18 0 99M 0 part
├─sdb3 8:19 0 128M 0 part
├─sdb4 8:20 0 88,6G 0 part # Shrinked Windows
├─sdb5 8:21 0 450M 0 part
└─sdb6 8:22 0 143,3G 0 part # New partition !
2. Copy /
and /home
to the new partition
Grab wathever live linux you have and boot it (mine was Xubuntu 14.04). Mount you old /
and the new one. Now you can cp
or rsync
the content from one to the other. Here is an example from the Archlinux wiki; don’t forget to change the --exclude
to match the path of the old root!
rsync -aAXS --info=progress2 --exclude={"/old/root/lost+found"} /old/root /path/to/new/root
Do the same for the old /home
to /new/root/home
if necessary.
3. Edit mount file of the new partition
Before you can use the new partion, you need to edit /new/root/etc/fstab
to match the new mountpoint. Use either UUID (that you can get with blkid
as root) or direct mountpoints.
Now that we have a nice copy of the root partition on the SSD, let’s boot it!
Getting it to boot
Uderstanding the boot process
The boot process of a computer is not something you’re supposed to go into every morning…
I read a loot of stuff all other the Internet before I figured it, and this page is a nice sum-up of all the things you need to know.
tl;dr (only for EFI-GPT systems)
- BIOS look for an EFI tagged partition
- EFI firmware run whatever is in
/boot/efi
, here the GRUB2 manager - GRUB2 use the file located at
boot/efi/EFI/fedora/grub.cfg
to configure startup enties - This file can be generated using
grub2-mkconfig
as described in the fedora doc - Each startup entry give the location of the kernel to run and root filesystem target
Here’s mine (expurged for clarity):
menuentry 'Fedora (4.5.2-302.fc24.x86_64) 24 (Workstation Edition)' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod ext2
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 [UUID]
else
search --no-floppy --fs-uuid --set=root [UUID]
fi
linuxefi /vmlinuz-4.5.2-302.fc24.x86_64 root=UUID=[UUID] ro vconsole.font=latarcyrheb-sun16 rhgb quiet
initrdefi /initramfs-4.5.2-302.fc24.x86_64.img
}
Booting up
Run as root:
$> grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg
GRUB2 will look into all the partitions and try to build a file by auto-detecting OSs. Now if you reboot, you should have a new entry to boot the new /
alongside the old one.
At this point, theorically, we should be able to boot the new /
partition - sbd6
in my case using the same /boot
and /boot/efi
as before (still on HDD).
But in real-life, the new startup entry is not working at all, giving us two errors:
error: can't find `linux`
error: can't find `initrd`
Nobody’s perfect
If you select the old startup entry, you can still boot on the HDD, therefor the issue lays into grub.cfg
.
Let’s take a close look at the generated startup entry:
menuentry 'Fedora (4.4.7-300.fc23.x86_64) 24 (Workstation Edition) (on /dev/sdb6)' {
insmod part_gpt
insmod ext2
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 [UUID]
else
search --no-floppy --fs-uuid --set=root [UUID]
fi
linux /vmlinuz-4.4.7-300.fc23.x86_64 root=/dev/sda3 ro vconsole.font=latarcyrheb-sun16 rhgb quiet
initrd /initramfs-4.4.7-300.fc23.x86_64.img
}
If you have sharp eyes and compare it with the previous one, you can spot several differences:
- some
insmod
are missing - kernel is started using
linux
instead oflinuxefi
, same thing forinitrd
- the root filesystem passed to the kernel is
sda3
(old HDD/
) instead ofsdb6
Let’s fix that!
menuentry 'Fedora (4.5.2-302.fc24.x86_64) 24 (Workstation Edition) (on /dev/sdb6)' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod ext2
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 [BOOT UUID]
else
search --no-floppy --fs-uuid --set=root [BOOT UUID]
fi
linuxefi /vmlinuz-4.5.2-302.fc24.x86_64 root=UUID=[sdb6 UUID] ro vconsole.font=latarcyrheb-sun16 rhgb quiet
initrdefi /initramfs-4.5.2-302.fc24.x86_64.img
}
Now reboot and enjoy the modern world!