Skip to contentSkip to conversation

btrfs: qgroup: Only queue rescan work after QUOTA_ENABLED flag takes effect

RFC PATCH New Qu Wenruo 1 participant 1 message May 7, 2018 Btrfs file system

lore
Share & tools
lore

Qu Wenruo

author
#0 lore raw

RFC PATCH 1/1 btrfs: qgroup: Only queue rescan work after QUOTA_ENABLED flag takes effect

Currently we set QUOTA_ENABLED flags and then queue rescan work, and then commit current transaction.

The behavior could lead to missing quota accounts as quota rescan only scan committed root, thus it won't account modification in current transaction.
While for current transaction, we rely btrfs_qgroup_extent_record structure to trace dirty extents, which is only created after QUOTA_ENABLED flags set.

Above behavior a window where any modification before we set QUOTA_ENABLED flags will not be accounted in current transaction.

This patch will fix the behavior by delaying setting QUOTA_ENABLED flags (sounds pretty familiar right? Just like the old pending_quota_status), and QUOTA_ENABLED will only be enabled after current transaction committed, then we queue rescan work.

---
 fs/btrfs/ioctl.c       | 16 ++-------------
 fs/btrfs/qgroup.c      | 46 +++++++++++++++++++++++++++++++++++-------
 fs/btrfs/qgroup.h      |  6 ++----
 fs/btrfs/transaction.c |  3 +++
 fs/btrfs/transaction.h |  6 ++++++
 5 files changed, 52 insertions(+), 25 deletions(-)
fs/btrfs/ioctl.c +2 -14
index e1dedc78d1ad..2ed8fdf9d1d5 100644
@@ -4527,9 +4527,7 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
 	struct inode *inode = file_inode(file);
 	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
 	struct btrfs_ioctl_quota_ctl_args *sa;
-	struct btrfs_trans_handle *trans = NULL;
 	int ret;
-	int err;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
@@ -4545,28 +4543,18 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
 	}
 
 	down_write(&fs_info->subvol_sem);
-	trans = btrfs_start_transaction(fs_info->tree_root, 2);
-	if (IS_ERR(trans)) {
-		ret = PTR_ERR(trans);
-		goto out;
-	}
 
 	switch (sa->cmd) {
 	case BTRFS_QUOTA_CTL_ENABLE:
-		ret = btrfs_quota_enable(trans, fs_info);
+		ret = btrfs_quota_enable(fs_info);
 		break;
 	case BTRFS_QUOTA_CTL_DISABLE:
-		ret = btrfs_quota_disable(trans, fs_info);
+		ret = btrfs_quota_disable(fs_info);
 		break;
 	default:
 		ret = -EINVAL;
 		break;
 	}
-
-	err = btrfs_commit_transaction(trans);
-	if (err && !ret)
-		ret = err;
-out:
 	kfree(sa);
 	up_write(&fs_info->subvol_sem);
 drop_write:
fs/btrfs/qgroup.c +39 -7

110 lines not on this page · raw message

fs/btrfs/qgroup.h +2 -4
index d60dd06445ce..bec7c9b17a8e 100644
@@ -141,10 +141,8 @@ struct btrfs_qgroup {
 #define QGROUP_RELEASE		(1<<1)
 #define QGROUP_FREE		(1<<2)
 
-int btrfs_quota_enable(struct btrfs_trans_handle *trans,
-		       struct btrfs_fs_info *fs_info);
-int btrfs_quota_disable(struct btrfs_trans_handle *trans,
-			struct btrfs_fs_info *fs_info);
+int btrfs_quota_enable(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);
 void btrfs_qgroup_rescan_resume(struct btrfs_fs_info *fs_info);
 int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info,
fs/btrfs/transaction.c +3 -0
index dd3b0e0d822f..46c6e31d79bc 100644
@@ -241,6 +241,7 @@ static noinline int join_transaction(struct btrfs_fs_info *fs_info,
 	refcount_set(&cur_trans->use_count, 2);
 	atomic_set(&cur_trans->pending_ordered, 0);
 	cur_trans->flags = 0;
+	cur_trans->pending_fs_info_flags = 0;
 	cur_trans->start_time = get_seconds();
 
 	memset(&cur_trans->delayed_refs, 0, sizeof(cur_trans->delayed_refs));
@@ -2218,6 +2219,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
 	spin_lock(&fs_info->trans_lock);
 	cur_trans->state = TRANS_STATE_UNBLOCKED;
 	fs_info->running_transaction = NULL;
+	fs_info->flags |= cur_trans->pending_fs_info_flags;
+	cur_trans->pending_fs_info_flags = 0;
 	spin_unlock(&fs_info->trans_lock);
 	mutex_unlock(&fs_info->reloc_mutex);
 
fs/btrfs/transaction.h +6 -0
index d8c0826bc2c7..3654d78dbf7b 100644
@@ -43,6 +43,12 @@ struct btrfs_transaction {
 
 	unsigned long flags;
 
+	/*
+	 * flags which will be set to fs_info->flags after this transaction
+	 * committed
+	 */
+	unsigned long pending_fs_info_flags;
+
 	/* Be protected by fs_info->trans_lock when we want to change it. */
 	enum btrfs_trans_state state;
 	int aborted;
Signature · 1 line
2.17.0