Some days ago, I made the decision to shrink the footprint of Windows system on my laptop and reallocate the disk space to the Ubuntu system that resides next to it. Ubuntu is competent for my daily use of programming and web browsing so I hardly launched the OEM-shipped Windows since the laptop was bought. The Windows takes up a not-so-small portion of my SSD space, which can be better utilized instead of wasted in vain.

(before)
| --- Windows C: (256 GB) --- | --- Ubuntu / (256 GB) --- |
(after)
| --- Windows C: (120 GB) --- | --- Ubuntu / (392 GB) --- |

As planned in the diagram above, 136 GB space would be reclaimed from the Windows C: partition and merged into the root partition of Ubuntu. I had the experience to adjust the size of disk partitions, but this time the job was a little more risky, since it involved moving the starting point of Linux root partition. Linux relies on special information in directory /boot/efi to boot itself, and if the information is not modified accordingly during the moving, the entire system would become unbootable.

To avoid catastrophic consequence, I did some research beforehand and read a detailed guidance on AskUbuntu. It turns out the tweak requires two steps to accomplish. First is to adjust the partition sizes with the GParted tool as I used to do for ordinary data partitions. The GParted system has to reside on and be booted from a separate USB device, so that the hard disks in my laptop can be fully unmounted for manipulation. This is the easiest part thanks to the straightforward GUI partition editor provided by GParted, with which I can do the adjustment in a few clicks.

Each disk partition is assigned with a UUID or serial number like b424102c-a5a6-489f-b0bd-0ea0fc3be7c3 to uniquely identify itself, which will change as the partition moved or resized. So the next step is to rebuild grub configuration to ensure it contains the new serial number of my root partition. But before running grub-install I have to emulate the directory hierarchy of my Ubuntu system by mounting relevant partitions to form the root directory and using chroot to start an interactive shell in it

(gparted)$ mkdir /tmp/mydir
(gparted)$ mount /dev/nvme0n1p5 /tmp/mydir
(gparted)$ mount --bind /dev /tmp/mydir/dev
(gparted)$ mount --bind /proc /tmp/mydir/proc
(gparted)$ mount --bind /sys /tmp/mydir/sys
(gparted)$ chroot /tmp/mydir
chroot: failed to run command ‘/bin/bash’: No such file or directory

Following the guidance, however, chroot did not succeed and complained that /bin/bash could not be found. I checked the corresponding directory /tmp/mydir/bin and found it was a broken symbolic link

(gparted)$ ls /tmp/mydir/bin -al
lrwxrwxrwx 1 root root 7 May 28 2020 /tmp/mydir/bin -> usr/bin

It appears that /bin is a symlink to usr/bin, but my /usr directory resides on the other partition and not yet mounted. With the directory /usr mounted, the chroot command works as desired.

(gparted)$ mount /dev/sda7 /tmp/mydir/usr
(gparted)$ chroot /tmp/mydir
(ubuntu)$

The spawned interactive shell allows command to run as it were in my Ubuntu system. Type grub-install /dev/nvme0n1 to write in the new serial number of root partition. It’s worth noting that the argument /dev/nvme0n1 passed to grub-install is the name of the hard disk device to write instead of some partition name like /dev/nvme0n1p1.

(ubuntu)$ grub-install /dev/nvme0n1
Installing for x86_64-efi platform.
grub-install: error: cannot find EFI directory.

Oops, the command failed and something still going wrong. After some time of inspection, I find the culprit to be that the directory /boot/efi is empty, which by default should be a bind mount to partition /dev/nvme0n1p1 but not mounted properly. This can be solved with another mount command

(ubuntu)$ mount /dev/nvme0n1p1 /boot/efi
(ubuntu)$ grub-install /dev/nvme0n1
Installing for x86_64-efi platform.
Installation finished. No error reported.

By now the boot information is eventually updated. I reboot my laptop and everything works as-is.

So the take away for this tweaking is that some special directories like /usr or /boot/efi reside in different partitions outside of the root directory / on my laptop. If you are fixing the grub and come across some similar error reports, be sure to correctly mount all concerning partitions to form the filesystem hierarchy.