Skip to content

Commit 14ac1a6

Browse files
boryaskdave
authored andcommitted
btrfs-progs: mkfs: add support for squota
Add the ability to enable simple quotas from mkfs with '-O squota' There is some complication around handling enable_gen while still counting the root node of an fs. To handle this, employ a hack of doing a no-op write on the root node to bump its generation up above that of the qgroup enable generation, which results in counting it properly. Reviewed-by: Josef Bacik <[email protected]> Signed-off-by: Boris Burkov <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 5bd9702 commit 14ac1a6

File tree

3 files changed

+86
-8
lines changed

3 files changed

+86
-8
lines changed

check/qgroup-verify.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,8 @@ static int repair_qgroup_status(struct btrfs_fs_info *info, bool silent)
16961696
struct btrfs_path path;
16971697
struct btrfs_key key;
16981698
struct btrfs_qgroup_status_item *status_item;
1699+
bool simple = btrfs_fs_incompat(info, SIMPLE_QUOTA);
1700+
u64 flags = BTRFS_QGROUP_STATUS_FLAG_ON;
16991701

17001702
if (!silent)
17011703
printf("Repair qgroup status item\n");
@@ -1718,8 +1720,9 @@ static int repair_qgroup_status(struct btrfs_fs_info *info, bool silent)
17181720

17191721
status_item = btrfs_item_ptr(path.nodes[0], path.slots[0],
17201722
struct btrfs_qgroup_status_item);
1721-
btrfs_set_qgroup_status_flags(path.nodes[0], status_item,
1722-
BTRFS_QGROUP_STATUS_FLAG_ON);
1723+
if (simple)
1724+
flags |= BTRFS_QGROUP_STATUS_FLAG_SIMPLE_MODE;
1725+
btrfs_set_qgroup_status_flags(path.nodes[0], status_item, flags);
17231726
btrfs_set_qgroup_status_rescan(path.nodes[0], status_item, 0);
17241727
btrfs_set_qgroup_status_generation(path.nodes[0], status_item,
17251728
trans->transid);

