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 192e635a27SChris Mason #include <linux/module.h> 203768f368SChris Mason #include "ctree.h" 21*5eda7b5eSChris Mason #include "transaction.h" 223768f368SChris Mason #include "disk-io.h" 233768f368SChris Mason #include "print-tree.h" 243768f368SChris Mason 253768f368SChris Mason int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, 263768f368SChris Mason struct btrfs_root_item *item, struct btrfs_key *key) 273768f368SChris Mason { 285caf2a00SChris Mason struct btrfs_path *path; 293768f368SChris Mason struct btrfs_key search_key; 303768f368SChris Mason struct btrfs_leaf *l; 313768f368SChris Mason int ret; 323768f368SChris Mason int slot; 333768f368SChris Mason 343768f368SChris Mason search_key.objectid = objectid; 353768f368SChris Mason search_key.flags = (u32)-1; 36*5eda7b5eSChris Mason search_key.offset = (u64)-1; 373768f368SChris Mason 385caf2a00SChris Mason path = btrfs_alloc_path(); 395caf2a00SChris Mason BUG_ON(!path); 405caf2a00SChris Mason ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); 413768f368SChris Mason if (ret < 0) 423768f368SChris Mason goto out; 433768f368SChris Mason BUG_ON(ret == 0); 445caf2a00SChris Mason l = btrfs_buffer_leaf(path->nodes[0]); 455caf2a00SChris Mason BUG_ON(path->slots[0] == 0); 465caf2a00SChris Mason slot = path->slots[0] - 1; 4762e2749eSChris Mason if (btrfs_disk_key_objectid(&l->items[slot].key) != objectid) { 483768f368SChris Mason ret = 1; 493768f368SChris Mason goto out; 503768f368SChris Mason } 51123abc88SChris Mason memcpy(item, btrfs_item_ptr(l, slot, struct btrfs_root_item), 523768f368SChris Mason sizeof(*item)); 533768f368SChris Mason btrfs_disk_key_to_cpu(key, &l->items[slot].key); 54*5eda7b5eSChris Mason printk("find last finds key %Lu %u %Lu slot %d search for obj %Lu\n", key->objectid, key->flags, key->offset, slot, objectid); 553768f368SChris Mason ret = 0; 563768f368SChris Mason out: 575caf2a00SChris Mason btrfs_release_path(root, path); 585caf2a00SChris Mason btrfs_free_path(path); 593768f368SChris Mason return ret; 603768f368SChris Mason } 613768f368SChris Mason 62e089f05cSChris Mason int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root 63e089f05cSChris Mason *root, struct btrfs_key *key, struct btrfs_root_item 64e089f05cSChris Mason *item) 653768f368SChris Mason { 665caf2a00SChris Mason struct btrfs_path *path; 673768f368SChris Mason struct btrfs_leaf *l; 683768f368SChris Mason int ret; 693768f368SChris Mason int slot; 70d6025579SChris Mason struct btrfs_root_item *update_item; 713768f368SChris Mason 725caf2a00SChris Mason path = btrfs_alloc_path(); 735caf2a00SChris Mason BUG_ON(!path); 745caf2a00SChris Mason ret = btrfs_search_slot(trans, root, key, path, 0, 1); 753768f368SChris Mason if (ret < 0) 763768f368SChris Mason goto out; 773768f368SChris Mason BUG_ON(ret != 0); 785caf2a00SChris Mason l = btrfs_buffer_leaf(path->nodes[0]); 795caf2a00SChris Mason slot = path->slots[0]; 80d6025579SChris Mason update_item = btrfs_item_ptr(l, slot, struct btrfs_root_item); 81d6025579SChris Mason btrfs_memcpy(root, l, update_item, item, sizeof(*item)); 825caf2a00SChris Mason btrfs_mark_buffer_dirty(path->nodes[0]); 833768f368SChris Mason out: 845caf2a00SChris Mason btrfs_release_path(root, path); 855caf2a00SChris Mason btrfs_free_path(path); 863768f368SChris Mason return ret; 873768f368SChris Mason } 883768f368SChris Mason 89e089f05cSChris Mason int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root 90e089f05cSChris Mason *root, struct btrfs_key *key, struct btrfs_root_item 91e089f05cSChris Mason *item) 923768f368SChris Mason { 933768f368SChris Mason int ret; 94e089f05cSChris Mason ret = btrfs_insert_item(trans, root, key, item, sizeof(*item)); 953768f368SChris Mason return ret; 963768f368SChris Mason } 973768f368SChris Mason 98*5eda7b5eSChris Mason int btrfs_find_dead_roots(struct btrfs_root *root) 99*5eda7b5eSChris Mason { 100*5eda7b5eSChris Mason struct btrfs_root *dead_root; 101*5eda7b5eSChris Mason struct btrfs_item *item; 102*5eda7b5eSChris Mason struct btrfs_root_item *ri; 103*5eda7b5eSChris Mason struct btrfs_key key; 104*5eda7b5eSChris Mason struct btrfs_path *path; 105*5eda7b5eSChris Mason int ret; 106*5eda7b5eSChris Mason u32 nritems; 107*5eda7b5eSChris Mason struct btrfs_leaf *leaf; 108*5eda7b5eSChris Mason int slot; 109*5eda7b5eSChris Mason 110*5eda7b5eSChris Mason key.objectid = 0; 111*5eda7b5eSChris Mason key.flags = 0; 112*5eda7b5eSChris Mason btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); 113*5eda7b5eSChris Mason key.offset = 0; 114*5eda7b5eSChris Mason path = btrfs_alloc_path(); 115*5eda7b5eSChris Mason if (!path) 116*5eda7b5eSChris Mason return -ENOMEM; 117*5eda7b5eSChris Mason ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 118*5eda7b5eSChris Mason if (ret < 0) 119*5eda7b5eSChris Mason goto err; 120*5eda7b5eSChris Mason while(1) { 121*5eda7b5eSChris Mason leaf = btrfs_buffer_leaf(path->nodes[0]); 122*5eda7b5eSChris Mason nritems = btrfs_header_nritems(&leaf->header); 123*5eda7b5eSChris Mason slot = path->slots[0]; 124*5eda7b5eSChris Mason if (slot >= nritems) { 125*5eda7b5eSChris Mason ret = btrfs_next_leaf(root, path); 126*5eda7b5eSChris Mason if (ret) 127*5eda7b5eSChris Mason break; 128*5eda7b5eSChris Mason leaf = btrfs_buffer_leaf(path->nodes[0]); 129*5eda7b5eSChris Mason nritems = btrfs_header_nritems(&leaf->header); 130*5eda7b5eSChris Mason slot = path->slots[0]; 131*5eda7b5eSChris Mason } 132*5eda7b5eSChris Mason item = leaf->items + slot; 133*5eda7b5eSChris Mason btrfs_disk_key_to_cpu(&key, &item->key); 134*5eda7b5eSChris Mason if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY) 135*5eda7b5eSChris Mason goto next; 136*5eda7b5eSChris Mason ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item); 137*5eda7b5eSChris Mason if (btrfs_root_refs(ri) != 0) 138*5eda7b5eSChris Mason goto next; 139*5eda7b5eSChris Mason dead_root = btrfs_read_fs_root_no_radix(root->fs_info, &key); 140*5eda7b5eSChris Mason if (IS_ERR(root)) { 141*5eda7b5eSChris Mason ret = PTR_ERR(root); 142*5eda7b5eSChris Mason goto err; 143*5eda7b5eSChris Mason } 144*5eda7b5eSChris Mason printk("found dead root %Lu %u %Lu\n", key.objectid, key.flags, key.offset); 145*5eda7b5eSChris Mason ret = btrfs_add_dead_root(dead_root, 146*5eda7b5eSChris Mason &root->fs_info->dead_roots); 147*5eda7b5eSChris Mason if (ret) 148*5eda7b5eSChris Mason goto err; 149*5eda7b5eSChris Mason next: 150*5eda7b5eSChris Mason slot++; 151*5eda7b5eSChris Mason path->slots[0]++; 152*5eda7b5eSChris Mason } 153*5eda7b5eSChris Mason ret = 0; 154*5eda7b5eSChris Mason err: 155*5eda7b5eSChris Mason btrfs_free_path(path); 156*5eda7b5eSChris Mason return ret; 157*5eda7b5eSChris Mason } 158*5eda7b5eSChris Mason 159e089f05cSChris Mason int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, 160e089f05cSChris Mason struct btrfs_key *key) 1613768f368SChris Mason { 1625caf2a00SChris Mason struct btrfs_path *path; 1633768f368SChris Mason int ret; 164c5739bbaSChris Mason u32 refs; 165c5739bbaSChris Mason struct btrfs_root_item *ri; 1663768f368SChris Mason 1675caf2a00SChris Mason path = btrfs_alloc_path(); 1685caf2a00SChris Mason BUG_ON(!path); 1695caf2a00SChris Mason ret = btrfs_search_slot(trans, root, key, path, -1, 1); 1703768f368SChris Mason if (ret < 0) 1713768f368SChris Mason goto out; 1723768f368SChris Mason BUG_ON(ret != 0); 173c5739bbaSChris Mason ri = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), 174c5739bbaSChris Mason path->slots[0], struct btrfs_root_item); 175c5739bbaSChris Mason 176c5739bbaSChris Mason refs = btrfs_root_refs(ri); 177*5eda7b5eSChris Mason BUG_ON(refs != 0); 1785caf2a00SChris Mason ret = btrfs_del_item(trans, root, path); 1793768f368SChris Mason out: 1805caf2a00SChris Mason btrfs_release_path(root, path); 1815caf2a00SChris Mason btrfs_free_path(path); 1823768f368SChris Mason return ret; 1833768f368SChris Mason } 184