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 * search forward for a root, starting with objectid 'search_start' 26d352ac68SChris Mason * if a root key is found, the objectid we find is filled into 'found_objectid' 27d352ac68SChris Mason * and 0 is returned. < 0 is returned on error, 1 if there is nothing 28d352ac68SChris Mason * left in the tree. 29bf4ef679SChris Mason */ 30bf4ef679SChris Mason int btrfs_search_root(struct btrfs_root *root, u64 search_start, 31bf4ef679SChris Mason u64 *found_objectid) 32bf4ef679SChris Mason { 33bf4ef679SChris Mason struct btrfs_path *path; 34bf4ef679SChris Mason struct btrfs_key search_key; 35bf4ef679SChris Mason int ret; 36bf4ef679SChris Mason 37bf4ef679SChris Mason root = root->fs_info->tree_root; 38bf4ef679SChris Mason search_key.objectid = search_start; 39bf4ef679SChris Mason search_key.type = (u8)-1; 40bf4ef679SChris Mason search_key.offset = (u64)-1; 41bf4ef679SChris Mason 42bf4ef679SChris Mason path = btrfs_alloc_path(); 43bf4ef679SChris Mason BUG_ON(!path); 44bf4ef679SChris Mason again: 45bf4ef679SChris Mason ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); 46bf4ef679SChris Mason if (ret < 0) 47bf4ef679SChris Mason goto out; 48bf4ef679SChris Mason if (ret == 0) { 49bf4ef679SChris Mason ret = 1; 50bf4ef679SChris Mason goto out; 51bf4ef679SChris Mason } 52bf4ef679SChris Mason if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) { 53bf4ef679SChris Mason ret = btrfs_next_leaf(root, path); 54bf4ef679SChris Mason if (ret) 55bf4ef679SChris Mason goto out; 56bf4ef679SChris Mason } 57bf4ef679SChris Mason btrfs_item_key_to_cpu(path->nodes[0], &search_key, path->slots[0]); 58bf4ef679SChris Mason if (search_key.type != BTRFS_ROOT_ITEM_KEY) { 59bf4ef679SChris Mason search_key.offset++; 60bf4ef679SChris Mason btrfs_release_path(root, path); 61bf4ef679SChris Mason goto again; 62bf4ef679SChris Mason } 63bf4ef679SChris Mason ret = 0; 64bf4ef679SChris Mason *found_objectid = search_key.objectid; 65bf4ef679SChris Mason 66bf4ef679SChris Mason out: 67bf4ef679SChris Mason btrfs_free_path(path); 68bf4ef679SChris Mason return ret; 69bf4ef679SChris Mason } 70bf4ef679SChris Mason 71d352ac68SChris Mason /* 72d352ac68SChris Mason * lookup the root with the highest offset for a given objectid. The key we do 73d352ac68SChris Mason * find is copied into 'key'. If we find something return 0, otherwise 1, < 0 74d352ac68SChris Mason * on error. 75d352ac68SChris Mason */ 763768f368SChris Mason int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, 773768f368SChris Mason struct btrfs_root_item *item, struct btrfs_key *key) 783768f368SChris Mason { 795caf2a00SChris Mason struct btrfs_path *path; 803768f368SChris Mason struct btrfs_key search_key; 815f39d397SChris Mason struct btrfs_key found_key; 825f39d397SChris Mason struct extent_buffer *l; 833768f368SChris Mason int ret; 843768f368SChris Mason int slot; 853768f368SChris Mason 863768f368SChris Mason search_key.objectid = objectid; 870660b5afSChris Mason search_key.type = BTRFS_ROOT_ITEM_KEY; 885eda7b5eSChris Mason search_key.offset = (u64)-1; 893768f368SChris Mason 905caf2a00SChris Mason path = btrfs_alloc_path(); 915caf2a00SChris Mason BUG_ON(!path); 925caf2a00SChris Mason ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); 933768f368SChris Mason if (ret < 0) 943768f368SChris Mason goto out; 955f39d397SChris Mason 963768f368SChris Mason BUG_ON(ret == 0); 975f39d397SChris Mason l = path->nodes[0]; 985caf2a00SChris Mason BUG_ON(path->slots[0] == 0); 995caf2a00SChris Mason slot = path->slots[0] - 1; 1005f39d397SChris Mason btrfs_item_key_to_cpu(l, &found_key, slot); 1015f39d397SChris Mason if (found_key.objectid != objectid) { 1023768f368SChris Mason ret = 1; 1033768f368SChris Mason goto out; 1043768f368SChris Mason } 1055f39d397SChris Mason read_extent_buffer(l, item, btrfs_item_ptr_offset(l, slot), 1063768f368SChris Mason sizeof(*item)); 1075f39d397SChris Mason memcpy(key, &found_key, sizeof(found_key)); 1083768f368SChris Mason ret = 0; 1093768f368SChris Mason out: 1105caf2a00SChris Mason btrfs_free_path(path); 1113768f368SChris Mason return ret; 1123768f368SChris Mason } 1133768f368SChris Mason 114d352ac68SChris Mason /* 115d352ac68SChris Mason * copy the data in 'item' into the btree 116d352ac68SChris Mason */ 117e089f05cSChris Mason int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root 118e089f05cSChris Mason *root, struct btrfs_key *key, struct btrfs_root_item 119e089f05cSChris Mason *item) 1203768f368SChris Mason { 1215caf2a00SChris Mason struct btrfs_path *path; 1225f39d397SChris Mason struct extent_buffer *l; 1233768f368SChris Mason int ret; 1243768f368SChris Mason int slot; 1255f39d397SChris Mason unsigned long ptr; 1263768f368SChris Mason 1275caf2a00SChris Mason path = btrfs_alloc_path(); 1285caf2a00SChris Mason BUG_ON(!path); 1295caf2a00SChris Mason ret = btrfs_search_slot(trans, root, key, path, 0, 1); 1303768f368SChris Mason if (ret < 0) 1313768f368SChris Mason goto out; 132d6667462SChris Mason 133d6667462SChris Mason if (ret != 0) { 134d6667462SChris Mason btrfs_print_leaf(root, path->nodes[0]); 135d6667462SChris Mason printk("unable to update root key %Lu %u %Lu\n", 136d6667462SChris Mason key->objectid, key->type, key->offset); 137d6667462SChris Mason BUG_ON(1); 138d6667462SChris Mason } 139d6667462SChris Mason 1405f39d397SChris Mason l = path->nodes[0]; 1415caf2a00SChris Mason slot = path->slots[0]; 1425f39d397SChris Mason ptr = btrfs_item_ptr_offset(l, slot); 1435f39d397SChris Mason write_extent_buffer(l, item, ptr, sizeof(*item)); 1445caf2a00SChris Mason btrfs_mark_buffer_dirty(path->nodes[0]); 1453768f368SChris Mason out: 1465caf2a00SChris Mason btrfs_release_path(root, path); 1475caf2a00SChris Mason btrfs_free_path(path); 1483768f368SChris Mason return ret; 1493768f368SChris Mason } 1503768f368SChris Mason 151e089f05cSChris Mason int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root 152e089f05cSChris Mason *root, struct btrfs_key *key, struct btrfs_root_item 153e089f05cSChris Mason *item) 1543768f368SChris Mason { 1553768f368SChris Mason int ret; 156e089f05cSChris Mason ret = btrfs_insert_item(trans, root, key, item, sizeof(*item)); 1573768f368SChris Mason return ret; 1583768f368SChris Mason } 1593768f368SChris Mason 160d352ac68SChris Mason /* 161d352ac68SChris Mason * at mount time we want to find all the old transaction snapshots that were in 162d352ac68SChris Mason * the process of being deleted if we crashed. This is any root item with an offset 163d352ac68SChris Mason * lower than the latest root. They need to be queued for deletion to finish 164d352ac68SChris Mason * what was happening when we crashed. 165d352ac68SChris Mason */ 1665ce14bbcSChris Mason int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid, 1675ce14bbcSChris Mason struct btrfs_root *latest) 1685eda7b5eSChris Mason { 1695eda7b5eSChris Mason struct btrfs_root *dead_root; 1705eda7b5eSChris Mason struct btrfs_item *item; 1715eda7b5eSChris Mason struct btrfs_root_item *ri; 1725eda7b5eSChris Mason struct btrfs_key key; 173a7a16fd7SChris Mason struct btrfs_key found_key; 1745eda7b5eSChris Mason struct btrfs_path *path; 1755eda7b5eSChris Mason int ret; 1765eda7b5eSChris Mason u32 nritems; 1775f39d397SChris Mason struct extent_buffer *leaf; 1785eda7b5eSChris Mason int slot; 1795eda7b5eSChris Mason 1805ce14bbcSChris Mason key.objectid = objectid; 1815eda7b5eSChris Mason btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); 1825eda7b5eSChris Mason key.offset = 0; 1835eda7b5eSChris Mason path = btrfs_alloc_path(); 1845eda7b5eSChris Mason if (!path) 1855eda7b5eSChris Mason return -ENOMEM; 186a7a16fd7SChris Mason 187a7a16fd7SChris Mason again: 1885eda7b5eSChris Mason ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 1895eda7b5eSChris Mason if (ret < 0) 1905eda7b5eSChris Mason goto err; 1915eda7b5eSChris Mason while(1) { 1925f39d397SChris Mason leaf = path->nodes[0]; 1935f39d397SChris Mason nritems = btrfs_header_nritems(leaf); 1945eda7b5eSChris Mason slot = path->slots[0]; 1955eda7b5eSChris Mason if (slot >= nritems) { 1965eda7b5eSChris Mason ret = btrfs_next_leaf(root, path); 1975eda7b5eSChris Mason if (ret) 1985eda7b5eSChris Mason break; 1995f39d397SChris Mason leaf = path->nodes[0]; 2005f39d397SChris Mason nritems = btrfs_header_nritems(leaf); 2015eda7b5eSChris Mason slot = path->slots[0]; 2025eda7b5eSChris Mason } 2035f39d397SChris Mason item = btrfs_item_nr(leaf, slot); 2045f39d397SChris Mason btrfs_item_key_to_cpu(leaf, &key, slot); 2055eda7b5eSChris Mason if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY) 2065eda7b5eSChris Mason goto next; 2075ce14bbcSChris Mason 2085ce14bbcSChris Mason if (key.objectid < objectid) 2095ce14bbcSChris Mason goto next; 2105ce14bbcSChris Mason 2115ce14bbcSChris Mason if (key.objectid > objectid) 2125ce14bbcSChris Mason break; 2135ce14bbcSChris Mason 2145eda7b5eSChris Mason ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item); 2155f39d397SChris Mason if (btrfs_disk_root_refs(leaf, ri) != 0) 2165eda7b5eSChris Mason goto next; 2175ce14bbcSChris Mason 218a7a16fd7SChris Mason memcpy(&found_key, &key, sizeof(key)); 219a7a16fd7SChris Mason key.offset++; 220a7a16fd7SChris Mason btrfs_release_path(root, path); 221e02119d5SChris Mason dead_root = 222e02119d5SChris Mason btrfs_read_fs_root_no_radix(root->fs_info->tree_root, 223a7a16fd7SChris Mason &found_key); 224a1f39630SAneesh if (IS_ERR(dead_root)) { 225a1f39630SAneesh ret = PTR_ERR(dead_root); 2265eda7b5eSChris Mason goto err; 2275eda7b5eSChris Mason } 2285ce14bbcSChris Mason 2291a40e23bSZheng Yan if (objectid == BTRFS_TREE_RELOC_OBJECTID) 2301a40e23bSZheng Yan ret = btrfs_add_dead_reloc_root(dead_root); 2311a40e23bSZheng Yan else 232b48652c1SYan Zheng ret = btrfs_add_dead_root(dead_root, latest); 2335eda7b5eSChris Mason if (ret) 2345eda7b5eSChris Mason goto err; 235a7a16fd7SChris Mason goto again; 2365eda7b5eSChris Mason next: 2375eda7b5eSChris Mason slot++; 2385eda7b5eSChris Mason path->slots[0]++; 2395eda7b5eSChris Mason } 2405eda7b5eSChris Mason ret = 0; 2415eda7b5eSChris Mason err: 2425eda7b5eSChris Mason btrfs_free_path(path); 2435eda7b5eSChris Mason return ret; 2445eda7b5eSChris Mason } 2455eda7b5eSChris Mason 246d352ac68SChris Mason /* drop the root item for 'key' from 'root' */ 247e089f05cSChris Mason int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, 248e089f05cSChris Mason struct btrfs_key *key) 2493768f368SChris Mason { 2505caf2a00SChris Mason struct btrfs_path *path; 2513768f368SChris Mason int ret; 252c5739bbaSChris Mason u32 refs; 253c5739bbaSChris Mason struct btrfs_root_item *ri; 2545f39d397SChris Mason struct extent_buffer *leaf; 2553768f368SChris Mason 2565caf2a00SChris Mason path = btrfs_alloc_path(); 2575caf2a00SChris Mason BUG_ON(!path); 2585caf2a00SChris Mason ret = btrfs_search_slot(trans, root, key, path, -1, 1); 2593768f368SChris Mason if (ret < 0) 2603768f368SChris Mason goto out; 261edbd8d4eSChris Mason if (ret) { 262edbd8d4eSChris Mason btrfs_print_leaf(root, path->nodes[0]); 263edbd8d4eSChris Mason printk("failed to del %Lu %u %Lu\n", key->objectid, key->type, key->offset); 264edbd8d4eSChris Mason 265edbd8d4eSChris Mason } 2663768f368SChris Mason BUG_ON(ret != 0); 2675f39d397SChris Mason leaf = path->nodes[0]; 2685f39d397SChris Mason ri = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_item); 269c5739bbaSChris Mason 2705f39d397SChris Mason refs = btrfs_disk_root_refs(leaf, ri); 2715eda7b5eSChris Mason BUG_ON(refs != 0); 2725caf2a00SChris Mason ret = btrfs_del_item(trans, root, path); 2733768f368SChris Mason out: 2745caf2a00SChris Mason btrfs_release_path(root, path); 2755caf2a00SChris Mason btrfs_free_path(path); 2763768f368SChris Mason return ret; 2773768f368SChris Mason } 2780660b5afSChris Mason 2790660b5afSChris Mason int btrfs_del_root_ref(struct btrfs_trans_handle *trans, 2800660b5afSChris Mason struct btrfs_root *tree_root, 2810660b5afSChris Mason u64 root_id, u8 type, u64 ref_id) 2820660b5afSChris Mason { 2830660b5afSChris Mason struct btrfs_key key; 2840660b5afSChris Mason int ret; 2850660b5afSChris Mason struct btrfs_path *path; 2860660b5afSChris Mason 2870660b5afSChris Mason path = btrfs_alloc_path(); 2880660b5afSChris Mason 2890660b5afSChris Mason key.objectid = root_id; 2900660b5afSChris Mason key.type = type; 2910660b5afSChris Mason key.offset = ref_id; 2920660b5afSChris Mason 2930660b5afSChris Mason ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); 2940660b5afSChris Mason BUG_ON(ret); 2950660b5afSChris Mason 2960660b5afSChris Mason ret = btrfs_del_item(trans, tree_root, path); 2970660b5afSChris Mason BUG_ON(ret); 2980660b5afSChris Mason 2990660b5afSChris Mason btrfs_free_path(path); 3000660b5afSChris Mason return ret; 3010660b5afSChris Mason } 3020660b5afSChris Mason 303*ea9e8b11SChris Mason int btrfs_find_root_ref(struct btrfs_root *tree_root, 304*ea9e8b11SChris Mason struct btrfs_path *path, 305*ea9e8b11SChris Mason u64 root_id, u64 ref_id) 306*ea9e8b11SChris Mason { 307*ea9e8b11SChris Mason struct btrfs_key key; 308*ea9e8b11SChris Mason int ret; 309*ea9e8b11SChris Mason 310*ea9e8b11SChris Mason key.objectid = root_id; 311*ea9e8b11SChris Mason key.type = BTRFS_ROOT_REF_KEY; 312*ea9e8b11SChris Mason key.offset = ref_id; 313*ea9e8b11SChris Mason 314*ea9e8b11SChris Mason ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0); 315*ea9e8b11SChris Mason return ret; 316*ea9e8b11SChris Mason } 317*ea9e8b11SChris Mason 318*ea9e8b11SChris Mason 3190660b5afSChris Mason /* 3200660b5afSChris Mason * add a btrfs_root_ref item. type is either BTRFS_ROOT_REF_KEY 3210660b5afSChris Mason * or BTRFS_ROOT_BACKREF_KEY. 3220660b5afSChris Mason * 3230660b5afSChris Mason * The dirid, sequence, name and name_len refer to the directory entry 3240660b5afSChris Mason * that is referencing the root. 3250660b5afSChris Mason * 3260660b5afSChris Mason * For a forward ref, the root_id is the id of the tree referencing 3270660b5afSChris Mason * the root and ref_id is the id of the subvol or snapshot. 3280660b5afSChris Mason * 3290660b5afSChris Mason * For a back ref the root_id is the id of the subvol or snapshot and 3300660b5afSChris Mason * ref_id is the id of the tree referencing it. 3310660b5afSChris Mason */ 3320660b5afSChris Mason int btrfs_add_root_ref(struct btrfs_trans_handle *trans, 3330660b5afSChris Mason struct btrfs_root *tree_root, 3340660b5afSChris Mason u64 root_id, u8 type, u64 ref_id, 3350660b5afSChris Mason u64 dirid, u64 sequence, 3360660b5afSChris Mason const char *name, int name_len) 3370660b5afSChris Mason { 3380660b5afSChris Mason struct btrfs_key key; 3390660b5afSChris Mason int ret; 3400660b5afSChris Mason struct btrfs_path *path; 3410660b5afSChris Mason struct btrfs_root_ref *ref; 3420660b5afSChris Mason struct extent_buffer *leaf; 3430660b5afSChris Mason unsigned long ptr; 3440660b5afSChris Mason 3450660b5afSChris Mason 3460660b5afSChris Mason path = btrfs_alloc_path(); 3470660b5afSChris Mason 3480660b5afSChris Mason key.objectid = root_id; 3490660b5afSChris Mason key.type = type; 3500660b5afSChris Mason key.offset = ref_id; 3510660b5afSChris Mason 3520660b5afSChris Mason ret = btrfs_insert_empty_item(trans, tree_root, path, &key, 3530660b5afSChris Mason sizeof(*ref) + name_len); 3540660b5afSChris Mason BUG_ON(ret); 3550660b5afSChris Mason 3560660b5afSChris Mason leaf = path->nodes[0]; 3570660b5afSChris Mason ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref); 3580660b5afSChris Mason btrfs_set_root_ref_dirid(leaf, ref, dirid); 3590660b5afSChris Mason btrfs_set_root_ref_sequence(leaf, ref, sequence); 3600660b5afSChris Mason btrfs_set_root_ref_name_len(leaf, ref, name_len); 3610660b5afSChris Mason ptr = (unsigned long)(ref + 1); 3620660b5afSChris Mason write_extent_buffer(leaf, name, ptr, name_len); 3630660b5afSChris Mason btrfs_mark_buffer_dirty(leaf); 3640660b5afSChris Mason 3650660b5afSChris Mason btrfs_free_path(path); 3660660b5afSChris Mason return ret; 3670660b5afSChris Mason } 368