@@ -1695,6 +1695,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);
+ int flags = BTRFS_QGROUP_STATUS_FLAG_ON;
if (!silent)
printf("Repair qgroup status item\n");
@@ -1717,8 +1719,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;
+ 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);
@@ -108,6 +108,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,5),
+ VERSION_NULL(safe),
+ VERSION_NULL(default),
+ .desc = "squota support (simple qgroups)"
+ },
{
.name = "extref",
.incompat_flag = BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF,
@@ -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,37 @@ static int insert_qgroup_items(struct btrfs_trans_handle *trans,
return ret;
}
+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);
+ 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);
+ btrfs_commit_transaction(trans, fs_info->fs_root);
+ 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 +923,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 +957,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;
+ }
+ 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 +986,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)
@@ -1743,7 +1794,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);