LCOV - code coverage report
Current view: top level - fs/btrfs - root-tree.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 0 292 0.0 %
Date: 2023-07-31 20:08:17 Functions: 0 13 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 2007 Oracle.  All rights reserved.
       4             :  */
       5             : 
       6             : #include <linux/err.h>
       7             : #include <linux/uuid.h>
       8             : #include "ctree.h"
       9             : #include "fs.h"
      10             : #include "messages.h"
      11             : #include "transaction.h"
      12             : #include "disk-io.h"
      13             : #include "print-tree.h"
      14             : #include "qgroup.h"
      15             : #include "space-info.h"
      16             : #include "accessors.h"
      17             : #include "root-tree.h"
      18             : #include "orphan.h"
      19             : 
      20             : /*
      21             :  * Read a root item from the tree. In case we detect a root item smaller then
      22             :  * sizeof(root_item), we know it's an old version of the root structure and
      23             :  * initialize all new fields to zero. The same happens if we detect mismatching
      24             :  * generation numbers as then we know the root was once mounted with an older
      25             :  * kernel that was not aware of the root item structure change.
      26             :  */
      27           0 : static void btrfs_read_root_item(struct extent_buffer *eb, int slot,
      28             :                                 struct btrfs_root_item *item)
      29             : {
      30           0 :         u32 len;
      31           0 :         int need_reset = 0;
      32             : 
      33           0 :         len = btrfs_item_size(eb, slot);
      34           0 :         read_extent_buffer(eb, item, btrfs_item_ptr_offset(eb, slot),
      35           0 :                            min_t(u32, len, sizeof(*item)));
      36           0 :         if (len < sizeof(*item))
      37             :                 need_reset = 1;
      38           0 :         if (!need_reset && btrfs_root_generation(item)
      39             :                 != btrfs_root_generation_v2(item)) {
      40           0 :                 if (btrfs_root_generation_v2(item) != 0) {
      41           0 :                         btrfs_warn(eb->fs_info,
      42             :                                         "mismatching generation and generation_v2 found in root item. This root was probably mounted with an older kernel. Resetting all new fields.");
      43             :                 }
      44             :                 need_reset = 1;
      45             :         }
      46           0 :         if (need_reset) {
      47             :                 /* Clear all members from generation_v2 onwards. */
      48           0 :                 memset_startat(item, 0, generation_v2);
      49           0 :                 generate_random_guid(item->uuid);
      50             :         }
      51           0 : }
      52             : 
      53             : /*
      54             :  * btrfs_find_root - lookup the root by the key.
      55             :  * root: the root of the root tree
      56             :  * search_key: the key to search
      57             :  * path: the path we search
      58             :  * root_item: the root item of the tree we look for
      59             :  * root_key: the root key of the tree we look for
      60             :  *
      61             :  * If ->offset of 'search_key' is -1ULL, it means we are not sure the offset
      62             :  * of the search key, just lookup the root with the highest offset for a
      63             :  * given objectid.
      64             :  *
      65             :  * If we find something return 0, otherwise > 0, < 0 on error.
      66             :  */
      67           0 : int btrfs_find_root(struct btrfs_root *root, const struct btrfs_key *search_key,
      68             :                     struct btrfs_path *path, struct btrfs_root_item *root_item,
      69             :                     struct btrfs_key *root_key)
      70             : {
      71           0 :         struct btrfs_key found_key;
      72           0 :         struct extent_buffer *l;
      73           0 :         int ret;
      74           0 :         int slot;
      75             : 
      76           0 :         ret = btrfs_search_slot(NULL, root, search_key, path, 0, 0);
      77           0 :         if (ret < 0)
      78             :                 return ret;
      79             : 
      80           0 :         if (search_key->offset != -1ULL) {   /* the search key is exact */
      81           0 :                 if (ret > 0)
      82           0 :                         goto out;
      83             :         } else {
      84           0 :                 BUG_ON(ret == 0);               /* Logical error */
      85           0 :                 if (path->slots[0] == 0)
      86           0 :                         goto out;
      87           0 :                 path->slots[0]--;
      88           0 :                 ret = 0;
      89             :         }
      90             : 
      91           0 :         l = path->nodes[0];
      92           0 :         slot = path->slots[0];
      93             : 
      94           0 :         btrfs_item_key_to_cpu(l, &found_key, slot);
      95           0 :         if (found_key.objectid != search_key->objectid ||
      96           0 :             found_key.type != BTRFS_ROOT_ITEM_KEY) {
      97           0 :                 ret = 1;
      98           0 :                 goto out;
      99             :         }
     100             : 
     101           0 :         if (root_item)
     102           0 :                 btrfs_read_root_item(l, slot, root_item);
     103           0 :         if (root_key)
     104           0 :                 memcpy(root_key, &found_key, sizeof(found_key));
     105           0 : out:
     106           0 :         btrfs_release_path(path);
     107           0 :         return ret;
     108             : }
     109             : 
     110           0 : void btrfs_set_root_node(struct btrfs_root_item *item,
     111             :                          struct extent_buffer *node)
     112             : {
     113           0 :         btrfs_set_root_bytenr(item, node->start);
     114           0 :         btrfs_set_root_level(item, btrfs_header_level(node));
     115           0 :         btrfs_set_root_generation(item, btrfs_header_generation(node));
     116           0 : }
     117             : 
     118             : /*
     119             :  * copy the data in 'item' into the btree
     120             :  */
     121           0 : int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
     122             :                       *root, struct btrfs_key *key, struct btrfs_root_item
     123             :                       *item)
     124             : {
     125           0 :         struct btrfs_fs_info *fs_info = root->fs_info;
     126           0 :         struct btrfs_path *path;
     127           0 :         struct extent_buffer *l;
     128           0 :         int ret;
     129           0 :         int slot;
     130           0 :         unsigned long ptr;
     131           0 :         u32 old_len;
     132             : 
     133           0 :         path = btrfs_alloc_path();
     134           0 :         if (!path)
     135             :                 return -ENOMEM;
     136             : 
     137           0 :         ret = btrfs_search_slot(trans, root, key, path, 0, 1);
     138           0 :         if (ret < 0)
     139           0 :                 goto out;
     140             : 
     141           0 :         if (ret > 0) {
     142           0 :                 btrfs_crit(fs_info,
     143             :                         "unable to find root key (%llu %u %llu) in tree %llu",
     144             :                         key->objectid, key->type, key->offset,
     145             :                         root->root_key.objectid);
     146           0 :                 ret = -EUCLEAN;
     147           0 :                 btrfs_abort_transaction(trans, ret);
     148           0 :                 goto out;
     149             :         }
     150             : 
     151           0 :         l = path->nodes[0];
     152           0 :         slot = path->slots[0];
     153           0 :         ptr = btrfs_item_ptr_offset(l, slot);
     154           0 :         old_len = btrfs_item_size(l, slot);
     155             : 
     156             :         /*
     157             :          * If this is the first time we update the root item which originated
     158             :          * from an older kernel, we need to enlarge the item size to make room
     159             :          * for the added fields.
     160             :          */
     161           0 :         if (old_len < sizeof(*item)) {
     162           0 :                 btrfs_release_path(path);
     163           0 :                 ret = btrfs_search_slot(trans, root, key, path,
     164             :                                 -1, 1);
     165           0 :                 if (ret < 0) {
     166           0 :                         btrfs_abort_transaction(trans, ret);
     167           0 :                         goto out;
     168             :                 }
     169             : 
     170           0 :                 ret = btrfs_del_item(trans, root, path);
     171           0 :                 if (ret < 0) {
     172           0 :                         btrfs_abort_transaction(trans, ret);
     173           0 :                         goto out;
     174             :                 }
     175           0 :                 btrfs_release_path(path);
     176           0 :                 ret = btrfs_insert_empty_item(trans, root, path,
     177             :                                 key, sizeof(*item));
     178           0 :                 if (ret < 0) {
     179           0 :                         btrfs_abort_transaction(trans, ret);
     180           0 :                         goto out;
     181             :                 }
     182           0 :                 l = path->nodes[0];
     183           0 :                 slot = path->slots[0];
     184           0 :                 ptr = btrfs_item_ptr_offset(l, slot);
     185             :         }
     186             : 
     187             :         /*
     188             :          * Update generation_v2 so at the next mount we know the new root
     189             :          * fields are valid.
     190             :          */
     191           0 :         btrfs_set_root_generation_v2(item, btrfs_root_generation(item));
     192             : 
     193           0 :         write_extent_buffer(l, item, ptr, sizeof(*item));
     194           0 :         btrfs_mark_buffer_dirty(path->nodes[0]);
     195           0 : out:
     196           0 :         btrfs_free_path(path);
     197           0 :         return ret;
     198             : }
     199             : 
     200           0 : int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
     201             :                       const struct btrfs_key *key, struct btrfs_root_item *item)
     202             : {
     203             :         /*
     204             :          * Make sure generation v1 and v2 match. See update_root for details.
     205             :          */
     206           0 :         btrfs_set_root_generation_v2(item, btrfs_root_generation(item));
     207           0 :         return btrfs_insert_item(trans, root, key, item, sizeof(*item));
     208             : }
     209             : 
     210           0 : int btrfs_find_orphan_roots(struct btrfs_fs_info *fs_info)
     211             : {
     212           0 :         struct btrfs_root *tree_root = fs_info->tree_root;
     213           0 :         struct extent_buffer *leaf;
     214           0 :         struct btrfs_path *path;
     215           0 :         struct btrfs_key key;
     216           0 :         struct btrfs_root *root;
     217           0 :         int err = 0;
     218           0 :         int ret;
     219             : 
     220           0 :         path = btrfs_alloc_path();
     221           0 :         if (!path)
     222             :                 return -ENOMEM;
     223             : 
     224           0 :         key.objectid = BTRFS_ORPHAN_OBJECTID;
     225           0 :         key.type = BTRFS_ORPHAN_ITEM_KEY;
     226           0 :         key.offset = 0;
     227             : 
     228           0 :         while (1) {
     229           0 :                 u64 root_objectid;
     230             : 
     231           0 :                 ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
     232           0 :                 if (ret < 0) {
     233             :                         err = ret;
     234             :                         break;
     235             :                 }
     236             : 
     237           0 :                 leaf = path->nodes[0];
     238           0 :                 if (path->slots[0] >= btrfs_header_nritems(leaf)) {
     239           0 :                         ret = btrfs_next_leaf(tree_root, path);
     240           0 :                         if (ret < 0)
     241             :                                 err = ret;
     242           0 :                         if (ret != 0)
     243             :                                 break;
     244           0 :                         leaf = path->nodes[0];
     245             :                 }
     246             : 
     247           0 :                 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
     248           0 :                 btrfs_release_path(path);
     249             : 
     250           0 :                 if (key.objectid != BTRFS_ORPHAN_OBJECTID ||
     251           0 :                     key.type != BTRFS_ORPHAN_ITEM_KEY)
     252             :                         break;
     253             : 
     254           0 :                 root_objectid = key.offset;
     255           0 :                 key.offset++;
     256             : 
     257           0 :                 root = btrfs_get_fs_root(fs_info, root_objectid, false);
     258           0 :                 err = PTR_ERR_OR_ZERO(root);
     259           0 :                 if (err && err != -ENOENT) {
     260             :                         break;
     261           0 :                 } else if (err == -ENOENT) {
     262           0 :                         struct btrfs_trans_handle *trans;
     263             : 
     264           0 :                         btrfs_release_path(path);
     265             : 
     266           0 :                         trans = btrfs_join_transaction(tree_root);
     267           0 :                         if (IS_ERR(trans)) {
     268           0 :                                 err = PTR_ERR(trans);
     269           0 :                                 btrfs_handle_fs_error(fs_info, err,
     270             :                                             "Failed to start trans to delete orphan item");
     271           0 :                                 break;
     272             :                         }
     273           0 :                         err = btrfs_del_orphan_item(trans, tree_root,
     274             :                                                     root_objectid);
     275           0 :                         btrfs_end_transaction(trans);
     276           0 :                         if (err) {
     277           0 :                                 btrfs_handle_fs_error(fs_info, err,
     278             :                                             "Failed to delete root orphan item");
     279           0 :                                 break;
     280             :                         }
     281           0 :                         continue;
     282             :                 }
     283             : 
     284           0 :                 WARN_ON(!test_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state));
     285           0 :                 if (btrfs_root_refs(&root->root_item) == 0) {
     286           0 :                         struct btrfs_key drop_key;
     287             : 
     288           0 :                         btrfs_disk_key_to_cpu(&drop_key, &root->root_item.drop_progress);
     289             :                         /*
     290             :                          * If we have a non-zero drop_progress then we know we
     291             :                          * made it partly through deleting this snapshot, and
     292             :                          * thus we need to make sure we block any balance from
     293             :                          * happening until this snapshot is completely dropped.
     294             :                          */
     295           0 :                         if (drop_key.objectid != 0 || drop_key.type != 0 ||
     296           0 :                             drop_key.offset != 0) {
     297           0 :                                 set_bit(BTRFS_FS_UNFINISHED_DROPS, &fs_info->flags);
     298           0 :                                 set_bit(BTRFS_ROOT_UNFINISHED_DROP, &root->state);
     299             :                         }
     300             : 
     301           0 :                         set_bit(BTRFS_ROOT_DEAD_TREE, &root->state);
     302           0 :                         btrfs_add_dead_root(root);
     303             :                 }
     304           0 :                 btrfs_put_root(root);
     305             :         }
     306             : 
     307           0 :         btrfs_free_path(path);
     308           0 :         return err;
     309             : }
     310             : 
     311             : /* drop the root item for 'key' from the tree root */
     312           0 : int btrfs_del_root(struct btrfs_trans_handle *trans,
     313             :                    const struct btrfs_key *key)
     314             : {
     315           0 :         struct btrfs_root *root = trans->fs_info->tree_root;
     316           0 :         struct btrfs_path *path;
     317           0 :         int ret;
     318             : 
     319           0 :         path = btrfs_alloc_path();
     320           0 :         if (!path)
     321             :                 return -ENOMEM;
     322           0 :         ret = btrfs_search_slot(trans, root, key, path, -1, 1);
     323           0 :         if (ret < 0)
     324           0 :                 goto out;
     325             : 
     326           0 :         BUG_ON(ret != 0);
     327             : 
     328           0 :         ret = btrfs_del_item(trans, root, path);
     329           0 : out:
     330           0 :         btrfs_free_path(path);
     331           0 :         return ret;
     332             : }
     333             : 
     334           0 : int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
     335             :                        u64 ref_id, u64 dirid, u64 *sequence,
     336             :                        const struct fscrypt_str *name)
     337             : {
     338           0 :         struct btrfs_root *tree_root = trans->fs_info->tree_root;
     339           0 :         struct btrfs_path *path;
     340           0 :         struct btrfs_root_ref *ref;
     341           0 :         struct extent_buffer *leaf;
     342           0 :         struct btrfs_key key;
     343           0 :         unsigned long ptr;
     344           0 :         int ret;
     345             : 
     346           0 :         path = btrfs_alloc_path();
     347           0 :         if (!path)
     348             :                 return -ENOMEM;
     349             : 
     350           0 :         key.objectid = root_id;
     351           0 :         key.type = BTRFS_ROOT_BACKREF_KEY;
     352           0 :         key.offset = ref_id;
     353           0 : again:
     354           0 :         ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
     355           0 :         if (ret < 0) {
     356           0 :                 goto out;
     357           0 :         } else if (ret == 0) {
     358           0 :                 leaf = path->nodes[0];
     359           0 :                 ref = btrfs_item_ptr(leaf, path->slots[0],
     360             :                                      struct btrfs_root_ref);
     361           0 :                 ptr = (unsigned long)(ref + 1);
     362           0 :                 if ((btrfs_root_ref_dirid(leaf, ref) != dirid) ||
     363           0 :                     (btrfs_root_ref_name_len(leaf, ref) != name->len) ||
     364           0 :                     memcmp_extent_buffer(leaf, name->name, ptr, name->len)) {
     365           0 :                         ret = -ENOENT;
     366           0 :                         goto out;
     367             :                 }
     368           0 :                 *sequence = btrfs_root_ref_sequence(leaf, ref);
     369             : 
     370           0 :                 ret = btrfs_del_item(trans, tree_root, path);
     371           0 :                 if (ret)
     372           0 :                         goto out;
     373             :         } else {
     374           0 :                 ret = -ENOENT;
     375           0 :                 goto out;
     376             :         }
     377             : 
     378           0 :         if (key.type == BTRFS_ROOT_BACKREF_KEY) {
     379           0 :                 btrfs_release_path(path);
     380           0 :                 key.objectid = ref_id;
     381           0 :                 key.type = BTRFS_ROOT_REF_KEY;
     382           0 :                 key.offset = root_id;
     383           0 :                 goto again;
     384             :         }
     385             : 
     386           0 : out:
     387           0 :         btrfs_free_path(path);
     388           0 :         return ret;
     389             : }
     390             : 
     391             : /*
     392             :  * add a btrfs_root_ref item.  type is either BTRFS_ROOT_REF_KEY
     393             :  * or BTRFS_ROOT_BACKREF_KEY.
     394             :  *
     395             :  * The dirid, sequence, name and name_len refer to the directory entry
     396             :  * that is referencing the root.
     397             :  *
     398             :  * For a forward ref, the root_id is the id of the tree referencing
     399             :  * the root and ref_id is the id of the subvol  or snapshot.
     400             :  *
     401             :  * For a back ref the root_id is the id of the subvol or snapshot and
     402             :  * ref_id is the id of the tree referencing it.
     403             :  *
     404             :  * Will return 0, -ENOMEM, or anything from the CoW path
     405             :  */
     406           0 : int btrfs_add_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
     407             :                        u64 ref_id, u64 dirid, u64 sequence,
     408             :                        const struct fscrypt_str *name)
     409             : {
     410           0 :         struct btrfs_root *tree_root = trans->fs_info->tree_root;
     411           0 :         struct btrfs_key key;
     412           0 :         int ret;
     413           0 :         struct btrfs_path *path;
     414           0 :         struct btrfs_root_ref *ref;
     415           0 :         struct extent_buffer *leaf;
     416           0 :         unsigned long ptr;
     417             : 
     418           0 :         path = btrfs_alloc_path();
     419           0 :         if (!path)
     420             :                 return -ENOMEM;
     421             : 
     422           0 :         key.objectid = root_id;
     423           0 :         key.type = BTRFS_ROOT_BACKREF_KEY;
     424           0 :         key.offset = ref_id;
     425           0 : again:
     426           0 :         ret = btrfs_insert_empty_item(trans, tree_root, path, &key,
     427           0 :                                       sizeof(*ref) + name->len);
     428           0 :         if (ret) {
     429           0 :                 btrfs_abort_transaction(trans, ret);
     430           0 :                 btrfs_free_path(path);
     431           0 :                 return ret;
     432             :         }
     433             : 
     434           0 :         leaf = path->nodes[0];
     435           0 :         ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref);
     436           0 :         btrfs_set_root_ref_dirid(leaf, ref, dirid);
     437           0 :         btrfs_set_root_ref_sequence(leaf, ref, sequence);
     438           0 :         btrfs_set_root_ref_name_len(leaf, ref, name->len);
     439           0 :         ptr = (unsigned long)(ref + 1);
     440           0 :         write_extent_buffer(leaf, name->name, ptr, name->len);
     441           0 :         btrfs_mark_buffer_dirty(leaf);
     442             : 
     443           0 :         if (key.type == BTRFS_ROOT_BACKREF_KEY) {
     444           0 :                 btrfs_release_path(path);
     445           0 :                 key.objectid = ref_id;
     446           0 :                 key.type = BTRFS_ROOT_REF_KEY;
     447           0 :                 key.offset = root_id;
     448           0 :                 goto again;
     449             :         }
     450             : 
     451           0 :         btrfs_free_path(path);
     452           0 :         return 0;
     453             : }
     454             : 
     455             : /*
     456             :  * Old btrfs forgets to init root_item->flags and root_item->byte_limit
     457             :  * for subvolumes. To work around this problem, we steal a bit from
     458             :  * root_item->inode_item->flags, and use it to indicate if those fields
     459             :  * have been properly initialized.
     460             :  */
     461           0 : void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
     462             : {
     463           0 :         u64 inode_flags = btrfs_stack_inode_flags(&root_item->inode);
     464             : 
     465           0 :         if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {
     466           0 :                 inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;
     467           0 :                 btrfs_set_stack_inode_flags(&root_item->inode, inode_flags);
     468           0 :                 btrfs_set_root_flags(root_item, 0);
     469           0 :                 btrfs_set_root_limit(root_item, 0);
     470             :         }
     471           0 : }
     472             : 
     473           0 : void btrfs_update_root_times(struct btrfs_trans_handle *trans,
     474             :                              struct btrfs_root *root)
     475             : {
     476           0 :         struct btrfs_root_item *item = &root->root_item;
     477           0 :         struct timespec64 ct;
     478             : 
     479           0 :         ktime_get_real_ts64(&ct);
     480           0 :         spin_lock(&root->root_item_lock);
     481           0 :         btrfs_set_root_ctransid(item, trans->transid);
     482           0 :         btrfs_set_stack_timespec_sec(&item->ctime, ct.tv_sec);
     483           0 :         btrfs_set_stack_timespec_nsec(&item->ctime, ct.tv_nsec);
     484           0 :         spin_unlock(&root->root_item_lock);
     485           0 : }
     486             : 
     487             : /*
     488             :  * btrfs_subvolume_reserve_metadata() - reserve space for subvolume operation
     489             :  * root: the root of the parent directory
     490             :  * rsv: block reservation
     491             :  * items: the number of items that we need do reservation
     492             :  * use_global_rsv: allow fallback to the global block reservation
     493             :  *
     494             :  * This function is used to reserve the space for snapshot/subvolume
     495             :  * creation and deletion. Those operations are different with the
     496             :  * common file/directory operations, they change two fs/file trees
     497             :  * and root tree, the number of items that the qgroup reserves is
     498             :  * different with the free space reservation. So we can not use
     499             :  * the space reservation mechanism in start_transaction().
     500             :  */
     501           0 : int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
     502             :                                      struct btrfs_block_rsv *rsv, int items,
     503             :                                      bool use_global_rsv)
     504             : {
     505           0 :         u64 qgroup_num_bytes = 0;
     506           0 :         u64 num_bytes;
     507           0 :         int ret;
     508           0 :         struct btrfs_fs_info *fs_info = root->fs_info;
     509           0 :         struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
     510             : 
     511           0 :         if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) {
     512             :                 /* One for parent inode, two for dir entries */
     513           0 :                 qgroup_num_bytes = 3 * fs_info->nodesize;
     514           0 :                 ret = btrfs_qgroup_reserve_meta_prealloc(root,
     515             :                                                          qgroup_num_bytes, true,
     516             :                                                          false);
     517           0 :                 if (ret)
     518             :                         return ret;
     519             :         }
     520             : 
     521           0 :         num_bytes = btrfs_calc_insert_metadata_size(fs_info, items);
     522           0 :         rsv->space_info = btrfs_find_space_info(fs_info,
     523             :                                             BTRFS_BLOCK_GROUP_METADATA);
     524           0 :         ret = btrfs_block_rsv_add(fs_info, rsv, num_bytes,
     525             :                                   BTRFS_RESERVE_FLUSH_ALL);
     526             : 
     527           0 :         if (ret == -ENOSPC && use_global_rsv)
     528           0 :                 ret = btrfs_block_rsv_migrate(global_rsv, rsv, num_bytes, true);
     529             : 
     530           0 :         if (ret && qgroup_num_bytes)
     531           0 :                 btrfs_qgroup_free_meta_prealloc(root, qgroup_num_bytes);
     532             : 
     533           0 :         if (!ret) {
     534           0 :                 spin_lock(&rsv->lock);
     535           0 :                 rsv->qgroup_rsv_reserved += qgroup_num_bytes;
     536           0 :                 spin_unlock(&rsv->lock);
     537             :         }
     538             :         return ret;
     539             : }
     540             : 
     541           0 : void btrfs_subvolume_release_metadata(struct btrfs_root *root,
     542             :                                       struct btrfs_block_rsv *rsv)
     543             : {
     544           0 :         struct btrfs_fs_info *fs_info = root->fs_info;
     545           0 :         u64 qgroup_to_release;
     546             : 
     547           0 :         btrfs_block_rsv_release(fs_info, rsv, (u64)-1, &qgroup_to_release);
     548           0 :         btrfs_qgroup_convert_reserved_meta(root, qgroup_to_release);
     549           0 : }

Generated by: LCOV version 1.14