diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-22 12:13:20 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-22 12:13:20 -0400 |
commit | e20d96d64f9cf9288ffecc9ad4714e91c3b97ca8 (patch) | |
tree | fbe07d48bc7997226075169118ffa2a2e63f5d51 /fs/btrfs/extent-tree.c | |
parent | 2e635a278354a1a7951e16cfea4c247d6d0e7c99 (diff) |
Mountable btrfs, with readdir
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 144 |
1 files changed, 74 insertions, 70 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 53a7550b5c1e..e3af2c035687 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -10,9 +10,8 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
10 | search_end, struct btrfs_key *ins); | 10 | search_end, struct btrfs_key *ins); |
11 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct | 11 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct |
12 | btrfs_root *extent_root); | 12 | btrfs_root *extent_root); |
13 | static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root | 13 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct |
14 | *extent_root); | 14 | btrfs_root *extent_root); |
15 | |||
16 | /* | 15 | /* |
17 | * pending extents are blocks that we're trying to allocate in the extent | 16 | * pending extents are blocks that we're trying to allocate in the extent |
18 | * map while trying to grow the map because of other allocations. To avoid | 17 | * map while trying to grow the map because of other allocations. To avoid |
@@ -21,6 +20,7 @@ static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root | |||
21 | * manner for deletes. | 20 | * manner for deletes. |
22 | */ | 21 | */ |
23 | #define CTREE_EXTENT_PENDING_DEL 0 | 22 | #define CTREE_EXTENT_PENDING_DEL 0 |
23 | #define CTREE_EXTENT_PINNED 1 | ||
24 | 24 | ||
25 | static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | 25 | static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root |
26 | *root, u64 blocknr) | 26 | *root, u64 blocknr) |
@@ -45,15 +45,14 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
45 | if (ret != 0) | 45 | if (ret != 0) |
46 | BUG(); | 46 | BUG(); |
47 | BUG_ON(ret != 0); | 47 | BUG_ON(ret != 0); |
48 | l = &path.nodes[0]->leaf; | 48 | l = btrfs_buffer_leaf(path.nodes[0]); |
49 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); | 49 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); |
50 | refs = btrfs_extent_refs(item); | 50 | refs = btrfs_extent_refs(item); |
51 | btrfs_set_extent_refs(item, refs + 1); | 51 | btrfs_set_extent_refs(item, refs + 1); |
52 | 52 | ||
53 | BUG_ON(list_empty(&path.nodes[0]->dirty)); | ||
54 | btrfs_release_path(root->fs_info->extent_root, &path); | 53 | btrfs_release_path(root->fs_info->extent_root, &path); |
55 | finish_current_insert(trans, root->fs_info->extent_root); | 54 | finish_current_insert(trans, root->fs_info->extent_root); |
56 | run_pending(trans, root->fs_info->extent_root); | 55 | del_pending_extents(trans, root->fs_info->extent_root); |
57 | return 0; | 56 | return 0; |
58 | } | 57 | } |
59 | 58 | ||
@@ -74,7 +73,7 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
74 | 0, 0); | 73 | 0, 0); |
75 | if (ret != 0) | 74 | if (ret != 0) |
76 | BUG(); | 75 | BUG(); |
77 | l = &path.nodes[0]->leaf; | 76 | l = btrfs_buffer_leaf(path.nodes[0]); |
78 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); | 77 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); |
79 | *refs = btrfs_extent_refs(item); | 78 | *refs = btrfs_extent_refs(item); |
80 | btrfs_release_path(root->fs_info->extent_root, &path); | 79 | btrfs_release_path(root->fs_info->extent_root, &path); |
@@ -82,18 +81,20 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
82 | } | 81 | } |
83 | 82 | ||
84 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 83 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
85 | struct btrfs_buffer *buf) | 84 | struct buffer_head *buf) |
86 | { | 85 | { |
87 | u64 blocknr; | 86 | u64 blocknr; |
87 | struct btrfs_node *buf_node; | ||
88 | int i; | 88 | int i; |
89 | 89 | ||
90 | if (!root->ref_cows) | 90 | if (!root->ref_cows) |
91 | return 0; | 91 | return 0; |
92 | if (btrfs_is_leaf(&buf->node)) | 92 | buf_node = btrfs_buffer_node(buf); |
93 | if (btrfs_is_leaf(buf_node)) | ||
93 | return 0; | 94 | return 0; |
94 | 95 | ||
95 | for (i = 0; i < btrfs_header_nritems(&buf->node.header); i++) { | 96 | for (i = 0; i < btrfs_header_nritems(&buf_node->header); i++) { |
96 | blocknr = btrfs_node_blockptr(&buf->node, i); | 97 | blocknr = btrfs_node_blockptr(buf_node, i); |
97 | inc_block_ref(trans, root, blocknr); | 98 | inc_block_ref(trans, root, blocknr); |
98 | } | 99 | } |
99 | return 0; | 100 | return 0; |
@@ -108,9 +109,10 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | |||
108 | int i; | 109 | int i; |
109 | 110 | ||
110 | while(1) { | 111 | while(1) { |
111 | ret = radix_tree_gang_lookup(&root->fs_info->pinned_radix, | 112 | ret = radix_tree_gang_lookup_tag(&root->fs_info->pinned_radix, |
112 | (void **)gang, 0, | 113 | (void **)gang, 0, |
113 | ARRAY_SIZE(gang)); | 114 | ARRAY_SIZE(gang), |
115 | CTREE_EXTENT_PINNED); | ||
114 | if (!ret) | 116 | if (!ret) |
115 | break; | 117 | break; |
116 | if (!first) | 118 | if (!first) |
@@ -137,7 +139,7 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
137 | 139 | ||
138 | btrfs_set_extent_refs(&extent_item, 1); | 140 | btrfs_set_extent_refs(&extent_item, 1); |
139 | btrfs_set_extent_owner(&extent_item, | 141 | btrfs_set_extent_owner(&extent_item, |
140 | btrfs_header_parentid(&extent_root->node->node.header)); | 142 | btrfs_header_parentid(btrfs_buffer_header(extent_root->node))); |
141 | ins.offset = 1; | 143 | ins.offset = 1; |
142 | ins.flags = 0; | 144 | ins.flags = 0; |
143 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); | 145 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); |
@@ -156,11 +158,24 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
156 | return 0; | 158 | return 0; |
157 | } | 159 | } |
158 | 160 | ||
161 | static int pin_down_block(struct btrfs_root *root, u64 blocknr, int tag) | ||
162 | { | ||
163 | int err; | ||
164 | err = radix_tree_insert(&root->fs_info->pinned_radix, | ||
165 | blocknr, (void *)blocknr); | ||
166 | BUG_ON(err); | ||
167 | if (err) | ||
168 | return err; | ||
169 | radix_tree_tag_set(&root->fs_info->pinned_radix, blocknr, | ||
170 | tag); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
159 | /* | 174 | /* |
160 | * remove an extent from the root, returns 0 on success | 175 | * remove an extent from the root, returns 0 on success |
161 | */ | 176 | */ |
162 | static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 177 | static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
163 | *root, u64 blocknr, u64 num_blocks, int pin) | 178 | *root, u64 blocknr, u64 num_blocks) |
164 | { | 179 | { |
165 | struct btrfs_path path; | 180 | struct btrfs_path path; |
166 | struct btrfs_key key; | 181 | struct btrfs_key key; |
@@ -171,7 +186,6 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
171 | struct btrfs_key ins; | 186 | struct btrfs_key ins; |
172 | u32 refs; | 187 | u32 refs; |
173 | 188 | ||
174 | BUG_ON(pin && num_blocks != 1); | ||
175 | key.objectid = blocknr; | 189 | key.objectid = blocknr; |
176 | key.flags = 0; | 190 | key.flags = 0; |
177 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 191 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
@@ -186,26 +200,18 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
186 | printk("failed to find %Lu\n", key.objectid); | 200 | printk("failed to find %Lu\n", key.objectid); |
187 | BUG(); | 201 | BUG(); |
188 | } | 202 | } |
189 | ei = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], | 203 | ei = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], |
190 | struct btrfs_extent_item); | 204 | struct btrfs_extent_item); |
191 | BUG_ON(ei->refs == 0); | 205 | BUG_ON(ei->refs == 0); |
192 | refs = btrfs_extent_refs(ei) - 1; | 206 | refs = btrfs_extent_refs(ei) - 1; |
193 | btrfs_set_extent_refs(ei, refs); | 207 | btrfs_set_extent_refs(ei, refs); |
194 | if (refs == 0) { | 208 | if (refs == 0) { |
195 | u64 super_blocks_used; | 209 | u64 super_blocks_used; |
196 | if (pin) { | ||
197 | int err; | ||
198 | radix_tree_preload(GFP_KERNEL); | ||
199 | err = radix_tree_insert(&info->pinned_radix, | ||
200 | blocknr, (void *)blocknr); | ||
201 | BUG_ON(err); | ||
202 | radix_tree_preload_end(); | ||
203 | } | ||
204 | super_blocks_used = btrfs_super_blocks_used(info->disk_super); | 210 | super_blocks_used = btrfs_super_blocks_used(info->disk_super); |
205 | btrfs_set_super_blocks_used(info->disk_super, | 211 | btrfs_set_super_blocks_used(info->disk_super, |
206 | super_blocks_used - num_blocks); | 212 | super_blocks_used - num_blocks); |
207 | ret = btrfs_del_item(trans, extent_root, &path); | 213 | ret = btrfs_del_item(trans, extent_root, &path); |
208 | if (!pin && extent_root->fs_info->last_insert.objectid > | 214 | if (extent_root->fs_info->last_insert.objectid > |
209 | blocknr) | 215 | blocknr) |
210 | extent_root->fs_info->last_insert.objectid = blocknr; | 216 | extent_root->fs_info->last_insert.objectid = blocknr; |
211 | if (ret) | 217 | if (ret) |
@@ -224,39 +230,32 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
224 | btrfs_root *extent_root) | 230 | btrfs_root *extent_root) |
225 | { | 231 | { |
226 | int ret; | 232 | int ret; |
227 | struct btrfs_buffer *gang[4]; | 233 | int wret; |
234 | int err = 0; | ||
235 | unsigned long gang[4]; | ||
228 | int i; | 236 | int i; |
237 | struct radix_tree_root *radix = &extent_root->fs_info->pinned_radix; | ||
229 | 238 | ||
230 | while(1) { | 239 | while(1) { |
231 | ret = radix_tree_gang_lookup_tag( | 240 | ret = radix_tree_gang_lookup_tag( |
232 | &extent_root->fs_info->cache_radix, | 241 | &extent_root->fs_info->pinned_radix, |
233 | (void **)gang, 0, | 242 | (void **)gang, 0, |
234 | ARRAY_SIZE(gang), | 243 | ARRAY_SIZE(gang), |
235 | CTREE_EXTENT_PENDING_DEL); | 244 | CTREE_EXTENT_PENDING_DEL); |
236 | if (!ret) | 245 | if (!ret) |
237 | break; | 246 | break; |
238 | for (i = 0; i < ret; i++) { | 247 | for (i = 0; i < ret; i++) { |
239 | ret = __free_extent(trans, extent_root, | 248 | radix_tree_tag_set(radix, gang[i], CTREE_EXTENT_PINNED); |
240 | gang[i]->blocknr, 1, 1); | 249 | radix_tree_tag_clear(radix, gang[i], |
241 | radix_tree_tag_clear(&extent_root->fs_info->cache_radix, | ||
242 | gang[i]->blocknr, | ||
243 | CTREE_EXTENT_PENDING_DEL); | 250 | CTREE_EXTENT_PENDING_DEL); |
244 | btrfs_block_release(extent_root, gang[i]); | 251 | wret = __free_extent(trans, extent_root, gang[i], 1); |
252 | if (wret) | ||
253 | err = wret; | ||
245 | } | 254 | } |
246 | } | 255 | } |
247 | return 0; | 256 | return err; |
248 | } | 257 | } |
249 | 258 | ||
250 | static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root | ||
251 | *extent_root) | ||
252 | { | ||
253 | while(radix_tree_tagged(&extent_root->fs_info->cache_radix, | ||
254 | CTREE_EXTENT_PENDING_DEL)) | ||
255 | del_pending_extents(trans, extent_root); | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | |||
260 | /* | 259 | /* |
261 | * remove an extent from the root, returns 0 on success | 260 | * remove an extent from the root, returns 0 on success |
262 | */ | 261 | */ |
@@ -264,18 +263,21 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
264 | *root, u64 blocknr, u64 num_blocks, int pin) | 263 | *root, u64 blocknr, u64 num_blocks, int pin) |
265 | { | 264 | { |
266 | struct btrfs_root *extent_root = root->fs_info->extent_root; | 265 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
267 | struct btrfs_buffer *t; | 266 | struct buffer_head *t; |
268 | int pending_ret; | 267 | int pending_ret; |
269 | int ret; | 268 | int ret; |
270 | 269 | ||
271 | if (root == extent_root) { | 270 | if (root == extent_root) { |
272 | t = find_tree_block(root, blocknr); | 271 | t = find_tree_block(root, blocknr); |
273 | radix_tree_tag_set(&root->fs_info->cache_radix, blocknr, | 272 | pin_down_block(root, blocknr, CTREE_EXTENT_PENDING_DEL); |
274 | CTREE_EXTENT_PENDING_DEL); | ||
275 | return 0; | 273 | return 0; |
276 | } | 274 | } |
277 | ret = __free_extent(trans, root, blocknr, num_blocks, pin); | 275 | if (pin) { |
278 | pending_ret = run_pending(trans, root->fs_info->extent_root); | 276 | ret = pin_down_block(root, blocknr, CTREE_EXTENT_PINNED); |
277 | BUG_ON(ret); | ||
278 | } | ||
279 | ret = __free_extent(trans, root, blocknr, num_blocks); | ||
280 | pending_ret = del_pending_extents(trans, root->fs_info->extent_root); | ||
279 | return ret ? ret : pending_ret; | 281 | return ret ? ret : pending_ret; |
280 | } | 282 | } |
281 | 283 | ||
@@ -296,14 +298,16 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
296 | int ret; | 298 | int ret; |
297 | u64 hole_size = 0; | 299 | u64 hole_size = 0; |
298 | int slot = 0; | 300 | int slot = 0; |
299 | u64 last_block; | 301 | u64 last_block = 0; |
300 | u64 test_block; | 302 | u64 test_block; |
301 | int start_found; | 303 | int start_found; |
302 | struct btrfs_leaf *l; | 304 | struct btrfs_leaf *l; |
303 | struct btrfs_root * root = orig_root->fs_info->extent_root; | 305 | struct btrfs_root * root = orig_root->fs_info->extent_root; |
304 | int total_needed = num_blocks; | 306 | int total_needed = num_blocks; |
307 | int level; | ||
305 | 308 | ||
306 | total_needed += (btrfs_header_level(&root->node->node.header) + 1) * 3; | 309 | level = btrfs_header_level(btrfs_buffer_header(root->node)); |
310 | total_needed += (level + 1) * 3; | ||
307 | if (root->fs_info->last_insert.objectid > search_start) | 311 | if (root->fs_info->last_insert.objectid > search_start) |
308 | search_start = root->fs_info->last_insert.objectid; | 312 | search_start = root->fs_info->last_insert.objectid; |
309 | 313 | ||
@@ -323,7 +327,7 @@ check_failed: | |||
323 | path.slots[0]--; | 327 | path.slots[0]--; |
324 | 328 | ||
325 | while (1) { | 329 | while (1) { |
326 | l = &path.nodes[0]->leaf; | 330 | l = btrfs_buffer_leaf(path.nodes[0]); |
327 | slot = path.slots[0]; | 331 | slot = path.slots[0]; |
328 | if (slot >= btrfs_header_nritems(&l->header)) { | 332 | if (slot >= btrfs_header_nritems(&l->header)) { |
329 | ret = btrfs_next_leaf(root, &path); | 333 | ret = btrfs_next_leaf(root, &path); |
@@ -429,7 +433,7 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
429 | sizeof(extent_item)); | 433 | sizeof(extent_item)); |
430 | 434 | ||
431 | finish_current_insert(trans, extent_root); | 435 | finish_current_insert(trans, extent_root); |
432 | pending_ret = run_pending(trans, extent_root); | 436 | pending_ret = del_pending_extents(trans, extent_root); |
433 | if (ret) | 437 | if (ret) |
434 | return ret; | 438 | return ret; |
435 | if (pending_ret) | 439 | if (pending_ret) |
@@ -441,16 +445,15 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
441 | * helper function to allocate a block for a given tree | 445 | * helper function to allocate a block for a given tree |
442 | * returns the tree buffer or NULL. | 446 | * returns the tree buffer or NULL. |
443 | */ | 447 | */ |
444 | struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 448 | struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
445 | struct btrfs_root *root) | 449 | struct btrfs_root *root) |
446 | { | 450 | { |
447 | struct btrfs_key ins; | 451 | struct btrfs_key ins; |
448 | int ret; | 452 | int ret; |
449 | struct btrfs_buffer *buf; | 453 | struct buffer_head *buf; |
450 | 454 | ||
451 | ret = alloc_extent(trans, root, 1, 0, (unsigned long)-1, | 455 | ret = alloc_extent(trans, root, 1, 0, (unsigned long)-1, |
452 | btrfs_header_parentid(&root->node->node.header), | 456 | btrfs_header_parentid(btrfs_buffer_header(root->node)), &ins); |
453 | &ins); | ||
454 | if (ret) { | 457 | if (ret) { |
455 | BUG(); | 458 | BUG(); |
456 | return NULL; | 459 | return NULL; |
@@ -467,13 +470,13 @@ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
467 | static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | 470 | static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root |
468 | *root, struct btrfs_path *path, int *level) | 471 | *root, struct btrfs_path *path, int *level) |
469 | { | 472 | { |
470 | struct btrfs_buffer *next; | 473 | struct buffer_head *next; |
471 | struct btrfs_buffer *cur; | 474 | struct buffer_head *cur; |
472 | u64 blocknr; | 475 | u64 blocknr; |
473 | int ret; | 476 | int ret; |
474 | u32 refs; | 477 | u32 refs; |
475 | 478 | ||
476 | ret = lookup_block_ref(trans, root, path->nodes[*level]->blocknr, | 479 | ret = lookup_block_ref(trans, root, path->nodes[*level]->b_blocknr, |
477 | &refs); | 480 | &refs); |
478 | BUG_ON(ret); | 481 | BUG_ON(ret); |
479 | if (refs > 1) | 482 | if (refs > 1) |
@@ -484,9 +487,10 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
484 | while(*level > 0) { | 487 | while(*level > 0) { |
485 | cur = path->nodes[*level]; | 488 | cur = path->nodes[*level]; |
486 | if (path->slots[*level] >= | 489 | if (path->slots[*level] >= |
487 | btrfs_header_nritems(&cur->node.header)) | 490 | btrfs_header_nritems(btrfs_buffer_header(cur))) |
488 | break; | 491 | break; |
489 | blocknr = btrfs_node_blockptr(&cur->node, path->slots[*level]); | 492 | blocknr = btrfs_node_blockptr(btrfs_buffer_node(cur), |
493 | path->slots[*level]); | ||
490 | ret = lookup_block_ref(trans, root, blocknr, &refs); | 494 | ret = lookup_block_ref(trans, root, blocknr, &refs); |
491 | if (refs != 1 || *level == 1) { | 495 | if (refs != 1 || *level == 1) { |
492 | path->slots[*level]++; | 496 | path->slots[*level]++; |
@@ -499,12 +503,12 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
499 | if (path->nodes[*level-1]) | 503 | if (path->nodes[*level-1]) |
500 | btrfs_block_release(root, path->nodes[*level-1]); | 504 | btrfs_block_release(root, path->nodes[*level-1]); |
501 | path->nodes[*level-1] = next; | 505 | path->nodes[*level-1] = next; |
502 | *level = btrfs_header_level(&next->node.header); | 506 | *level = btrfs_header_level(btrfs_buffer_header(next)); |
503 | path->slots[*level] = 0; | 507 | path->slots[*level] = 0; |
504 | } | 508 | } |
505 | out: | 509 | out: |
506 | ret = btrfs_free_extent(trans, root, path->nodes[*level]->blocknr, 1, | 510 | ret = btrfs_free_extent(trans, root, path->nodes[*level]->b_blocknr, |
507 | 1); | 511 | 1, 1); |
508 | btrfs_block_release(root, path->nodes[*level]); | 512 | btrfs_block_release(root, path->nodes[*level]); |
509 | path->nodes[*level] = NULL; | 513 | path->nodes[*level] = NULL; |
510 | *level += 1; | 514 | *level += 1; |
@@ -525,14 +529,14 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
525 | int ret; | 529 | int ret; |
526 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { | 530 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { |
527 | slot = path->slots[i]; | 531 | slot = path->slots[i]; |
528 | if (slot < | 532 | if (slot < btrfs_header_nritems( |
529 | btrfs_header_nritems(&path->nodes[i]->node.header)- 1) { | 533 | btrfs_buffer_header(path->nodes[i])) - 1) { |
530 | path->slots[i]++; | 534 | path->slots[i]++; |
531 | *level = i; | 535 | *level = i; |
532 | return 0; | 536 | return 0; |
533 | } else { | 537 | } else { |
534 | ret = btrfs_free_extent(trans, root, | 538 | ret = btrfs_free_extent(trans, root, |
535 | path->nodes[*level]->blocknr, | 539 | path->nodes[*level]->b_blocknr, |
536 | 1, 1); | 540 | 1, 1); |
537 | btrfs_block_release(root, path->nodes[*level]); | 541 | btrfs_block_release(root, path->nodes[*level]); |
538 | path->nodes[*level] = NULL; | 542 | path->nodes[*level] = NULL; |
@@ -549,7 +553,7 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
549 | * decremented. | 553 | * decremented. |
550 | */ | 554 | */ |
551 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | 555 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root |
552 | *root, struct btrfs_buffer *snap) | 556 | *root, struct buffer_head *snap) |
553 | { | 557 | { |
554 | int ret = 0; | 558 | int ret = 0; |
555 | int wret; | 559 | int wret; |
@@ -560,7 +564,7 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
560 | 564 | ||
561 | btrfs_init_path(&path); | 565 | btrfs_init_path(&path); |
562 | 566 | ||
563 | level = btrfs_header_level(&snap->node.header); | 567 | level = btrfs_header_level(btrfs_buffer_header(snap)); |
564 | orig_level = level; | 568 | orig_level = level; |
565 | path.nodes[level] = snap; | 569 | path.nodes[level] = snap; |
566 | path.slots[level] = 0; | 570 | path.slots[level] = 0; |