LCOV - code coverage report
Current view: top level - fs/btrfs - root-tree.c (source / functions) Hit Total Coverage
Test: btrfstest.info Lines: 145 191 75.9 %
Date: 2014-11-28 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2007 Oracle.  All rights reserved.
       3             :  *
       4             :  * This program is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU General Public
       6             :  * License v2 as published by the Free Software Foundation.
       7             :  *
       8             :  * This program is distributed in the hope that it will be useful,
       9             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      10             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      11             :  * General Public License for more details.
      12             :  *
      13             :  * You should have received a copy of the GNU General Public
      14             :  * License along with this program; if not, write to the
      15             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      16             :  * Boston, MA 021110-1307, USA.
      17             :  */
      18             : 
      19             : #include <linux/err.h>
      20             : #include <linux/uuid.h>
      21             : #include "ctree.h"
      22             : #include "transaction.h"
      23             : #include "disk-io.h"
      24             : #include "print-tree.h"
      25             : 
      26             : /*
      27             :  * Read a root item from the tree. In case we detect a root item smaller then
      28             :  * sizeof(root_item), we know it's an old version of the root structure and
      29             :  * initialize all new fields to zero. The same happens if we detect mismatching
      30             :  * generation numbers as then we know the root was once mounted with an older
      31             :  * kernel that was not aware of the root item structure change.
      32             :  */
      33        1915 : static void btrfs_read_root_item(struct extent_buffer *eb, int slot,
      34             :                                 struct btrfs_root_item *item)
      35             : {
      36             :         uuid_le uuid;
      37             :         int len;
      38             :         int need_reset = 0;
      39             : 
      40        1915 :         len = btrfs_item_size_nr(eb, slot);
      41        3830 :         read_extent_buffer(eb, item, btrfs_item_ptr_offset(eb, slot),
      42        1915 :                         min_t(int, len, (int)sizeof(*item)));
      43        1915 :         if (len < sizeof(*item))
      44             :                 need_reset = 1;
      45        3830 :         if (!need_reset && btrfs_root_generation(item)
      46             :                 != btrfs_root_generation_v2(item)) {
      47           0 :                 if (btrfs_root_generation_v2(item) != 0) {
      48           0 :                         printk(KERN_WARNING "BTRFS: mismatching "
      49             :                                         "generation and generation_v2 "
      50             :                                         "found in root item. This root "
      51             :                                         "was probably mounted with an "
      52             :                                         "older kernel. Resetting all "
      53             :                                         "new fields.\n");
      54             :                 }
      55             :                 need_reset = 1;
      56             :         }
      57        1915 :         if (need_reset) {
      58           0 :                 memset(&item->generation_v2, 0,
      59             :                         sizeof(*item) - offsetof(struct btrfs_root_item,
      60             :                                         generation_v2));
      61             : 
      62           0 :                 uuid_le_gen(&uuid);
      63           0 :                 memcpy(item->uuid, uuid.b, BTRFS_UUID_SIZE);
      64             :         }
      65        1915 : }
      66             : 
      67             : /*
      68             :  * btrfs_find_root - lookup the root by the key.
      69             :  * root: the root of the root tree
      70             :  * search_key: the key to search
      71             :  * path: the path we search
      72             :  * root_item: the root item of the tree we look for
      73             :  * root_key: the reak key of the tree we look for
      74             :  *
      75             :  * If ->offset of 'seach_key' is -1ULL, it means we are not sure the offset
      76             :  * of the search key, just lookup the root with the highest offset for a
      77             :  * given objectid.
      78             :  *
      79             :  * If we find something return 0, otherwise > 0, < 0 on error.
      80             :  */
      81        2243 : int btrfs_find_root(struct btrfs_root *root, struct btrfs_key *search_key,
      82             :                     struct btrfs_path *path, struct btrfs_root_item *root_item,
      83             :                     struct btrfs_key *root_key)
      84             : {
      85             :         struct btrfs_key found_key;
      86             :         struct extent_buffer *l;
      87             :         int ret;
      88             :         int slot;
      89             : 
      90        2243 :         ret = btrfs_search_slot(NULL, root, search_key, path, 0, 0);
      91        2243 :         if (ret < 0)
      92             :                 return ret;
      93             : 
      94        2243 :         if (search_key->offset != -1ULL) {   /* the search key is exact */
      95        1779 :                 if (ret > 0)
      96             :                         goto out;
      97             :         } else {
      98         464 :                 BUG_ON(ret == 0);               /* Logical error */
      99         464 :                 if (path->slots[0] == 0)
     100             :                         goto out;
     101         464 :                 path->slots[0]--;
     102             :                 ret = 0;
     103             :         }
     104             : 
     105        1915 :         l = path->nodes[0];
     106        1915 :         slot = path->slots[0];
     107             : 
     108        1915 :         btrfs_item_key_to_cpu(l, &found_key, slot);
     109        3830 :         if (found_key.objectid != search_key->objectid ||
     110        1915 :             found_key.type != BTRFS_ROOT_ITEM_KEY) {
     111             :                 ret = 1;
     112             :                 goto out;
     113             :         }
     114             : 
     115        1915 :         if (root_item)
     116        1915 :                 btrfs_read_root_item(l, slot, root_item);
     117        1915 :         if (root_key)
     118        1915 :                 memcpy(root_key, &found_key, sizeof(found_key));
     119             : out:
     120        2243 :         btrfs_release_path(path);
     121        2243 :         return ret;
     122             : }
     123             : 
     124       13319 : void btrfs_set_root_node(struct btrfs_root_item *item,
     125       26638 :                          struct extent_buffer *node)
     126             : {
     127       13319 :         btrfs_set_root_bytenr(item, node->start);
     128             :         btrfs_set_root_level(item, btrfs_header_level(node));
     129             :         btrfs_set_root_generation(item, btrfs_header_generation(node));
     130       13319 : }
     131             : 
     132             : /*
     133             :  * copy the data in 'item' into the btree
     134             :  */
     135       10015 : int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
     136             :                       *root, struct btrfs_key *key, struct btrfs_root_item
     137             :                       *item)
     138             : {
     139             :         struct btrfs_path *path;
     140             :         struct extent_buffer *l;
     141             :         int ret;
     142             :         int slot;
     143             :         unsigned long ptr;
     144             :         int old_len;
     145             : 
     146       10015 :         path = btrfs_alloc_path();
     147       10015 :         if (!path)
     148             :                 return -ENOMEM;
     149             : 
     150       10015 :         ret = btrfs_search_slot(trans, root, key, path, 0, 1);
     151       10015 :         if (ret < 0) {
     152           0 :                 btrfs_abort_transaction(trans, root, ret);
     153           0 :                 goto out;
     154             :         }
     155             : 
     156       10015 :         if (ret != 0) {
     157           0 :                 btrfs_print_leaf(root, path->nodes[0]);
     158           0 :                 btrfs_crit(root->fs_info, "unable to update root key %llu %u %llu",
     159             :                        key->objectid, key->type, key->offset);
     160           0 :                 BUG_ON(1);
     161             :         }
     162             : 
     163       10015 :         l = path->nodes[0];
     164       10015 :         slot = path->slots[0];
     165       10015 :         ptr = btrfs_item_ptr_offset(l, slot);
     166             :         old_len = btrfs_item_size_nr(l, slot);
     167             : 
     168             :         /*
     169             :          * If this is the first time we update the root item which originated
     170             :          * from an older kernel, we need to enlarge the item size to make room
     171             :          * for the added fields.
     172             :          */
     173       10015 :         if (old_len < sizeof(*item)) {
     174           0 :                 btrfs_release_path(path);
     175           0 :                 ret = btrfs_search_slot(trans, root, key, path,
     176             :                                 -1, 1);
     177           0 :                 if (ret < 0) {
     178           0 :                         btrfs_abort_transaction(trans, root, ret);
     179           0 :                         goto out;
     180             :                 }
     181             : 
     182             :                 ret = btrfs_del_item(trans, root, path);
     183           0 :                 if (ret < 0) {
     184           0 :                         btrfs_abort_transaction(trans, root, ret);
     185           0 :                         goto out;
     186             :                 }
     187           0 :                 btrfs_release_path(path);
     188             :                 ret = btrfs_insert_empty_item(trans, root, path,
     189             :                                 key, sizeof(*item));
     190           0 :                 if (ret < 0) {
     191           0 :                         btrfs_abort_transaction(trans, root, ret);
     192           0 :                         goto out;
     193             :                 }
     194           0 :                 l = path->nodes[0];
     195           0 :                 slot = path->slots[0];
     196           0 :                 ptr = btrfs_item_ptr_offset(l, slot);
     197             :         }
     198             : 
     199             :         /*
     200             :          * Update generation_v2 so at the next mount we know the new root
     201             :          * fields are valid.
     202             :          */
     203             :         btrfs_set_root_generation_v2(item, btrfs_root_generation(item));
     204             : 
     205       10015 :         write_extent_buffer(l, item, ptr, sizeof(*item));
     206       10015 :         btrfs_mark_buffer_dirty(path->nodes[0]);
     207             : out:
     208       10015 :         btrfs_free_path(path);
     209       10015 :         return ret;
     210             : }
     211             : 
     212         962 : int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
     213             :                       struct btrfs_key *key, struct btrfs_root_item *item)
     214             : {
     215             :         /*
     216             :          * Make sure generation v1 and v2 match. See update_root for details.
     217             :          */
     218             :         btrfs_set_root_generation_v2(item, btrfs_root_generation(item));
     219         962 :         return btrfs_insert_item(trans, root, key, item, sizeof(*item));
     220             : }
     221             : 
     222         221 : int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
     223             : {
     224         293 :         struct extent_buffer *leaf;
     225             :         struct btrfs_path *path;
     226             :         struct btrfs_key key;
     227             :         struct btrfs_key root_key;
     228             :         struct btrfs_root *root;
     229             :         int err = 0;
     230             :         int ret;
     231             :         bool can_recover = true;
     232             : 
     233             :         if (tree_root->fs_info->sb->s_flags & MS_RDONLY)
     234             :                 can_recover = false;
     235             : 
     236         221 :         path = btrfs_alloc_path();
     237         221 :         if (!path)
     238             :                 return -ENOMEM;
     239             : 
     240         221 :         key.objectid = BTRFS_ORPHAN_OBJECTID;
     241         221 :         key.type = BTRFS_ORPHAN_ITEM_KEY;
     242         221 :         key.offset = 0;
     243             : 
     244         221 :         root_key.type = BTRFS_ROOT_ITEM_KEY;
     245         221 :         root_key.offset = (u64)-1;
     246             : 
     247             :         while (1) {
     248         293 :                 ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
     249         293 :                 if (ret < 0) {
     250             :                         err = ret;
     251             :                         break;
     252             :                 }
     253             : 
     254         293 :                 leaf = path->nodes[0];
     255         586 :                 if (path->slots[0] >= btrfs_header_nritems(leaf)) {
     256         221 :                         ret = btrfs_next_leaf(tree_root, path);
     257         221 :                         if (ret < 0)
     258             :                                 err = ret;
     259         221 :                         if (ret != 0)
     260             :                                 break;
     261           0 :                         leaf = path->nodes[0];
     262             :                 }
     263             : 
     264          72 :                 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
     265          72 :                 btrfs_release_path(path);
     266             : 
     267         144 :                 if (key.objectid != BTRFS_ORPHAN_OBJECTID ||
     268          72 :                     key.type != BTRFS_ORPHAN_ITEM_KEY)
     269             :                         break;
     270             : 
     271          72 :                 root_key.objectid = key.offset;
     272          72 :                 key.offset++;
     273             : 
     274          72 :                 root = btrfs_read_fs_root(tree_root, &root_key);
     275             :                 err = PTR_ERR_OR_ZERO(root);
     276          72 :                 if (err && err != -ENOENT) {
     277             :                         break;
     278          72 :                 } else if (err == -ENOENT) {
     279             :                         struct btrfs_trans_handle *trans;
     280             : 
     281           0 :                         btrfs_release_path(path);
     282             : 
     283           0 :                         trans = btrfs_join_transaction(tree_root);
     284           0 :                         if (IS_ERR(trans)) {
     285           0 :                                 err = PTR_ERR(trans);
     286           0 :                                 btrfs_error(tree_root->fs_info, err,
     287             :                                             "Failed to start trans to delete "
     288             :                                             "orphan item");
     289           0 :                                 break;
     290             :                         }
     291           0 :                         err = btrfs_del_orphan_item(trans, tree_root,
     292             :                                                     root_key.objectid);
     293           0 :                         btrfs_end_transaction(trans, tree_root);
     294           0 :                         if (err) {
     295           0 :                                 btrfs_error(tree_root->fs_info, err,
     296             :                                             "Failed to delete root orphan "
     297             :                                             "item");
     298           0 :                                 break;
     299             :                         }
     300           0 :                         continue;
     301             :                 }
     302             : 
     303          72 :                 err = btrfs_init_fs_root(root);
     304          72 :                 if (err) {
     305           0 :                         btrfs_free_fs_root(root);
     306           0 :                         break;
     307             :                 }
     308             : 
     309             :                 set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state);
     310             : 
     311          72 :                 err = btrfs_insert_fs_root(root->fs_info, root);
     312          72 :                 if (err) {
     313           0 :                         BUG_ON(err == -EEXIST);
     314           0 :                         btrfs_free_fs_root(root);
     315           0 :                         break;
     316             :                 }
     317             : 
     318          72 :                 if (btrfs_root_refs(&root->root_item) == 0)
     319          72 :                         btrfs_add_dead_root(root);
     320             :         }
     321             : 
     322         221 :         btrfs_free_path(path);
     323         221 :         return err;
     324             : }
     325             : 
     326             : /* drop the root item for 'key' from 'root' */
     327         450 : int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
     328             :                    struct btrfs_key *key)
     329             : {
     330             :         struct btrfs_path *path;
     331             :         int ret;
     332             : 
     333         450 :         path = btrfs_alloc_path();
     334         450 :         if (!path)
     335             :                 return -ENOMEM;
     336         450 :         ret = btrfs_search_slot(trans, root, key, path, -1, 1);
     337         450 :         if (ret < 0)
     338             :                 goto out;
     339             : 
     340         450 :         BUG_ON(ret != 0);
     341             : 
     342             :         ret = btrfs_del_item(trans, root, path);
     343             : out:
     344         450 :         btrfs_free_path(path);
     345         450 :         return ret;
     346             : }
     347             : 
     348          34 : int btrfs_del_root_ref(struct btrfs_trans_handle *trans,
     349             :                        struct btrfs_root *tree_root,
     350             :                        u64 root_id, u64 ref_id, u64 dirid, u64 *sequence,
     351             :                        const char *name, int name_len)
     352             : 
     353             : {
     354             :         struct btrfs_path *path;
     355             :         struct btrfs_root_ref *ref;
     356             :         struct extent_buffer *leaf;
     357             :         struct btrfs_key key;
     358             :         unsigned long ptr;
     359             :         int err = 0;
     360             :         int ret;
     361             : 
     362          34 :         path = btrfs_alloc_path();
     363          34 :         if (!path)
     364             :                 return -ENOMEM;
     365             : 
     366          34 :         key.objectid = root_id;
     367          34 :         key.type = BTRFS_ROOT_BACKREF_KEY;
     368          34 :         key.offset = ref_id;
     369             : again:
     370          68 :         ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
     371          68 :         BUG_ON(ret < 0);
     372          68 :         if (ret == 0) {
     373          68 :                 leaf = path->nodes[0];
     374         136 :                 ref = btrfs_item_ptr(leaf, path->slots[0],
     375             :                                      struct btrfs_root_ref);
     376             : 
     377          68 :                 WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid);
     378          68 :                 WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len);
     379          68 :                 ptr = (unsigned long)(ref + 1);
     380          68 :                 WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len));
     381          68 :                 *sequence = btrfs_root_ref_sequence(leaf, ref);
     382             : 
     383             :                 ret = btrfs_del_item(trans, tree_root, path);
     384          68 :                 if (ret) {
     385             :                         err = ret;
     386             :                         goto out;
     387             :                 }
     388             :         } else
     389             :                 err = -ENOENT;
     390             : 
     391          68 :         if (key.type == BTRFS_ROOT_BACKREF_KEY) {
     392          34 :                 btrfs_release_path(path);
     393          34 :                 key.objectid = ref_id;
     394          34 :                 key.type = BTRFS_ROOT_REF_KEY;
     395          34 :                 key.offset = root_id;
     396          34 :                 goto again;
     397             :         }
     398             : 
     399             : out:
     400          34 :         btrfs_free_path(path);
     401          34 :         return err;
     402             : }
     403             : 
     404             : /*
     405             :  * add a btrfs_root_ref item.  type is either BTRFS_ROOT_REF_KEY
     406             :  * or BTRFS_ROOT_BACKREF_KEY.
     407             :  *
     408             :  * The dirid, sequence, name and name_len refer to the directory entry
     409             :  * that is referencing the root.
     410             :  *
     411             :  * For a forward ref, the root_id is the id of the tree referencing
     412             :  * the root and ref_id is the id of the subvol  or snapshot.
     413             :  *
     414             :  * For a back ref the root_id is the id of the subvol or snapshot and
     415             :  * ref_id is the id of the tree referencing it.
     416             :  *
     417             :  * Will return 0, -ENOMEM, or anything from the CoW path
     418             :  */
     419         196 : int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
     420             :                        struct btrfs_root *tree_root,
     421             :                        u64 root_id, u64 ref_id, u64 dirid, u64 sequence,
     422             :                        const char *name, int name_len)
     423             : {
     424             :         struct btrfs_key key;
     425             :         int ret;
     426             :         struct btrfs_path *path;
     427             :         struct btrfs_root_ref *ref;
     428             :         struct extent_buffer *leaf;
     429             :         unsigned long ptr;
     430             : 
     431         196 :         path = btrfs_alloc_path();
     432         196 :         if (!path)
     433             :                 return -ENOMEM;
     434             : 
     435         196 :         key.objectid = root_id;
     436         196 :         key.type = BTRFS_ROOT_BACKREF_KEY;
     437         196 :         key.offset = ref_id;
     438             : again:
     439         392 :         ret = btrfs_insert_empty_item(trans, tree_root, path, &key,
     440             :                                       sizeof(*ref) + name_len);
     441         392 :         if (ret) {
     442           0 :                 btrfs_abort_transaction(trans, tree_root, ret);
     443           0 :                 btrfs_free_path(path);
     444           0 :                 return ret;
     445             :         }
     446             : 
     447         392 :         leaf = path->nodes[0];
     448         784 :         ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref);
     449             :         btrfs_set_root_ref_dirid(leaf, ref, dirid);
     450             :         btrfs_set_root_ref_sequence(leaf, ref, sequence);
     451         392 :         btrfs_set_root_ref_name_len(leaf, ref, name_len);
     452         392 :         ptr = (unsigned long)(ref + 1);
     453         392 :         write_extent_buffer(leaf, name, ptr, name_len);
     454         392 :         btrfs_mark_buffer_dirty(leaf);
     455             : 
     456         392 :         if (key.type == BTRFS_ROOT_BACKREF_KEY) {
     457         196 :                 btrfs_release_path(path);
     458         196 :                 key.objectid = ref_id;
     459         196 :                 key.type = BTRFS_ROOT_REF_KEY;
     460         196 :                 key.offset = root_id;
     461         196 :                 goto again;
     462             :         }
     463             : 
     464         196 :         btrfs_free_path(path);
     465         196 :         return 0;
     466             : }
     467             : 
     468             : /*
     469             :  * Old btrfs forgets to init root_item->flags and root_item->byte_limit
     470             :  * for subvolumes. To work around this problem, we steal a bit from
     471             :  * root_item->inode_item->flags, and use it to indicate if those fields
     472             :  * have been properly initialized.
     473             :  */
     474        1273 : void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
     475             : {
     476             :         u64 inode_flags = btrfs_stack_inode_flags(&root_item->inode);
     477             : 
     478        1273 :         if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {
     479         291 :                 inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;
     480             :                 btrfs_set_stack_inode_flags(&root_item->inode, inode_flags);
     481             :                 btrfs_set_root_flags(root_item, 0);
     482             :                 btrfs_set_root_limit(root_item, 0);
     483             :         }
     484        1273 : }
     485             : 
     486      170671 : void btrfs_update_root_times(struct btrfs_trans_handle *trans,
     487             :                              struct btrfs_root *root)
     488             : {
     489             :         struct btrfs_root_item *item = &root->root_item;
     490      170671 :         struct timespec ct = CURRENT_TIME;
     491             : 
     492             :         spin_lock(&root->root_item_lock);
     493      170676 :         btrfs_set_root_ctransid(item, trans->transid);
     494      170676 :         btrfs_set_stack_timespec_sec(&item->ctime, ct.tv_sec);
     495      170676 :         btrfs_set_stack_timespec_nsec(&item->ctime, ct.tv_nsec);
     496             :         spin_unlock(&root->root_item_lock);
     497      170675 : }

Generated by: LCOV version 1.10