hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/fs/btrfs/root-tree.c
....@@ -9,6 +9,8 @@
99 #include "transaction.h"
1010 #include "disk-io.h"
1111 #include "print-tree.h"
12
+#include "qgroup.h"
13
+#include "space-info.h"
1214
1315 /*
1416 * Read a root item from the tree. In case we detect a root item smaller then
....@@ -20,13 +22,12 @@
2022 static void btrfs_read_root_item(struct extent_buffer *eb, int slot,
2123 struct btrfs_root_item *item)
2224 {
23
- uuid_le uuid;
24
- int len;
25
+ u32 len;
2526 int need_reset = 0;
2627
2728 len = btrfs_item_size_nr(eb, slot);
2829 read_extent_buffer(eb, item, btrfs_item_ptr_offset(eb, slot),
29
- min_t(int, len, (int)sizeof(*item)));
30
+ min_t(u32, len, sizeof(*item)));
3031 if (len < sizeof(*item))
3132 need_reset = 1;
3233 if (!need_reset && btrfs_root_generation(item)
....@@ -42,8 +43,7 @@
4243 sizeof(*item) - offsetof(struct btrfs_root_item,
4344 generation_v2));
4445
45
- uuid_le_gen(&uuid);
46
- memcpy(item->uuid, uuid.b, BTRFS_UUID_SIZE);
46
+ generate_random_guid(item->uuid);
4747 }
4848 }
4949
....@@ -210,7 +210,6 @@
210210 struct extent_buffer *leaf;
211211 struct btrfs_path *path;
212212 struct btrfs_key key;
213
- struct btrfs_key root_key;
214213 struct btrfs_root *root;
215214 int err = 0;
216215 int ret;
....@@ -223,10 +222,9 @@
223222 key.type = BTRFS_ORPHAN_ITEM_KEY;
224223 key.offset = 0;
225224
226
- root_key.type = BTRFS_ROOT_ITEM_KEY;
227
- root_key.offset = (u64)-1;
228
-
229225 while (1) {
226
+ u64 root_objectid;
227
+
230228 ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
231229 if (ret < 0) {
232230 err = ret;
....@@ -250,26 +248,10 @@
250248 key.type != BTRFS_ORPHAN_ITEM_KEY)
251249 break;
252250
253
- root_key.objectid = key.offset;
251
+ root_objectid = key.offset;
254252 key.offset++;
255253
256
- /*
257
- * The root might have been inserted already, as before we look
258
- * for orphan roots, log replay might have happened, which
259
- * triggers a transaction commit and qgroup accounting, which
260
- * in turn reads and inserts fs roots while doing backref
261
- * walking.
262
- */
263
- root = btrfs_lookup_fs_root(fs_info, root_key.objectid);
264
- if (root) {
265
- WARN_ON(!test_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED,
266
- &root->state));
267
- if (btrfs_root_refs(&root->root_item) == 0)
268
- btrfs_add_dead_root(root);
269
- continue;
270
- }
271
-
272
- root = btrfs_read_fs_root(tree_root, &root_key);
254
+ root = btrfs_get_fs_root(fs_info, root_objectid, false);
273255 err = PTR_ERR_OR_ZERO(root);
274256 if (err && err != -ENOENT) {
275257 break;
....@@ -286,7 +268,7 @@
286268 break;
287269 }
288270 err = btrfs_del_orphan_item(trans, tree_root,
289
- root_key.objectid);
271
+ root_objectid);
290272 btrfs_end_transaction(trans);
291273 if (err) {
292274 btrfs_handle_fs_error(fs_info, err,
....@@ -296,23 +278,12 @@
296278 continue;
297279 }
298280
299
- err = btrfs_init_fs_root(root);
300
- if (err) {
301
- btrfs_free_fs_root(root);
302
- break;
303
- }
304
-
305
- set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state);
306
-
307
- err = btrfs_insert_fs_root(fs_info, root);
308
- if (err) {
309
- BUG_ON(err == -EEXIST);
310
- btrfs_free_fs_root(root);
311
- break;
312
- }
313
-
314
- if (btrfs_root_refs(&root->root_item) == 0)
281
+ WARN_ON(!test_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state));
282
+ if (btrfs_root_refs(&root->root_item) == 0) {
283
+ set_bit(BTRFS_ROOT_DEAD_TREE, &root->state);
315284 btrfs_add_dead_root(root);
285
+ }
286
+ btrfs_put_root(root);
316287 }
317288
318289 btrfs_free_path(path);
....@@ -365,8 +336,10 @@
365336 key.offset = ref_id;
366337 again:
367338 ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
368
- BUG_ON(ret < 0);
369
- if (ret == 0) {
339
+ if (ret < 0) {
340
+ err = ret;
341
+ goto out;
342
+ } else if (ret == 0) {
370343 leaf = path->nodes[0];
371344 ref = btrfs_item_ptr(leaf, path->slots[0],
372345 struct btrfs_root_ref);
....@@ -495,3 +468,66 @@
495468 btrfs_set_stack_timespec_nsec(&item->ctime, ct.tv_nsec);
496469 spin_unlock(&root->root_item_lock);
497470 }
471
+
472
+/*
473
+ * btrfs_subvolume_reserve_metadata() - reserve space for subvolume operation
474
+ * root: the root of the parent directory
475
+ * rsv: block reservation
476
+ * items: the number of items that we need do reservation
477
+ * use_global_rsv: allow fallback to the global block reservation
478
+ *
479
+ * This function is used to reserve the space for snapshot/subvolume
480
+ * creation and deletion. Those operations are different with the
481
+ * common file/directory operations, they change two fs/file trees
482
+ * and root tree, the number of items that the qgroup reserves is
483
+ * different with the free space reservation. So we can not use
484
+ * the space reservation mechanism in start_transaction().
485
+ */
486
+int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
487
+ struct btrfs_block_rsv *rsv, int items,
488
+ bool use_global_rsv)
489
+{
490
+ u64 qgroup_num_bytes = 0;
491
+ u64 num_bytes;
492
+ int ret;
493
+ struct btrfs_fs_info *fs_info = root->fs_info;
494
+ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
495
+
496
+ if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) {
497
+ /* One for parent inode, two for dir entries */
498
+ qgroup_num_bytes = 3 * fs_info->nodesize;
499
+ ret = btrfs_qgroup_reserve_meta_prealloc(root,
500
+ qgroup_num_bytes, true);
501
+ if (ret)
502
+ return ret;
503
+ }
504
+
505
+ num_bytes = btrfs_calc_insert_metadata_size(fs_info, items);
506
+ rsv->space_info = btrfs_find_space_info(fs_info,
507
+ BTRFS_BLOCK_GROUP_METADATA);
508
+ ret = btrfs_block_rsv_add(root, rsv, num_bytes,
509
+ BTRFS_RESERVE_FLUSH_ALL);
510
+
511
+ if (ret == -ENOSPC && use_global_rsv)
512
+ ret = btrfs_block_rsv_migrate(global_rsv, rsv, num_bytes, true);
513
+
514
+ if (ret && qgroup_num_bytes)
515
+ btrfs_qgroup_free_meta_prealloc(root, qgroup_num_bytes);
516
+
517
+ if (!ret) {
518
+ spin_lock(&rsv->lock);
519
+ rsv->qgroup_rsv_reserved += qgroup_num_bytes;
520
+ spin_unlock(&rsv->lock);
521
+ }
522
+ return ret;
523
+}
524
+
525
+void btrfs_subvolume_release_metadata(struct btrfs_root *root,
526
+ struct btrfs_block_rsv *rsv)
527
+{
528
+ struct btrfs_fs_info *fs_info = root->fs_info;
529
+ u64 qgroup_to_release;
530
+
531
+ btrfs_block_rsv_release(fs_info, rsv, (u64)-1, &qgroup_to_release);
532
+ btrfs_qgroup_convert_reserved_meta(root, qgroup_to_release);
533
+}