xref: /linux/fs/btrfs/root-tree.c (revision 5eda7b5e9b0bed864dd18284c7df9b3c8207dad7)
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