Recently, I sent a set of patches to btrfs community for qgroup to make quota working much better.
NOTE, before this patchset, I have sent a lot of patches for bug-fix about quota in btrfs.
(1). Probem: user found quota did not reach the limit but can not write any more.
Example:
Script:
mkfs.btrfs /dev/sdc -f
mount /dev/sdc /mnt
btrfs quota enable /mnt
btrfs quota rescan /mnt
sync
btrfs sub create /mnt/sub
btrfs qgroup limit -e 10M /mnt/sub
dd if=/dev/zero of=/mnt/sub/data bs=$((1024)) count=10240000000
sync
btrfs qgroup show -prce /mnt
Result:
dd: error writing ‘/mnt/sub/data’: Disk quota exceeded
10174+0 records in
10173+0 records out
10417152 bytes (10 MB) copied, 0.0356769 s, 292 MB/s
-rw-r--r--. 1 root root 10417152 Mar 22 08:49 /mnt/sub/data
qgroupid rfer excl max_rfer max_excl parent child
-------- ---- ---- -------- -------- ------ -----
0/5 16.00KiB 16.00KiB 0.00B 0.00B --- ---
0/257 9.95MiB 9.95MiB 0.00B 10.00MiB --- ---
0/258 16.00KiB 16.00KiB 0.00B 0.00B --- ---
It's very confusing to user, that "I limited my subvolume with 10M, and I found the quota number of
it is 9.95M, but I can't write any byte into it."
(2). Reason: qgroup in btrfs only account and limit size both of data and metadata.
That said, when a user want to write something into subvolume, btrfs will reserve some
metadata for it. Although what you want to write is not out of the limit, but the size of data and metadata
is out of the limit.
(3). Solution: account and limit data and metadata separately.
(a). I restructed the btrfs_qgroup in memory: btrfs_qgroup: |-------------| ----------------- |rfer | |data_info |--------------->btrfs_qgroup_info|rfer_cmpr | |metadata_info | |excl | | | |excl_cmpr | |data_limits | --------------- |metadata_limits| |mixed_limits |--------------->btrfs_qgroup_limits|------------- |-------------- | |lim_flags | |max_rfer | |max_excl | |rsv_rfer | |rsv_excl | ------------ In this way, we can store the information for data and metadata separately. And we can limit then in three ways: data_limits, metadata_limits and mixed_limits. (b). I have to add a incompatability feature for it. I reuse the objectid to search btrfs_qgroup_info_item. ------------------------------------ ------------------------------------------------ |0 |BTRFS_QGROUP_INFO_KEY |qgroupid| ------------>|TYPE_OBJECTID |BTRFS_QGROUP_INFO_KEY |qgroupid| ------------------------------------ ------------------------------------------------ And introduce two macros for different type of infos. #define BTRFS_QGROUP_DATA_INFO_OBJECTID 1ULL #define BTRFS_QGROUP_METADATA_INFO_OBJECTID 2ULL There is a similar change for limits. (c). Testing. Hi Chris and David, as what I mentioned in a offline mail, there is a url for merging or testing. btrfs: https://yangdongsheng <at> github.com/yangdongsheng/linux.git qgroup_type_v2 btrfs-progs: https://yangdongsheng <at> github.com/yangdongsheng/btrfs-progs.git qgroup_type_v2 (1). btrfs/022 and btrfs/042 kernel.v4.0-4c1 kernel.qgroup_type.patched v3.19-rc2(progs) pass pass Patched(progs) pass pass (2). No qgroup type. Script: # mkfs.btrfs /dev/sdc -f # mount /dev/sdc /mnt # btrfs quota enable /mnt # btrfs quota rescan -w /mnt # btrfs sub create /mnt/sub # btrfs qgroup limit -e 10M 0/257 /mnt # dd if=/dev/zero of=/mnt/sub/data bs=1024 count=1000000 # sync # btrfs qgroup show -prce --raw /mnt Expected: dd: error writing '/mnt/sub/data': Disk quota exceeded 10145+0 records in 10144+0 records out 10387456 bytes (10 MB) copied, 0.0368423 s, 282 MB/s qgroupid rfer excl max_rfer max_excl parent child -------- ---- ---- -------- -------- ------ ----- 0/5 16384 16384 0 0 --- --- 0/257 10403840 10403840 0 0 --- --- kernel.v4.0-4c1.bugfix_patched kernel.qgroup_type.patched v3.19-rc2(progs) pass pass Patched(progs) pass pass (3) qgroup type. Script: # mkfs.btrfs -O qgroup-type /dev/sdc -f # mount /dev/sdc /mnt # btrfs quota enable /mnt # btrfs quota rescan -w /mnt # btrfs sub create /mnt/sub # btrfs qgroup limit --type data -e 10M 0/257 /mnt # dd if=/dev/zero of=/mnt/sub/data bs=1024 count=1000000 # sync # btrfs qgroup show -prce --raw --type data /mnt # btrfs qgroup show -prce --raw --type metadata /mnt # btrfs qgroup show -prce --raw --type mixed /mnt kernel.v4.0-4c1.bugfix_patched kernel.qgroup_type.patched v3.19-rc2(progs) mkfs fail(no feature for qgroup-type) mkfs fail(no feature for qgroup-type) Patched(progs) open_ctree failed. (Expected) result as below. (pass) Result: dd: error writing '/mnt/sub/data': Disk quota exceeded 10241+0 records in 10240+0 records out <------10240 means 10M 10485760 bytes (10 MB) copied, 0.0331533 s, 316 MB/s qgroupid rfer excl max_rfer max_excl parent child -------- ---- ---- -------- -------- ------ ----- 0/5 0 0 0 0 --- --- 0/257 10485760 10485760 0 10485760 --- --- <------DATA info and limits qgroupid rfer excl max_rfer max_excl parent child -------- ---- ---- -------- -------- ------ ----- 0/5 16384 16384 0 0 --- --- 0/257 16384 16384 0 0 --- --- <------METADATA info and limits qgroupid rfer excl max_rfer max_excl parent child -------- ---- ---- -------- -------- ------ ----- 0/5 16384 16384 0 0 --- --- 0/257 10502144 10502144 0 0 --- --- <------MIXED info and limits After all, you can use btrfs-debug-tree tool to show the details for each items.