Resizing Partitions
If reducing the size of a partition, be sure to reduce the size of the filesystem it contains first. If extending the size of a partition, do this last. Generally, the system can be recovered if done in the wrong order by reverting to the original system state and then completing the actions in the correct order.
Resizing LVM2 Logical Volumes
Note
The Arch Linux wiki page on LVM2 is very helpful here
In this example, I'll be reducing the size of an LVM2 logical volume (LV) named
home
to make space for a 30 GiB btrfs
partition. Obviously, I checked to
make sure that the filesystem has the available space to support this
reduction.
I begin by booting into a Debian LiveCD, which I configure with an SSH server.
The credentials to log in are user:live
, and no password is required for
sudo
access.
I currently have the following layout:
root@debian:/home/user# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 465.8G 0 disk
├─sda1 8:1 0 243M 0 part
├─sda2 8:2 0 1K 0 part
├─sda3 8:3 0 781M 0 part
└─sda5 8:5 0 464.8G 0 part
├─edtwardy--vg-root
│ 253:0 0 23.3G 0 lvm
├─edtwardy--vg-var
│ 253:1 0 76.4G 0 lvm
├─edtwardy--vg-swap_1
│ 253:2 0 13.9G 0 lvm
├─edtwardy--vg-tmp
│ 253:3 0 1.9G 0 lvm
└─edtwardy--vg-home
253:4 0 349.2G 0 lvm
root@debian:/home/user# lvs -v --segments
LV VG Attr Start SSize #Str Type Stripe Chunk
home edtwardy-vg -wi-a----- 0 <349.24g 1 linear 0 0
root edtwardy-vg -wi-a----- 0 23.28g 1 linear 0 0
swap_1 edtwardy-vg -wi-a----- 0 <13.93g 1 linear 0 0
tmp edtwardy-vg -wi-a----- 0 <1.86g 1 linear 0 0
var edtwardy-vg -wi-a----- 0 9.31g 1 linear 0 0
var edtwardy-vg -wi-a----- 9.31g <16.38g 1 linear 0 0
var edtwardy-vg -wi-a----- <25.69g 50.76g 1 linear 0 0
root@debian:/home/user# pvs
PV VG Fmt Attr PSize PFree
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 0
I use resize2fs to reduce the size of the ext4 filesystem on the home
LV.
Start by using dumpe2fs
to calculate the new block size of the filesystem.
This allows us to remove any ambiguity caused by the interpretation of units
(m, M, g, G, etc.).
root@debian:/home/user# dumpe2fs -h /dev/edtwardy-vg/home
dumpe2fs 1.47.0 (5-Feb-2023)
...
Block count: 91550464
...
Block size: 4096
...
Calculate the new size with the formula:
reduction = 30 * 2**30 (30 GiB)
block_count - (reduction / block_size)
root@debian:/home/user# e2fsck -f /dev/edtwardy-vg/home
e2fsck 1.47.0 (5-Feb-2023)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/edtwardy-vg/home: 3436910/22888448 files (0.5% non-contiguous), 44044815/91550464 blocks
root@debian:/home/user# resize2fs /dev/edtwardy-vg/home 83686144
resize2fs 1.47.0 (5-Feb-2023)
Resizing the filesystem on /dev/edtwardy-vg/home to 83686144 (4k) blocks.
The filesystem on /dev/edtwardy-vg/home is now 83686144 (4k) blocks long.
Note that lvreduce
does have a --resizefs
switch that can be used to reduce
the underlying filesystem in one go, but I chose not to do that here to
underscore that this is a required step (however it's accomplished).
Use lvreduce
to reduce the size of the LV. We can specify a relative change
in any units we want, but again, we're going to use PE's, to remove all
ambiguity. The PE size can be taken from the output of pvdisplay
, and the
size of the LV in PE's is displayed by the field Current LE
in the output of
lvdisplay
.
root@debian:/home/user# pvdisplay
--- Physical volume ---
...
PE Size 4.00 MiB
...
root@debian:/home/user# lvreduce --extents -7680 /dev/edtwardy-vg/home
WARNING: Reducing active logical volume to <319.24 GiB.
THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce edtwardy-vg/home? [y/n]: y
Size of logical volume edtwardy-vg/home changed from <349.24 GiB (89405 extents) to <319.24 GiB (81725 extents).
Logical volume edtwardy-vg/home successfully resized.
We've likely created some empty space in the middle of our PV, so we may need
to use pvmove
to move the extents of a around to partition to consume the
newly freed space and arrange the free extents to live at the end of the volume
group. To test, check the output of pvs
:
root@debian:/home/user# pvs -v --segments
PV VG Fmt Attr PSize PFree Start SSize LV Start Type PE Ranges
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 0 5960 root 0 linear /dev/sda5:0-5959
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 5960 2384 var 0 linear /dev/sda5:5960-8343
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 8344 3566 swap_1 0 linear /dev/sda5:8344-11909
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 11910 476 tmp 0 linear /dev/sda5:11910-12385
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 12386 81725 home 0 linear /dev/sda5:12386-94110
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 94111 7680 0 free
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 101791 12995 var 6576 linear /dev/sda5:101791-114785
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 114786 4192 var 2384 linear /dev/sda5:114786-118977
Since the free space is large enough to contain the entire last segment, we'll need to do this in two steps:
root@debian:/home/user# pvmove --alloc anywhere /dev/sda5:114786-118977
/dev/sda5: Moved: 0.19%
...
/dev/sda5: Moved: 100.00%
Now the landlocked segment is smaller than the last segment, so we have to do some math.
root@debian:/home/user# pvs -v --segments /dev/sda5
PV VG Fmt Attr PSize PFree Start SSize LV Start Type PE Ranges
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 0 5960 root 0 linear /dev/sda5:0-5959
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 5960 2384 var 0 linear /dev/sda5:5960-8343
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 8344 3566 swap_1 0 linear /dev/sda5:8344-11909
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 11910 476 tmp 0 linear /dev/sda5:11910-12385
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 12386 81725 home 0 linear /dev/sda5:12386-94110
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 94111 4192 var 2384 linear /dev/sda5:94111-98302
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 98303 3488 0 free
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 101791 12995 var 6576 linear /dev/sda5:101791-114785
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 114786 4192 0 free
114785 (end of final segment) - 3488 (size of free space) = 111297
root@debian:/home/user# pvmove --alloc anywhere /dev/sda5:111297-114785
/dev/sda5: Moved: 0.89%
...
/dev/sda5: Moved: 99.80%
Whoops! Looks like that didn't work.
root@debian:/home/user# pvs -v --segments
PV VG Fmt Attr PSize PFree Start SSize LV Start Type PE Ranges
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 0 5960 root 0 linear /dev/sda5:0-5959
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 5960 2384 var 0 linear /dev/sda5:5960-8343
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 8344 3566 swap_1 0 linear /dev/sda5:8344-11909
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 11910 476 tmp 0 linear /dev/sda5:11910-12385
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 12386 81725 home 0 linear /dev/sda5:12386-94110
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 94111 4192 var 2384 linear /dev/sda5:94111-98302
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 98303 3488 0 free
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 101791 9506 var 6576 linear /dev/sda5:101791-111296
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 111297 3489 0 free
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 114786 3489 var 16082 linear /dev/sda5:114786-118274
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 118275 703 0 free
Let's try again:
root@debian:/home/user# pvmove --alloc anywhere /dev/sda5:114787-118274 /dev/sda5:983
03-101791
/dev/sda5: Moved: 1.06%
...
/dev/sda5: Moved: 100.00%
Almost, now!
root@debian:/home/user# pvs -v --segments
PV VG Fmt Attr PSize PFree Start SSize LV Start Type PE Ranges
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 0 5960 root 0 linear /dev/sda5:0-5959
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 5960 2384 var 0 linear /dev/sda5:5960-8343
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 8344 3566 swap_1 0 linear /dev/sda5:8344-11909
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 11910 476 tmp 0 linear /dev/sda5:11910-12385
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 12386 81725 home 0 linear /dev/sda5:12386-94110
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 94111 4192 var 2384 linear /dev/sda5:94111-98302
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 98303 3488 var 16083 linear /dev/sda5:98303-101790
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 101791 9506 var 6576 linear /dev/sda5:101791-111296
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 111297 3489 0 free
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 114786 1 var 16082 linear /dev/sda5:114786-114786
/dev/sda5 edtwardy-vg lvm2 a-- <464.76g 30.00g 114787 4191 0 free
One final move, and it's perfect:
root@debian:/home/user# pvmove --alloc anywhere /dev/sda5:114787-114788 /dev/sda5:111297-111298
/dev/sda5: Moved: 100.00%
Use pvresize
to reduce the size of the physical volume. For no apparent rhyme
or reason, the size argument to pvresize
defaults to units of MiB, so we need
to convert our new size from PE's to MiB.
root@debian:/home/user# pvdisplay
--- Physical volume ---
PV Name /dev/sda5
VG Name edtwardy-vg
...
PE Size 4.00 MiB
Total PE 118978
Free PE 7680
Allocated PE 111298
...
I frequently get output like this, indicating the size I provided is too small:
root@debian:/home/user# pvresize --setphysicalvolumesize 445192 /dev/sda5
/dev/sda5: Requested size <434.76 GiB is less than real size <464.76 GiB. Proceed? [y/n]: y
WARNING: /dev/sda5: Pretending size is 911753216 not 974669825 sectors.
/dev/sda5: cannot resize to 111297 extents as 111298 are allocated.
0 physical volume(s) resized or updated / 1 physical volume(s) not resized
Of course, this doesn't make sense, because 445192 MiB is exactly 111298 PE's.
So, we just need to increment the number of PE's in the calculation until
pvresize
is happy.
root@debian:/home/user# pvresize --setphysicalvolumesize 445196 /dev/sda5
/dev/sda5: Requested size 434.76 GiB is less than real size <464.76 GiB. Proceed? [y/n]: y
WARNING: /dev/sda5: Pretending size is 911761408 not 974669825 sectors.
Physical volume "/dev/sda5" changed
1 physical volume(s) resized or updated / 0 physical volume(s) not resized
Use fdisk
to delete the extended partition, and create a new extended
partition at the exact same start sector, and a new logical partition in the
exact same start sector, but with reduced size.
I'm gonna use some math to determine the new end sector of the extended partition:
previous_end = 975171584
sector_size = 512
previous_end - (30 * 2**30 / sector_size)
root@debian:/home/user# fdisk /dev/sda
Welcome to fdisk (util-linux 2.38.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
This disk is currently in use - repartitioning is probably a bad idea.
It's recommended to umount all file systems, and swapoff all swap
partitions on this disk.
Command (m for help): p
Disk /dev/sda: 465.76 GiB, 500107862016 bytes, 976773168 sectors
Disk model: WDC WDS500G2B0A
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x5124b043
Device Boot Start End Sectors Size Id Type
/dev/sda1 2048 499711 497664 243M 83 Linux
/dev/sda2 501758 975171584 974669827 464.8G 5 Extended
/dev/sda3 * 975173632 976773167 1599536 781M 83 Linux
/dev/sda5 501760 975171584 974669825 464.8G 8e Linux LVM
Partition table entries are not in disk order.
Command (m for help): d
Partition number (1-3,5, default 5): 2
Partition 2 has been deleted.
Command (m for help): p
Disk /dev/sda: 465.76 GiB, 500107862016 bytes, 976773168 sectors
Disk model: WDC WDS500G2B0A
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x5124b043
Device Boot Start End Sectors Size Id Type
/dev/sda1 2048 499711 497664 243M 83 Linux
/dev/sda3 * 975173632 976773167 1599536 781M 83 Linux
Command (m for help): n
Partition type
p primary (2 primary, 0 extended, 2 free)
e extended (container for logical partitions)
Select (default p): e
Partition number (2,4, default 2):
First sector (499712-975173631, default 499712): 501758
Last sector, +/-sectors or +/-size{K,M,G,T,P} (501758-975173631, default 975173631): 912257024
Created a new partition 2 of type 'Extended' and of size 434.8 GiB.
Command (m for help): n
Partition type
p primary (2 primary, 1 extended, 1 free)
l logical (numbered from 5)
Select (default p): l
Adding logical partition 5
First sector (503806-912257024, default 503808):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (503808-912257024, default 912257024):
Created a new partition 5 of type 'Linux' and of size 434.8 GiB.
Partition #5 contains a ext4 signature.
Do you want to remove the signature? [Y]es/[N]o: n
Command (m for help): x
Expert command (m for help): b
Partition number (1-3,5, default 5):
New beginning of data (501759-912257024, default 503808): 501760
Expert command (m for help): r
Command (m for help): p
Disk /dev/sda: 465.76 GiB, 500107862016 bytes, 976773168 sectors
Disk model: WDC WDS500G2B0A
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x5124b043
Device Boot Start End Sectors Size Id Type
/dev/sda1 2048 499711 497664 243M 83 Linux
/dev/sda2 501758 912257024 911755267 434.8G 5 Extended
/dev/sda3 * 975173632 976773167 1599536 781M 83 Linux
/dev/sda5 501760 912257024 911755265 434.8G 83 Linux
Partition table entries are not in disk order.
Now, I'm going to create a new partition that will contain our btrfs
filesystem.
Command (m for help): n
Partition type
p primary (2 primary, 1 extended, 1 free)
l logical (numbered from 5)
Select (default p):
Using default response p.
Selected partition 4
First sector (912257025-975173631, default 912259072):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (912259072-975173631, default 975173631):
Created a new partition 4 of type 'Linux' and of size 30 GiB.
Command (m for help): p
Disk /dev/sda: 465.76 GiB, 500107862016 bytes, 976773168 sectors
Disk model: WDC WDS500G2B0A
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x5124b043
Device Boot Start End Sectors Size Id Type
/dev/sda1 2048 499711 497664 243M 83 Linux
/dev/sda2 501758 912257024 911755267 434.8G 5 Extended
/dev/sda3 * 975173632 976773167 1599536 781M 83 Linux
/dev/sda4 912259072 975173631 62914560 30G 83 Linux
/dev/sda5 501760 912257024 911755265 434.8G 83 Linux
Partition table entries are not in disk order.
Command (m for help): w
The partition table has been altered.
Failed to update system information about partition 2: Device or resource busy
The kernel still uses the old partitions. The new table will be used at the next reboot.
Syncing disks.
The error at the end doesn't seem to ever have caused any trouble for me, so I ignore it?
But we're not out of the woods yet. Running pvs
gives a warning that the PV
is larger than the partition:
root@debian:/home/user# pvs -v --segments
WARNING: Device /dev/sda5 has size of 911755265 sectors which is smaller than corresponding PV size of 911759360 sectors. Was device resized?
WARNING: One or more devices used as PVs in VG edtwardy-vg have changed sizes.
...
I simply resize the PV to be the same size as the partition, and we're good to go:
root@debian:/home/user# pvresize --setphysicalvolumesize 911759360s /dev/sda5
WARNING: Device /dev/sda5 has size of 911755265 sectors which is smaller than corresponding PV size of 911759360 sectors. Was device resized?
WARNING: One or more devices used as PVs in VG edtwardy-vg have changed sizes.
WARNING: /dev/sda5: Overriding real size <434.76 GiB. You could lose data.
/dev/sda5: Requested size 434.76 GiB exceeds real size <434.76 GiB. Proceed? [y/n]: y
WARNING: /dev/sda5: Pretending size is 911759360 not 911755265 sectors.
Physical volume "/dev/sda5" changed
1 physical volume(s) resized or updated / 0 physical volume(s) not resized
I'm not sure why this happens. My expectation is that if it were unsafe,
pvresize
would complain, like it otherwise does if you try to reduce the PV
size to below the actual space used by the allocated LEs. It's scary, but I
haven't had a problem so far, and I've done this twice.
If this is done incorrectly, the kernel may fail to boot, and device-mapper will put an error in the boot log. From this error, it should be easy to determine what to do. Usually, this means extending the partition by some number of sectors.
Don't forget to update /etc/fstab
if the root or boot partitions were
changed.
Filesystem Management Tools
ext2, ext3, ext4
The dumpe2fs
tool will dump information about the filesystem. It can be used,
e.g. to determine the current size of the filesystem. The resize2fs
tool is
used to resize the filesystem, and e2fsck
will repair a filesystem.
ISO-9660
The isoinfo
tool provides information about these filesystems.
Btrfs
The package btrfs-progs
contains useful utilities for working with these
filesystems.
LVM2
LVM uses device-mapper to create various storage pools that expose a storage layout to userspace that doesn't necessarily reflect the physical organization of storage.
In LVM2, volume groups may contain mutliple physical volumes and multiple logical volumes. A logical volume is a block of storage that is presented to userspace as a contiguous disk.
The tools vgdisplay
, lvdisplay
and pvdisplay
can be used to show the
existing storage layout. The tools lvreduce
and lvextend
can be used to
change the size of a logical volume:
# Extend the size of the volume by 50GiB
lvextend -L +50G volume-group/my-volume
The volume argument to the above command correlates to the device-mapper device
exposed at /dev/volume-group/my-volume
.
Creating an NTFS partition on Linux
Using fdisk
, first create a partition label (DOS/GPT/whatever), then a new
partition. Use the t
command to change the partition type to 7--NTFS/exFAT
.
Finally, use the mkfs.ntfs
command to create an NTFS partition on the disk.
On Arch Linux, this tool is installed via the ntfs-3g
package.