3

I have btrfs image file set as backend for LXD (2.18) but I would like to shrink it's size. What I did:

  • mounted image to loop device losetup /dev/loop1 /home/btrfs.img
  • mounted device to /mnt dir mount /dev/loop1 /mnt/brtfs
  • resized btrfs partition with btrfs filesystem resize -100G /mnt/btrfs

And after that df correctly shows partition size of /mnt/btrfs:

root@host:/mnt/btrfs# df -k .
Filesystem      1K-blocks       Used Available Use% Mounted on
/dev/loop1     1614807040 1563273068  48426164  97% /mnt/btrfs

but file is still with the same size

root@host:/home# ls -al
total 1848321632
drwx------ 2 root root          4096 Nov 11 10:19 .
drwxr-xr-x 4 root root          4096 Nov 11 10:19 ..
-rw------- 1 root root 1932735283200 Nov 11 06:29 btrfs.img

Later I've tried btrfs filesystem resize -100GB /home/btrfs.img and it didn't work according to documentation:

Warning: If path is a file containing a BTRFS image then resize does not work as expected and does not resize the image. This would resize the underlying filesystem instead.

My question is: how can I shrink whole file without loosing data?

Kaburabu
  • 31
  • 3

3 Answers3

1

truncate -s100G /home/btrfs.img

expert
  • 322
  • 1
  • 3
  • 14
  • 1
    And if I run across a file where the embedded btrfs filesystem isn't occupying all the file space, how do I "shrink-wrap" the file to match the filesystem? I.e., where do I find the exact parameter to use with `truncate`? – rickhg12hs Aug 28 '18 at 17:42
0

In Automatically resize (shrink) BTRFS image file #5801, member stgraber notes "There are tricks you can do to do it anyway, effectively manually creating a second loop file, adding it to btrfs as a mirror device, then removing the original, but this is slow and very much a manual process that we have no intention to automate in LXD." However, he doesn't give additional details.

The procedure below worked well for me on Ubuntu 20.04. I freed up 3GB on a VPS and it only required the one loop file.

  1. Make sure you have some free disk space available--maybe 200MB
  2. Stop LXD, locate your storage pool, and note it's current size:
    sudo systemctl stop snap.lxd.daemon
    POOL=$(lxc storage list |grep ^..default |grep -Eo '/var/snap/lxd[^ ]+') && echo "POOL: $POOL"
    echo BEFORE
    sudo ls -al $POOL
    
  3. Set your desired size in bytes:
    NEWSIZE=12000000000  # 12GB
    
  4. Shrink the pool:
    LOOPDEV=$(sudo losetup --find --show $POOL |grep -Po /dev/loop[0-9]+); echo "LOOPDEV: $LOOPDEV"
    sudo mount $LOOPDEV /mnt
    sudo df --block-size=1 /mnt
    sudo btrfs filesystem resize $NEWSIZE /mnt
    sudo df --block-size=1 /mnt
    sudo umount /mnt
    sudo truncate --size=$NEWSIZE $POOL
    
  5. Verify the new size and resume LXD:
    echo AFTER
    sudo ls -al $POOL
    sudo systemctl start snap.lxd.daemon
    

If you receive errors to any of these steps, particularly the LOOPDEV=..., reboot and try again from the beginning.

bitinerant
  • 180
  • 5
0

Try to shrink step by step from gui. Sometimes disk shows 95 GB full but you can shrink to 200G at best!

lsblk shows mounted loop device

loop0    7:0    0   535G  0 loop /var/lib/lxd/storage-pools/gedizsStoragePool
vda    254:0    0   550G  0 disk 
├─vda1 254:1    0   512M  0 part /boot/efi
└─vda2 254:2    0 549.5G  0 part /

resize filesystem from gui (suppose that to 200G worked):

sudo gparted /dev/loop0 

then truncate (suppose desired size is 200 GB) :

sudo truncate --size=200G /var/lib/lxd/disks/<yourdiskimage.img>

And to make sure if you need :

 sudo btrfs filesystem resize 200G /var/lib/lxd/storage-pools/gedizsStoragePool
Gediz GÜRSU
  • 536
  • 4
  • 12