From 8d203d87385fa56753832864ff462ad8b61b7c8f Mon Sep 17 00:00:00 2001
From: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
Date: Thu, 13 Nov 2014 12:56:06 -0500
Subject: [PATCH] btrfs: free quota reserved in delay_ref handler
Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
fs/btrfs/extent-tree.c | 2 +-
fs/btrfs/file.c | 2 +-
fs/btrfs/qgroup.c | 23 +++++++++++++++++++++--
fs/btrfs/qgroup.h | 1 +
4 files changed, 24 insertions(+), 4 deletions(-)
@@ -5300,7 +5300,7 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
trace_btrfs_space_reservation(root->fs_info, "delalloc",
btrfs_ino(inode), to_free, 0);
if (root->fs_info->quota_enabled) {
- btrfs_qgroup_free(root, num_bytes +
+ btrfs_qgroup_delayed_free(root, num_bytes +
dropped * root->leafsize);
}
@@ -2609,7 +2609,7 @@ static long btrfs_fallocate(struct file *file, int mode,
out:
mutex_unlock(&inode->i_mutex);
if (root->fs_info->quota_enabled)
- btrfs_qgroup_free(root, alloc_end - alloc_start);
+ btrfs_qgroup_delayed_free(root, alloc_end - alloc_start);
out_reserve_fail:
/* Let go of our reservation. */
btrfs_free_reserved_data_space(inode, alloc_end - alloc_start);
@@ -73,6 +73,7 @@ struct btrfs_qgroup {
* reservation tracking
*/
u64 reserved;
+ u64 delayed_release;
/*
* lists
@@ -1409,6 +1410,11 @@ static int qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
qgroup->excl += sign * oper->num_bytes;
qgroup->excl_cmpr += sign * oper->num_bytes;
+ if (qgroup->delayed_release) {
+ qgroup->reserved -= qgroup->delayed_release;
+ qgroup->delayed_release = 0;
+ }
+
qgroup_dirty(fs_info, qgroup);
/* Get all of the parent groups that contain this qgroup */
@@ -2440,7 +2446,7 @@ out:
return ret;
}
-void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes)
+static void qgroup_free(struct btrfs_root *root, u64 num_bytes, int delay)
{
struct btrfs_root *quota_root;
struct btrfs_qgroup *qgroup;
@@ -2478,7 +2484,10 @@ void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes)
qg = u64_to_ptr(unode->aux);
- qg->reserved -= num_bytes;
+ if (delay)
+ qg->delayed_release += num_bytes;
+ else
+ qg->reserved -= num_bytes;
list_for_each_entry(glist, &qg->groups, next_group) {
ret = ulist_add(fs_info->qgroup_ulist,
@@ -2493,6 +2502,16 @@ out:
spin_unlock(&fs_info->qgroup_lock);
}
+void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes)
+{
+ return qgroup_free(root, num_bytes, 0);
+}
+
+void btrfs_qgroup_delayed_free(struct btrfs_root *root, u64 num_bytes)
+{
+ return qgroup_free(root, num_bytes, 1);
+}
+
void assert_qgroups_uptodate(struct btrfs_trans_handle *trans)
{
if (list_empty(&trans->qgroup_ref_list) && !trans->delayed_ref_elem.seq)
@@ -97,6 +97,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
struct btrfs_qgroup_inherit *inherit);
int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes);
void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes);
+void btrfs_qgroup_delayed_free(struct btrfs_root *root, u64 num_bytes);
void assert_qgroups_uptodate(struct btrfs_trans_handle *trans);
--
1.8.3.1