hc
2024-05-11 297b60346df8beafee954a0fd7c2d64f33f3b9bc
kernel/fs/btrfs/qgroup.c
....@@ -1202,11 +1202,22 @@
12021202 int ret = 0;
12031203
12041204 /*
1205
- * We need to have subvol_sem write locked, to prevent races between
1206
- * concurrent tasks trying to disable quotas, because we will unlock
1207
- * and relock qgroup_ioctl_lock across BTRFS_FS_QUOTA_ENABLED changes.
1205
+ * We need to have subvol_sem write locked to prevent races with
1206
+ * snapshot creation.
12081207 */
12091208 lockdep_assert_held_write(&fs_info->subvol_sem);
1209
+
1210
+ /*
1211
+ * Lock the cleaner mutex to prevent races with concurrent relocation,
1212
+ * because relocation may be building backrefs for blocks of the quota
1213
+ * root while we are deleting the root. This is like dropping fs roots
1214
+ * of deleted snapshots/subvolumes, we need the same protection.
1215
+ *
1216
+ * This also prevents races between concurrent tasks trying to disable
1217
+ * quotas, because we will unlock and relock qgroup_ioctl_lock across
1218
+ * BTRFS_FS_QUOTA_ENABLED changes.
1219
+ */
1220
+ mutex_lock(&fs_info->cleaner_mutex);
12101221
12111222 mutex_lock(&fs_info->qgroup_ioctl_lock);
12121223 if (!fs_info->quota_root)
....@@ -1270,7 +1281,9 @@
12701281 goto out;
12711282 }
12721283
1284
+ spin_lock(&fs_info->trans_lock);
12731285 list_del(&quota_root->dirty_list);
1286
+ spin_unlock(&fs_info->trans_lock);
12741287
12751288 btrfs_tree_lock(quota_root->node);
12761289 btrfs_clean_tree_block(quota_root->node);
....@@ -1285,6 +1298,7 @@
12851298 btrfs_end_transaction(trans);
12861299 else if (trans)
12871300 ret = btrfs_end_transaction(trans);
1301
+ mutex_unlock(&fs_info->cleaner_mutex);
12881302
12891303 return ret;
12901304 }
....@@ -2762,12 +2776,21 @@
27622776 }
27632777
27642778 /*
2765
- * called from commit_transaction. Writes all changed qgroups to disk.
2779
+ * Writes all changed qgroups to disk.
2780
+ * Called by the transaction commit path and the qgroup assign ioctl.
27662781 */
27672782 int btrfs_run_qgroups(struct btrfs_trans_handle *trans)
27682783 {
27692784 struct btrfs_fs_info *fs_info = trans->fs_info;
27702785 int ret = 0;
2786
+
2787
+ /*
2788
+ * In case we are called from the qgroup assign ioctl, assert that we
2789
+ * are holding the qgroup_ioctl_lock, otherwise we can race with a quota
2790
+ * disable operation (ioctl) and access a freed quota root.
2791
+ */
2792
+ if (trans->transaction->state != TRANS_STATE_COMMIT_DOING)
2793
+ lockdep_assert_held(&fs_info->qgroup_ioctl_lock);
27712794
27722795 if (!fs_info->quota_root)
27732796 return ret;
....@@ -3296,6 +3319,7 @@
32963319 int err = -ENOMEM;
32973320 int ret = 0;
32983321 bool stopped = false;
3322
+ bool did_leaf_rescans = false;
32993323
33003324 path = btrfs_alloc_path();
33013325 if (!path)
....@@ -3316,6 +3340,7 @@
33163340 }
33173341
33183342 err = qgroup_rescan_leaf(trans, path);
3343
+ did_leaf_rescans = true;
33193344
33203345 if (err > 0)
33213346 btrfs_commit_transaction(trans);
....@@ -3336,16 +3361,23 @@
33363361 mutex_unlock(&fs_info->qgroup_rescan_lock);
33373362
33383363 /*
3339
- * only update status, since the previous part has already updated the
3340
- * qgroup info.
3364
+ * Only update status, since the previous part has already updated the
3365
+ * qgroup info, and only if we did any actual work. This also prevents
3366
+ * race with a concurrent quota disable, which has already set
3367
+ * fs_info->quota_root to NULL and cleared BTRFS_FS_QUOTA_ENABLED at
3368
+ * btrfs_quota_disable().
33413369 */
3342
- trans = btrfs_start_transaction(fs_info->quota_root, 1);
3343
- if (IS_ERR(trans)) {
3344
- err = PTR_ERR(trans);
3370
+ if (did_leaf_rescans) {
3371
+ trans = btrfs_start_transaction(fs_info->quota_root, 1);
3372
+ if (IS_ERR(trans)) {
3373
+ err = PTR_ERR(trans);
3374
+ trans = NULL;
3375
+ btrfs_err(fs_info,
3376
+ "fail to start transaction for status update: %d",
3377
+ err);
3378
+ }
3379
+ } else {
33453380 trans = NULL;
3346
- btrfs_err(fs_info,
3347
- "fail to start transaction for status update: %d",
3348
- err);
33493381 }
33503382
33513383 mutex_lock(&fs_info->qgroup_rescan_lock);
....@@ -4356,4 +4388,5 @@
43564388 ulist_free(entry->old_roots);
43574389 kfree(entry);
43584390 }
4391
+ *root = RB_ROOT;
43594392 }