Moved from Ext4 to BTRFS, now quotas have no effect

Hello,

First I installed Debian 13 with Incus 7.0.1 (backports) in a single Ext4 partition for whole OS. I enabled “prjquota” and succeeded on setting containers’ device root size.

After this, I created a separate BTRFS partition and moved /var to it, so all Incus data (with VPS, VM, etc.) is there now. The move was done from an external session (Debian 13 Live) by only copying files: cp -a /media/user/rootvolume/var/* /media/user/var/

Once rebooted into static media (Debian+Incus), I see containers have devices:root:size set but this setting has no effect. Inside each container whole host partition space is seen.

From host I see:

$ sudo btrfs qgroup show -r /var
Qgroupid    Referenced    Exclusive  Max referenced   Path
0/5          987.34GiB    987.34GiB            none   

What should I do to apply storage quotas to containers again?

Thank you.

hmm, I’d have expected that enabling quotas on btrfs and then re-applying your root size limits would populate things. Though I don’t remember btrfs quotas being reflected in df or similar in the container, so that part may be normal.

Ext4 quotas (prjquota) were reflected in guest df

How do I see this when using btrfs filesystem for DIR containers?

This command has no effect with my btrfs, as a way to re-apply root size limit:

$ incus config device set MyContainerName root size=20GiB

I’ve also tried with new container creation, and I find same lack of disk limit appearance:

$ incus launch images:debian/13 MyContainerName2 --device root,size=20GiB

And also tested reality of limits; no limit in effect:

$ incus config device set MyContainerName2 root size=5GiB
$ incus exec MyContainerName2 -- dd if=/dev/urandom bs=1M count=10240 of=test1.dat

I see from incus admin init wizard:

  • Do you want to configure a new local storage pool? (yes/no) [default=yes]:
  • Name of the storage backend to use (dir, btrfs) [default=btrfs]:
  • Would you like to create a new btrfs subvolume under /var/lib/incus? (yes/no) [default=yes]:

I suppose when it’s asking between {dir, btrfs} i really means {ext4, btrfs} because btrfs is used with DIR driver; am I right?

Do I need to do some storage pool conversion from DIR[ext4] to DIR[btrfs] ?

Yes, the kernel report project quotas in disk usage, it doesn’t report the btrfs qgroups though.
That’s not something we control ourselves.

Ah, so yeah, if you’re using the dir driver on top of btrfs, then you get the worse of both worlds :slight_smile:
Basically you don’t get the btrfs subvolume based stuff, so still duplicate a lot of data AND you don’t get quotas at all because you don’t have project quotas and aren’t using the driver that knows how to do qgroups.

Then you mean for btrfs I also need to run tune2fs -O project -Q prjquota to this volume? Or I need to create subvolumes? Or this can be done by running incus admin init wizard again?

Is it the same to get deduplication/CoW feature?

Documentation is a bit confusing about dir/btrfs; If BTRFS driver means not DIR, this should be clear, and then mention DIR driver has only sense on top of Ext3/Ext4.

dir works on any filesystem and therefore supports almost no features. You can run it on ext3/ext4, you can run it on vfat, on xfs or on top of btrfs or ZFS. It will basically always work, just equally as bad everywhere.

btrfs is what you want when you want to run on btrfs (as the name kinda implies) and it therefore uses btrfs features like subvolumes, quota groups, send/receive, compression, …

tune2fs is the ext3/ext4 configuration tool, so that cannot do anything useful on a btrfs filesystem.

I suggest for documentation to note that neither “DIR on btrfs” nor “DIR on zfs” are the same as “direct btrfs” or “direct zfs”, and that there is no “direct ext4” without DIR.

This could avoid a mistake as mine.

What can I do to fix current situation? What does Incus need from my “DIR on btrfs” to convert to “direct btrfs”?

Define a new storage pool with incus storage create, then use incus move and incus storage volume move to move things one by one between the two pools.

$ incus storage create local-btrfs btrfs
Storage pool local-btrfs created

$ incus storage list
+-------------+--------+-------------+---------+---------+
|    NAME     | DRIVER | DESCRIPTION | USED BY |  STATE  |
+-------------+--------+-------------+---------+---------+
| local       | dir    |             | 12      | CREATED |
+-------------+--------+-------------+---------+---------+
| local-btrfs | btrfs  |             | 0       | CREATED |
+-------------+--------+-------------+---------+---------+

$ incus storage volume list local -c ntc
+-------------------------------+-----------------+--------------+
|             NAME              |      TYPE       | CONTENT-TYPE |
+-------------------------------+-----------------+--------------+
| MyCloudContainer              | container       | filesystem   |
+-------------------------------+-----------------+--------------+
| MyContainerName               | container       | filesystem   |
+-------------------------------+-----------------+--------------+
| MyContainerName3              | container       | filesystem   |
+-------------------------------+-----------------+--------------+
| MyMachine                     | virtual-machine | block        |
+-------------------------------+-----------------+--------------+
| debian                        | container       | filesystem   |
+-------------------------------+-----------------+--------------+
| debian-13.6.0-amd64-DVD-1.iso | custom          | iso          |
+-------------------------------+-----------------+--------------+
| frxyt                         | container       | filesystem   |
+-------------------------------+-----------------+--------------+
| gentle-tetra                  | container       | filesystem   |
+-------------------------------+-----------------+--------------+
| ubuntu                        | container       | filesystem   |
+-------------------------------+-----------------+--------------+
| ubuntu2                       | container       | filesystem   |
+-------------------------------+-----------------+--------------+
| webtop                        | container       | filesystem   |
+-------------------------------+-----------------+--------------+

$ incus storage volume move local/MyCloudContainer local-btrfs/MyCloudContainer
Error: Storage pool volume not found

Custom volumes are moved with incus storage volume move, instances are moved with incus move.

Then what do I need to move?

Shouldn’t I need to move each listed volume from “local” storage pool to “local-btrfs” one?

Everything is in same host, then Really I need to use “incus move”… to rename instances?

incus move NAME --storage NEW-POOL

Okay, I’ve processed every instance with commands like:

$ incus stop MyCloudContainer --force
$ incus move MyCloudContainer --storage local-btrfs
$ incus start MyCloudContainer

And that ISO image with:

$ incus storage volume move local/debian-13.6.0-amd64-DVD-1.iso local-btrfs/debian-13.6.0-amd64-DVD-1.iso

(I had to set more room to fit all stuff into new storage pool):

$ incus storage set local-btrfs size=1TiB --target=$(hostname)

But Oh surprise! now all containers have 1TiB of disk quota and following has no effect:

$ incus config device set MyContainerName root size=50GiB
$ incus storage volume set local-btrfs container/MyContainerName size=50GiB
Error: Volume "size" property is not valid for volume type

How did you determine that they have 1TiB disk quota?

$ df -hT /var
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/nvme0n1p4 btrfs  1.8T  976G  827G  55% /var

$ for ccc in $(incus list -c n -f compact,noheader) ; do incus exec $ccc -- df -hT / ; done
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/loop0     btrfs  1.0T   68G  957G   7% /
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/loop0     btrfs  1.0T   68G  957G   7% /
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/loop0     btrfs  1.0T   68G  957G   7% /
Filesystem             Type   Size  Used Avail Use% Mounted on
/dev/mapper/sda2_crypt btrfs   50G   39G  9.6G  81% /
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/loop0     btrfs  1.0T   68G  957G   7% /
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/loop0     btrfs  1.0T   68G  957G   7% /
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/loop0     btrfs  1.0T   68G  957G   7% /
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/loop0     btrfs  1.0T   68G  957G   7% /
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/loop0     btrfs  1.0T   68G  957G   7% /
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/loop0     btrfs  1.0T   68G  957G   7% /

Please see my previous message: Moved from Ext4 to BTRFS, now DIR quotas have no effect - #5 by stgraber

Okay, I’ve enabled quotas, then I’ve created a new storage pool and moved all containers into it but, once I reboot Incus host, no effect on per-container quota:

$ sudo btrfs quota enable /var
$ incus storage create base-btrfs btrfs
$ incus storage set base-btrfs size=1TiB --target=$(hostname)
$ for ccc in $(incus list -c n -f compact,noheader) ; do incus stop $ccc --force ; incus move $ccc --storage base-btrfs ; incus start $ccc ; done
$ incus storage volume move local-btrfs/debian-13.6.0-amd64-DVD-1.iso base-btrfs/debian-13.6.0-amd64-DVD-1.iso
Storage volume moved successfully!
$ sudo reboot
$ incus exec MyContainerName -- df -hT /
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/loop0     btrfs  1.0T   62G  962G   7% /
$ incus config device set MyContainerName root size=50GiB
$ incus exec MyContainerName -- df -hT /
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/loop0     btrfs  1.0T   62G  962G   7% /
$ sudo btrfs qgroup show -r /var
Qgroupid    Referenced    Exclusive  Max referenced   Path 
--------    ----------    ---------  --------------   ---- 
0/5          966.86GiB    966.86GiB            none   <toplevel>

What else do I should to do to see if Linux kernel is reporting or not qgroups in disk usage? cmdline? mounts?

$ btrfs quota status /var
Quotas on /var:
  Enabled:                 yes
  Mode:                    qgroup (full accounting)
  Inconsistent:            no
  Override limits:         no
  Drop subtree threshold:  3
  Total count:             1
  Level 0:                 1

Thank you.

root@v1:~# incus storage create btrfs btrfs
Storage pool btrfs created
root@v1:~# btrfs qgroup show /var/lib/incus/storage-pools/btrfs/
ERROR: can't list qgroups: quotas not enabled

root@v1:~# incus launch images:debian/13 c1 --storage btrfs -d root,size=1GiB
Launching c1
root@v1:~# btrfs qgroup show /var/lib/incus/storage-pools/btrfs/
Qgroupid    Referenced    Exclusive   Path 
--------    ----------    ---------   ---- 
0/5           16.00KiB     16.00KiB   <toplevel>
0/256        406.22MiB      1.00MiB   images/76be7a5c0def9ffeec3d08755613b2ac9974352c18a204110e1250f77c7b305d
0/257        417.06MiB     11.84MiB   containers/c1

root@v1:~# incus exec c1 bash
root@c1:~# df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0       30G  441M   30G   2% /
root@c1:~# dd if=/dev/urandom of=out.img bs=4M count=1000
dd: error writing 'out.img': Disk quota exceeded
152+0 records in
151+0 records out
635011072 bytes (635 MB, 606 MiB) copied, 2.00688 s, 316 MB/s
root@c1:~# df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0       30G  1.1G   29G   4% /
root@c1:~# 
exit

root@v1:~# incus launch images:debian/13 c2 --storage default -d root,size=5GiB
Launching c2
root@v1:~# incus stop c2
root@v1:~# incus move c2 --storage btrfs
root@v1:~# btrfs qgroup show /var/lib/incus/storage-pools/btrfs/
Qgroupid    Referenced    Exclusive   Path 
--------    ----------    ---------   ---- 
0/5           16.00KiB     16.00KiB   <toplevel>
0/256        406.22MiB      1.46MiB   images/76be7a5c0def9ffeec3d08755613b2ac9974352c18a204110e1250f77c7b305d
0/257       1023.98MiB    619.22MiB   containers/c1
0/258        402.93MiB    402.93MiB   containers/c2
root@v1:~# incus start c2
root@v1:~# incus exec c2 bash
root@c2:~# dd if=/dev/urandom of=out.img bs=4M count=2000
dd: error writing 'out.img': Disk quota exceeded
1177+0 records in
1176+0 records out
4934565888 bytes (4.9 GB, 4.6 GiB) copied, 15.0142 s, 329 MB/s
root@c2:~# df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0       30G  6.1G   24G  21% /

Try running the qgroup commands against /var/lib/incus/storage-pools/base-btrfs in your case, see if that picks up the right part of the tree.