aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/qgroup.c
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2017-01-25 09:50:33 -0500
committerDavid Sterba <dsterba@suse.com>2017-02-14 09:50:59 -0500
commit003d7c59e8afc9b2c6b0d163e8e115406c4faecc (patch)
tree5e3f48d58117b4c784c403a4751b3c76cb836180 /fs/btrfs/qgroup.c
parent9a9239acb465df1f6aab379c77befd5cde98c9df (diff)
btrfs: allow unlink to exceed subvolume quota
Once a qgroup limit is exceeded, it's impossible to restore normal operation to the subvolume without modifying the limit or removing the subvolume. This is a surprising situation for many users used to the typical workflow with quotas on other file systems where it's possible to remove files until the used space is back under the limit. When we go to unlink a file and start the transaction, we'll hit the qgroup limit while trying to reserve space for the items we'll modify while removing the file. We discussed last month how best to handle this situation and agreed that there is no perfect solution. The best principle-of-least-surprise solution is to handle it similarly to how we already handle ENOSPC when unlinking, which is to allow the operation to succeed with the expectation that it will ultimately release space under most circumstances. This patch modifies the transaction start path to select whether to honor the qgroups limits. btrfs_start_transaction_fallback_global_rsv is the only caller that skips enforcement. The reservation and tracking still happens normally -- it just skips the enforcement step. Signed-off-by: Jeff Mahoney <jeffm@suse.com> Reviewed-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/qgroup.c')
-rw-r--r--fs/btrfs/qgroup.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 1c555f1e49ba..8496dbf3f38b 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -2324,7 +2324,20 @@ out:
2324 return ret; 2324 return ret;
2325} 2325}
2326 2326
2327static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes) 2327static bool qgroup_check_limits(const struct btrfs_qgroup *qg, u64 num_bytes)
2328{
2329 if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
2330 qg->reserved + (s64)qg->rfer + num_bytes > qg->max_rfer)
2331 return false;
2332
2333 if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) &&
2334 qg->reserved + (s64)qg->excl + num_bytes > qg->max_excl)
2335 return false;
2336
2337 return true;
2338}
2339
2340static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes, bool enforce)
2328{ 2341{
2329 struct btrfs_root *quota_root; 2342 struct btrfs_root *quota_root;
2330 struct btrfs_qgroup *qgroup; 2343 struct btrfs_qgroup *qgroup;
@@ -2365,16 +2378,7 @@ static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes)
2365 2378
2366 qg = unode_aux_to_qgroup(unode); 2379 qg = unode_aux_to_qgroup(unode);
2367 2380
2368 if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) && 2381 if (enforce && !qgroup_check_limits(qg, num_bytes)) {
2369 qg->reserved + (s64)qg->rfer + num_bytes >
2370 qg->max_rfer) {
2371 ret = -EDQUOT;
2372 goto out;
2373 }
2374
2375 if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) &&
2376 qg->reserved + (s64)qg->excl + num_bytes >
2377 qg->max_excl) {
2378 ret = -EDQUOT; 2382 ret = -EDQUOT;
2379 goto out; 2383 goto out;
2380 } 2384 }
@@ -2832,7 +2836,7 @@ int btrfs_qgroup_reserve_data(struct inode *inode, u64 start, u64 len)
2832 QGROUP_RESERVE); 2836 QGROUP_RESERVE);
2833 if (ret < 0) 2837 if (ret < 0)
2834 goto cleanup; 2838 goto cleanup;
2835 ret = qgroup_reserve(root, changeset.bytes_changed); 2839 ret = qgroup_reserve(root, changeset.bytes_changed, true);
2836 if (ret < 0) 2840 if (ret < 0)
2837 goto cleanup; 2841 goto cleanup;
2838 2842
@@ -2913,7 +2917,8 @@ int btrfs_qgroup_release_data(struct inode *inode, u64 start, u64 len)
2913 return __btrfs_qgroup_release_data(inode, start, len, 0); 2917 return __btrfs_qgroup_release_data(inode, start, len, 0);
2914} 2918}
2915 2919
2916int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes) 2920int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
2921 bool enforce)
2917{ 2922{
2918 struct btrfs_fs_info *fs_info = root->fs_info; 2923 struct btrfs_fs_info *fs_info = root->fs_info;
2919 int ret; 2924 int ret;
@@ -2923,7 +2928,7 @@ int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes)
2923 return 0; 2928 return 0;
2924 2929
2925 BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize)); 2930 BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize));
2926 ret = qgroup_reserve(root, num_bytes); 2931 ret = qgroup_reserve(root, num_bytes, enforce);
2927 if (ret < 0) 2932 if (ret < 0)
2928 return ret; 2933 return ret;
2929 atomic_add(num_bytes, &root->qgroup_meta_rsv); 2934 atomic_add(num_bytes, &root->qgroup_meta_rsv);