aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/root-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-06-22 14:16:25 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-06-22 14:16:25 -0400
commit5eda7b5e9b0bed864dd18284c7df9b3c8207dad7 (patch)
tree9efe48de46e77f2b7b97a2ce3ee93c9da6451671 /fs/btrfs/root-tree.c
parent54aa1f4dfdacd60a19c4471220b24e581be6f774 (diff)
Btrfs: Add the ability to find and remove dead roots after a crash.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/root-tree.c')
-rw-r--r--fs/btrfs/root-tree.c75
1 files changed, 66 insertions, 9 deletions
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index ac0fae7780ff..737e5a38d17e 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -18,6 +18,7 @@
18 18
19#include <linux/module.h> 19#include <linux/module.h>
20#include "ctree.h" 20#include "ctree.h"
21#include "transaction.h"
21#include "disk-io.h" 22#include "disk-io.h"
22#include "print-tree.h" 23#include "print-tree.h"
23 24
@@ -32,7 +33,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
32 33
33 search_key.objectid = objectid; 34 search_key.objectid = objectid;
34 search_key.flags = (u32)-1; 35 search_key.flags = (u32)-1;
35 search_key.offset = (u32)-1; 36 search_key.offset = (u64)-1;
36 37
37 path = btrfs_alloc_path(); 38 path = btrfs_alloc_path();
38 BUG_ON(!path); 39 BUG_ON(!path);
@@ -50,6 +51,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
50 memcpy(item, btrfs_item_ptr(l, slot, struct btrfs_root_item), 51 memcpy(item, btrfs_item_ptr(l, slot, struct btrfs_root_item),
51 sizeof(*item)); 52 sizeof(*item));
52 btrfs_disk_key_to_cpu(key, &l->items[slot].key); 53 btrfs_disk_key_to_cpu(key, &l->items[slot].key);
54printk("find last finds key %Lu %u %Lu slot %d search for obj %Lu\n", key->objectid, key->flags, key->offset, slot, objectid);
53 ret = 0; 55 ret = 0;
54out: 56out:
55 btrfs_release_path(root, path); 57 btrfs_release_path(root, path);
@@ -93,6 +95,67 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
93 return ret; 95 return ret;
94} 96}
95 97
98int btrfs_find_dead_roots(struct btrfs_root *root)
99{
100 struct btrfs_root *dead_root;
101 struct btrfs_item *item;
102 struct btrfs_root_item *ri;
103 struct btrfs_key key;
104 struct btrfs_path *path;
105 int ret;
106 u32 nritems;
107 struct btrfs_leaf *leaf;
108 int slot;
109
110 key.objectid = 0;
111 key.flags = 0;
112 btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
113 key.offset = 0;
114 path = btrfs_alloc_path();
115 if (!path)
116 return -ENOMEM;
117 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
118 if (ret < 0)
119 goto err;
120 while(1) {
121 leaf = btrfs_buffer_leaf(path->nodes[0]);
122 nritems = btrfs_header_nritems(&leaf->header);
123 slot = path->slots[0];
124 if (slot >= nritems) {
125 ret = btrfs_next_leaf(root, path);
126 if (ret)
127 break;
128 leaf = btrfs_buffer_leaf(path->nodes[0]);
129 nritems = btrfs_header_nritems(&leaf->header);
130 slot = path->slots[0];
131 }
132 item = leaf->items + slot;
133 btrfs_disk_key_to_cpu(&key, &item->key);
134 if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY)
135 goto next;
136 ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item);
137 if (btrfs_root_refs(ri) != 0)
138 goto next;
139 dead_root = btrfs_read_fs_root_no_radix(root->fs_info, &key);
140 if (IS_ERR(root)) {
141 ret = PTR_ERR(root);
142 goto err;
143 }
144printk("found dead root %Lu %u %Lu\n", key.objectid, key.flags, key.offset);
145 ret = btrfs_add_dead_root(dead_root,
146 &root->fs_info->dead_roots);
147 if (ret)
148 goto err;
149next:
150 slot++;
151 path->slots[0]++;
152 }
153 ret = 0;
154err:
155 btrfs_free_path(path);
156 return ret;
157}
158
96int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, 159int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
97 struct btrfs_key *key) 160 struct btrfs_key *key)
98{ 161{
@@ -111,14 +174,8 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
111 path->slots[0], struct btrfs_root_item); 174 path->slots[0], struct btrfs_root_item);
112 175
113 refs = btrfs_root_refs(ri); 176 refs = btrfs_root_refs(ri);
114 BUG_ON(refs == 0); 177 BUG_ON(refs != 0);
115 if (refs == 1) { 178 ret = btrfs_del_item(trans, root, path);
116 ret = btrfs_del_item(trans, root, path);
117 } else {
118 btrfs_set_root_refs(ri, refs - 1);
119 WARN_ON(1);
120 mark_buffer_dirty(path->nodes[0]);
121 }
122out: 179out:
123 btrfs_release_path(root, path); 180 btrfs_release_path(root, path);
124 btrfs_free_path(path); 181 btrfs_free_path(path);