diff options
author | Dongsheng Yang <yangds.fnst@cn.fujitsu.com> | 2015-02-06 10:26:52 -0500 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-04-13 07:52:50 -0700 |
commit | e2d1f92399afb6ec518b68867ed10db2585b283a (patch) | |
tree | a6964e3b445268bf5c67c4b482de6c98b03571c8 /fs/btrfs/qgroup.c | |
parent | 237c0e9f1fbfdca7287f3539f1fa73e5063156b5 (diff) | |
download | linux-e2d1f92399afb6ec518b68867ed10db2585b283a.tar.bz2 |
btrfs: qgroup: do a reservation in a higher level.
There are two problems in qgroup:
a). The PAGE_CACHE is 4K, even when we are writing a data of 1K,
qgroup will reserve a 4K size. It will cause the last 3K in a qgroup
is not available to user.
b). When user is writing a inline data, qgroup will not reserve it,
it means this is a window we can exceed the limit of a qgroup.
The main idea of this patch is reserving the data size of write_bytes
rather than the reserve_bytes. It means qgroup will not care about
the data size btrfs will reserve for user, but only care about the
data size user is going to write. Then reserve it when user want to
write and release it in transaction committed.
In this way, qgroup can be released from the complex procedure in
btrfs and only do the reserve when user want to write and account
when the data is written in commit_transaction().
Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/qgroup.c')
-rw-r--r-- | fs/btrfs/qgroup.c | 70 |
1 files changed, 4 insertions, 66 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index cd291733dc3e..17881ad8ed96 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -72,7 +72,6 @@ struct btrfs_qgroup { /* * reservation tracking */ - u64 may_use; u64 reserved; /* @@ -2383,67 +2382,6 @@ out: return ret; } -int btrfs_qgroup_update_reserved_bytes(struct btrfs_fs_info *fs_info, - u64 ref_root, - u64 num_bytes, - int sign) -{ - struct btrfs_root *quota_root; - struct btrfs_qgroup *qgroup; - int ret = 0; - struct ulist_node *unode; - struct ulist_iterator uiter; - - if (!is_fstree(ref_root) || !fs_info->quota_enabled) - return 0; - - if (num_bytes == 0) - return 0; - - spin_lock(&fs_info->qgroup_lock); - quota_root = fs_info->quota_root; - if (!quota_root) - goto out; - - qgroup = find_qgroup_rb(fs_info, ref_root); - if (!qgroup) - goto out; - - ulist_reinit(fs_info->qgroup_ulist); - ret = ulist_add(fs_info->qgroup_ulist, qgroup->qgroupid, - (uintptr_t)qgroup, GFP_ATOMIC); - if (ret < 0) - goto out; - - ULIST_ITER_INIT(&uiter); - while ((unode = ulist_next(fs_info->qgroup_ulist, &uiter))) { - struct btrfs_qgroup *qg; - struct btrfs_qgroup_list *glist; - - qg = u64_to_ptr(unode->aux); - - qg->reserved += sign * num_bytes; - - list_for_each_entry(glist, &qg->groups, next_group) { - ret = ulist_add(fs_info->qgroup_ulist, - glist->group->qgroupid, - (uintptr_t)glist->group, GFP_ATOMIC); - if (ret < 0) - goto out; - } - } - -out: - spin_unlock(&fs_info->qgroup_lock); - return ret; -} - -/* - * reserve some space for a qgroup and all its parents. The reservation takes - * place with start_transaction or dealloc_reserve, similar to ENOSPC - * accounting. If not enough space is available, EDQUOT is returned. - * We assume that the requested space is new for all qgroups. - */ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes) { struct btrfs_root *quota_root; @@ -2486,14 +2424,14 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes) qg = u64_to_ptr(unode->aux); if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) && - qg->reserved + qg->may_use + (s64)qg->rfer + num_bytes > + qg->reserved + (s64)qg->rfer + num_bytes > qg->max_rfer) { ret = -EDQUOT; goto out; } if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) && - qg->reserved + qg->may_use + (s64)qg->excl + num_bytes > + qg->reserved + (s64)qg->excl + num_bytes > qg->max_excl) { ret = -EDQUOT; goto out; @@ -2517,7 +2455,7 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes) qg = u64_to_ptr(unode->aux); - qg->may_use += num_bytes; + qg->reserved += num_bytes; } out: @@ -2563,7 +2501,7 @@ void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes) qg = u64_to_ptr(unode->aux); - qg->may_use -= num_bytes; + qg->reserved -= num_bytes; list_for_each_entry(glist, &qg->groups, next_group) { ret = ulist_add(fs_info->qgroup_ulist, |