16cbd5570SChris Mason /* 26cbd5570SChris Mason * Copyright (C) 2007 Oracle. All rights reserved. 36cbd5570SChris Mason * 46cbd5570SChris Mason * This program is free software; you can redistribute it and/or 56cbd5570SChris Mason * modify it under the terms of the GNU General Public 66cbd5570SChris Mason * License v2 as published by the Free Software Foundation. 76cbd5570SChris Mason * 86cbd5570SChris Mason * This program is distributed in the hope that it will be useful, 96cbd5570SChris Mason * but WITHOUT ANY WARRANTY; without even the implied warranty of 106cbd5570SChris Mason * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 116cbd5570SChris Mason * General Public License for more details. 126cbd5570SChris Mason * 136cbd5570SChris Mason * You should have received a copy of the GNU General Public 146cbd5570SChris Mason * License along with this program; if not, write to the 156cbd5570SChris Mason * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 166cbd5570SChris Mason * Boston, MA 021110-1307, USA. 176cbd5570SChris Mason */ 186cbd5570SChris Mason 19886322e8SSachin Kamat #include <linux/err.h> 208ea05e3aSAlexander Block #include <linux/uuid.h> 213768f368SChris Mason #include "ctree.h" 225eda7b5eSChris Mason #include "transaction.h" 233768f368SChris Mason #include "disk-io.h" 243768f368SChris Mason #include "print-tree.h" 253768f368SChris Mason 26bf4ef679SChris Mason /* 278ea05e3aSAlexander Block * Read a root item from the tree. In case we detect a root item smaller then 288ea05e3aSAlexander Block * sizeof(root_item), we know it's an old version of the root structure and 298ea05e3aSAlexander Block * initialize all new fields to zero. The same happens if we detect mismatching 308ea05e3aSAlexander Block * generation numbers as then we know the root was once mounted with an older 318ea05e3aSAlexander Block * kernel that was not aware of the root item structure change. 328ea05e3aSAlexander Block */ 33171170c1SSergei Trofimovich static void btrfs_read_root_item(struct extent_buffer *eb, int slot, 348ea05e3aSAlexander Block struct btrfs_root_item *item) 358ea05e3aSAlexander Block { 368ea05e3aSAlexander Block uuid_le uuid; 378ea05e3aSAlexander Block int len; 388ea05e3aSAlexander Block int need_reset = 0; 398ea05e3aSAlexander Block 408ea05e3aSAlexander Block len = btrfs_item_size_nr(eb, slot); 418ea05e3aSAlexander Block read_extent_buffer(eb, item, btrfs_item_ptr_offset(eb, slot), 428ea05e3aSAlexander Block min_t(int, len, (int)sizeof(*item))); 438ea05e3aSAlexander Block if (len < sizeof(*item)) 448ea05e3aSAlexander Block need_reset = 1; 458ea05e3aSAlexander Block if (!need_reset && btrfs_root_generation(item) 468ea05e3aSAlexander Block != btrfs_root_generation_v2(item)) { 478ea05e3aSAlexander Block if (btrfs_root_generation_v2(item) != 0) { 48f14d104dSDavid Sterba btrfs_warn(eb->fs_info, 49f14d104dSDavid Sterba "mismatching " 508ea05e3aSAlexander Block "generation and generation_v2 " 518ea05e3aSAlexander Block "found in root item. This root " 528ea05e3aSAlexander Block "was probably mounted with an " 538ea05e3aSAlexander Block "older kernel. Resetting all " 54f14d104dSDavid Sterba "new fields."); 558ea05e3aSAlexander Block } 568ea05e3aSAlexander Block need_reset = 1; 578ea05e3aSAlexander Block } 588ea05e3aSAlexander Block if (need_reset) { 598ea05e3aSAlexander Block memset(&item->generation_v2, 0, 608ea05e3aSAlexander Block sizeof(*item) - offsetof(struct btrfs_root_item, 618ea05e3aSAlexander Block generation_v2)); 628ea05e3aSAlexander Block 638ea05e3aSAlexander Block uuid_le_gen(&uuid); 648ea05e3aSAlexander Block memcpy(item->uuid, uuid.b, BTRFS_UUID_SIZE); 658ea05e3aSAlexander Block } 668ea05e3aSAlexander Block } 678ea05e3aSAlexander Block 688ea05e3aSAlexander Block /* 69cb517eabSMiao Xie * btrfs_find_root - lookup the root by the key. 70cb517eabSMiao Xie * root: the root of the root tree 71cb517eabSMiao Xie * search_key: the key to search 72cb517eabSMiao Xie * path: the path we search 73cb517eabSMiao Xie * root_item: the root item of the tree we look for 74*01327610SNicholas D Steeves * root_key: the root key of the tree we look for 75cb517eabSMiao Xie * 76*01327610SNicholas D Steeves * If ->offset of 'search_key' is -1ULL, it means we are not sure the offset 77cb517eabSMiao Xie * of the search key, just lookup the root with the highest offset for a 78cb517eabSMiao Xie * given objectid. 79cb517eabSMiao Xie * 80cb517eabSMiao Xie * If we find something return 0, otherwise > 0, < 0 on error. 81d352ac68SChris Mason */ 82cb517eabSMiao Xie int btrfs_find_root(struct btrfs_root *root, struct btrfs_key *search_key, 83cb517eabSMiao Xie struct btrfs_path *path, struct btrfs_root_item *root_item, 84cb517eabSMiao Xie struct btrfs_key *root_key) 853768f368SChris Mason { 865f39d397SChris Mason struct btrfs_key found_key; 875f39d397SChris Mason struct extent_buffer *l; 883768f368SChris Mason int ret; 893768f368SChris Mason int slot; 903768f368SChris Mason 91cb517eabSMiao Xie ret = btrfs_search_slot(NULL, root, search_key, path, 0, 0); 923768f368SChris Mason if (ret < 0) 93cb517eabSMiao Xie return ret; 945f39d397SChris Mason 95cb517eabSMiao Xie if (search_key->offset != -1ULL) { /* the search key is exact */ 96cb517eabSMiao Xie if (ret > 0) 973768f368SChris Mason goto out; 98cb517eabSMiao Xie } else { 99cb517eabSMiao Xie BUG_ON(ret == 0); /* Logical error */ 100cb517eabSMiao Xie if (path->slots[0] == 0) 101cb517eabSMiao Xie goto out; 102cb517eabSMiao Xie path->slots[0]--; 103cb517eabSMiao Xie ret = 0; 1043768f368SChris Mason } 105cb517eabSMiao Xie 10676dda93cSYan, Zheng l = path->nodes[0]; 107cb517eabSMiao Xie slot = path->slots[0]; 108cb517eabSMiao Xie 10976dda93cSYan, Zheng btrfs_item_key_to_cpu(l, &found_key, slot); 110cb517eabSMiao Xie if (found_key.objectid != search_key->objectid || 11176dda93cSYan, Zheng found_key.type != BTRFS_ROOT_ITEM_KEY) { 11276dda93cSYan, Zheng ret = 1; 11376dda93cSYan, Zheng goto out; 11476dda93cSYan, Zheng } 1158ea05e3aSAlexander Block 116cb517eabSMiao Xie if (root_item) 117cb517eabSMiao Xie btrfs_read_root_item(l, slot, root_item); 118cb517eabSMiao Xie if (root_key) 119cb517eabSMiao Xie memcpy(root_key, &found_key, sizeof(found_key)); 1203768f368SChris Mason out: 121cb517eabSMiao Xie btrfs_release_path(path); 1223768f368SChris Mason return ret; 1233768f368SChris Mason } 1243768f368SChris Mason 125bf5f32ecSMark Fasheh void btrfs_set_root_node(struct btrfs_root_item *item, 1265d4f98a2SYan Zheng struct extent_buffer *node) 1275d4f98a2SYan Zheng { 1285d4f98a2SYan Zheng btrfs_set_root_bytenr(item, node->start); 1295d4f98a2SYan Zheng btrfs_set_root_level(item, btrfs_header_level(node)); 1305d4f98a2SYan Zheng btrfs_set_root_generation(item, btrfs_header_generation(node)); 1315d4f98a2SYan Zheng } 1325d4f98a2SYan Zheng 133d352ac68SChris Mason /* 134d352ac68SChris Mason * copy the data in 'item' into the btree 135d352ac68SChris Mason */ 136e089f05cSChris Mason int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root 137e089f05cSChris Mason *root, struct btrfs_key *key, struct btrfs_root_item 138e089f05cSChris Mason *item) 1393768f368SChris Mason { 1405caf2a00SChris Mason struct btrfs_path *path; 1415f39d397SChris Mason struct extent_buffer *l; 1423768f368SChris Mason int ret; 1433768f368SChris Mason int slot; 1445f39d397SChris Mason unsigned long ptr; 1450412e58cSAlexandru Moise u32 old_len; 1463768f368SChris Mason 1475caf2a00SChris Mason path = btrfs_alloc_path(); 148b45a9d8bSJeff Mahoney if (!path) 149b45a9d8bSJeff Mahoney return -ENOMEM; 150b45a9d8bSJeff Mahoney 1515caf2a00SChris Mason ret = btrfs_search_slot(trans, root, key, path, 0, 1); 152005d6427SDavid Sterba if (ret < 0) { 153005d6427SDavid Sterba btrfs_abort_transaction(trans, root, ret); 154005d6427SDavid Sterba goto out; 155005d6427SDavid Sterba } 156d6667462SChris Mason 157d6667462SChris Mason if (ret != 0) { 158d6667462SChris Mason btrfs_print_leaf(root, path->nodes[0]); 159efe120a0SFrank Holton btrfs_crit(root->fs_info, "unable to update root key %llu %u %llu", 160c1c9ff7cSGeert Uytterhoeven key->objectid, key->type, key->offset); 161d6667462SChris Mason BUG_ON(1); 162d6667462SChris Mason } 163d6667462SChris Mason 1645f39d397SChris Mason l = path->nodes[0]; 1655caf2a00SChris Mason slot = path->slots[0]; 1665f39d397SChris Mason ptr = btrfs_item_ptr_offset(l, slot); 1678ea05e3aSAlexander Block old_len = btrfs_item_size_nr(l, slot); 1688ea05e3aSAlexander Block 1698ea05e3aSAlexander Block /* 1708ea05e3aSAlexander Block * If this is the first time we update the root item which originated 1718ea05e3aSAlexander Block * from an older kernel, we need to enlarge the item size to make room 1728ea05e3aSAlexander Block * for the added fields. 1738ea05e3aSAlexander Block */ 1748ea05e3aSAlexander Block if (old_len < sizeof(*item)) { 1758ea05e3aSAlexander Block btrfs_release_path(path); 1768ea05e3aSAlexander Block ret = btrfs_search_slot(trans, root, key, path, 1778ea05e3aSAlexander Block -1, 1); 178005d6427SDavid Sterba if (ret < 0) { 179005d6427SDavid Sterba btrfs_abort_transaction(trans, root, ret); 180005d6427SDavid Sterba goto out; 181005d6427SDavid Sterba } 182005d6427SDavid Sterba 1838ea05e3aSAlexander Block ret = btrfs_del_item(trans, root, path); 184005d6427SDavid Sterba if (ret < 0) { 185005d6427SDavid Sterba btrfs_abort_transaction(trans, root, ret); 186005d6427SDavid Sterba goto out; 187005d6427SDavid Sterba } 1888ea05e3aSAlexander Block btrfs_release_path(path); 1898ea05e3aSAlexander Block ret = btrfs_insert_empty_item(trans, root, path, 1908ea05e3aSAlexander Block key, sizeof(*item)); 191005d6427SDavid Sterba if (ret < 0) { 192005d6427SDavid Sterba btrfs_abort_transaction(trans, root, ret); 193005d6427SDavid Sterba goto out; 194005d6427SDavid Sterba } 1958ea05e3aSAlexander Block l = path->nodes[0]; 1968ea05e3aSAlexander Block slot = path->slots[0]; 1978ea05e3aSAlexander Block ptr = btrfs_item_ptr_offset(l, slot); 1988ea05e3aSAlexander Block } 1998ea05e3aSAlexander Block 2008ea05e3aSAlexander Block /* 2018ea05e3aSAlexander Block * Update generation_v2 so at the next mount we know the new root 2028ea05e3aSAlexander Block * fields are valid. 2038ea05e3aSAlexander Block */ 2048ea05e3aSAlexander Block btrfs_set_root_generation_v2(item, btrfs_root_generation(item)); 2058ea05e3aSAlexander Block 2065f39d397SChris Mason write_extent_buffer(l, item, ptr, sizeof(*item)); 2075caf2a00SChris Mason btrfs_mark_buffer_dirty(path->nodes[0]); 2083768f368SChris Mason out: 2095caf2a00SChris Mason btrfs_free_path(path); 2103768f368SChris Mason return ret; 2113768f368SChris Mason } 2123768f368SChris Mason 213d16cb050SJeff Mahoney int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, 214d16cb050SJeff Mahoney struct btrfs_key *key, struct btrfs_root_item *item) 2153768f368SChris Mason { 2168ea05e3aSAlexander Block /* 2178ea05e3aSAlexander Block * Make sure generation v1 and v2 match. See update_root for details. 2188ea05e3aSAlexander Block */ 2198ea05e3aSAlexander Block btrfs_set_root_generation_v2(item, btrfs_root_generation(item)); 220d16cb050SJeff Mahoney return btrfs_insert_item(trans, root, key, item, sizeof(*item)); 2213768f368SChris Mason } 2223768f368SChris Mason 22376dda93cSYan, Zheng int btrfs_find_orphan_roots(struct btrfs_root *tree_root) 22476dda93cSYan, Zheng { 22576dda93cSYan, Zheng struct extent_buffer *leaf; 22676dda93cSYan, Zheng struct btrfs_path *path; 22776dda93cSYan, Zheng struct btrfs_key key; 228d68fc57bSYan, Zheng struct btrfs_key root_key; 229d68fc57bSYan, Zheng struct btrfs_root *root; 23076dda93cSYan, Zheng int err = 0; 23176dda93cSYan, Zheng int ret; 23268a7342cSJosef Bacik bool can_recover = true; 23368a7342cSJosef Bacik 23468a7342cSJosef Bacik if (tree_root->fs_info->sb->s_flags & MS_RDONLY) 23568a7342cSJosef Bacik can_recover = false; 23676dda93cSYan, Zheng 23776dda93cSYan, Zheng path = btrfs_alloc_path(); 23876dda93cSYan, Zheng if (!path) 23976dda93cSYan, Zheng return -ENOMEM; 24076dda93cSYan, Zheng 24176dda93cSYan, Zheng key.objectid = BTRFS_ORPHAN_OBJECTID; 24276dda93cSYan, Zheng key.type = BTRFS_ORPHAN_ITEM_KEY; 24376dda93cSYan, Zheng key.offset = 0; 24476dda93cSYan, Zheng 245d68fc57bSYan, Zheng root_key.type = BTRFS_ROOT_ITEM_KEY; 246d68fc57bSYan, Zheng root_key.offset = (u64)-1; 247d68fc57bSYan, Zheng 24876dda93cSYan, Zheng while (1) { 24976dda93cSYan, Zheng ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0); 25076dda93cSYan, Zheng if (ret < 0) { 25176dda93cSYan, Zheng err = ret; 25276dda93cSYan, Zheng break; 25376dda93cSYan, Zheng } 25476dda93cSYan, Zheng 25576dda93cSYan, Zheng leaf = path->nodes[0]; 25676dda93cSYan, Zheng if (path->slots[0] >= btrfs_header_nritems(leaf)) { 25776dda93cSYan, Zheng ret = btrfs_next_leaf(tree_root, path); 25876dda93cSYan, Zheng if (ret < 0) 25976dda93cSYan, Zheng err = ret; 26076dda93cSYan, Zheng if (ret != 0) 26176dda93cSYan, Zheng break; 26276dda93cSYan, Zheng leaf = path->nodes[0]; 26376dda93cSYan, Zheng } 26476dda93cSYan, Zheng 26576dda93cSYan, Zheng btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 266b3b4aa74SDavid Sterba btrfs_release_path(path); 26776dda93cSYan, Zheng 26876dda93cSYan, Zheng if (key.objectid != BTRFS_ORPHAN_OBJECTID || 26976dda93cSYan, Zheng key.type != BTRFS_ORPHAN_ITEM_KEY) 27076dda93cSYan, Zheng break; 27176dda93cSYan, Zheng 272d68fc57bSYan, Zheng root_key.objectid = key.offset; 273d68fc57bSYan, Zheng key.offset++; 274d68fc57bSYan, Zheng 275cb517eabSMiao Xie root = btrfs_read_fs_root(tree_root, &root_key); 276886322e8SSachin Kamat err = PTR_ERR_OR_ZERO(root); 27768a7342cSJosef Bacik if (err && err != -ENOENT) { 27876dda93cSYan, Zheng break; 27968a7342cSJosef Bacik } else if (err == -ENOENT) { 28068a7342cSJosef Bacik struct btrfs_trans_handle *trans; 28168a7342cSJosef Bacik 28268a7342cSJosef Bacik btrfs_release_path(path); 28368a7342cSJosef Bacik 28468a7342cSJosef Bacik trans = btrfs_join_transaction(tree_root); 28568a7342cSJosef Bacik if (IS_ERR(trans)) { 28668a7342cSJosef Bacik err = PTR_ERR(trans); 287a4553fefSAnand Jain btrfs_std_error(tree_root->fs_info, err, 28868a7342cSJosef Bacik "Failed to start trans to delete " 28968a7342cSJosef Bacik "orphan item"); 29068a7342cSJosef Bacik break; 29168a7342cSJosef Bacik } 29268a7342cSJosef Bacik err = btrfs_del_orphan_item(trans, tree_root, 29368a7342cSJosef Bacik root_key.objectid); 29468a7342cSJosef Bacik btrfs_end_transaction(trans, tree_root); 29568a7342cSJosef Bacik if (err) { 296a4553fefSAnand Jain btrfs_std_error(tree_root->fs_info, err, 29768a7342cSJosef Bacik "Failed to delete root orphan " 29868a7342cSJosef Bacik "item"); 29968a7342cSJosef Bacik break; 30068a7342cSJosef Bacik } 30168a7342cSJosef Bacik continue; 30276dda93cSYan, Zheng } 30376dda93cSYan, Zheng 304cb517eabSMiao Xie err = btrfs_init_fs_root(root); 305cb517eabSMiao Xie if (err) { 306cb517eabSMiao Xie btrfs_free_fs_root(root); 307cb517eabSMiao Xie break; 308cb517eabSMiao Xie } 309cb517eabSMiao Xie 31027cdeb70SMiao Xie set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state); 311cb517eabSMiao Xie 312cb517eabSMiao Xie err = btrfs_insert_fs_root(root->fs_info, root); 313909c3a22SFilipe Manana /* 314909c3a22SFilipe Manana * The root might have been inserted already, as before we look 315909c3a22SFilipe Manana * for orphan roots, log replay might have happened, which 316909c3a22SFilipe Manana * triggers a transaction commit and qgroup accounting, which 317909c3a22SFilipe Manana * in turn reads and inserts fs roots while doing backref 318909c3a22SFilipe Manana * walking. 319909c3a22SFilipe Manana */ 320909c3a22SFilipe Manana if (err == -EEXIST) 321909c3a22SFilipe Manana err = 0; 322cb517eabSMiao Xie if (err) { 323cb517eabSMiao Xie btrfs_free_fs_root(root); 324d68fc57bSYan, Zheng break; 325d68fc57bSYan, Zheng } 32614927d95SMiao Xie 32714927d95SMiao Xie if (btrfs_root_refs(&root->root_item) == 0) 32814927d95SMiao Xie btrfs_add_dead_root(root); 32976dda93cSYan, Zheng } 33076dda93cSYan, Zheng 33176dda93cSYan, Zheng btrfs_free_path(path); 33276dda93cSYan, Zheng return err; 33376dda93cSYan, Zheng } 33476dda93cSYan, Zheng 335d352ac68SChris Mason /* drop the root item for 'key' from 'root' */ 336e089f05cSChris Mason int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, 337e089f05cSChris Mason struct btrfs_key *key) 3383768f368SChris Mason { 3395caf2a00SChris Mason struct btrfs_path *path; 3403768f368SChris Mason int ret; 3413768f368SChris Mason 3425caf2a00SChris Mason path = btrfs_alloc_path(); 343db5b493aSTsutomu Itoh if (!path) 344db5b493aSTsutomu Itoh return -ENOMEM; 3455caf2a00SChris Mason ret = btrfs_search_slot(trans, root, key, path, -1, 1); 3463768f368SChris Mason if (ret < 0) 3473768f368SChris Mason goto out; 348edbd8d4eSChris Mason 3493768f368SChris Mason BUG_ON(ret != 0); 350c5739bbaSChris Mason 3515caf2a00SChris Mason ret = btrfs_del_item(trans, root, path); 3523768f368SChris Mason out: 3535caf2a00SChris Mason btrfs_free_path(path); 3543768f368SChris Mason return ret; 3553768f368SChris Mason } 3560660b5afSChris Mason 3570660b5afSChris Mason int btrfs_del_root_ref(struct btrfs_trans_handle *trans, 3580660b5afSChris Mason struct btrfs_root *tree_root, 3594df27c4dSYan, Zheng u64 root_id, u64 ref_id, u64 dirid, u64 *sequence, 3604df27c4dSYan, Zheng const char *name, int name_len) 3614df27c4dSYan, Zheng 3620660b5afSChris Mason { 3630660b5afSChris Mason struct btrfs_path *path; 3644df27c4dSYan, Zheng struct btrfs_root_ref *ref; 3654df27c4dSYan, Zheng struct extent_buffer *leaf; 3664df27c4dSYan, Zheng struct btrfs_key key; 3674df27c4dSYan, Zheng unsigned long ptr; 3684df27c4dSYan, Zheng int err = 0; 3694df27c4dSYan, Zheng int ret; 3700660b5afSChris Mason 3710660b5afSChris Mason path = btrfs_alloc_path(); 3724df27c4dSYan, Zheng if (!path) 3734df27c4dSYan, Zheng return -ENOMEM; 3740660b5afSChris Mason 3750660b5afSChris Mason key.objectid = root_id; 3764df27c4dSYan, Zheng key.type = BTRFS_ROOT_BACKREF_KEY; 3770660b5afSChris Mason key.offset = ref_id; 3784df27c4dSYan, Zheng again: 3790660b5afSChris Mason ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); 3804df27c4dSYan, Zheng BUG_ON(ret < 0); 3814df27c4dSYan, Zheng if (ret == 0) { 3824df27c4dSYan, Zheng leaf = path->nodes[0]; 3834df27c4dSYan, Zheng ref = btrfs_item_ptr(leaf, path->slots[0], 3844df27c4dSYan, Zheng struct btrfs_root_ref); 3854df27c4dSYan, Zheng 3864df27c4dSYan, Zheng WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid); 3874df27c4dSYan, Zheng WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len); 3884df27c4dSYan, Zheng ptr = (unsigned long)(ref + 1); 3894df27c4dSYan, Zheng WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len)); 3904df27c4dSYan, Zheng *sequence = btrfs_root_ref_sequence(leaf, ref); 3910660b5afSChris Mason 3920660b5afSChris Mason ret = btrfs_del_item(trans, tree_root, path); 39365a246c5STsutomu Itoh if (ret) { 39465a246c5STsutomu Itoh err = ret; 39565a246c5STsutomu Itoh goto out; 39665a246c5STsutomu Itoh } 3974df27c4dSYan, Zheng } else 3984df27c4dSYan, Zheng err = -ENOENT; 3994df27c4dSYan, Zheng 4004df27c4dSYan, Zheng if (key.type == BTRFS_ROOT_BACKREF_KEY) { 401b3b4aa74SDavid Sterba btrfs_release_path(path); 4024df27c4dSYan, Zheng key.objectid = ref_id; 4034df27c4dSYan, Zheng key.type = BTRFS_ROOT_REF_KEY; 4044df27c4dSYan, Zheng key.offset = root_id; 4054df27c4dSYan, Zheng goto again; 4064df27c4dSYan, Zheng } 4070660b5afSChris Mason 40865a246c5STsutomu Itoh out: 4090660b5afSChris Mason btrfs_free_path(path); 4104df27c4dSYan, Zheng return err; 4110660b5afSChris Mason } 4120660b5afSChris Mason 4130660b5afSChris Mason /* 4140660b5afSChris Mason * add a btrfs_root_ref item. type is either BTRFS_ROOT_REF_KEY 4150660b5afSChris Mason * or BTRFS_ROOT_BACKREF_KEY. 4160660b5afSChris Mason * 4170660b5afSChris Mason * The dirid, sequence, name and name_len refer to the directory entry 4180660b5afSChris Mason * that is referencing the root. 4190660b5afSChris Mason * 4200660b5afSChris Mason * For a forward ref, the root_id is the id of the tree referencing 4210660b5afSChris Mason * the root and ref_id is the id of the subvol or snapshot. 4220660b5afSChris Mason * 4230660b5afSChris Mason * For a back ref the root_id is the id of the subvol or snapshot and 4240660b5afSChris Mason * ref_id is the id of the tree referencing it. 42579787eaaSJeff Mahoney * 42679787eaaSJeff Mahoney * Will return 0, -ENOMEM, or anything from the CoW path 4270660b5afSChris Mason */ 4280660b5afSChris Mason int btrfs_add_root_ref(struct btrfs_trans_handle *trans, 4290660b5afSChris Mason struct btrfs_root *tree_root, 4304df27c4dSYan, Zheng u64 root_id, u64 ref_id, u64 dirid, u64 sequence, 4310660b5afSChris Mason const char *name, int name_len) 4320660b5afSChris Mason { 4330660b5afSChris Mason struct btrfs_key key; 4340660b5afSChris Mason int ret; 4350660b5afSChris Mason struct btrfs_path *path; 4360660b5afSChris Mason struct btrfs_root_ref *ref; 4370660b5afSChris Mason struct extent_buffer *leaf; 4380660b5afSChris Mason unsigned long ptr; 4390660b5afSChris Mason 4400660b5afSChris Mason path = btrfs_alloc_path(); 4414df27c4dSYan, Zheng if (!path) 4424df27c4dSYan, Zheng return -ENOMEM; 4430660b5afSChris Mason 4440660b5afSChris Mason key.objectid = root_id; 4454df27c4dSYan, Zheng key.type = BTRFS_ROOT_BACKREF_KEY; 4460660b5afSChris Mason key.offset = ref_id; 4474df27c4dSYan, Zheng again: 4480660b5afSChris Mason ret = btrfs_insert_empty_item(trans, tree_root, path, &key, 4490660b5afSChris Mason sizeof(*ref) + name_len); 45079787eaaSJeff Mahoney if (ret) { 45179787eaaSJeff Mahoney btrfs_abort_transaction(trans, tree_root, ret); 45279787eaaSJeff Mahoney btrfs_free_path(path); 45379787eaaSJeff Mahoney return ret; 45479787eaaSJeff Mahoney } 4550660b5afSChris Mason 4560660b5afSChris Mason leaf = path->nodes[0]; 4570660b5afSChris Mason ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref); 4580660b5afSChris Mason btrfs_set_root_ref_dirid(leaf, ref, dirid); 4590660b5afSChris Mason btrfs_set_root_ref_sequence(leaf, ref, sequence); 4600660b5afSChris Mason btrfs_set_root_ref_name_len(leaf, ref, name_len); 4610660b5afSChris Mason ptr = (unsigned long)(ref + 1); 4620660b5afSChris Mason write_extent_buffer(leaf, name, ptr, name_len); 4630660b5afSChris Mason btrfs_mark_buffer_dirty(leaf); 4640660b5afSChris Mason 4654df27c4dSYan, Zheng if (key.type == BTRFS_ROOT_BACKREF_KEY) { 466b3b4aa74SDavid Sterba btrfs_release_path(path); 4674df27c4dSYan, Zheng key.objectid = ref_id; 4684df27c4dSYan, Zheng key.type = BTRFS_ROOT_REF_KEY; 4694df27c4dSYan, Zheng key.offset = root_id; 4704df27c4dSYan, Zheng goto again; 4714df27c4dSYan, Zheng } 4724df27c4dSYan, Zheng 4730660b5afSChris Mason btrfs_free_path(path); 4744df27c4dSYan, Zheng return 0; 4750660b5afSChris Mason } 47608fe4db1SLi Zefan 47708fe4db1SLi Zefan /* 47808fe4db1SLi Zefan * Old btrfs forgets to init root_item->flags and root_item->byte_limit 47908fe4db1SLi Zefan * for subvolumes. To work around this problem, we steal a bit from 48008fe4db1SLi Zefan * root_item->inode_item->flags, and use it to indicate if those fields 48108fe4db1SLi Zefan * have been properly initialized. 48208fe4db1SLi Zefan */ 48308fe4db1SLi Zefan void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item) 48408fe4db1SLi Zefan { 4853cae210fSQu Wenruo u64 inode_flags = btrfs_stack_inode_flags(&root_item->inode); 48608fe4db1SLi Zefan 48708fe4db1SLi Zefan if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) { 48808fe4db1SLi Zefan inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT; 4893cae210fSQu Wenruo btrfs_set_stack_inode_flags(&root_item->inode, inode_flags); 4903cae210fSQu Wenruo btrfs_set_root_flags(root_item, 0); 4913cae210fSQu Wenruo btrfs_set_root_limit(root_item, 0); 49208fe4db1SLi Zefan } 49308fe4db1SLi Zefan } 4948ea05e3aSAlexander Block 4958ea05e3aSAlexander Block void btrfs_update_root_times(struct btrfs_trans_handle *trans, 4968ea05e3aSAlexander Block struct btrfs_root *root) 4978ea05e3aSAlexander Block { 4988ea05e3aSAlexander Block struct btrfs_root_item *item = &root->root_item; 49904b285f3SDeepa Dinamani struct timespec ct = current_fs_time(root->fs_info->sb); 5008ea05e3aSAlexander Block 5015f3ab90aSAnand Jain spin_lock(&root->root_item_lock); 5023cae210fSQu Wenruo btrfs_set_root_ctransid(item, trans->transid); 5033cae210fSQu Wenruo btrfs_set_stack_timespec_sec(&item->ctime, ct.tv_sec); 5043cae210fSQu Wenruo btrfs_set_stack_timespec_nsec(&item->ctime, ct.tv_nsec); 5055f3ab90aSAnand Jain spin_unlock(&root->root_item_lock); 5068ea05e3aSAlexander Block } 507