common/fsfeatures.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,15 @@ static const struct btrfs_feature mkfs_features[] = {
109109
VERSION_NULL(default),
110110
.desc = "quota support (qgroups)"
111111
},
112+
{
113+
.name = "squota",
114+
.incompat_flag = BTRFS_FEATURE_INCOMPAT_SIMPLE_QUOTA,
115+
.sysfs_name = "squota",
116+
VERSION_TO_STRING2(compat, 6,7),
117+
VERSION_NULL(safe),
118+
VERSION_NULL(default),
119+
.desc = "squota support (simple accounting qgroups)"
120+
},
112121
{
113122
.name = "extref",
114123
.incompat_flag = BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF,

mkfs/main.c

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
#include "mkfs/common.h"
6060
#include "mkfs/rootdir.h"
6161

62+
#include "libbtrfs/ctree.h"
63+
6264
struct mkfs_allocation {
6365
u64 data;
6466
u64 metadata;
@@ -882,6 +884,51 @@ static int insert_qgroup_items(struct btrfs_trans_handle *trans,
882884
return ret;
883885
}
884886

887+
/*
888+
* Workaround for squota so the enable_gen can be properly used.
889+
*/
890+
static int touch_root_subvol(struct btrfs_fs_info *fs_info)
891+
{
892+
struct btrfs_trans_handle *trans;
893+
struct btrfs_key key = {
894+
.objectid = BTRFS_FIRST_FREE_OBJECTID,
895+
.type = BTRFS_INODE_ITEM_KEY,
896+
.offset = 0,
897+
};
898+
struct extent_buffer *leaf;
899+
int slot;
900+
struct btrfs_path path;
901+
int ret;
902+
903+
trans = btrfs_start_transaction(fs_info->fs_root, 1);
904+
if (IS_ERR(trans)) {
905+
ret = PTR_ERR(trans);
906+
errno = -ret;
907+
error_msg(ERROR_MSG_START_TRANS, "%m");
908+
return ret;
909+
}
910+
btrfs_init_path(&path);
911+
ret = btrfs_search_slot(trans, fs_info->fs_root, &key, &path, 0, 1);
912+
if (ret)
913+
goto fail;
914+
leaf = path.nodes[0];
915+
slot = path.slots[0];
916+
btrfs_item_key_to_cpu(leaf, &key, slot);
917+
btrfs_mark_buffer_dirty(leaf);
918+
ret = btrfs_commit_transaction(trans, fs_info->fs_root);
919+
if (ret < 0) {
920+
errno = -ret;
921+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
922+
return ret;
923+
}
924+
btrfs_release_path(&path);
925+
return 0;
926+
fail:
927+
btrfs_abort_transaction(trans, ret);
928+
btrfs_release_path(&path);
929+
return ret;
930+
}
931+
885932
static int setup_quota_root(struct btrfs_fs_info *fs_info)
886933
{
887934
struct btrfs_trans_handle *trans;
@@ -890,8 +937,11 @@ static int setup_quota_root(struct btrfs_fs_info *fs_info)
890937
struct btrfs_path path;
891938
struct btrfs_key key;
892939
int qgroup_repaired = 0;
940+
bool simple = btrfs_fs_incompat(fs_info, SIMPLE_QUOTA);
941+
int flags;
893942
int ret;
894943

944+
895945
/* One to modify tree root, one for quota root */
896946
trans = btrfs_start_transaction(fs_info->tree_root, 2);
897947
if (IS_ERR(trans)) {
@@ -921,13 +971,19 @@ static int setup_quota_root(struct btrfs_fs_info *fs_info)
921971

922972
qsi = btrfs_item_ptr(path.nodes[0], path.slots[0],
923973
struct btrfs_qgroup_status_item);
924-
btrfs_set_qgroup_status_generation(path.nodes[0], qsi, 0);
974+
btrfs_set_qgroup_status_generation(path.nodes[0], qsi, trans->transid);
925975
btrfs_set_qgroup_status_rescan(path.nodes[0], qsi, 0);
976+
flags = BTRFS_QGROUP_STATUS_FLAG_ON;
977+
if (simple) {
978+
btrfs_set_qgroup_status_enable_gen(path.nodes[0], qsi, trans->transid);
979+
flags |= BTRFS_QGROUP_STATUS_FLAG_SIMPLE_MODE;
980+
}
981+
else {
982+
flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
983+
}
926984

927-
/* Mark current status info inconsistent, and fix it later */
928-
btrfs_set_qgroup_status_flags(path.nodes[0], qsi,
929-
BTRFS_QGROUP_STATUS_FLAG_ON |
930-
BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT);
985+
btrfs_set_qgroup_status_version(path.nodes[0], qsi, 1);
986+
btrfs_set_qgroup_status_flags(path.nodes[0], qsi, flags);
931987
btrfs_release_path(&path);
932988

933989
/* Currently mkfs will only create one subvolume */
@@ -944,6 +1000,15 @@ static int setup_quota_root(struct btrfs_fs_info *fs_info)
9441000
return ret;
9451001
}
9461002

1003+
/* Hack to count the default subvol metadata by dirtying it */
1004+
if (simple) {
1005+
ret = touch_root_subvol(fs_info);
1006+
if (ret) {
1007+
error("failed to touch root dir for simple quota accounting %d (%m)", ret);
1008+
goto fail;
1009+
}
1010+
}
1011+
9471012
/*
9481013
* Qgroup is setup but with wrong info, use qgroup-verify
9491014
* infrastructure to repair them. (Just acts as offline rescan)
@@ -1813,7 +1878,8 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
18131878
}
18141879
}
18151880

1816-
if (features.runtime_flags & BTRFS_FEATURE_RUNTIME_QUOTA) {
1881+
if (features.runtime_flags & BTRFS_FEATURE_RUNTIME_QUOTA ||
1882+
features.incompat_flags & BTRFS_FEATURE_INCOMPAT_SIMPLE_QUOTA) {
18171883
ret = setup_quota_root(fs_info);
18181884
if (ret < 0) {
18191885
error("failed to initialize quota: %d (%m)", ret);

0 commit comments

Comments
 (0)