aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2018-10-09 02:36:45 -0400
committerDavid Sterba <dsterba@suse.com>2018-10-15 11:23:40 -0400
commit3628b4ca64f24a4ec55055597d0cb1c814729f8b (patch)
treee4848dbc56270ade0438975be2df36cf4c979476
parent0f375eed92b5a407657532637ed9652611a682f5 (diff)
btrfs: qgroup: Avoid calling qgroup functions if qgroup is not enabled
Some qgroup trace events like btrfs_qgroup_release_data() and btrfs_qgroup_free_delayed_ref() can still be triggered even if qgroup is not enabled. This is caused by the lack of qgroup status check before calling some qgroup functions. Thankfully the functions can handle quota disabled case well and just do nothing for qgroup disabled case. This patch will do earlier check before triggering related trace events. And for enabled <-> disabled race case: 1) For enabled->disabled case Disable will wipe out all qgroups data including reservation and excl/rfer. Even if we leak some reservation or numbers, it will still be cleared, so nothing will go wrong. 2) For disabled -> enabled case Current btrfs_qgroup_release_data() will use extent_io tree to ensure we won't underflow reservation. And for delayed_ref we use head->qgroup_reserved to record the reserved space, so in that case head->qgroup_reserved should be 0 and we won't underflow. CC: stable@vger.kernel.org # 4.14+ Reported-by: Chris Murphy <lists@colorremedies.com> Link: https://lore.kernel.org/linux-btrfs/CAJCQCtQau7DtuUUeycCkZ36qjbKuxNzsgqJ7+sJ6W0dK_NLE3w@mail.gmail.com/ Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/qgroup.c4
-rw-r--r--fs/btrfs/qgroup.h2
2 files changed, 6 insertions, 0 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index ac9690f36a94..27f517315388 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -3521,6 +3521,10 @@ static int __btrfs_qgroup_release_data(struct inode *inode,
3521 int trace_op = QGROUP_RELEASE; 3521 int trace_op = QGROUP_RELEASE;
3522 int ret; 3522 int ret;
3523 3523
3524 if (!test_bit(BTRFS_FS_QUOTA_ENABLED,
3525 &BTRFS_I(inode)->root->fs_info->flags))
3526 return 0;
3527
3524 /* In release case, we shouldn't have @reserved */ 3528 /* In release case, we shouldn't have @reserved */
3525 WARN_ON(!free && reserved); 3529 WARN_ON(!free && reserved);
3526 if (free && reserved) 3530 if (free && reserved)
diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h
index 80ebeb3ab5ba..d8f78f5ab854 100644
--- a/fs/btrfs/qgroup.h
+++ b/fs/btrfs/qgroup.h
@@ -255,6 +255,8 @@ void btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info,
255static inline void btrfs_qgroup_free_delayed_ref(struct btrfs_fs_info *fs_info, 255static inline void btrfs_qgroup_free_delayed_ref(struct btrfs_fs_info *fs_info,
256 u64 ref_root, u64 num_bytes) 256 u64 ref_root, u64 num_bytes)
257{ 257{
258 if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
259 return;
258 trace_btrfs_qgroup_free_delayed_ref(fs_info, ref_root, num_bytes); 260 trace_btrfs_qgroup_free_delayed_ref(fs_info, ref_root, num_bytes);
259 btrfs_qgroup_free_refroot(fs_info, ref_root, num_bytes, 261 btrfs_qgroup_free_refroot(fs_info, ref_root, num_bytes,
260 BTRFS_QGROUP_RSV_DATA); 262 BTRFS_QGROUP_RSV_DATA);