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 <josef@toxicpanda.com> Signed-off-by: Boris Burkov <boris@bur.io> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
5bd97022f3
commit
14ac1a6051
|
@ -1696,6 +1696,8 @@ static int repair_qgroup_status(struct btrfs_fs_info *info, bool silent)
|
|||
struct btrfs_path path;
|
||||
struct btrfs_key key;
|
||||
struct btrfs_qgroup_status_item *status_item;
|
||||
bool simple = btrfs_fs_incompat(info, SIMPLE_QUOTA);
|
||||
u64 flags = BTRFS_QGROUP_STATUS_FLAG_ON;
|
||||
|
||||
if (!silent)
|
||||
printf("Repair qgroup status item\n");
|
||||
|
@ -1718,8 +1720,9 @@ static int repair_qgroup_status(struct btrfs_fs_info *info, bool silent)
|
|||
|
||||
status_item = btrfs_item_ptr(path.nodes[0], path.slots[0],
|
||||
struct btrfs_qgroup_status_item);
|
||||
btrfs_set_qgroup_status_flags(path.nodes[0], status_item,
|
||||
BTRFS_QGROUP_STATUS_FLAG_ON);
|
||||
if (simple)
|
||||
flags |= BTRFS_QGROUP_STATUS_FLAG_SIMPLE_MODE;
|
||||
btrfs_set_qgroup_status_flags(path.nodes[0], status_item, flags);
|
||||
btrfs_set_qgroup_status_rescan(path.nodes[0], status_item, 0);
|
||||
btrfs_set_qgroup_status_generation(path.nodes[0], status_item,
|
||||
trans->transid);
|
||||
|
|
|
@ -109,6 +109,15 @@ static const struct btrfs_feature mkfs_features[] = {
|
|||
VERSION_NULL(default),
|
||||
.desc = "quota support (qgroups)"
|
||||
},
|
||||
{
|
||||
.name = "squota",
|
||||
.incompat_flag = BTRFS_FEATURE_INCOMPAT_SIMPLE_QUOTA,
|
||||
.sysfs_name = "squota",
|
||||
VERSION_TO_STRING2(compat, 6,7),
|
||||
VERSION_NULL(safe),
|
||||
VERSION_NULL(default),
|
||||
.desc = "squota support (simple accounting qgroups)"
|
||||
},
|
||||
{
|
||||
.name = "extref",
|
||||
.incompat_flag = BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF,
|
||||
|
|
78
mkfs/main.c
78
mkfs/main.c
|
@ -59,6 +59,8 @@
|
|||
#include "mkfs/common.h"
|
||||
#include "mkfs/rootdir.h"
|
||||
|
||||
#include "libbtrfs/ctree.h"
|
||||
|
||||
struct mkfs_allocation {
|
||||
u64 data;
|
||||
u64 metadata;
|
||||
|
@ -882,6 +884,51 @@ static int insert_qgroup_items(struct btrfs_trans_handle *trans,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Workaround for squota so the enable_gen can be properly used.
|
||||
*/
|
||||
static int touch_root_subvol(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
struct btrfs_trans_handle *trans;
|
||||
struct btrfs_key key = {
|
||||
.objectid = BTRFS_FIRST_FREE_OBJECTID,
|
||||
.type = BTRFS_INODE_ITEM_KEY,
|
||||
.offset = 0,
|
||||
};
|
||||
struct extent_buffer *leaf;
|
||||
int slot;
|
||||
struct btrfs_path path;
|
||||
int ret;
|
||||
|
||||
trans = btrfs_start_transaction(fs_info->fs_root, 1);
|
||||
if (IS_ERR(trans)) {
|
||||
ret = PTR_ERR(trans);
|
||||
errno = -ret;
|
||||
error_msg(ERROR_MSG_START_TRANS, "%m");
|
||||
return ret;
|
||||
}
|
||||
btrfs_init_path(&path);
|
||||
ret = btrfs_search_slot(trans, fs_info->fs_root, &key, &path, 0, 1);
|
||||
if (ret)
|
||||
goto fail;
|
||||
leaf = path.nodes[0];
|
||||
slot = path.slots[0];
|
||||
btrfs_item_key_to_cpu(leaf, &key, slot);
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
ret = btrfs_commit_transaction(trans, fs_info->fs_root);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
|
||||
return ret;
|
||||
}
|
||||
btrfs_release_path(&path);
|
||||
return 0;
|
||||
fail:
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
btrfs_release_path(&path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int setup_quota_root(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
struct btrfs_trans_handle *trans;
|
||||
|
@ -890,8 +937,11 @@ static int setup_quota_root(struct btrfs_fs_info *fs_info)
|
|||
struct btrfs_path path;
|
||||
struct btrfs_key key;
|
||||
int qgroup_repaired = 0;
|
||||
bool simple = btrfs_fs_incompat(fs_info, SIMPLE_QUOTA);
|
||||
int flags;
|
||||
int ret;
|
||||
|
||||
|
||||
/* One to modify tree root, one for quota root */
|
||||
trans = btrfs_start_transaction(fs_info->tree_root, 2);
|
||||
if (IS_ERR(trans)) {
|
||||
|
@ -921,13 +971,19 @@ static int setup_quota_root(struct btrfs_fs_info *fs_info)
|
|||
|
||||
qsi = btrfs_item_ptr(path.nodes[0], path.slots[0],
|
||||
struct btrfs_qgroup_status_item);
|
||||
btrfs_set_qgroup_status_generation(path.nodes[0], qsi, 0);
|
||||
btrfs_set_qgroup_status_generation(path.nodes[0], qsi, trans->transid);
|
||||
btrfs_set_qgroup_status_rescan(path.nodes[0], qsi, 0);
|
||||
flags = BTRFS_QGROUP_STATUS_FLAG_ON;
|
||||
if (simple) {
|
||||
btrfs_set_qgroup_status_enable_gen(path.nodes[0], qsi, trans->transid);
|
||||
flags |= BTRFS_QGROUP_STATUS_FLAG_SIMPLE_MODE;
|
||||
}
|
||||
else {
|
||||
flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
|
||||
}
|
||||
|
||||
/* Mark current status info inconsistent, and fix it later */
|
||||
btrfs_set_qgroup_status_flags(path.nodes[0], qsi,
|
||||
BTRFS_QGROUP_STATUS_FLAG_ON |
|
||||
BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT);
|
||||
btrfs_set_qgroup_status_version(path.nodes[0], qsi, 1);
|
||||
btrfs_set_qgroup_status_flags(path.nodes[0], qsi, flags);
|
||||
btrfs_release_path(&path);
|
||||
|
||||
/* Currently mkfs will only create one subvolume */
|
||||
|
@ -944,6 +1000,15 @@ static int setup_quota_root(struct btrfs_fs_info *fs_info)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Hack to count the default subvol metadata by dirtying it */
|
||||
if (simple) {
|
||||
ret = touch_root_subvol(fs_info);
|
||||
if (ret) {
|
||||
error("failed to touch root dir for simple quota accounting %d (%m)", ret);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Qgroup is setup but with wrong info, use qgroup-verify
|
||||
* infrastructure to repair them. (Just acts as offline rescan)
|
||||
|
@ -1813,7 +1878,8 @@ raid_groups:
|
|||
}
|
||||
}
|
||||
|
||||
if (features.runtime_flags & BTRFS_FEATURE_RUNTIME_QUOTA) {
|
||||
if (features.runtime_flags & BTRFS_FEATURE_RUNTIME_QUOTA ||
|
||||
features.incompat_flags & BTRFS_FEATURE_INCOMPAT_SIMPLE_QUOTA) {
|
||||
ret = setup_quota_root(fs_info);
|
||||
if (ret < 0) {
|
||||
error("failed to initialize quota: %d (%m)", ret);
|
||||
|
|
Loading…
Reference in New Issue