diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-06-22 14:16:25 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-06-22 14:16:25 -0400 |
commit | 5eda7b5e9b0bed864dd18284c7df9b3c8207dad7 (patch) | |
tree | 9efe48de46e77f2b7b97a2ce3ee93c9da6451671 /fs/btrfs/root-tree.c | |
parent | 54aa1f4dfdacd60a19c4471220b24e581be6f774 (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.c | 75 |
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); |
54 | printk("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; |
54 | out: | 56 | out: |
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 | ||
98 | int 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 | } | ||
144 | printk("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; | ||
149 | next: | ||
150 | slot++; | ||
151 | path->slots[0]++; | ||
152 | } | ||
153 | ret = 0; | ||
154 | err: | ||
155 | btrfs_free_path(path); | ||
156 | return ret; | ||
157 | } | ||
158 | |||
96 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 159 | int 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 | } | ||
122 | out: | 179 | out: |
123 | btrfs_release_path(root, path); | 180 | btrfs_release_path(root, path); |
124 | btrfs_free_path(path); | 181 | btrfs_free_path(path); |