Commit 182940f4 authored by Boris Burkov's avatar Boris Burkov Committed by David Sterba

btrfs: qgroup: add new quota mode for simple quotas

Add a new quota mode called "simple quotas". It can be enabled by the
existing quota enable ioctl via a new command, and sets an incompat
bit, as the implementation of simple quotas will make backwards
incompatible changes to the disk format of the extent tree.
Signed-off-by: default avatarBoris Burkov <boris@bur.io>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 6b0cd63b
...@@ -959,8 +959,7 @@ int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans, ...@@ -959,8 +959,7 @@ int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
return -ENOMEM; return -ENOMEM;
} }
if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) && if (btrfs_qgroup_enabled(fs_info) && !generic_ref->skip_qgroup) {
!generic_ref->skip_qgroup) {
record = kzalloc(sizeof(*record), GFP_NOFS); record = kzalloc(sizeof(*record), GFP_NOFS);
if (!record) { if (!record) {
kmem_cache_free(btrfs_delayed_tree_ref_cachep, ref); kmem_cache_free(btrfs_delayed_tree_ref_cachep, ref);
...@@ -1063,8 +1062,7 @@ int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans, ...@@ -1063,8 +1062,7 @@ int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
return -ENOMEM; return -ENOMEM;
} }
if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) && if (btrfs_qgroup_enabled(fs_info) && !generic_ref->skip_qgroup) {
!generic_ref->skip_qgroup) {
record = kzalloc(sizeof(*record), GFP_NOFS); record = kzalloc(sizeof(*record), GFP_NOFS);
if (!record) { if (!record) {
kmem_cache_free(btrfs_delayed_data_ref_cachep, ref); kmem_cache_free(btrfs_delayed_data_ref_cachep, ref);
......
...@@ -220,7 +220,8 @@ enum { ...@@ -220,7 +220,8 @@ enum {
BTRFS_FEATURE_INCOMPAT_NO_HOLES | \ BTRFS_FEATURE_INCOMPAT_NO_HOLES | \
BTRFS_FEATURE_INCOMPAT_METADATA_UUID | \ BTRFS_FEATURE_INCOMPAT_METADATA_UUID | \
BTRFS_FEATURE_INCOMPAT_RAID1C34 | \ BTRFS_FEATURE_INCOMPAT_RAID1C34 | \
BTRFS_FEATURE_INCOMPAT_ZONED) BTRFS_FEATURE_INCOMPAT_ZONED | \
BTRFS_FEATURE_INCOMPAT_SIMPLE_QUOTA)
#ifdef CONFIG_BTRFS_DEBUG #ifdef CONFIG_BTRFS_DEBUG
/* /*
......
...@@ -3697,7 +3697,8 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg) ...@@ -3697,7 +3697,8 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
switch (sa->cmd) { switch (sa->cmd) {
case BTRFS_QUOTA_CTL_ENABLE: case BTRFS_QUOTA_CTL_ENABLE:
ret = btrfs_quota_enable(fs_info); case BTRFS_QUOTA_CTL_ENABLE_SIMPLE_QUOTA:
ret = btrfs_quota_enable(fs_info, sa);
break; break;
case BTRFS_QUOTA_CTL_DISABLE: case BTRFS_QUOTA_CTL_DISABLE:
ret = btrfs_quota_disable(fs_info); ret = btrfs_quota_disable(fs_info);
......
This diff is collapsed.
...@@ -101,8 +101,15 @@ ...@@ -101,8 +101,15 @@
* subtree rescan for them. * subtree rescan for them.
*/ */
#define BTRFS_QGROUP_RUNTIME_FLAG_CANCEL_RESCAN (1UL << 3) /*
#define BTRFS_QGROUP_RUNTIME_FLAG_NO_ACCOUNTING (1UL << 4) * These flags share the flags field of the btrfs_qgroup_status_item with the
* persisted flags defined in btrfs_tree.h.
*
* To minimize the chance of collision with new persisted status flags, these
* count backwards from the MSB.
*/
#define BTRFS_QGROUP_RUNTIME_FLAG_CANCEL_RESCAN (1ULL << 63)
#define BTRFS_QGROUP_RUNTIME_FLAG_NO_ACCOUNTING (1ULL << 62)
/* /*
* Record a dirty extent, and info qgroup to update quota on it * Record a dirty extent, and info qgroup to update quota on it
...@@ -276,13 +283,17 @@ enum { ...@@ -276,13 +283,17 @@ enum {
ENUM_BIT(QGROUP_FREE), ENUM_BIT(QGROUP_FREE),
}; };
int btrfs_quota_enable(struct btrfs_fs_info *fs_info);
enum btrfs_qgroup_mode { enum btrfs_qgroup_mode {
BTRFS_QGROUP_MODE_DISABLED, BTRFS_QGROUP_MODE_DISABLED,
BTRFS_QGROUP_MODE_FULL, BTRFS_QGROUP_MODE_FULL,
BTRFS_QGROUP_MODE_SIMPLE
}; };
enum btrfs_qgroup_mode btrfs_qgroup_mode(struct btrfs_fs_info *fs_info); enum btrfs_qgroup_mode btrfs_qgroup_mode(struct btrfs_fs_info *fs_info);
bool btrfs_qgroup_enabled(struct btrfs_fs_info *fs_info);
bool btrfs_qgroup_full_accounting(struct btrfs_fs_info *fs_info);
int btrfs_quota_enable(struct btrfs_fs_info *fs_info,
struct btrfs_ioctl_quota_ctl_args *quota_ctl_args);
int btrfs_quota_disable(struct btrfs_fs_info *fs_info); int btrfs_quota_disable(struct btrfs_fs_info *fs_info);
int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info); int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
void btrfs_qgroup_rescan_resume(struct btrfs_fs_info *fs_info); void btrfs_qgroup_rescan_resume(struct btrfs_fs_info *fs_info);
......
...@@ -510,7 +510,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, ...@@ -510,7 +510,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_fs_info *fs_info = root->fs_info;
struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) { if (btrfs_qgroup_enabled(fs_info)) {
/* One for parent inode, two for dir entries */ /* One for parent inode, two for dir entries */
qgroup_num_bytes = 3 * fs_info->nodesize; qgroup_num_bytes = 3 * fs_info->nodesize;
ret = btrfs_qgroup_reserve_meta_prealloc(root, ret = btrfs_qgroup_reserve_meta_prealloc(root,
......
...@@ -1620,11 +1620,10 @@ static int qgroup_account_snapshot(struct btrfs_trans_handle *trans, ...@@ -1620,11 +1620,10 @@ static int qgroup_account_snapshot(struct btrfs_trans_handle *trans,
int ret; int ret;
/* /*
* Save some performance in the case that qgroups are not * Save some performance in the case that full qgroups are not enabled.
* enabled. If this check races with the ioctl, rescan will * If this check races with the ioctl, rescan will kick in anyway.
* kick in anyway.
*/ */
if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) if (!btrfs_qgroup_full_accounting(fs_info))
return 0; return 0;
/* /*
......
...@@ -334,6 +334,7 @@ struct btrfs_ioctl_fs_info_args { ...@@ -334,6 +334,7 @@ struct btrfs_ioctl_fs_info_args {
#define BTRFS_FEATURE_INCOMPAT_ZONED (1ULL << 12) #define BTRFS_FEATURE_INCOMPAT_ZONED (1ULL << 12)
#define BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2 (1ULL << 13) #define BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2 (1ULL << 13)
#define BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE (1ULL << 14) #define BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE (1ULL << 14)
#define BTRFS_FEATURE_INCOMPAT_SIMPLE_QUOTA (1ULL << 16)
struct btrfs_ioctl_feature_flags { struct btrfs_ioctl_feature_flags {
__u64 compat_flags; __u64 compat_flags;
...@@ -754,6 +755,7 @@ struct btrfs_ioctl_get_dev_stats { ...@@ -754,6 +755,7 @@ struct btrfs_ioctl_get_dev_stats {
#define BTRFS_QUOTA_CTL_ENABLE 1 #define BTRFS_QUOTA_CTL_ENABLE 1
#define BTRFS_QUOTA_CTL_DISABLE 2 #define BTRFS_QUOTA_CTL_DISABLE 2
#define BTRFS_QUOTA_CTL_RESCAN__NOTUSED 3 #define BTRFS_QUOTA_CTL_RESCAN__NOTUSED 3
#define BTRFS_QUOTA_CTL_ENABLE_SIMPLE_QUOTA 4
struct btrfs_ioctl_quota_ctl_args { struct btrfs_ioctl_quota_ctl_args {
__u64 cmd; __u64 cmd;
__u64 status; __u64 status;
......
...@@ -1233,9 +1233,17 @@ static inline __u16 btrfs_qgroup_level(__u64 qgroupid) ...@@ -1233,9 +1233,17 @@ static inline __u16 btrfs_qgroup_level(__u64 qgroupid)
*/ */
#define BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT (1ULL << 2) #define BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT (1ULL << 2)
/*
* Whether or not this filesystem is using simple quotas. Not exactly the
* incompat bit, because we support using simple quotas, disabling it, then
* going back to full qgroup quotas.
*/
#define BTRFS_QGROUP_STATUS_FLAG_SIMPLE_MODE (1ULL << 3)
#define BTRFS_QGROUP_STATUS_FLAGS_MASK (BTRFS_QGROUP_STATUS_FLAG_ON | \ #define BTRFS_QGROUP_STATUS_FLAGS_MASK (BTRFS_QGROUP_STATUS_FLAG_ON | \
BTRFS_QGROUP_STATUS_FLAG_RESCAN | \ BTRFS_QGROUP_STATUS_FLAG_RESCAN | \
BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT) BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT | \
BTRFS_QGROUP_STATUS_FLAG_SIMPLE_MODE)
#define BTRFS_QGROUP_STATUS_VERSION 1 #define BTRFS_QGROUP_STATUS_VERSION 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment