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 193768f368SChris Mason #include "ctree.h" 205eda7b5eSChris Mason #include "transaction.h" 213768f368SChris Mason #include "disk-io.h" 223768f368SChris Mason #include "print-tree.h" 233768f368SChris Mason 24bf4ef679SChris Mason /* 25d352ac68SChris Mason * lookup the root with the highest offset for a given objectid. The key we do 26d352ac68SChris Mason * find is copied into 'key'. If we find something return 0, otherwise 1, < 0 27d352ac68SChris Mason * on error. 28d352ac68SChris Mason */ 293768f368SChris Mason int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, 303768f368SChris Mason struct btrfs_root_item *item, struct btrfs_key *key) 313768f368SChris Mason { 325caf2a00SChris Mason struct btrfs_path *path; 333768f368SChris Mason struct btrfs_key search_key; 345f39d397SChris Mason struct btrfs_key found_key; 355f39d397SChris Mason struct extent_buffer *l; 363768f368SChris Mason int ret; 373768f368SChris Mason int slot; 383768f368SChris Mason 393768f368SChris Mason search_key.objectid = objectid; 400660b5afSChris Mason search_key.type = BTRFS_ROOT_ITEM_KEY; 415eda7b5eSChris Mason search_key.offset = (u64)-1; 423768f368SChris Mason 435caf2a00SChris Mason path = btrfs_alloc_path(); 44db5b493aSTsutomu Itoh if (!path) 45db5b493aSTsutomu Itoh return -ENOMEM; 465caf2a00SChris Mason ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); 473768f368SChris Mason if (ret < 0) 483768f368SChris Mason goto out; 495f39d397SChris Mason 503768f368SChris Mason BUG_ON(ret == 0); 5176dda93cSYan, Zheng if (path->slots[0] == 0) { 523768f368SChris Mason ret = 1; 533768f368SChris Mason goto out; 543768f368SChris Mason } 5576dda93cSYan, Zheng l = path->nodes[0]; 5676dda93cSYan, Zheng slot = path->slots[0] - 1; 5776dda93cSYan, Zheng btrfs_item_key_to_cpu(l, &found_key, slot); 5876dda93cSYan, Zheng if (found_key.objectid != objectid || 5976dda93cSYan, Zheng found_key.type != BTRFS_ROOT_ITEM_KEY) { 6076dda93cSYan, Zheng ret = 1; 6176dda93cSYan, Zheng goto out; 6276dda93cSYan, Zheng } 6376dda93cSYan, Zheng if (item) 645f39d397SChris Mason read_extent_buffer(l, item, btrfs_item_ptr_offset(l, slot), 653768f368SChris Mason sizeof(*item)); 6676dda93cSYan, Zheng if (key) 675f39d397SChris Mason memcpy(key, &found_key, sizeof(found_key)); 683768f368SChris Mason ret = 0; 693768f368SChris Mason out: 705caf2a00SChris Mason btrfs_free_path(path); 713768f368SChris Mason return ret; 723768f368SChris Mason } 733768f368SChris Mason 74*bf5f32ecSMark Fasheh void btrfs_set_root_node(struct btrfs_root_item *item, 755d4f98a2SYan Zheng struct extent_buffer *node) 765d4f98a2SYan Zheng { 775d4f98a2SYan Zheng btrfs_set_root_bytenr(item, node->start); 785d4f98a2SYan Zheng btrfs_set_root_level(item, btrfs_header_level(node)); 795d4f98a2SYan Zheng btrfs_set_root_generation(item, btrfs_header_generation(node)); 805d4f98a2SYan Zheng } 815d4f98a2SYan Zheng 82d352ac68SChris Mason /* 83d352ac68SChris Mason * copy the data in 'item' into the btree 84d352ac68SChris Mason */ 85e089f05cSChris Mason int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root 86e089f05cSChris Mason *root, struct btrfs_key *key, struct btrfs_root_item 87e089f05cSChris Mason *item) 883768f368SChris Mason { 895caf2a00SChris Mason struct btrfs_path *path; 905f39d397SChris Mason struct extent_buffer *l; 913768f368SChris Mason int ret; 923768f368SChris Mason int slot; 935f39d397SChris Mason unsigned long ptr; 943768f368SChris Mason 955caf2a00SChris Mason path = btrfs_alloc_path(); 965caf2a00SChris Mason BUG_ON(!path); 975caf2a00SChris Mason ret = btrfs_search_slot(trans, root, key, path, 0, 1); 983768f368SChris Mason if (ret < 0) 993768f368SChris Mason goto out; 100d6667462SChris Mason 101d6667462SChris Mason if (ret != 0) { 102d6667462SChris Mason btrfs_print_leaf(root, path->nodes[0]); 103d397712bSChris Mason printk(KERN_CRIT "unable to update root key %llu %u %llu\n", 104d397712bSChris Mason (unsigned long long)key->objectid, key->type, 105d397712bSChris Mason (unsigned long long)key->offset); 106d6667462SChris Mason BUG_ON(1); 107d6667462SChris Mason } 108d6667462SChris Mason 1095f39d397SChris Mason l = path->nodes[0]; 1105caf2a00SChris Mason slot = path->slots[0]; 1115f39d397SChris Mason ptr = btrfs_item_ptr_offset(l, slot); 1125f39d397SChris Mason write_extent_buffer(l, item, ptr, sizeof(*item)); 1135caf2a00SChris Mason btrfs_mark_buffer_dirty(path->nodes[0]); 1143768f368SChris Mason out: 1155caf2a00SChris Mason btrfs_free_path(path); 1163768f368SChris Mason return ret; 1173768f368SChris Mason } 1183768f368SChris Mason 119e089f05cSChris Mason int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root 120e089f05cSChris Mason *root, struct btrfs_key *key, struct btrfs_root_item 121e089f05cSChris Mason *item) 1223768f368SChris Mason { 1233768f368SChris Mason int ret; 124e089f05cSChris Mason ret = btrfs_insert_item(trans, root, key, item, sizeof(*item)); 1253768f368SChris Mason return ret; 1263768f368SChris Mason } 1273768f368SChris Mason 128d352ac68SChris Mason /* 129d352ac68SChris Mason * at mount time we want to find all the old transaction snapshots that were in 130d397712bSChris Mason * the process of being deleted if we crashed. This is any root item with an 131d397712bSChris Mason * offset lower than the latest root. They need to be queued for deletion to 132d397712bSChris Mason * finish what was happening when we crashed. 133d352ac68SChris Mason */ 1345d4f98a2SYan Zheng int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid) 1355eda7b5eSChris Mason { 1365eda7b5eSChris Mason struct btrfs_root *dead_root; 1375eda7b5eSChris Mason struct btrfs_root_item *ri; 1385eda7b5eSChris Mason struct btrfs_key key; 139a7a16fd7SChris Mason struct btrfs_key found_key; 1405eda7b5eSChris Mason struct btrfs_path *path; 1415eda7b5eSChris Mason int ret; 1425eda7b5eSChris Mason u32 nritems; 1435f39d397SChris Mason struct extent_buffer *leaf; 1445eda7b5eSChris Mason int slot; 1455eda7b5eSChris Mason 1465ce14bbcSChris Mason key.objectid = objectid; 1475eda7b5eSChris Mason btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); 1485eda7b5eSChris Mason key.offset = 0; 1495eda7b5eSChris Mason path = btrfs_alloc_path(); 1505eda7b5eSChris Mason if (!path) 1515eda7b5eSChris Mason return -ENOMEM; 152a7a16fd7SChris Mason 153a7a16fd7SChris Mason again: 1545eda7b5eSChris Mason ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 1555eda7b5eSChris Mason if (ret < 0) 1565eda7b5eSChris Mason goto err; 1575eda7b5eSChris Mason while (1) { 1585f39d397SChris Mason leaf = path->nodes[0]; 1595f39d397SChris Mason nritems = btrfs_header_nritems(leaf); 1605eda7b5eSChris Mason slot = path->slots[0]; 1615eda7b5eSChris Mason if (slot >= nritems) { 1625eda7b5eSChris Mason ret = btrfs_next_leaf(root, path); 1635eda7b5eSChris Mason if (ret) 1645eda7b5eSChris Mason break; 1655f39d397SChris Mason leaf = path->nodes[0]; 1665f39d397SChris Mason nritems = btrfs_header_nritems(leaf); 1675eda7b5eSChris Mason slot = path->slots[0]; 1685eda7b5eSChris Mason } 1695f39d397SChris Mason btrfs_item_key_to_cpu(leaf, &key, slot); 1705eda7b5eSChris Mason if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY) 1715eda7b5eSChris Mason goto next; 1725ce14bbcSChris Mason 1735ce14bbcSChris Mason if (key.objectid < objectid) 1745ce14bbcSChris Mason goto next; 1755ce14bbcSChris Mason 1765ce14bbcSChris Mason if (key.objectid > objectid) 1775ce14bbcSChris Mason break; 1785ce14bbcSChris Mason 1795eda7b5eSChris Mason ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item); 1805f39d397SChris Mason if (btrfs_disk_root_refs(leaf, ri) != 0) 1815eda7b5eSChris Mason goto next; 1825ce14bbcSChris Mason 183a7a16fd7SChris Mason memcpy(&found_key, &key, sizeof(key)); 184a7a16fd7SChris Mason key.offset++; 185b3b4aa74SDavid Sterba btrfs_release_path(path); 186e02119d5SChris Mason dead_root = 187e02119d5SChris Mason btrfs_read_fs_root_no_radix(root->fs_info->tree_root, 188a7a16fd7SChris Mason &found_key); 189a1f39630SAneesh if (IS_ERR(dead_root)) { 190a1f39630SAneesh ret = PTR_ERR(dead_root); 1915eda7b5eSChris Mason goto err; 1925eda7b5eSChris Mason } 1935ce14bbcSChris Mason 1945d4f98a2SYan Zheng ret = btrfs_add_dead_root(dead_root); 1955eda7b5eSChris Mason if (ret) 1965eda7b5eSChris Mason goto err; 197a7a16fd7SChris Mason goto again; 1985eda7b5eSChris Mason next: 1995eda7b5eSChris Mason slot++; 2005eda7b5eSChris Mason path->slots[0]++; 2015eda7b5eSChris Mason } 2025eda7b5eSChris Mason ret = 0; 2035eda7b5eSChris Mason err: 2045eda7b5eSChris Mason btrfs_free_path(path); 2055eda7b5eSChris Mason return ret; 2065eda7b5eSChris Mason } 2075eda7b5eSChris Mason 20876dda93cSYan, Zheng int btrfs_find_orphan_roots(struct btrfs_root *tree_root) 20976dda93cSYan, Zheng { 21076dda93cSYan, Zheng struct extent_buffer *leaf; 21176dda93cSYan, Zheng struct btrfs_path *path; 21276dda93cSYan, Zheng struct btrfs_key key; 213d68fc57bSYan, Zheng struct btrfs_key root_key; 214d68fc57bSYan, Zheng struct btrfs_root *root; 21576dda93cSYan, Zheng int err = 0; 21676dda93cSYan, Zheng int ret; 21776dda93cSYan, Zheng 21876dda93cSYan, Zheng path = btrfs_alloc_path(); 21976dda93cSYan, Zheng if (!path) 22076dda93cSYan, Zheng return -ENOMEM; 22176dda93cSYan, Zheng 22276dda93cSYan, Zheng key.objectid = BTRFS_ORPHAN_OBJECTID; 22376dda93cSYan, Zheng key.type = BTRFS_ORPHAN_ITEM_KEY; 22476dda93cSYan, Zheng key.offset = 0; 22576dda93cSYan, Zheng 226d68fc57bSYan, Zheng root_key.type = BTRFS_ROOT_ITEM_KEY; 227d68fc57bSYan, Zheng root_key.offset = (u64)-1; 228d68fc57bSYan, Zheng 22976dda93cSYan, Zheng while (1) { 23076dda93cSYan, Zheng ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0); 23176dda93cSYan, Zheng if (ret < 0) { 23276dda93cSYan, Zheng err = ret; 23376dda93cSYan, Zheng break; 23476dda93cSYan, Zheng } 23576dda93cSYan, Zheng 23676dda93cSYan, Zheng leaf = path->nodes[0]; 23776dda93cSYan, Zheng if (path->slots[0] >= btrfs_header_nritems(leaf)) { 23876dda93cSYan, Zheng ret = btrfs_next_leaf(tree_root, path); 23976dda93cSYan, Zheng if (ret < 0) 24076dda93cSYan, Zheng err = ret; 24176dda93cSYan, Zheng if (ret != 0) 24276dda93cSYan, Zheng break; 24376dda93cSYan, Zheng leaf = path->nodes[0]; 24476dda93cSYan, Zheng } 24576dda93cSYan, Zheng 24676dda93cSYan, Zheng btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 247b3b4aa74SDavid Sterba btrfs_release_path(path); 24876dda93cSYan, Zheng 24976dda93cSYan, Zheng if (key.objectid != BTRFS_ORPHAN_OBJECTID || 25076dda93cSYan, Zheng key.type != BTRFS_ORPHAN_ITEM_KEY) 25176dda93cSYan, Zheng break; 25276dda93cSYan, Zheng 253d68fc57bSYan, Zheng root_key.objectid = key.offset; 254d68fc57bSYan, Zheng key.offset++; 255d68fc57bSYan, Zheng 256d68fc57bSYan, Zheng root = btrfs_read_fs_root_no_name(tree_root->fs_info, 257d68fc57bSYan, Zheng &root_key); 258d68fc57bSYan, Zheng if (!IS_ERR(root)) 259d68fc57bSYan, Zheng continue; 260d68fc57bSYan, Zheng 261d68fc57bSYan, Zheng ret = PTR_ERR(root); 262d68fc57bSYan, Zheng if (ret != -ENOENT) { 26376dda93cSYan, Zheng err = ret; 26476dda93cSYan, Zheng break; 26576dda93cSYan, Zheng } 26676dda93cSYan, Zheng 267d68fc57bSYan, Zheng ret = btrfs_find_dead_roots(tree_root, root_key.objectid); 268d68fc57bSYan, Zheng if (ret) { 269d68fc57bSYan, Zheng err = ret; 270d68fc57bSYan, Zheng break; 271d68fc57bSYan, Zheng } 27276dda93cSYan, Zheng } 27376dda93cSYan, Zheng 27476dda93cSYan, Zheng btrfs_free_path(path); 27576dda93cSYan, Zheng return err; 27676dda93cSYan, Zheng } 27776dda93cSYan, Zheng 278d352ac68SChris Mason /* drop the root item for 'key' from 'root' */ 279e089f05cSChris Mason int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, 280e089f05cSChris Mason struct btrfs_key *key) 2813768f368SChris Mason { 2825caf2a00SChris Mason struct btrfs_path *path; 2833768f368SChris Mason int ret; 284c5739bbaSChris Mason struct btrfs_root_item *ri; 2855f39d397SChris Mason struct extent_buffer *leaf; 2863768f368SChris Mason 2875caf2a00SChris Mason path = btrfs_alloc_path(); 288db5b493aSTsutomu Itoh if (!path) 289db5b493aSTsutomu Itoh return -ENOMEM; 2905caf2a00SChris Mason ret = btrfs_search_slot(trans, root, key, path, -1, 1); 2913768f368SChris Mason if (ret < 0) 2923768f368SChris Mason goto out; 293edbd8d4eSChris Mason 2943768f368SChris Mason BUG_ON(ret != 0); 2955f39d397SChris Mason leaf = path->nodes[0]; 2965f39d397SChris Mason ri = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_item); 297c5739bbaSChris Mason 2985caf2a00SChris Mason ret = btrfs_del_item(trans, root, path); 2993768f368SChris Mason out: 3005caf2a00SChris Mason btrfs_free_path(path); 3013768f368SChris Mason return ret; 3023768f368SChris Mason } 3030660b5afSChris Mason 3040660b5afSChris Mason int btrfs_del_root_ref(struct btrfs_trans_handle *trans, 3050660b5afSChris Mason struct btrfs_root *tree_root, 3064df27c4dSYan, Zheng u64 root_id, u64 ref_id, u64 dirid, u64 *sequence, 3074df27c4dSYan, Zheng const char *name, int name_len) 3084df27c4dSYan, Zheng 3090660b5afSChris Mason { 3100660b5afSChris Mason struct btrfs_path *path; 3114df27c4dSYan, Zheng struct btrfs_root_ref *ref; 3124df27c4dSYan, Zheng struct extent_buffer *leaf; 3134df27c4dSYan, Zheng struct btrfs_key key; 3144df27c4dSYan, Zheng unsigned long ptr; 3154df27c4dSYan, Zheng int err = 0; 3164df27c4dSYan, Zheng int ret; 3170660b5afSChris Mason 3180660b5afSChris Mason path = btrfs_alloc_path(); 3194df27c4dSYan, Zheng if (!path) 3204df27c4dSYan, Zheng return -ENOMEM; 3210660b5afSChris Mason 3220660b5afSChris Mason key.objectid = root_id; 3234df27c4dSYan, Zheng key.type = BTRFS_ROOT_BACKREF_KEY; 3240660b5afSChris Mason key.offset = ref_id; 3254df27c4dSYan, Zheng again: 3260660b5afSChris Mason ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); 3274df27c4dSYan, Zheng BUG_ON(ret < 0); 3284df27c4dSYan, Zheng if (ret == 0) { 3294df27c4dSYan, Zheng leaf = path->nodes[0]; 3304df27c4dSYan, Zheng ref = btrfs_item_ptr(leaf, path->slots[0], 3314df27c4dSYan, Zheng struct btrfs_root_ref); 3324df27c4dSYan, Zheng 3334df27c4dSYan, Zheng WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid); 3344df27c4dSYan, Zheng WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len); 3354df27c4dSYan, Zheng ptr = (unsigned long)(ref + 1); 3364df27c4dSYan, Zheng WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len)); 3374df27c4dSYan, Zheng *sequence = btrfs_root_ref_sequence(leaf, ref); 3380660b5afSChris Mason 3390660b5afSChris Mason ret = btrfs_del_item(trans, tree_root, path); 34065a246c5STsutomu Itoh if (ret) { 34165a246c5STsutomu Itoh err = ret; 34265a246c5STsutomu Itoh goto out; 34365a246c5STsutomu Itoh } 3444df27c4dSYan, Zheng } else 3454df27c4dSYan, Zheng err = -ENOENT; 3464df27c4dSYan, Zheng 3474df27c4dSYan, Zheng if (key.type == BTRFS_ROOT_BACKREF_KEY) { 348b3b4aa74SDavid Sterba btrfs_release_path(path); 3494df27c4dSYan, Zheng key.objectid = ref_id; 3504df27c4dSYan, Zheng key.type = BTRFS_ROOT_REF_KEY; 3514df27c4dSYan, Zheng key.offset = root_id; 3524df27c4dSYan, Zheng goto again; 3534df27c4dSYan, Zheng } 3540660b5afSChris Mason 35565a246c5STsutomu Itoh out: 3560660b5afSChris Mason btrfs_free_path(path); 3574df27c4dSYan, Zheng return err; 3580660b5afSChris Mason } 3590660b5afSChris Mason 360ea9e8b11SChris Mason int btrfs_find_root_ref(struct btrfs_root *tree_root, 361ea9e8b11SChris Mason struct btrfs_path *path, 362ea9e8b11SChris Mason u64 root_id, u64 ref_id) 363ea9e8b11SChris Mason { 364ea9e8b11SChris Mason struct btrfs_key key; 365ea9e8b11SChris Mason int ret; 366ea9e8b11SChris Mason 367ea9e8b11SChris Mason key.objectid = root_id; 368ea9e8b11SChris Mason key.type = BTRFS_ROOT_REF_KEY; 369ea9e8b11SChris Mason key.offset = ref_id; 370ea9e8b11SChris Mason 371ea9e8b11SChris Mason ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0); 372ea9e8b11SChris Mason return ret; 373ea9e8b11SChris Mason } 374ea9e8b11SChris Mason 3750660b5afSChris Mason /* 3760660b5afSChris Mason * add a btrfs_root_ref item. type is either BTRFS_ROOT_REF_KEY 3770660b5afSChris Mason * or BTRFS_ROOT_BACKREF_KEY. 3780660b5afSChris Mason * 3790660b5afSChris Mason * The dirid, sequence, name and name_len refer to the directory entry 3800660b5afSChris Mason * that is referencing the root. 3810660b5afSChris Mason * 3820660b5afSChris Mason * For a forward ref, the root_id is the id of the tree referencing 3830660b5afSChris Mason * the root and ref_id is the id of the subvol or snapshot. 3840660b5afSChris Mason * 3850660b5afSChris Mason * For a back ref the root_id is the id of the subvol or snapshot and 3860660b5afSChris Mason * ref_id is the id of the tree referencing it. 3870660b5afSChris Mason */ 3880660b5afSChris Mason int btrfs_add_root_ref(struct btrfs_trans_handle *trans, 3890660b5afSChris Mason struct btrfs_root *tree_root, 3904df27c4dSYan, Zheng u64 root_id, u64 ref_id, u64 dirid, u64 sequence, 3910660b5afSChris Mason const char *name, int name_len) 3920660b5afSChris Mason { 3930660b5afSChris Mason struct btrfs_key key; 3940660b5afSChris Mason int ret; 3950660b5afSChris Mason struct btrfs_path *path; 3960660b5afSChris Mason struct btrfs_root_ref *ref; 3970660b5afSChris Mason struct extent_buffer *leaf; 3980660b5afSChris Mason unsigned long ptr; 3990660b5afSChris Mason 4000660b5afSChris Mason path = btrfs_alloc_path(); 4014df27c4dSYan, Zheng if (!path) 4024df27c4dSYan, Zheng return -ENOMEM; 4030660b5afSChris Mason 4040660b5afSChris Mason key.objectid = root_id; 4054df27c4dSYan, Zheng key.type = BTRFS_ROOT_BACKREF_KEY; 4060660b5afSChris Mason key.offset = ref_id; 4074df27c4dSYan, Zheng again: 4080660b5afSChris Mason ret = btrfs_insert_empty_item(trans, tree_root, path, &key, 4090660b5afSChris Mason sizeof(*ref) + name_len); 4100660b5afSChris Mason BUG_ON(ret); 4110660b5afSChris Mason 4120660b5afSChris Mason leaf = path->nodes[0]; 4130660b5afSChris Mason ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref); 4140660b5afSChris Mason btrfs_set_root_ref_dirid(leaf, ref, dirid); 4150660b5afSChris Mason btrfs_set_root_ref_sequence(leaf, ref, sequence); 4160660b5afSChris Mason btrfs_set_root_ref_name_len(leaf, ref, name_len); 4170660b5afSChris Mason ptr = (unsigned long)(ref + 1); 4180660b5afSChris Mason write_extent_buffer(leaf, name, ptr, name_len); 4190660b5afSChris Mason btrfs_mark_buffer_dirty(leaf); 4200660b5afSChris Mason 4214df27c4dSYan, Zheng if (key.type == BTRFS_ROOT_BACKREF_KEY) { 422b3b4aa74SDavid Sterba btrfs_release_path(path); 4234df27c4dSYan, Zheng key.objectid = ref_id; 4244df27c4dSYan, Zheng key.type = BTRFS_ROOT_REF_KEY; 4254df27c4dSYan, Zheng key.offset = root_id; 4264df27c4dSYan, Zheng goto again; 4274df27c4dSYan, Zheng } 4284df27c4dSYan, Zheng 4290660b5afSChris Mason btrfs_free_path(path); 4304df27c4dSYan, Zheng return 0; 4310660b5afSChris Mason } 43208fe4db1SLi Zefan 43308fe4db1SLi Zefan /* 43408fe4db1SLi Zefan * Old btrfs forgets to init root_item->flags and root_item->byte_limit 43508fe4db1SLi Zefan * for subvolumes. To work around this problem, we steal a bit from 43608fe4db1SLi Zefan * root_item->inode_item->flags, and use it to indicate if those fields 43708fe4db1SLi Zefan * have been properly initialized. 43808fe4db1SLi Zefan */ 43908fe4db1SLi Zefan void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item) 44008fe4db1SLi Zefan { 44108fe4db1SLi Zefan u64 inode_flags = le64_to_cpu(root_item->inode.flags); 44208fe4db1SLi Zefan 44308fe4db1SLi Zefan if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) { 44408fe4db1SLi Zefan inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT; 44508fe4db1SLi Zefan root_item->inode.flags = cpu_to_le64(inode_flags); 44608fe4db1SLi Zefan root_item->flags = 0; 44708fe4db1SLi Zefan root_item->byte_limit = 0; 44808fe4db1SLi Zefan } 44908fe4db1SLi Zefan } 450