Sometimes, you need to resize your partitions on Linux. And this may not be as easy as you think...
When I installed Debian on my work computer a few months ago, the wizard suggested creating 2 separate partitions: one for root (with the OS itself), another for home (with my personal data). Alas! The suggested sizes (that I naively accepted) were highly unsuitable and a month later, the root partition (only 40 Go) was full. I had to resize them. It turns out that now, 5 months later, the home is full (I really generate a lot of data for my current project). It's time to resize my partitions again but this time I will keep track of the entire procedure in this article. Who knows when I will have to resize them one more time...
Current State and Goal
My computer as a single encrypted SSD disk:
% lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1 259:0 0 3.6T 0 disk
├─nvme0n1p1 259:1 0 512M 0 part /boot/efi
├─nvme0n1p2 259:2 0 488M 0 part /boot
└─nvme0n1p3 259:3 0 3.6T 0 part
└─nvme0n1p3_crypt 253:0 0 3.6T 0 crypt
├─debian--vg-root 253:1 0 2.6T 0 lvm /
├─debian--vg-swap_1 253:2 0 976M 0 lvm [SWAP]
└─debian--vg-home 253:3 0 1T 0 lvm /home
fdisk -l
shows similar information.
As I said, my home partition is full. However, the root partition is almost empty:
% df -h | grep debian
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/debian--vg-root 2.6T 202G 2.3T 8% /
/dev/mapper/debian--vg-home 1007G 937G 19G 99% /home
My goal is to resize the partitions so that root is 1T and home occupies the rest of the disk. This will be a 2-step process: first, shrink root ; second, extend home.
Apparently, I can't do this from the graphical disk utility (note "Edit Partition..." and "Resize..." being greyed out):
It's time to open a terminal and input some weird commands!
Shrinking Root
Because I want to resize the root partition, it seems that I can't directly work from my installed Debian. I put my hands back on my bootable USB drive (the one I used to install Debian in the first place) and I reboot my computer on it. It doesn't provide a live Debian mode, so I have to use the rescue mode to get a shell:
Yes, I took pictures on my laptop's screen.
Once I have configured my language and keyboard layout, and skipped the network configuration, I can finally enter the rescue mode for real:
I have to enter my passphrase because my disk is encrypted, and I now have a shell. Hooray!
Resizing a "partition" is not a single-step operation. Indeed, there are in fact a logical volume and a filesystem on top of it. Both need to be resized in the correct order.
First, reduce the filesystem with the resize2fs
command. In this first step, I use a temporary size, not the desired size. It must be big enough to hold all the files but smaller that the desired size. The output df -h
above shows that 202G are used on root. The desired size is 1T. Hence, 300G seems fine.
resize2fs /dev/mapper/debian--vg-root 300G
I am asked to check the filesystem first with e2fsck -f /dev/mapper/debian--vg-home
. Once the check and possible fixes are done, I can call resize2fs
again.
Second, reduce the volume to the desired size (1T) with the lvreduce
command:
lvreduce -L 1T /dev/vgroot/lvroot
Third (and last), extend the filesystem to use the entire volume. This is done by passing only the volume to resize2fs
because if the "size parameter is not specified, it will default to the size of the partition".
resize2fs /dev/vgroot/lvroot
This is how it looks like in real life:
Note that step 3 may be performed directly in step 2, because lvreduce
has an option that seems to do it:
-r
,--resizefs
Resize underlying filesystem together with the logical volume usingfsadm
.
To be honest, I wasn't really keen to try on my work computer, I can't afford any data loss. So I stuck a procedure that I knew to work, but I encourage you to test it 😅
Checking Root
Now, I shut down my computer, I remove the USB drive, I reboot to my actual system, and I'm glad to see that it still works 😄
I can check the state of my disk:
% df -h | grep mapper
/dev/mapper/debian--vg-root 1008G 202G 756G 22% /
/dev/mapper/debian--vg-home 1007G 937G 19G 99% /home
% lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1 259:0 0 3.6T 0 disk
├─nvme0n1p1 259:1 0 512M 0 part /boot/efi
├─nvme0n1p2 259:2 0 488M 0 part /boot
└─nvme0n1p3 259:3 0 3.6T 0 part
└─nvme0n1p3_crypt 253:0 0 3.6T 0 crypt
├─debian--vg-root 253:1 0 1T 0 lvm /
├─debian--vg-swap_1 253:2 0 976M 0 lvm [SWAP]
└─debian--vg-home 253:3 0 1T 0 lvm /home
The root partition is fine. Of course, the home partition is unchanged. Let's resize it now.
Extending Home
This time, I don't need to boot on my USB drive.
First, extend the volume with the lvextend
command. I don't have to calculate the remaining size, I just ask to add 100% of the free space of the disk to the volume:
% sudo lvextend -l +100%FREE /dev/mapper/debian--vg-home
Size of logical volume debian-vg/home changed from 1.00 TiB (262144 extents) to <2.64 TiB (691219 extents).
Logical volume debian-vg/home successfully resized.
Note that the option is -l
(lowercase) not -L
(uppercase), unlike with lvreduce
.
Second (and last), resize the filesystem to use the entire volume (same as last operation for root):
% sudo resize2fs /dev/mapper/debian--vg-home
resize2fs 1.47.0 (5-Feb-2023)
Filesystem at /dev/mapper/debian--vg-home is mounted on /home; on-line resizing required
old_desc_blocks = 128, new_desc_blocks = 338
The filesystem on /dev/mapper/debian--vg-home is now 707808256 (4k) blocks long.
Checking Home
Finally, I have reached my goal:
% df -h | grep mapper
/dev/mapper/debian--vg-root 1008G 202G 756G 22% /
/dev/mapper/debian--vg-home 2.6T 937G 1.6T 37% /home
% lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1 259:0 0 3.6T 0 disk
├─nvme0n1p1 259:1 0 512M 0 part /boot/efi
├─nvme0n1p2 259:2 0 488M 0 part /boot
└─nvme0n1p3 259:3 0 3.6T 0 part
└─nvme0n1p3_crypt 253:0 0 3.6T 0 crypt
├─debian--vg-root 253:1 0 1T 0 lvm /
├─debian--vg-swap_1 253:2 0 976M 0 lvm [SWAP]
└─debian--vg-home 253:3 0 2.6T 0 lvm /home
Conclusion
I have to be honest, it was quite scary to resize partitions 😱 Of course, I backed up my important data, but I can't really back up a full system with all the installed tools and settings I have as a software developer on my machine.
At the end of the day, I left this uncomfortable situation:
Before:
% df -h | grep mapper
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/debian--vg-root 2.6T 202G 2.3T 8% /
/dev/mapper/debian--vg-home 1007G 937G 19G 99% /home
And I have reached with much more cozy one:
% df -h | grep mapper
/dev/mapper/debian--vg-root 1008G 202G 756G 22% /
/dev/mapper/debian--vg-home 2.6T 937G 1.6T 37% /home
I hope this was the last time I had to resize my partitions on this computer! 😁
Top comments (2)
A few thoughts.
Root is still way over-allocated
...First off: Why? By which I mean, why waste a full terabyte on the root partition? It's only using 202GB right now. How much bigger do you expect it to grow???
Data is consumed on Linux filesystems in the user space — the home partition. The root partition might grow slightly over time, but once the system has been up and running and all of the software you need is installed, it's unlikely to experience significant growth beyond its current size. If your root partition is currently 202GB, 250GB is the maximum I'd allocate to it, because it's unlikely to grow beyond that.
You say, "I hope this was the last time I had to resize my partitions on this computer!", but by continuing to waste almost 800GB of empty space on a root allocation, you're making it more likely that it won't be the last time. Eventually, you'll probably want more of that space for home.
Counter-intuitively, it's a mistake to fully allocate an LVM volume-group up front
As you've seen, shrinking logical volumes is a pain in the neck. But growing them is a simple, convenient, on-demand action that can be performed at any time — online, without even unmounting the partition! Heck, you can grow a logical volume while you're actively hammering it with data transfers, and the only consequence will be that both operations take slightly longer to complete.
Because LVM offers on-demand, near-instant ad-hoc growth, the best way to manage volume allocations is to wait until you need the space. You say,
...The mistake you made originally wasn't accepting the wizard's recommendation of a 40GB root partition, it was giving the entire rest of the disk to the home partition.
You're working with a 3.6TB physical volume. If it were me, I'd initially have accepted that 40GB root allocation, and allocated maybe a 1TB home. I'd have left the rest of the space in the volume group completely unallocated.
Then, when the root proved far too small, I'd simply have allocated another 100GB to it with
sudo lvresize -r -L +100G debian-vg/root
.When the first 1TB of
/home
filled up,sudo lvresize -r -L +500G debian-vg/home
to give it more wiggle room. When that runs out, just do it again.If you start with reasonable size allocations and leave yourself lots of unallocated extents in the volume group, you can let the logical volumes grow gradually and organically as they fill up their current allocations.
The absolute worst position to be in is the one you've set up at every point in this process: fully-allocating your volume group so it's depleted of unallocated extents. Until you hit that point (which you should try to hold off as long as humanly possible), LVM's dynamically-allocated extent mapping is incredibly flexible. Once it's fully allocated, you've basically given up almost every advantage LVM has over dumb, pre-LVM static partitioning.
ALWAYS use the
-r
option tolvresize
(orlvextend
/lvreduce
, but who uses those anymore?)You say you're wary of it, I'm telling you: Do not be. Rely on it. There's no reason to ever fiddle with manual
resize2fs
runs to make partitions fit inside logical volumes. Just let LVM resize the partition to fit the logical volume at every step along the way.And when growing LVs into unallocated extents, it reduces the entire operation to a single, atomic
lvresize
command.Hello
Thanks for your enlightening comment.
1/Root is still way over-allocated
I don't know. How could you know? 3 months later, I now have:
I may be able to make some cleanup to regain some space, but I don't want to do this kind of cleanup often if I can afford to do occasionally (or at least, to afford to delay the moment where I will have to understand what this cleanup would be).
1T was probably too much. However, 250G would have been too little. Maybe 500G could be a good point.
2/ Counter-intuitively, it's a mistake to fully allocate an LVM volume-group up front
I like the approach you are showing. Next time I set up a new machine, I will try it.
I have just run Debian installer inside a VM to see again how the wizard proposes to arrange the disk. At some point, you have to choose between "Use entire disk" or "Manual". If you select the first option, you are then asked if you want a separate partition for
/home
. If you don't know your proposed approach, well, you end up with the rest of the disk for the home partition.I have been wondering whether having a separate partition for
/home
was even a good idea. What is your opinion in this?3/ ALWAYS use the -r option to lvresize
I was already convinced to use it next time. Thank you for reassuring me, though :D