Resizing Encrypted Filesystems
Posted by dkg on Tue 26 Jun 2007 at 14:13
Yes! You can grow an encrypted partition, as long as the size of the underlying block device grows first. If you have an ext3 filesystem on the encrypted partition, you can even grow the (encrypted) filesystem without unmounting it. This article gives a brief overview of how it is done.
I recommend reading the man pages for the commands used here. They are all quite good.
Below is a full transcript of creating and resizing an encrypted filesystem with a test setup. I don't include any RAID (mdadm) here, because that would all happen way before you even get to this step, since RAID devices are usually used as physical volumes to feed into an LVM Volume Group. The process below is basically two phases:
Phase 0 (Setup)
- Create a logical volume (just a block device, no filesystem yet)
- Overlay it with strong encryption (using LUKS)
- Create a filesystem on top of the encrypted device
- Mount the filesystem, and put some data into its tree
(and no, that's not my real passphrase; this is an experiment!)
[0 root@monkey ~]# vgs VG #PV #LV #SN Attr VSize VFree monkey0 1 9 0 wz--n- 54.49G 20.49G [0 root@monkey ~]# lvcreate --name=testy --size=50M monkey0 Rounding up size to full physical extent 52.00 MB Logical volume "testy" created [0 root@monkey ~]# cryptsetup luksFormat /dev/mapper/monkey0-testy WARNING! ======== This will overwrite data on /dev/mapper/monkey0-testy irrevocably. Are you sure? (Type uppercase yes): YES Enter LUKS passphrase: abc123 Verify passphrase: abc123 Command successful. [0 root@monkey ~]# cryptsetup luksOpen /dev/mapper/monkey0-testy testy_crypt Enter LUKS passphrase: abc123 key slot 0 unlocked. Command successful. [0 root@monkey ~]# mkfs -t ext3 -q /dev/mapper/testy_crypt [0 root@monkey ~]# mount /dev/mapper/testy_crypt /mnt [0 root@monkey ~]# dd if=/dev/zero of=/mnt/zeroes bs=1k count=1k 1024+0 records in 1024+0 records out 1048576 bytes (1.0 MB) copied, 0.0200926 seconds, 52.2 MB/s [0 root@monkey ~]# df -h /mnt Filesystem Size Used Avail Use% Mounted on /dev/mapper/testy_crypt 50M 5.9M 42M 13% /mnt [0 root@monkey ~]#
Phase 1 (Resizing)
- Grow the logical volume with lvresize
- Ask the cryptsetup subsystem to acknowledge the new size
- Grow the filesystem on top of the newly bigger encrypted device
- Look to see how much more space you've got!
In the transcript below, it's interesting to watch how the kernel's representation of the underlying block devices change in size. You can see this by grepping the content of /proc/partitions, which i've done during these steps to demonstrate:
[0 root@monkey ~]# lvs | grep testy testy monkey0 -wi-ao 52.00M [0 root@monkey ~]# ls -la /dev/mapper/monkey0-testy /dev/mapper/testy_crypt brw-rw---- 1 root disk 253, 14 2007-06-06 00:10 /dev/mapper/monkey0-testy brw-rw---- 1 root disk 253, 15 2007-06-06 00:10 /dev/mapper/testy_crypt [0 root@monkey ~]# grep '^\s*253\s*1[45]\s' /proc/partitions 253 14 53248 dm-14 253 15 52732 dm-15 [0 root@monkey ~]# lvresize --size=150M monkey0/testy Rounding up size to full physical extent 152.00 MB Extending logical volume testy to 152.00 MB Logical volume testy successfully resized [0 root@monkey ~]# grep '^\s*253\s*1[45]\s' /proc/partitions 253 14 155648 dm-14 253 15 52732 dm-15 [0 root@monkey ~]# cryptsetup resize testy_crypt [0 root@monkey ~]# grep '^\s*253\s*1[45]\s' /proc/partitions 253 14 155648 dm-14 253 15 155132 dm-15 [0 root@monkey ~]# df -h /mnt Filesystem Size Used Avail Use% Mounted on /dev/mapper/testy_crypt 50M 5.9M 42M 13% /mnt [0 root@monkey ~]# resize2fs /dev/mapper/testy_crypt resize2fs 1.40-WIP (14-Nov-2006) Filesystem at /dev/mapper/testy_crypt is mounted on /mnt; on-line resizing required old desc_blocks = 1, new_desc_blocks = 1 Performing an on-line resize of /dev/mapper/testy_crypt to 155132 (1k) blocks. The filesystem on /dev/mapper/testy_crypt is now 155132 blocks long. [0 root@monkey ~]# df -h /mnt Filesystem Size Used Avail Use% Mounted on /dev/mapper/testy_crypt 148M 6.3M 134M 5% /mnt [0 root@monkey ~]# ls -la /mnt/ total 1046 drwxr-xr-x 3 root root 1024 2007-06-06 00:12 . drwxr-xr-x 21 root root 4096 2007-02-27 20:08 .. drwx------ 2 root root 12288 2007-06-06 00:10 lost+found -rw-r--r-- 1 root root 1048576 2007-06-06 00:12 zeroes [0 root@monkey ~]#
Software versions
Here are the versions of the software used on monkey at the time i made this test, fwiw:
[0 dkg@monkey ~]$ uname -a Linux monkey 2.6.18-4-686 #1 SMP Mon Mar 26 17:17:36 UTC 2007 i686 GNU/Linux [0 dkg@monkey ~]$ dpkg -l e2fsprogs lvm2 cryptsetup Desired=Unknown/Install/Remove/Purge/Hold | Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed |/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad) ||/ Name Version Description +++-===========-=================================-========================================= ii cryptsetup 1.0.4+svn26-1 configures encrypted block devices ii e2fsprogs 1.39+1.40-WIP-2006.11.14+dfsg-2 ext2 file system utilities and libraries ii lvm2 2.02.06-4 The Linux Logical Volume Manager [0 dkg@monkey ~]$
Cleanup the experiment
And since no example is responsibly complete without the cleanup phase, here it is (note that this cleanup makes it nearly impossible to recover data from the filesystem so removed, particularly if you've forgotten the LUKS passphrase):
[0 root@monkey ~]# umount /mnt [0 root@monkey ~]# cryptsetup luksClose testy_crypt [0 root@monkey ~]# lvremove monkey0/testy Do you really want to remove active logical volume "testy"? [y/n]: y Logical volume "testy" successfully removed [0 root@monkey ~]#
I hope this is useful!
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
# grow raid array (raid1 with sda1 sdb1)
mdadm /dev/md0 --grow --size=max
# JFS resize
mount -o remount,resize /mnt/my_jfs_filesystem
It worked great nonetheless :
~# cat /proc/partitions
major minor #blocks name
8 1 488384001 sda1
8 17 488384001 sdb1
9 0 488383936 md0
253 0 488383420 dm-0
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
I might have figured it out myself, but that saved me some time. Also it's nice to *know* that it'll work beforehand.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ Send Message | View dkg's Scratchpad | View Weblogs ]
[ Parent | Reply to this comment ]
[root@localhost ~]# cryptsetup resize testy_crypt [root@localhost ~]# resize2fs /dev/mapper/testy_crypt resize2fs 1.39 (29-May-2006) Filesystem at /dev/mapper/testy_crypt is mounted on /mnt; on-line resizing required On-line shrinking from 212863 to 139135 not supported. [root@localhost ~]# umount /dev/mapper/testy_crypt [root@localhost ~]# resize2fs /dev/mapper/testy_crypt resize2fs 1.39 (29-May-2006) Please run 'e2fsck -f /dev/mapper/testy_crypt' first. [root@localhost ~]# e2fsck -f /dev/mapper/testy_crypt e2fsck 1.39 (29-May-2006) The filesystem size (according to the superblock) is 212863 blocks The physical size of the device is 139135 blocks Either the superblock or the partition table is likely to be corrupt! Abort? no Pass 1: Checking inodes, blocks, and sizes Error reading block 163877 (Invalid argument) while doing inode scan. Ignore error? no Error while scanning inodes (69600): Can't read next inode e2fsck: aborted [root@localhost ~]# resize2fs /dev/mapper/testy_crypt resize2fs 1.39 (29-May-2006) Please run 'e2fsck -f /dev/mapper/testy_crypt' first. [root@localhost ~]# e2fsck -f /dev/mapper/testy_crypt e2fsck 1.39 (29-May-2006) The filesystem size (according to the superblock) is 212863 blocks The physical size of the device is 139135 blocks Either the superblock or the partition table is likely to be corrupt! Abort? no Pass 1: Checking inodes, blocks, and sizes Error reading block 163877 (Invalid argument) while doing inode scan. Ignore error? no Error while scanning inodes (69600): Can't read next inode e2fsck: aborted [root@localhost ~]# resize2fs /dev/mapper/testy_crypt resize2fs 1.39 (29-May-2006) Please run 'e2fsck -f /dev/mapper/testy_crypt' first.Any ideas?
[ Parent | Reply to this comment ]
[ Send Message | View dkg's Scratchpad | View Weblogs ]
That is, for shrinking a filesystem, you'll want to:
- resize2fs
- cryptsetup resize
- lvresize
If you try it that way, does it work for you?
[ Parent | Reply to this comment ]
- resized the fs from 1Gb to 100Mb
- resized the crypted fs accordingly
- resized the partition from 1Gb to 150Mb (so a bigger value than the fs)
- resized the crypted fs
- resized the fs automatically up to the new partition size
[root@localhost ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup00-rt
4.8G 2.7G 1.9G 60% /
/dev/md0 99M 25M 70M 27% /boot
tmpfs 187M 0 187M 0% /dev/shm
/dev/mapper/testy_crypt
1010M 17M 954M 2% /mnt
[root@localhost ~]# resize2fs /dev/mapper/testy_crypt 100M
resize2fs 1.39 (29-May-2006)
Filesystem at /dev/mapper/testy_crypt is mounted on /mnt; on-line resizing required
On-line shrinking from 262015 to 25600 not supported.
[root@localhost ~]# umount /dev/mapper/testy_crypt
[root@localhost ~]# resize2fs /dev/mapper/testy_crypt 100M
resize2fs 1.39 (29-May-2006)
Please run 'e2fsck -f /dev/mapper/testy_crypt' first.
[root@localhost ~]# e2fsck -f /dev/mapper/testy_crypt
e2fsck 1.39 (29-May-2006)
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/mapper/testy_crypt: 17/111360 files (5.9% non-contiguous), 7800/262015 blocks
[root@localhost ~]# resize2fs /dev/mapper/testy_crypt 100M
resize2fs 1.39 (29-May-2006)
Resizing the filesystem on /dev/mapper/testy_crypt to 25600 (4k) blocks.
The filesystem on /dev/mapper/testy_crypt is now 25600 blocks long.
[root@localhost ~]# cryptsetup resize testy_crypt
[root@localhost ~]# lvresize /dev/VolGroup00/crypt -L 150M
Rounding up size to full physical extent 160.00 MB
WARNING: Reducing active and open logical volume to 160.00 MB
THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce testy? [y/n]: y
Reducing logical volume testy to 160.00 MB
Logical volume testy successfully resized
[root@localhost ~]# cryptsetup resize testy_crypt
[root@localhost ~]# resize2fs /dev/mapper/testy_crypt
resize2fs 1.39 (29-May-2006)
Resizing the filesystem on /dev/mapper/testy_crypt to 40831 (4k) blocks.
The filesystem on /dev/mapper/testy_crypt is now 40831 blocks long.
[root@localhost ~]# lvs
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
testy VolGroup00 -wi-ao 160.00M
rt VolGroup00 -wi-ao 4.88G
swp VolGroup00 -wi-ao 992.00M
[root@localhost ~]# mount /dev/mapper/testy_crypt /mnt
[root@localhost ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup00-rt
4.8G 2.7G 1.9G 60% /
/dev/md0 99M 25M 70M 27% /boot
tmpfs 187M 0 187M 0% /dev/shm
/dev/mapper/testy_crypt
157M 17M 135M 11% /mnt
[root@localhost ~]# ls -l /mnt
total 100
-rwxr-xr-x 1 root root 1310 Aug 11 20:25 anaconda-ks.cfg
-rw-r--r-- 1 root root 14157 Aug 11 20:25 asdasdasdasd.txt
-rwxr-xr-x 1 root root 22287 Aug 11 20:25 install.log
-rwxr-xr-x 1 root root 4037 Aug 11 20:25 install.log.syslog
drwx------ 2 root root 16384 Aug 11 16:28 lost+found
-rw-r--r-- 1 root root 14157 Aug 11 20:25 test.txt
[ Parent | Reply to this comment ]
Be careful with the units you use, when you specify "100M", it does not always have the same meaning across tools, it can either refer to "megabytes" (1000 kilobytes) or "mebibytes" (1024 kibibytes) (read wikipedia about this).
I urge you to check which meaning has each tool by reading the manpages (for LVM tools, it's in the pvs(1) manpage, and it's all about the case of the character)
[ Parent | Reply to this comment ]
# cryptsetup resize testy_crypt
will shrink the the luks device. I think it will enlarge it to the maximum possible size. You have to use the "--size" option and specify the new number of sectors. Doing it as you did will leave the luks device larger than the logical volume under it.
[ Parent | Reply to this comment ]
Also, do you need to take metadata overhead into account? In other words, if I use resize2fs to resize a 1T partition to 500 gigabytes, can I simply type "cryptsetup resize --size <500G of sectors> <diskname>", or do I need to take overhead into account?
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
I don't think you have to resize, unless you cannot remove. 'resize' is for devices that are actively mapped. For others 'create' will just create larger/smaller, if the size of the device has changed.
If I am correct, for a block-device that has changed its size while being mapped, just call
cryptsetup resize $device
[ Parent | Reply to this comment ]
[ Send Message | View dkg's Scratchpad | View Weblogs ]
cryptsetup takes an existing block device, and produces (via the device-mapper) a new block device. The "underlying block device" is the input to this process (even if it was itself created by the device mapper and has yet another underlying block device beneath it in the stack).
As for the metadata, are you talking about filesystem metadata or LVM or LUKS metadata? If you're talking about LVM or LUKS metadata, that's all metadata that eventually gets fed in one form or another to the device mapper. Each dm-exported block device has a size that does not reflect any metadata. That is, when the device-mapper offers a block device, nothing you write into that block device should be directly possible to screw up the metadata that defines that block device.
[ Parent | Reply to this comment ]
Your article about cryptsetup resize was a day saver. Thanks!
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]