diff options
| -rw-r--r-- | fs/btrfs/Makefile | 2 | ||||
| -rw-r--r-- | fs/btrfs/ctree.c | 1484 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 849 | ||||
| -rw-r--r-- | fs/btrfs/dir-item.c | 102 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 391 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.h | 55 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 294 | ||||
| -rw-r--r-- | fs/btrfs/extent_map.c | 672 | ||||
| -rw-r--r-- | fs/btrfs/extent_map.h | 75 | ||||
| -rw-r--r-- | fs/btrfs/file-item.c | 63 | ||||
| -rw-r--r-- | fs/btrfs/file.c | 129 | ||||
| -rw-r--r-- | fs/btrfs/inode-item.c | 22 | ||||
| -rw-r--r-- | fs/btrfs/inode-map.c | 17 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 435 | ||||
| -rw-r--r-- | fs/btrfs/print-tree.c | 96 | ||||
| -rw-r--r-- | fs/btrfs/print-tree.h | 4 | ||||
| -rw-r--r-- | fs/btrfs/root-tree.c | 51 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 7 | ||||
| -rw-r--r-- | fs/btrfs/sysfs.c | 10 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 61 | ||||
| -rw-r--r-- | fs/btrfs/transaction.h | 5 | ||||
| -rw-r--r-- | fs/btrfs/tree-defrag.c | 58 |
22 files changed, 2794 insertions, 2088 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index 6341cf7a9f91..a3b51085d7f0 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile | |||
| @@ -23,4 +23,6 @@ modules_install: | |||
| 23 | clean: | 23 | clean: |
| 24 | $(MAKE) -C $(KERNELDIR) M=`pwd` clean | 24 | $(MAKE) -C $(KERNELDIR) M=`pwd` clean |
| 25 | 25 | ||
| 26 | tester: | ||
| 27 | $(MAKE) -C $(KERNELDIR) M=`pwd` tree-defrag.o transaction.o sysfs.o super.o root-tree.o inode-map.o inode-item.o inode.o file-item.o file.o extent_map.o disk-io.o ctree.o dir-item.o extent-tree.o | ||
| 26 | endif | 28 | endif |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index b41f48ade419..f60920e8a0e0 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -16,21 +16,24 @@ | |||
| 16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/highmem.h> | ||
| 19 | #include "ctree.h" | 20 | #include "ctree.h" |
| 20 | #include "disk-io.h" | 21 | #include "disk-io.h" |
| 21 | #include "transaction.h" | 22 | #include "transaction.h" |
| 23 | #include "print-tree.h" | ||
| 22 | 24 | ||
| 23 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | 25 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root |
| 24 | *root, struct btrfs_path *path, int level); | 26 | *root, struct btrfs_path *path, int level); |
| 25 | static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | 27 | static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root |
| 26 | *root, struct btrfs_key *ins_key, | 28 | *root, struct btrfs_key *ins_key, |
| 27 | struct btrfs_path *path, int data_size); | 29 | struct btrfs_path *path, int data_size); |
| 28 | static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root | 30 | static int push_node_left(struct btrfs_trans_handle *trans, |
| 29 | *root, struct buffer_head *dst, struct buffer_head | 31 | struct btrfs_root *root, struct extent_buffer *dst, |
| 30 | *src); | 32 | struct extent_buffer *src); |
| 31 | static int balance_node_right(struct btrfs_trans_handle *trans, struct | 33 | static int balance_node_right(struct btrfs_trans_handle *trans, |
| 32 | btrfs_root *root, struct buffer_head *dst_buf, | 34 | struct btrfs_root *root, |
| 33 | struct buffer_head *src_buf); | 35 | struct extent_buffer *dst_buf, |
| 36 | struct extent_buffer *src_buf); | ||
| 34 | static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 37 | static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 35 | struct btrfs_path *path, int level, int slot); | 38 | struct btrfs_path *path, int level, int slot); |
| 36 | 39 | ||
| @@ -62,40 +65,38 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) | |||
| 62 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) { | 65 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) { |
| 63 | if (!p->nodes[i]) | 66 | if (!p->nodes[i]) |
| 64 | break; | 67 | break; |
| 65 | btrfs_block_release(root, p->nodes[i]); | 68 | free_extent_buffer(p->nodes[i]); |
| 66 | } | 69 | } |
| 67 | memset(p, 0, sizeof(*p)); | 70 | memset(p, 0, sizeof(*p)); |
| 68 | } | 71 | } |
| 69 | 72 | ||
| 70 | static int __btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | 73 | static int __btrfs_cow_block(struct btrfs_trans_handle *trans, |
| 71 | *root, struct buffer_head *buf, struct buffer_head | 74 | struct btrfs_root *root, |
| 72 | *parent, int parent_slot, struct buffer_head | 75 | struct extent_buffer *buf, |
| 73 | **cow_ret, u64 search_start, u64 empty_size) | 76 | struct extent_buffer *parent, int parent_slot, |
| 77 | struct extent_buffer **cow_ret, | ||
| 78 | u64 search_start, u64 empty_size) | ||
| 74 | { | 79 | { |
| 75 | struct buffer_head *cow; | 80 | struct extent_buffer *cow; |
| 76 | struct btrfs_node *cow_node; | ||
| 77 | int ret = 0; | 81 | int ret = 0; |
| 78 | int different_trans = 0; | 82 | int different_trans = 0; |
| 79 | 83 | ||
| 80 | WARN_ON(root->ref_cows && trans->transid != root->last_trans); | 84 | WARN_ON(root->ref_cows && trans->transid != root->last_trans); |
| 81 | WARN_ON(!buffer_uptodate(buf)); | 85 | |
| 82 | cow = btrfs_alloc_free_block(trans, root, search_start, empty_size); | 86 | cow = btrfs_alloc_free_block(trans, root, search_start, empty_size); |
| 83 | if (IS_ERR(cow)) | 87 | if (IS_ERR(cow)) |
| 84 | return PTR_ERR(cow); | 88 | return PTR_ERR(cow); |
| 85 | 89 | ||
| 86 | cow_node = btrfs_buffer_node(cow); | 90 | if (buf->len != root->sectorsize || cow->len != root->sectorsize) |
| 87 | if (buf->b_size != root->blocksize || cow->b_size != root->blocksize) | ||
| 88 | WARN_ON(1); | 91 | WARN_ON(1); |
| 89 | 92 | ||
| 90 | memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize); | 93 | copy_extent_buffer(cow, buf, 0, 0, cow->len); |
| 91 | btrfs_set_header_blocknr(&cow_node->header, bh_blocknr(cow)); | 94 | btrfs_set_header_blocknr(cow, extent_buffer_blocknr(cow)); |
| 92 | btrfs_set_header_generation(&cow_node->header, trans->transid); | 95 | btrfs_set_header_generation(cow, trans->transid); |
| 93 | btrfs_set_header_owner(&cow_node->header, root->root_key.objectid); | 96 | btrfs_set_header_owner(cow, root->root_key.objectid); |
| 94 | 97 | ||
| 95 | WARN_ON(btrfs_header_generation(btrfs_buffer_header(buf)) > | 98 | WARN_ON(btrfs_header_generation(buf) > trans->transid); |
| 96 | trans->transid); | 99 | if (btrfs_header_generation(buf) != trans->transid) { |
| 97 | if (btrfs_header_generation(btrfs_buffer_header(buf)) != | ||
| 98 | trans->transid) { | ||
| 99 | different_trans = 1; | 100 | different_trans = 1; |
| 100 | ret = btrfs_inc_ref(trans, root, buf); | 101 | ret = btrfs_inc_ref(trans, root, buf); |
| 101 | if (ret) | 102 | if (ret) |
| @@ -106,29 +107,29 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 106 | 107 | ||
| 107 | if (buf == root->node) { | 108 | if (buf == root->node) { |
| 108 | root->node = cow; | 109 | root->node = cow; |
| 109 | get_bh(cow); | 110 | extent_buffer_get(cow); |
| 110 | if (buf != root->commit_root) { | 111 | if (buf != root->commit_root) { |
| 111 | btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1); | 112 | btrfs_free_extent(trans, root, |
| 113 | extent_buffer_blocknr(buf), 1, 1); | ||
| 112 | } | 114 | } |
| 113 | btrfs_block_release(root, buf); | 115 | free_extent_buffer(buf); |
| 114 | } else { | 116 | } else { |
| 115 | btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot, | 117 | btrfs_set_node_blockptr(parent, parent_slot, |
| 116 | bh_blocknr(cow)); | 118 | extent_buffer_blocknr(cow)); |
| 117 | btrfs_mark_buffer_dirty(parent); | 119 | btrfs_mark_buffer_dirty(parent); |
| 118 | WARN_ON(btrfs_header_generation(btrfs_buffer_header(parent)) != | 120 | WARN_ON(btrfs_header_generation(parent) != trans->transid); |
| 119 | trans->transid); | 121 | btrfs_free_extent(trans, root, extent_buffer_blocknr(buf),1,1); |
| 120 | btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1); | ||
| 121 | } | 122 | } |
| 122 | btrfs_block_release(root, buf); | 123 | free_extent_buffer(buf); |
| 123 | btrfs_mark_buffer_dirty(cow); | 124 | btrfs_mark_buffer_dirty(cow); |
| 124 | *cow_ret = cow; | 125 | *cow_ret = cow; |
| 125 | return 0; | 126 | return 0; |
| 126 | } | 127 | } |
| 127 | 128 | ||
| 128 | int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | 129 | int btrfs_cow_block(struct btrfs_trans_handle *trans, |
| 129 | *root, struct buffer_head *buf, struct buffer_head | 130 | struct btrfs_root *root, struct extent_buffer *buf, |
| 130 | *parent, int parent_slot, struct buffer_head | 131 | struct extent_buffer *parent, int parent_slot, |
| 131 | **cow_ret) | 132 | struct extent_buffer **cow_ret) |
| 132 | { | 133 | { |
| 133 | u64 search_start; | 134 | u64 search_start; |
| 134 | if (trans->transaction != root->fs_info->running_transaction) { | 135 | if (trans->transaction != root->fs_info->running_transaction) { |
| @@ -141,13 +142,12 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 141 | root->fs_info->generation); | 142 | root->fs_info->generation); |
| 142 | WARN_ON(1); | 143 | WARN_ON(1); |
| 143 | } | 144 | } |
| 144 | if (btrfs_header_generation(btrfs_buffer_header(buf)) == | 145 | if (btrfs_header_generation(buf) == trans->transid) { |
| 145 | trans->transid) { | ||
| 146 | *cow_ret = buf; | 146 | *cow_ret = buf; |
| 147 | return 0; | 147 | return 0; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | search_start = bh_blocknr(buf) & ~((u64)65535); | 150 | search_start = extent_buffer_blocknr(buf) & ~((u64)65535); |
| 151 | return __btrfs_cow_block(trans, root, buf, parent, | 151 | return __btrfs_cow_block(trans, root, buf, parent, |
| 152 | parent_slot, cow_ret, search_start, 0); | 152 | parent_slot, cow_ret, search_start, 0); |
| 153 | } | 153 | } |
| @@ -161,9 +161,11 @@ static int close_blocks(u64 blocknr, u64 other) | |||
| 161 | return 0; | 161 | return 0; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static int should_defrag_leaf(struct buffer_head *bh) | 164 | #if 0 |
| 165 | static int should_defrag_leaf(struct extent_buffer *eb) | ||
| 165 | { | 166 | { |
| 166 | struct btrfs_leaf *leaf = btrfs_buffer_leaf(bh); | 167 | return 0; |
| 168 | struct btrfs_leaf *leaf = btrfs_buffer_leaf(eb); | ||
| 167 | struct btrfs_disk_key *key; | 169 | struct btrfs_disk_key *key; |
| 168 | u32 nritems; | 170 | u32 nritems; |
| 169 | 171 | ||
| @@ -188,14 +190,17 @@ static int should_defrag_leaf(struct buffer_head *bh) | |||
| 188 | } | 190 | } |
| 189 | return 0; | 191 | return 0; |
| 190 | } | 192 | } |
| 193 | #endif | ||
| 191 | 194 | ||
| 192 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, | 195 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, |
| 193 | struct btrfs_root *root, struct buffer_head *parent, | 196 | struct btrfs_root *root, struct extent_buffer *parent, |
| 194 | int cache_only, u64 *last_ret) | 197 | int cache_only, u64 *last_ret) |
| 195 | { | 198 | { |
| 199 | return 0; | ||
| 200 | #if 0 | ||
| 196 | struct btrfs_node *parent_node; | 201 | struct btrfs_node *parent_node; |
| 197 | struct buffer_head *cur_bh; | 202 | struct extent_buffer *cur_eb; |
| 198 | struct buffer_head *tmp_bh; | 203 | struct extent_buffer *tmp_eb; |
| 199 | u64 blocknr; | 204 | u64 blocknr; |
| 200 | u64 search_start = *last_ret; | 205 | u64 search_start = *last_ret; |
| 201 | u64 last_block = 0; | 206 | u64 last_block = 0; |
| @@ -281,6 +286,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
| 281 | brelse(tmp_bh); | 286 | brelse(tmp_bh); |
| 282 | } | 287 | } |
| 283 | return err; | 288 | return err; |
| 289 | #endif | ||
| 284 | } | 290 | } |
| 285 | 291 | ||
| 286 | /* | 292 | /* |
| @@ -289,12 +295,12 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
| 289 | * which is the stop of the leaf data stack | 295 | * which is the stop of the leaf data stack |
| 290 | */ | 296 | */ |
| 291 | static inline unsigned int leaf_data_end(struct btrfs_root *root, | 297 | static inline unsigned int leaf_data_end(struct btrfs_root *root, |
| 292 | struct btrfs_leaf *leaf) | 298 | struct extent_buffer *leaf) |
| 293 | { | 299 | { |
| 294 | u32 nr = btrfs_header_nritems(&leaf->header); | 300 | u32 nr = btrfs_header_nritems(leaf); |
| 295 | if (nr == 0) | 301 | if (nr == 0) |
| 296 | return BTRFS_LEAF_DATA_SIZE(root); | 302 | return BTRFS_LEAF_DATA_SIZE(root); |
| 297 | return btrfs_item_offset(leaf->items + nr - 1); | 303 | return btrfs_item_offset_nr(leaf, nr - 1); |
| 298 | } | 304 | } |
| 299 | 305 | ||
| 300 | /* | 306 | /* |
| @@ -310,9 +316,9 @@ static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2) | |||
| 310 | return 1; | 316 | return 1; |
| 311 | if (k1.objectid < k2->objectid) | 317 | if (k1.objectid < k2->objectid) |
| 312 | return -1; | 318 | return -1; |
| 313 | if (k1.flags > k2->flags) | 319 | if (k1.type > k2->type) |
| 314 | return 1; | 320 | return 1; |
| 315 | if (k1.flags < k2->flags) | 321 | if (k1.type < k2->type) |
| 316 | return -1; | 322 | return -1; |
| 317 | if (k1.offset > k2->offset) | 323 | if (k1.offset > k2->offset) |
| 318 | return 1; | 324 | return 1; |
| @@ -324,37 +330,39 @@ static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2) | |||
| 324 | static int check_node(struct btrfs_root *root, struct btrfs_path *path, | 330 | static int check_node(struct btrfs_root *root, struct btrfs_path *path, |
| 325 | int level) | 331 | int level) |
| 326 | { | 332 | { |
| 327 | struct btrfs_node *parent = NULL; | 333 | struct extent_buffer *parent = NULL; |
| 328 | struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]); | 334 | struct extent_buffer *node = path->nodes[level]; |
| 335 | struct btrfs_disk_key parent_key; | ||
| 336 | struct btrfs_disk_key node_key; | ||
| 329 | int parent_slot; | 337 | int parent_slot; |
| 330 | int slot; | 338 | int slot; |
| 331 | struct btrfs_key cpukey; | 339 | struct btrfs_key cpukey; |
| 332 | u32 nritems = btrfs_header_nritems(&node->header); | 340 | u32 nritems = btrfs_header_nritems(node); |
| 333 | 341 | ||
| 334 | if (path->nodes[level + 1]) | 342 | if (path->nodes[level + 1]) |
| 335 | parent = btrfs_buffer_node(path->nodes[level + 1]); | 343 | parent = path->nodes[level + 1]; |
| 336 | 344 | ||
| 337 | slot = path->slots[level]; | 345 | slot = path->slots[level]; |
| 338 | BUG_ON(!buffer_uptodate(path->nodes[level])); | ||
| 339 | BUG_ON(nritems == 0); | 346 | BUG_ON(nritems == 0); |
| 340 | if (parent) { | 347 | if (parent) { |
| 341 | struct btrfs_disk_key *parent_key; | ||
| 342 | |||
| 343 | parent_slot = path->slots[level + 1]; | 348 | parent_slot = path->slots[level + 1]; |
| 344 | parent_key = &parent->ptrs[parent_slot].key; | 349 | btrfs_node_key(parent, &parent_key, parent_slot); |
| 345 | BUG_ON(memcmp(parent_key, &node->ptrs[0].key, | 350 | btrfs_node_key(node, &node_key, 0); |
| 351 | BUG_ON(memcmp(&parent_key, &node_key, | ||
| 346 | sizeof(struct btrfs_disk_key))); | 352 | sizeof(struct btrfs_disk_key))); |
| 347 | BUG_ON(btrfs_node_blockptr(parent, parent_slot) != | 353 | BUG_ON(btrfs_node_blockptr(parent, parent_slot) != |
| 348 | btrfs_header_blocknr(&node->header)); | 354 | btrfs_header_blocknr(node)); |
| 349 | } | 355 | } |
| 350 | BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root)); | 356 | BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root)); |
| 351 | if (slot != 0) { | 357 | if (slot != 0) { |
| 352 | btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[slot - 1].key); | 358 | btrfs_node_key_to_cpu(node, &cpukey, slot - 1); |
| 353 | BUG_ON(comp_keys(&node->ptrs[slot].key, &cpukey) <= 0); | 359 | btrfs_node_key(node, &node_key, slot); |
| 360 | BUG_ON(comp_keys(&node_key, &cpukey) <= 0); | ||
| 354 | } | 361 | } |
| 355 | if (slot < nritems - 1) { | 362 | if (slot < nritems - 1) { |
| 356 | btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[slot + 1].key); | 363 | btrfs_node_key_to_cpu(node, &cpukey, slot + 1); |
| 357 | BUG_ON(comp_keys(&node->ptrs[slot].key, &cpukey) >= 0); | 364 | btrfs_node_key(node, &node_key, slot); |
| 365 | BUG_ON(comp_keys(&node_key, &cpukey) >= 0); | ||
| 358 | } | 366 | } |
| 359 | return 0; | 367 | return 0; |
| 360 | } | 368 | } |
| @@ -362,83 +370,172 @@ static int check_node(struct btrfs_root *root, struct btrfs_path *path, | |||
| 362 | static int check_leaf(struct btrfs_root *root, struct btrfs_path *path, | 370 | static int check_leaf(struct btrfs_root *root, struct btrfs_path *path, |
| 363 | int level) | 371 | int level) |
| 364 | { | 372 | { |
| 365 | struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[level]); | 373 | struct extent_buffer *leaf = path->nodes[level]; |
| 366 | struct btrfs_node *parent = NULL; | 374 | struct extent_buffer *parent = NULL; |
| 367 | int parent_slot; | 375 | int parent_slot; |
| 368 | int slot = path->slots[0]; | ||
| 369 | struct btrfs_key cpukey; | 376 | struct btrfs_key cpukey; |
| 377 | struct btrfs_disk_key parent_key; | ||
| 378 | struct btrfs_disk_key leaf_key; | ||
| 379 | int slot = path->slots[0]; | ||
| 370 | 380 | ||
| 371 | u32 nritems = btrfs_header_nritems(&leaf->header); | 381 | u32 nritems = btrfs_header_nritems(leaf); |
| 372 | 382 | ||
| 373 | if (path->nodes[level + 1]) | 383 | if (path->nodes[level + 1]) |
| 374 | parent = btrfs_buffer_node(path->nodes[level + 1]); | 384 | parent = path->nodes[level + 1]; |
| 375 | |||
| 376 | BUG_ON(btrfs_leaf_free_space(root, leaf) < 0); | ||
| 377 | 385 | ||
| 378 | if (nritems == 0) | 386 | if (nritems == 0) |
| 379 | return 0; | 387 | return 0; |
| 380 | 388 | ||
| 381 | if (parent) { | 389 | if (parent) { |
| 382 | struct btrfs_disk_key *parent_key; | ||
| 383 | |||
| 384 | parent_slot = path->slots[level + 1]; | 390 | parent_slot = path->slots[level + 1]; |
| 385 | parent_key = &parent->ptrs[parent_slot].key; | 391 | btrfs_node_key(parent, &parent_key, parent_slot); |
| 392 | btrfs_item_key(leaf, &leaf_key, 0); | ||
| 386 | 393 | ||
| 387 | BUG_ON(memcmp(parent_key, &leaf->items[0].key, | 394 | BUG_ON(memcmp(&parent_key, &leaf_key, |
| 388 | sizeof(struct btrfs_disk_key))); | 395 | sizeof(struct btrfs_disk_key))); |
| 389 | BUG_ON(btrfs_node_blockptr(parent, parent_slot) != | 396 | BUG_ON(btrfs_node_blockptr(parent, parent_slot) != |
| 390 | btrfs_header_blocknr(&leaf->header)); | 397 | btrfs_header_blocknr(leaf)); |
| 398 | } | ||
| 399 | #if 0 | ||
| 400 | for (i = 0; nritems > 1 && i < nritems - 2; i++) { | ||
| 401 | btrfs_item_key_to_cpu(leaf, &cpukey, i + 1); | ||
| 402 | btrfs_item_key(leaf, &leaf_key, i); | ||
| 403 | if (comp_keys(&leaf_key, &cpukey) >= 0) { | ||
| 404 | btrfs_print_leaf(root, leaf); | ||
| 405 | printk("slot %d offset bad key\n", i); | ||
| 406 | BUG_ON(1); | ||
| 407 | } | ||
| 408 | if (btrfs_item_offset_nr(leaf, i) != | ||
| 409 | btrfs_item_end_nr(leaf, i + 1)) { | ||
| 410 | btrfs_print_leaf(root, leaf); | ||
| 411 | printk("slot %d offset bad\n", i); | ||
| 412 | BUG_ON(1); | ||
| 413 | } | ||
| 414 | if (i == 0) { | ||
| 415 | if (btrfs_item_offset_nr(leaf, i) + | ||
| 416 | btrfs_item_size_nr(leaf, i) != | ||
| 417 | BTRFS_LEAF_DATA_SIZE(root)) { | ||
| 418 | btrfs_print_leaf(root, leaf); | ||
| 419 | printk("slot %d first offset bad\n", i); | ||
| 420 | BUG_ON(1); | ||
| 421 | } | ||
| 422 | } | ||
| 391 | } | 423 | } |
| 392 | if (slot != 0) { | 424 | if (nritems > 0) { |
| 393 | btrfs_disk_key_to_cpu(&cpukey, &leaf->items[slot - 1].key); | 425 | if (btrfs_item_size_nr(leaf, nritems - 1) > 4096) { |
| 394 | BUG_ON(comp_keys(&leaf->items[slot].key, &cpukey) <= 0); | 426 | btrfs_print_leaf(root, leaf); |
| 395 | BUG_ON(btrfs_item_offset(leaf->items + slot - 1) != | 427 | printk("slot %d bad size \n", nritems - 1); |
| 396 | btrfs_item_end(leaf->items + slot)); | 428 | BUG_ON(1); |
| 429 | } | ||
| 430 | } | ||
| 431 | #endif | ||
| 432 | if (slot != 0 && slot < nritems - 1) { | ||
| 433 | btrfs_item_key(leaf, &leaf_key, slot); | ||
| 434 | btrfs_item_key_to_cpu(leaf, &cpukey, slot - 1); | ||
| 435 | if (comp_keys(&leaf_key, &cpukey) <= 0) { | ||
| 436 | btrfs_print_leaf(root, leaf); | ||
| 437 | printk("slot %d offset bad key\n", slot); | ||
| 438 | BUG_ON(1); | ||
| 439 | } | ||
| 440 | if (btrfs_item_offset_nr(leaf, slot - 1) != | ||
| 441 | btrfs_item_end_nr(leaf, slot)) { | ||
| 442 | btrfs_print_leaf(root, leaf); | ||
| 443 | printk("slot %d offset bad\n", slot); | ||
| 444 | BUG_ON(1); | ||
| 445 | } | ||
| 397 | } | 446 | } |
| 398 | if (slot < nritems - 1) { | 447 | if (slot < nritems - 1) { |
| 399 | btrfs_disk_key_to_cpu(&cpukey, &leaf->items[slot + 1].key); | 448 | btrfs_item_key(leaf, &leaf_key, slot); |
| 400 | BUG_ON(comp_keys(&leaf->items[slot].key, &cpukey) >= 0); | 449 | btrfs_item_key_to_cpu(leaf, &cpukey, slot + 1); |
| 401 | BUG_ON(btrfs_item_offset(leaf->items + slot) != | 450 | BUG_ON(comp_keys(&leaf_key, &cpukey) >= 0); |
| 402 | btrfs_item_end(leaf->items + slot + 1)); | 451 | if (btrfs_item_offset_nr(leaf, slot) != |
| 452 | btrfs_item_end_nr(leaf, slot + 1)) { | ||
| 453 | btrfs_print_leaf(root, leaf); | ||
| 454 | printk("slot %d offset bad\n", slot); | ||
| 455 | BUG_ON(1); | ||
| 456 | } | ||
| 403 | } | 457 | } |
| 404 | BUG_ON(btrfs_item_offset(leaf->items) + | 458 | BUG_ON(btrfs_item_offset_nr(leaf, 0) + |
| 405 | btrfs_item_size(leaf->items) != BTRFS_LEAF_DATA_SIZE(root)); | 459 | btrfs_item_size_nr(leaf, 0) != BTRFS_LEAF_DATA_SIZE(root)); |
| 406 | return 0; | 460 | return 0; |
| 407 | } | 461 | } |
| 408 | 462 | ||
| 409 | static int check_block(struct btrfs_root *root, struct btrfs_path *path, | 463 | static int check_block(struct btrfs_root *root, struct btrfs_path *path, |
| 410 | int level) | 464 | int level) |
| 411 | { | 465 | { |
| 412 | struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]); | 466 | struct extent_buffer *buf = path->nodes[level]; |
| 413 | if (memcmp(node->header.fsid, root->fs_info->disk_super->fsid, | 467 | char fsid[BTRFS_FSID_SIZE]; |
| 414 | sizeof(node->header.fsid))) | 468 | |
| 415 | BUG(); | 469 | read_extent_buffer(buf, fsid, (unsigned long)btrfs_header_fsid(buf), |
| 470 | BTRFS_FSID_SIZE); | ||
| 471 | |||
| 472 | if (memcmp(fsid, root->fs_info->fsid, BTRFS_FSID_SIZE)) { | ||
| 473 | int i = 0; | ||
| 474 | printk("warning bad block %Lu\n", buf->start); | ||
| 475 | if (!btrfs_buffer_uptodate(buf)) { | ||
| 476 | WARN_ON(1); | ||
| 477 | } | ||
| 478 | for (i = 0; i < BTRFS_FSID_SIZE; i++) { | ||
| 479 | printk("%x:%x ", root->fs_info->fsid[i], fsid[i]); | ||
| 480 | } | ||
| 481 | printk("\n"); | ||
| 482 | // BUG(); | ||
| 483 | } | ||
| 416 | if (level == 0) | 484 | if (level == 0) |
| 417 | return check_leaf(root, path, level); | 485 | return check_leaf(root, path, level); |
| 418 | return check_node(root, path, level); | 486 | return check_node(root, path, level); |
| 419 | } | 487 | } |
| 420 | 488 | ||
| 421 | /* | 489 | /* |
| 422 | * search for key in the array p. items p are item_size apart | 490 | * search for key in the extent_buffer. The items start at offset p, |
| 423 | * and there are 'max' items in p | 491 | * and they are item_size apart. There are 'max' items in p. |
| 492 | * | ||
| 424 | * the slot in the array is returned via slot, and it points to | 493 | * the slot in the array is returned via slot, and it points to |
| 425 | * the place where you would insert key if it is not found in | 494 | * the place where you would insert key if it is not found in |
| 426 | * the array. | 495 | * the array. |
| 427 | * | 496 | * |
| 428 | * slot may point to max if the key is bigger than all of the keys | 497 | * slot may point to max if the key is bigger than all of the keys |
| 429 | */ | 498 | */ |
| 430 | static int generic_bin_search(char *p, int item_size, struct btrfs_key *key, | 499 | static int generic_bin_search(struct extent_buffer *eb, unsigned long p, |
| 431 | int max, int *slot) | 500 | int item_size, struct btrfs_key *key, |
| 501 | int max, int *slot) | ||
| 432 | { | 502 | { |
| 433 | int low = 0; | 503 | int low = 0; |
| 434 | int high = max; | 504 | int high = max; |
| 435 | int mid; | 505 | int mid; |
| 436 | int ret; | 506 | int ret; |
| 437 | struct btrfs_disk_key *tmp; | 507 | struct btrfs_disk_key *tmp; |
| 508 | struct btrfs_disk_key unaligned; | ||
| 509 | unsigned long offset; | ||
| 510 | char *map_token = NULL; | ||
| 511 | char *kaddr = NULL; | ||
| 512 | unsigned long map_start = 0; | ||
| 513 | unsigned long map_len = 0; | ||
| 438 | 514 | ||
| 439 | while(low < high) { | 515 | while(low < high) { |
| 440 | mid = (low + high) / 2; | 516 | mid = (low + high) / 2; |
| 441 | tmp = (struct btrfs_disk_key *)(p + mid * item_size); | 517 | offset = p + mid * item_size; |
| 518 | |||
| 519 | if (!map_token || offset < map_start || | ||
| 520 | (offset + sizeof(struct btrfs_disk_key)) > | ||
| 521 | map_start + map_len) { | ||
| 522 | if (map_token) | ||
| 523 | unmap_extent_buffer(eb, map_token, KM_USER0); | ||
| 524 | map_extent_buffer(eb, offset, &map_token, &kaddr, | ||
| 525 | &map_start, &map_len, KM_USER0); | ||
| 526 | |||
| 527 | } | ||
| 528 | if (offset + sizeof(struct btrfs_disk_key) > | ||
| 529 | map_start + map_len) { | ||
| 530 | unmap_extent_buffer(eb, map_token, KM_USER0); | ||
| 531 | read_extent_buffer(eb, &unaligned, | ||
| 532 | offset, sizeof(unaligned)); | ||
| 533 | map_token = NULL; | ||
| 534 | tmp = &unaligned; | ||
| 535 | } else { | ||
| 536 | tmp = (struct btrfs_disk_key *)(kaddr + offset - | ||
| 537 | map_start); | ||
| 538 | } | ||
| 442 | ret = comp_keys(tmp, key); | 539 | ret = comp_keys(tmp, key); |
| 443 | 540 | ||
| 444 | if (ret < 0) | 541 | if (ret < 0) |
| @@ -447,10 +544,13 @@ static int generic_bin_search(char *p, int item_size, struct btrfs_key *key, | |||
| 447 | high = mid; | 544 | high = mid; |
| 448 | else { | 545 | else { |
| 449 | *slot = mid; | 546 | *slot = mid; |
| 547 | unmap_extent_buffer(eb, map_token, KM_USER0); | ||
| 450 | return 0; | 548 | return 0; |
| 451 | } | 549 | } |
| 452 | } | 550 | } |
| 453 | *slot = low; | 551 | *slot = low; |
| 552 | if (map_token) | ||
| 553 | unmap_extent_buffer(eb, map_token, KM_USER0); | ||
| 454 | return 1; | 554 | return 1; |
| 455 | } | 555 | } |
| 456 | 556 | ||
| @@ -458,46 +558,42 @@ static int generic_bin_search(char *p, int item_size, struct btrfs_key *key, | |||
| 458 | * simple bin_search frontend that does the right thing for | 558 | * simple bin_search frontend that does the right thing for |
| 459 | * leaves vs nodes | 559 | * leaves vs nodes |
| 460 | */ | 560 | */ |
| 461 | static int bin_search(struct btrfs_node *c, struct btrfs_key *key, int *slot) | 561 | static int bin_search(struct extent_buffer *eb, struct btrfs_key *key, |
| 562 | int level, int *slot) | ||
| 462 | { | 563 | { |
| 463 | if (btrfs_is_leaf(c)) { | 564 | if (level == 0) { |
| 464 | struct btrfs_leaf *l = (struct btrfs_leaf *)c; | 565 | return generic_bin_search(eb, |
| 465 | return generic_bin_search((void *)l->items, | 566 | offsetof(struct btrfs_leaf, items), |
| 466 | sizeof(struct btrfs_item), | 567 | sizeof(struct btrfs_item), |
| 467 | key, btrfs_header_nritems(&c->header), | 568 | key, btrfs_header_nritems(eb), |
| 468 | slot); | 569 | slot); |
| 469 | } else { | 570 | } else { |
| 470 | return generic_bin_search((void *)c->ptrs, | 571 | return generic_bin_search(eb, |
| 572 | offsetof(struct btrfs_node, ptrs), | ||
| 471 | sizeof(struct btrfs_key_ptr), | 573 | sizeof(struct btrfs_key_ptr), |
| 472 | key, btrfs_header_nritems(&c->header), | 574 | key, btrfs_header_nritems(eb), |
| 473 | slot); | 575 | slot); |
| 474 | } | 576 | } |
| 475 | return -1; | 577 | return -1; |
| 476 | } | 578 | } |
| 477 | 579 | ||
| 478 | static struct buffer_head *read_node_slot(struct btrfs_root *root, | 580 | static struct extent_buffer *read_node_slot(struct btrfs_root *root, |
| 479 | struct buffer_head *parent_buf, | 581 | struct extent_buffer *parent, int slot) |
| 480 | int slot) | ||
| 481 | { | 582 | { |
| 482 | struct btrfs_node *node = btrfs_buffer_node(parent_buf); | ||
| 483 | if (slot < 0) | 583 | if (slot < 0) |
| 484 | return NULL; | 584 | return NULL; |
| 485 | if (slot >= btrfs_header_nritems(&node->header)) | 585 | if (slot >= btrfs_header_nritems(parent)) |
| 486 | return NULL; | 586 | return NULL; |
| 487 | return read_tree_block(root, btrfs_node_blockptr(node, slot)); | 587 | return read_tree_block(root, btrfs_node_blockptr(parent, slot)); |
| 488 | } | 588 | } |
| 489 | 589 | ||
| 490 | static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | 590 | static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root |
| 491 | *root, struct btrfs_path *path, int level) | 591 | *root, struct btrfs_path *path, int level) |
| 492 | { | 592 | { |
| 493 | struct buffer_head *right_buf; | 593 | struct extent_buffer *right = NULL; |
| 494 | struct buffer_head *mid_buf; | 594 | struct extent_buffer *mid; |
| 495 | struct buffer_head *left_buf; | 595 | struct extent_buffer *left = NULL; |
| 496 | struct buffer_head *parent_buf = NULL; | 596 | struct extent_buffer *parent = NULL; |
| 497 | struct btrfs_node *right = NULL; | ||
| 498 | struct btrfs_node *mid; | ||
| 499 | struct btrfs_node *left = NULL; | ||
| 500 | struct btrfs_node *parent = NULL; | ||
| 501 | int ret = 0; | 597 | int ret = 0; |
| 502 | int wret; | 598 | int wret; |
| 503 | int pslot; | 599 | int pslot; |
| @@ -508,60 +604,57 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 508 | if (level == 0) | 604 | if (level == 0) |
| 509 | return 0; | 605 | return 0; |
| 510 | 606 | ||
| 511 | mid_buf = path->nodes[level]; | 607 | mid = path->nodes[level]; |
| 512 | mid = btrfs_buffer_node(mid_buf); | ||
| 513 | orig_ptr = btrfs_node_blockptr(mid, orig_slot); | 608 | orig_ptr = btrfs_node_blockptr(mid, orig_slot); |
| 514 | 609 | ||
| 515 | if (level < BTRFS_MAX_LEVEL - 1) | 610 | if (level < BTRFS_MAX_LEVEL - 1) |
| 516 | parent_buf = path->nodes[level + 1]; | 611 | parent = path->nodes[level + 1]; |
| 517 | pslot = path->slots[level + 1]; | 612 | pslot = path->slots[level + 1]; |
| 518 | 613 | ||
| 519 | /* | 614 | /* |
| 520 | * deal with the case where there is only one pointer in the root | 615 | * deal with the case where there is only one pointer in the root |
| 521 | * by promoting the node below to a root | 616 | * by promoting the node below to a root |
| 522 | */ | 617 | */ |
| 523 | if (!parent_buf) { | 618 | if (!parent) { |
| 524 | struct buffer_head *child; | 619 | struct extent_buffer *child; |
| 525 | u64 blocknr = bh_blocknr(mid_buf); | 620 | u64 blocknr = extent_buffer_blocknr(mid); |
| 526 | 621 | ||
| 527 | if (btrfs_header_nritems(&mid->header) != 1) | 622 | if (btrfs_header_nritems(mid) != 1) |
| 528 | return 0; | 623 | return 0; |
| 529 | 624 | ||
| 530 | /* promote the child to a root */ | 625 | /* promote the child to a root */ |
| 531 | child = read_node_slot(root, mid_buf, 0); | 626 | child = read_node_slot(root, mid, 0); |
| 532 | BUG_ON(!child); | 627 | BUG_ON(!child); |
| 533 | root->node = child; | 628 | root->node = child; |
| 534 | path->nodes[level] = NULL; | 629 | path->nodes[level] = NULL; |
| 535 | clean_tree_block(trans, root, mid_buf); | 630 | clean_tree_block(trans, root, mid); |
| 536 | wait_on_buffer(mid_buf); | 631 | wait_on_tree_block_writeback(root, mid); |
| 537 | /* once for the path */ | 632 | /* once for the path */ |
| 538 | btrfs_block_release(root, mid_buf); | 633 | free_extent_buffer(mid); |
| 539 | /* once for the root ptr */ | 634 | /* once for the root ptr */ |
| 540 | btrfs_block_release(root, mid_buf); | 635 | free_extent_buffer(mid); |
| 541 | return btrfs_free_extent(trans, root, blocknr, 1, 1); | 636 | return btrfs_free_extent(trans, root, blocknr, 1, 1); |
| 542 | } | 637 | } |
| 543 | parent = btrfs_buffer_node(parent_buf); | 638 | if (btrfs_header_nritems(mid) > |
| 544 | |||
| 545 | if (btrfs_header_nritems(&mid->header) > | ||
| 546 | BTRFS_NODEPTRS_PER_BLOCK(root) / 4) | 639 | BTRFS_NODEPTRS_PER_BLOCK(root) / 4) |
| 547 | return 0; | 640 | return 0; |
| 548 | 641 | ||
| 549 | if (btrfs_header_nritems(&mid->header) < 2) | 642 | if (btrfs_header_nritems(mid) < 2) |
| 550 | err_on_enospc = 1; | 643 | err_on_enospc = 1; |
| 551 | 644 | ||
| 552 | left_buf = read_node_slot(root, parent_buf, pslot - 1); | 645 | left = read_node_slot(root, parent, pslot - 1); |
| 553 | if (left_buf) { | 646 | if (left) { |
| 554 | wret = btrfs_cow_block(trans, root, left_buf, | 647 | wret = btrfs_cow_block(trans, root, left, |
| 555 | parent_buf, pslot - 1, &left_buf); | 648 | parent, pslot - 1, &left); |
| 556 | if (wret) { | 649 | if (wret) { |
| 557 | ret = wret; | 650 | ret = wret; |
| 558 | goto enospc; | 651 | goto enospc; |
| 559 | } | 652 | } |
| 560 | } | 653 | } |
| 561 | right_buf = read_node_slot(root, parent_buf, pslot + 1); | 654 | right = read_node_slot(root, parent, pslot + 1); |
| 562 | if (right_buf) { | 655 | if (right) { |
| 563 | wret = btrfs_cow_block(trans, root, right_buf, | 656 | wret = btrfs_cow_block(trans, root, right, |
| 564 | parent_buf, pslot + 1, &right_buf); | 657 | parent, pslot + 1, &right); |
| 565 | if (wret) { | 658 | if (wret) { |
| 566 | ret = wret; | 659 | ret = wret; |
| 567 | goto enospc; | 660 | goto enospc; |
| @@ -569,30 +662,27 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 569 | } | 662 | } |
| 570 | 663 | ||
| 571 | /* first, try to make some room in the middle buffer */ | 664 | /* first, try to make some room in the middle buffer */ |
| 572 | if (left_buf) { | 665 | if (left) { |
| 573 | left = btrfs_buffer_node(left_buf); | 666 | orig_slot += btrfs_header_nritems(left); |
| 574 | orig_slot += btrfs_header_nritems(&left->header); | 667 | wret = push_node_left(trans, root, left, mid); |
| 575 | wret = push_node_left(trans, root, left_buf, mid_buf); | ||
| 576 | if (wret < 0) | 668 | if (wret < 0) |
| 577 | ret = wret; | 669 | ret = wret; |
| 578 | if (btrfs_header_nritems(&mid->header) < 2) | 670 | if (btrfs_header_nritems(mid) < 2) |
| 579 | err_on_enospc = 1; | 671 | err_on_enospc = 1; |
| 580 | } | 672 | } |
| 581 | 673 | ||
| 582 | /* | 674 | /* |
| 583 | * then try to empty the right most buffer into the middle | 675 | * then try to empty the right most buffer into the middle |
| 584 | */ | 676 | */ |
| 585 | if (right_buf) { | 677 | if (right) { |
| 586 | right = btrfs_buffer_node(right_buf); | 678 | wret = push_node_left(trans, root, mid, right); |
| 587 | wret = push_node_left(trans, root, mid_buf, right_buf); | ||
| 588 | if (wret < 0 && wret != -ENOSPC) | 679 | if (wret < 0 && wret != -ENOSPC) |
| 589 | ret = wret; | 680 | ret = wret; |
| 590 | if (btrfs_header_nritems(&right->header) == 0) { | 681 | if (btrfs_header_nritems(right) == 0) { |
| 591 | u64 blocknr = bh_blocknr(right_buf); | 682 | u64 blocknr = extent_buffer_blocknr(right); |
| 592 | clean_tree_block(trans, root, right_buf); | 683 | clean_tree_block(trans, root, right); |
| 593 | wait_on_buffer(right_buf); | 684 | wait_on_tree_block_writeback(root, right); |
| 594 | btrfs_block_release(root, right_buf); | 685 | free_extent_buffer(right); |
| 595 | right_buf = NULL; | ||
| 596 | right = NULL; | 686 | right = NULL; |
| 597 | wret = del_ptr(trans, root, path, level + 1, pslot + | 687 | wret = del_ptr(trans, root, path, level + 1, pslot + |
| 598 | 1); | 688 | 1); |
| @@ -602,14 +692,13 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 602 | if (wret) | 692 | if (wret) |
| 603 | ret = wret; | 693 | ret = wret; |
| 604 | } else { | 694 | } else { |
| 605 | btrfs_memcpy(root, parent, | 695 | struct btrfs_disk_key right_key; |
| 606 | &parent->ptrs[pslot + 1].key, | 696 | btrfs_node_key(right, &right_key, 0); |
| 607 | &right->ptrs[0].key, | 697 | btrfs_set_node_key(parent, &right_key, pslot + 1); |
| 608 | sizeof(struct btrfs_disk_key)); | 698 | btrfs_mark_buffer_dirty(parent); |
| 609 | btrfs_mark_buffer_dirty(parent_buf); | ||
| 610 | } | 699 | } |
| 611 | } | 700 | } |
| 612 | if (btrfs_header_nritems(&mid->header) == 1) { | 701 | if (btrfs_header_nritems(mid) == 1) { |
| 613 | /* | 702 | /* |
| 614 | * we're not allowed to leave a node with one item in the | 703 | * we're not allowed to leave a node with one item in the |
| 615 | * tree during a delete. A deletion from lower in the tree | 704 | * tree during a delete. A deletion from lower in the tree |
| @@ -619,21 +708,20 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 619 | * otherwise we would have pulled some pointers from the | 708 | * otherwise we would have pulled some pointers from the |
| 620 | * right | 709 | * right |
| 621 | */ | 710 | */ |
| 622 | BUG_ON(!left_buf); | 711 | BUG_ON(!left); |
| 623 | wret = balance_node_right(trans, root, mid_buf, left_buf); | 712 | wret = balance_node_right(trans, root, mid, left); |
| 624 | if (wret < 0) { | 713 | if (wret < 0) { |
| 625 | ret = wret; | 714 | ret = wret; |
| 626 | goto enospc; | 715 | goto enospc; |
| 627 | } | 716 | } |
| 628 | BUG_ON(wret == 1); | 717 | BUG_ON(wret == 1); |
| 629 | } | 718 | } |
| 630 | if (btrfs_header_nritems(&mid->header) == 0) { | 719 | if (btrfs_header_nritems(mid) == 0) { |
| 631 | /* we've managed to empty the middle node, drop it */ | 720 | /* we've managed to empty the middle node, drop it */ |
| 632 | u64 blocknr = bh_blocknr(mid_buf); | 721 | u64 blocknr = extent_buffer_blocknr(mid); |
| 633 | clean_tree_block(trans, root, mid_buf); | 722 | clean_tree_block(trans, root, mid); |
| 634 | wait_on_buffer(mid_buf); | 723 | wait_on_tree_block_writeback(root, mid); |
| 635 | btrfs_block_release(root, mid_buf); | 724 | free_extent_buffer(mid); |
| 636 | mid_buf = NULL; | ||
| 637 | mid = NULL; | 725 | mid = NULL; |
| 638 | wret = del_ptr(trans, root, path, level + 1, pslot); | 726 | wret = del_ptr(trans, root, path, level + 1, pslot); |
| 639 | if (wret) | 727 | if (wret) |
| @@ -643,37 +731,36 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 643 | ret = wret; | 731 | ret = wret; |
| 644 | } else { | 732 | } else { |
| 645 | /* update the parent key to reflect our changes */ | 733 | /* update the parent key to reflect our changes */ |
| 646 | btrfs_memcpy(root, parent, | 734 | struct btrfs_disk_key mid_key; |
| 647 | &parent->ptrs[pslot].key, &mid->ptrs[0].key, | 735 | btrfs_node_key(mid, &mid_key, 0); |
| 648 | sizeof(struct btrfs_disk_key)); | 736 | btrfs_set_node_key(parent, &mid_key, pslot); |
| 649 | btrfs_mark_buffer_dirty(parent_buf); | 737 | btrfs_mark_buffer_dirty(parent); |
| 650 | } | 738 | } |
| 651 | 739 | ||
| 652 | /* update the path */ | 740 | /* update the path */ |
| 653 | if (left_buf) { | 741 | if (left) { |
| 654 | if (btrfs_header_nritems(&left->header) > orig_slot) { | 742 | if (btrfs_header_nritems(left) > orig_slot) { |
| 655 | get_bh(left_buf); | 743 | extent_buffer_get(left); |
| 656 | path->nodes[level] = left_buf; | 744 | path->nodes[level] = left; |
| 657 | path->slots[level + 1] -= 1; | 745 | path->slots[level + 1] -= 1; |
| 658 | path->slots[level] = orig_slot; | 746 | path->slots[level] = orig_slot; |
| 659 | if (mid_buf) | 747 | if (mid) |
| 660 | btrfs_block_release(root, mid_buf); | 748 | free_extent_buffer(mid); |
| 661 | } else { | 749 | } else { |
| 662 | orig_slot -= btrfs_header_nritems(&left->header); | 750 | orig_slot -= btrfs_header_nritems(left); |
| 663 | path->slots[level] = orig_slot; | 751 | path->slots[level] = orig_slot; |
| 664 | } | 752 | } |
| 665 | } | 753 | } |
| 666 | /* double check we haven't messed things up */ | 754 | /* double check we haven't messed things up */ |
| 667 | check_block(root, path, level); | 755 | check_block(root, path, level); |
| 668 | if (orig_ptr != | 756 | if (orig_ptr != |
| 669 | btrfs_node_blockptr(btrfs_buffer_node(path->nodes[level]), | 757 | btrfs_node_blockptr(path->nodes[level], path->slots[level])) |
| 670 | path->slots[level])) | ||
| 671 | BUG(); | 758 | BUG(); |
| 672 | enospc: | 759 | enospc: |
| 673 | if (right_buf) | 760 | if (right) |
| 674 | btrfs_block_release(root, right_buf); | 761 | free_extent_buffer(right); |
| 675 | if (left_buf) | 762 | if (left) |
| 676 | btrfs_block_release(root, left_buf); | 763 | free_extent_buffer(left); |
| 677 | return ret; | 764 | return ret; |
| 678 | } | 765 | } |
| 679 | 766 | ||
| @@ -682,14 +769,10 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
| 682 | struct btrfs_root *root, | 769 | struct btrfs_root *root, |
| 683 | struct btrfs_path *path, int level) | 770 | struct btrfs_path *path, int level) |
| 684 | { | 771 | { |
| 685 | struct buffer_head *right_buf; | 772 | struct extent_buffer *right = NULL; |
| 686 | struct buffer_head *mid_buf; | 773 | struct extent_buffer *mid; |
| 687 | struct buffer_head *left_buf; | 774 | struct extent_buffer *left = NULL; |
| 688 | struct buffer_head *parent_buf = NULL; | 775 | struct extent_buffer *parent = NULL; |
| 689 | struct btrfs_node *right = NULL; | ||
| 690 | struct btrfs_node *mid; | ||
| 691 | struct btrfs_node *left = NULL; | ||
| 692 | struct btrfs_node *parent = NULL; | ||
| 693 | int ret = 0; | 776 | int ret = 0; |
| 694 | int wret; | 777 | int wret; |
| 695 | int pslot; | 778 | int pslot; |
| @@ -699,107 +782,101 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
| 699 | if (level == 0) | 782 | if (level == 0) |
| 700 | return 1; | 783 | return 1; |
| 701 | 784 | ||
| 702 | mid_buf = path->nodes[level]; | 785 | mid = path->nodes[level]; |
| 703 | mid = btrfs_buffer_node(mid_buf); | ||
| 704 | orig_ptr = btrfs_node_blockptr(mid, orig_slot); | 786 | orig_ptr = btrfs_node_blockptr(mid, orig_slot); |
| 705 | 787 | ||
| 706 | if (level < BTRFS_MAX_LEVEL - 1) | 788 | if (level < BTRFS_MAX_LEVEL - 1) |
| 707 | parent_buf = path->nodes[level + 1]; | 789 | parent = path->nodes[level + 1]; |
| 708 | pslot = path->slots[level + 1]; | 790 | pslot = path->slots[level + 1]; |
| 709 | 791 | ||
| 710 | if (!parent_buf) | 792 | if (!parent) |
| 711 | return 1; | 793 | return 1; |
| 712 | parent = btrfs_buffer_node(parent_buf); | ||
| 713 | 794 | ||
| 714 | left_buf = read_node_slot(root, parent_buf, pslot - 1); | 795 | left = read_node_slot(root, parent, pslot - 1); |
| 715 | 796 | ||
| 716 | /* first, try to make some room in the middle buffer */ | 797 | /* first, try to make some room in the middle buffer */ |
| 717 | if (left_buf) { | 798 | if (left) { |
| 718 | u32 left_nr; | 799 | u32 left_nr; |
| 719 | left = btrfs_buffer_node(left_buf); | 800 | left_nr = btrfs_header_nritems(left); |
| 720 | left_nr = btrfs_header_nritems(&left->header); | ||
| 721 | if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { | 801 | if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { |
| 722 | wret = 1; | 802 | wret = 1; |
| 723 | } else { | 803 | } else { |
| 724 | ret = btrfs_cow_block(trans, root, left_buf, parent_buf, | 804 | ret = btrfs_cow_block(trans, root, left, parent, |
| 725 | pslot - 1, &left_buf); | 805 | pslot - 1, &left); |
| 726 | if (ret) | 806 | if (ret) |
| 727 | wret = 1; | 807 | wret = 1; |
| 728 | else { | 808 | else { |
| 729 | left = btrfs_buffer_node(left_buf); | ||
| 730 | wret = push_node_left(trans, root, | 809 | wret = push_node_left(trans, root, |
| 731 | left_buf, mid_buf); | 810 | left, mid); |
| 732 | } | 811 | } |
| 733 | } | 812 | } |
| 734 | if (wret < 0) | 813 | if (wret < 0) |
| 735 | ret = wret; | 814 | ret = wret; |
| 736 | if (wret == 0) { | 815 | if (wret == 0) { |
| 816 | struct btrfs_disk_key disk_key; | ||
| 737 | orig_slot += left_nr; | 817 | orig_slot += left_nr; |
| 738 | btrfs_memcpy(root, parent, | 818 | btrfs_node_key(mid, &disk_key, 0); |
| 739 | &parent->ptrs[pslot].key, | 819 | btrfs_set_node_key(parent, &disk_key, pslot); |
| 740 | &mid->ptrs[0].key, | 820 | btrfs_mark_buffer_dirty(parent); |
| 741 | sizeof(struct btrfs_disk_key)); | 821 | if (btrfs_header_nritems(left) > orig_slot) { |
| 742 | btrfs_mark_buffer_dirty(parent_buf); | 822 | path->nodes[level] = left; |
| 743 | if (btrfs_header_nritems(&left->header) > orig_slot) { | ||
| 744 | path->nodes[level] = left_buf; | ||
| 745 | path->slots[level + 1] -= 1; | 823 | path->slots[level + 1] -= 1; |
| 746 | path->slots[level] = orig_slot; | 824 | path->slots[level] = orig_slot; |
| 747 | btrfs_block_release(root, mid_buf); | 825 | free_extent_buffer(mid); |
| 748 | } else { | 826 | } else { |
| 749 | orig_slot -= | 827 | orig_slot -= |
| 750 | btrfs_header_nritems(&left->header); | 828 | btrfs_header_nritems(left); |
| 751 | path->slots[level] = orig_slot; | 829 | path->slots[level] = orig_slot; |
| 752 | btrfs_block_release(root, left_buf); | 830 | free_extent_buffer(left); |
| 753 | } | 831 | } |
| 754 | check_node(root, path, level); | 832 | check_node(root, path, level); |
| 755 | return 0; | 833 | return 0; |
| 756 | } | 834 | } |
| 757 | btrfs_block_release(root, left_buf); | 835 | free_extent_buffer(left); |
| 758 | } | 836 | } |
| 759 | right_buf = read_node_slot(root, parent_buf, pslot + 1); | 837 | right= read_node_slot(root, parent, pslot + 1); |
| 760 | 838 | ||
| 761 | /* | 839 | /* |
| 762 | * then try to empty the right most buffer into the middle | 840 | * then try to empty the right most buffer into the middle |
| 763 | */ | 841 | */ |
| 764 | if (right_buf) { | 842 | if (right) { |
| 765 | u32 right_nr; | 843 | u32 right_nr; |
| 766 | right = btrfs_buffer_node(right_buf); | 844 | right_nr = btrfs_header_nritems(right); |
| 767 | right_nr = btrfs_header_nritems(&right->header); | ||
| 768 | if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { | 845 | if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { |
| 769 | wret = 1; | 846 | wret = 1; |
| 770 | } else { | 847 | } else { |
| 771 | ret = btrfs_cow_block(trans, root, right_buf, | 848 | ret = btrfs_cow_block(trans, root, right, |
| 772 | parent_buf, pslot + 1, | 849 | parent, pslot + 1, |
| 773 | &right_buf); | 850 | &right); |
| 774 | if (ret) | 851 | if (ret) |
| 775 | wret = 1; | 852 | wret = 1; |
| 776 | else { | 853 | else { |
| 777 | right = btrfs_buffer_node(right_buf); | ||
| 778 | wret = balance_node_right(trans, root, | 854 | wret = balance_node_right(trans, root, |
| 779 | right_buf, mid_buf); | 855 | right, mid); |
| 780 | } | 856 | } |
| 781 | } | 857 | } |
| 782 | if (wret < 0) | 858 | if (wret < 0) |
| 783 | ret = wret; | 859 | ret = wret; |
| 784 | if (wret == 0) { | 860 | if (wret == 0) { |
| 785 | btrfs_memcpy(root, parent, | 861 | struct btrfs_disk_key disk_key; |
| 786 | &parent->ptrs[pslot + 1].key, | 862 | |
| 787 | &right->ptrs[0].key, | 863 | btrfs_node_key(right, &disk_key, 0); |
| 788 | sizeof(struct btrfs_disk_key)); | 864 | btrfs_set_node_key(parent, &disk_key, pslot + 1); |
| 789 | btrfs_mark_buffer_dirty(parent_buf); | 865 | btrfs_mark_buffer_dirty(parent); |
| 790 | if (btrfs_header_nritems(&mid->header) <= orig_slot) { | 866 | |
| 791 | path->nodes[level] = right_buf; | 867 | if (btrfs_header_nritems(mid) <= orig_slot) { |
| 868 | path->nodes[level] = right; | ||
| 792 | path->slots[level + 1] += 1; | 869 | path->slots[level + 1] += 1; |
| 793 | path->slots[level] = orig_slot - | 870 | path->slots[level] = orig_slot - |
| 794 | btrfs_header_nritems(&mid->header); | 871 | btrfs_header_nritems(mid); |
| 795 | btrfs_block_release(root, mid_buf); | 872 | free_extent_buffer(mid); |
| 796 | } else { | 873 | } else { |
| 797 | btrfs_block_release(root, right_buf); | 874 | free_extent_buffer(right); |
| 798 | } | 875 | } |
| 799 | check_node(root, path, level); | 876 | check_node(root, path, level); |
| 800 | return 0; | 877 | return 0; |
| 801 | } | 878 | } |
| 802 | btrfs_block_release(root, right_buf); | 879 | free_extent_buffer(right); |
| 803 | } | 880 | } |
| 804 | check_node(root, path, level); | 881 | check_node(root, path, level); |
| 805 | return 1; | 882 | return 1; |
| @@ -811,10 +888,9 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
| 811 | static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path, | 888 | static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path, |
| 812 | int level, int slot) | 889 | int level, int slot) |
| 813 | { | 890 | { |
| 814 | struct btrfs_node *node; | 891 | struct extent_buffer *node; |
| 815 | int i; | 892 | int i; |
| 816 | u32 nritems; | 893 | u32 nritems; |
| 817 | u64 item_objectid; | ||
| 818 | u64 blocknr; | 894 | u64 blocknr; |
| 819 | u64 search; | 895 | u64 search; |
| 820 | u64 cluster_start; | 896 | u64 cluster_start; |
| @@ -823,7 +899,7 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path, | |||
| 823 | int direction = path->reada; | 899 | int direction = path->reada; |
| 824 | struct radix_tree_root found; | 900 | struct radix_tree_root found; |
| 825 | unsigned long gang[8]; | 901 | unsigned long gang[8]; |
| 826 | struct buffer_head *bh; | 902 | struct extent_buffer *eb; |
| 827 | 903 | ||
| 828 | if (level == 0) | 904 | if (level == 0) |
| 829 | return; | 905 | return; |
| @@ -831,18 +907,17 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path, | |||
| 831 | if (!path->nodes[level]) | 907 | if (!path->nodes[level]) |
| 832 | return; | 908 | return; |
| 833 | 909 | ||
| 834 | node = btrfs_buffer_node(path->nodes[level]); | 910 | node = path->nodes[level]; |
| 835 | search = btrfs_node_blockptr(node, slot); | 911 | search = btrfs_node_blockptr(node, slot); |
| 836 | bh = btrfs_find_tree_block(root, search); | 912 | eb = btrfs_find_tree_block(root, search); |
| 837 | if (bh) { | 913 | if (eb) { |
| 838 | brelse(bh); | 914 | free_extent_buffer(eb); |
| 839 | return; | 915 | return; |
| 840 | } | 916 | } |
| 841 | 917 | ||
| 842 | init_bit_radix(&found); | 918 | init_bit_radix(&found); |
| 843 | nritems = btrfs_header_nritems(&node->header); | 919 | nritems = btrfs_header_nritems(node); |
| 844 | for (i = slot; i < nritems; i++) { | 920 | for (i = slot; i < nritems; i++) { |
| 845 | item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key); | ||
| 846 | blocknr = btrfs_node_blockptr(node, i); | 921 | blocknr = btrfs_node_blockptr(node, i); |
| 847 | set_radix_bit(&found, blocknr); | 922 | set_radix_bit(&found, blocknr); |
| 848 | } | 923 | } |
| @@ -886,8 +961,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 886 | *root, struct btrfs_key *key, struct btrfs_path *p, int | 961 | *root, struct btrfs_key *key, struct btrfs_path *p, int |
| 887 | ins_len, int cow) | 962 | ins_len, int cow) |
| 888 | { | 963 | { |
| 889 | struct buffer_head *b; | 964 | struct extent_buffer *b; |
| 890 | struct btrfs_node *c; | ||
| 891 | u64 blocknr; | 965 | u64 blocknr; |
| 892 | int slot; | 966 | int slot; |
| 893 | int ret; | 967 | int ret; |
| @@ -901,10 +975,9 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 901 | WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex)); | 975 | WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex)); |
| 902 | again: | 976 | again: |
| 903 | b = root->node; | 977 | b = root->node; |
| 904 | get_bh(b); | 978 | extent_buffer_get(b); |
| 905 | while (b) { | 979 | while (b) { |
| 906 | c = btrfs_buffer_node(b); | 980 | level = btrfs_header_level(b); |
| 907 | level = btrfs_header_level(&c->header); | ||
| 908 | if (cow) { | 981 | if (cow) { |
| 909 | int wret; | 982 | int wret; |
| 910 | wret = btrfs_cow_block(trans, root, b, | 983 | wret = btrfs_cow_block(trans, root, b, |
| @@ -912,32 +985,30 @@ again: | |||
| 912 | p->slots[level + 1], | 985 | p->slots[level + 1], |
| 913 | &b); | 986 | &b); |
| 914 | if (wret) { | 987 | if (wret) { |
| 915 | btrfs_block_release(root, b); | 988 | free_extent_buffer(b); |
| 916 | return wret; | 989 | return wret; |
| 917 | } | 990 | } |
| 918 | c = btrfs_buffer_node(b); | ||
| 919 | } | 991 | } |
| 920 | BUG_ON(!cow && ins_len); | 992 | BUG_ON(!cow && ins_len); |
| 921 | if (level != btrfs_header_level(&c->header)) | 993 | if (level != btrfs_header_level(b)) |
| 922 | WARN_ON(1); | 994 | WARN_ON(1); |
| 923 | level = btrfs_header_level(&c->header); | 995 | level = btrfs_header_level(b); |
| 924 | p->nodes[level] = b; | 996 | p->nodes[level] = b; |
| 925 | ret = check_block(root, p, level); | 997 | ret = check_block(root, p, level); |
| 926 | if (ret) | 998 | if (ret) |
| 927 | return -1; | 999 | return -1; |
| 928 | ret = bin_search(c, key, &slot); | 1000 | ret = bin_search(b, key, level, &slot); |
| 929 | if (!btrfs_is_leaf(c)) { | 1001 | if (level != 0) { |
| 930 | if (ret && slot > 0) | 1002 | if (ret && slot > 0) |
| 931 | slot -= 1; | 1003 | slot -= 1; |
| 932 | p->slots[level] = slot; | 1004 | p->slots[level] = slot; |
| 933 | if (ins_len > 0 && btrfs_header_nritems(&c->header) >= | 1005 | if (ins_len > 0 && btrfs_header_nritems(b) >= |
| 934 | BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { | 1006 | BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { |
| 935 | int sret = split_node(trans, root, p, level); | 1007 | int sret = split_node(trans, root, p, level); |
| 936 | BUG_ON(sret > 0); | 1008 | BUG_ON(sret > 0); |
| 937 | if (sret) | 1009 | if (sret) |
| 938 | return sret; | 1010 | return sret; |
| 939 | b = p->nodes[level]; | 1011 | b = p->nodes[level]; |
| 940 | c = btrfs_buffer_node(b); | ||
| 941 | slot = p->slots[level]; | 1012 | slot = p->slots[level]; |
| 942 | } else if (ins_len < 0) { | 1013 | } else if (ins_len < 0) { |
| 943 | int sret = balance_level(trans, root, p, | 1014 | int sret = balance_level(trans, root, p, |
| @@ -947,22 +1018,19 @@ again: | |||
| 947 | b = p->nodes[level]; | 1018 | b = p->nodes[level]; |
| 948 | if (!b) | 1019 | if (!b) |
| 949 | goto again; | 1020 | goto again; |
| 950 | c = btrfs_buffer_node(b); | ||
| 951 | slot = p->slots[level]; | 1021 | slot = p->slots[level]; |
| 952 | BUG_ON(btrfs_header_nritems(&c->header) == 1); | 1022 | BUG_ON(btrfs_header_nritems(b) == 1); |
| 953 | } | 1023 | } |
| 954 | /* this is only true while dropping a snapshot */ | 1024 | /* this is only true while dropping a snapshot */ |
| 955 | if (level == lowest_level) | 1025 | if (level == lowest_level) |
| 956 | break; | 1026 | break; |
| 957 | blocknr = btrfs_node_blockptr(c, slot); | 1027 | blocknr = btrfs_node_blockptr(b, slot); |
| 958 | if (should_reada) | 1028 | if (should_reada) |
| 959 | reada_for_search(root, p, level, slot); | 1029 | reada_for_search(root, p, level, slot); |
| 960 | b = read_tree_block(root, btrfs_node_blockptr(c, slot)); | 1030 | b = read_tree_block(root, btrfs_node_blockptr(b, slot)); |
| 961 | |||
| 962 | } else { | 1031 | } else { |
| 963 | struct btrfs_leaf *l = (struct btrfs_leaf *)c; | ||
| 964 | p->slots[level] = slot; | 1032 | p->slots[level] = slot; |
| 965 | if (ins_len > 0 && btrfs_leaf_free_space(root, l) < | 1033 | if (ins_len > 0 && btrfs_leaf_free_space(root, b) < |
| 966 | sizeof(struct btrfs_item) + ins_len) { | 1034 | sizeof(struct btrfs_item) + ins_len) { |
| 967 | int sret = split_leaf(trans, root, key, | 1035 | int sret = split_leaf(trans, root, key, |
| 968 | p, ins_len); | 1036 | p, ins_len); |
| @@ -986,19 +1054,20 @@ again: | |||
| 986 | * If this fails to write a tree block, it returns -1, but continues | 1054 | * If this fails to write a tree block, it returns -1, but continues |
| 987 | * fixing up the blocks in ram so the tree is consistent. | 1055 | * fixing up the blocks in ram so the tree is consistent. |
| 988 | */ | 1056 | */ |
| 989 | static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root | 1057 | static int fixup_low_keys(struct btrfs_trans_handle *trans, |
| 990 | *root, struct btrfs_path *path, struct btrfs_disk_key | 1058 | struct btrfs_root *root, struct btrfs_path *path, |
| 991 | *key, int level) | 1059 | struct btrfs_disk_key *key, int level) |
| 992 | { | 1060 | { |
| 993 | int i; | 1061 | int i; |
| 994 | int ret = 0; | 1062 | int ret = 0; |
| 1063 | struct extent_buffer *t; | ||
| 1064 | |||
| 995 | for (i = level; i < BTRFS_MAX_LEVEL; i++) { | 1065 | for (i = level; i < BTRFS_MAX_LEVEL; i++) { |
| 996 | struct btrfs_node *t; | ||
| 997 | int tslot = path->slots[i]; | 1066 | int tslot = path->slots[i]; |
| 998 | if (!path->nodes[i]) | 1067 | if (!path->nodes[i]) |
| 999 | break; | 1068 | break; |
| 1000 | t = btrfs_buffer_node(path->nodes[i]); | 1069 | t = path->nodes[i]; |
| 1001 | btrfs_memcpy(root, t, &t->ptrs[tslot].key, key, sizeof(*key)); | 1070 | btrfs_set_node_key(t, key, tslot); |
| 1002 | btrfs_mark_buffer_dirty(path->nodes[i]); | 1071 | btrfs_mark_buffer_dirty(path->nodes[i]); |
| 1003 | if (tslot != 0) | 1072 | if (tslot != 0) |
| 1004 | break; | 1073 | break; |
| @@ -1014,18 +1083,16 @@ static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1014 | * error, and > 0 if there was no room in the left hand block. | 1083 | * error, and > 0 if there was no room in the left hand block. |
| 1015 | */ | 1084 | */ |
| 1016 | static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root | 1085 | static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root |
| 1017 | *root, struct buffer_head *dst_buf, struct | 1086 | *root, struct extent_buffer *dst, |
| 1018 | buffer_head *src_buf) | 1087 | struct extent_buffer *src) |
| 1019 | { | 1088 | { |
| 1020 | struct btrfs_node *src = btrfs_buffer_node(src_buf); | ||
| 1021 | struct btrfs_node *dst = btrfs_buffer_node(dst_buf); | ||
| 1022 | int push_items = 0; | 1089 | int push_items = 0; |
| 1023 | int src_nritems; | 1090 | int src_nritems; |
| 1024 | int dst_nritems; | 1091 | int dst_nritems; |
| 1025 | int ret = 0; | 1092 | int ret = 0; |
| 1026 | 1093 | ||
| 1027 | src_nritems = btrfs_header_nritems(&src->header); | 1094 | src_nritems = btrfs_header_nritems(src); |
| 1028 | dst_nritems = btrfs_header_nritems(&dst->header); | 1095 | dst_nritems = btrfs_header_nritems(dst); |
| 1029 | push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; | 1096 | push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; |
| 1030 | 1097 | ||
| 1031 | if (push_items <= 0) { | 1098 | if (push_items <= 0) { |
| @@ -1035,17 +1102,21 @@ static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1035 | if (src_nritems < push_items) | 1102 | if (src_nritems < push_items) |
| 1036 | push_items = src_nritems; | 1103 | push_items = src_nritems; |
| 1037 | 1104 | ||
| 1038 | btrfs_memcpy(root, dst, dst->ptrs + dst_nritems, src->ptrs, | 1105 | copy_extent_buffer(dst, src, |
| 1039 | push_items * sizeof(struct btrfs_key_ptr)); | 1106 | btrfs_node_key_ptr_offset(dst_nritems), |
| 1107 | btrfs_node_key_ptr_offset(0), | ||
| 1108 | push_items * sizeof(struct btrfs_key_ptr)); | ||
| 1109 | |||
| 1040 | if (push_items < src_nritems) { | 1110 | if (push_items < src_nritems) { |
| 1041 | btrfs_memmove(root, src, src->ptrs, src->ptrs + push_items, | 1111 | memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0), |
| 1042 | (src_nritems - push_items) * | 1112 | btrfs_node_key_ptr_offset(push_items), |
| 1043 | sizeof(struct btrfs_key_ptr)); | 1113 | (src_nritems - push_items) * |
| 1044 | } | 1114 | sizeof(struct btrfs_key_ptr)); |
| 1045 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); | 1115 | } |
| 1046 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); | 1116 | btrfs_set_header_nritems(src, src_nritems - push_items); |
| 1047 | btrfs_mark_buffer_dirty(src_buf); | 1117 | btrfs_set_header_nritems(dst, dst_nritems + push_items); |
| 1048 | btrfs_mark_buffer_dirty(dst_buf); | 1118 | btrfs_mark_buffer_dirty(src); |
| 1119 | btrfs_mark_buffer_dirty(dst); | ||
| 1049 | return ret; | 1120 | return ret; |
| 1050 | } | 1121 | } |
| 1051 | 1122 | ||
| @@ -1058,24 +1129,22 @@ static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1058 | * | 1129 | * |
| 1059 | * this will only push up to 1/2 the contents of the left node over | 1130 | * this will only push up to 1/2 the contents of the left node over |
| 1060 | */ | 1131 | */ |
| 1061 | static int balance_node_right(struct btrfs_trans_handle *trans, struct | 1132 | static int balance_node_right(struct btrfs_trans_handle *trans, |
| 1062 | btrfs_root *root, struct buffer_head *dst_buf, | 1133 | struct btrfs_root *root, |
| 1063 | struct buffer_head *src_buf) | 1134 | struct extent_buffer *dst, |
| 1135 | struct extent_buffer *src) | ||
| 1064 | { | 1136 | { |
| 1065 | struct btrfs_node *src = btrfs_buffer_node(src_buf); | ||
| 1066 | struct btrfs_node *dst = btrfs_buffer_node(dst_buf); | ||
| 1067 | int push_items = 0; | 1137 | int push_items = 0; |
| 1068 | int max_push; | 1138 | int max_push; |
| 1069 | int src_nritems; | 1139 | int src_nritems; |
| 1070 | int dst_nritems; | 1140 | int dst_nritems; |
| 1071 | int ret = 0; | 1141 | int ret = 0; |
| 1072 | 1142 | ||
| 1073 | src_nritems = btrfs_header_nritems(&src->header); | 1143 | src_nritems = btrfs_header_nritems(src); |
| 1074 | dst_nritems = btrfs_header_nritems(&dst->header); | 1144 | dst_nritems = btrfs_header_nritems(dst); |
| 1075 | push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; | 1145 | push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; |
| 1076 | if (push_items <= 0) { | 1146 | if (push_items <= 0) |
| 1077 | return 1; | 1147 | return 1; |
| 1078 | } | ||
| 1079 | 1148 | ||
| 1080 | max_push = src_nritems / 2 + 1; | 1149 | max_push = src_nritems / 2 + 1; |
| 1081 | /* don't try to empty the node */ | 1150 | /* don't try to empty the node */ |
| @@ -1085,18 +1154,21 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct | |||
| 1085 | if (max_push < push_items) | 1154 | if (max_push < push_items) |
| 1086 | push_items = max_push; | 1155 | push_items = max_push; |
| 1087 | 1156 | ||
| 1088 | btrfs_memmove(root, dst, dst->ptrs + push_items, dst->ptrs, | 1157 | memmove_extent_buffer(dst, btrfs_node_key_ptr_offset(push_items), |
| 1089 | dst_nritems * sizeof(struct btrfs_key_ptr)); | 1158 | btrfs_node_key_ptr_offset(0), |
| 1159 | (dst_nritems) * | ||
| 1160 | sizeof(struct btrfs_key_ptr)); | ||
| 1090 | 1161 | ||
| 1091 | btrfs_memcpy(root, dst, dst->ptrs, | 1162 | copy_extent_buffer(dst, src, |
| 1092 | src->ptrs + src_nritems - push_items, | 1163 | btrfs_node_key_ptr_offset(0), |
| 1093 | push_items * sizeof(struct btrfs_key_ptr)); | 1164 | btrfs_node_key_ptr_offset(src_nritems - push_items), |
| 1165 | push_items * sizeof(struct btrfs_key_ptr)); | ||
| 1094 | 1166 | ||
| 1095 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); | 1167 | btrfs_set_header_nritems(src, src_nritems - push_items); |
| 1096 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); | 1168 | btrfs_set_header_nritems(dst, dst_nritems + push_items); |
| 1097 | 1169 | ||
| 1098 | btrfs_mark_buffer_dirty(src_buf); | 1170 | btrfs_mark_buffer_dirty(src); |
| 1099 | btrfs_mark_buffer_dirty(dst_buf); | 1171 | btrfs_mark_buffer_dirty(dst); |
| 1100 | return ret; | 1172 | return ret; |
| 1101 | } | 1173 | } |
| 1102 | 1174 | ||
| @@ -1107,45 +1179,46 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct | |||
| 1107 | * | 1179 | * |
| 1108 | * returns zero on success or < 0 on failure. | 1180 | * returns zero on success or < 0 on failure. |
| 1109 | */ | 1181 | */ |
| 1110 | static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root | 1182 | static int insert_new_root(struct btrfs_trans_handle *trans, |
| 1111 | *root, struct btrfs_path *path, int level) | 1183 | struct btrfs_root *root, |
| 1184 | struct btrfs_path *path, int level) | ||
| 1112 | { | 1185 | { |
| 1113 | struct buffer_head *t; | 1186 | struct extent_buffer *lower; |
| 1114 | struct btrfs_node *lower; | 1187 | struct extent_buffer *c; |
| 1115 | struct btrfs_node *c; | 1188 | struct btrfs_disk_key lower_key; |
| 1116 | struct btrfs_disk_key *lower_key; | ||
| 1117 | 1189 | ||
| 1118 | BUG_ON(path->nodes[level]); | 1190 | BUG_ON(path->nodes[level]); |
| 1119 | BUG_ON(path->nodes[level-1] != root->node); | 1191 | BUG_ON(path->nodes[level-1] != root->node); |
| 1120 | 1192 | ||
| 1121 | t = btrfs_alloc_free_block(trans, root, root->node->b_blocknr, 0); | 1193 | c = btrfs_alloc_free_block(trans, root, |
| 1122 | if (IS_ERR(t)) | 1194 | extent_buffer_blocknr(root->node), 0); |
| 1123 | return PTR_ERR(t); | 1195 | if (IS_ERR(c)) |
| 1124 | c = btrfs_buffer_node(t); | 1196 | return PTR_ERR(c); |
| 1125 | memset(c, 0, root->blocksize); | 1197 | memset_extent_buffer(c, 0, 0, root->nodesize); |
| 1126 | btrfs_set_header_nritems(&c->header, 1); | 1198 | btrfs_set_header_nritems(c, 1); |
| 1127 | btrfs_set_header_level(&c->header, level); | 1199 | btrfs_set_header_level(c, level); |
| 1128 | btrfs_set_header_blocknr(&c->header, bh_blocknr(t)); | 1200 | btrfs_set_header_blocknr(c, extent_buffer_blocknr(c)); |
| 1129 | btrfs_set_header_generation(&c->header, trans->transid); | 1201 | btrfs_set_header_generation(c, trans->transid); |
| 1130 | btrfs_set_header_owner(&c->header, root->root_key.objectid); | 1202 | btrfs_set_header_owner(c, root->root_key.objectid); |
| 1131 | lower = btrfs_buffer_node(path->nodes[level-1]); | 1203 | lower = path->nodes[level-1]; |
| 1132 | memcpy(c->header.fsid, root->fs_info->disk_super->fsid, | 1204 | |
| 1133 | sizeof(c->header.fsid)); | 1205 | write_extent_buffer(c, root->fs_info->fsid, |
| 1134 | if (btrfs_is_leaf(lower)) | 1206 | (unsigned long)btrfs_header_fsid(c), |
| 1135 | lower_key = &((struct btrfs_leaf *)lower)->items[0].key; | 1207 | BTRFS_FSID_SIZE); |
| 1208 | if (level == 1) | ||
| 1209 | btrfs_item_key(lower, &lower_key, 0); | ||
| 1136 | else | 1210 | else |
| 1137 | lower_key = &lower->ptrs[0].key; | 1211 | btrfs_node_key(lower, &lower_key, 0); |
| 1138 | btrfs_memcpy(root, c, &c->ptrs[0].key, lower_key, | 1212 | btrfs_set_node_key(c, &lower_key, 0); |
| 1139 | sizeof(struct btrfs_disk_key)); | 1213 | btrfs_set_node_blockptr(c, 0, extent_buffer_blocknr(lower)); |
| 1140 | btrfs_set_node_blockptr(c, 0, bh_blocknr(path->nodes[level - 1])); | ||
| 1141 | 1214 | ||
| 1142 | btrfs_mark_buffer_dirty(t); | 1215 | btrfs_mark_buffer_dirty(c); |
| 1143 | 1216 | ||
| 1144 | /* the super has an extra ref to root->node */ | 1217 | /* the super has an extra ref to root->node */ |
| 1145 | btrfs_block_release(root, root->node); | 1218 | free_extent_buffer(root->node); |
| 1146 | root->node = t; | 1219 | root->node = c; |
| 1147 | get_bh(t); | 1220 | extent_buffer_get(c); |
| 1148 | path->nodes[level] = t; | 1221 | path->nodes[level] = c; |
| 1149 | path->slots[level] = 0; | 1222 | path->slots[level] = 0; |
| 1150 | return 0; | 1223 | return 0; |
| 1151 | } | 1224 | } |
| @@ -1163,26 +1236,26 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1163 | *root, struct btrfs_path *path, struct btrfs_disk_key | 1236 | *root, struct btrfs_path *path, struct btrfs_disk_key |
| 1164 | *key, u64 blocknr, int slot, int level) | 1237 | *key, u64 blocknr, int slot, int level) |
| 1165 | { | 1238 | { |
| 1166 | struct btrfs_node *lower; | 1239 | struct extent_buffer *lower; |
| 1167 | int nritems; | 1240 | int nritems; |
| 1168 | 1241 | ||
| 1169 | BUG_ON(!path->nodes[level]); | 1242 | BUG_ON(!path->nodes[level]); |
| 1170 | lower = btrfs_buffer_node(path->nodes[level]); | 1243 | lower = path->nodes[level]; |
| 1171 | nritems = btrfs_header_nritems(&lower->header); | 1244 | nritems = btrfs_header_nritems(lower); |
| 1172 | if (slot > nritems) | 1245 | if (slot > nritems) |
| 1173 | BUG(); | 1246 | BUG(); |
| 1174 | if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root)) | 1247 | if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root)) |
| 1175 | BUG(); | 1248 | BUG(); |
| 1176 | if (slot != nritems) { | 1249 | if (slot != nritems) { |
| 1177 | btrfs_memmove(root, lower, lower->ptrs + slot + 1, | 1250 | memmove_extent_buffer(lower, |
| 1178 | lower->ptrs + slot, | 1251 | btrfs_node_key_ptr_offset(slot + 1), |
| 1252 | btrfs_node_key_ptr_offset(slot), | ||
| 1179 | (nritems - slot) * sizeof(struct btrfs_key_ptr)); | 1253 | (nritems - slot) * sizeof(struct btrfs_key_ptr)); |
| 1180 | } | 1254 | } |
| 1181 | btrfs_memcpy(root, lower, &lower->ptrs[slot].key, | 1255 | btrfs_set_node_key(lower, key, slot); |
| 1182 | key, sizeof(struct btrfs_disk_key)); | ||
| 1183 | btrfs_set_node_blockptr(lower, slot, blocknr); | 1256 | btrfs_set_node_blockptr(lower, slot, blocknr); |
| 1184 | btrfs_set_header_nritems(&lower->header, nritems + 1); | 1257 | btrfs_set_header_nritems(lower, nritems + 1); |
| 1185 | btrfs_mark_buffer_dirty(path->nodes[level]); | 1258 | btrfs_mark_buffer_dirty(lower); |
| 1186 | check_node(root, path, level); | 1259 | check_node(root, path, level); |
| 1187 | return 0; | 1260 | return 0; |
| 1188 | } | 1261 | } |
| @@ -1199,69 +1272,73 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1199 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | 1272 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root |
| 1200 | *root, struct btrfs_path *path, int level) | 1273 | *root, struct btrfs_path *path, int level) |
| 1201 | { | 1274 | { |
| 1202 | struct buffer_head *t; | 1275 | struct extent_buffer *c; |
| 1203 | struct btrfs_node *c; | 1276 | struct extent_buffer *split; |
| 1204 | struct buffer_head *split_buffer; | 1277 | struct btrfs_disk_key disk_key; |
| 1205 | struct btrfs_node *split; | ||
| 1206 | int mid; | 1278 | int mid; |
| 1207 | int ret; | 1279 | int ret; |
| 1208 | int wret; | 1280 | int wret; |
| 1209 | u32 c_nritems; | 1281 | u32 c_nritems; |
| 1210 | 1282 | ||
| 1211 | t = path->nodes[level]; | 1283 | c = path->nodes[level]; |
| 1212 | c = btrfs_buffer_node(t); | 1284 | if (c == root->node) { |
| 1213 | if (t == root->node) { | ||
| 1214 | /* trying to split the root, lets make a new one */ | 1285 | /* trying to split the root, lets make a new one */ |
| 1215 | ret = insert_new_root(trans, root, path, level + 1); | 1286 | ret = insert_new_root(trans, root, path, level + 1); |
| 1216 | if (ret) | 1287 | if (ret) |
| 1217 | return ret; | 1288 | return ret; |
| 1218 | } else { | 1289 | } else { |
| 1219 | ret = push_nodes_for_insert(trans, root, path, level); | 1290 | ret = push_nodes_for_insert(trans, root, path, level); |
| 1220 | t = path->nodes[level]; | 1291 | c = path->nodes[level]; |
| 1221 | c = btrfs_buffer_node(t); | 1292 | if (!ret && btrfs_header_nritems(c) < |
| 1222 | if (!ret && | ||
| 1223 | btrfs_header_nritems(&c->header) < | ||
| 1224 | BTRFS_NODEPTRS_PER_BLOCK(root) - 1) | 1293 | BTRFS_NODEPTRS_PER_BLOCK(root) - 1) |
| 1225 | return 0; | 1294 | return 0; |
| 1226 | if (ret < 0) | 1295 | if (ret < 0) |
| 1227 | return ret; | 1296 | return ret; |
| 1228 | } | 1297 | } |
| 1229 | 1298 | ||
| 1230 | c_nritems = btrfs_header_nritems(&c->header); | 1299 | c_nritems = btrfs_header_nritems(c); |
| 1231 | split_buffer = btrfs_alloc_free_block(trans, root, t->b_blocknr, 0); | 1300 | split = btrfs_alloc_free_block(trans, root, |
| 1232 | if (IS_ERR(split_buffer)) | 1301 | extent_buffer_blocknr(c), 0); |
| 1233 | return PTR_ERR(split_buffer); | 1302 | if (IS_ERR(split)) |
| 1303 | return PTR_ERR(split); | ||
| 1304 | |||
| 1305 | btrfs_set_header_flags(split, btrfs_header_flags(c)); | ||
| 1306 | btrfs_set_header_level(split, btrfs_header_level(c)); | ||
| 1307 | btrfs_set_header_blocknr(split, extent_buffer_blocknr(split)); | ||
| 1308 | btrfs_set_header_generation(split, trans->transid); | ||
| 1309 | btrfs_set_header_owner(split, root->root_key.objectid); | ||
| 1310 | write_extent_buffer(split, root->fs_info->fsid, | ||
| 1311 | (unsigned long)btrfs_header_fsid(split), | ||
| 1312 | BTRFS_FSID_SIZE); | ||
| 1234 | 1313 | ||
| 1235 | split = btrfs_buffer_node(split_buffer); | ||
| 1236 | btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header)); | ||
| 1237 | btrfs_set_header_level(&split->header, btrfs_header_level(&c->header)); | ||
| 1238 | btrfs_set_header_blocknr(&split->header, bh_blocknr(split_buffer)); | ||
| 1239 | btrfs_set_header_generation(&split->header, trans->transid); | ||
| 1240 | btrfs_set_header_owner(&split->header, root->root_key.objectid); | ||
| 1241 | memcpy(split->header.fsid, root->fs_info->disk_super->fsid, | ||
| 1242 | sizeof(split->header.fsid)); | ||
| 1243 | mid = (c_nritems + 1) / 2; | 1314 | mid = (c_nritems + 1) / 2; |
| 1244 | btrfs_memcpy(root, split, split->ptrs, c->ptrs + mid, | 1315 | |
| 1245 | (c_nritems - mid) * sizeof(struct btrfs_key_ptr)); | 1316 | copy_extent_buffer(split, c, |
| 1246 | btrfs_set_header_nritems(&split->header, c_nritems - mid); | 1317 | btrfs_node_key_ptr_offset(0), |
| 1247 | btrfs_set_header_nritems(&c->header, mid); | 1318 | btrfs_node_key_ptr_offset(mid), |
| 1319 | (c_nritems - mid) * sizeof(struct btrfs_key_ptr)); | ||
| 1320 | btrfs_set_header_nritems(split, c_nritems - mid); | ||
| 1321 | btrfs_set_header_nritems(c, mid); | ||
| 1248 | ret = 0; | 1322 | ret = 0; |
| 1249 | 1323 | ||
| 1250 | btrfs_mark_buffer_dirty(t); | 1324 | btrfs_mark_buffer_dirty(c); |
| 1251 | btrfs_mark_buffer_dirty(split_buffer); | 1325 | btrfs_mark_buffer_dirty(split); |
| 1252 | wret = insert_ptr(trans, root, path, &split->ptrs[0].key, | 1326 | |
| 1253 | bh_blocknr(split_buffer), path->slots[level + 1] + 1, | 1327 | btrfs_node_key(split, &disk_key, 0); |
| 1328 | wret = insert_ptr(trans, root, path, &disk_key, | ||
| 1329 | extent_buffer_blocknr(split), | ||
| 1330 | path->slots[level + 1] + 1, | ||
| 1254 | level + 1); | 1331 | level + 1); |
| 1255 | if (wret) | 1332 | if (wret) |
| 1256 | ret = wret; | 1333 | ret = wret; |
| 1257 | 1334 | ||
| 1258 | if (path->slots[level] >= mid) { | 1335 | if (path->slots[level] >= mid) { |
| 1259 | path->slots[level] -= mid; | 1336 | path->slots[level] -= mid; |
| 1260 | btrfs_block_release(root, t); | 1337 | free_extent_buffer(c); |
| 1261 | path->nodes[level] = split_buffer; | 1338 | path->nodes[level] = split; |
| 1262 | path->slots[level + 1] += 1; | 1339 | path->slots[level + 1] += 1; |
| 1263 | } else { | 1340 | } else { |
| 1264 | btrfs_block_release(root, split_buffer); | 1341 | free_extent_buffer(split); |
| 1265 | } | 1342 | } |
| 1266 | return ret; | 1343 | return ret; |
| 1267 | } | 1344 | } |
| @@ -1271,16 +1348,16 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1271 | * and nr indicate which items in the leaf to check. This totals up the | 1348 | * and nr indicate which items in the leaf to check. This totals up the |
| 1272 | * space used both by the item structs and the item data | 1349 | * space used both by the item structs and the item data |
| 1273 | */ | 1350 | */ |
| 1274 | static int leaf_space_used(struct btrfs_leaf *l, int start, int nr) | 1351 | static int leaf_space_used(struct extent_buffer *l, int start, int nr) |
| 1275 | { | 1352 | { |
| 1276 | int data_len; | 1353 | int data_len; |
| 1277 | int nritems = btrfs_header_nritems(&l->header); | 1354 | int nritems = btrfs_header_nritems(l); |
| 1278 | int end = min(nritems, start + nr) - 1; | 1355 | int end = min(nritems, start + nr) - 1; |
| 1279 | 1356 | ||
| 1280 | if (!nr) | 1357 | if (!nr) |
| 1281 | return 0; | 1358 | return 0; |
| 1282 | data_len = btrfs_item_end(l->items + start); | 1359 | data_len = btrfs_item_end_nr(l, start); |
| 1283 | data_len = data_len - btrfs_item_offset(l->items + end); | 1360 | data_len = data_len - btrfs_item_offset_nr(l, end); |
| 1284 | data_len += sizeof(struct btrfs_item) * nr; | 1361 | data_len += sizeof(struct btrfs_item) * nr; |
| 1285 | WARN_ON(data_len < 0); | 1362 | WARN_ON(data_len < 0); |
| 1286 | return data_len; | 1363 | return data_len; |
| @@ -1291,10 +1368,17 @@ static int leaf_space_used(struct btrfs_leaf *l, int start, int nr) | |||
| 1291 | * the start of the leaf data. IOW, how much room | 1368 | * the start of the leaf data. IOW, how much room |
| 1292 | * the leaf has left for both items and data | 1369 | * the leaf has left for both items and data |
| 1293 | */ | 1370 | */ |
| 1294 | int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf) | 1371 | int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf) |
| 1295 | { | 1372 | { |
| 1296 | int nritems = btrfs_header_nritems(&leaf->header); | 1373 | int nritems = btrfs_header_nritems(leaf); |
| 1297 | return BTRFS_LEAF_DATA_SIZE(root) - leaf_space_used(leaf, 0, nritems); | 1374 | int ret; |
| 1375 | ret = BTRFS_LEAF_DATA_SIZE(root) - leaf_space_used(leaf, 0, nritems); | ||
| 1376 | if (ret < 0) { | ||
| 1377 | printk("leaf free space ret %d, leaf data size %lu, used %d nritems %d\n", | ||
| 1378 | ret, BTRFS_LEAF_DATA_SIZE(root), | ||
| 1379 | leaf_space_used(leaf, 0, nritems), nritems); | ||
| 1380 | } | ||
| 1381 | return ret; | ||
| 1298 | } | 1382 | } |
| 1299 | 1383 | ||
| 1300 | /* | 1384 | /* |
| @@ -1307,12 +1391,10 @@ int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf) | |||
| 1307 | static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | 1391 | static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root |
| 1308 | *root, struct btrfs_path *path, int data_size) | 1392 | *root, struct btrfs_path *path, int data_size) |
| 1309 | { | 1393 | { |
| 1310 | struct buffer_head *left_buf = path->nodes[0]; | 1394 | struct extent_buffer *left = path->nodes[0]; |
| 1311 | struct btrfs_leaf *left = btrfs_buffer_leaf(left_buf); | 1395 | struct extent_buffer *right; |
| 1312 | struct btrfs_leaf *right; | 1396 | struct extent_buffer *upper; |
| 1313 | struct buffer_head *right_buf; | 1397 | struct btrfs_disk_key disk_key; |
| 1314 | struct buffer_head *upper; | ||
| 1315 | struct btrfs_node *upper_node; | ||
| 1316 | int slot; | 1398 | int slot; |
| 1317 | int i; | 1399 | int i; |
| 1318 | int free_space; | 1400 | int free_space; |
| @@ -1321,6 +1403,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1321 | struct btrfs_item *item; | 1403 | struct btrfs_item *item; |
| 1322 | u32 left_nritems; | 1404 | u32 left_nritems; |
| 1323 | u32 right_nritems; | 1405 | u32 right_nritems; |
| 1406 | u32 data_end; | ||
| 1324 | int ret; | 1407 | int ret; |
| 1325 | 1408 | ||
| 1326 | slot = path->slots[1]; | 1409 | slot = path->slots[1]; |
| @@ -1328,102 +1411,109 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1328 | return 1; | 1411 | return 1; |
| 1329 | } | 1412 | } |
| 1330 | upper = path->nodes[1]; | 1413 | upper = path->nodes[1]; |
| 1331 | upper_node = btrfs_buffer_node(upper); | 1414 | if (slot >= btrfs_header_nritems(upper) - 1) |
| 1332 | if (slot >= btrfs_header_nritems(&upper_node->header) - 1) { | ||
| 1333 | return 1; | 1415 | return 1; |
| 1334 | } | 1416 | |
| 1335 | right_buf = read_tree_block(root, | 1417 | right = read_tree_block(root, btrfs_node_blockptr(upper, slot + 1)); |
| 1336 | btrfs_node_blockptr(btrfs_buffer_node(upper), slot + 1)); | ||
| 1337 | right = btrfs_buffer_leaf(right_buf); | ||
| 1338 | free_space = btrfs_leaf_free_space(root, right); | 1418 | free_space = btrfs_leaf_free_space(root, right); |
| 1339 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 1419 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
| 1340 | btrfs_block_release(root, right_buf); | 1420 | free_extent_buffer(right); |
| 1341 | return 1; | 1421 | return 1; |
| 1342 | } | 1422 | } |
| 1423 | |||
| 1343 | /* cow and double check */ | 1424 | /* cow and double check */ |
| 1344 | ret = btrfs_cow_block(trans, root, right_buf, upper, | 1425 | ret = btrfs_cow_block(trans, root, right, upper, |
| 1345 | slot + 1, &right_buf); | 1426 | slot + 1, &right); |
| 1346 | if (ret) { | 1427 | if (ret) { |
| 1347 | btrfs_block_release(root, right_buf); | 1428 | free_extent_buffer(right); |
| 1348 | return 1; | 1429 | return 1; |
| 1349 | } | 1430 | } |
| 1350 | right = btrfs_buffer_leaf(right_buf); | ||
| 1351 | free_space = btrfs_leaf_free_space(root, right); | 1431 | free_space = btrfs_leaf_free_space(root, right); |
| 1352 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 1432 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
| 1353 | btrfs_block_release(root, right_buf); | 1433 | free_extent_buffer(right); |
| 1354 | return 1; | 1434 | return 1; |
| 1355 | } | 1435 | } |
| 1356 | 1436 | ||
| 1357 | left_nritems = btrfs_header_nritems(&left->header); | 1437 | left_nritems = btrfs_header_nritems(left); |
| 1358 | if (left_nritems == 0) { | 1438 | if (left_nritems == 0) { |
| 1359 | btrfs_block_release(root, right_buf); | 1439 | free_extent_buffer(right); |
| 1360 | return 1; | 1440 | return 1; |
| 1361 | } | 1441 | } |
| 1442 | |||
| 1362 | for (i = left_nritems - 1; i >= 1; i--) { | 1443 | for (i = left_nritems - 1; i >= 1; i--) { |
| 1363 | item = left->items + i; | 1444 | item = btrfs_item_nr(left, i); |
| 1364 | if (path->slots[0] == i) | 1445 | if (path->slots[0] == i) |
| 1365 | push_space += data_size + sizeof(*item); | 1446 | push_space += data_size + sizeof(*item); |
| 1366 | if (btrfs_item_size(item) + sizeof(*item) + push_space > | 1447 | if (btrfs_item_size(left, item) + sizeof(*item) + push_space > |
| 1367 | free_space) | 1448 | free_space) |
| 1368 | break; | 1449 | break; |
| 1369 | push_items++; | 1450 | push_items++; |
| 1370 | push_space += btrfs_item_size(item) + sizeof(*item); | 1451 | push_space += btrfs_item_size(left, item) + sizeof(*item); |
| 1371 | } | 1452 | } |
| 1453 | |||
| 1372 | if (push_items == 0) { | 1454 | if (push_items == 0) { |
| 1373 | btrfs_block_release(root, right_buf); | 1455 | free_extent_buffer(right); |
| 1374 | return 1; | 1456 | return 1; |
| 1375 | } | 1457 | } |
| 1458 | |||
| 1376 | if (push_items == left_nritems) | 1459 | if (push_items == left_nritems) |
| 1377 | WARN_ON(1); | 1460 | WARN_ON(1); |
| 1378 | right_nritems = btrfs_header_nritems(&right->header); | 1461 | |
| 1379 | /* push left to right */ | 1462 | /* push left to right */ |
| 1380 | push_space = btrfs_item_end(left->items + left_nritems - push_items); | 1463 | right_nritems = btrfs_header_nritems(right); |
| 1464 | push_space = btrfs_item_end_nr(left, left_nritems - push_items); | ||
| 1381 | push_space -= leaf_data_end(root, left); | 1465 | push_space -= leaf_data_end(root, left); |
| 1466 | |||
| 1382 | /* make room in the right data area */ | 1467 | /* make room in the right data area */ |
| 1383 | btrfs_memmove(root, right, btrfs_leaf_data(right) + | 1468 | data_end = leaf_data_end(root, right); |
| 1384 | leaf_data_end(root, right) - push_space, | 1469 | memmove_extent_buffer(right, |
| 1385 | btrfs_leaf_data(right) + | 1470 | btrfs_leaf_data(right) + data_end - push_space, |
| 1386 | leaf_data_end(root, right), BTRFS_LEAF_DATA_SIZE(root) - | 1471 | btrfs_leaf_data(right) + data_end, |
| 1387 | leaf_data_end(root, right)); | 1472 | BTRFS_LEAF_DATA_SIZE(root) - data_end); |
| 1473 | |||
| 1388 | /* copy from the left data area */ | 1474 | /* copy from the left data area */ |
| 1389 | btrfs_memcpy(root, right, btrfs_leaf_data(right) + | 1475 | copy_extent_buffer(right, left, btrfs_leaf_data(right) + |
| 1390 | BTRFS_LEAF_DATA_SIZE(root) - push_space, | 1476 | BTRFS_LEAF_DATA_SIZE(root) - push_space, |
| 1391 | btrfs_leaf_data(left) + leaf_data_end(root, left), | 1477 | btrfs_leaf_data(left) + leaf_data_end(root, left), |
| 1392 | push_space); | 1478 | push_space); |
| 1393 | btrfs_memmove(root, right, right->items + push_items, right->items, | 1479 | |
| 1394 | right_nritems * sizeof(struct btrfs_item)); | 1480 | memmove_extent_buffer(right, btrfs_item_nr_offset(push_items), |
| 1481 | btrfs_item_nr_offset(0), | ||
| 1482 | right_nritems * sizeof(struct btrfs_item)); | ||
| 1483 | |||
| 1395 | /* copy the items from left to right */ | 1484 | /* copy the items from left to right */ |
| 1396 | btrfs_memcpy(root, right, right->items, left->items + | 1485 | copy_extent_buffer(right, left, btrfs_item_nr_offset(0), |
| 1397 | left_nritems - push_items, | 1486 | btrfs_item_nr_offset(left_nritems - push_items), |
| 1398 | push_items * sizeof(struct btrfs_item)); | 1487 | push_items * sizeof(struct btrfs_item)); |
| 1399 | 1488 | ||
| 1400 | /* update the item pointers */ | 1489 | /* update the item pointers */ |
| 1401 | right_nritems += push_items; | 1490 | right_nritems += push_items; |
| 1402 | btrfs_set_header_nritems(&right->header, right_nritems); | 1491 | btrfs_set_header_nritems(right, right_nritems); |
| 1403 | push_space = BTRFS_LEAF_DATA_SIZE(root); | 1492 | push_space = BTRFS_LEAF_DATA_SIZE(root); |
| 1404 | for (i = 0; i < right_nritems; i++) { | 1493 | for (i = 0; i < right_nritems; i++) { |
| 1405 | btrfs_set_item_offset(right->items + i, push_space - | 1494 | item = btrfs_item_nr(right, i); |
| 1406 | btrfs_item_size(right->items + i)); | 1495 | btrfs_set_item_offset(right, item, push_space - |
| 1407 | push_space = btrfs_item_offset(right->items + i); | 1496 | btrfs_item_size(right, item)); |
| 1497 | push_space = btrfs_item_offset(right, item); | ||
| 1408 | } | 1498 | } |
| 1409 | left_nritems -= push_items; | 1499 | left_nritems -= push_items; |
| 1410 | btrfs_set_header_nritems(&left->header, left_nritems); | 1500 | btrfs_set_header_nritems(left, left_nritems); |
| 1411 | 1501 | ||
| 1412 | btrfs_mark_buffer_dirty(left_buf); | 1502 | btrfs_mark_buffer_dirty(left); |
| 1413 | btrfs_mark_buffer_dirty(right_buf); | 1503 | btrfs_mark_buffer_dirty(right); |
| 1414 | 1504 | ||
| 1415 | btrfs_memcpy(root, upper_node, &upper_node->ptrs[slot + 1].key, | 1505 | btrfs_item_key(right, &disk_key, 0); |
| 1416 | &right->items[0].key, sizeof(struct btrfs_disk_key)); | 1506 | btrfs_set_node_key(upper, &disk_key, slot + 1); |
| 1417 | btrfs_mark_buffer_dirty(upper); | 1507 | btrfs_mark_buffer_dirty(upper); |
| 1418 | 1508 | ||
| 1419 | /* then fixup the leaf pointer in the path */ | 1509 | /* then fixup the leaf pointer in the path */ |
| 1420 | if (path->slots[0] >= left_nritems) { | 1510 | if (path->slots[0] >= left_nritems) { |
| 1421 | path->slots[0] -= left_nritems; | 1511 | path->slots[0] -= left_nritems; |
| 1422 | btrfs_block_release(root, path->nodes[0]); | 1512 | free_extent_buffer(path->nodes[0]); |
| 1423 | path->nodes[0] = right_buf; | 1513 | path->nodes[0] = right; |
| 1424 | path->slots[1] += 1; | 1514 | path->slots[1] += 1; |
| 1425 | } else { | 1515 | } else { |
| 1426 | btrfs_block_release(root, right_buf); | 1516 | free_extent_buffer(right); |
| 1427 | } | 1517 | } |
| 1428 | if (path->nodes[1]) | 1518 | if (path->nodes[1]) |
| 1429 | check_node(root, path, 1); | 1519 | check_node(root, path, 1); |
| @@ -1436,10 +1526,9 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1436 | static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | 1526 | static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root |
| 1437 | *root, struct btrfs_path *path, int data_size) | 1527 | *root, struct btrfs_path *path, int data_size) |
| 1438 | { | 1528 | { |
| 1439 | struct buffer_head *right_buf = path->nodes[0]; | 1529 | struct btrfs_disk_key disk_key; |
| 1440 | struct btrfs_leaf *right = btrfs_buffer_leaf(right_buf); | 1530 | struct extent_buffer *right = path->nodes[0]; |
| 1441 | struct buffer_head *t; | 1531 | struct extent_buffer *left; |
| 1442 | struct btrfs_leaf *left; | ||
| 1443 | int slot; | 1532 | int slot; |
| 1444 | int i; | 1533 | int i; |
| 1445 | int free_space; | 1534 | int free_space; |
| @@ -1447,119 +1536,128 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1447 | int push_items = 0; | 1536 | int push_items = 0; |
| 1448 | struct btrfs_item *item; | 1537 | struct btrfs_item *item; |
| 1449 | u32 old_left_nritems; | 1538 | u32 old_left_nritems; |
| 1539 | u32 right_nritems; | ||
| 1450 | int ret = 0; | 1540 | int ret = 0; |
| 1451 | int wret; | 1541 | int wret; |
| 1452 | 1542 | ||
| 1453 | slot = path->slots[1]; | 1543 | slot = path->slots[1]; |
| 1454 | if (slot == 0) { | 1544 | if (slot == 0) |
| 1455 | return 1; | 1545 | return 1; |
| 1456 | } | 1546 | if (!path->nodes[1]) |
| 1457 | if (!path->nodes[1]) { | ||
| 1458 | return 1; | 1547 | return 1; |
| 1459 | } | 1548 | |
| 1460 | t = read_tree_block(root, | 1549 | left = read_tree_block(root, btrfs_node_blockptr(path->nodes[1], |
| 1461 | btrfs_node_blockptr(btrfs_buffer_node(path->nodes[1]), slot - 1)); | 1550 | slot - 1)); |
| 1462 | left = btrfs_buffer_leaf(t); | ||
| 1463 | free_space = btrfs_leaf_free_space(root, left); | 1551 | free_space = btrfs_leaf_free_space(root, left); |
| 1464 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 1552 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
| 1465 | btrfs_block_release(root, t); | 1553 | free_extent_buffer(left); |
| 1466 | return 1; | 1554 | return 1; |
| 1467 | } | 1555 | } |
| 1468 | 1556 | ||
| 1469 | /* cow and double check */ | 1557 | /* cow and double check */ |
| 1470 | ret = btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t); | 1558 | ret = btrfs_cow_block(trans, root, left, |
| 1559 | path->nodes[1], slot - 1, &left); | ||
| 1471 | if (ret) { | 1560 | if (ret) { |
| 1472 | /* we hit -ENOSPC, but it isn't fatal here */ | 1561 | /* we hit -ENOSPC, but it isn't fatal here */ |
| 1473 | btrfs_block_release(root, t); | 1562 | free_extent_buffer(left); |
| 1474 | return 1; | 1563 | return 1; |
| 1475 | } | 1564 | } |
| 1476 | left = btrfs_buffer_leaf(t); | ||
| 1477 | free_space = btrfs_leaf_free_space(root, left); | 1565 | free_space = btrfs_leaf_free_space(root, left); |
| 1478 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 1566 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
| 1479 | btrfs_block_release(root, t); | 1567 | free_extent_buffer(left); |
| 1480 | return 1; | 1568 | return 1; |
| 1481 | } | 1569 | } |
| 1482 | 1570 | ||
| 1483 | if (btrfs_header_nritems(&right->header) == 0) { | 1571 | right_nritems = btrfs_header_nritems(right); |
| 1484 | btrfs_block_release(root, t); | 1572 | if (right_nritems == 0) { |
| 1573 | free_extent_buffer(left); | ||
| 1485 | return 1; | 1574 | return 1; |
| 1486 | } | 1575 | } |
| 1487 | 1576 | ||
| 1488 | for (i = 0; i < btrfs_header_nritems(&right->header) - 1; i++) { | 1577 | for (i = 0; i < right_nritems - 1; i++) { |
| 1489 | item = right->items + i; | 1578 | item = btrfs_item_nr(right, i); |
| 1490 | if (path->slots[0] == i) | 1579 | if (path->slots[0] == i) |
| 1491 | push_space += data_size + sizeof(*item); | 1580 | push_space += data_size + sizeof(*item); |
| 1492 | if (btrfs_item_size(item) + sizeof(*item) + push_space > | 1581 | if (btrfs_item_size(right, item) + sizeof(*item) + push_space > |
| 1493 | free_space) | 1582 | free_space) |
| 1494 | break; | 1583 | break; |
| 1495 | push_items++; | 1584 | push_items++; |
| 1496 | push_space += btrfs_item_size(item) + sizeof(*item); | 1585 | push_space += btrfs_item_size(right, item) + sizeof(*item); |
| 1497 | } | 1586 | } |
| 1498 | if (push_items == 0) { | 1587 | if (push_items == 0) { |
| 1499 | btrfs_block_release(root, t); | 1588 | free_extent_buffer(left); |
| 1500 | return 1; | 1589 | return 1; |
| 1501 | } | 1590 | } |
| 1502 | if (push_items == btrfs_header_nritems(&right->header)) | 1591 | if (push_items == btrfs_header_nritems(right)) |
| 1503 | WARN_ON(1); | 1592 | WARN_ON(1); |
| 1593 | |||
| 1504 | /* push data from right to left */ | 1594 | /* push data from right to left */ |
| 1505 | btrfs_memcpy(root, left, left->items + | 1595 | copy_extent_buffer(left, right, |
| 1506 | btrfs_header_nritems(&left->header), | 1596 | btrfs_item_nr_offset(btrfs_header_nritems(left)), |
| 1507 | right->items, push_items * sizeof(struct btrfs_item)); | 1597 | btrfs_item_nr_offset(0), |
| 1598 | push_items * sizeof(struct btrfs_item)); | ||
| 1599 | |||
| 1508 | push_space = BTRFS_LEAF_DATA_SIZE(root) - | 1600 | push_space = BTRFS_LEAF_DATA_SIZE(root) - |
| 1509 | btrfs_item_offset(right->items + push_items -1); | 1601 | btrfs_item_offset_nr(right, push_items -1); |
| 1510 | btrfs_memcpy(root, left, btrfs_leaf_data(left) + | 1602 | |
| 1603 | copy_extent_buffer(left, right, btrfs_leaf_data(left) + | ||
| 1511 | leaf_data_end(root, left) - push_space, | 1604 | leaf_data_end(root, left) - push_space, |
| 1512 | btrfs_leaf_data(right) + | 1605 | btrfs_leaf_data(right) + |
| 1513 | btrfs_item_offset(right->items + push_items - 1), | 1606 | btrfs_item_offset_nr(right, push_items - 1), |
| 1514 | push_space); | 1607 | push_space); |
| 1515 | old_left_nritems = btrfs_header_nritems(&left->header); | 1608 | old_left_nritems = btrfs_header_nritems(left); |
| 1516 | BUG_ON(old_left_nritems < 0); | 1609 | BUG_ON(old_left_nritems < 0); |
| 1517 | 1610 | ||
| 1518 | for (i = old_left_nritems; i < old_left_nritems + push_items; i++) { | 1611 | for (i = old_left_nritems; i < old_left_nritems + push_items; i++) { |
| 1519 | u32 ioff = btrfs_item_offset(left->items + i); | 1612 | u32 ioff; |
| 1520 | btrfs_set_item_offset(left->items + i, ioff - | 1613 | item = btrfs_item_nr(left, i); |
| 1521 | (BTRFS_LEAF_DATA_SIZE(root) - | 1614 | ioff = btrfs_item_offset(left, item); |
| 1522 | btrfs_item_offset(left->items + | 1615 | btrfs_set_item_offset(left, item, |
| 1523 | old_left_nritems - 1))); | 1616 | ioff - (BTRFS_LEAF_DATA_SIZE(root) - |
| 1617 | btrfs_item_offset_nr(left, old_left_nritems - 1))); | ||
| 1524 | } | 1618 | } |
| 1525 | btrfs_set_header_nritems(&left->header, old_left_nritems + push_items); | 1619 | btrfs_set_header_nritems(left, old_left_nritems + push_items); |
| 1526 | 1620 | ||
| 1527 | /* fixup right node */ | 1621 | /* fixup right node */ |
| 1528 | push_space = btrfs_item_offset(right->items + push_items - 1) - | 1622 | push_space = btrfs_item_offset_nr(right, push_items - 1) - |
| 1529 | leaf_data_end(root, right); | 1623 | leaf_data_end(root, right); |
| 1530 | btrfs_memmove(root, right, btrfs_leaf_data(right) + | 1624 | memmove_extent_buffer(right, btrfs_leaf_data(right) + |
| 1531 | BTRFS_LEAF_DATA_SIZE(root) - push_space, | 1625 | BTRFS_LEAF_DATA_SIZE(root) - push_space, |
| 1532 | btrfs_leaf_data(right) + | 1626 | btrfs_leaf_data(right) + |
| 1533 | leaf_data_end(root, right), push_space); | 1627 | leaf_data_end(root, right), push_space); |
| 1534 | btrfs_memmove(root, right, right->items, right->items + push_items, | 1628 | |
| 1535 | (btrfs_header_nritems(&right->header) - push_items) * | 1629 | memmove_extent_buffer(right, btrfs_item_nr_offset(0), |
| 1536 | sizeof(struct btrfs_item)); | 1630 | btrfs_item_nr_offset(push_items), |
| 1537 | btrfs_set_header_nritems(&right->header, | 1631 | (btrfs_header_nritems(right) - push_items) * |
| 1538 | btrfs_header_nritems(&right->header) - | 1632 | sizeof(struct btrfs_item)); |
| 1539 | push_items); | 1633 | |
| 1634 | right_nritems = btrfs_header_nritems(right) - push_items; | ||
| 1635 | btrfs_set_header_nritems(right, right_nritems); | ||
| 1540 | push_space = BTRFS_LEAF_DATA_SIZE(root); | 1636 | push_space = BTRFS_LEAF_DATA_SIZE(root); |
| 1541 | 1637 | ||
| 1542 | for (i = 0; i < btrfs_header_nritems(&right->header); i++) { | 1638 | for (i = 0; i < right_nritems; i++) { |
| 1543 | btrfs_set_item_offset(right->items + i, push_space - | 1639 | item = btrfs_item_nr(right, i); |
| 1544 | btrfs_item_size(right->items + i)); | 1640 | btrfs_set_item_offset(right, item, push_space - |
| 1545 | push_space = btrfs_item_offset(right->items + i); | 1641 | btrfs_item_size(right, item)); |
| 1642 | push_space = btrfs_item_offset(right, item); | ||
| 1546 | } | 1643 | } |
| 1547 | 1644 | ||
| 1548 | btrfs_mark_buffer_dirty(t); | 1645 | btrfs_mark_buffer_dirty(left); |
| 1549 | btrfs_mark_buffer_dirty(right_buf); | 1646 | btrfs_mark_buffer_dirty(right); |
| 1550 | 1647 | ||
| 1551 | wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); | 1648 | btrfs_item_key(right, &disk_key, 0); |
| 1649 | wret = fixup_low_keys(trans, root, path, &disk_key, 1); | ||
| 1552 | if (wret) | 1650 | if (wret) |
| 1553 | ret = wret; | 1651 | ret = wret; |
| 1554 | 1652 | ||
| 1555 | /* then fixup the leaf pointer in the path */ | 1653 | /* then fixup the leaf pointer in the path */ |
| 1556 | if (path->slots[0] < push_items) { | 1654 | if (path->slots[0] < push_items) { |
| 1557 | path->slots[0] += old_left_nritems; | 1655 | path->slots[0] += old_left_nritems; |
| 1558 | btrfs_block_release(root, path->nodes[0]); | 1656 | free_extent_buffer(path->nodes[0]); |
| 1559 | path->nodes[0] = t; | 1657 | path->nodes[0] = left; |
| 1560 | path->slots[1] -= 1; | 1658 | path->slots[1] -= 1; |
| 1561 | } else { | 1659 | } else { |
| 1562 | btrfs_block_release(root, t); | 1660 | free_extent_buffer(left); |
| 1563 | path->slots[0] -= push_items; | 1661 | path->slots[0] -= push_items; |
| 1564 | } | 1662 | } |
| 1565 | BUG_ON(path->slots[0] < 0); | 1663 | BUG_ON(path->slots[0] < 0); |
| @@ -1578,13 +1676,11 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1578 | *root, struct btrfs_key *ins_key, | 1676 | *root, struct btrfs_key *ins_key, |
| 1579 | struct btrfs_path *path, int data_size) | 1677 | struct btrfs_path *path, int data_size) |
| 1580 | { | 1678 | { |
| 1581 | struct buffer_head *l_buf; | 1679 | struct extent_buffer *l; |
| 1582 | struct btrfs_leaf *l; | ||
| 1583 | u32 nritems; | 1680 | u32 nritems; |
| 1584 | int mid; | 1681 | int mid; |
| 1585 | int slot; | 1682 | int slot; |
| 1586 | struct btrfs_leaf *right; | 1683 | struct extent_buffer *right; |
| 1587 | struct buffer_head *right_buffer; | ||
| 1588 | int space_needed = data_size + sizeof(struct btrfs_item); | 1684 | int space_needed = data_size + sizeof(struct btrfs_item); |
| 1589 | int data_copy_size; | 1685 | int data_copy_size; |
| 1590 | int rt_data_off; | 1686 | int rt_data_off; |
| @@ -1603,8 +1699,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1603 | if (wret < 0) | 1699 | if (wret < 0) |
| 1604 | return wret; | 1700 | return wret; |
| 1605 | } | 1701 | } |
| 1606 | l_buf = path->nodes[0]; | 1702 | l = path->nodes[0]; |
| 1607 | l = btrfs_buffer_leaf(l_buf); | ||
| 1608 | 1703 | ||
| 1609 | /* did the pushes work? */ | 1704 | /* did the pushes work? */ |
| 1610 | if (btrfs_leaf_free_space(root, l) >= | 1705 | if (btrfs_leaf_free_space(root, l) >= |
| @@ -1617,36 +1712,38 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1617 | return ret; | 1712 | return ret; |
| 1618 | } | 1713 | } |
| 1619 | slot = path->slots[0]; | 1714 | slot = path->slots[0]; |
| 1620 | nritems = btrfs_header_nritems(&l->header); | 1715 | nritems = btrfs_header_nritems(l); |
| 1621 | mid = (nritems + 1)/ 2; | 1716 | mid = (nritems + 1)/ 2; |
| 1622 | 1717 | ||
| 1623 | right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr, 0); | 1718 | right = btrfs_alloc_free_block(trans, root, |
| 1624 | if (IS_ERR(right_buffer)) | 1719 | extent_buffer_blocknr(l), 0); |
| 1625 | return PTR_ERR(right_buffer); | 1720 | if (IS_ERR(right)) |
| 1626 | 1721 | return PTR_ERR(right); | |
| 1627 | right = btrfs_buffer_leaf(right_buffer); | 1722 | |
| 1628 | memset(&right->header, 0, sizeof(right->header)); | 1723 | memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header)); |
| 1629 | btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer)); | 1724 | btrfs_set_header_blocknr(right, extent_buffer_blocknr(right)); |
| 1630 | btrfs_set_header_generation(&right->header, trans->transid); | 1725 | btrfs_set_header_generation(right, trans->transid); |
| 1631 | btrfs_set_header_owner(&right->header, root->root_key.objectid); | 1726 | btrfs_set_header_owner(right, root->root_key.objectid); |
| 1632 | btrfs_set_header_level(&right->header, 0); | 1727 | btrfs_set_header_level(right, 0); |
| 1633 | memcpy(right->header.fsid, root->fs_info->disk_super->fsid, | 1728 | write_extent_buffer(right, root->fs_info->fsid, |
| 1634 | sizeof(right->header.fsid)); | 1729 | (unsigned long)btrfs_header_fsid(right), |
| 1730 | BTRFS_FSID_SIZE); | ||
| 1731 | |||
| 1635 | if (mid <= slot) { | 1732 | if (mid <= slot) { |
| 1636 | if (nritems == 1 || | 1733 | if (nritems == 1 || |
| 1637 | leaf_space_used(l, mid, nritems - mid) + space_needed > | 1734 | leaf_space_used(l, mid, nritems - mid) + space_needed > |
| 1638 | BTRFS_LEAF_DATA_SIZE(root)) { | 1735 | BTRFS_LEAF_DATA_SIZE(root)) { |
| 1639 | if (slot >= nritems) { | 1736 | if (slot >= nritems) { |
| 1640 | btrfs_cpu_key_to_disk(&disk_key, ins_key); | 1737 | btrfs_cpu_key_to_disk(&disk_key, ins_key); |
| 1641 | btrfs_set_header_nritems(&right->header, 0); | 1738 | btrfs_set_header_nritems(right, 0); |
| 1642 | wret = insert_ptr(trans, root, path, | 1739 | wret = insert_ptr(trans, root, path, |
| 1643 | &disk_key, | 1740 | &disk_key, |
| 1644 | bh_blocknr(right_buffer), | 1741 | extent_buffer_blocknr(right), |
| 1645 | path->slots[1] + 1, 1); | 1742 | path->slots[1] + 1, 1); |
| 1646 | if (wret) | 1743 | if (wret) |
| 1647 | ret = wret; | 1744 | ret = wret; |
| 1648 | btrfs_block_release(root, path->nodes[0]); | 1745 | free_extent_buffer(path->nodes[0]); |
| 1649 | path->nodes[0] = right_buffer; | 1746 | path->nodes[0] = right; |
| 1650 | path->slots[0] = 0; | 1747 | path->slots[0] = 0; |
| 1651 | path->slots[1] += 1; | 1748 | path->slots[1] += 1; |
| 1652 | return ret; | 1749 | return ret; |
| @@ -1659,15 +1756,15 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1659 | BTRFS_LEAF_DATA_SIZE(root)) { | 1756 | BTRFS_LEAF_DATA_SIZE(root)) { |
| 1660 | if (slot == 0) { | 1757 | if (slot == 0) { |
| 1661 | btrfs_cpu_key_to_disk(&disk_key, ins_key); | 1758 | btrfs_cpu_key_to_disk(&disk_key, ins_key); |
| 1662 | btrfs_set_header_nritems(&right->header, 0); | 1759 | btrfs_set_header_nritems(right, 0); |
| 1663 | wret = insert_ptr(trans, root, path, | 1760 | wret = insert_ptr(trans, root, path, |
| 1664 | &disk_key, | 1761 | &disk_key, |
| 1665 | bh_blocknr(right_buffer), | 1762 | extent_buffer_blocknr(right), |
| 1666 | path->slots[1], 1); | 1763 | path->slots[1], 1); |
| 1667 | if (wret) | 1764 | if (wret) |
| 1668 | ret = wret; | 1765 | ret = wret; |
| 1669 | btrfs_block_release(root, path->nodes[0]); | 1766 | free_extent_buffer(path->nodes[0]); |
| 1670 | path->nodes[0] = right_buffer; | 1767 | path->nodes[0] = right; |
| 1671 | path->slots[0] = 0; | 1768 | path->slots[0] = 0; |
| 1672 | if (path->slots[1] == 0) { | 1769 | if (path->slots[1] == 0) { |
| 1673 | wret = fixup_low_keys(trans, root, | 1770 | wret = fixup_low_keys(trans, root, |
| @@ -1681,61 +1778,74 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1681 | double_split = 1; | 1778 | double_split = 1; |
| 1682 | } | 1779 | } |
| 1683 | } | 1780 | } |
| 1684 | btrfs_set_header_nritems(&right->header, nritems - mid); | 1781 | nritems = nritems - mid; |
| 1685 | data_copy_size = btrfs_item_end(l->items + mid) - | 1782 | btrfs_set_header_nritems(right, nritems); |
| 1686 | leaf_data_end(root, l); | 1783 | data_copy_size = btrfs_item_end_nr(l, mid) - leaf_data_end(root, l); |
| 1687 | btrfs_memcpy(root, right, right->items, l->items + mid, | 1784 | |
| 1688 | (nritems - mid) * sizeof(struct btrfs_item)); | 1785 | copy_extent_buffer(right, l, btrfs_item_nr_offset(0), |
| 1689 | btrfs_memcpy(root, right, | 1786 | btrfs_item_nr_offset(mid), |
| 1787 | nritems * sizeof(struct btrfs_item)); | ||
| 1788 | |||
| 1789 | copy_extent_buffer(right, l, | ||
| 1690 | btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) - | 1790 | btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) - |
| 1691 | data_copy_size, btrfs_leaf_data(l) + | 1791 | data_copy_size, btrfs_leaf_data(l) + |
| 1692 | leaf_data_end(root, l), data_copy_size); | 1792 | leaf_data_end(root, l), data_copy_size); |
| 1793 | |||
| 1693 | rt_data_off = BTRFS_LEAF_DATA_SIZE(root) - | 1794 | rt_data_off = BTRFS_LEAF_DATA_SIZE(root) - |
| 1694 | btrfs_item_end(l->items + mid); | 1795 | btrfs_item_end_nr(l, mid); |
| 1695 | 1796 | ||
| 1696 | for (i = 0; i < btrfs_header_nritems(&right->header); i++) { | 1797 | for (i = 0; i < nritems; i++) { |
| 1697 | u32 ioff = btrfs_item_offset(right->items + i); | 1798 | struct btrfs_item *item = btrfs_item_nr(right, i); |
| 1698 | btrfs_set_item_offset(right->items + i, ioff + rt_data_off); | 1799 | u32 ioff = btrfs_item_offset(right, item); |
| 1800 | btrfs_set_item_offset(right, item, ioff + rt_data_off); | ||
| 1699 | } | 1801 | } |
| 1700 | 1802 | ||
| 1701 | btrfs_set_header_nritems(&l->header, mid); | 1803 | btrfs_set_header_nritems(l, mid); |
| 1702 | ret = 0; | 1804 | ret = 0; |
| 1703 | wret = insert_ptr(trans, root, path, &right->items[0].key, | 1805 | btrfs_item_key(right, &disk_key, 0); |
| 1704 | bh_blocknr(right_buffer), path->slots[1] + 1, 1); | 1806 | wret = insert_ptr(trans, root, path, &disk_key, |
| 1807 | extent_buffer_blocknr(right), path->slots[1] + 1, 1); | ||
| 1705 | if (wret) | 1808 | if (wret) |
| 1706 | ret = wret; | 1809 | ret = wret; |
| 1707 | btrfs_mark_buffer_dirty(right_buffer); | 1810 | |
| 1708 | btrfs_mark_buffer_dirty(l_buf); | 1811 | btrfs_mark_buffer_dirty(right); |
| 1812 | btrfs_mark_buffer_dirty(l); | ||
| 1709 | BUG_ON(path->slots[0] != slot); | 1813 | BUG_ON(path->slots[0] != slot); |
| 1814 | |||
| 1710 | if (mid <= slot) { | 1815 | if (mid <= slot) { |
| 1711 | btrfs_block_release(root, path->nodes[0]); | 1816 | free_extent_buffer(path->nodes[0]); |
| 1712 | path->nodes[0] = right_buffer; | 1817 | path->nodes[0] = right; |
| 1713 | path->slots[0] -= mid; | 1818 | path->slots[0] -= mid; |
| 1714 | path->slots[1] += 1; | 1819 | path->slots[1] += 1; |
| 1715 | } else | 1820 | } else |
| 1716 | btrfs_block_release(root, right_buffer); | 1821 | free_extent_buffer(right); |
| 1822 | |||
| 1717 | BUG_ON(path->slots[0] < 0); | 1823 | BUG_ON(path->slots[0] < 0); |
| 1718 | check_node(root, path, 1); | 1824 | check_node(root, path, 1); |
| 1825 | check_leaf(root, path, 0); | ||
| 1719 | 1826 | ||
| 1720 | if (!double_split) | 1827 | if (!double_split) |
| 1721 | return ret; | 1828 | return ret; |
| 1722 | right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr, 0); | 1829 | |
| 1723 | if (IS_ERR(right_buffer)) | 1830 | right = btrfs_alloc_free_block(trans, root, |
| 1724 | return PTR_ERR(right_buffer); | 1831 | extent_buffer_blocknr(l), 0); |
| 1725 | 1832 | if (IS_ERR(right)) | |
| 1726 | right = btrfs_buffer_leaf(right_buffer); | 1833 | return PTR_ERR(right); |
| 1727 | memset(&right->header, 0, sizeof(right->header)); | 1834 | |
| 1728 | btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer)); | 1835 | memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header)); |
| 1729 | btrfs_set_header_generation(&right->header, trans->transid); | 1836 | btrfs_set_header_blocknr(right, extent_buffer_blocknr(right)); |
| 1730 | btrfs_set_header_owner(&right->header, root->root_key.objectid); | 1837 | btrfs_set_header_generation(right, trans->transid); |
| 1731 | btrfs_set_header_level(&right->header, 0); | 1838 | btrfs_set_header_owner(right, root->root_key.objectid); |
| 1732 | memcpy(right->header.fsid, root->fs_info->disk_super->fsid, | 1839 | btrfs_set_header_level(right, 0); |
| 1733 | sizeof(right->header.fsid)); | 1840 | write_extent_buffer(right, root->fs_info->fsid, |
| 1841 | (unsigned long)btrfs_header_fsid(right), | ||
| 1842 | BTRFS_FSID_SIZE); | ||
| 1843 | |||
| 1734 | btrfs_cpu_key_to_disk(&disk_key, ins_key); | 1844 | btrfs_cpu_key_to_disk(&disk_key, ins_key); |
| 1735 | btrfs_set_header_nritems(&right->header, 0); | 1845 | btrfs_set_header_nritems(right, 0); |
| 1736 | wret = insert_ptr(trans, root, path, | 1846 | wret = insert_ptr(trans, root, path, |
| 1737 | &disk_key, | 1847 | &disk_key, |
| 1738 | bh_blocknr(right_buffer), | 1848 | extent_buffer_blocknr(right), |
| 1739 | path->slots[1], 1); | 1849 | path->slots[1], 1); |
| 1740 | if (wret) | 1850 | if (wret) |
| 1741 | ret = wret; | 1851 | ret = wret; |
| @@ -1744,8 +1854,8 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1744 | if (wret) | 1854 | if (wret) |
| 1745 | ret = wret; | 1855 | ret = wret; |
| 1746 | } | 1856 | } |
| 1747 | btrfs_block_release(root, path->nodes[0]); | 1857 | free_extent_buffer(path->nodes[0]); |
| 1748 | path->nodes[0] = right_buffer; | 1858 | path->nodes[0] = right; |
| 1749 | path->slots[0] = 0; | 1859 | path->slots[0] = 0; |
| 1750 | check_node(root, path, 1); | 1860 | check_node(root, path, 1); |
| 1751 | check_leaf(root, path, 0); | 1861 | check_leaf(root, path, 0); |
| @@ -1760,8 +1870,8 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans, | |||
| 1760 | int ret = 0; | 1870 | int ret = 0; |
| 1761 | int slot; | 1871 | int slot; |
| 1762 | int slot_orig; | 1872 | int slot_orig; |
| 1763 | struct btrfs_leaf *leaf; | 1873 | struct extent_buffer *leaf; |
| 1764 | struct buffer_head *leaf_buf; | 1874 | struct btrfs_item *item; |
| 1765 | u32 nritems; | 1875 | u32 nritems; |
| 1766 | unsigned int data_end; | 1876 | unsigned int data_end; |
| 1767 | unsigned int old_data_start; | 1877 | unsigned int old_data_start; |
| @@ -1770,15 +1880,14 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans, | |||
| 1770 | int i; | 1880 | int i; |
| 1771 | 1881 | ||
| 1772 | slot_orig = path->slots[0]; | 1882 | slot_orig = path->slots[0]; |
| 1773 | leaf_buf = path->nodes[0]; | 1883 | leaf = path->nodes[0]; |
| 1774 | leaf = btrfs_buffer_leaf(leaf_buf); | ||
| 1775 | 1884 | ||
| 1776 | nritems = btrfs_header_nritems(&leaf->header); | 1885 | nritems = btrfs_header_nritems(leaf); |
| 1777 | data_end = leaf_data_end(root, leaf); | 1886 | data_end = leaf_data_end(root, leaf); |
| 1778 | 1887 | ||
| 1779 | slot = path->slots[0]; | 1888 | slot = path->slots[0]; |
| 1780 | old_data_start = btrfs_item_offset(leaf->items + slot); | 1889 | old_data_start = btrfs_item_offset_nr(leaf, slot); |
| 1781 | old_size = btrfs_item_size(leaf->items + slot); | 1890 | old_size = btrfs_item_size_nr(leaf, slot); |
| 1782 | BUG_ON(old_size <= new_size); | 1891 | BUG_ON(old_size <= new_size); |
| 1783 | size_diff = old_size - new_size; | 1892 | size_diff = old_size - new_size; |
| 1784 | 1893 | ||
| @@ -1790,32 +1899,38 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans, | |||
| 1790 | */ | 1899 | */ |
| 1791 | /* first correct the data pointers */ | 1900 | /* first correct the data pointers */ |
| 1792 | for (i = slot; i < nritems; i++) { | 1901 | for (i = slot; i < nritems; i++) { |
| 1793 | u32 ioff = btrfs_item_offset(leaf->items + i); | 1902 | u32 ioff; |
| 1794 | btrfs_set_item_offset(leaf->items + i, | 1903 | item = btrfs_item_nr(leaf, i); |
| 1795 | ioff + size_diff); | 1904 | ioff = btrfs_item_offset(leaf, item); |
| 1905 | btrfs_set_item_offset(leaf, item, ioff + size_diff); | ||
| 1796 | } | 1906 | } |
| 1797 | /* shift the data */ | 1907 | /* shift the data */ |
| 1798 | btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + | 1908 | memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + |
| 1799 | data_end + size_diff, btrfs_leaf_data(leaf) + | 1909 | data_end + size_diff, btrfs_leaf_data(leaf) + |
| 1800 | data_end, old_data_start + new_size - data_end); | 1910 | data_end, old_data_start + new_size - data_end); |
| 1801 | btrfs_set_item_size(leaf->items + slot, new_size); | 1911 | |
| 1802 | btrfs_mark_buffer_dirty(leaf_buf); | 1912 | item = btrfs_item_nr(leaf, slot); |
| 1913 | btrfs_set_item_size(leaf, item, new_size); | ||
| 1914 | btrfs_mark_buffer_dirty(leaf); | ||
| 1803 | 1915 | ||
| 1804 | ret = 0; | 1916 | ret = 0; |
| 1805 | if (btrfs_leaf_free_space(root, leaf) < 0) | 1917 | if (btrfs_leaf_free_space(root, leaf) < 0) { |
| 1918 | btrfs_print_leaf(root, leaf); | ||
| 1806 | BUG(); | 1919 | BUG(); |
| 1920 | } | ||
| 1807 | check_leaf(root, path, 0); | 1921 | check_leaf(root, path, 0); |
| 1808 | return ret; | 1922 | return ret; |
| 1809 | } | 1923 | } |
| 1810 | 1924 | ||
| 1811 | int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root | 1925 | int btrfs_extend_item(struct btrfs_trans_handle *trans, |
| 1812 | *root, struct btrfs_path *path, u32 data_size) | 1926 | struct btrfs_root *root, struct btrfs_path *path, |
| 1927 | u32 data_size) | ||
| 1813 | { | 1928 | { |
| 1814 | int ret = 0; | 1929 | int ret = 0; |
| 1815 | int slot; | 1930 | int slot; |
| 1816 | int slot_orig; | 1931 | int slot_orig; |
| 1817 | struct btrfs_leaf *leaf; | 1932 | struct extent_buffer *leaf; |
| 1818 | struct buffer_head *leaf_buf; | 1933 | struct btrfs_item *item; |
| 1819 | u32 nritems; | 1934 | u32 nritems; |
| 1820 | unsigned int data_end; | 1935 | unsigned int data_end; |
| 1821 | unsigned int old_data; | 1936 | unsigned int old_data; |
| @@ -1823,16 +1938,17 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1823 | int i; | 1938 | int i; |
| 1824 | 1939 | ||
| 1825 | slot_orig = path->slots[0]; | 1940 | slot_orig = path->slots[0]; |
| 1826 | leaf_buf = path->nodes[0]; | 1941 | leaf = path->nodes[0]; |
| 1827 | leaf = btrfs_buffer_leaf(leaf_buf); | ||
| 1828 | 1942 | ||
| 1829 | nritems = btrfs_header_nritems(&leaf->header); | 1943 | nritems = btrfs_header_nritems(leaf); |
| 1830 | data_end = leaf_data_end(root, leaf); | 1944 | data_end = leaf_data_end(root, leaf); |
| 1831 | 1945 | ||
| 1832 | if (btrfs_leaf_free_space(root, leaf) < data_size) | 1946 | if (btrfs_leaf_free_space(root, leaf) < data_size) { |
| 1947 | btrfs_print_leaf(root, leaf); | ||
| 1833 | BUG(); | 1948 | BUG(); |
| 1949 | } | ||
| 1834 | slot = path->slots[0]; | 1950 | slot = path->slots[0]; |
| 1835 | old_data = btrfs_item_end(leaf->items + slot); | 1951 | old_data = btrfs_item_end_nr(leaf, slot); |
| 1836 | 1952 | ||
| 1837 | BUG_ON(slot < 0); | 1953 | BUG_ON(slot < 0); |
| 1838 | BUG_ON(slot >= nritems); | 1954 | BUG_ON(slot >= nritems); |
| @@ -1842,22 +1958,28 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1842 | */ | 1958 | */ |
| 1843 | /* first correct the data pointers */ | 1959 | /* first correct the data pointers */ |
| 1844 | for (i = slot; i < nritems; i++) { | 1960 | for (i = slot; i < nritems; i++) { |
| 1845 | u32 ioff = btrfs_item_offset(leaf->items + i); | 1961 | u32 ioff; |
| 1846 | btrfs_set_item_offset(leaf->items + i, | 1962 | item = btrfs_item_nr(leaf, i); |
| 1847 | ioff - data_size); | 1963 | ioff = btrfs_item_offset(leaf, item); |
| 1964 | btrfs_set_item_offset(leaf, item, ioff - data_size); | ||
| 1848 | } | 1965 | } |
| 1966 | |||
| 1849 | /* shift the data */ | 1967 | /* shift the data */ |
| 1850 | btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + | 1968 | memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + |
| 1851 | data_end - data_size, btrfs_leaf_data(leaf) + | 1969 | data_end - data_size, btrfs_leaf_data(leaf) + |
| 1852 | data_end, old_data - data_end); | 1970 | data_end, old_data - data_end); |
| 1971 | |||
| 1853 | data_end = old_data; | 1972 | data_end = old_data; |
| 1854 | old_size = btrfs_item_size(leaf->items + slot); | 1973 | old_size = btrfs_item_size_nr(leaf, slot); |
| 1855 | btrfs_set_item_size(leaf->items + slot, old_size + data_size); | 1974 | item = btrfs_item_nr(leaf, slot); |
| 1856 | btrfs_mark_buffer_dirty(leaf_buf); | 1975 | btrfs_set_item_size(leaf, item, old_size + data_size); |
| 1976 | btrfs_mark_buffer_dirty(leaf); | ||
| 1857 | 1977 | ||
| 1858 | ret = 0; | 1978 | ret = 0; |
| 1859 | if (btrfs_leaf_free_space(root, leaf) < 0) | 1979 | if (btrfs_leaf_free_space(root, leaf) < 0) { |
| 1980 | btrfs_print_leaf(root, leaf); | ||
| 1860 | BUG(); | 1981 | BUG(); |
| 1982 | } | ||
| 1861 | check_leaf(root, path, 0); | 1983 | check_leaf(root, path, 0); |
| 1862 | return ret; | 1984 | return ret; |
| 1863 | } | 1985 | } |
| @@ -1866,15 +1988,16 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1866 | * Given a key and some data, insert an item into the tree. | 1988 | * Given a key and some data, insert an item into the tree. |
| 1867 | * This does all the path init required, making room in the tree if needed. | 1989 | * This does all the path init required, making room in the tree if needed. |
| 1868 | */ | 1990 | */ |
| 1869 | int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root | 1991 | int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, |
| 1870 | *root, struct btrfs_path *path, struct btrfs_key | 1992 | struct btrfs_root *root, |
| 1871 | *cpu_key, u32 data_size) | 1993 | struct btrfs_path *path, |
| 1994 | struct btrfs_key *cpu_key, u32 data_size) | ||
| 1872 | { | 1995 | { |
| 1996 | struct extent_buffer *leaf; | ||
| 1997 | struct btrfs_item *item; | ||
| 1873 | int ret = 0; | 1998 | int ret = 0; |
| 1874 | int slot; | 1999 | int slot; |
| 1875 | int slot_orig; | 2000 | int slot_orig; |
| 1876 | struct btrfs_leaf *leaf; | ||
| 1877 | struct buffer_head *leaf_buf; | ||
| 1878 | u32 nritems; | 2001 | u32 nritems; |
| 1879 | unsigned int data_end; | 2002 | unsigned int data_end; |
| 1880 | struct btrfs_disk_key disk_key; | 2003 | struct btrfs_disk_key disk_key; |
| @@ -1884,6 +2007,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1884 | /* create a root if there isn't one */ | 2007 | /* create a root if there isn't one */ |
| 1885 | if (!root->node) | 2008 | if (!root->node) |
| 1886 | BUG(); | 2009 | BUG(); |
| 2010 | |||
| 1887 | ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1); | 2011 | ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1); |
| 1888 | if (ret == 0) { | 2012 | if (ret == 0) { |
| 1889 | return -EEXIST; | 2013 | return -EEXIST; |
| @@ -1892,57 +2016,68 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1892 | goto out; | 2016 | goto out; |
| 1893 | 2017 | ||
| 1894 | slot_orig = path->slots[0]; | 2018 | slot_orig = path->slots[0]; |
| 1895 | leaf_buf = path->nodes[0]; | 2019 | leaf = path->nodes[0]; |
| 1896 | leaf = btrfs_buffer_leaf(leaf_buf); | ||
| 1897 | 2020 | ||
| 1898 | nritems = btrfs_header_nritems(&leaf->header); | 2021 | nritems = btrfs_header_nritems(leaf); |
| 1899 | data_end = leaf_data_end(root, leaf); | 2022 | data_end = leaf_data_end(root, leaf); |
| 1900 | 2023 | ||
| 1901 | if (btrfs_leaf_free_space(root, leaf) < | 2024 | if (btrfs_leaf_free_space(root, leaf) < |
| 1902 | sizeof(struct btrfs_item) + data_size) { | 2025 | sizeof(struct btrfs_item) + data_size) { |
| 1903 | BUG(); | 2026 | BUG(); |
| 1904 | } | 2027 | } |
| 2028 | |||
| 1905 | slot = path->slots[0]; | 2029 | slot = path->slots[0]; |
| 1906 | BUG_ON(slot < 0); | 2030 | BUG_ON(slot < 0); |
| 2031 | |||
| 1907 | if (slot != nritems) { | 2032 | if (slot != nritems) { |
| 1908 | int i; | 2033 | int i; |
| 1909 | unsigned int old_data = btrfs_item_end(leaf->items + slot); | 2034 | unsigned int old_data = btrfs_item_end_nr(leaf, slot); |
| 1910 | 2035 | ||
| 2036 | if (old_data < data_end) { | ||
| 2037 | btrfs_print_leaf(root, leaf); | ||
| 2038 | printk("slot %d old_data %d data_end %d\n", | ||
| 2039 | slot, old_data, data_end); | ||
| 2040 | BUG_ON(1); | ||
| 2041 | } | ||
| 1911 | /* | 2042 | /* |
| 1912 | * item0..itemN ... dataN.offset..dataN.size .. data0.size | 2043 | * item0..itemN ... dataN.offset..dataN.size .. data0.size |
| 1913 | */ | 2044 | */ |
| 1914 | /* first correct the data pointers */ | 2045 | /* first correct the data pointers */ |
| 1915 | for (i = slot; i < nritems; i++) { | 2046 | for (i = slot; i < nritems; i++) { |
| 1916 | u32 ioff = btrfs_item_offset(leaf->items + i); | 2047 | u32 ioff; |
| 1917 | btrfs_set_item_offset(leaf->items + i, | 2048 | item = btrfs_item_nr(leaf, i); |
| 1918 | ioff - data_size); | 2049 | ioff = btrfs_item_offset(leaf, item); |
| 2050 | btrfs_set_item_offset(leaf, item, ioff - data_size); | ||
| 1919 | } | 2051 | } |
| 1920 | 2052 | ||
| 1921 | /* shift the items */ | 2053 | /* shift the items */ |
| 1922 | btrfs_memmove(root, leaf, leaf->items + slot + 1, | 2054 | memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1), |
| 1923 | leaf->items + slot, | 2055 | btrfs_item_nr_offset(slot), |
| 1924 | (nritems - slot) * sizeof(struct btrfs_item)); | 2056 | (nritems - slot) * sizeof(struct btrfs_item)); |
| 1925 | 2057 | ||
| 1926 | /* shift the data */ | 2058 | /* shift the data */ |
| 1927 | btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + | 2059 | memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + |
| 1928 | data_end - data_size, btrfs_leaf_data(leaf) + | 2060 | data_end - data_size, btrfs_leaf_data(leaf) + |
| 1929 | data_end, old_data - data_end); | 2061 | data_end, old_data - data_end); |
| 1930 | data_end = old_data; | 2062 | data_end = old_data; |
| 1931 | } | 2063 | } |
| 2064 | |||
| 1932 | /* setup the item for the new data */ | 2065 | /* setup the item for the new data */ |
| 1933 | btrfs_memcpy(root, leaf, &leaf->items[slot].key, &disk_key, | 2066 | btrfs_set_item_key(leaf, &disk_key, slot); |
| 1934 | sizeof(struct btrfs_disk_key)); | 2067 | item = btrfs_item_nr(leaf, slot); |
| 1935 | btrfs_set_item_offset(leaf->items + slot, data_end - data_size); | 2068 | btrfs_set_item_offset(leaf, item, data_end - data_size); |
| 1936 | btrfs_set_item_size(leaf->items + slot, data_size); | 2069 | btrfs_set_item_size(leaf, item, data_size); |
| 1937 | btrfs_set_header_nritems(&leaf->header, nritems + 1); | 2070 | btrfs_set_header_nritems(leaf, nritems + 1); |
| 1938 | btrfs_mark_buffer_dirty(leaf_buf); | 2071 | btrfs_mark_buffer_dirty(leaf); |
| 1939 | 2072 | ||
| 1940 | ret = 0; | 2073 | ret = 0; |
| 1941 | if (slot == 0) | 2074 | if (slot == 0) |
| 1942 | ret = fixup_low_keys(trans, root, path, &disk_key, 1); | 2075 | ret = fixup_low_keys(trans, root, path, &disk_key, 1); |
| 1943 | 2076 | ||
| 1944 | if (btrfs_leaf_free_space(root, leaf) < 0) | 2077 | if (btrfs_leaf_free_space(root, leaf) < 0) { |
| 2078 | btrfs_print_leaf(root, leaf); | ||
| 1945 | BUG(); | 2079 | BUG(); |
| 2080 | } | ||
| 1946 | check_leaf(root, path, 0); | 2081 | check_leaf(root, path, 0); |
| 1947 | out: | 2082 | out: |
| 1948 | return ret; | 2083 | return ret; |
| @@ -1958,17 +2093,17 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1958 | { | 2093 | { |
| 1959 | int ret = 0; | 2094 | int ret = 0; |
| 1960 | struct btrfs_path *path; | 2095 | struct btrfs_path *path; |
| 1961 | u8 *ptr; | 2096 | struct extent_buffer *leaf; |
| 2097 | unsigned long ptr; | ||
| 1962 | 2098 | ||
| 1963 | path = btrfs_alloc_path(); | 2099 | path = btrfs_alloc_path(); |
| 1964 | BUG_ON(!path); | 2100 | BUG_ON(!path); |
| 1965 | ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); | 2101 | ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); |
| 1966 | if (!ret) { | 2102 | if (!ret) { |
| 1967 | ptr = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | 2103 | leaf = path->nodes[0]; |
| 1968 | path->slots[0], u8); | 2104 | ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); |
| 1969 | btrfs_memcpy(root, path->nodes[0]->b_data, | 2105 | write_extent_buffer(leaf, data, ptr, data_size); |
| 1970 | ptr, data, data_size); | 2106 | btrfs_mark_buffer_dirty(leaf); |
| 1971 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
| 1972 | } | 2107 | } |
| 1973 | btrfs_free_path(path); | 2108 | btrfs_free_path(path); |
| 1974 | return ret; | 2109 | return ret; |
| @@ -1984,30 +2119,30 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1984 | static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 2119 | static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 1985 | struct btrfs_path *path, int level, int slot) | 2120 | struct btrfs_path *path, int level, int slot) |
| 1986 | { | 2121 | { |
| 1987 | struct btrfs_node *node; | 2122 | struct extent_buffer *parent = path->nodes[level]; |
| 1988 | struct buffer_head *parent = path->nodes[level]; | ||
| 1989 | u32 nritems; | 2123 | u32 nritems; |
| 1990 | int ret = 0; | 2124 | int ret = 0; |
| 1991 | int wret; | 2125 | int wret; |
| 1992 | 2126 | ||
| 1993 | node = btrfs_buffer_node(parent); | 2127 | nritems = btrfs_header_nritems(parent); |
| 1994 | nritems = btrfs_header_nritems(&node->header); | ||
| 1995 | if (slot != nritems -1) { | 2128 | if (slot != nritems -1) { |
| 1996 | btrfs_memmove(root, node, node->ptrs + slot, | 2129 | memmove_extent_buffer(parent, |
| 1997 | node->ptrs + slot + 1, | 2130 | btrfs_node_key_ptr_offset(slot), |
| 2131 | btrfs_node_key_ptr_offset(slot + 1), | ||
| 1998 | sizeof(struct btrfs_key_ptr) * | 2132 | sizeof(struct btrfs_key_ptr) * |
| 1999 | (nritems - slot - 1)); | 2133 | (nritems - slot - 1)); |
| 2000 | } | 2134 | } |
| 2001 | nritems--; | 2135 | nritems--; |
| 2002 | btrfs_set_header_nritems(&node->header, nritems); | 2136 | btrfs_set_header_nritems(parent, nritems); |
| 2003 | if (nritems == 0 && parent == root->node) { | 2137 | if (nritems == 0 && parent == root->node) { |
| 2004 | struct btrfs_header *header = btrfs_buffer_header(root->node); | 2138 | BUG_ON(btrfs_header_level(root->node) != 1); |
| 2005 | BUG_ON(btrfs_header_level(header) != 1); | ||
| 2006 | /* just turn the root into a leaf and break */ | 2139 | /* just turn the root into a leaf and break */ |
| 2007 | btrfs_set_header_level(header, 0); | 2140 | btrfs_set_header_level(root->node, 0); |
| 2008 | } else if (slot == 0) { | 2141 | } else if (slot == 0) { |
| 2009 | wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key, | 2142 | struct btrfs_disk_key disk_key; |
| 2010 | level + 1); | 2143 | |
| 2144 | btrfs_node_key(parent, &disk_key, 0); | ||
| 2145 | wret = fixup_low_keys(trans, root, path, &disk_key, level + 1); | ||
| 2011 | if (wret) | 2146 | if (wret) |
| 2012 | ret = wret; | 2147 | ret = wret; |
| 2013 | } | 2148 | } |
| @@ -2023,59 +2158,67 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 2023 | struct btrfs_path *path) | 2158 | struct btrfs_path *path) |
| 2024 | { | 2159 | { |
| 2025 | int slot; | 2160 | int slot; |
| 2026 | struct btrfs_leaf *leaf; | 2161 | struct extent_buffer *leaf; |
| 2027 | struct buffer_head *leaf_buf; | 2162 | struct btrfs_item *item; |
| 2028 | int doff; | 2163 | int doff; |
| 2029 | int dsize; | 2164 | int dsize; |
| 2030 | int ret = 0; | 2165 | int ret = 0; |
| 2031 | int wret; | 2166 | int wret; |
| 2032 | u32 nritems; | 2167 | u32 nritems; |
| 2033 | 2168 | ||
| 2034 | leaf_buf = path->nodes[0]; | 2169 | leaf = path->nodes[0]; |
| 2035 | leaf = btrfs_buffer_leaf(leaf_buf); | ||
| 2036 | slot = path->slots[0]; | 2170 | slot = path->slots[0]; |
| 2037 | doff = btrfs_item_offset(leaf->items + slot); | 2171 | doff = btrfs_item_offset_nr(leaf, slot); |
| 2038 | dsize = btrfs_item_size(leaf->items + slot); | 2172 | dsize = btrfs_item_size_nr(leaf, slot); |
| 2039 | nritems = btrfs_header_nritems(&leaf->header); | 2173 | nritems = btrfs_header_nritems(leaf); |
| 2040 | 2174 | ||
| 2041 | if (slot != nritems - 1) { | 2175 | if (slot != nritems - 1) { |
| 2042 | int i; | 2176 | int i; |
| 2043 | int data_end = leaf_data_end(root, leaf); | 2177 | int data_end = leaf_data_end(root, leaf); |
| 2044 | btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + | 2178 | |
| 2179 | memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + | ||
| 2045 | data_end + dsize, | 2180 | data_end + dsize, |
| 2046 | btrfs_leaf_data(leaf) + data_end, | 2181 | btrfs_leaf_data(leaf) + data_end, |
| 2047 | doff - data_end); | 2182 | doff - data_end); |
| 2183 | |||
| 2048 | for (i = slot + 1; i < nritems; i++) { | 2184 | for (i = slot + 1; i < nritems; i++) { |
| 2049 | u32 ioff = btrfs_item_offset(leaf->items + i); | 2185 | u32 ioff; |
| 2050 | btrfs_set_item_offset(leaf->items + i, ioff + dsize); | 2186 | item = btrfs_item_nr(leaf, i); |
| 2187 | ioff = btrfs_item_offset(leaf, item); | ||
| 2188 | btrfs_set_item_offset(leaf, item, ioff + dsize); | ||
| 2051 | } | 2189 | } |
| 2052 | btrfs_memmove(root, leaf, leaf->items + slot, | 2190 | memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot), |
| 2053 | leaf->items + slot + 1, | 2191 | btrfs_item_nr_offset(slot + 1), |
| 2054 | sizeof(struct btrfs_item) * | 2192 | sizeof(struct btrfs_item) * |
| 2055 | (nritems - slot - 1)); | 2193 | (nritems - slot - 1)); |
| 2056 | } | 2194 | } |
| 2057 | btrfs_set_header_nritems(&leaf->header, nritems - 1); | 2195 | btrfs_set_header_nritems(leaf, nritems - 1); |
| 2058 | nritems--; | 2196 | nritems--; |
| 2197 | |||
| 2059 | /* delete the leaf if we've emptied it */ | 2198 | /* delete the leaf if we've emptied it */ |
| 2060 | if (nritems == 0) { | 2199 | if (nritems == 0) { |
| 2061 | if (leaf_buf == root->node) { | 2200 | if (leaf == root->node) { |
| 2062 | btrfs_set_header_level(&leaf->header, 0); | 2201 | btrfs_set_header_level(leaf, 0); |
| 2063 | } else { | 2202 | } else { |
| 2064 | clean_tree_block(trans, root, leaf_buf); | 2203 | clean_tree_block(trans, root, leaf); |
| 2065 | wait_on_buffer(leaf_buf); | 2204 | wait_on_tree_block_writeback(root, leaf); |
| 2066 | wret = del_ptr(trans, root, path, 1, path->slots[1]); | 2205 | wret = del_ptr(trans, root, path, 1, path->slots[1]); |
| 2067 | if (wret) | 2206 | if (wret) |
| 2068 | ret = wret; | 2207 | ret = wret; |
| 2069 | wret = btrfs_free_extent(trans, root, | 2208 | wret = btrfs_free_extent(trans, root, |
| 2070 | bh_blocknr(leaf_buf), 1, 1); | 2209 | extent_buffer_blocknr(leaf), |
| 2210 | 1, 1); | ||
| 2071 | if (wret) | 2211 | if (wret) |
| 2072 | ret = wret; | 2212 | ret = wret; |
| 2073 | } | 2213 | } |
| 2074 | } else { | 2214 | } else { |
| 2075 | int used = leaf_space_used(leaf, 0, nritems); | 2215 | int used = leaf_space_used(leaf, 0, nritems); |
| 2076 | if (slot == 0) { | 2216 | if (slot == 0) { |
| 2217 | struct btrfs_disk_key disk_key; | ||
| 2218 | |||
| 2219 | btrfs_item_key(leaf, &disk_key, 0); | ||
| 2077 | wret = fixup_low_keys(trans, root, path, | 2220 | wret = fixup_low_keys(trans, root, path, |
| 2078 | &leaf->items[0].key, 1); | 2221 | &disk_key, 1); |
| 2079 | if (wret) | 2222 | if (wret) |
| 2080 | ret = wret; | 2223 | ret = wret; |
| 2081 | } | 2224 | } |
| @@ -2087,34 +2230,40 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 2087 | * for possible call to del_ptr below | 2230 | * for possible call to del_ptr below |
| 2088 | */ | 2231 | */ |
| 2089 | slot = path->slots[1]; | 2232 | slot = path->slots[1]; |
| 2090 | get_bh(leaf_buf); | 2233 | extent_buffer_get(leaf); |
| 2234 | |||
| 2091 | wret = push_leaf_left(trans, root, path, 1); | 2235 | wret = push_leaf_left(trans, root, path, 1); |
| 2092 | if (wret < 0 && wret != -ENOSPC) | 2236 | if (wret < 0 && wret != -ENOSPC) |
| 2093 | ret = wret; | 2237 | ret = wret; |
| 2094 | if (path->nodes[0] == leaf_buf && | 2238 | |
| 2095 | btrfs_header_nritems(&leaf->header)) { | 2239 | if (path->nodes[0] == leaf && |
| 2240 | btrfs_header_nritems(leaf)) { | ||
| 2096 | wret = push_leaf_right(trans, root, path, 1); | 2241 | wret = push_leaf_right(trans, root, path, 1); |
| 2097 | if (wret < 0 && wret != -ENOSPC) | 2242 | if (wret < 0 && wret != -ENOSPC) |
| 2098 | ret = wret; | 2243 | ret = wret; |
| 2099 | } | 2244 | } |
| 2100 | if (btrfs_header_nritems(&leaf->header) == 0) { | 2245 | |
| 2101 | u64 blocknr = bh_blocknr(leaf_buf); | 2246 | if (btrfs_header_nritems(leaf) == 0) { |
| 2102 | clean_tree_block(trans, root, leaf_buf); | 2247 | u64 blocknr = extent_buffer_blocknr(leaf); |
| 2103 | wait_on_buffer(leaf_buf); | 2248 | |
| 2249 | clean_tree_block(trans, root, leaf); | ||
| 2250 | wait_on_tree_block_writeback(root, leaf); | ||
| 2251 | |||
| 2104 | wret = del_ptr(trans, root, path, 1, slot); | 2252 | wret = del_ptr(trans, root, path, 1, slot); |
| 2105 | if (wret) | 2253 | if (wret) |
| 2106 | ret = wret; | 2254 | ret = wret; |
| 2107 | btrfs_block_release(root, leaf_buf); | 2255 | |
| 2256 | free_extent_buffer(leaf); | ||
| 2108 | wret = btrfs_free_extent(trans, root, blocknr, | 2257 | wret = btrfs_free_extent(trans, root, blocknr, |
| 2109 | 1, 1); | 2258 | 1, 1); |
| 2110 | if (wret) | 2259 | if (wret) |
| 2111 | ret = wret; | 2260 | ret = wret; |
| 2112 | } else { | 2261 | } else { |
| 2113 | btrfs_mark_buffer_dirty(leaf_buf); | 2262 | btrfs_mark_buffer_dirty(leaf); |
| 2114 | btrfs_block_release(root, leaf_buf); | 2263 | free_extent_buffer(leaf); |
| 2115 | } | 2264 | } |
| 2116 | } else { | 2265 | } else { |
| 2117 | btrfs_mark_buffer_dirty(leaf_buf); | 2266 | btrfs_mark_buffer_dirty(leaf); |
| 2118 | } | 2267 | } |
| 2119 | } | 2268 | } |
| 2120 | return ret; | 2269 | return ret; |
| @@ -2130,25 +2279,27 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
| 2130 | int slot; | 2279 | int slot; |
| 2131 | int level = 1; | 2280 | int level = 1; |
| 2132 | u64 blocknr; | 2281 | u64 blocknr; |
| 2133 | struct buffer_head *c; | 2282 | struct extent_buffer *c; |
| 2134 | struct btrfs_node *c_node; | 2283 | struct extent_buffer *next = NULL; |
| 2135 | struct buffer_head *next = NULL; | ||
| 2136 | 2284 | ||
| 2137 | while(level < BTRFS_MAX_LEVEL) { | 2285 | while(level < BTRFS_MAX_LEVEL) { |
| 2138 | if (!path->nodes[level]) | 2286 | if (!path->nodes[level]) |
| 2139 | return 1; | 2287 | return 1; |
| 2288 | |||
| 2140 | slot = path->slots[level] + 1; | 2289 | slot = path->slots[level] + 1; |
| 2141 | c = path->nodes[level]; | 2290 | c = path->nodes[level]; |
| 2142 | c_node = btrfs_buffer_node(c); | 2291 | if (slot >= btrfs_header_nritems(c)) { |
| 2143 | if (slot >= btrfs_header_nritems(&c_node->header)) { | ||
| 2144 | level++; | 2292 | level++; |
| 2145 | continue; | 2293 | continue; |
| 2146 | } | 2294 | } |
| 2147 | blocknr = btrfs_node_blockptr(c_node, slot); | 2295 | |
| 2296 | blocknr = btrfs_node_blockptr(c, slot); | ||
| 2148 | if (next) | 2297 | if (next) |
| 2149 | btrfs_block_release(root, next); | 2298 | free_extent_buffer(next); |
| 2299 | |||
| 2150 | if (path->reada) | 2300 | if (path->reada) |
| 2151 | reada_for_search(root, path, level, slot); | 2301 | reada_for_search(root, path, level, slot); |
| 2302 | |||
| 2152 | next = read_tree_block(root, blocknr); | 2303 | next = read_tree_block(root, blocknr); |
| 2153 | break; | 2304 | break; |
| 2154 | } | 2305 | } |
| @@ -2156,15 +2307,14 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
| 2156 | while(1) { | 2307 | while(1) { |
| 2157 | level--; | 2308 | level--; |
| 2158 | c = path->nodes[level]; | 2309 | c = path->nodes[level]; |
| 2159 | btrfs_block_release(root, c); | 2310 | free_extent_buffer(c); |
| 2160 | path->nodes[level] = next; | 2311 | path->nodes[level] = next; |
| 2161 | path->slots[level] = 0; | 2312 | path->slots[level] = 0; |
| 2162 | if (!level) | 2313 | if (!level) |
| 2163 | break; | 2314 | break; |
| 2164 | if (path->reada) | 2315 | if (path->reada) |
| 2165 | reada_for_search(root, path, level, 0); | 2316 | reada_for_search(root, path, level, 0); |
| 2166 | next = read_tree_block(root, | 2317 | next = read_tree_block(root, btrfs_node_blockptr(next, 0)); |
| 2167 | btrfs_node_blockptr(btrfs_buffer_node(next), 0)); | ||
| 2168 | } | 2318 | } |
| 2169 | return 0; | 2319 | return 0; |
| 2170 | } | 2320 | } |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 800a3499cc3f..c4b829806855 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -20,10 +20,10 @@ | |||
| 20 | #define __BTRFS__ | 20 | #define __BTRFS__ |
| 21 | 21 | ||
| 22 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
| 23 | #include <linux/buffer_head.h> | ||
| 24 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
| 25 | #include <linux/completion.h> | 24 | #include <linux/completion.h> |
| 26 | #include "bit-radix.h" | 25 | #include "bit-radix.h" |
| 26 | #include "extent_map.h" | ||
| 27 | 27 | ||
| 28 | struct btrfs_trans_handle; | 28 | struct btrfs_trans_handle; |
| 29 | struct btrfs_transaction; | 29 | struct btrfs_transaction; |
| @@ -32,7 +32,7 @@ extern struct kmem_cache *btrfs_transaction_cachep; | |||
| 32 | extern struct kmem_cache *btrfs_bit_radix_cachep; | 32 | extern struct kmem_cache *btrfs_bit_radix_cachep; |
| 33 | extern struct kmem_cache *btrfs_path_cachep; | 33 | extern struct kmem_cache *btrfs_path_cachep; |
| 34 | 34 | ||
| 35 | #define BTRFS_MAGIC "_BtRfS_M" | 35 | #define BTRFS_MAGIC "_B2RfS_M" |
| 36 | 36 | ||
| 37 | #define BTRFS_ROOT_TREE_OBJECTID 1ULL | 37 | #define BTRFS_ROOT_TREE_OBJECTID 1ULL |
| 38 | #define BTRFS_EXTENT_TREE_OBJECTID 2ULL | 38 | #define BTRFS_EXTENT_TREE_OBJECTID 2ULL |
| @@ -78,41 +78,41 @@ extern struct kmem_cache *btrfs_path_cachep; | |||
| 78 | */ | 78 | */ |
| 79 | struct btrfs_disk_key { | 79 | struct btrfs_disk_key { |
| 80 | __le64 objectid; | 80 | __le64 objectid; |
| 81 | __le32 flags; | 81 | u8 type; |
| 82 | __le64 offset; | 82 | __le64 offset; |
| 83 | } __attribute__ ((__packed__)); | 83 | } __attribute__ ((__packed__)); |
| 84 | 84 | ||
| 85 | struct btrfs_key { | 85 | struct btrfs_key { |
| 86 | u64 objectid; | 86 | u64 objectid; |
| 87 | u32 flags; | 87 | u8 type; |
| 88 | u64 offset; | 88 | u64 offset; |
| 89 | } __attribute__ ((__packed__)); | 89 | } __attribute__ ((__packed__)); |
| 90 | 90 | ||
| 91 | #define BTRFS_FSID_SIZE 16 | ||
| 91 | /* | 92 | /* |
| 92 | * every tree block (leaf or node) starts with this header. | 93 | * every tree block (leaf or node) starts with this header. |
| 93 | */ | 94 | */ |
| 94 | struct btrfs_header { | 95 | struct btrfs_header { |
| 95 | u8 csum[BTRFS_CSUM_SIZE]; | 96 | u8 csum[BTRFS_CSUM_SIZE]; |
| 96 | u8 fsid[16]; /* FS specific uuid */ | 97 | u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */ |
| 97 | __le64 blocknr; /* which block this node is supposed to live in */ | 98 | __le64 blocknr; /* which block this node is supposed to live in */ |
| 98 | __le64 generation; | 99 | __le64 generation; |
| 99 | __le64 owner; | 100 | __le64 owner; |
| 100 | __le16 nritems; | 101 | __le32 nritems; |
| 101 | __le16 flags; | 102 | __le16 flags; |
| 102 | u8 level; | 103 | u8 level; |
| 103 | } __attribute__ ((__packed__)); | 104 | } __attribute__ ((__packed__)); |
| 104 | 105 | ||
| 105 | #define BTRFS_MAX_LEVEL 8 | 106 | #define BTRFS_MAX_LEVEL 8 |
| 106 | #define BTRFS_NODEPTRS_PER_BLOCK(r) (((r)->blocksize - \ | 107 | #define BTRFS_NODEPTRS_PER_BLOCK(r) (((r)->nodesize - \ |
| 107 | sizeof(struct btrfs_header)) / \ | 108 | sizeof(struct btrfs_header)) / \ |
| 108 | (sizeof(struct btrfs_disk_key) + sizeof(u64))) | 109 | (sizeof(struct btrfs_disk_key) + sizeof(u64))) |
| 109 | #define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header)) | 110 | #define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header)) |
| 110 | #define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->blocksize)) | 111 | #define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->leafsize)) |
| 111 | #define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \ | 112 | #define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \ |
| 112 | sizeof(struct btrfs_item) - \ | 113 | sizeof(struct btrfs_item) - \ |
| 113 | sizeof(struct btrfs_file_extent_item)) | 114 | sizeof(struct btrfs_file_extent_item)) |
| 114 | 115 | ||
| 115 | struct buffer_head; | ||
| 116 | /* | 116 | /* |
| 117 | * the super block basically lists the main trees of the FS | 117 | * the super block basically lists the main trees of the FS |
| 118 | * it currently lacks any block count etc etc | 118 | * it currently lacks any block count etc etc |
| @@ -128,7 +128,9 @@ struct btrfs_super_block { | |||
| 128 | __le64 total_blocks; | 128 | __le64 total_blocks; |
| 129 | __le64 blocks_used; | 129 | __le64 blocks_used; |
| 130 | __le64 root_dir_objectid; | 130 | __le64 root_dir_objectid; |
| 131 | __le32 blocksize; | 131 | __le32 sectorsize; |
| 132 | __le32 nodesize; | ||
| 133 | __le32 leafsize; | ||
| 132 | } __attribute__ ((__packed__)); | 134 | } __attribute__ ((__packed__)); |
| 133 | 135 | ||
| 134 | /* | 136 | /* |
| @@ -138,7 +140,7 @@ struct btrfs_super_block { | |||
| 138 | struct btrfs_item { | 140 | struct btrfs_item { |
| 139 | struct btrfs_disk_key key; | 141 | struct btrfs_disk_key key; |
| 140 | __le32 offset; | 142 | __le32 offset; |
| 141 | __le16 size; | 143 | __le32 size; |
| 142 | } __attribute__ ((__packed__)); | 144 | } __attribute__ ((__packed__)); |
| 143 | 145 | ||
| 144 | /* | 146 | /* |
| @@ -176,7 +178,7 @@ struct btrfs_node { | |||
| 176 | * used while walking the tree. | 178 | * used while walking the tree. |
| 177 | */ | 179 | */ |
| 178 | struct btrfs_path { | 180 | struct btrfs_path { |
| 179 | struct buffer_head *nodes[BTRFS_MAX_LEVEL]; | 181 | struct extent_buffer *nodes[BTRFS_MAX_LEVEL]; |
| 180 | int slots[BTRFS_MAX_LEVEL]; | 182 | int slots[BTRFS_MAX_LEVEL]; |
| 181 | int reada; | 183 | int reada; |
| 182 | int lowest_level; | 184 | int lowest_level; |
| @@ -292,6 +294,7 @@ struct btrfs_block_group_cache { | |||
| 292 | }; | 294 | }; |
| 293 | 295 | ||
| 294 | struct btrfs_fs_info { | 296 | struct btrfs_fs_info { |
| 297 | u8 fsid[BTRFS_FSID_SIZE]; | ||
| 295 | struct btrfs_root *extent_root; | 298 | struct btrfs_root *extent_root; |
| 296 | struct btrfs_root *tree_root; | 299 | struct btrfs_root *tree_root; |
| 297 | struct radix_tree_root fs_roots_radix; | 300 | struct radix_tree_root fs_roots_radix; |
| @@ -304,9 +307,8 @@ struct btrfs_fs_info { | |||
| 304 | u64 generation; | 307 | u64 generation; |
| 305 | u64 last_trans_committed; | 308 | u64 last_trans_committed; |
| 306 | struct btrfs_transaction *running_transaction; | 309 | struct btrfs_transaction *running_transaction; |
| 307 | struct btrfs_super_block *disk_super; | ||
| 308 | struct btrfs_super_block super_copy; | 310 | struct btrfs_super_block super_copy; |
| 309 | struct buffer_head *sb_buffer; | 311 | struct extent_buffer *sb_buffer; |
| 310 | struct super_block *sb; | 312 | struct super_block *sb; |
| 311 | struct inode *btree_inode; | 313 | struct inode *btree_inode; |
| 312 | struct mutex trans_mutex; | 314 | struct mutex trans_mutex; |
| @@ -325,8 +327,8 @@ struct btrfs_fs_info { | |||
| 325 | * and for the extent tree extent_root root. | 327 | * and for the extent tree extent_root root. |
| 326 | */ | 328 | */ |
| 327 | struct btrfs_root { | 329 | struct btrfs_root { |
| 328 | struct buffer_head *node; | 330 | struct extent_buffer *node; |
| 329 | struct buffer_head *commit_root; | 331 | struct extent_buffer *commit_root; |
| 330 | struct btrfs_root_item root_item; | 332 | struct btrfs_root_item root_item; |
| 331 | struct btrfs_key root_key; | 333 | struct btrfs_key root_key; |
| 332 | struct btrfs_fs_info *fs_info; | 334 | struct btrfs_fs_info *fs_info; |
| @@ -336,7 +338,16 @@ struct btrfs_root { | |||
| 336 | struct rw_semaphore snap_sem; | 338 | struct rw_semaphore snap_sem; |
| 337 | u64 objectid; | 339 | u64 objectid; |
| 338 | u64 last_trans; | 340 | u64 last_trans; |
| 339 | u32 blocksize; | 341 | |
| 342 | /* data allocations are done in sectorsize units */ | ||
| 343 | u32 sectorsize; | ||
| 344 | |||
| 345 | /* node allocations are done in nodesize units */ | ||
| 346 | u32 nodesize; | ||
| 347 | |||
| 348 | /* leaf allocations are done in leafsize units */ | ||
| 349 | u32 leafsize; | ||
| 350 | |||
| 340 | u32 type; | 351 | u32 type; |
| 341 | u64 highest_inode; | 352 | u64 highest_inode; |
| 342 | u64 last_inode_alloc; | 353 | u64 last_inode_alloc; |
| @@ -347,12 +358,6 @@ struct btrfs_root { | |||
| 347 | char *name; | 358 | char *name; |
| 348 | }; | 359 | }; |
| 349 | 360 | ||
| 350 | /* the lower bits in the key flags defines the item type */ | ||
| 351 | #define BTRFS_KEY_TYPE_MAX 256 | ||
| 352 | #define BTRFS_KEY_TYPE_SHIFT 24 | ||
| 353 | #define BTRFS_KEY_TYPE_MASK (((u32)BTRFS_KEY_TYPE_MAX - 1) << \ | ||
| 354 | BTRFS_KEY_TYPE_SHIFT) | ||
| 355 | |||
| 356 | /* | 361 | /* |
| 357 | * inode items have the data typically returned from stat and store other | 362 | * inode items have the data typically returned from stat and store other |
| 358 | * info about object characteristics. There is one for every file and dir in | 363 | * info about object characteristics. There is one for every file and dir in |
| @@ -402,246 +407,253 @@ struct btrfs_root { | |||
| 402 | */ | 407 | */ |
| 403 | #define BTRFS_STRING_ITEM_KEY 253 | 408 | #define BTRFS_STRING_ITEM_KEY 253 |
| 404 | 409 | ||
| 410 | /* some macros to generate set/get funcs for the struct fields. This | ||
| 411 | * assumes there is a lefoo_to_cpu for every type, so lets make a simple | ||
| 412 | * one for u8: | ||
| 413 | */ | ||
| 414 | #define le8_to_cpu(v) (v) | ||
| 415 | #define cpu_to_le8(v) (v) | ||
| 416 | #define __le8 u8 | ||
| 417 | |||
| 418 | #define read_eb_member(eb, ptr, type, member, result) ( \ | ||
| 419 | read_extent_buffer(eb, (char *)(result), \ | ||
| 420 | ((unsigned long)(ptr)) + \ | ||
| 421 | offsetof(type, member), \ | ||
| 422 | sizeof(((type *)0)->member))) | ||
| 423 | |||
| 424 | #define write_eb_member(eb, ptr, type, member, result) ( \ | ||
| 425 | write_extent_buffer(eb, (char *)(result), \ | ||
| 426 | ((unsigned long)(ptr)) + \ | ||
| 427 | offsetof(type, member), \ | ||
| 428 | sizeof(((type *)0)->member))) | ||
| 429 | |||
| 430 | #define BTRFS_SETGET_FUNCS(name, type, member, bits) \ | ||
| 431 | static inline u##bits btrfs_##name(struct extent_buffer *eb, \ | ||
| 432 | type *s) \ | ||
| 433 | { \ | ||
| 434 | __le##bits res; \ | ||
| 435 | read_eb_member(eb, s, type, member, &res); \ | ||
| 436 | return le##bits##_to_cpu(res); \ | ||
| 437 | } \ | ||
| 438 | static inline void btrfs_set_##name(struct extent_buffer *eb, \ | ||
| 439 | type *s, u##bits val) \ | ||
| 440 | { \ | ||
| 441 | val = cpu_to_le##bits(val); \ | ||
| 442 | write_eb_member(eb, s, type, member, &val); \ | ||
| 443 | } | ||
| 444 | |||
| 445 | #define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \ | ||
| 446 | static inline u##bits btrfs_##name(struct extent_buffer *eb) \ | ||
| 447 | { \ | ||
| 448 | __le##bits res; \ | ||
| 449 | read_eb_member(eb, NULL, type, member, &res); \ | ||
| 450 | return le##bits##_to_cpu(res); \ | ||
| 451 | } \ | ||
| 452 | static inline void btrfs_set_##name(struct extent_buffer *eb, \ | ||
| 453 | u##bits val) \ | ||
| 454 | { \ | ||
| 455 | val = cpu_to_le##bits(val); \ | ||
| 456 | write_eb_member(eb, NULL, type, member, &val); \ | ||
| 457 | } | ||
| 405 | 458 | ||
| 406 | static inline u64 btrfs_block_group_used(struct btrfs_block_group_item *bi) | 459 | #define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \ |
| 407 | { | 460 | static inline u##bits btrfs_##name(type *s) \ |
| 408 | return le64_to_cpu(bi->used); | 461 | { \ |
| 409 | } | 462 | return le##bits##_to_cpu(s->member); \ |
| 410 | 463 | } \ | |
| 411 | static inline void btrfs_set_block_group_used(struct | 464 | static inline void btrfs_set_##name(type *s, u##bits val) \ |
| 412 | btrfs_block_group_item *bi, | 465 | { \ |
| 413 | u64 val) | 466 | s->member = cpu_to_le##bits(val); \ |
| 414 | { | ||
| 415 | bi->used = cpu_to_le64(val); | ||
| 416 | } | ||
| 417 | |||
| 418 | static inline u64 btrfs_inode_generation(struct btrfs_inode_item *i) | ||
| 419 | { | ||
| 420 | return le64_to_cpu(i->generation); | ||
| 421 | } | ||
| 422 | |||
| 423 | static inline void btrfs_set_inode_generation(struct btrfs_inode_item *i, | ||
| 424 | u64 val) | ||
| 425 | { | ||
| 426 | i->generation = cpu_to_le64(val); | ||
| 427 | } | ||
| 428 | |||
| 429 | static inline u64 btrfs_inode_size(struct btrfs_inode_item *i) | ||
| 430 | { | ||
| 431 | return le64_to_cpu(i->size); | ||
| 432 | } | ||
| 433 | |||
| 434 | static inline void btrfs_set_inode_size(struct btrfs_inode_item *i, u64 val) | ||
| 435 | { | ||
| 436 | i->size = cpu_to_le64(val); | ||
| 437 | } | ||
| 438 | |||
| 439 | static inline u64 btrfs_inode_nblocks(struct btrfs_inode_item *i) | ||
| 440 | { | ||
| 441 | return le64_to_cpu(i->nblocks); | ||
| 442 | } | ||
| 443 | |||
| 444 | static inline void btrfs_set_inode_nblocks(struct btrfs_inode_item *i, u64 val) | ||
| 445 | { | ||
| 446 | i->nblocks = cpu_to_le64(val); | ||
| 447 | } | ||
| 448 | |||
| 449 | static inline u64 btrfs_inode_block_group(struct btrfs_inode_item *i) | ||
| 450 | { | ||
| 451 | return le64_to_cpu(i->block_group); | ||
| 452 | } | ||
| 453 | |||
| 454 | static inline void btrfs_set_inode_block_group(struct btrfs_inode_item *i, | ||
| 455 | u64 val) | ||
| 456 | { | ||
| 457 | i->block_group = cpu_to_le64(val); | ||
| 458 | } | ||
| 459 | |||
| 460 | static inline u32 btrfs_inode_nlink(struct btrfs_inode_item *i) | ||
| 461 | { | ||
| 462 | return le32_to_cpu(i->nlink); | ||
| 463 | } | ||
| 464 | |||
| 465 | static inline void btrfs_set_inode_nlink(struct btrfs_inode_item *i, u32 val) | ||
| 466 | { | ||
| 467 | i->nlink = cpu_to_le32(val); | ||
| 468 | } | ||
| 469 | |||
| 470 | static inline u32 btrfs_inode_uid(struct btrfs_inode_item *i) | ||
| 471 | { | ||
| 472 | return le32_to_cpu(i->uid); | ||
| 473 | } | ||
| 474 | |||
| 475 | static inline void btrfs_set_inode_uid(struct btrfs_inode_item *i, u32 val) | ||
| 476 | { | ||
| 477 | i->uid = cpu_to_le32(val); | ||
| 478 | } | ||
| 479 | |||
| 480 | static inline u32 btrfs_inode_gid(struct btrfs_inode_item *i) | ||
| 481 | { | ||
| 482 | return le32_to_cpu(i->gid); | ||
| 483 | } | ||
| 484 | |||
| 485 | static inline void btrfs_set_inode_gid(struct btrfs_inode_item *i, u32 val) | ||
| 486 | { | ||
| 487 | i->gid = cpu_to_le32(val); | ||
| 488 | } | ||
| 489 | |||
| 490 | static inline u32 btrfs_inode_mode(struct btrfs_inode_item *i) | ||
| 491 | { | ||
| 492 | return le32_to_cpu(i->mode); | ||
| 493 | } | ||
| 494 | |||
| 495 | static inline void btrfs_set_inode_mode(struct btrfs_inode_item *i, u32 val) | ||
| 496 | { | ||
| 497 | i->mode = cpu_to_le32(val); | ||
| 498 | } | 467 | } |
| 499 | 468 | ||
| 500 | static inline u32 btrfs_inode_rdev(struct btrfs_inode_item *i) | 469 | /* struct btrfs_block_group_item */ |
| 501 | { | 470 | BTRFS_SETGET_STACK_FUNCS(block_group_used, struct btrfs_block_group_item, |
| 502 | return le32_to_cpu(i->rdev); | 471 | used, 64); |
| 503 | } | 472 | BTRFS_SETGET_FUNCS(disk_block_group_used, struct btrfs_block_group_item, |
| 473 | used, 64); | ||
| 504 | 474 | ||
| 505 | static inline void btrfs_set_inode_rdev(struct btrfs_inode_item *i, u32 val) | 475 | /* struct btrfs_inode_item */ |
| 506 | { | 476 | BTRFS_SETGET_FUNCS(inode_generation, struct btrfs_inode_item, generation, 64); |
| 507 | i->rdev = cpu_to_le32(val); | 477 | BTRFS_SETGET_FUNCS(inode_size, struct btrfs_inode_item, size, 64); |
| 508 | } | 478 | BTRFS_SETGET_FUNCS(inode_nblocks, struct btrfs_inode_item, nblocks, 64); |
| 479 | BTRFS_SETGET_FUNCS(inode_block_group, struct btrfs_inode_item, block_group, 64); | ||
| 480 | BTRFS_SETGET_FUNCS(inode_nlink, struct btrfs_inode_item, nlink, 32); | ||
| 481 | BTRFS_SETGET_FUNCS(inode_uid, struct btrfs_inode_item, uid, 32); | ||
| 482 | BTRFS_SETGET_FUNCS(inode_gid, struct btrfs_inode_item, gid, 32); | ||
| 483 | BTRFS_SETGET_FUNCS(inode_mode, struct btrfs_inode_item, mode, 32); | ||
| 484 | BTRFS_SETGET_FUNCS(inode_rdev, struct btrfs_inode_item, rdev, 32); | ||
| 485 | BTRFS_SETGET_FUNCS(inode_flags, struct btrfs_inode_item, flags, 16); | ||
| 486 | BTRFS_SETGET_FUNCS(inode_compat_flags, struct btrfs_inode_item, | ||
| 487 | compat_flags, 16); | ||
| 509 | 488 | ||
| 510 | static inline u16 btrfs_inode_flags(struct btrfs_inode_item *i) | 489 | static inline struct btrfs_inode_timespec * |
| 490 | btrfs_inode_atime(struct btrfs_inode_item *inode_item) | ||
| 511 | { | 491 | { |
| 512 | return le16_to_cpu(i->flags); | 492 | unsigned long ptr = (unsigned long)inode_item; |
| 493 | ptr += offsetof(struct btrfs_inode_item, atime); | ||
| 494 | return (struct btrfs_inode_timespec *)ptr; | ||
| 513 | } | 495 | } |
| 514 | 496 | ||
| 515 | static inline void btrfs_set_inode_flags(struct btrfs_inode_item *i, u16 val) | 497 | static inline struct btrfs_inode_timespec * |
| 498 | btrfs_inode_mtime(struct btrfs_inode_item *inode_item) | ||
| 516 | { | 499 | { |
| 517 | i->flags = cpu_to_le16(val); | 500 | unsigned long ptr = (unsigned long)inode_item; |
| 501 | ptr += offsetof(struct btrfs_inode_item, mtime); | ||
| 502 | return (struct btrfs_inode_timespec *)ptr; | ||
| 518 | } | 503 | } |
| 519 | 504 | ||
| 520 | static inline u16 btrfs_inode_compat_flags(struct btrfs_inode_item *i) | 505 | static inline struct btrfs_inode_timespec * |
| 506 | btrfs_inode_ctime(struct btrfs_inode_item *inode_item) | ||
| 521 | { | 507 | { |
| 522 | return le16_to_cpu(i->compat_flags); | 508 | unsigned long ptr = (unsigned long)inode_item; |
| 509 | ptr += offsetof(struct btrfs_inode_item, ctime); | ||
| 510 | return (struct btrfs_inode_timespec *)ptr; | ||
| 523 | } | 511 | } |
| 524 | 512 | ||
| 525 | static inline void btrfs_set_inode_compat_flags(struct btrfs_inode_item *i, | 513 | static inline struct btrfs_inode_timespec * |
| 526 | u16 val) | 514 | btrfs_inode_otime(struct btrfs_inode_item *inode_item) |
| 527 | { | 515 | { |
| 528 | i->compat_flags = cpu_to_le16(val); | 516 | unsigned long ptr = (unsigned long)inode_item; |
| 517 | ptr += offsetof(struct btrfs_inode_item, otime); | ||
| 518 | return (struct btrfs_inode_timespec *)ptr; | ||
| 529 | } | 519 | } |
| 530 | 520 | ||
| 531 | static inline u64 btrfs_timespec_sec(struct btrfs_inode_timespec *ts) | 521 | BTRFS_SETGET_FUNCS(timespec_sec, struct btrfs_inode_timespec, sec, 64); |
| 532 | { | 522 | BTRFS_SETGET_FUNCS(timespec_nsec, struct btrfs_inode_timespec, nsec, 32); |
| 533 | return le64_to_cpu(ts->sec); | ||
| 534 | } | ||
| 535 | 523 | ||
| 536 | static inline void btrfs_set_timespec_sec(struct btrfs_inode_timespec *ts, | 524 | /* struct btrfs_extent_item */ |
| 537 | u64 val) | 525 | BTRFS_SETGET_FUNCS(extent_refs, struct btrfs_extent_item, refs, 32); |
| 538 | { | 526 | BTRFS_SETGET_FUNCS(extent_owner, struct btrfs_extent_item, owner, 32); |
| 539 | ts->sec = cpu_to_le64(val); | ||
| 540 | } | ||
| 541 | 527 | ||
| 542 | static inline u32 btrfs_timespec_nsec(struct btrfs_inode_timespec *ts) | 528 | BTRFS_SETGET_STACK_FUNCS(stack_extent_refs, struct btrfs_extent_item, |
| 543 | { | 529 | refs, 32); |
| 544 | return le32_to_cpu(ts->nsec); | 530 | BTRFS_SETGET_STACK_FUNCS(stack_extent_owner, struct btrfs_extent_item, |
| 545 | } | 531 | owner, 32); |
| 546 | 532 | ||
| 547 | static inline void btrfs_set_timespec_nsec(struct btrfs_inode_timespec *ts, | 533 | /* struct btrfs_node */ |
| 548 | u32 val) | 534 | BTRFS_SETGET_FUNCS(key_blockptr, struct btrfs_key_ptr, blockptr, 64); |
| 549 | { | ||
| 550 | ts->nsec = cpu_to_le32(val); | ||
| 551 | } | ||
| 552 | 535 | ||
| 553 | static inline u32 btrfs_extent_refs(struct btrfs_extent_item *ei) | 536 | static inline u64 btrfs_node_blockptr(struct extent_buffer *eb, int nr) |
| 554 | { | 537 | { |
| 555 | return le32_to_cpu(ei->refs); | 538 | unsigned long ptr; |
| 539 | ptr = offsetof(struct btrfs_node, ptrs) + | ||
| 540 | sizeof(struct btrfs_key_ptr) * nr; | ||
| 541 | return btrfs_key_blockptr(eb, (struct btrfs_key_ptr *)ptr); | ||
| 556 | } | 542 | } |
| 557 | 543 | ||
| 558 | static inline void btrfs_set_extent_refs(struct btrfs_extent_item *ei, u32 val) | 544 | static inline void btrfs_set_node_blockptr(struct extent_buffer *eb, |
| 545 | int nr, u64 val) | ||
| 559 | { | 546 | { |
| 560 | ei->refs = cpu_to_le32(val); | 547 | unsigned long ptr; |
| 548 | ptr = offsetof(struct btrfs_node, ptrs) + | ||
| 549 | sizeof(struct btrfs_key_ptr) * nr; | ||
| 550 | btrfs_set_key_blockptr(eb, (struct btrfs_key_ptr *)ptr, val); | ||
| 561 | } | 551 | } |
| 562 | 552 | ||
| 563 | static inline u64 btrfs_extent_owner(struct btrfs_extent_item *ei) | 553 | static unsigned long btrfs_node_key_ptr_offset(int nr) |
| 564 | { | 554 | { |
| 565 | return le64_to_cpu(ei->owner); | 555 | return offsetof(struct btrfs_node, ptrs) + |
| 556 | sizeof(struct btrfs_key_ptr) * nr; | ||
| 566 | } | 557 | } |
| 567 | 558 | ||
| 568 | static inline void btrfs_set_extent_owner(struct btrfs_extent_item *ei, u64 val) | 559 | static void btrfs_node_key(struct extent_buffer *eb, |
| 560 | struct btrfs_disk_key *disk_key, int nr) | ||
| 569 | { | 561 | { |
| 570 | ei->owner = cpu_to_le64(val); | 562 | unsigned long ptr; |
| 563 | ptr = btrfs_node_key_ptr_offset(nr); | ||
| 564 | read_eb_member(eb, (struct btrfs_key_ptr *)ptr, | ||
| 565 | struct btrfs_key_ptr, key, disk_key); | ||
| 571 | } | 566 | } |
| 572 | 567 | static inline void btrfs_set_node_key(struct extent_buffer *eb, | |
| 573 | static inline u64 btrfs_node_blockptr(struct btrfs_node *n, int nr) | 568 | struct btrfs_disk_key *disk_key, int nr) |
| 574 | { | 569 | { |
| 575 | return le64_to_cpu(n->ptrs[nr].blockptr); | 570 | unsigned long ptr; |
| 571 | ptr = btrfs_node_key_ptr_offset(nr); | ||
| 572 | write_eb_member(eb, (struct btrfs_key_ptr *)ptr, | ||
| 573 | struct btrfs_key_ptr, key, disk_key); | ||
| 576 | } | 574 | } |
| 577 | 575 | ||
| 576 | /* struct btrfs_item */ | ||
| 577 | BTRFS_SETGET_FUNCS(item_offset, struct btrfs_item, offset, 32); | ||
| 578 | BTRFS_SETGET_FUNCS(item_size, struct btrfs_item, size, 32); | ||
| 578 | 579 | ||
| 579 | static inline void btrfs_set_node_blockptr(struct btrfs_node *n, int nr, | 580 | static inline unsigned long btrfs_item_nr_offset(int nr) |
| 580 | u64 val) | ||
| 581 | { | 581 | { |
| 582 | n->ptrs[nr].blockptr = cpu_to_le64(val); | 582 | return offsetof(struct btrfs_leaf, items) + |
| 583 | sizeof(struct btrfs_item) * nr; | ||
| 583 | } | 584 | } |
| 584 | 585 | ||
| 585 | static inline u32 btrfs_item_offset(struct btrfs_item *item) | 586 | static inline struct btrfs_item *btrfs_item_nr(struct extent_buffer *eb, |
| 587 | int nr) | ||
| 586 | { | 588 | { |
| 587 | return le32_to_cpu(item->offset); | 589 | return (struct btrfs_item *)btrfs_item_nr_offset(nr); |
| 588 | } | 590 | } |
| 589 | 591 | ||
| 590 | static inline void btrfs_set_item_offset(struct btrfs_item *item, u32 val) | 592 | static inline u32 btrfs_item_end(struct extent_buffer *eb, |
| 593 | struct btrfs_item *item) | ||
| 591 | { | 594 | { |
| 592 | item->offset = cpu_to_le32(val); | 595 | return btrfs_item_offset(eb, item) + btrfs_item_size(eb, item); |
| 593 | } | 596 | } |
| 594 | 597 | ||
| 595 | static inline u32 btrfs_item_end(struct btrfs_item *item) | 598 | static inline u32 btrfs_item_end_nr(struct extent_buffer *eb, int nr) |
| 596 | { | 599 | { |
| 597 | return le32_to_cpu(item->offset) + le16_to_cpu(item->size); | 600 | return btrfs_item_end(eb, btrfs_item_nr(eb, nr)); |
| 598 | } | 601 | } |
| 599 | 602 | ||
| 600 | static inline u16 btrfs_item_size(struct btrfs_item *item) | 603 | static inline u32 btrfs_item_offset_nr(struct extent_buffer *eb, int nr) |
| 601 | { | 604 | { |
| 602 | return le16_to_cpu(item->size); | 605 | return btrfs_item_offset(eb, btrfs_item_nr(eb, nr)); |
| 603 | } | 606 | } |
| 604 | 607 | ||
| 605 | static inline void btrfs_set_item_size(struct btrfs_item *item, u16 val) | 608 | static inline u32 btrfs_item_size_nr(struct extent_buffer *eb, int nr) |
| 606 | { | 609 | { |
| 607 | item->size = cpu_to_le16(val); | 610 | return btrfs_item_size(eb, btrfs_item_nr(eb, nr)); |
| 608 | } | 611 | } |
| 609 | 612 | ||
| 610 | static inline u16 btrfs_dir_flags(struct btrfs_dir_item *d) | 613 | static inline void btrfs_item_key(struct extent_buffer *eb, |
| 614 | struct btrfs_disk_key *disk_key, int nr) | ||
| 611 | { | 615 | { |
| 612 | return le16_to_cpu(d->flags); | 616 | struct btrfs_item *item = btrfs_item_nr(eb, nr); |
| 617 | read_eb_member(eb, item, struct btrfs_item, key, disk_key); | ||
| 613 | } | 618 | } |
| 614 | 619 | ||
| 615 | static inline void btrfs_set_dir_flags(struct btrfs_dir_item *d, u16 val) | 620 | static inline void btrfs_set_item_key(struct extent_buffer *eb, |
| 621 | struct btrfs_disk_key *disk_key, int nr) | ||
| 616 | { | 622 | { |
| 617 | d->flags = cpu_to_le16(val); | 623 | struct btrfs_item *item = btrfs_item_nr(eb, nr); |
| 624 | write_eb_member(eb, item, struct btrfs_item, key, disk_key); | ||
| 618 | } | 625 | } |
| 619 | 626 | ||
| 620 | static inline u8 btrfs_dir_type(struct btrfs_dir_item *d) | 627 | /* struct btrfs_dir_item */ |
| 621 | { | 628 | BTRFS_SETGET_FUNCS(dir_flags, struct btrfs_dir_item, flags, 16); |
| 622 | return d->type; | 629 | BTRFS_SETGET_FUNCS(dir_type, struct btrfs_dir_item, type, 8); |
| 623 | } | 630 | BTRFS_SETGET_FUNCS(dir_name_len, struct btrfs_dir_item, name_len, 16); |
| 624 | 631 | ||
| 625 | static inline void btrfs_set_dir_type(struct btrfs_dir_item *d, u8 val) | 632 | static inline void btrfs_dir_item_key(struct extent_buffer *eb, |
| 633 | struct btrfs_dir_item *item, | ||
| 634 | struct btrfs_disk_key *key) | ||
| 626 | { | 635 | { |
| 627 | d->type = val; | 636 | read_eb_member(eb, item, struct btrfs_dir_item, location, key); |
| 628 | } | 637 | } |
| 629 | 638 | ||
| 630 | static inline u16 btrfs_dir_name_len(struct btrfs_dir_item *d) | 639 | static inline void btrfs_set_dir_item_key(struct extent_buffer *eb, |
| 640 | struct btrfs_dir_item *item, | ||
| 641 | struct btrfs_disk_key *key) | ||
| 631 | { | 642 | { |
| 632 | return le16_to_cpu(d->name_len); | 643 | write_eb_member(eb, item, struct btrfs_dir_item, location, key); |
| 633 | } | 644 | } |
| 634 | 645 | ||
| 635 | static inline void btrfs_set_dir_name_len(struct btrfs_dir_item *d, u16 val) | 646 | /* struct btrfs_disk_key */ |
| 636 | { | 647 | BTRFS_SETGET_STACK_FUNCS(disk_key_objectid, struct btrfs_disk_key, |
| 637 | d->name_len = cpu_to_le16(val); | 648 | objectid, 64); |
| 638 | } | 649 | BTRFS_SETGET_STACK_FUNCS(disk_key_offset, struct btrfs_disk_key, offset, 64); |
| 650 | BTRFS_SETGET_STACK_FUNCS(disk_key_type, struct btrfs_disk_key, type, 8); | ||
| 639 | 651 | ||
| 640 | static inline void btrfs_disk_key_to_cpu(struct btrfs_key *cpu, | 652 | static inline void btrfs_disk_key_to_cpu(struct btrfs_key *cpu, |
| 641 | struct btrfs_disk_key *disk) | 653 | struct btrfs_disk_key *disk) |
| 642 | { | 654 | { |
| 643 | cpu->offset = le64_to_cpu(disk->offset); | 655 | cpu->offset = le64_to_cpu(disk->offset); |
| 644 | cpu->flags = le32_to_cpu(disk->flags); | 656 | cpu->type = disk->type; |
| 645 | cpu->objectid = le64_to_cpu(disk->objectid); | 657 | cpu->objectid = le64_to_cpu(disk->objectid); |
| 646 | } | 658 | } |
| 647 | 659 | ||
| @@ -649,400 +661,167 @@ static inline void btrfs_cpu_key_to_disk(struct btrfs_disk_key *disk, | |||
| 649 | struct btrfs_key *cpu) | 661 | struct btrfs_key *cpu) |
| 650 | { | 662 | { |
| 651 | disk->offset = cpu_to_le64(cpu->offset); | 663 | disk->offset = cpu_to_le64(cpu->offset); |
| 652 | disk->flags = cpu_to_le32(cpu->flags); | 664 | disk->type = cpu->type; |
| 653 | disk->objectid = cpu_to_le64(cpu->objectid); | 665 | disk->objectid = cpu_to_le64(cpu->objectid); |
| 654 | } | 666 | } |
| 655 | 667 | ||
| 656 | static inline u64 btrfs_disk_key_objectid(struct btrfs_disk_key *disk) | 668 | static inline void btrfs_node_key_to_cpu(struct extent_buffer *eb, |
| 657 | { | 669 | struct btrfs_key *key, int nr) |
| 658 | return le64_to_cpu(disk->objectid); | ||
| 659 | } | ||
| 660 | |||
| 661 | static inline void btrfs_set_disk_key_objectid(struct btrfs_disk_key *disk, | ||
| 662 | u64 val) | ||
| 663 | { | ||
| 664 | disk->objectid = cpu_to_le64(val); | ||
| 665 | } | ||
| 666 | |||
| 667 | static inline u64 btrfs_disk_key_offset(struct btrfs_disk_key *disk) | ||
| 668 | { | ||
| 669 | return le64_to_cpu(disk->offset); | ||
| 670 | } | ||
| 671 | |||
| 672 | static inline void btrfs_set_disk_key_offset(struct btrfs_disk_key *disk, | ||
| 673 | u64 val) | ||
| 674 | { | ||
| 675 | disk->offset = cpu_to_le64(val); | ||
| 676 | } | ||
| 677 | |||
| 678 | static inline u32 btrfs_disk_key_flags(struct btrfs_disk_key *disk) | ||
| 679 | { | ||
| 680 | return le32_to_cpu(disk->flags); | ||
| 681 | } | ||
| 682 | |||
| 683 | static inline void btrfs_set_disk_key_flags(struct btrfs_disk_key *disk, | ||
| 684 | u32 val) | ||
| 685 | { | ||
| 686 | disk->flags = cpu_to_le32(val); | ||
| 687 | } | ||
| 688 | |||
| 689 | static inline u32 btrfs_disk_key_type(struct btrfs_disk_key *key) | ||
| 690 | { | ||
| 691 | return le32_to_cpu(key->flags) >> BTRFS_KEY_TYPE_SHIFT; | ||
| 692 | } | ||
| 693 | |||
| 694 | static inline void btrfs_set_disk_key_type(struct btrfs_disk_key *key, | ||
| 695 | u32 val) | ||
| 696 | { | ||
| 697 | u32 flags = btrfs_disk_key_flags(key); | ||
| 698 | BUG_ON(val >= BTRFS_KEY_TYPE_MAX); | ||
| 699 | val = val << BTRFS_KEY_TYPE_SHIFT; | ||
| 700 | flags = (flags & ~BTRFS_KEY_TYPE_MASK) | val; | ||
| 701 | btrfs_set_disk_key_flags(key, flags); | ||
| 702 | } | ||
| 703 | |||
| 704 | static inline u32 btrfs_key_type(struct btrfs_key *key) | ||
| 705 | { | ||
| 706 | return key->flags >> BTRFS_KEY_TYPE_SHIFT; | ||
| 707 | } | ||
| 708 | |||
| 709 | static inline void btrfs_set_key_type(struct btrfs_key *key, u32 val) | ||
| 710 | { | ||
| 711 | BUG_ON(val >= BTRFS_KEY_TYPE_MAX); | ||
| 712 | val = val << BTRFS_KEY_TYPE_SHIFT; | ||
| 713 | key->flags = (key->flags & ~(BTRFS_KEY_TYPE_MASK)) | val; | ||
| 714 | } | ||
| 715 | |||
| 716 | static inline u64 btrfs_header_blocknr(struct btrfs_header *h) | ||
| 717 | { | ||
| 718 | return le64_to_cpu(h->blocknr); | ||
| 719 | } | ||
| 720 | |||
| 721 | static inline void btrfs_set_header_blocknr(struct btrfs_header *h, u64 blocknr) | ||
| 722 | { | ||
| 723 | h->blocknr = cpu_to_le64(blocknr); | ||
| 724 | } | ||
| 725 | |||
| 726 | static inline u64 btrfs_header_generation(struct btrfs_header *h) | ||
| 727 | { | 670 | { |
| 728 | return le64_to_cpu(h->generation); | 671 | struct btrfs_disk_key disk_key; |
| 672 | btrfs_node_key(eb, &disk_key, nr); | ||
| 673 | btrfs_disk_key_to_cpu(key, &disk_key); | ||
| 729 | } | 674 | } |
| 730 | 675 | ||
| 731 | static inline void btrfs_set_header_generation(struct btrfs_header *h, | 676 | static inline void btrfs_item_key_to_cpu(struct extent_buffer *eb, |
| 732 | u64 val) | 677 | struct btrfs_key *key, int nr) |
| 733 | { | 678 | { |
| 734 | h->generation = cpu_to_le64(val); | 679 | struct btrfs_disk_key disk_key; |
| 680 | btrfs_item_key(eb, &disk_key, nr); | ||
| 681 | btrfs_disk_key_to_cpu(key, &disk_key); | ||
| 735 | } | 682 | } |
| 736 | 683 | ||
| 737 | static inline u64 btrfs_header_owner(struct btrfs_header *h) | 684 | static inline void btrfs_dir_item_key_to_cpu(struct extent_buffer *eb, |
| 685 | struct btrfs_dir_item *item, | ||
| 686 | struct btrfs_key *key) | ||
| 738 | { | 687 | { |
| 739 | return le64_to_cpu(h->owner); | 688 | struct btrfs_disk_key disk_key; |
| 689 | btrfs_dir_item_key(eb, item, &disk_key); | ||
| 690 | btrfs_disk_key_to_cpu(key, &disk_key); | ||
| 740 | } | 691 | } |
| 741 | 692 | ||
| 742 | static inline void btrfs_set_header_owner(struct btrfs_header *h, | ||
| 743 | u64 val) | ||
| 744 | { | ||
| 745 | h->owner = cpu_to_le64(val); | ||
| 746 | } | ||
| 747 | |||
| 748 | static inline u16 btrfs_header_nritems(struct btrfs_header *h) | ||
| 749 | { | ||
| 750 | return le16_to_cpu(h->nritems); | ||
| 751 | } | ||
| 752 | |||
| 753 | static inline void btrfs_set_header_nritems(struct btrfs_header *h, u16 val) | ||
| 754 | { | ||
| 755 | h->nritems = cpu_to_le16(val); | ||
| 756 | } | ||
| 757 | |||
| 758 | static inline u16 btrfs_header_flags(struct btrfs_header *h) | ||
| 759 | { | ||
| 760 | return le16_to_cpu(h->flags); | ||
| 761 | } | ||
| 762 | |||
| 763 | static inline void btrfs_set_header_flags(struct btrfs_header *h, u16 val) | ||
| 764 | { | ||
| 765 | h->flags = cpu_to_le16(val); | ||
| 766 | } | ||
| 767 | |||
| 768 | static inline int btrfs_header_level(struct btrfs_header *h) | ||
| 769 | { | ||
| 770 | return h->level; | ||
| 771 | } | ||
| 772 | |||
| 773 | static inline void btrfs_set_header_level(struct btrfs_header *h, int level) | ||
| 774 | { | ||
| 775 | BUG_ON(level > BTRFS_MAX_LEVEL); | ||
| 776 | h->level = level; | ||
| 777 | } | ||
| 778 | |||
| 779 | static inline int btrfs_is_leaf(struct btrfs_node *n) | ||
| 780 | { | ||
| 781 | return (btrfs_header_level(&n->header) == 0); | ||
| 782 | } | ||
| 783 | |||
| 784 | static inline u64 btrfs_root_blocknr(struct btrfs_root_item *item) | ||
| 785 | { | ||
| 786 | return le64_to_cpu(item->blocknr); | ||
| 787 | } | ||
| 788 | |||
| 789 | static inline void btrfs_set_root_blocknr(struct btrfs_root_item *item, u64 val) | ||
| 790 | { | ||
| 791 | item->blocknr = cpu_to_le64(val); | ||
| 792 | } | ||
| 793 | |||
| 794 | static inline u64 btrfs_root_dirid(struct btrfs_root_item *item) | ||
| 795 | { | ||
| 796 | return le64_to_cpu(item->root_dirid); | ||
| 797 | } | ||
| 798 | |||
| 799 | static inline void btrfs_set_root_dirid(struct btrfs_root_item *item, u64 val) | ||
| 800 | { | ||
| 801 | item->root_dirid = cpu_to_le64(val); | ||
| 802 | } | ||
| 803 | |||
| 804 | static inline u32 btrfs_root_refs(struct btrfs_root_item *item) | ||
| 805 | { | ||
| 806 | return le32_to_cpu(item->refs); | ||
| 807 | } | ||
| 808 | |||
| 809 | static inline void btrfs_set_root_refs(struct btrfs_root_item *item, u32 val) | ||
| 810 | { | ||
| 811 | item->refs = cpu_to_le32(val); | ||
| 812 | } | ||
| 813 | |||
| 814 | static inline u32 btrfs_root_flags(struct btrfs_root_item *item) | ||
| 815 | { | ||
| 816 | return le32_to_cpu(item->flags); | ||
| 817 | } | ||
| 818 | |||
| 819 | static inline void btrfs_set_root_flags(struct btrfs_root_item *item, u32 val) | ||
| 820 | { | ||
| 821 | item->flags = cpu_to_le32(val); | ||
| 822 | } | ||
| 823 | |||
| 824 | static inline void btrfs_set_root_blocks_used(struct btrfs_root_item *item, | ||
| 825 | u64 val) | ||
| 826 | { | ||
| 827 | item->blocks_used = cpu_to_le64(val); | ||
| 828 | } | ||
| 829 | |||
| 830 | static inline u64 btrfs_root_blocks_used(struct btrfs_root_item *item) | ||
| 831 | { | ||
| 832 | return le64_to_cpu(item->blocks_used); | ||
| 833 | } | ||
| 834 | |||
| 835 | static inline void btrfs_set_root_block_limit(struct btrfs_root_item *item, | ||
| 836 | u64 val) | ||
| 837 | { | ||
| 838 | item->block_limit = cpu_to_le64(val); | ||
| 839 | } | ||
| 840 | |||
| 841 | static inline u64 btrfs_root_block_limit(struct btrfs_root_item *item) | ||
| 842 | { | ||
| 843 | return le64_to_cpu(item->block_limit); | ||
| 844 | } | ||
| 845 | 693 | ||
| 846 | static inline u64 btrfs_super_blocknr(struct btrfs_super_block *s) | 694 | static inline u8 btrfs_key_type(struct btrfs_key *key) |
| 847 | { | 695 | { |
| 848 | return le64_to_cpu(s->blocknr); | 696 | return key->type; |
| 849 | } | 697 | } |
| 850 | 698 | ||
| 851 | static inline void btrfs_set_super_blocknr(struct btrfs_super_block *s, u64 val) | 699 | static inline void btrfs_set_key_type(struct btrfs_key *key, u8 val) |
| 852 | { | 700 | { |
| 853 | s->blocknr = cpu_to_le64(val); | 701 | key->type = val; |
| 854 | } | 702 | } |
| 855 | 703 | ||
| 856 | static inline u64 btrfs_super_generation(struct btrfs_super_block *s) | 704 | /* struct btrfs_header */ |
| 857 | { | 705 | BTRFS_SETGET_HEADER_FUNCS(header_blocknr, struct btrfs_header, blocknr, 64); |
| 858 | return le64_to_cpu(s->generation); | 706 | BTRFS_SETGET_HEADER_FUNCS(header_generation, struct btrfs_header, |
| 859 | } | 707 | generation, 64); |
| 708 | BTRFS_SETGET_HEADER_FUNCS(header_owner, struct btrfs_header, owner, 64); | ||
| 709 | BTRFS_SETGET_HEADER_FUNCS(header_nritems, struct btrfs_header, nritems, 32); | ||
| 710 | BTRFS_SETGET_HEADER_FUNCS(header_flags, struct btrfs_header, flags, 16); | ||
| 711 | BTRFS_SETGET_HEADER_FUNCS(header_level, struct btrfs_header, level, 8); | ||
| 860 | 712 | ||
| 861 | static inline void btrfs_set_super_generation(struct btrfs_super_block *s, | 713 | static inline u8 *btrfs_header_fsid(struct extent_buffer *eb) |
| 862 | u64 val) | ||
| 863 | { | 714 | { |
| 864 | s->generation = cpu_to_le64(val); | 715 | unsigned long ptr = offsetof(struct btrfs_header, fsid); |
| 716 | return (u8 *)ptr; | ||
| 865 | } | 717 | } |
| 866 | 718 | ||
| 867 | static inline u64 btrfs_super_root(struct btrfs_super_block *s) | 719 | static inline u8 *btrfs_super_fsid(struct extent_buffer *eb) |
| 868 | { | 720 | { |
| 869 | return le64_to_cpu(s->root); | 721 | unsigned long ptr = offsetof(struct btrfs_super_block, fsid); |
| 722 | return (u8 *)ptr; | ||
| 870 | } | 723 | } |
| 871 | 724 | ||
| 872 | static inline void btrfs_set_super_root(struct btrfs_super_block *s, u64 val) | 725 | static inline u8 *btrfs_header_csum(struct extent_buffer *eb) |
| 873 | { | 726 | { |
| 874 | s->root = cpu_to_le64(val); | 727 | unsigned long ptr = offsetof(struct btrfs_header, csum); |
| 728 | return (u8 *)ptr; | ||
| 875 | } | 729 | } |
| 876 | 730 | ||
| 877 | static inline u64 btrfs_super_total_blocks(struct btrfs_super_block *s) | 731 | static inline struct btrfs_node *btrfs_buffer_node(struct extent_buffer *eb) |
| 878 | { | 732 | { |
| 879 | return le64_to_cpu(s->total_blocks); | 733 | return NULL; |
| 880 | } | 734 | } |
| 881 | 735 | ||
| 882 | static inline void btrfs_set_super_total_blocks(struct btrfs_super_block *s, | 736 | static inline struct btrfs_leaf *btrfs_buffer_leaf(struct extent_buffer *eb) |
| 883 | u64 val) | ||
| 884 | { | 737 | { |
| 885 | s->total_blocks = cpu_to_le64(val); | 738 | return NULL; |
| 886 | } | 739 | } |
| 887 | 740 | ||
| 888 | static inline u64 btrfs_super_blocks_used(struct btrfs_super_block *s) | 741 | static inline struct btrfs_header *btrfs_buffer_header(struct extent_buffer *eb) |
| 889 | { | 742 | { |
| 890 | return le64_to_cpu(s->blocks_used); | 743 | return NULL; |
| 891 | } | 744 | } |
| 892 | 745 | ||
| 893 | static inline void btrfs_set_super_blocks_used(struct btrfs_super_block *s, | 746 | static inline int btrfs_is_leaf(struct extent_buffer *eb) |
| 894 | u64 val) | ||
| 895 | { | 747 | { |
| 896 | s->blocks_used = cpu_to_le64(val); | 748 | return (btrfs_header_level(eb) == 0); |
| 897 | } | 749 | } |
| 898 | 750 | ||
| 899 | static inline u32 btrfs_super_blocksize(struct btrfs_super_block *s) | 751 | /* struct btrfs_root_item */ |
| 900 | { | 752 | BTRFS_SETGET_FUNCS(disk_root_refs, struct btrfs_root_item, refs, 32); |
| 901 | return le32_to_cpu(s->blocksize); | 753 | BTRFS_SETGET_FUNCS(disk_root_blocknr, struct btrfs_root_item, blocknr, 64); |
| 902 | } | ||
| 903 | 754 | ||
| 904 | static inline void btrfs_set_super_blocksize(struct btrfs_super_block *s, | 755 | BTRFS_SETGET_STACK_FUNCS(root_blocknr, struct btrfs_root_item, blocknr, 64); |
| 905 | u32 val) | 756 | BTRFS_SETGET_STACK_FUNCS(root_dirid, struct btrfs_root_item, root_dirid, 64); |
| 906 | { | 757 | BTRFS_SETGET_STACK_FUNCS(root_refs, struct btrfs_root_item, refs, 32); |
| 907 | s->blocksize = cpu_to_le32(val); | 758 | BTRFS_SETGET_STACK_FUNCS(root_flags, struct btrfs_root_item, flags, 32); |
| 908 | } | 759 | BTRFS_SETGET_STACK_FUNCS(root_used, struct btrfs_root_item, blocks_used, 64); |
| 760 | BTRFS_SETGET_STACK_FUNCS(root_limit, struct btrfs_root_item, block_limit, 64); | ||
| 909 | 761 | ||
| 910 | static inline u64 btrfs_super_root_dir(struct btrfs_super_block *s) | 762 | /* struct btrfs_super_block */ |
| 911 | { | 763 | BTRFS_SETGET_STACK_FUNCS(super_blocknr, struct btrfs_super_block, blocknr, 64); |
| 912 | return le64_to_cpu(s->root_dir_objectid); | 764 | BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block, |
| 913 | } | 765 | generation, 64); |
| 766 | BTRFS_SETGET_STACK_FUNCS(super_root, struct btrfs_super_block, root, 64); | ||
| 767 | BTRFS_SETGET_STACK_FUNCS(super_total_blocks, struct btrfs_super_block, | ||
| 768 | total_blocks, 64); | ||
| 769 | BTRFS_SETGET_STACK_FUNCS(super_blocks_used, struct btrfs_super_block, | ||
| 770 | blocks_used, 64); | ||
| 771 | BTRFS_SETGET_STACK_FUNCS(super_sectorsize, struct btrfs_super_block, | ||
| 772 | sectorsize, 32); | ||
| 773 | BTRFS_SETGET_STACK_FUNCS(super_nodesize, struct btrfs_super_block, | ||
| 774 | nodesize, 32); | ||
| 775 | BTRFS_SETGET_STACK_FUNCS(super_leafsize, struct btrfs_super_block, | ||
| 776 | leafsize, 32); | ||
| 777 | BTRFS_SETGET_STACK_FUNCS(super_root_dir, struct btrfs_super_block, | ||
| 778 | root_dir_objectid, 64); | ||
| 914 | 779 | ||
| 915 | static inline void btrfs_set_super_root_dir(struct btrfs_super_block *s, u64 | 780 | static inline unsigned long btrfs_leaf_data(struct extent_buffer *l) |
| 916 | val) | ||
| 917 | { | 781 | { |
| 918 | s->root_dir_objectid = cpu_to_le64(val); | 782 | return offsetof(struct btrfs_leaf, items); |
| 919 | } | 783 | } |
| 920 | 784 | ||
| 921 | static inline u8 *btrfs_leaf_data(struct btrfs_leaf *l) | 785 | /* struct btrfs_file_extent_item */ |
| 922 | { | 786 | BTRFS_SETGET_FUNCS(file_extent_type, struct btrfs_file_extent_item, type, 8); |
| 923 | return (u8 *)l->items; | ||
| 924 | } | ||
| 925 | 787 | ||
| 926 | static inline int btrfs_file_extent_type(struct btrfs_file_extent_item *e) | 788 | static inline unsigned long btrfs_file_extent_inline_start(struct |
| 927 | { | ||
| 928 | return e->type; | ||
| 929 | } | ||
| 930 | static inline void btrfs_set_file_extent_type(struct btrfs_file_extent_item *e, | ||
| 931 | u8 val) | ||
| 932 | { | ||
| 933 | e->type = val; | ||
| 934 | } | ||
| 935 | |||
| 936 | static inline char *btrfs_file_extent_inline_start(struct | ||
| 937 | btrfs_file_extent_item *e) | 789 | btrfs_file_extent_item *e) |
| 938 | { | 790 | { |
| 939 | return (char *)(&e->disk_blocknr); | 791 | unsigned long offset = (unsigned long)e; |
| 792 | offset += offsetof(struct btrfs_file_extent_item, disk_blocknr); | ||
| 793 | return offset; | ||
| 940 | } | 794 | } |
| 941 | 795 | ||
| 942 | static inline u32 btrfs_file_extent_calc_inline_size(u32 datasize) | 796 | static inline u32 btrfs_file_extent_calc_inline_size(u32 datasize) |
| 943 | { | 797 | { |
| 944 | return (unsigned long)(&((struct | 798 | return offsetof(struct btrfs_file_extent_item, disk_blocknr) + datasize; |
| 945 | btrfs_file_extent_item *)NULL)->disk_blocknr) + datasize; | ||
| 946 | } | ||
| 947 | |||
| 948 | static inline u32 btrfs_file_extent_inline_len(struct btrfs_item *e) | ||
| 949 | { | ||
| 950 | struct btrfs_file_extent_item *fe = NULL; | ||
| 951 | return btrfs_item_size(e) - (unsigned long)(&fe->disk_blocknr); | ||
| 952 | } | ||
| 953 | |||
| 954 | static inline u64 btrfs_file_extent_disk_blocknr(struct btrfs_file_extent_item | ||
| 955 | *e) | ||
| 956 | { | ||
| 957 | return le64_to_cpu(e->disk_blocknr); | ||
| 958 | } | 799 | } |
| 959 | 800 | ||
| 960 | static inline void btrfs_set_file_extent_disk_blocknr(struct | 801 | static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb, |
| 961 | btrfs_file_extent_item | 802 | struct btrfs_item *e) |
| 962 | *e, u64 val) | ||
| 963 | { | 803 | { |
| 964 | e->disk_blocknr = cpu_to_le64(val); | 804 | unsigned long offset; |
| 805 | offset = offsetof(struct btrfs_file_extent_item, disk_blocknr); | ||
| 806 | return btrfs_item_size(eb, e) - offset; | ||
| 965 | } | 807 | } |
| 966 | 808 | ||
| 967 | static inline u64 btrfs_file_extent_generation(struct btrfs_file_extent_item *e) | 809 | BTRFS_SETGET_FUNCS(file_extent_disk_blocknr, struct btrfs_file_extent_item, |
| 968 | { | 810 | disk_blocknr, 64); |
| 969 | return le64_to_cpu(e->generation); | 811 | BTRFS_SETGET_FUNCS(file_extent_generation, struct btrfs_file_extent_item, |
| 970 | } | 812 | generation, 64); |
| 971 | 813 | BTRFS_SETGET_FUNCS(file_extent_disk_num_blocks, struct btrfs_file_extent_item, | |
| 972 | static inline void btrfs_set_file_extent_generation(struct | 814 | disk_num_blocks, 64); |
| 973 | btrfs_file_extent_item *e, | 815 | BTRFS_SETGET_FUNCS(file_extent_offset, struct btrfs_file_extent_item, |
| 974 | u64 val) | 816 | offset, 64); |
| 975 | { | 817 | BTRFS_SETGET_FUNCS(file_extent_num_blocks, struct btrfs_file_extent_item, |
| 976 | e->generation = cpu_to_le64(val); | 818 | num_blocks, 64); |
| 977 | } | ||
| 978 | |||
| 979 | static inline u64 btrfs_file_extent_disk_num_blocks(struct | ||
| 980 | btrfs_file_extent_item *e) | ||
| 981 | { | ||
| 982 | return le64_to_cpu(e->disk_num_blocks); | ||
| 983 | } | ||
| 984 | |||
| 985 | static inline void btrfs_set_file_extent_disk_num_blocks(struct | ||
| 986 | btrfs_file_extent_item | ||
| 987 | *e, u64 val) | ||
| 988 | { | ||
| 989 | e->disk_num_blocks = cpu_to_le64(val); | ||
| 990 | } | ||
| 991 | |||
| 992 | static inline u64 btrfs_file_extent_offset(struct btrfs_file_extent_item *e) | ||
| 993 | { | ||
| 994 | return le64_to_cpu(e->offset); | ||
| 995 | } | ||
| 996 | |||
| 997 | static inline void btrfs_set_file_extent_offset(struct btrfs_file_extent_item | ||
| 998 | *e, u64 val) | ||
| 999 | { | ||
| 1000 | e->offset = cpu_to_le64(val); | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | static inline u64 btrfs_file_extent_num_blocks(struct btrfs_file_extent_item | ||
| 1004 | *e) | ||
| 1005 | { | ||
| 1006 | return le64_to_cpu(e->num_blocks); | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | static inline void btrfs_set_file_extent_num_blocks(struct | ||
| 1010 | btrfs_file_extent_item *e, | ||
| 1011 | u64 val) | ||
| 1012 | { | ||
| 1013 | e->num_blocks = cpu_to_le64(val); | ||
| 1014 | } | ||
| 1015 | 819 | ||
| 1016 | static inline struct btrfs_root *btrfs_sb(struct super_block *sb) | 820 | static inline struct btrfs_root *btrfs_sb(struct super_block *sb) |
| 1017 | { | 821 | { |
| 1018 | return sb->s_fs_info; | 822 | return sb->s_fs_info; |
| 1019 | } | 823 | } |
| 1020 | 824 | ||
| 1021 | static inline void btrfs_check_bounds(void *vptr, size_t len, | ||
| 1022 | void *vcontainer, size_t container_len) | ||
| 1023 | { | ||
| 1024 | char *ptr = vptr; | ||
| 1025 | char *container = vcontainer; | ||
| 1026 | WARN_ON(ptr < container); | ||
| 1027 | WARN_ON(ptr + len > container + container_len); | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | static inline void btrfs_memcpy(struct btrfs_root *root, | ||
| 1031 | void *dst_block, | ||
| 1032 | void *dst, const void *src, size_t nr) | ||
| 1033 | { | ||
| 1034 | btrfs_check_bounds(dst, nr, dst_block, root->fs_info->sb->s_blocksize); | ||
| 1035 | memcpy(dst, src, nr); | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | static inline void btrfs_memmove(struct btrfs_root *root, | ||
| 1039 | void *dst_block, | ||
| 1040 | void *dst, void *src, size_t nr) | ||
| 1041 | { | ||
| 1042 | btrfs_check_bounds(dst, nr, dst_block, root->fs_info->sb->s_blocksize); | ||
| 1043 | memmove(dst, src, nr); | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | static inline int btrfs_set_root_name(struct btrfs_root *root, | 825 | static inline int btrfs_set_root_name(struct btrfs_root *root, |
| 1047 | const char *name, int len) | 826 | const char *name, int len) |
| 1048 | { | 827 | { |
| @@ -1063,7 +842,11 @@ static inline int btrfs_set_root_name(struct btrfs_root *root, | |||
| 1063 | /* helper function to cast into the data area of the leaf. */ | 842 | /* helper function to cast into the data area of the leaf. */ |
| 1064 | #define btrfs_item_ptr(leaf, slot, type) \ | 843 | #define btrfs_item_ptr(leaf, slot, type) \ |
| 1065 | ((type *)(btrfs_leaf_data(leaf) + \ | 844 | ((type *)(btrfs_leaf_data(leaf) + \ |
| 1066 | btrfs_item_offset((leaf)->items + (slot)))) | 845 | btrfs_item_offset_nr(leaf, slot))) |
| 846 | |||
| 847 | #define btrfs_item_ptr_offset(leaf, slot) \ | ||
| 848 | ((unsigned long)(btrfs_leaf_data(leaf) + \ | ||
| 849 | btrfs_item_offset_nr(leaf, slot))) | ||
| 1067 | 850 | ||
| 1068 | /* mount option defines and helpers */ | 851 | /* mount option defines and helpers */ |
| 1069 | #define BTRFS_MOUNT_SUBVOL 0x000001 | 852 | #define BTRFS_MOUNT_SUBVOL 0x000001 |
| @@ -1084,7 +867,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
| 1084 | int data, int owner); | 867 | int data, int owner); |
| 1085 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, | 868 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, |
| 1086 | struct btrfs_root *root); | 869 | struct btrfs_root *root); |
| 1087 | struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 870 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
| 1088 | struct btrfs_root *root, u64 hint, | 871 | struct btrfs_root *root, u64 hint, |
| 1089 | u64 empty_size); | 872 | u64 empty_size); |
| 1090 | int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | 873 | int btrfs_alloc_extent(struct btrfs_trans_handle *trans, |
| @@ -1092,7 +875,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
| 1092 | u64 num_blocks, u64 empty_size, u64 search_start, | 875 | u64 num_blocks, u64 empty_size, u64 search_start, |
| 1093 | u64 search_end, struct btrfs_key *ins, int data); | 876 | u64 search_end, struct btrfs_key *ins, int data); |
| 1094 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 877 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 1095 | struct buffer_head *buf); | 878 | struct extent_buffer *buf); |
| 1096 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 879 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
| 1097 | *root, u64 blocknr, u64 num_blocks, int pin); | 880 | *root, u64 blocknr, u64 num_blocks, int pin); |
| 1098 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | 881 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, |
| @@ -1106,10 +889,10 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | |||
| 1106 | int btrfs_free_block_groups(struct btrfs_fs_info *info); | 889 | int btrfs_free_block_groups(struct btrfs_fs_info *info); |
| 1107 | int btrfs_read_block_groups(struct btrfs_root *root); | 890 | int btrfs_read_block_groups(struct btrfs_root *root); |
| 1108 | /* ctree.c */ | 891 | /* ctree.c */ |
| 1109 | int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | 892 | int btrfs_cow_block(struct btrfs_trans_handle *trans, |
| 1110 | *root, struct buffer_head *buf, struct buffer_head | 893 | struct btrfs_root *root, struct extent_buffer *buf, |
| 1111 | *parent, int parent_slot, struct buffer_head | 894 | struct extent_buffer *parent, int parent_slot, |
| 1112 | **cow_ret); | 895 | struct extent_buffer **cow_ret); |
| 1113 | int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root | 896 | int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root |
| 1114 | *root, struct btrfs_path *path, u32 data_size); | 897 | *root, struct btrfs_path *path, u32 data_size); |
| 1115 | int btrfs_truncate_item(struct btrfs_trans_handle *trans, | 898 | int btrfs_truncate_item(struct btrfs_trans_handle *trans, |
| @@ -1120,7 +903,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1120 | *root, struct btrfs_key *key, struct btrfs_path *p, int | 903 | *root, struct btrfs_key *key, struct btrfs_path *p, int |
| 1121 | ins_len, int cow); | 904 | ins_len, int cow); |
| 1122 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, | 905 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, |
| 1123 | struct btrfs_root *root, struct buffer_head *parent, | 906 | struct btrfs_root *root, struct extent_buffer *parent, |
| 1124 | int cache_only, u64 *last_ret); | 907 | int cache_only, u64 *last_ret); |
| 1125 | void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p); | 908 | void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p); |
| 1126 | struct btrfs_path *btrfs_alloc_path(void); | 909 | struct btrfs_path *btrfs_alloc_path(void); |
| @@ -1134,7 +917,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1134 | *root, struct btrfs_path *path, struct btrfs_key | 917 | *root, struct btrfs_path *path, struct btrfs_key |
| 1135 | *cpu_key, u32 data_size); | 918 | *cpu_key, u32 data_size); |
| 1136 | int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); | 919 | int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); |
| 1137 | int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf); | 920 | int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf); |
| 1138 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | 921 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root |
| 1139 | *root); | 922 | *root); |
| 1140 | /* root-item.c */ | 923 | /* root-item.c */ |
| @@ -1179,9 +962,9 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | |||
| 1179 | int btrfs_find_highest_inode(struct btrfs_root *fs_root, u64 *objectid); | 962 | int btrfs_find_highest_inode(struct btrfs_root *fs_root, u64 *objectid); |
| 1180 | 963 | ||
| 1181 | /* inode-item.c */ | 964 | /* inode-item.c */ |
| 1182 | int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root | 965 | int btrfs_insert_empty_inode(struct btrfs_trans_handle *trans, |
| 1183 | *root, u64 objectid, struct btrfs_inode_item | 966 | struct btrfs_root *root, |
| 1184 | *inode_item); | 967 | struct btrfs_path *path, u64 objectid); |
| 1185 | int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root | 968 | int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root |
| 1186 | *root, struct btrfs_path *path, | 969 | *root, struct btrfs_path *path, |
| 1187 | struct btrfs_key *location, int mod); | 970 | struct btrfs_key *location, int mod); |
| @@ -1224,8 +1007,6 @@ struct inode *btrfs_iget_locked(struct super_block *s, u64 objectid, | |||
| 1224 | struct btrfs_root *root); | 1007 | struct btrfs_root *root); |
| 1225 | int btrfs_commit_write(struct file *file, struct page *page, | 1008 | int btrfs_commit_write(struct file *file, struct page *page, |
| 1226 | unsigned from, unsigned to); | 1009 | unsigned from, unsigned to); |
| 1227 | int btrfs_get_block(struct inode *inode, sector_t iblock, | ||
| 1228 | struct buffer_head *result, int create); | ||
| 1229 | struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, | 1010 | struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, |
| 1230 | size_t page_offset, u64 start, u64 end, | 1011 | size_t page_offset, u64 start, u64 end, |
| 1231 | int create); | 1012 | int create); |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 49db5fa7ced3..6f19de41b878 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
| @@ -33,7 +33,7 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle | |||
| 33 | int ret; | 33 | int ret; |
| 34 | char *ptr; | 34 | char *ptr; |
| 35 | struct btrfs_item *item; | 35 | struct btrfs_item *item; |
| 36 | struct btrfs_leaf *leaf; | 36 | struct extent_buffer *leaf; |
| 37 | 37 | ||
| 38 | ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); | 38 | ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); |
| 39 | if (ret == -EEXIST) { | 39 | if (ret == -EEXIST) { |
| @@ -49,11 +49,11 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle | |||
| 49 | if (ret < 0) | 49 | if (ret < 0) |
| 50 | return ERR_PTR(ret); | 50 | return ERR_PTR(ret); |
| 51 | WARN_ON(ret > 0); | 51 | WARN_ON(ret > 0); |
| 52 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 52 | leaf = path->nodes[0]; |
| 53 | item = leaf->items + path->slots[0]; | 53 | item = btrfs_item_nr(leaf, path->slots[0]); |
| 54 | ptr = btrfs_item_ptr(leaf, path->slots[0], char); | 54 | ptr = btrfs_item_ptr(leaf, path->slots[0], char); |
| 55 | BUG_ON(data_size > btrfs_item_size(item)); | 55 | BUG_ON(data_size > btrfs_item_size(leaf, item)); |
| 56 | ptr += btrfs_item_size(item) - data_size; | 56 | ptr += btrfs_item_size(leaf, item) - data_size; |
| 57 | return (struct btrfs_dir_item *)ptr; | 57 | return (struct btrfs_dir_item *)ptr; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| @@ -65,12 +65,13 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 65 | int ret2 = 0; | 65 | int ret2 = 0; |
| 66 | struct btrfs_path *path; | 66 | struct btrfs_path *path; |
| 67 | struct btrfs_dir_item *dir_item; | 67 | struct btrfs_dir_item *dir_item; |
| 68 | char *name_ptr; | 68 | struct extent_buffer *leaf; |
| 69 | unsigned long name_ptr; | ||
| 69 | struct btrfs_key key; | 70 | struct btrfs_key key; |
| 71 | struct btrfs_disk_key disk_key; | ||
| 70 | u32 data_size; | 72 | u32 data_size; |
| 71 | 73 | ||
| 72 | key.objectid = dir; | 74 | key.objectid = dir; |
| 73 | key.flags = 0; | ||
| 74 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); | 75 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); |
| 75 | ret = btrfs_name_hash(name, name_len, &key.offset); | 76 | ret = btrfs_name_hash(name, name_len, &key.offset); |
| 76 | BUG_ON(ret); | 77 | BUG_ON(ret); |
| @@ -85,14 +86,16 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 85 | goto out; | 86 | goto out; |
| 86 | } | 87 | } |
| 87 | 88 | ||
| 88 | btrfs_cpu_key_to_disk(&dir_item->location, location); | 89 | leaf = path->nodes[0]; |
| 89 | btrfs_set_dir_type(dir_item, type); | 90 | btrfs_cpu_key_to_disk(&disk_key, location); |
| 90 | btrfs_set_dir_flags(dir_item, 0); | 91 | btrfs_set_dir_item_key(leaf, dir_item, &disk_key); |
| 91 | btrfs_set_dir_name_len(dir_item, name_len); | 92 | btrfs_set_dir_type(leaf, dir_item, type); |
| 92 | name_ptr = (char *)(dir_item + 1); | 93 | btrfs_set_dir_flags(leaf, dir_item, 0); |
| 94 | btrfs_set_dir_name_len(leaf, dir_item, name_len); | ||
| 95 | name_ptr = (unsigned long)(dir_item + 1); | ||
| 93 | 96 | ||
| 94 | btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); | 97 | write_extent_buffer(leaf, name, name_ptr, name_len); |
| 95 | btrfs_mark_buffer_dirty(path->nodes[0]); | 98 | btrfs_mark_buffer_dirty(leaf); |
| 96 | 99 | ||
| 97 | second_insert: | 100 | second_insert: |
| 98 | /* FIXME, use some real flag for selecting the extra index */ | 101 | /* FIXME, use some real flag for selecting the extra index */ |
| @@ -110,13 +113,15 @@ second_insert: | |||
| 110 | ret2 = PTR_ERR(dir_item); | 113 | ret2 = PTR_ERR(dir_item); |
| 111 | goto out; | 114 | goto out; |
| 112 | } | 115 | } |
| 113 | btrfs_cpu_key_to_disk(&dir_item->location, location); | 116 | leaf = path->nodes[0]; |
| 114 | btrfs_set_dir_type(dir_item, type); | 117 | btrfs_cpu_key_to_disk(&disk_key, location); |
| 115 | btrfs_set_dir_flags(dir_item, 0); | 118 | btrfs_set_dir_item_key(leaf, dir_item, &disk_key); |
| 116 | btrfs_set_dir_name_len(dir_item, name_len); | 119 | btrfs_set_dir_type(leaf, dir_item, type); |
| 117 | name_ptr = (char *)(dir_item + 1); | 120 | btrfs_set_dir_flags(leaf, dir_item, 0); |
| 118 | btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); | 121 | btrfs_set_dir_name_len(leaf, dir_item, name_len); |
| 119 | btrfs_mark_buffer_dirty(path->nodes[0]); | 122 | name_ptr = (unsigned long)(dir_item + 1); |
| 123 | write_extent_buffer(leaf, name, name_ptr, name_len); | ||
| 124 | btrfs_mark_buffer_dirty(leaf); | ||
| 120 | out: | 125 | out: |
| 121 | btrfs_free_path(path); | 126 | btrfs_free_path(path); |
| 122 | if (ret) | 127 | if (ret) |
| @@ -136,14 +141,15 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, | |||
| 136 | struct btrfs_key key; | 141 | struct btrfs_key key; |
| 137 | int ins_len = mod < 0 ? -1 : 0; | 142 | int ins_len = mod < 0 ? -1 : 0; |
| 138 | int cow = mod != 0; | 143 | int cow = mod != 0; |
| 139 | struct btrfs_disk_key *found_key; | 144 | struct btrfs_key found_key; |
| 140 | struct btrfs_leaf *leaf; | 145 | struct extent_buffer *leaf; |
| 141 | 146 | ||
| 142 | key.objectid = dir; | 147 | key.objectid = dir; |
| 143 | key.flags = 0; | ||
| 144 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); | 148 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); |
| 149 | |||
| 145 | ret = btrfs_name_hash(name, name_len, &key.offset); | 150 | ret = btrfs_name_hash(name, name_len, &key.offset); |
| 146 | BUG_ON(ret); | 151 | BUG_ON(ret); |
| 152 | |||
| 147 | ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); | 153 | ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); |
| 148 | if (ret < 0) | 154 | if (ret < 0) |
| 149 | return ERR_PTR(ret); | 155 | return ERR_PTR(ret); |
| @@ -152,12 +158,13 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, | |||
| 152 | return NULL; | 158 | return NULL; |
| 153 | path->slots[0]--; | 159 | path->slots[0]--; |
| 154 | } | 160 | } |
| 155 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
| 156 | found_key = &leaf->items[path->slots[0]].key; | ||
| 157 | 161 | ||
| 158 | if (btrfs_disk_key_objectid(found_key) != dir || | 162 | leaf = path->nodes[0]; |
| 159 | btrfs_disk_key_type(found_key) != BTRFS_DIR_ITEM_KEY || | 163 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
| 160 | btrfs_disk_key_offset(found_key) != key.offset) | 164 | |
| 165 | if (found_key.objectid != dir || | ||
| 166 | btrfs_key_type(&found_key) != BTRFS_DIR_ITEM_KEY || | ||
| 167 | found_key.offset != key.offset) | ||
| 161 | return NULL; | 168 | return NULL; |
| 162 | 169 | ||
| 163 | return btrfs_match_dir_item_name(root, path, name, name_len); | 170 | return btrfs_match_dir_item_name(root, path, name, name_len); |
| @@ -176,7 +183,6 @@ btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, | |||
| 176 | int cow = mod != 0; | 183 | int cow = mod != 0; |
| 177 | 184 | ||
| 178 | key.objectid = dir; | 185 | key.objectid = dir; |
| 179 | key.flags = 0; | ||
| 180 | btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); | 186 | btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); |
| 181 | key.offset = objectid; | 187 | key.offset = objectid; |
| 182 | 188 | ||
| @@ -193,21 +199,22 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, | |||
| 193 | const char *name, int name_len) | 199 | const char *name, int name_len) |
| 194 | { | 200 | { |
| 195 | struct btrfs_dir_item *dir_item; | 201 | struct btrfs_dir_item *dir_item; |
| 196 | char *name_ptr; | 202 | unsigned long name_ptr; |
| 197 | u32 total_len; | 203 | u32 total_len; |
| 198 | u32 cur = 0; | 204 | u32 cur = 0; |
| 199 | u32 this_len; | 205 | u32 this_len; |
| 200 | struct btrfs_leaf *leaf; | 206 | struct extent_buffer *leaf; |
| 201 | 207 | ||
| 202 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 208 | leaf = path->nodes[0]; |
| 203 | dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); | 209 | dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); |
| 204 | total_len = btrfs_item_size(leaf->items + path->slots[0]); | 210 | total_len = btrfs_item_size_nr(leaf, path->slots[0]); |
| 205 | while(cur < total_len) { | 211 | while(cur < total_len) { |
| 206 | this_len = sizeof(*dir_item) + btrfs_dir_name_len(dir_item); | 212 | this_len = sizeof(*dir_item) + |
| 207 | name_ptr = (char *)(dir_item + 1); | 213 | btrfs_dir_name_len(leaf, dir_item); |
| 214 | name_ptr = (unsigned long)(dir_item + 1); | ||
| 208 | 215 | ||
| 209 | if (btrfs_dir_name_len(dir_item) == name_len && | 216 | if (btrfs_dir_name_len(leaf, dir_item) == name_len && |
| 210 | memcmp(name_ptr, name, name_len) == 0) | 217 | memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0) |
| 211 | return dir_item; | 218 | return dir_item; |
| 212 | 219 | ||
| 213 | cur += this_len; | 220 | cur += this_len; |
| @@ -223,20 +230,23 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, | |||
| 223 | struct btrfs_dir_item *di) | 230 | struct btrfs_dir_item *di) |
| 224 | { | 231 | { |
| 225 | 232 | ||
| 226 | struct btrfs_leaf *leaf; | 233 | struct extent_buffer *leaf; |
| 227 | u32 sub_item_len; | 234 | u32 sub_item_len; |
| 228 | u32 item_len; | 235 | u32 item_len; |
| 229 | int ret = 0; | 236 | int ret = 0; |
| 230 | 237 | ||
| 231 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 238 | leaf = path->nodes[0]; |
| 232 | sub_item_len = sizeof(*di) + btrfs_dir_name_len(di); | 239 | sub_item_len = sizeof(*di) + btrfs_dir_name_len(leaf, di); |
| 233 | item_len = btrfs_item_size(leaf->items + path->slots[0]); | 240 | item_len = btrfs_item_size_nr(leaf, path->slots[0]); |
| 234 | if (sub_item_len == btrfs_item_size(leaf->items + path->slots[0])) { | 241 | if (sub_item_len == item_len) { |
| 235 | ret = btrfs_del_item(trans, root, path); | 242 | ret = btrfs_del_item(trans, root, path); |
| 236 | } else { | 243 | } else { |
| 237 | char *ptr = (char *)di; | 244 | /* MARKER */ |
| 238 | char *start = btrfs_item_ptr(leaf, path->slots[0], char); | 245 | unsigned long ptr = (unsigned long)di; |
| 239 | btrfs_memmove(root, leaf, ptr, ptr + sub_item_len, | 246 | unsigned long start; |
| 247 | |||
| 248 | start = btrfs_item_ptr_offset(leaf, path->slots[0]); | ||
| 249 | memmove_extent_buffer(leaf, ptr, ptr + sub_item_len, | ||
| 240 | item_len - (ptr + sub_item_len - start)); | 250 | item_len - (ptr + sub_item_len - start)); |
| 241 | ret = btrfs_truncate_item(trans, root, path, | 251 | ret = btrfs_truncate_item(trans, root, path, |
| 242 | item_len - sub_item_len); | 252 | item_len - sub_item_len); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index ef6d76f2ec20..0c1f90cbedb0 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -23,138 +23,132 @@ | |||
| 23 | #include <linux/swap.h> | 23 | #include <linux/swap.h> |
| 24 | #include <linux/radix-tree.h> | 24 | #include <linux/radix-tree.h> |
| 25 | #include <linux/writeback.h> | 25 | #include <linux/writeback.h> |
| 26 | #include <linux/buffer_head.h> // for block_sync_page | ||
| 26 | #include "ctree.h" | 27 | #include "ctree.h" |
| 27 | #include "disk-io.h" | 28 | #include "disk-io.h" |
| 28 | #include "transaction.h" | 29 | #include "transaction.h" |
| 29 | #include "btrfs_inode.h" | 30 | #include "btrfs_inode.h" |
| 30 | 31 | ||
| 31 | u64 bh_blocknr(struct buffer_head *bh) | 32 | #if 0 |
| 33 | static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf) | ||
| 32 | { | 34 | { |
| 33 | return bh->b_blocknr; | 35 | if (extent_buffer_blocknr(buf) != btrfs_header_blocknr(buf)) { |
| 34 | } | 36 | printk(KERN_CRIT "buf blocknr(buf) is %llu, header is %llu\n", |
| 35 | 37 | (unsigned long long)extent_buffer_blocknr(buf), | |
| 36 | static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) | 38 | (unsigned long long)btrfs_header_blocknr(buf)); |
| 37 | { | ||
| 38 | struct btrfs_node *node = btrfs_buffer_node(buf); | ||
| 39 | if (bh_blocknr(buf) != btrfs_header_blocknr(&node->header)) { | ||
| 40 | printk(KERN_CRIT "bh_blocknr(buf) is %llu, header is %llu\n", | ||
| 41 | (unsigned long long)bh_blocknr(buf), | ||
| 42 | (unsigned long long)btrfs_header_blocknr(&node->header)); | ||
| 43 | return 1; | 39 | return 1; |
| 44 | } | 40 | } |
| 45 | return 0; | 41 | return 0; |
| 46 | } | 42 | } |
| 43 | #endif | ||
| 47 | 44 | ||
| 48 | struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) | 45 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, |
| 46 | u64 blocknr) | ||
| 49 | { | 47 | { |
| 50 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; | 48 | struct inode *btree_inode = root->fs_info->btree_inode; |
| 51 | int blockbits = root->fs_info->sb->s_blocksize_bits; | 49 | return find_extent_buffer(&BTRFS_I(btree_inode)->extent_tree, |
| 52 | unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); | 50 | blocknr * root->sectorsize, |
| 53 | struct page *page; | 51 | root->sectorsize, GFP_NOFS); |
| 54 | struct buffer_head *bh; | 52 | } |
| 55 | struct buffer_head *head; | ||
| 56 | struct buffer_head *ret = NULL; | ||
| 57 | |||
| 58 | |||
| 59 | page = find_lock_page(mapping, index); | ||
| 60 | if (!page) | ||
| 61 | return NULL; | ||
| 62 | |||
| 63 | if (!page_has_buffers(page)) | ||
| 64 | goto out_unlock; | ||
| 65 | 53 | ||
| 66 | head = page_buffers(page); | 54 | struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, |
| 67 | bh = head; | 55 | u64 blocknr) |
| 68 | do { | 56 | { |
| 69 | if (buffer_mapped(bh) && bh_blocknr(bh) == blocknr) { | 57 | struct inode *btree_inode = root->fs_info->btree_inode; |
| 70 | ret = bh; | 58 | return alloc_extent_buffer(&BTRFS_I(btree_inode)->extent_tree, |
| 71 | get_bh(bh); | 59 | blocknr * root->sectorsize, |
| 72 | goto out_unlock; | 60 | root->sectorsize, GFP_NOFS); |
| 73 | } | ||
| 74 | bh = bh->b_this_page; | ||
| 75 | } while (bh != head); | ||
| 76 | out_unlock: | ||
| 77 | unlock_page(page); | ||
| 78 | page_cache_release(page); | ||
| 79 | return ret; | ||
| 80 | } | 61 | } |
| 81 | 62 | ||
| 82 | int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, | 63 | struct extent_map *btree_get_extent(struct inode *inode, struct page *page, |
| 83 | u64 logical) | 64 | size_t page_offset, u64 start, u64 end, |
| 65 | int create) | ||
| 84 | { | 66 | { |
| 85 | if (logical == 0) { | 67 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
| 86 | bh->b_bdev = NULL; | 68 | struct extent_map *em; |
| 87 | bh->b_blocknr = 0; | 69 | int ret; |
| 88 | set_buffer_mapped(bh); | 70 | |
| 89 | } else { | 71 | again: |
| 90 | map_bh(bh, root->fs_info->sb, logical); | 72 | em = lookup_extent_mapping(em_tree, start, end); |
| 73 | if (em) { | ||
| 74 | goto out; | ||
| 91 | } | 75 | } |
| 92 | return 0; | 76 | em = alloc_extent_map(GFP_NOFS); |
| 77 | if (!em) { | ||
| 78 | em = ERR_PTR(-ENOMEM); | ||
| 79 | goto out; | ||
| 80 | } | ||
| 81 | em->start = 0; | ||
| 82 | em->end = (i_size_read(inode) & ~((u64)PAGE_CACHE_SIZE -1)) - 1; | ||
| 83 | em->block_start = 0; | ||
| 84 | em->block_end = em->end; | ||
| 85 | em->bdev = inode->i_sb->s_bdev; | ||
| 86 | ret = add_extent_mapping(em_tree, em); | ||
| 87 | if (ret == -EEXIST) { | ||
| 88 | free_extent_map(em); | ||
| 89 | em = NULL; | ||
| 90 | goto again; | ||
| 91 | } else if (ret) { | ||
| 92 | em = ERR_PTR(ret); | ||
| 93 | } | ||
| 94 | out: | ||
| 95 | return em; | ||
| 93 | } | 96 | } |
| 94 | 97 | ||
| 95 | struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, | 98 | static int btree_writepage(struct page *page, struct writeback_control *wbc) |
| 96 | u64 blocknr) | ||
| 97 | { | 99 | { |
| 98 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; | 100 | struct extent_map_tree *tree; |
| 99 | int blockbits = root->fs_info->sb->s_blocksize_bits; | 101 | tree = &BTRFS_I(page->mapping->host)->extent_tree; |
| 100 | unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); | 102 | return extent_write_full_page(tree, page, btree_get_extent, wbc); |
| 101 | struct page *page; | 103 | } |
| 102 | struct buffer_head *bh; | 104 | int btree_readpage(struct file *file, struct page *page) |
| 103 | struct buffer_head *head; | 105 | { |
| 104 | struct buffer_head *ret = NULL; | 106 | struct extent_map_tree *tree; |
| 105 | int err; | 107 | tree = &BTRFS_I(page->mapping->host)->extent_tree; |
| 106 | u64 first_block = index << (PAGE_CACHE_SHIFT - blockbits); | 108 | return extent_read_full_page(tree, page, btree_get_extent); |
| 109 | } | ||
| 107 | 110 | ||
| 108 | page = find_or_create_page(mapping, index, GFP_NOFS); | 111 | static int btree_releasepage(struct page *page, gfp_t unused_gfp_flags) |
| 109 | if (!page) | 112 | { |
| 110 | return NULL; | 113 | struct extent_map_tree *tree; |
| 114 | int ret; | ||
| 111 | 115 | ||
| 112 | if (!page_has_buffers(page)) | 116 | BUG_ON(page->private != 1); |
| 113 | create_empty_buffers(page, root->fs_info->sb->s_blocksize, 0); | 117 | tree = &BTRFS_I(page->mapping->host)->extent_tree; |
| 114 | head = page_buffers(page); | 118 | ret = try_release_extent_mapping(tree, page); |
| 115 | bh = head; | 119 | if (ret == 1) { |
| 116 | do { | 120 | ClearPagePrivate(page); |
| 117 | if (!buffer_mapped(bh)) { | 121 | set_page_private(page, 0); |
| 118 | err = btrfs_map_bh_to_logical(root, bh, first_block); | 122 | page_cache_release(page); |
| 119 | BUG_ON(err); | 123 | } |
| 120 | } | ||
| 121 | if (bh_blocknr(bh) == blocknr) { | ||
| 122 | ret = bh; | ||
| 123 | get_bh(bh); | ||
| 124 | goto out_unlock; | ||
| 125 | } | ||
| 126 | bh = bh->b_this_page; | ||
| 127 | first_block++; | ||
| 128 | } while (bh != head); | ||
| 129 | out_unlock: | ||
| 130 | unlock_page(page); | ||
| 131 | if (ret) | ||
| 132 | touch_buffer(ret); | ||
| 133 | page_cache_release(page); | ||
| 134 | return ret; | 124 | return ret; |
| 135 | } | 125 | } |
| 136 | 126 | ||
| 137 | static int btree_get_block(struct inode *inode, sector_t iblock, | 127 | static void btree_invalidatepage(struct page *page, unsigned long offset) |
| 138 | struct buffer_head *bh, int create) | ||
| 139 | { | 128 | { |
| 140 | int err; | 129 | struct extent_map_tree *tree; |
| 141 | struct btrfs_root *root = BTRFS_I(bh->b_page->mapping->host)->root; | 130 | tree = &BTRFS_I(page->mapping->host)->extent_tree; |
| 142 | err = btrfs_map_bh_to_logical(root, bh, iblock); | 131 | extent_invalidatepage(tree, page, offset); |
| 143 | return err; | 132 | btree_releasepage(page, GFP_NOFS); |
| 144 | } | 133 | } |
| 145 | 134 | ||
| 146 | int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, | 135 | int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, |
| 147 | char *result) | 136 | char *result) |
| 148 | { | 137 | { |
| 138 | return 0; | ||
| 139 | #if 0 | ||
| 149 | u32 crc; | 140 | u32 crc; |
| 150 | crc = crc32c(0, data, len); | 141 | crc = crc32c(0, data, len); |
| 151 | memcpy(result, &crc, BTRFS_CRC32_SIZE); | 142 | memcpy(result, &crc, BTRFS_CRC32_SIZE); |
| 152 | return 0; | 143 | return 0; |
| 144 | #endif | ||
| 153 | } | 145 | } |
| 154 | 146 | ||
| 155 | static int csum_tree_block(struct btrfs_root *root, struct buffer_head *bh, | 147 | #if 0 |
| 148 | static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, | ||
| 156 | int verify) | 149 | int verify) |
| 157 | { | 150 | { |
| 151 | return 0; | ||
| 158 | char result[BTRFS_CRC32_SIZE]; | 152 | char result[BTRFS_CRC32_SIZE]; |
| 159 | int ret; | 153 | int ret; |
| 160 | struct btrfs_node *node; | 154 | struct btrfs_node *node; |
| @@ -176,7 +170,9 @@ static int csum_tree_block(struct btrfs_root *root, struct buffer_head *bh, | |||
| 176 | } | 170 | } |
| 177 | return 0; | 171 | return 0; |
| 178 | } | 172 | } |
| 173 | #endif | ||
| 179 | 174 | ||
| 175 | #if 0 | ||
| 180 | static int btree_writepage(struct page *page, struct writeback_control *wbc) | 176 | static int btree_writepage(struct page *page, struct writeback_control *wbc) |
| 181 | { | 177 | { |
| 182 | struct buffer_head *bh; | 178 | struct buffer_head *bh; |
| @@ -195,87 +191,65 @@ static int btree_writepage(struct page *page, struct writeback_control *wbc) | |||
| 195 | } while (bh != head); | 191 | } while (bh != head); |
| 196 | return block_write_full_page(page, btree_get_block, wbc); | 192 | return block_write_full_page(page, btree_get_block, wbc); |
| 197 | } | 193 | } |
| 198 | 194 | #endif | |
| 199 | static int btree_readpage(struct file * file, struct page * page) | ||
| 200 | { | ||
| 201 | return block_read_full_page(page, btree_get_block); | ||
| 202 | } | ||
| 203 | 195 | ||
| 204 | static struct address_space_operations btree_aops = { | 196 | static struct address_space_operations btree_aops = { |
| 205 | .readpage = btree_readpage, | 197 | .readpage = btree_readpage, |
| 206 | .writepage = btree_writepage, | 198 | .writepage = btree_writepage, |
| 199 | .releasepage = btree_releasepage, | ||
| 200 | .invalidatepage = btree_invalidatepage, | ||
| 207 | .sync_page = block_sync_page, | 201 | .sync_page = block_sync_page, |
| 208 | }; | 202 | }; |
| 209 | 203 | ||
| 210 | int readahead_tree_block(struct btrfs_root *root, u64 blocknr) | 204 | int readahead_tree_block(struct btrfs_root *root, u64 blocknr) |
| 211 | { | 205 | { |
| 212 | struct buffer_head *bh = NULL; | 206 | struct extent_buffer *buf = NULL; |
| 207 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
| 213 | int ret = 0; | 208 | int ret = 0; |
| 214 | 209 | ||
| 215 | bh = btrfs_find_create_tree_block(root, blocknr); | 210 | buf = btrfs_find_create_tree_block(root, blocknr); |
| 216 | if (!bh) | 211 | if (!buf) |
| 217 | return 0; | 212 | return 0; |
| 218 | if (buffer_uptodate(bh)) { | 213 | read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, |
| 219 | ret = 1; | 214 | buf, 0); |
| 220 | goto done; | 215 | free_extent_buffer(buf); |
| 221 | } | ||
| 222 | if (test_set_buffer_locked(bh)) { | ||
| 223 | ret = 1; | ||
| 224 | goto done; | ||
| 225 | } | ||
| 226 | if (!buffer_uptodate(bh)) { | ||
| 227 | get_bh(bh); | ||
| 228 | bh->b_end_io = end_buffer_read_sync; | ||
| 229 | submit_bh(READ, bh); | ||
| 230 | } else { | ||
| 231 | unlock_buffer(bh); | ||
| 232 | ret = 1; | ||
| 233 | } | ||
| 234 | done: | ||
| 235 | brelse(bh); | ||
| 236 | return ret; | 216 | return ret; |
| 237 | } | 217 | } |
| 238 | 218 | ||
| 239 | struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) | 219 | struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr) |
| 240 | { | 220 | { |
| 241 | struct buffer_head *bh = NULL; | 221 | struct extent_buffer *buf = NULL; |
| 242 | 222 | struct inode *btree_inode = root->fs_info->btree_inode; | |
| 243 | bh = btrfs_find_create_tree_block(root, blocknr); | 223 | |
| 244 | if (!bh) | 224 | buf = btrfs_find_create_tree_block(root, blocknr); |
| 245 | return bh; | 225 | if (!buf) |
| 246 | if (buffer_uptodate(bh)) | 226 | return NULL; |
| 247 | goto uptodate; | 227 | read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, |
| 248 | lock_buffer(bh); | 228 | buf, 1); |
| 249 | if (!buffer_uptodate(bh)) { | 229 | return buf; |
| 250 | get_bh(bh); | ||
| 251 | bh->b_end_io = end_buffer_read_sync; | ||
| 252 | submit_bh(READ, bh); | ||
| 253 | wait_on_buffer(bh); | ||
| 254 | if (!buffer_uptodate(bh)) | ||
| 255 | goto fail; | ||
| 256 | } else { | ||
| 257 | unlock_buffer(bh); | ||
| 258 | } | ||
| 259 | uptodate: | ||
| 260 | if (!buffer_checked(bh)) { | ||
| 261 | csum_tree_block(root, bh, 1); | ||
| 262 | set_buffer_checked(bh); | ||
| 263 | } | ||
| 264 | if (check_tree_block(root, bh)) | ||
| 265 | goto fail; | ||
| 266 | return bh; | ||
| 267 | fail: | ||
| 268 | brelse(bh); | ||
| 269 | return NULL; | ||
| 270 | } | 230 | } |
| 271 | 231 | ||
| 272 | int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 232 | int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 273 | struct buffer_head *buf) | 233 | struct extent_buffer *buf) |
| 274 | { | 234 | { |
| 275 | WARN_ON(atomic_read(&buf->b_count) == 0); | 235 | struct inode *btree_inode = root->fs_info->btree_inode; |
| 276 | lock_buffer(buf); | 236 | clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf); |
| 277 | clear_buffer_dirty(buf); | 237 | return 0; |
| 278 | unlock_buffer(buf); | 238 | } |
| 239 | |||
| 240 | int wait_on_tree_block_writeback(struct btrfs_root *root, | ||
| 241 | struct extent_buffer *buf) | ||
| 242 | { | ||
| 243 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
| 244 | wait_on_extent_buffer_writeback(&BTRFS_I(btree_inode)->extent_tree, | ||
| 245 | buf); | ||
| 246 | return 0; | ||
| 247 | } | ||
| 248 | |||
| 249 | int set_tree_block_dirty(struct btrfs_root *root, struct extent_buffer *buf) | ||
| 250 | { | ||
| 251 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
| 252 | set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf); | ||
| 279 | return 0; | 253 | return 0; |
| 280 | } | 254 | } |
| 281 | 255 | ||
| @@ -287,7 +261,9 @@ static int __setup_root(int blocksize, | |||
| 287 | root->node = NULL; | 261 | root->node = NULL; |
| 288 | root->inode = NULL; | 262 | root->inode = NULL; |
| 289 | root->commit_root = NULL; | 263 | root->commit_root = NULL; |
| 290 | root->blocksize = blocksize; | 264 | root->sectorsize = blocksize; |
| 265 | root->nodesize = blocksize; | ||
| 266 | root->leafsize = blocksize; | ||
| 291 | root->ref_cows = 0; | 267 | root->ref_cows = 0; |
| 292 | root->fs_info = fs_info; | 268 | root->fs_info = fs_info; |
| 293 | root->objectid = objectid; | 269 | root->objectid = objectid; |
| @@ -332,7 +308,7 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, | |||
| 332 | struct btrfs_root *root; | 308 | struct btrfs_root *root; |
| 333 | struct btrfs_root *tree_root = fs_info->tree_root; | 309 | struct btrfs_root *tree_root = fs_info->tree_root; |
| 334 | struct btrfs_path *path; | 310 | struct btrfs_path *path; |
| 335 | struct btrfs_leaf *l; | 311 | struct extent_buffer *l; |
| 336 | u64 highest_inode; | 312 | u64 highest_inode; |
| 337 | int ret = 0; | 313 | int ret = 0; |
| 338 | 314 | ||
| @@ -361,11 +337,10 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, | |||
| 361 | ret = -ENOENT; | 337 | ret = -ENOENT; |
| 362 | goto out; | 338 | goto out; |
| 363 | } | 339 | } |
| 364 | l = btrfs_buffer_leaf(path->nodes[0]); | 340 | l = path->nodes[0]; |
| 365 | memcpy(&root->root_item, | 341 | read_extent_buffer(l, &root->root_item, |
| 366 | btrfs_item_ptr(l, path->slots[0], struct btrfs_root_item), | 342 | btrfs_item_ptr_offset(l, path->slots[0]), |
| 367 | sizeof(root->root_item)); | 343 | sizeof(root->root_item)); |
| 368 | memcpy(&root->root_key, location, sizeof(*location)); | ||
| 369 | ret = 0; | 344 | ret = 0; |
| 370 | out: | 345 | out: |
| 371 | btrfs_release_path(root, path); | 346 | btrfs_release_path(root, path); |
| @@ -406,21 +381,21 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, | |||
| 406 | (unsigned long)root->root_key.objectid, | 381 | (unsigned long)root->root_key.objectid, |
| 407 | root); | 382 | root); |
| 408 | if (ret) { | 383 | if (ret) { |
| 409 | brelse(root->node); | 384 | free_extent_buffer(root->node); |
| 410 | kfree(root); | 385 | kfree(root); |
| 411 | return ERR_PTR(ret); | 386 | return ERR_PTR(ret); |
| 412 | } | 387 | } |
| 413 | 388 | ||
| 414 | ret = btrfs_set_root_name(root, name, namelen); | 389 | ret = btrfs_set_root_name(root, name, namelen); |
| 415 | if (ret) { | 390 | if (ret) { |
| 416 | brelse(root->node); | 391 | free_extent_buffer(root->node); |
| 417 | kfree(root); | 392 | kfree(root); |
| 418 | return ERR_PTR(ret); | 393 | return ERR_PTR(ret); |
| 419 | } | 394 | } |
| 420 | 395 | ||
| 421 | ret = btrfs_sysfs_add_root(root); | 396 | ret = btrfs_sysfs_add_root(root); |
| 422 | if (ret) { | 397 | if (ret) { |
| 423 | brelse(root->node); | 398 | free_extent_buffer(root->node); |
| 424 | kfree(root->name); | 399 | kfree(root->name); |
| 425 | kfree(root); | 400 | kfree(root); |
| 426 | return ERR_PTR(ret); | 401 | return ERR_PTR(ret); |
| @@ -471,6 +446,9 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
| 471 | fs_info->btree_inode->i_nlink = 1; | 446 | fs_info->btree_inode->i_nlink = 1; |
| 472 | fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; | 447 | fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; |
| 473 | fs_info->btree_inode->i_mapping->a_ops = &btree_aops; | 448 | fs_info->btree_inode->i_mapping->a_ops = &btree_aops; |
| 449 | extent_map_tree_init(&BTRFS_I(fs_info->btree_inode)->extent_tree, | ||
| 450 | fs_info->btree_inode->i_mapping, | ||
| 451 | GFP_NOFS); | ||
| 474 | fs_info->do_barriers = 1; | 452 | fs_info->do_barriers = 1; |
| 475 | fs_info->closing = 0; | 453 | fs_info->closing = 0; |
| 476 | 454 | ||
| @@ -493,10 +471,14 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
| 493 | 471 | ||
| 494 | if (!fs_info->sb_buffer) | 472 | if (!fs_info->sb_buffer) |
| 495 | goto fail_iput; | 473 | goto fail_iput; |
| 496 | disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data; | ||
| 497 | fs_info->disk_super = disk_super; | ||
| 498 | memcpy(&fs_info->super_copy, disk_super, sizeof(fs_info->super_copy)); | ||
| 499 | 474 | ||
| 475 | read_extent_buffer(fs_info->sb_buffer, &fs_info->super_copy, 0, | ||
| 476 | sizeof(fs_info->super_copy)); | ||
| 477 | |||
| 478 | read_extent_buffer(fs_info->sb_buffer, fs_info->fsid, | ||
| 479 | (unsigned long)btrfs_super_fsid(fs_info->sb_buffer), | ||
| 480 | BTRFS_FSID_SIZE); | ||
| 481 | disk_super = &fs_info->super_copy; | ||
| 500 | if (!btrfs_super_root(disk_super)) | 482 | if (!btrfs_super_root(disk_super)) |
| 501 | goto fail_sb_buffer; | 483 | goto fail_sb_buffer; |
| 502 | 484 | ||
| @@ -530,9 +512,9 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
| 530 | return tree_root; | 512 | return tree_root; |
| 531 | 513 | ||
| 532 | fail_tree_root: | 514 | fail_tree_root: |
| 533 | btrfs_block_release(tree_root, tree_root->node); | 515 | free_extent_buffer(tree_root->node); |
| 534 | fail_sb_buffer: | 516 | fail_sb_buffer: |
| 535 | btrfs_block_release(tree_root, fs_info->sb_buffer); | 517 | free_extent_buffer(fs_info->sb_buffer); |
| 536 | fail_iput: | 518 | fail_iput: |
| 537 | iput(fs_info->btree_inode); | 519 | iput(fs_info->btree_inode); |
| 538 | fail: | 520 | fail: |
| @@ -546,31 +528,13 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 546 | *root) | 528 | *root) |
| 547 | { | 529 | { |
| 548 | int ret; | 530 | int ret; |
| 549 | struct buffer_head *bh = root->fs_info->sb_buffer; | 531 | struct extent_buffer *super = root->fs_info->sb_buffer; |
| 550 | 532 | struct inode *btree_inode = root->fs_info->btree_inode; | |
| 551 | lock_buffer(bh); | 533 | |
| 552 | WARN_ON(atomic_read(&bh->b_count) < 1); | 534 | set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, super); |
| 553 | clear_buffer_dirty(bh); | 535 | ret = sync_page_range_nolock(btree_inode, btree_inode->i_mapping, |
| 554 | csum_tree_block(root, bh, 0); | 536 | super->start, super->len); |
| 555 | bh->b_end_io = end_buffer_write_sync; | 537 | return ret; |
| 556 | get_bh(bh); | ||
| 557 | if (root->fs_info->do_barriers) | ||
| 558 | ret = submit_bh(WRITE_BARRIER, bh); | ||
| 559 | else | ||
| 560 | ret = submit_bh(WRITE, bh); | ||
| 561 | if (ret == -EOPNOTSUPP) { | ||
| 562 | get_bh(bh); | ||
| 563 | lock_buffer(bh); | ||
| 564 | set_buffer_uptodate(bh); | ||
| 565 | root->fs_info->do_barriers = 0; | ||
| 566 | ret = submit_bh(WRITE, bh); | ||
| 567 | } | ||
| 568 | wait_on_buffer(bh); | ||
| 569 | if (!buffer_uptodate(bh)) { | ||
| 570 | WARN_ON(1); | ||
| 571 | return -EIO; | ||
| 572 | } | ||
| 573 | return 0; | ||
| 574 | } | 538 | } |
| 575 | 539 | ||
| 576 | int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) | 540 | int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) |
| @@ -581,9 +545,9 @@ int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) | |||
| 581 | if (root->inode) | 545 | if (root->inode) |
| 582 | iput(root->inode); | 546 | iput(root->inode); |
| 583 | if (root->node) | 547 | if (root->node) |
| 584 | brelse(root->node); | 548 | free_extent_buffer(root->node); |
| 585 | if (root->commit_root) | 549 | if (root->commit_root) |
| 586 | brelse(root->commit_root); | 550 | free_extent_buffer(root->commit_root); |
| 587 | if (root->name) | 551 | if (root->name) |
| 588 | kfree(root->name); | 552 | kfree(root->name); |
| 589 | kfree(root); | 553 | kfree(root); |
| @@ -629,12 +593,10 @@ int close_ctree(struct btrfs_root *root) | |||
| 629 | mutex_unlock(&fs_info->fs_mutex); | 593 | mutex_unlock(&fs_info->fs_mutex); |
| 630 | 594 | ||
| 631 | if (fs_info->extent_root->node) | 595 | if (fs_info->extent_root->node) |
| 632 | btrfs_block_release(fs_info->extent_root, | 596 | free_extent_buffer(fs_info->extent_root->node); |
| 633 | fs_info->extent_root->node); | ||
| 634 | if (fs_info->tree_root->node) | 597 | if (fs_info->tree_root->node) |
| 635 | btrfs_block_release(fs_info->tree_root, | 598 | free_extent_buffer(fs_info->tree_root->node); |
| 636 | fs_info->tree_root->node); | 599 | free_extent_buffer(fs_info->sb_buffer); |
| 637 | btrfs_block_release(root, fs_info->sb_buffer); | ||
| 638 | truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); | 600 | truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); |
| 639 | iput(fs_info->btree_inode); | 601 | iput(fs_info->btree_inode); |
| 640 | 602 | ||
| @@ -645,25 +607,32 @@ int close_ctree(struct btrfs_root *root) | |||
| 645 | return 0; | 607 | return 0; |
| 646 | } | 608 | } |
| 647 | 609 | ||
| 648 | void btrfs_mark_buffer_dirty(struct buffer_head *bh) | 610 | int btrfs_buffer_uptodate(struct extent_buffer *buf) |
| 611 | { | ||
| 612 | struct inode *btree_inode = buf->pages[0]->mapping->host; | ||
| 613 | return extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, buf); | ||
| 614 | } | ||
| 615 | |||
| 616 | int btrfs_set_buffer_uptodate(struct extent_buffer *buf) | ||
| 649 | { | 617 | { |
| 650 | struct btrfs_root *root = BTRFS_I(bh->b_page->mapping->host)->root; | 618 | struct inode *btree_inode = buf->pages[0]->mapping->host; |
| 651 | u64 transid = btrfs_header_generation(btrfs_buffer_header(bh)); | 619 | return set_extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, |
| 620 | buf); | ||
| 621 | } | ||
| 652 | 622 | ||
| 653 | WARN_ON(!atomic_read(&bh->b_count)); | 623 | void btrfs_mark_buffer_dirty(struct extent_buffer *buf) |
| 624 | { | ||
| 625 | struct btrfs_root *root = BTRFS_I(buf->pages[0]->mapping->host)->root; | ||
| 626 | u64 transid = btrfs_header_generation(buf); | ||
| 627 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
| 654 | 628 | ||
| 655 | if (transid != root->fs_info->generation) { | 629 | if (transid != root->fs_info->generation) { |
| 656 | printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n", | 630 | printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n", |
| 657 | (unsigned long long)bh->b_blocknr, | 631 | (unsigned long long)extent_buffer_blocknr(buf), |
| 658 | transid, root->fs_info->generation); | 632 | transid, root->fs_info->generation); |
| 659 | WARN_ON(1); | 633 | WARN_ON(1); |
| 660 | } | 634 | } |
| 661 | mark_buffer_dirty(bh); | 635 | set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf); |
| 662 | } | ||
| 663 | |||
| 664 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf) | ||
| 665 | { | ||
| 666 | brelse(buf); | ||
| 667 | } | 636 | } |
| 668 | 637 | ||
| 669 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) | 638 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index fc6b520c6e0b..70d9413c599f 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
| @@ -19,68 +19,35 @@ | |||
| 19 | #ifndef __DISKIO__ | 19 | #ifndef __DISKIO__ |
| 20 | #define __DISKIO__ | 20 | #define __DISKIO__ |
| 21 | 21 | ||
| 22 | #include <linux/buffer_head.h> | ||
| 23 | |||
| 24 | #define BTRFS_SUPER_INFO_OFFSET (16 * 1024) | 22 | #define BTRFS_SUPER_INFO_OFFSET (16 * 1024) |
| 25 | 23 | ||
| 26 | enum btrfs_bh_state_bits { | 24 | struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr); |
| 27 | BH_Checked = BH_PrivateStart, | ||
| 28 | BH_Defrag, | ||
| 29 | BH_DefragDone, | ||
| 30 | }; | ||
| 31 | BUFFER_FNS(Checked, checked); | ||
| 32 | BUFFER_FNS(Defrag, defrag); | ||
| 33 | BUFFER_FNS(DefragDone, defrag_done); | ||
| 34 | |||
| 35 | static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh) | ||
| 36 | { | ||
| 37 | return (struct btrfs_node *)bh->b_data; | ||
| 38 | } | ||
| 39 | |||
| 40 | static inline struct btrfs_leaf *btrfs_buffer_leaf(struct buffer_head *bh) | ||
| 41 | { | ||
| 42 | return (struct btrfs_leaf *)bh->b_data; | ||
| 43 | } | ||
| 44 | |||
| 45 | static inline struct btrfs_header *btrfs_buffer_header(struct buffer_head *bh) | ||
| 46 | { | ||
| 47 | return &((struct btrfs_node *)bh->b_data)->header; | ||
| 48 | } | ||
| 49 | |||
| 50 | struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr); | ||
| 51 | int readahead_tree_block(struct btrfs_root *root, u64 blocknr); | 25 | int readahead_tree_block(struct btrfs_root *root, u64 blocknr); |
| 52 | struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, | 26 | struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, |
| 53 | u64 blocknr); | 27 | u64 blocknr); |
| 54 | int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | ||
| 55 | struct buffer_head *buf); | ||
| 56 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | ||
| 57 | struct buffer_head *buf); | ||
| 58 | int clean_tree_block(struct btrfs_trans_handle *trans, | 28 | int clean_tree_block(struct btrfs_trans_handle *trans, |
| 59 | struct btrfs_root *root, struct buffer_head *buf); | 29 | struct btrfs_root *root, struct extent_buffer *buf); |
| 60 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | ||
| 61 | struct btrfs_root *root); | ||
| 62 | struct btrfs_root *open_ctree(struct super_block *sb); | 30 | struct btrfs_root *open_ctree(struct super_block *sb); |
| 63 | int close_ctree(struct btrfs_root *root); | 31 | int close_ctree(struct btrfs_root *root); |
| 64 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf); | ||
| 65 | int write_ctree_super(struct btrfs_trans_handle *trans, | 32 | int write_ctree_super(struct btrfs_trans_handle *trans, |
| 66 | struct btrfs_root *root); | 33 | struct btrfs_root *root); |
| 67 | struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr); | 34 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, |
| 68 | int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, | 35 | u64 blocknr); |
| 69 | char *result); | ||
| 70 | struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, | 36 | struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, |
| 71 | struct btrfs_key *location, | 37 | struct btrfs_key *location, |
| 72 | const char *name, int namelen); | 38 | const char *name, int namelen); |
| 73 | struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, | 39 | struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, |
| 74 | struct btrfs_key *location); | 40 | struct btrfs_key *location); |
| 75 | u64 bh_blocknr(struct buffer_head *bh); | ||
| 76 | int btrfs_insert_dev_radix(struct btrfs_root *root, | 41 | int btrfs_insert_dev_radix(struct btrfs_root *root, |
| 77 | struct block_device *bdev, | 42 | struct block_device *bdev, |
| 78 | u64 device_id, | 43 | u64 device_id, |
| 79 | u64 block_start, | 44 | u64 block_start, |
| 80 | u64 num_blocks); | 45 | u64 num_blocks); |
| 81 | int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, | ||
| 82 | u64 logical); | ||
| 83 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); | 46 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); |
| 84 | int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); | 47 | int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); |
| 85 | void btrfs_mark_buffer_dirty(struct buffer_head *bh); | 48 | void btrfs_mark_buffer_dirty(struct extent_buffer *buf); |
| 49 | int btrfs_buffer_uptodate(struct extent_buffer *buf); | ||
| 50 | int btrfs_set_buffer_uptodate(struct extent_buffer *buf); | ||
| 51 | int wait_on_tree_block_writeback(struct btrfs_root *root, | ||
| 52 | struct extent_buffer *buf); | ||
| 86 | #endif | 53 | #endif |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index f261a8326cdf..089c41cbca74 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -33,7 +33,7 @@ static int cache_block_group(struct btrfs_root *root, | |||
| 33 | struct btrfs_path *path; | 33 | struct btrfs_path *path; |
| 34 | int ret; | 34 | int ret; |
| 35 | struct btrfs_key key; | 35 | struct btrfs_key key; |
| 36 | struct btrfs_leaf *leaf; | 36 | struct extent_buffer *leaf; |
| 37 | struct radix_tree_root *extent_radix; | 37 | struct radix_tree_root *extent_radix; |
| 38 | int slot; | 38 | int slot; |
| 39 | u64 i; | 39 | u64 i; |
| @@ -56,7 +56,6 @@ static int cache_block_group(struct btrfs_root *root, | |||
| 56 | path->reada = 2; | 56 | path->reada = 2; |
| 57 | first_free = block_group->key.objectid; | 57 | first_free = block_group->key.objectid; |
| 58 | key.objectid = block_group->key.objectid; | 58 | key.objectid = block_group->key.objectid; |
| 59 | key.flags = 0; | ||
| 60 | key.offset = 0; | 59 | key.offset = 0; |
| 61 | 60 | ||
| 62 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 61 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
| @@ -69,9 +68,9 @@ static int cache_block_group(struct btrfs_root *root, | |||
| 69 | path->slots[0]--; | 68 | path->slots[0]--; |
| 70 | 69 | ||
| 71 | while(1) { | 70 | while(1) { |
| 72 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 71 | leaf = path->nodes[0]; |
| 73 | slot = path->slots[0]; | 72 | slot = path->slots[0]; |
| 74 | if (slot >= btrfs_header_nritems(&leaf->header)) { | 73 | if (slot >= btrfs_header_nritems(leaf)) { |
| 75 | ret = btrfs_next_leaf(root, path); | 74 | ret = btrfs_next_leaf(root, path); |
| 76 | if (ret < 0) | 75 | if (ret < 0) |
| 77 | goto err; | 76 | goto err; |
| @@ -82,7 +81,7 @@ static int cache_block_group(struct btrfs_root *root, | |||
| 82 | } | 81 | } |
| 83 | } | 82 | } |
| 84 | 83 | ||
| 85 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); | 84 | btrfs_item_key_to_cpu(leaf, &key, slot); |
| 86 | if (key.objectid < block_group->key.objectid) { | 85 | if (key.objectid < block_group->key.objectid) { |
| 87 | if (key.objectid + key.offset > first_free) | 86 | if (key.objectid + key.offset > first_free) |
| 88 | first_free = key.objectid + key.offset; | 87 | first_free = key.objectid + key.offset; |
| @@ -116,8 +115,7 @@ next: | |||
| 116 | hole_size = block_group->key.objectid + | 115 | hole_size = block_group->key.objectid + |
| 117 | block_group->key.offset - last; | 116 | block_group->key.offset - last; |
| 118 | for (i = 0; i < hole_size; i++) { | 117 | for (i = 0; i < hole_size; i++) { |
| 119 | set_radix_bit(extent_radix, | 118 | set_radix_bit(extent_radix, last + i); |
| 120 | last + i); | ||
| 121 | } | 119 | } |
| 122 | } | 120 | } |
| 123 | block_group->cached = 1; | 121 | block_group->cached = 1; |
| @@ -366,7 +364,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | |||
| 366 | struct btrfs_path *path; | 364 | struct btrfs_path *path; |
| 367 | int ret; | 365 | int ret; |
| 368 | struct btrfs_key key; | 366 | struct btrfs_key key; |
| 369 | struct btrfs_leaf *l; | 367 | struct extent_buffer *l; |
| 370 | struct btrfs_extent_item *item; | 368 | struct btrfs_extent_item *item; |
| 371 | u32 refs; | 369 | u32 refs; |
| 372 | 370 | ||
| @@ -375,7 +373,6 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | |||
| 375 | return -ENOMEM; | 373 | return -ENOMEM; |
| 376 | 374 | ||
| 377 | key.objectid = blocknr; | 375 | key.objectid = blocknr; |
| 378 | key.flags = 0; | ||
| 379 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 376 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
| 380 | key.offset = num_blocks; | 377 | key.offset = num_blocks; |
| 381 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path, | 378 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path, |
| @@ -386,10 +383,10 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | |||
| 386 | BUG(); | 383 | BUG(); |
| 387 | } | 384 | } |
| 388 | BUG_ON(ret != 0); | 385 | BUG_ON(ret != 0); |
| 389 | l = btrfs_buffer_leaf(path->nodes[0]); | 386 | l = path->nodes[0]; |
| 390 | item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item); | 387 | item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item); |
| 391 | refs = btrfs_extent_refs(item); | 388 | refs = btrfs_extent_refs(l, item); |
| 392 | btrfs_set_extent_refs(item, refs + 1); | 389 | btrfs_set_extent_refs(l, item, refs + 1); |
| 393 | btrfs_mark_buffer_dirty(path->nodes[0]); | 390 | btrfs_mark_buffer_dirty(path->nodes[0]); |
| 394 | 391 | ||
| 395 | btrfs_release_path(root->fs_info->extent_root, path); | 392 | btrfs_release_path(root->fs_info->extent_root, path); |
| @@ -414,23 +411,25 @@ static int lookup_extent_ref(struct btrfs_trans_handle *trans, | |||
| 414 | struct btrfs_path *path; | 411 | struct btrfs_path *path; |
| 415 | int ret; | 412 | int ret; |
| 416 | struct btrfs_key key; | 413 | struct btrfs_key key; |
| 417 | struct btrfs_leaf *l; | 414 | struct extent_buffer *l; |
| 418 | struct btrfs_extent_item *item; | 415 | struct btrfs_extent_item *item; |
| 419 | 416 | ||
| 420 | path = btrfs_alloc_path(); | 417 | path = btrfs_alloc_path(); |
| 421 | key.objectid = blocknr; | 418 | key.objectid = blocknr; |
| 422 | key.offset = num_blocks; | 419 | key.offset = num_blocks; |
| 423 | key.flags = 0; | ||
| 424 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 420 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
| 425 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path, | 421 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path, |
| 426 | 0, 0); | 422 | 0, 0); |
| 427 | if (ret < 0) | 423 | if (ret < 0) |
| 428 | goto out; | 424 | goto out; |
| 429 | if (ret != 0) | 425 | if (ret != 0) { |
| 426 | btrfs_print_leaf(root, path->nodes[0]); | ||
| 427 | printk("failed to find block number %Lu\n", blocknr); | ||
| 430 | BUG(); | 428 | BUG(); |
| 431 | l = btrfs_buffer_leaf(path->nodes[0]); | 429 | } |
| 430 | l = path->nodes[0]; | ||
| 432 | item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item); | 431 | item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item); |
| 433 | *refs = btrfs_extent_refs(item); | 432 | *refs = btrfs_extent_refs(l, item); |
| 434 | out: | 433 | out: |
| 435 | btrfs_free_path(path); | 434 | btrfs_free_path(path); |
| 436 | return 0; | 435 | return 0; |
| @@ -439,16 +438,16 @@ out: | |||
| 439 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, | 438 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, |
| 440 | struct btrfs_root *root) | 439 | struct btrfs_root *root) |
| 441 | { | 440 | { |
| 442 | return btrfs_inc_extent_ref(trans, root, bh_blocknr(root->node), 1); | 441 | return btrfs_inc_extent_ref(trans, root, |
| 442 | extent_buffer_blocknr(root->node), 1); | ||
| 443 | } | 443 | } |
| 444 | 444 | ||
| 445 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 445 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 446 | struct buffer_head *buf) | 446 | struct extent_buffer *buf) |
| 447 | { | 447 | { |
| 448 | u64 blocknr; | 448 | u64 blocknr; |
| 449 | struct btrfs_node *buf_node; | 449 | u32 nritems; |
| 450 | struct btrfs_leaf *buf_leaf; | 450 | struct btrfs_key key; |
| 451 | struct btrfs_disk_key *key; | ||
| 452 | struct btrfs_file_extent_item *fi; | 451 | struct btrfs_file_extent_item *fi; |
| 453 | int i; | 452 | int i; |
| 454 | int leaf; | 453 | int leaf; |
| @@ -458,31 +457,31 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 458 | 457 | ||
| 459 | if (!root->ref_cows) | 458 | if (!root->ref_cows) |
| 460 | return 0; | 459 | return 0; |
| 461 | buf_node = btrfs_buffer_node(buf); | 460 | |
| 462 | leaf = btrfs_is_leaf(buf_node); | 461 | leaf = btrfs_is_leaf(buf); |
| 463 | buf_leaf = btrfs_buffer_leaf(buf); | 462 | nritems = btrfs_header_nritems(buf); |
| 464 | for (i = 0; i < btrfs_header_nritems(&buf_node->header); i++) { | 463 | for (i = 0; i < nritems; i++) { |
| 465 | if (leaf) { | 464 | if (leaf) { |
| 466 | u64 disk_blocknr; | 465 | u64 disk_blocknr; |
| 467 | key = &buf_leaf->items[i].key; | 466 | btrfs_item_key_to_cpu(buf, &key, i); |
| 468 | if (btrfs_disk_key_type(key) != BTRFS_EXTENT_DATA_KEY) | 467 | if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY) |
| 469 | continue; | 468 | continue; |
| 470 | fi = btrfs_item_ptr(buf_leaf, i, | 469 | fi = btrfs_item_ptr(buf, i, |
| 471 | struct btrfs_file_extent_item); | 470 | struct btrfs_file_extent_item); |
| 472 | if (btrfs_file_extent_type(fi) == | 471 | if (btrfs_file_extent_type(buf, fi) == |
| 473 | BTRFS_FILE_EXTENT_INLINE) | 472 | BTRFS_FILE_EXTENT_INLINE) |
| 474 | continue; | 473 | continue; |
| 475 | disk_blocknr = btrfs_file_extent_disk_blocknr(fi); | 474 | disk_blocknr = btrfs_file_extent_disk_blocknr(buf, fi); |
| 476 | if (disk_blocknr == 0) | 475 | if (disk_blocknr == 0) |
| 477 | continue; | 476 | continue; |
| 478 | ret = btrfs_inc_extent_ref(trans, root, disk_blocknr, | 477 | ret = btrfs_inc_extent_ref(trans, root, disk_blocknr, |
| 479 | btrfs_file_extent_disk_num_blocks(fi)); | 478 | btrfs_file_extent_disk_num_blocks(buf, fi)); |
| 480 | if (ret) { | 479 | if (ret) { |
| 481 | faili = i; | 480 | faili = i; |
| 482 | goto fail; | 481 | goto fail; |
| 483 | } | 482 | } |
| 484 | } else { | 483 | } else { |
| 485 | blocknr = btrfs_node_blockptr(buf_node, i); | 484 | blocknr = btrfs_node_blockptr(buf, i); |
| 486 | ret = btrfs_inc_extent_ref(trans, root, blocknr, 1); | 485 | ret = btrfs_inc_extent_ref(trans, root, blocknr, 1); |
| 487 | if (ret) { | 486 | if (ret) { |
| 488 | faili = i; | 487 | faili = i; |
| @@ -496,22 +495,23 @@ fail: | |||
| 496 | for (i =0; i < faili; i++) { | 495 | for (i =0; i < faili; i++) { |
| 497 | if (leaf) { | 496 | if (leaf) { |
| 498 | u64 disk_blocknr; | 497 | u64 disk_blocknr; |
| 499 | key = &buf_leaf->items[i].key; | 498 | btrfs_item_key_to_cpu(buf, &key, i); |
| 500 | if (btrfs_disk_key_type(key) != BTRFS_EXTENT_DATA_KEY) | 499 | if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY) |
| 501 | continue; | 500 | continue; |
| 502 | fi = btrfs_item_ptr(buf_leaf, i, | 501 | fi = btrfs_item_ptr(buf, i, |
| 503 | struct btrfs_file_extent_item); | 502 | struct btrfs_file_extent_item); |
| 504 | if (btrfs_file_extent_type(fi) == | 503 | if (btrfs_file_extent_type(buf, fi) == |
| 505 | BTRFS_FILE_EXTENT_INLINE) | 504 | BTRFS_FILE_EXTENT_INLINE) |
| 506 | continue; | 505 | continue; |
| 507 | disk_blocknr = btrfs_file_extent_disk_blocknr(fi); | 506 | disk_blocknr = btrfs_file_extent_disk_blocknr(buf, fi); |
| 508 | if (disk_blocknr == 0) | 507 | if (disk_blocknr == 0) |
| 509 | continue; | 508 | continue; |
| 510 | err = btrfs_free_extent(trans, root, disk_blocknr, | 509 | err = btrfs_free_extent(trans, root, disk_blocknr, |
| 511 | btrfs_file_extent_disk_num_blocks(fi), 0); | 510 | btrfs_file_extent_disk_num_blocks(buf, |
| 511 | fi), 0); | ||
| 512 | BUG_ON(err); | 512 | BUG_ON(err); |
| 513 | } else { | 513 | } else { |
| 514 | blocknr = btrfs_node_blockptr(buf_node, i); | 514 | blocknr = btrfs_node_blockptr(buf, i); |
| 515 | err = btrfs_free_extent(trans, root, blocknr, 1, 0); | 515 | err = btrfs_free_extent(trans, root, blocknr, 1, 0); |
| 516 | BUG_ON(err); | 516 | BUG_ON(err); |
| 517 | } | 517 | } |
| @@ -527,16 +527,18 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans, | |||
| 527 | int ret; | 527 | int ret; |
| 528 | int pending_ret; | 528 | int pending_ret; |
| 529 | struct btrfs_root *extent_root = root->fs_info->extent_root; | 529 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
| 530 | struct btrfs_block_group_item *bi; | 530 | unsigned long bi; |
| 531 | struct extent_buffer *leaf; | ||
| 531 | 532 | ||
| 532 | ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); | 533 | ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); |
| 533 | if (ret < 0) | 534 | if (ret < 0) |
| 534 | goto fail; | 535 | goto fail; |
| 535 | BUG_ON(ret); | 536 | BUG_ON(ret); |
| 536 | bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | 537 | |
| 537 | struct btrfs_block_group_item); | 538 | leaf = path->nodes[0]; |
| 538 | memcpy(bi, &cache->item, sizeof(*bi)); | 539 | bi = btrfs_item_ptr_offset(leaf, path->slots[0]); |
| 539 | btrfs_mark_buffer_dirty(path->nodes[0]); | 540 | write_extent_buffer(leaf, &cache->item, bi, sizeof(cache->item)); |
| 541 | btrfs_mark_buffer_dirty(leaf); | ||
| 540 | btrfs_release_path(extent_root, path); | 542 | btrfs_release_path(extent_root, path); |
| 541 | fail: | 543 | fail: |
| 542 | finish_current_insert(trans, extent_root); | 544 | finish_current_insert(trans, extent_root); |
| @@ -768,11 +770,11 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
| 768 | unsigned long gang[8]; | 770 | unsigned long gang[8]; |
| 769 | struct btrfs_fs_info *info = extent_root->fs_info; | 771 | struct btrfs_fs_info *info = extent_root->fs_info; |
| 770 | 772 | ||
| 771 | btrfs_set_extent_refs(&extent_item, 1); | 773 | btrfs_set_stack_extent_refs(&extent_item, 1); |
| 772 | ins.offset = 1; | 774 | ins.offset = 1; |
| 773 | ins.flags = 0; | ||
| 774 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); | 775 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); |
| 775 | btrfs_set_extent_owner(&extent_item, extent_root->root_key.objectid); | 776 | btrfs_set_stack_extent_owner(&extent_item, |
| 777 | extent_root->root_key.objectid); | ||
| 776 | 778 | ||
| 777 | while(1) { | 779 | while(1) { |
| 778 | ret = find_first_radix_bit(&info->extent_ins_radix, gang, 0, | 780 | ret = find_first_radix_bit(&info->extent_ins_radix, gang, 0, |
| @@ -795,23 +797,20 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
| 795 | static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) | 797 | static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) |
| 796 | { | 798 | { |
| 797 | int err; | 799 | int err; |
| 798 | struct btrfs_header *header; | 800 | struct extent_buffer *buf; |
| 799 | struct buffer_head *bh; | ||
| 800 | 801 | ||
| 801 | if (!pending) { | 802 | if (!pending) { |
| 802 | bh = btrfs_find_tree_block(root, blocknr); | 803 | buf = btrfs_find_tree_block(root, blocknr); |
| 803 | if (bh) { | 804 | if (buf) { |
| 804 | if (buffer_uptodate(bh)) { | 805 | if (btrfs_buffer_uptodate(buf)) { |
| 805 | u64 transid = | 806 | u64 transid = |
| 806 | root->fs_info->running_transaction->transid; | 807 | root->fs_info->running_transaction->transid; |
| 807 | header = btrfs_buffer_header(bh); | 808 | if (btrfs_header_generation(buf) == transid) { |
| 808 | if (btrfs_header_generation(header) == | 809 | free_extent_buffer(buf); |
| 809 | transid) { | ||
| 810 | btrfs_block_release(root, bh); | ||
| 811 | return 0; | 810 | return 0; |
| 812 | } | 811 | } |
| 813 | } | 812 | } |
| 814 | btrfs_block_release(root, bh); | 813 | free_extent_buffer(buf); |
| 815 | } | 814 | } |
| 816 | err = set_radix_bit(&root->fs_info->pinned_radix, blocknr); | 815 | err = set_radix_bit(&root->fs_info->pinned_radix, blocknr); |
| 817 | if (!err) { | 816 | if (!err) { |
| @@ -839,12 +838,12 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 839 | struct btrfs_key key; | 838 | struct btrfs_key key; |
| 840 | struct btrfs_fs_info *info = root->fs_info; | 839 | struct btrfs_fs_info *info = root->fs_info; |
| 841 | struct btrfs_root *extent_root = info->extent_root; | 840 | struct btrfs_root *extent_root = info->extent_root; |
| 841 | struct extent_buffer *leaf; | ||
| 842 | int ret; | 842 | int ret; |
| 843 | struct btrfs_extent_item *ei; | 843 | struct btrfs_extent_item *ei; |
| 844 | u32 refs; | 844 | u32 refs; |
| 845 | 845 | ||
| 846 | key.objectid = blocknr; | 846 | key.objectid = blocknr; |
| 847 | key.flags = 0; | ||
| 848 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 847 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
| 849 | key.offset = num_blocks; | 848 | key.offset = num_blocks; |
| 850 | 849 | ||
| @@ -856,12 +855,16 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 856 | if (ret < 0) | 855 | if (ret < 0) |
| 857 | return ret; | 856 | return ret; |
| 858 | BUG_ON(ret); | 857 | BUG_ON(ret); |
| 859 | ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | 858 | |
| 859 | leaf = path->nodes[0]; | ||
| 860 | ei = btrfs_item_ptr(leaf, path->slots[0], | ||
| 860 | struct btrfs_extent_item); | 861 | struct btrfs_extent_item); |
| 861 | BUG_ON(ei->refs == 0); | 862 | refs = btrfs_extent_refs(leaf, ei); |
| 862 | refs = btrfs_extent_refs(ei) - 1; | 863 | BUG_ON(refs == 0); |
| 863 | btrfs_set_extent_refs(ei, refs); | 864 | refs -= 1; |
| 864 | btrfs_mark_buffer_dirty(path->nodes[0]); | 865 | btrfs_set_extent_refs(leaf, ei, refs); |
| 866 | btrfs_mark_buffer_dirty(leaf); | ||
| 867 | |||
| 865 | if (refs == 0) { | 868 | if (refs == 0) { |
| 866 | u64 super_blocks_used, root_blocks_used; | 869 | u64 super_blocks_used, root_blocks_used; |
| 867 | 870 | ||
| @@ -876,8 +879,8 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 876 | super_blocks_used - num_blocks); | 879 | super_blocks_used - num_blocks); |
| 877 | 880 | ||
| 878 | /* block accounting for root item */ | 881 | /* block accounting for root item */ |
| 879 | root_blocks_used = btrfs_root_blocks_used(&root->root_item); | 882 | root_blocks_used = btrfs_root_used(&root->root_item); |
| 880 | btrfs_set_root_blocks_used(&root->root_item, | 883 | btrfs_set_root_used(&root->root_item, |
| 881 | root_blocks_used - num_blocks); | 884 | root_blocks_used - num_blocks); |
| 882 | 885 | ||
| 883 | ret = btrfs_del_item(trans, extent_root, path); | 886 | ret = btrfs_del_item(trans, extent_root, path); |
| @@ -984,7 +987,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 984 | u64 test_block; | 987 | u64 test_block; |
| 985 | u64 orig_search_start = search_start; | 988 | u64 orig_search_start = search_start; |
| 986 | int start_found; | 989 | int start_found; |
| 987 | struct btrfs_leaf *l; | 990 | struct extent_buffer *l; |
| 988 | struct btrfs_root * root = orig_root->fs_info->extent_root; | 991 | struct btrfs_root * root = orig_root->fs_info->extent_root; |
| 989 | struct btrfs_fs_info *info = root->fs_info; | 992 | struct btrfs_fs_info *info = root->fs_info; |
| 990 | int total_needed = num_blocks; | 993 | int total_needed = num_blocks; |
| @@ -994,10 +997,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 994 | int wrapped = 0; | 997 | int wrapped = 0; |
| 995 | 998 | ||
| 996 | WARN_ON(num_blocks < 1); | 999 | WARN_ON(num_blocks < 1); |
| 997 | ins->flags = 0; | ||
| 998 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); | 1000 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); |
| 999 | 1001 | ||
| 1000 | level = btrfs_header_level(btrfs_buffer_header(root->node)); | 1002 | level = btrfs_header_level(root->node); |
| 1003 | |||
| 1001 | if (search_end == (u64)-1) | 1004 | if (search_end == (u64)-1) |
| 1002 | search_end = btrfs_super_total_blocks(&info->super_copy); | 1005 | search_end = btrfs_super_total_blocks(&info->super_copy); |
| 1003 | if (hint_block) { | 1006 | if (hint_block) { |
| @@ -1034,8 +1037,9 @@ check_failed: | |||
| 1034 | path->slots[0]--; | 1037 | path->slots[0]--; |
| 1035 | } | 1038 | } |
| 1036 | 1039 | ||
| 1037 | l = btrfs_buffer_leaf(path->nodes[0]); | 1040 | l = path->nodes[0]; |
| 1038 | btrfs_disk_key_to_cpu(&key, &l->items[path->slots[0]].key); | 1041 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); |
| 1042 | |||
| 1039 | /* | 1043 | /* |
| 1040 | * a rare case, go back one key if we hit a block group item | 1044 | * a rare case, go back one key if we hit a block group item |
| 1041 | * instead of an extent item | 1045 | * instead of an extent item |
| @@ -1055,9 +1059,9 @@ check_failed: | |||
| 1055 | } | 1059 | } |
| 1056 | 1060 | ||
| 1057 | while (1) { | 1061 | while (1) { |
| 1058 | l = btrfs_buffer_leaf(path->nodes[0]); | 1062 | l = path->nodes[0]; |
| 1059 | slot = path->slots[0]; | 1063 | slot = path->slots[0]; |
| 1060 | if (slot >= btrfs_header_nritems(&l->header)) { | 1064 | if (slot >= btrfs_header_nritems(l)) { |
| 1061 | ret = btrfs_next_leaf(root, path); | 1065 | ret = btrfs_next_leaf(root, path); |
| 1062 | if (ret == 0) | 1066 | if (ret == 0) |
| 1063 | continue; | 1067 | continue; |
| @@ -1075,7 +1079,7 @@ check_failed: | |||
| 1075 | goto check_pending; | 1079 | goto check_pending; |
| 1076 | } | 1080 | } |
| 1077 | 1081 | ||
| 1078 | btrfs_disk_key_to_cpu(&key, &l->items[slot].key); | 1082 | btrfs_item_key_to_cpu(l, &key, slot); |
| 1079 | if (key.objectid >= search_start && key.objectid > last_block && | 1083 | if (key.objectid >= search_start && key.objectid > last_block && |
| 1080 | start_found) { | 1084 | start_found) { |
| 1081 | if (last_block < search_start) | 1085 | if (last_block < search_start) |
| @@ -1183,8 +1187,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
| 1183 | struct btrfs_root *extent_root = info->extent_root; | 1187 | struct btrfs_root *extent_root = info->extent_root; |
| 1184 | struct btrfs_extent_item extent_item; | 1188 | struct btrfs_extent_item extent_item; |
| 1185 | 1189 | ||
| 1186 | btrfs_set_extent_refs(&extent_item, 1); | 1190 | btrfs_set_stack_extent_refs(&extent_item, 1); |
| 1187 | btrfs_set_extent_owner(&extent_item, owner); | 1191 | btrfs_set_stack_extent_owner(&extent_item, owner); |
| 1188 | 1192 | ||
| 1189 | WARN_ON(num_blocks < 1); | 1193 | WARN_ON(num_blocks < 1); |
| 1190 | ret = find_free_extent(trans, root, num_blocks, empty_size, | 1194 | ret = find_free_extent(trans, root, num_blocks, empty_size, |
| @@ -1201,8 +1205,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
| 1201 | num_blocks); | 1205 | num_blocks); |
| 1202 | 1206 | ||
| 1203 | /* block accounting for root item */ | 1207 | /* block accounting for root item */ |
| 1204 | root_blocks_used = btrfs_root_blocks_used(&root->root_item); | 1208 | root_blocks_used = btrfs_root_used(&root->root_item); |
| 1205 | btrfs_set_root_blocks_used(&root->root_item, root_blocks_used + | 1209 | btrfs_set_root_used(&root->root_item, root_blocks_used + |
| 1206 | num_blocks); | 1210 | num_blocks); |
| 1207 | 1211 | ||
| 1208 | if (root == extent_root) { | 1212 | if (root == extent_root) { |
| @@ -1241,13 +1245,13 @@ update_block: | |||
| 1241 | * helper function to allocate a block for a given tree | 1245 | * helper function to allocate a block for a given tree |
| 1242 | * returns the tree buffer or NULL. | 1246 | * returns the tree buffer or NULL. |
| 1243 | */ | 1247 | */ |
| 1244 | struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 1248 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
| 1245 | struct btrfs_root *root, u64 hint, | 1249 | struct btrfs_root *root, u64 hint, |
| 1246 | u64 empty_size) | 1250 | u64 empty_size) |
| 1247 | { | 1251 | { |
| 1248 | struct btrfs_key ins; | 1252 | struct btrfs_key ins; |
| 1249 | int ret; | 1253 | int ret; |
| 1250 | struct buffer_head *buf; | 1254 | struct extent_buffer *buf; |
| 1251 | 1255 | ||
| 1252 | ret = btrfs_alloc_extent(trans, root, root->root_key.objectid, | 1256 | ret = btrfs_alloc_extent(trans, root, root->root_key.objectid, |
| 1253 | 1, empty_size, hint, (u64)-1, &ins, 0); | 1257 | 1, empty_size, hint, (u64)-1, &ins, 0); |
| @@ -1260,53 +1264,57 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
| 1260 | btrfs_free_extent(trans, root, ins.objectid, 1, 0); | 1264 | btrfs_free_extent(trans, root, ins.objectid, 1, 0); |
| 1261 | return ERR_PTR(-ENOMEM); | 1265 | return ERR_PTR(-ENOMEM); |
| 1262 | } | 1266 | } |
| 1263 | WARN_ON(buffer_dirty(buf)); | 1267 | btrfs_set_buffer_uptodate(buf); |
| 1264 | set_buffer_uptodate(buf); | 1268 | set_extent_dirty(&trans->transaction->dirty_pages, buf->start, |
| 1269 | buf->start + buf->len - 1, GFP_NOFS); | ||
| 1270 | /* | ||
| 1265 | set_buffer_checked(buf); | 1271 | set_buffer_checked(buf); |
| 1266 | set_buffer_defrag(buf); | 1272 | set_buffer_defrag(buf); |
| 1267 | set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index); | 1273 | */ |
| 1274 | /* FIXME!!!!!!!!!!!!!!!! | ||
| 1275 | set_radix_bit(&trans->transaction->dirty_pages, buf->pages[0]->index); | ||
| 1276 | */ | ||
| 1268 | trans->blocks_used++; | 1277 | trans->blocks_used++; |
| 1269 | return buf; | 1278 | return buf; |
| 1270 | } | 1279 | } |
| 1271 | 1280 | ||
| 1272 | static int drop_leaf_ref(struct btrfs_trans_handle *trans, | 1281 | static int drop_leaf_ref(struct btrfs_trans_handle *trans, |
| 1273 | struct btrfs_root *root, struct buffer_head *cur) | 1282 | struct btrfs_root *root, struct extent_buffer *leaf) |
| 1274 | { | 1283 | { |
| 1275 | struct btrfs_disk_key *key; | 1284 | struct btrfs_key key; |
| 1276 | struct btrfs_leaf *leaf; | ||
| 1277 | struct btrfs_file_extent_item *fi; | 1285 | struct btrfs_file_extent_item *fi; |
| 1278 | int i; | 1286 | int i; |
| 1279 | int nritems; | 1287 | int nritems; |
| 1280 | int ret; | 1288 | int ret; |
| 1281 | 1289 | ||
| 1282 | BUG_ON(!btrfs_is_leaf(btrfs_buffer_node(cur))); | 1290 | BUG_ON(!btrfs_is_leaf(leaf)); |
| 1283 | leaf = btrfs_buffer_leaf(cur); | 1291 | nritems = btrfs_header_nritems(leaf); |
| 1284 | nritems = btrfs_header_nritems(&leaf->header); | ||
| 1285 | for (i = 0; i < nritems; i++) { | 1292 | for (i = 0; i < nritems; i++) { |
| 1286 | u64 disk_blocknr; | 1293 | u64 disk_blocknr; |
| 1287 | key = &leaf->items[i].key; | 1294 | |
| 1288 | if (btrfs_disk_key_type(key) != BTRFS_EXTENT_DATA_KEY) | 1295 | btrfs_item_key_to_cpu(leaf, &key, i); |
| 1296 | if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY) | ||
| 1289 | continue; | 1297 | continue; |
| 1290 | fi = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item); | 1298 | fi = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item); |
| 1291 | if (btrfs_file_extent_type(fi) == BTRFS_FILE_EXTENT_INLINE) | 1299 | if (btrfs_file_extent_type(leaf, fi) == |
| 1300 | BTRFS_FILE_EXTENT_INLINE) | ||
| 1292 | continue; | 1301 | continue; |
| 1293 | /* | 1302 | /* |
| 1294 | * FIXME make sure to insert a trans record that | 1303 | * FIXME make sure to insert a trans record that |
| 1295 | * repeats the snapshot del on crash | 1304 | * repeats the snapshot del on crash |
| 1296 | */ | 1305 | */ |
| 1297 | disk_blocknr = btrfs_file_extent_disk_blocknr(fi); | 1306 | disk_blocknr = btrfs_file_extent_disk_blocknr(leaf, fi); |
| 1298 | if (disk_blocknr == 0) | 1307 | if (disk_blocknr == 0) |
| 1299 | continue; | 1308 | continue; |
| 1300 | ret = btrfs_free_extent(trans, root, disk_blocknr, | 1309 | ret = btrfs_free_extent(trans, root, disk_blocknr, |
| 1301 | btrfs_file_extent_disk_num_blocks(fi), | 1310 | btrfs_file_extent_disk_num_blocks(leaf, fi), 0); |
| 1302 | 0); | ||
| 1303 | BUG_ON(ret); | 1311 | BUG_ON(ret); |
| 1304 | } | 1312 | } |
| 1305 | return 0; | 1313 | return 0; |
| 1306 | } | 1314 | } |
| 1307 | 1315 | ||
| 1308 | static void reada_walk_down(struct btrfs_root *root, | 1316 | static void reada_walk_down(struct btrfs_root *root, |
| 1309 | struct btrfs_node *node) | 1317 | struct extent_buffer *node) |
| 1310 | { | 1318 | { |
| 1311 | int i; | 1319 | int i; |
| 1312 | u32 nritems; | 1320 | u32 nritems; |
| @@ -1314,7 +1322,7 @@ static void reada_walk_down(struct btrfs_root *root, | |||
| 1314 | int ret; | 1322 | int ret; |
| 1315 | u32 refs; | 1323 | u32 refs; |
| 1316 | 1324 | ||
| 1317 | nritems = btrfs_header_nritems(&node->header); | 1325 | nritems = btrfs_header_nritems(node); |
| 1318 | for (i = 0; i < nritems; i++) { | 1326 | for (i = 0; i < nritems; i++) { |
| 1319 | blocknr = btrfs_node_blockptr(node, i); | 1327 | blocknr = btrfs_node_blockptr(node, i); |
| 1320 | ret = lookup_extent_ref(NULL, root, blocknr, 1, &refs); | 1328 | ret = lookup_extent_ref(NULL, root, blocknr, 1, &refs); |
| @@ -1337,16 +1345,17 @@ static void reada_walk_down(struct btrfs_root *root, | |||
| 1337 | static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | 1345 | static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root |
| 1338 | *root, struct btrfs_path *path, int *level) | 1346 | *root, struct btrfs_path *path, int *level) |
| 1339 | { | 1347 | { |
| 1340 | struct buffer_head *next; | 1348 | struct extent_buffer *next; |
| 1341 | struct buffer_head *cur; | 1349 | struct extent_buffer *cur; |
| 1342 | u64 blocknr; | 1350 | u64 blocknr; |
| 1343 | int ret; | 1351 | int ret; |
| 1344 | u32 refs; | 1352 | u32 refs; |
| 1345 | 1353 | ||
| 1346 | WARN_ON(*level < 0); | 1354 | WARN_ON(*level < 0); |
| 1347 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | 1355 | WARN_ON(*level >= BTRFS_MAX_LEVEL); |
| 1348 | ret = lookup_extent_ref(trans, root, bh_blocknr(path->nodes[*level]), | 1356 | ret = lookup_extent_ref(trans, root, |
| 1349 | 1, &refs); | 1357 | extent_buffer_blocknr(path->nodes[*level]), |
| 1358 | 1, &refs); | ||
| 1350 | BUG_ON(ret); | 1359 | BUG_ON(ret); |
| 1351 | if (refs > 1) | 1360 | if (refs > 1) |
| 1352 | goto out; | 1361 | goto out; |
| @@ -1360,21 +1369,20 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1360 | cur = path->nodes[*level]; | 1369 | cur = path->nodes[*level]; |
| 1361 | 1370 | ||
| 1362 | if (*level > 0 && path->slots[*level] == 0) | 1371 | if (*level > 0 && path->slots[*level] == 0) |
| 1363 | reada_walk_down(root, btrfs_buffer_node(cur)); | 1372 | reada_walk_down(root, cur); |
| 1364 | 1373 | ||
| 1365 | if (btrfs_header_level(btrfs_buffer_header(cur)) != *level) | 1374 | if (btrfs_header_level(cur) != *level) |
| 1366 | WARN_ON(1); | 1375 | WARN_ON(1); |
| 1367 | 1376 | ||
| 1368 | if (path->slots[*level] >= | 1377 | if (path->slots[*level] >= |
| 1369 | btrfs_header_nritems(btrfs_buffer_header(cur))) | 1378 | btrfs_header_nritems(cur)) |
| 1370 | break; | 1379 | break; |
| 1371 | if (*level == 0) { | 1380 | if (*level == 0) { |
| 1372 | ret = drop_leaf_ref(trans, root, cur); | 1381 | ret = drop_leaf_ref(trans, root, cur); |
| 1373 | BUG_ON(ret); | 1382 | BUG_ON(ret); |
| 1374 | break; | 1383 | break; |
| 1375 | } | 1384 | } |
| 1376 | blocknr = btrfs_node_blockptr(btrfs_buffer_node(cur), | 1385 | blocknr = btrfs_node_blockptr(cur, path->slots[*level]); |
| 1377 | path->slots[*level]); | ||
| 1378 | ret = lookup_extent_ref(trans, root, blocknr, 1, &refs); | 1386 | ret = lookup_extent_ref(trans, root, blocknr, 1, &refs); |
| 1379 | BUG_ON(ret); | 1387 | BUG_ON(ret); |
| 1380 | if (refs != 1) { | 1388 | if (refs != 1) { |
| @@ -1384,8 +1392,8 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1384 | continue; | 1392 | continue; |
| 1385 | } | 1393 | } |
| 1386 | next = btrfs_find_tree_block(root, blocknr); | 1394 | next = btrfs_find_tree_block(root, blocknr); |
| 1387 | if (!next || !buffer_uptodate(next)) { | 1395 | if (!next || !btrfs_buffer_uptodate(next)) { |
| 1388 | brelse(next); | 1396 | free_extent_buffer(next); |
| 1389 | mutex_unlock(&root->fs_info->fs_mutex); | 1397 | mutex_unlock(&root->fs_info->fs_mutex); |
| 1390 | next = read_tree_block(root, blocknr); | 1398 | next = read_tree_block(root, blocknr); |
| 1391 | mutex_lock(&root->fs_info->fs_mutex); | 1399 | mutex_lock(&root->fs_info->fs_mutex); |
| @@ -1395,7 +1403,7 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1395 | BUG_ON(ret); | 1403 | BUG_ON(ret); |
| 1396 | if (refs != 1) { | 1404 | if (refs != 1) { |
| 1397 | path->slots[*level]++; | 1405 | path->slots[*level]++; |
| 1398 | brelse(next); | 1406 | free_extent_buffer(next); |
| 1399 | ret = btrfs_free_extent(trans, root, | 1407 | ret = btrfs_free_extent(trans, root, |
| 1400 | blocknr, 1, 1); | 1408 | blocknr, 1, 1); |
| 1401 | BUG_ON(ret); | 1409 | BUG_ON(ret); |
| @@ -1404,17 +1412,17 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1404 | } | 1412 | } |
| 1405 | WARN_ON(*level <= 0); | 1413 | WARN_ON(*level <= 0); |
| 1406 | if (path->nodes[*level-1]) | 1414 | if (path->nodes[*level-1]) |
| 1407 | btrfs_block_release(root, path->nodes[*level-1]); | 1415 | free_extent_buffer(path->nodes[*level-1]); |
| 1408 | path->nodes[*level-1] = next; | 1416 | path->nodes[*level-1] = next; |
| 1409 | *level = btrfs_header_level(btrfs_buffer_header(next)); | 1417 | *level = btrfs_header_level(next); |
| 1410 | path->slots[*level] = 0; | 1418 | path->slots[*level] = 0; |
| 1411 | } | 1419 | } |
| 1412 | out: | 1420 | out: |
| 1413 | WARN_ON(*level < 0); | 1421 | WARN_ON(*level < 0); |
| 1414 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | 1422 | WARN_ON(*level >= BTRFS_MAX_LEVEL); |
| 1415 | ret = btrfs_free_extent(trans, root, | 1423 | ret = btrfs_free_extent(trans, root, |
| 1416 | bh_blocknr(path->nodes[*level]), 1, 1); | 1424 | extent_buffer_blocknr(path->nodes[*level]), 1, 1); |
| 1417 | btrfs_block_release(root, path->nodes[*level]); | 1425 | free_extent_buffer(path->nodes[*level]); |
| 1418 | path->nodes[*level] = NULL; | 1426 | path->nodes[*level] = NULL; |
| 1419 | *level += 1; | 1427 | *level += 1; |
| 1420 | BUG_ON(ret); | 1428 | BUG_ON(ret); |
| @@ -1436,24 +1444,24 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1436 | 1444 | ||
| 1437 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { | 1445 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { |
| 1438 | slot = path->slots[i]; | 1446 | slot = path->slots[i]; |
| 1439 | if (slot < btrfs_header_nritems( | 1447 | if (slot < btrfs_header_nritems(path->nodes[i]) - 1) { |
| 1440 | btrfs_buffer_header(path->nodes[i])) - 1) { | 1448 | struct extent_buffer *node; |
| 1441 | struct btrfs_node *node; | 1449 | struct btrfs_disk_key disk_key; |
| 1442 | node = btrfs_buffer_node(path->nodes[i]); | 1450 | node = path->nodes[i]; |
| 1443 | path->slots[i]++; | 1451 | path->slots[i]++; |
| 1444 | *level = i; | 1452 | *level = i; |
| 1445 | WARN_ON(*level == 0); | 1453 | WARN_ON(*level == 0); |
| 1454 | btrfs_node_key(node, &disk_key, path->slots[i]); | ||
| 1446 | memcpy(&root_item->drop_progress, | 1455 | memcpy(&root_item->drop_progress, |
| 1447 | &node->ptrs[path->slots[i]].key, | 1456 | &disk_key, sizeof(disk_key)); |
| 1448 | sizeof(root_item->drop_progress)); | ||
| 1449 | root_item->drop_level = i; | 1457 | root_item->drop_level = i; |
| 1450 | return 0; | 1458 | return 0; |
| 1451 | } else { | 1459 | } else { |
| 1452 | ret = btrfs_free_extent(trans, root, | 1460 | ret = btrfs_free_extent(trans, root, |
| 1453 | bh_blocknr(path->nodes[*level]), | 1461 | extent_buffer_blocknr(path->nodes[*level]), |
| 1454 | 1, 1); | 1462 | 1, 1); |
| 1455 | BUG_ON(ret); | 1463 | BUG_ON(ret); |
| 1456 | btrfs_block_release(root, path->nodes[*level]); | 1464 | free_extent_buffer(path->nodes[*level]); |
| 1457 | path->nodes[*level] = NULL; | 1465 | path->nodes[*level] = NULL; |
| 1458 | *level = i + 1; | 1466 | *level = i + 1; |
| 1459 | } | 1467 | } |
| @@ -1480,15 +1488,15 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1480 | path = btrfs_alloc_path(); | 1488 | path = btrfs_alloc_path(); |
| 1481 | BUG_ON(!path); | 1489 | BUG_ON(!path); |
| 1482 | 1490 | ||
| 1483 | level = btrfs_header_level(btrfs_buffer_header(root->node)); | 1491 | level = btrfs_header_level(root->node); |
| 1484 | orig_level = level; | 1492 | orig_level = level; |
| 1485 | if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) { | 1493 | if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) { |
| 1486 | path->nodes[level] = root->node; | 1494 | path->nodes[level] = root->node; |
| 1487 | path->slots[level] = 0; | 1495 | path->slots[level] = 0; |
| 1488 | } else { | 1496 | } else { |
| 1489 | struct btrfs_key key; | 1497 | struct btrfs_key key; |
| 1490 | struct btrfs_disk_key *found_key; | 1498 | struct btrfs_disk_key found_key; |
| 1491 | struct btrfs_node *node; | 1499 | struct extent_buffer *node; |
| 1492 | 1500 | ||
| 1493 | btrfs_disk_key_to_cpu(&key, &root_item->drop_progress); | 1501 | btrfs_disk_key_to_cpu(&key, &root_item->drop_progress); |
| 1494 | level = root_item->drop_level; | 1502 | level = root_item->drop_level; |
| @@ -1498,10 +1506,10 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1498 | ret = wret; | 1506 | ret = wret; |
| 1499 | goto out; | 1507 | goto out; |
| 1500 | } | 1508 | } |
| 1501 | node = btrfs_buffer_node(path->nodes[level]); | 1509 | node = path->nodes[level]; |
| 1502 | found_key = &node->ptrs[path->slots[level]].key; | 1510 | btrfs_node_key(node, &found_key, path->slots[level]); |
| 1503 | WARN_ON(memcmp(found_key, &root_item->drop_progress, | 1511 | WARN_ON(memcmp(&found_key, &root_item->drop_progress, |
| 1504 | sizeof(*found_key))); | 1512 | sizeof(found_key))); |
| 1505 | } | 1513 | } |
| 1506 | while(1) { | 1514 | while(1) { |
| 1507 | wret = walk_down_tree(trans, root, path, &level); | 1515 | wret = walk_down_tree(trans, root, path, &level); |
| @@ -1516,12 +1524,12 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1516 | if (wret < 0) | 1524 | if (wret < 0) |
| 1517 | ret = wret; | 1525 | ret = wret; |
| 1518 | ret = -EAGAIN; | 1526 | ret = -EAGAIN; |
| 1519 | get_bh(root->node); | 1527 | extent_buffer_get(root->node); |
| 1520 | break; | 1528 | break; |
| 1521 | } | 1529 | } |
| 1522 | for (i = 0; i <= orig_level; i++) { | 1530 | for (i = 0; i <= orig_level; i++) { |
| 1523 | if (path->nodes[i]) { | 1531 | if (path->nodes[i]) { |
| 1524 | btrfs_block_release(root, path->nodes[i]); | 1532 | free_extent_buffer(path->nodes[i]); |
| 1525 | path->nodes[i] = 0; | 1533 | path->nodes[i] = 0; |
| 1526 | } | 1534 | } |
| 1527 | } | 1535 | } |
| @@ -1581,13 +1589,12 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
| 1581 | struct btrfs_path *path; | 1589 | struct btrfs_path *path; |
| 1582 | int ret; | 1590 | int ret; |
| 1583 | int err = 0; | 1591 | int err = 0; |
| 1584 | struct btrfs_block_group_item *bi; | ||
| 1585 | struct btrfs_block_group_cache *cache; | 1592 | struct btrfs_block_group_cache *cache; |
| 1586 | struct btrfs_fs_info *info = root->fs_info; | 1593 | struct btrfs_fs_info *info = root->fs_info; |
| 1587 | struct radix_tree_root *radix; | 1594 | struct radix_tree_root *radix; |
| 1588 | struct btrfs_key key; | 1595 | struct btrfs_key key; |
| 1589 | struct btrfs_key found_key; | 1596 | struct btrfs_key found_key; |
| 1590 | struct btrfs_leaf *leaf; | 1597 | struct extent_buffer *leaf; |
| 1591 | u64 group_size_blocks; | 1598 | u64 group_size_blocks; |
| 1592 | u64 used; | 1599 | u64 used; |
| 1593 | 1600 | ||
| @@ -1596,7 +1603,6 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
| 1596 | root = info->extent_root; | 1603 | root = info->extent_root; |
| 1597 | key.objectid = 0; | 1604 | key.objectid = 0; |
| 1598 | key.offset = group_size_blocks; | 1605 | key.offset = group_size_blocks; |
| 1599 | key.flags = 0; | ||
| 1600 | btrfs_set_key_type(&key, BTRFS_BLOCK_GROUP_ITEM_KEY); | 1606 | btrfs_set_key_type(&key, BTRFS_BLOCK_GROUP_ITEM_KEY); |
| 1601 | 1607 | ||
| 1602 | path = btrfs_alloc_path(); | 1608 | path = btrfs_alloc_path(); |
| @@ -1610,18 +1616,18 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
| 1610 | err = ret; | 1616 | err = ret; |
| 1611 | break; | 1617 | break; |
| 1612 | } | 1618 | } |
| 1613 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 1619 | leaf = path->nodes[0]; |
| 1614 | btrfs_disk_key_to_cpu(&found_key, | 1620 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
| 1615 | &leaf->items[path->slots[0]].key); | ||
| 1616 | cache = kmalloc(sizeof(*cache), GFP_NOFS); | 1621 | cache = kmalloc(sizeof(*cache), GFP_NOFS); |
| 1617 | if (!cache) { | 1622 | if (!cache) { |
| 1618 | err = -1; | 1623 | err = -1; |
| 1619 | break; | 1624 | break; |
| 1620 | } | 1625 | } |
| 1621 | 1626 | ||
| 1622 | bi = btrfs_item_ptr(leaf, path->slots[0], | 1627 | read_extent_buffer(leaf, &cache->item, |
| 1623 | struct btrfs_block_group_item); | 1628 | btrfs_item_ptr_offset(leaf, path->slots[0]), |
| 1624 | if (bi->flags & BTRFS_BLOCK_GROUP_DATA) { | 1629 | sizeof(cache->item)); |
| 1630 | if (cache->item.flags & BTRFS_BLOCK_GROUP_DATA) { | ||
| 1625 | radix = &info->block_group_data_radix; | 1631 | radix = &info->block_group_data_radix; |
| 1626 | cache->data = 1; | 1632 | cache->data = 1; |
| 1627 | } else { | 1633 | } else { |
| @@ -1629,7 +1635,6 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
| 1629 | cache->data = 0; | 1635 | cache->data = 0; |
| 1630 | } | 1636 | } |
| 1631 | 1637 | ||
| 1632 | memcpy(&cache->item, bi, sizeof(*bi)); | ||
| 1633 | memcpy(&cache->key, &found_key, sizeof(found_key)); | 1638 | memcpy(&cache->key, &found_key, sizeof(found_key)); |
| 1634 | cache->last_alloc = cache->key.objectid; | 1639 | cache->last_alloc = cache->key.objectid; |
| 1635 | cache->first_free = cache->key.objectid; | 1640 | cache->first_free = cache->key.objectid; |
| @@ -1640,11 +1645,12 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
| 1640 | 1645 | ||
| 1641 | key.objectid = found_key.objectid + found_key.offset; | 1646 | key.objectid = found_key.objectid + found_key.offset; |
| 1642 | btrfs_release_path(root, path); | 1647 | btrfs_release_path(root, path); |
| 1648 | |||
| 1643 | ret = radix_tree_insert(radix, found_key.objectid + | 1649 | ret = radix_tree_insert(radix, found_key.objectid + |
| 1644 | found_key.offset - 1, | 1650 | found_key.offset - 1, |
| 1645 | (void *)cache); | 1651 | (void *)cache); |
| 1646 | BUG_ON(ret); | 1652 | BUG_ON(ret); |
| 1647 | used = btrfs_block_group_used(bi); | 1653 | used = btrfs_block_group_used(&cache->item); |
| 1648 | if (used < div_factor(key.offset, 8)) { | 1654 | if (used < div_factor(key.offset, 8)) { |
| 1649 | radix_tree_tag_set(radix, found_key.objectid + | 1655 | radix_tree_tag_set(radix, found_key.objectid + |
| 1650 | found_key.offset - 1, | 1656 | found_key.offset - 1, |
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 0ab368e091f9..55fefdfab84c 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
| @@ -26,16 +26,6 @@ struct tree_entry { | |||
| 26 | struct rb_node rb_node; | 26 | struct rb_node rb_node; |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | /* bits for the extent state */ | ||
| 30 | #define EXTENT_DIRTY 1 | ||
| 31 | #define EXTENT_WRITEBACK (1 << 1) | ||
| 32 | #define EXTENT_UPTODATE (1 << 2) | ||
| 33 | #define EXTENT_LOCKED (1 << 3) | ||
| 34 | #define EXTENT_NEW (1 << 4) | ||
| 35 | #define EXTENT_DELALLOC (1 << 5) | ||
| 36 | |||
| 37 | #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) | ||
| 38 | |||
| 39 | void __init extent_map_init(void) | 29 | void __init extent_map_init(void) |
| 40 | { | 30 | { |
| 41 | extent_map_cache = btrfs_cache_create("extent_map", | 31 | extent_map_cache = btrfs_cache_create("extent_map", |
| @@ -223,7 +213,8 @@ int add_extent_mapping(struct extent_map_tree *tree, | |||
| 223 | if (rb) | 213 | if (rb) |
| 224 | prev = rb_entry(rb, struct extent_map, rb_node); | 214 | prev = rb_entry(rb, struct extent_map, rb_node); |
| 225 | if (prev && prev->end + 1 == em->start && | 215 | if (prev && prev->end + 1 == em->start && |
| 226 | ((em->block_start == 0 && prev->block_start == 0) || | 216 | ((em->block_start == EXTENT_MAP_HOLE && |
| 217 | prev->block_start == EXTENT_MAP_HOLE) || | ||
| 227 | (em->block_start == prev->block_end + 1))) { | 218 | (em->block_start == prev->block_end + 1))) { |
| 228 | em->start = prev->start; | 219 | em->start = prev->start; |
| 229 | em->block_start = prev->block_start; | 220 | em->block_start = prev->block_start; |
| @@ -926,6 +917,40 @@ int set_range_writeback(struct extent_map_tree *tree, u64 start, u64 end) | |||
| 926 | } | 917 | } |
| 927 | EXPORT_SYMBOL(set_range_writeback); | 918 | EXPORT_SYMBOL(set_range_writeback); |
| 928 | 919 | ||
| 920 | int find_first_extent_bit(struct extent_map_tree *tree, u64 start, | ||
| 921 | u64 *start_ret, u64 *end_ret, int bits) | ||
| 922 | { | ||
| 923 | struct rb_node *node; | ||
| 924 | struct extent_state *state; | ||
| 925 | int ret = 1; | ||
| 926 | |||
| 927 | write_lock_irq(&tree->lock); | ||
| 928 | /* | ||
| 929 | * this search will find all the extents that end after | ||
| 930 | * our range starts. | ||
| 931 | */ | ||
| 932 | node = tree_search(&tree->state, start); | ||
| 933 | if (!node || IS_ERR(node)) { | ||
| 934 | goto out; | ||
| 935 | } | ||
| 936 | |||
| 937 | while(1) { | ||
| 938 | state = rb_entry(node, struct extent_state, rb_node); | ||
| 939 | if (state->state & bits) { | ||
| 940 | *start_ret = state->start; | ||
| 941 | *end_ret = state->end; | ||
| 942 | ret = 0; | ||
| 943 | } | ||
| 944 | node = rb_next(node); | ||
| 945 | if (!node) | ||
| 946 | break; | ||
| 947 | } | ||
| 948 | out: | ||
| 949 | write_unlock_irq(&tree->lock); | ||
| 950 | return ret; | ||
| 951 | } | ||
| 952 | EXPORT_SYMBOL(find_first_extent_bit); | ||
| 953 | |||
| 929 | u64 find_lock_delalloc_range(struct extent_map_tree *tree, | 954 | u64 find_lock_delalloc_range(struct extent_map_tree *tree, |
| 930 | u64 start, u64 lock_start, u64 *end, u64 max_bytes) | 955 | u64 start, u64 lock_start, u64 *end, u64 max_bytes) |
| 931 | { | 956 | { |
| @@ -1450,7 +1475,7 @@ int extent_read_full_page(struct extent_map_tree *tree, struct page *page, | |||
| 1450 | em = NULL; | 1475 | em = NULL; |
| 1451 | 1476 | ||
| 1452 | /* we've found a hole, just zero and go on */ | 1477 | /* we've found a hole, just zero and go on */ |
| 1453 | if (block_start == 0) { | 1478 | if (block_start == EXTENT_MAP_HOLE) { |
| 1454 | zero_user_page(page, page_offset, iosize, KM_USER0); | 1479 | zero_user_page(page, page_offset, iosize, KM_USER0); |
| 1455 | set_extent_uptodate(tree, cur, cur + iosize - 1, | 1480 | set_extent_uptodate(tree, cur, cur + iosize - 1, |
| 1456 | GFP_NOFS); | 1481 | GFP_NOFS); |
| @@ -1593,7 +1618,8 @@ int extent_write_full_page(struct extent_map_tree *tree, struct page *page, | |||
| 1593 | free_extent_map(em); | 1618 | free_extent_map(em); |
| 1594 | em = NULL; | 1619 | em = NULL; |
| 1595 | 1620 | ||
| 1596 | if (block_start == 0 || block_start == EXTENT_MAP_INLINE) { | 1621 | if (block_start == EXTENT_MAP_HOLE || |
| 1622 | block_start == EXTENT_MAP_INLINE) { | ||
| 1597 | clear_extent_dirty(tree, cur, | 1623 | clear_extent_dirty(tree, cur, |
| 1598 | cur + iosize - 1, GFP_NOFS); | 1624 | cur + iosize - 1, GFP_NOFS); |
| 1599 | cur = cur + iosize; | 1625 | cur = cur + iosize; |
| @@ -1630,7 +1656,6 @@ int extent_write_full_page(struct extent_map_tree *tree, struct page *page, | |||
| 1630 | nr++; | 1656 | nr++; |
| 1631 | } | 1657 | } |
| 1632 | done: | 1658 | done: |
| 1633 | WARN_ON(test_range_bit(tree, start, page_end, EXTENT_DIRTY, 0)); | ||
| 1634 | unlock_extent(tree, start, page_end, GFP_NOFS); | 1659 | unlock_extent(tree, start, page_end, GFP_NOFS); |
| 1635 | unlock_page(page); | 1660 | unlock_page(page); |
| 1636 | return 0; | 1661 | return 0; |
| @@ -1827,8 +1852,623 @@ sector_t extent_bmap(struct address_space *mapping, sector_t iblock, | |||
| 1827 | 1852 | ||
| 1828 | // XXX(hch): block 0 is valid in some cases, e.g. XFS RT device | 1853 | // XXX(hch): block 0 is valid in some cases, e.g. XFS RT device |
| 1829 | if (em->block_start == EXTENT_MAP_INLINE || | 1854 | if (em->block_start == EXTENT_MAP_INLINE || |
| 1830 | em->block_start == 0) | 1855 | em->block_start == EXTENT_MAP_HOLE) |
| 1831 | return 0; | 1856 | return 0; |
| 1832 | 1857 | ||
| 1833 | return (em->block_start + start - em->start) >> inode->i_blkbits; | 1858 | return (em->block_start + start - em->start) >> inode->i_blkbits; |
| 1834 | } | 1859 | } |
| 1860 | |||
| 1861 | struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree, | ||
| 1862 | u64 start, unsigned long len, | ||
| 1863 | gfp_t mask) | ||
| 1864 | { | ||
| 1865 | unsigned long num_pages = ((start + len - 1) >> PAGE_CACHE_SHIFT) - | ||
| 1866 | (start >> PAGE_CACHE_SHIFT) + 1; | ||
| 1867 | unsigned long i; | ||
| 1868 | unsigned long index = start >> PAGE_CACHE_SHIFT; | ||
| 1869 | struct extent_buffer *eb; | ||
| 1870 | struct page *p; | ||
| 1871 | struct address_space *mapping = tree->mapping; | ||
| 1872 | int uptodate = 0; | ||
| 1873 | |||
| 1874 | eb = kzalloc(EXTENT_BUFFER_SIZE(num_pages), mask); | ||
| 1875 | if (!eb || IS_ERR(eb)) | ||
| 1876 | return NULL; | ||
| 1877 | |||
| 1878 | eb->start = start; | ||
| 1879 | eb->len = len; | ||
| 1880 | atomic_set(&eb->refs, 1); | ||
| 1881 | |||
| 1882 | for (i = 0; i < num_pages; i++, index++) { | ||
| 1883 | p = find_or_create_page(mapping, index, mask | __GFP_HIGHMEM); | ||
| 1884 | if (!p) | ||
| 1885 | goto fail; | ||
| 1886 | eb->pages[i] = p; | ||
| 1887 | if (!PageUptodate(p)) | ||
| 1888 | uptodate = 0; | ||
| 1889 | unlock_page(p); | ||
| 1890 | } | ||
| 1891 | if (uptodate) | ||
| 1892 | eb->flags |= EXTENT_UPTODATE; | ||
| 1893 | return eb; | ||
| 1894 | fail: | ||
| 1895 | free_extent_buffer(eb); | ||
| 1896 | return NULL; | ||
| 1897 | } | ||
| 1898 | EXPORT_SYMBOL(alloc_extent_buffer); | ||
| 1899 | |||
| 1900 | struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree, | ||
| 1901 | u64 start, unsigned long len, | ||
| 1902 | gfp_t mask) | ||
| 1903 | { | ||
| 1904 | unsigned long num_pages = ((start + len - 1) >> PAGE_CACHE_SHIFT) - | ||
| 1905 | (start >> PAGE_CACHE_SHIFT) + 1; | ||
| 1906 | unsigned long i; | ||
| 1907 | unsigned long index = start >> PAGE_CACHE_SHIFT; | ||
| 1908 | struct extent_buffer *eb; | ||
| 1909 | struct page *p; | ||
| 1910 | struct address_space *mapping = tree->mapping; | ||
| 1911 | |||
| 1912 | eb = kzalloc(EXTENT_BUFFER_SIZE(num_pages), mask); | ||
| 1913 | if (!eb || IS_ERR(eb)) | ||
| 1914 | return NULL; | ||
| 1915 | |||
| 1916 | eb->start = start; | ||
| 1917 | eb->len = len; | ||
| 1918 | atomic_set(&eb->refs, 1); | ||
| 1919 | |||
| 1920 | for (i = 0; i < num_pages; i++, index++) { | ||
| 1921 | p = find_get_page(mapping, index); | ||
| 1922 | if (!p) | ||
| 1923 | goto fail; | ||
| 1924 | eb->pages[i] = p; | ||
| 1925 | } | ||
| 1926 | return eb; | ||
| 1927 | fail: | ||
| 1928 | free_extent_buffer(eb); | ||
| 1929 | return NULL; | ||
| 1930 | } | ||
| 1931 | EXPORT_SYMBOL(find_extent_buffer); | ||
| 1932 | |||
| 1933 | void free_extent_buffer(struct extent_buffer *eb) | ||
| 1934 | { | ||
| 1935 | unsigned long i; | ||
| 1936 | unsigned long num_pages; | ||
| 1937 | |||
| 1938 | if (!eb) | ||
| 1939 | return; | ||
| 1940 | |||
| 1941 | if (!atomic_dec_and_test(&eb->refs)) | ||
| 1942 | return; | ||
| 1943 | |||
| 1944 | num_pages = ((eb->start + eb->len - 1) >> PAGE_CACHE_SHIFT) - | ||
| 1945 | (eb->start >> PAGE_CACHE_SHIFT) + 1; | ||
| 1946 | |||
| 1947 | for (i = 0; i < num_pages; i++) { | ||
| 1948 | if (eb->pages[i]) | ||
| 1949 | page_cache_release(eb->pages[i]); | ||
| 1950 | } | ||
| 1951 | kfree(eb); | ||
| 1952 | } | ||
| 1953 | EXPORT_SYMBOL(free_extent_buffer); | ||
| 1954 | |||
| 1955 | int clear_extent_buffer_dirty(struct extent_map_tree *tree, | ||
| 1956 | struct extent_buffer *eb) | ||
| 1957 | { | ||
| 1958 | int set; | ||
| 1959 | unsigned long i; | ||
| 1960 | unsigned long num_pages; | ||
| 1961 | struct page *page; | ||
| 1962 | |||
| 1963 | u64 start = eb->start; | ||
| 1964 | u64 end = start + eb->len - 1; | ||
| 1965 | |||
| 1966 | set = clear_extent_dirty(tree, start, end, GFP_NOFS); | ||
| 1967 | num_pages = ((eb->start + eb->len - 1) >> PAGE_CACHE_SHIFT) - | ||
| 1968 | (eb->start >> PAGE_CACHE_SHIFT) + 1; | ||
| 1969 | |||
| 1970 | for (i = 0; i < num_pages; i++) { | ||
| 1971 | page = eb->pages[i]; | ||
| 1972 | lock_page(page); | ||
| 1973 | /* | ||
| 1974 | * if we're on the last page or the first page and the | ||
| 1975 | * block isn't aligned on a page boundary, do extra checks | ||
| 1976 | * to make sure we don't clean page that is partially dirty | ||
| 1977 | */ | ||
| 1978 | if ((i == 0 && (eb->start & (PAGE_CACHE_SIZE - 1))) || | ||
| 1979 | ((i == num_pages - 1) && | ||
| 1980 | ((eb->start + eb->len - 1) & (PAGE_CACHE_SIZE - 1)))) { | ||
| 1981 | start = page->index << PAGE_CACHE_SHIFT; | ||
| 1982 | end = start + PAGE_CACHE_SIZE - 1; | ||
| 1983 | if (test_range_bit(tree, start, end, | ||
| 1984 | EXTENT_DIRTY, 0)) { | ||
| 1985 | unlock_page(page); | ||
| 1986 | continue; | ||
| 1987 | } | ||
| 1988 | } | ||
| 1989 | clear_page_dirty_for_io(page); | ||
| 1990 | unlock_page(page); | ||
| 1991 | } | ||
| 1992 | return 0; | ||
| 1993 | } | ||
| 1994 | EXPORT_SYMBOL(clear_extent_buffer_dirty); | ||
| 1995 | |||
| 1996 | int wait_on_extent_buffer_writeback(struct extent_map_tree *tree, | ||
| 1997 | struct extent_buffer *eb) | ||
| 1998 | { | ||
| 1999 | return wait_on_extent_writeback(tree, eb->start, | ||
| 2000 | eb->start + eb->len - 1); | ||
| 2001 | } | ||
| 2002 | EXPORT_SYMBOL(wait_on_extent_buffer_writeback); | ||
| 2003 | |||
| 2004 | int set_extent_buffer_dirty(struct extent_map_tree *tree, | ||
| 2005 | struct extent_buffer *eb) | ||
| 2006 | { | ||
| 2007 | return set_range_dirty(tree, eb->start, eb->start + eb->len - 1); | ||
| 2008 | } | ||
| 2009 | EXPORT_SYMBOL(set_extent_buffer_dirty); | ||
| 2010 | |||
| 2011 | int set_extent_buffer_uptodate(struct extent_map_tree *tree, | ||
| 2012 | struct extent_buffer *eb) | ||
| 2013 | { | ||
| 2014 | unsigned long i; | ||
| 2015 | struct page *page; | ||
| 2016 | unsigned long num_pages; | ||
| 2017 | |||
| 2018 | num_pages = ((eb->start + eb->len - 1) >> PAGE_CACHE_SHIFT) - | ||
| 2019 | (eb->start >> PAGE_CACHE_SHIFT) + 1; | ||
| 2020 | |||
| 2021 | set_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, | ||
| 2022 | GFP_NOFS); | ||
| 2023 | for (i = 0; i < num_pages; i++) { | ||
| 2024 | page = eb->pages[i]; | ||
| 2025 | if ((i == 0 && (eb->start & (PAGE_CACHE_SIZE - 1))) || | ||
| 2026 | ((i == num_pages - 1) && | ||
| 2027 | ((eb->start + eb->len - 1) & (PAGE_CACHE_SIZE - 1)))) { | ||
| 2028 | check_page_uptodate(tree, page); | ||
| 2029 | continue; | ||
| 2030 | } | ||
| 2031 | SetPageUptodate(page); | ||
| 2032 | } | ||
| 2033 | return 0; | ||
| 2034 | } | ||
| 2035 | EXPORT_SYMBOL(set_extent_buffer_uptodate); | ||
| 2036 | |||
| 2037 | int extent_buffer_uptodate(struct extent_map_tree *tree, | ||
| 2038 | struct extent_buffer *eb) | ||
| 2039 | { | ||
| 2040 | if (eb->flags & EXTENT_UPTODATE) | ||
| 2041 | return 1; | ||
| 2042 | return test_range_bit(tree, eb->start, eb->start + eb->len - 1, | ||
| 2043 | EXTENT_UPTODATE, 1); | ||
| 2044 | } | ||
| 2045 | EXPORT_SYMBOL(extent_buffer_uptodate); | ||
| 2046 | |||
| 2047 | int read_extent_buffer_pages(struct extent_map_tree *tree, | ||
| 2048 | struct extent_buffer *eb, int wait) | ||
| 2049 | { | ||
| 2050 | unsigned long i; | ||
| 2051 | struct page *page; | ||
| 2052 | int err; | ||
| 2053 | int ret = 0; | ||
| 2054 | unsigned long num_pages; | ||
| 2055 | |||
| 2056 | if (eb->flags & EXTENT_UPTODATE) | ||
| 2057 | return 0; | ||
| 2058 | |||
| 2059 | if (test_range_bit(tree, eb->start, eb->start + eb->len - 1, | ||
| 2060 | EXTENT_UPTODATE, 1)) { | ||
| 2061 | return 0; | ||
| 2062 | } | ||
| 2063 | |||
| 2064 | num_pages = ((eb->start + eb->len - 1) >> PAGE_CACHE_SHIFT) - | ||
| 2065 | (eb->start >> PAGE_CACHE_SHIFT) + 1; | ||
| 2066 | for (i = 0; i < num_pages; i++) { | ||
| 2067 | page = eb->pages[i]; | ||
| 2068 | if (PageUptodate(page)) { | ||
| 2069 | continue; | ||
| 2070 | } | ||
| 2071 | if (!wait) { | ||
| 2072 | if (TestSetPageLocked(page)) { | ||
| 2073 | continue; | ||
| 2074 | } | ||
| 2075 | } else { | ||
| 2076 | lock_page(page); | ||
| 2077 | } | ||
| 2078 | if (!PageUptodate(page)) { | ||
| 2079 | err = page->mapping->a_ops->readpage(NULL, page); | ||
| 2080 | if (err) { | ||
| 2081 | ret = err; | ||
| 2082 | } | ||
| 2083 | } else { | ||
| 2084 | unlock_page(page); | ||
| 2085 | } | ||
| 2086 | } | ||
| 2087 | |||
| 2088 | if (ret || !wait) { | ||
| 2089 | return ret; | ||
| 2090 | } | ||
| 2091 | |||
| 2092 | for (i = 0; i < num_pages; i++) { | ||
| 2093 | page = eb->pages[i]; | ||
| 2094 | wait_on_page_locked(page); | ||
| 2095 | if (!PageUptodate(page)) { | ||
| 2096 | ret = -EIO; | ||
| 2097 | } | ||
| 2098 | } | ||
| 2099 | eb->flags |= EXTENT_UPTODATE; | ||
| 2100 | return ret; | ||
| 2101 | } | ||
| 2102 | EXPORT_SYMBOL(read_extent_buffer_pages); | ||
| 2103 | |||
| 2104 | void read_extent_buffer(struct extent_buffer *eb, void *dstv, | ||
| 2105 | unsigned long start, | ||
| 2106 | unsigned long len) | ||
| 2107 | { | ||
| 2108 | size_t cur; | ||
| 2109 | size_t offset; | ||
| 2110 | struct page *page; | ||
| 2111 | char *kaddr; | ||
| 2112 | char *dst = (char *)dstv; | ||
| 2113 | size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1); | ||
| 2114 | unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT; | ||
| 2115 | |||
| 2116 | WARN_ON(start > eb->len); | ||
| 2117 | WARN_ON(start + len > eb->start + eb->len); | ||
| 2118 | |||
| 2119 | page = eb->pages[i]; | ||
| 2120 | offset = start & ((unsigned long)PAGE_CACHE_SIZE - 1); | ||
| 2121 | if (i == 0) | ||
| 2122 | offset += start_offset; | ||
| 2123 | |||
| 2124 | while(len > 0) { | ||
| 2125 | WARN_ON(!PageUptodate(page)); | ||
| 2126 | |||
| 2127 | cur = min(len, (PAGE_CACHE_SIZE - offset)); | ||
| 2128 | // kaddr = kmap_atomic(page, KM_USER0); | ||
| 2129 | kaddr = page_address(page); | ||
| 2130 | memcpy(dst, kaddr + offset, cur); | ||
| 2131 | // kunmap_atomic(kaddr, KM_USER0); | ||
| 2132 | |||
| 2133 | dst += cur; | ||
| 2134 | len -= cur; | ||
| 2135 | offset = 0; | ||
| 2136 | i++; | ||
| 2137 | page = eb->pages[i]; | ||
| 2138 | } | ||
| 2139 | } | ||
| 2140 | EXPORT_SYMBOL(read_extent_buffer); | ||
| 2141 | |||
| 2142 | int map_extent_buffer(struct extent_buffer *eb, unsigned long start, | ||
| 2143 | char **token, char **map, | ||
| 2144 | unsigned long *map_start, | ||
| 2145 | unsigned long *map_len, int km) | ||
| 2146 | { | ||
| 2147 | size_t offset; | ||
| 2148 | char *kaddr; | ||
| 2149 | size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1); | ||
| 2150 | unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT; | ||
| 2151 | |||
| 2152 | WARN_ON(start > eb->len); | ||
| 2153 | |||
| 2154 | if (i == 0) { | ||
| 2155 | offset = start_offset; | ||
| 2156 | *map_start = 0; | ||
| 2157 | } else { | ||
| 2158 | offset = 0; | ||
| 2159 | *map_start = (i << PAGE_CACHE_SHIFT) - offset; | ||
| 2160 | } | ||
| 2161 | |||
| 2162 | // kaddr = kmap_atomic(eb->pages[i], km); | ||
| 2163 | kaddr = page_address(eb->pages[i]); | ||
| 2164 | *token = kaddr; | ||
| 2165 | *map = kaddr + offset; | ||
| 2166 | *map_len = PAGE_CACHE_SIZE - offset; | ||
| 2167 | return 0; | ||
| 2168 | } | ||
| 2169 | EXPORT_SYMBOL(map_extent_buffer); | ||
| 2170 | |||
| 2171 | void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km) | ||
| 2172 | { | ||
| 2173 | // kunmap_atomic(token, km); | ||
| 2174 | } | ||
| 2175 | EXPORT_SYMBOL(unmap_extent_buffer); | ||
| 2176 | |||
| 2177 | int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv, | ||
| 2178 | unsigned long start, | ||
| 2179 | unsigned long len) | ||
| 2180 | { | ||
| 2181 | size_t cur; | ||
| 2182 | size_t offset; | ||
| 2183 | struct page *page; | ||
| 2184 | char *kaddr; | ||
| 2185 | char *ptr = (char *)ptrv; | ||
| 2186 | size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1); | ||
| 2187 | unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT; | ||
| 2188 | int ret = 0; | ||
| 2189 | |||
| 2190 | WARN_ON(start > eb->len); | ||
| 2191 | WARN_ON(start + len > eb->start + eb->len); | ||
| 2192 | |||
| 2193 | page = eb->pages[i]; | ||
| 2194 | offset = start & ((unsigned long)PAGE_CACHE_SIZE - 1); | ||
| 2195 | if (i == 0) | ||
| 2196 | offset += start_offset; | ||
| 2197 | |||
| 2198 | while(len > 0) { | ||
| 2199 | WARN_ON(!PageUptodate(page)); | ||
| 2200 | |||
| 2201 | cur = min(len, (PAGE_CACHE_SIZE - offset)); | ||
| 2202 | |||
| 2203 | // kaddr = kmap_atomic(page, KM_USER0); | ||
| 2204 | kaddr = page_address(page); | ||
| 2205 | ret = memcmp(ptr, kaddr + offset, cur); | ||
| 2206 | // kunmap_atomic(kaddr, KM_USER0); | ||
| 2207 | if (ret) | ||
| 2208 | break; | ||
| 2209 | |||
| 2210 | ptr += cur; | ||
| 2211 | len -= cur; | ||
| 2212 | offset = 0; | ||
| 2213 | i++; | ||
| 2214 | page = eb->pages[i]; | ||
| 2215 | } | ||
| 2216 | return ret; | ||
| 2217 | } | ||
| 2218 | EXPORT_SYMBOL(memcmp_extent_buffer); | ||
| 2219 | |||
| 2220 | void write_extent_buffer(struct extent_buffer *eb, const void *srcv, | ||
| 2221 | unsigned long start, unsigned long len) | ||
| 2222 | { | ||
| 2223 | size_t cur; | ||
| 2224 | size_t offset; | ||
| 2225 | struct page *page; | ||
| 2226 | char *kaddr; | ||
| 2227 | char *src = (char *)srcv; | ||
| 2228 | size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1); | ||
| 2229 | unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT; | ||
| 2230 | |||
| 2231 | WARN_ON(start > eb->len); | ||
| 2232 | WARN_ON(start + len > eb->start + eb->len); | ||
| 2233 | |||
| 2234 | page = eb->pages[i]; | ||
| 2235 | offset = start & ((unsigned long)PAGE_CACHE_SIZE - 1); | ||
| 2236 | if (i == 0) | ||
| 2237 | offset += start_offset; | ||
| 2238 | |||
| 2239 | while(len > 0) { | ||
| 2240 | WARN_ON(!PageUptodate(page)); | ||
| 2241 | |||
| 2242 | cur = min(len, PAGE_CACHE_SIZE - offset); | ||
| 2243 | // kaddr = kmap_atomic(page, KM_USER0); | ||
| 2244 | kaddr = page_address(page); | ||
| 2245 | memcpy(kaddr + offset, src, cur); | ||
| 2246 | // kunmap_atomic(kaddr, KM_USER0); | ||
| 2247 | |||
| 2248 | src += cur; | ||
| 2249 | len -= cur; | ||
| 2250 | offset = 0; | ||
| 2251 | i++; | ||
| 2252 | page = eb->pages[i]; | ||
| 2253 | } | ||
| 2254 | } | ||
| 2255 | EXPORT_SYMBOL(write_extent_buffer); | ||
| 2256 | |||
| 2257 | void memset_extent_buffer(struct extent_buffer *eb, char c, | ||
| 2258 | unsigned long start, unsigned long len) | ||
| 2259 | { | ||
| 2260 | size_t cur; | ||
| 2261 | size_t offset; | ||
| 2262 | struct page *page; | ||
| 2263 | char *kaddr; | ||
| 2264 | size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1); | ||
| 2265 | unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT; | ||
| 2266 | |||
| 2267 | WARN_ON(start > eb->len); | ||
| 2268 | WARN_ON(start + len > eb->start + eb->len); | ||
| 2269 | |||
| 2270 | page = eb->pages[i]; | ||
| 2271 | offset = start & ((unsigned long)PAGE_CACHE_SIZE - 1); | ||
| 2272 | if (i == 0) | ||
| 2273 | offset += start_offset; | ||
| 2274 | |||
| 2275 | while(len > 0) { | ||
| 2276 | WARN_ON(!PageUptodate(page)); | ||
| 2277 | |||
| 2278 | cur = min(len, PAGE_CACHE_SIZE - offset); | ||
| 2279 | // kaddr = kmap_atomic(page, KM_USER0); | ||
| 2280 | kaddr = page_address(page); | ||
| 2281 | memset(kaddr + offset, c, cur); | ||
| 2282 | // kunmap_atomic(kaddr, KM_USER0); | ||
| 2283 | |||
| 2284 | len -= cur; | ||
| 2285 | offset = 0; | ||
| 2286 | i++; | ||
| 2287 | page = eb->pages[i]; | ||
| 2288 | } | ||
| 2289 | } | ||
| 2290 | EXPORT_SYMBOL(memset_extent_buffer); | ||
| 2291 | |||
| 2292 | void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src, | ||
| 2293 | unsigned long dst_offset, unsigned long src_offset, | ||
| 2294 | unsigned long len) | ||
| 2295 | { | ||
| 2296 | u64 dst_len = dst->len; | ||
| 2297 | size_t cur; | ||
| 2298 | size_t offset; | ||
| 2299 | struct page *page; | ||
| 2300 | char *kaddr; | ||
| 2301 | size_t start_offset = dst->start & ((u64)PAGE_CACHE_SIZE - 1); | ||
| 2302 | unsigned long i = (start_offset + dst_offset) >> PAGE_CACHE_SHIFT; | ||
| 2303 | |||
| 2304 | WARN_ON(src->len != dst_len); | ||
| 2305 | |||
| 2306 | offset = dst_offset & ((unsigned long)PAGE_CACHE_SIZE - 1); | ||
| 2307 | if (i == 0) | ||
| 2308 | offset += start_offset; | ||
| 2309 | |||
| 2310 | while(len > 0) { | ||
| 2311 | page = dst->pages[i]; | ||
| 2312 | WARN_ON(!PageUptodate(page)); | ||
| 2313 | |||
| 2314 | cur = min(len, (unsigned long)(PAGE_CACHE_SIZE - offset)); | ||
| 2315 | |||
| 2316 | // kaddr = kmap_atomic(page, KM_USER1); | ||
| 2317 | kaddr = page_address(page); | ||
| 2318 | read_extent_buffer(src, kaddr + offset, src_offset, cur); | ||
| 2319 | // kunmap_atomic(kaddr, KM_USER1); | ||
| 2320 | |||
| 2321 | src_offset += cur; | ||
| 2322 | len -= cur; | ||
| 2323 | offset = 0; | ||
| 2324 | i++; | ||
| 2325 | } | ||
| 2326 | } | ||
| 2327 | EXPORT_SYMBOL(copy_extent_buffer); | ||
| 2328 | |||
| 2329 | static void move_pages(struct page *dst_page, struct page *src_page, | ||
| 2330 | unsigned long dst_off, unsigned long src_off, | ||
| 2331 | unsigned long len) | ||
| 2332 | { | ||
| 2333 | // char *dst_kaddr = kmap_atomic(dst_page, KM_USER0); | ||
| 2334 | char *dst_kaddr = page_address(dst_page); | ||
| 2335 | if (dst_page == src_page) { | ||
| 2336 | memmove(dst_kaddr + dst_off, dst_kaddr + src_off, len); | ||
| 2337 | } else { | ||
| 2338 | // char *src_kaddr = kmap_atomic(src_page, KM_USER1); | ||
| 2339 | char *src_kaddr = page_address(src_page); | ||
| 2340 | char *p = dst_kaddr + dst_off + len; | ||
| 2341 | char *s = src_kaddr + src_off + len; | ||
| 2342 | |||
| 2343 | while (len--) | ||
| 2344 | *--p = *--s; | ||
| 2345 | |||
| 2346 | // kunmap_atomic(src_kaddr, KM_USER1); | ||
| 2347 | } | ||
| 2348 | // kunmap_atomic(dst_kaddr, KM_USER0); | ||
| 2349 | } | ||
| 2350 | |||
| 2351 | static void copy_pages(struct page *dst_page, struct page *src_page, | ||
| 2352 | unsigned long dst_off, unsigned long src_off, | ||
| 2353 | unsigned long len) | ||
| 2354 | { | ||
| 2355 | //kmap_atomic(dst_page, KM_USER0); | ||
| 2356 | char *dst_kaddr = page_address(dst_page); | ||
| 2357 | char *src_kaddr; | ||
| 2358 | |||
| 2359 | if (dst_page != src_page) | ||
| 2360 | src_kaddr = page_address(src_page); // kmap_atomic(src_page, KM_USER1); | ||
| 2361 | else | ||
| 2362 | src_kaddr = dst_kaddr; | ||
| 2363 | |||
| 2364 | memcpy(dst_kaddr + dst_off, src_kaddr + src_off, len); | ||
| 2365 | /* | ||
| 2366 | kunmap_atomic(dst_kaddr, KM_USER0); | ||
| 2367 | if (dst_page != src_page) | ||
| 2368 | kunmap_atomic(src_kaddr, KM_USER1); | ||
| 2369 | */ | ||
| 2370 | } | ||
| 2371 | |||
| 2372 | void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, | ||
| 2373 | unsigned long src_offset, unsigned long len) | ||
| 2374 | { | ||
| 2375 | size_t cur; | ||
| 2376 | size_t dst_off_in_page; | ||
| 2377 | size_t src_off_in_page; | ||
| 2378 | size_t start_offset = dst->start & ((u64)PAGE_CACHE_SIZE - 1); | ||
| 2379 | unsigned long dst_i; | ||
| 2380 | unsigned long src_i; | ||
| 2381 | |||
| 2382 | if (src_offset + len > dst->len) { | ||
| 2383 | printk("memmove bogus src_offset %lu move len %lu len %lu\n", | ||
| 2384 | src_offset, len, dst->len); | ||
| 2385 | BUG_ON(1); | ||
| 2386 | } | ||
| 2387 | if (dst_offset + len > dst->len) { | ||
| 2388 | printk("memmove bogus dst_offset %lu move len %lu len %lu\n", | ||
| 2389 | dst_offset, len, dst->len); | ||
| 2390 | BUG_ON(1); | ||
| 2391 | } | ||
| 2392 | |||
| 2393 | while(len > 0) { | ||
| 2394 | dst_off_in_page = dst_offset & | ||
| 2395 | ((unsigned long)PAGE_CACHE_SIZE - 1); | ||
| 2396 | src_off_in_page = src_offset & | ||
| 2397 | ((unsigned long)PAGE_CACHE_SIZE - 1); | ||
| 2398 | |||
| 2399 | dst_i = (start_offset + dst_offset) >> PAGE_CACHE_SHIFT; | ||
| 2400 | src_i = (start_offset + src_offset) >> PAGE_CACHE_SHIFT; | ||
| 2401 | |||
| 2402 | if (src_i == 0) | ||
| 2403 | src_off_in_page += start_offset; | ||
| 2404 | if (dst_i == 0) | ||
| 2405 | dst_off_in_page += start_offset; | ||
| 2406 | |||
| 2407 | cur = min(len, (unsigned long)(PAGE_CACHE_SIZE - | ||
| 2408 | src_off_in_page)); | ||
| 2409 | cur = min(cur, (unsigned long)(PAGE_CACHE_SIZE - | ||
| 2410 | dst_off_in_page)); | ||
| 2411 | |||
| 2412 | copy_pages(dst->pages[dst_i], dst->pages[src_i], | ||
| 2413 | dst_off_in_page, src_off_in_page, cur); | ||
| 2414 | |||
| 2415 | src_offset += cur; | ||
| 2416 | dst_offset += cur; | ||
| 2417 | len -= cur; | ||
| 2418 | } | ||
| 2419 | } | ||
| 2420 | EXPORT_SYMBOL(memcpy_extent_buffer); | ||
| 2421 | |||
| 2422 | void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, | ||
| 2423 | unsigned long src_offset, unsigned long len) | ||
| 2424 | { | ||
| 2425 | size_t cur; | ||
| 2426 | size_t dst_off_in_page; | ||
| 2427 | size_t src_off_in_page; | ||
| 2428 | unsigned long dst_end = dst_offset + len - 1; | ||
| 2429 | unsigned long src_end = src_offset + len - 1; | ||
| 2430 | size_t start_offset = dst->start & ((u64)PAGE_CACHE_SIZE - 1); | ||
| 2431 | unsigned long dst_i; | ||
| 2432 | unsigned long src_i; | ||
| 2433 | |||
| 2434 | if (src_offset + len > dst->len) { | ||
| 2435 | printk("memmove bogus src_offset %lu move len %lu len %lu\n", | ||
| 2436 | src_offset, len, dst->len); | ||
| 2437 | BUG_ON(1); | ||
| 2438 | } | ||
| 2439 | if (dst_offset + len > dst->len) { | ||
| 2440 | printk("memmove bogus dst_offset %lu move len %lu len %lu\n", | ||
| 2441 | dst_offset, len, dst->len); | ||
| 2442 | BUG_ON(1); | ||
| 2443 | } | ||
| 2444 | if (dst_offset < src_offset) { | ||
| 2445 | memcpy_extent_buffer(dst, dst_offset, src_offset, len); | ||
| 2446 | return; | ||
| 2447 | } | ||
| 2448 | while(len > 0) { | ||
| 2449 | dst_i = (start_offset + dst_end) >> PAGE_CACHE_SHIFT; | ||
| 2450 | src_i = (start_offset + src_end) >> PAGE_CACHE_SHIFT; | ||
| 2451 | |||
| 2452 | dst_off_in_page = dst_end & | ||
| 2453 | ((unsigned long)PAGE_CACHE_SIZE - 1); | ||
| 2454 | src_off_in_page = src_end & | ||
| 2455 | ((unsigned long)PAGE_CACHE_SIZE - 1); | ||
| 2456 | |||
| 2457 | if (src_i == 0) | ||
| 2458 | src_off_in_page += start_offset; | ||
| 2459 | if (dst_i == 0) | ||
| 2460 | dst_off_in_page += start_offset; | ||
| 2461 | |||
| 2462 | cur = min(len, src_off_in_page + 1); | ||
| 2463 | cur = min(cur, dst_off_in_page + 1); | ||
| 2464 | // printk("move pages orig dst %lu src %lu len %lu, this %lu %lu %lu\n", dst_offset, src_offset, len, dst_off_in_page - cur + 1, src_off_in_page - cur + 1, cur); | ||
| 2465 | move_pages(dst->pages[dst_i], dst->pages[src_i], | ||
| 2466 | dst_off_in_page - cur + 1, | ||
| 2467 | src_off_in_page - cur + 1, cur); | ||
| 2468 | |||
| 2469 | dst_end -= cur - 1; | ||
| 2470 | src_end -= cur - 1; | ||
| 2471 | len -= cur; | ||
| 2472 | } | ||
| 2473 | } | ||
| 2474 | EXPORT_SYMBOL(memmove_extent_buffer); | ||
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index d913ce01248d..430b997a70f6 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h | |||
| @@ -3,9 +3,20 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/rbtree.h> | 4 | #include <linux/rbtree.h> |
| 5 | 5 | ||
| 6 | #define EXTENT_MAP_HOLE (u64)-3 | ||
| 6 | #define EXTENT_MAP_INLINE (u64)-2 | 7 | #define EXTENT_MAP_INLINE (u64)-2 |
| 7 | #define EXTENT_MAP_DELALLOC (u64)-1 | 8 | #define EXTENT_MAP_DELALLOC (u64)-1 |
| 8 | 9 | ||
| 10 | /* bits for the extent state */ | ||
| 11 | #define EXTENT_DIRTY 1 | ||
| 12 | #define EXTENT_WRITEBACK (1 << 1) | ||
| 13 | #define EXTENT_UPTODATE (1 << 2) | ||
| 14 | #define EXTENT_LOCKED (1 << 3) | ||
| 15 | #define EXTENT_NEW (1 << 4) | ||
| 16 | #define EXTENT_DELALLOC (1 << 5) | ||
| 17 | #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) | ||
| 18 | |||
| 19 | |||
| 9 | struct extent_map_ops { | 20 | struct extent_map_ops { |
| 10 | int (*fill_delalloc)(struct inode *inode, u64 start, u64 end); | 21 | int (*fill_delalloc)(struct inode *inode, u64 start, u64 end); |
| 11 | int (*writepage_io_hook)(struct page *page, u64 start, u64 end); | 22 | int (*writepage_io_hook)(struct page *page, u64 start, u64 end); |
| @@ -51,10 +62,13 @@ struct extent_state { | |||
| 51 | struct list_head list; | 62 | struct list_head list; |
| 52 | }; | 63 | }; |
| 53 | 64 | ||
| 65 | #define EXTENT_BUFFER_SIZE(nr) (sizeof(struct extent_buffer) + \ | ||
| 66 | (nr - 1) * sizeof(struct page *)) | ||
| 54 | struct extent_buffer { | 67 | struct extent_buffer { |
| 55 | u64 start; | 68 | u64 start; |
| 56 | u64 end; /* inclusive */ | 69 | unsigned long len; |
| 57 | char *addr; | 70 | atomic_t refs; |
| 71 | int flags; | ||
| 58 | struct page *pages[]; | 72 | struct page *pages[]; |
| 59 | }; | 73 | }; |
| 60 | 74 | ||
| @@ -87,8 +101,12 @@ int set_extent_new(struct extent_map_tree *tree, u64 start, u64 end, | |||
| 87 | gfp_t mask); | 101 | gfp_t mask); |
| 88 | int set_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end, | 102 | int set_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end, |
| 89 | gfp_t mask); | 103 | gfp_t mask); |
| 104 | int clear_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end, | ||
| 105 | gfp_t mask); | ||
| 90 | int set_extent_delalloc(struct extent_map_tree *tree, u64 start, u64 end, | 106 | int set_extent_delalloc(struct extent_map_tree *tree, u64 start, u64 end, |
| 91 | gfp_t mask); | 107 | gfp_t mask); |
| 108 | int find_first_extent_bit(struct extent_map_tree *tree, u64 start, | ||
| 109 | u64 *start_ret, u64 *end_ret, int bits); | ||
| 92 | int extent_invalidatepage(struct extent_map_tree *tree, | 110 | int extent_invalidatepage(struct extent_map_tree *tree, |
| 93 | struct page *page, unsigned long offset); | 111 | struct page *page, unsigned long offset); |
| 94 | int extent_write_full_page(struct extent_map_tree *tree, struct page *page, | 112 | int extent_write_full_page(struct extent_map_tree *tree, struct page *page, |
| @@ -106,4 +124,57 @@ int set_range_dirty(struct extent_map_tree *tree, u64 start, u64 end); | |||
| 106 | int set_state_private(struct extent_map_tree *tree, u64 start, u64 private); | 124 | int set_state_private(struct extent_map_tree *tree, u64 start, u64 private); |
| 107 | int get_state_private(struct extent_map_tree *tree, u64 start, u64 *private); | 125 | int get_state_private(struct extent_map_tree *tree, u64 start, u64 *private); |
| 108 | void set_page_extent_mapped(struct page *page); | 126 | void set_page_extent_mapped(struct page *page); |
| 127 | |||
| 128 | struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree, | ||
| 129 | u64 start, unsigned long len, | ||
| 130 | gfp_t mask); | ||
| 131 | struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree, | ||
| 132 | u64 start, unsigned long len, | ||
| 133 | gfp_t mask); | ||
| 134 | void free_extent_buffer(struct extent_buffer *eb); | ||
| 135 | int read_extent_buffer_pages(struct extent_map_tree *tree, | ||
| 136 | struct extent_buffer *eb, int wait); | ||
| 137 | |||
| 138 | static inline void extent_buffer_get(struct extent_buffer *eb) | ||
| 139 | { | ||
| 140 | atomic_inc(&eb->refs); | ||
| 141 | } | ||
| 142 | |||
| 143 | static inline u64 extent_buffer_blocknr(struct extent_buffer *eb) | ||
| 144 | { | ||
| 145 | return eb->start / 4096; | ||
| 146 | } | ||
| 147 | |||
| 148 | int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv, | ||
| 149 | unsigned long start, | ||
| 150 | unsigned long len); | ||
| 151 | void read_extent_buffer(struct extent_buffer *eb, void *dst, | ||
| 152 | unsigned long start, | ||
| 153 | unsigned long len); | ||
| 154 | void write_extent_buffer(struct extent_buffer *eb, const void *src, | ||
| 155 | unsigned long start, unsigned long len); | ||
| 156 | void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src, | ||
| 157 | unsigned long dst_offset, unsigned long src_offset, | ||
| 158 | unsigned long len); | ||
| 159 | void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, | ||
| 160 | unsigned long src_offset, unsigned long len); | ||
| 161 | void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, | ||
| 162 | unsigned long src_offset, unsigned long len); | ||
| 163 | void memset_extent_buffer(struct extent_buffer *eb, char c, | ||
| 164 | unsigned long start, unsigned long len); | ||
| 165 | int wait_on_extent_buffer_writeback(struct extent_map_tree *tree, | ||
| 166 | struct extent_buffer *eb); | ||
| 167 | int clear_extent_buffer_dirty(struct extent_map_tree *tree, | ||
| 168 | struct extent_buffer *eb); | ||
| 169 | int set_extent_buffer_dirty(struct extent_map_tree *tree, | ||
| 170 | struct extent_buffer *eb); | ||
| 171 | int set_extent_buffer_uptodate(struct extent_map_tree *tree, | ||
| 172 | struct extent_buffer *eb); | ||
| 173 | int extent_buffer_uptodate(struct extent_map_tree *tree, | ||
| 174 | struct extent_buffer *eb); | ||
| 175 | int map_extent_buffer(struct extent_buffer *eb, unsigned long offset, | ||
| 176 | char **token, char **map, | ||
| 177 | unsigned long *map_start, | ||
| 178 | unsigned long *map_len, int km); | ||
| 179 | void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km); | ||
| 109 | #endif | 180 | #endif |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index ea4dd4c5fce3..226f6d028c3f 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
| @@ -34,12 +34,12 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, | |||
| 34 | struct btrfs_file_extent_item *item; | 34 | struct btrfs_file_extent_item *item; |
| 35 | struct btrfs_key file_key; | 35 | struct btrfs_key file_key; |
| 36 | struct btrfs_path *path; | 36 | struct btrfs_path *path; |
| 37 | struct extent_buffer *leaf; | ||
| 37 | 38 | ||
| 38 | path = btrfs_alloc_path(); | 39 | path = btrfs_alloc_path(); |
| 39 | BUG_ON(!path); | 40 | BUG_ON(!path); |
| 40 | file_key.objectid = objectid; | 41 | file_key.objectid = objectid; |
| 41 | file_key.offset = pos; | 42 | file_key.offset = pos; |
| 42 | file_key.flags = 0; | ||
| 43 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); | 43 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); |
| 44 | 44 | ||
| 45 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, | 45 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, |
| @@ -47,15 +47,16 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, | |||
| 47 | if (ret < 0) | 47 | if (ret < 0) |
| 48 | goto out; | 48 | goto out; |
| 49 | BUG_ON(ret); | 49 | BUG_ON(ret); |
| 50 | item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | 50 | leaf = path->nodes[0]; |
| 51 | item = btrfs_item_ptr(leaf, path->slots[0], | ||
| 51 | struct btrfs_file_extent_item); | 52 | struct btrfs_file_extent_item); |
| 52 | btrfs_set_file_extent_disk_blocknr(item, offset); | 53 | btrfs_set_file_extent_disk_blocknr(leaf, item, offset); |
| 53 | btrfs_set_file_extent_disk_num_blocks(item, disk_num_blocks); | 54 | btrfs_set_file_extent_disk_num_blocks(leaf, item, disk_num_blocks); |
| 54 | btrfs_set_file_extent_offset(item, 0); | 55 | btrfs_set_file_extent_offset(leaf, item, 0); |
| 55 | btrfs_set_file_extent_num_blocks(item, num_blocks); | 56 | btrfs_set_file_extent_num_blocks(leaf, item, num_blocks); |
| 56 | btrfs_set_file_extent_generation(item, trans->transid); | 57 | btrfs_set_file_extent_generation(leaf, item, trans->transid); |
| 57 | btrfs_set_file_extent_type(item, BTRFS_FILE_EXTENT_REG); | 58 | btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG); |
| 58 | btrfs_mark_buffer_dirty(path->nodes[0]); | 59 | btrfs_mark_buffer_dirty(leaf); |
| 59 | out: | 60 | out: |
| 60 | btrfs_free_path(path); | 61 | btrfs_free_path(path); |
| 61 | return ret; | 62 | return ret; |
| @@ -71,32 +72,30 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, | |||
| 71 | struct btrfs_key file_key; | 72 | struct btrfs_key file_key; |
| 72 | struct btrfs_key found_key; | 73 | struct btrfs_key found_key; |
| 73 | struct btrfs_csum_item *item; | 74 | struct btrfs_csum_item *item; |
| 74 | struct btrfs_leaf *leaf; | 75 | struct extent_buffer *leaf; |
| 75 | u64 csum_offset = 0; | 76 | u64 csum_offset = 0; |
| 76 | int csums_in_item; | 77 | int csums_in_item; |
| 77 | 78 | ||
| 78 | file_key.objectid = objectid; | 79 | file_key.objectid = objectid; |
| 79 | file_key.offset = offset; | 80 | file_key.offset = offset; |
| 80 | file_key.flags = 0; | ||
| 81 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); | 81 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); |
| 82 | ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow); | 82 | ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow); |
| 83 | if (ret < 0) | 83 | if (ret < 0) |
| 84 | goto fail; | 84 | goto fail; |
| 85 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 85 | leaf = path->nodes[0]; |
| 86 | if (ret > 0) { | 86 | if (ret > 0) { |
| 87 | ret = 1; | 87 | ret = 1; |
| 88 | if (path->slots[0] == 0) | 88 | if (path->slots[0] == 0) |
| 89 | goto fail; | 89 | goto fail; |
| 90 | path->slots[0]--; | 90 | path->slots[0]--; |
| 91 | btrfs_disk_key_to_cpu(&found_key, | 91 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
| 92 | &leaf->items[path->slots[0]].key); | ||
| 93 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || | 92 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || |
| 94 | found_key.objectid != objectid) { | 93 | found_key.objectid != objectid) { |
| 95 | goto fail; | 94 | goto fail; |
| 96 | } | 95 | } |
| 97 | csum_offset = (offset - found_key.offset) >> | 96 | csum_offset = (offset - found_key.offset) >> |
| 98 | root->fs_info->sb->s_blocksize_bits; | 97 | root->fs_info->sb->s_blocksize_bits; |
| 99 | csums_in_item = btrfs_item_size(leaf->items + path->slots[0]); | 98 | csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]); |
| 100 | csums_in_item /= BTRFS_CRC32_SIZE; | 99 | csums_in_item /= BTRFS_CRC32_SIZE; |
| 101 | 100 | ||
| 102 | if (csum_offset >= csums_in_item) { | 101 | if (csum_offset >= csums_in_item) { |
| @@ -127,7 +126,6 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | |||
| 127 | 126 | ||
| 128 | file_key.objectid = objectid; | 127 | file_key.objectid = objectid; |
| 129 | file_key.offset = offset; | 128 | file_key.offset = offset; |
| 130 | file_key.flags = 0; | ||
| 131 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); | 129 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); |
| 132 | ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow); | 130 | ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow); |
| 133 | return ret; | 131 | return ret; |
| @@ -138,12 +136,14 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
| 138 | u64 objectid, u64 offset, | 136 | u64 objectid, u64 offset, |
| 139 | char *data, size_t len) | 137 | char *data, size_t len) |
| 140 | { | 138 | { |
| 139 | return 0; | ||
| 140 | #if 0 | ||
| 141 | int ret; | 141 | int ret; |
| 142 | struct btrfs_key file_key; | 142 | struct btrfs_key file_key; |
| 143 | struct btrfs_key found_key; | 143 | struct btrfs_key found_key; |
| 144 | struct btrfs_path *path; | 144 | struct btrfs_path *path; |
| 145 | struct btrfs_csum_item *item; | 145 | struct btrfs_csum_item *item; |
| 146 | struct btrfs_leaf *leaf; | 146 | struct extent_buffer *leaf; |
| 147 | u64 csum_offset; | 147 | u64 csum_offset; |
| 148 | 148 | ||
| 149 | path = btrfs_alloc_path(); | 149 | path = btrfs_alloc_path(); |
| @@ -161,8 +161,8 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
| 161 | if (ret == -EFBIG) { | 161 | if (ret == -EFBIG) { |
| 162 | u32 item_size; | 162 | u32 item_size; |
| 163 | /* we found one, but it isn't big enough yet */ | 163 | /* we found one, but it isn't big enough yet */ |
| 164 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 164 | leaf = path->nodes[0]; |
| 165 | item_size = btrfs_item_size(leaf->items + path->slots[0]); | 165 | item_size = btrfs_item_size_nr(leaf, path->slots[0]); |
| 166 | if ((item_size / BTRFS_CRC32_SIZE) >= MAX_CSUM_ITEMS(root)) { | 166 | if ((item_size / BTRFS_CRC32_SIZE) >= MAX_CSUM_ITEMS(root)) { |
| 167 | /* already at max size, make a new one */ | 167 | /* already at max size, make a new one */ |
| 168 | goto insert; | 168 | goto insert; |
| @@ -188,8 +188,8 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
| 188 | goto insert; | 188 | goto insert; |
| 189 | } | 189 | } |
| 190 | path->slots[0]--; | 190 | path->slots[0]--; |
| 191 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 191 | leaf = path->nodes[0]; |
| 192 | btrfs_disk_key_to_cpu(&found_key, &leaf->items[path->slots[0]].key); | 192 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
| 193 | csum_offset = (offset - found_key.offset) >> | 193 | csum_offset = (offset - found_key.offset) >> |
| 194 | root->fs_info->sb->s_blocksize_bits; | 194 | root->fs_info->sb->s_blocksize_bits; |
| 195 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || | 195 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || |
| @@ -197,10 +197,10 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
| 197 | csum_offset >= MAX_CSUM_ITEMS(root)) { | 197 | csum_offset >= MAX_CSUM_ITEMS(root)) { |
| 198 | goto insert; | 198 | goto insert; |
| 199 | } | 199 | } |
| 200 | if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) / | 200 | if (csum_offset >= btrfs_item_size_nr(leaf, path->slots[0]) / |
| 201 | BTRFS_CRC32_SIZE) { | 201 | BTRFS_CRC32_SIZE) { |
| 202 | u32 diff = (csum_offset + 1) * BTRFS_CRC32_SIZE; | 202 | u32 diff = (csum_offset + 1) * BTRFS_CRC32_SIZE; |
| 203 | diff = diff - btrfs_item_size(leaf->items + path->slots[0]); | 203 | diff = diff - btrfs_item_size_nr(leaf, path->slots[0]); |
| 204 | if (diff != BTRFS_CRC32_SIZE) | 204 | if (diff != BTRFS_CRC32_SIZE) |
| 205 | goto insert; | 205 | goto insert; |
| 206 | ret = btrfs_extend_item(trans, root, path, diff); | 206 | ret = btrfs_extend_item(trans, root, path, diff); |
| @@ -220,21 +220,20 @@ insert: | |||
| 220 | goto fail; | 220 | goto fail; |
| 221 | } | 221 | } |
| 222 | csum: | 222 | csum: |
| 223 | item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | 223 | leaf = path->nodes[0]; |
| 224 | struct btrfs_csum_item); | 224 | item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); |
| 225 | ret = 0; | 225 | ret = 0; |
| 226 | item = (struct btrfs_csum_item *)((unsigned char *)item + | 226 | item = (struct btrfs_csum_item *)((unsigned char *)item + |
| 227 | csum_offset * BTRFS_CRC32_SIZE); | 227 | csum_offset * BTRFS_CRC32_SIZE); |
| 228 | found: | 228 | found: |
| 229 | btrfs_check_bounds(&item->csum, BTRFS_CRC32_SIZE, | 229 | /* FIXME!!!!!!!!!!!! */ |
| 230 | path->nodes[0]->b_data, | ||
| 231 | root->fs_info->sb->s_blocksize); | ||
| 232 | ret = btrfs_csum_data(root, data, len, &item->csum); | 230 | ret = btrfs_csum_data(root, data, len, &item->csum); |
| 233 | btrfs_mark_buffer_dirty(path->nodes[0]); | 231 | btrfs_mark_buffer_dirty(path->nodes[0]); |
| 234 | fail: | 232 | fail: |
| 235 | btrfs_release_path(root, path); | 233 | btrfs_release_path(root, path); |
| 236 | btrfs_free_path(path); | 234 | btrfs_free_path(path); |
| 237 | return ret; | 235 | return ret; |
| 236 | #endif | ||
| 238 | } | 237 | } |
| 239 | 238 | ||
| 240 | int btrfs_csum_truncate(struct btrfs_trans_handle *trans, | 239 | int btrfs_csum_truncate(struct btrfs_trans_handle *trans, |
| @@ -242,21 +241,21 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans, | |||
| 242 | u64 isize) | 241 | u64 isize) |
| 243 | { | 242 | { |
| 244 | struct btrfs_key key; | 243 | struct btrfs_key key; |
| 245 | struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[0]); | 244 | struct extent_buffer *leaf = path->nodes[0]; |
| 246 | int slot = path->slots[0]; | 245 | int slot = path->slots[0]; |
| 247 | int ret; | 246 | int ret; |
| 248 | u32 new_item_size; | 247 | u32 new_item_size; |
| 249 | u64 new_item_span; | 248 | u64 new_item_span; |
| 250 | u64 blocks; | 249 | u64 blocks; |
| 251 | 250 | ||
| 252 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); | 251 | btrfs_item_key_to_cpu(leaf, &key, slot); |
| 253 | if (isize <= key.offset) | 252 | if (isize <= key.offset) |
| 254 | return 0; | 253 | return 0; |
| 255 | new_item_span = isize - key.offset; | 254 | new_item_span = isize - key.offset; |
| 256 | blocks = (new_item_span + root->blocksize - 1) >> | 255 | blocks = (new_item_span + root->sectorsize - 1) >> |
| 257 | root->fs_info->sb->s_blocksize_bits; | 256 | root->fs_info->sb->s_blocksize_bits; |
| 258 | new_item_size = blocks * BTRFS_CRC32_SIZE; | 257 | new_item_size = blocks * BTRFS_CRC32_SIZE; |
| 259 | if (new_item_size >= btrfs_item_size(leaf->items + slot)) | 258 | if (new_item_size >= btrfs_item_size_nr(leaf, slot)) |
| 260 | return 0; | 259 | return 0; |
| 261 | ret = btrfs_truncate_item(trans, root, path, new_item_size); | 260 | ret = btrfs_truncate_item(trans, root, path, new_item_size); |
| 262 | BUG_ON(ret); | 261 | BUG_ON(ret); |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 4cc459c943ec..1734ca695555 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/buffer_head.h> | ||
| 20 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
| 21 | #include <linux/pagemap.h> | 20 | #include <linux/pagemap.h> |
| 22 | #include <linux/highmem.h> | 21 | #include <linux/highmem.h> |
| @@ -88,7 +87,9 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
| 88 | { | 87 | { |
| 89 | struct btrfs_key key; | 88 | struct btrfs_key key; |
| 90 | struct btrfs_path *path; | 89 | struct btrfs_path *path; |
| 91 | char *ptr, *kaddr; | 90 | struct extent_buffer *leaf; |
| 91 | char *kaddr; | ||
| 92 | unsigned long ptr; | ||
| 92 | struct btrfs_file_extent_item *ei; | 93 | struct btrfs_file_extent_item *ei; |
| 93 | u32 datasize; | 94 | u32 datasize; |
| 94 | int err = 0; | 95 | int err = 0; |
| @@ -102,7 +103,6 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
| 102 | 103 | ||
| 103 | key.objectid = inode->i_ino; | 104 | key.objectid = inode->i_ino; |
| 104 | key.offset = offset; | 105 | key.offset = offset; |
| 105 | key.flags = 0; | ||
| 106 | btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY); | 106 | btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY); |
| 107 | BUG_ON(size >= PAGE_CACHE_SIZE); | 107 | BUG_ON(size >= PAGE_CACHE_SIZE); |
| 108 | datasize = btrfs_file_extent_calc_inline_size(size); | 108 | datasize = btrfs_file_extent_calc_inline_size(size); |
| @@ -113,18 +113,17 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
| 113 | err = ret; | 113 | err = ret; |
| 114 | goto fail; | 114 | goto fail; |
| 115 | } | 115 | } |
| 116 | ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | 116 | leaf = path->nodes[0]; |
| 117 | path->slots[0], struct btrfs_file_extent_item); | 117 | ei = btrfs_item_ptr(leaf, path->slots[0], |
| 118 | btrfs_set_file_extent_generation(ei, trans->transid); | 118 | struct btrfs_file_extent_item); |
| 119 | btrfs_set_file_extent_type(ei, | 119 | btrfs_set_file_extent_generation(leaf, ei, trans->transid); |
| 120 | BTRFS_FILE_EXTENT_INLINE); | 120 | btrfs_set_file_extent_type(leaf, ei, BTRFS_FILE_EXTENT_INLINE); |
| 121 | ptr = btrfs_file_extent_inline_start(ei); | 121 | ptr = btrfs_file_extent_inline_start(ei); |
| 122 | 122 | ||
| 123 | kaddr = kmap_atomic(page, KM_USER0); | 123 | kaddr = kmap_atomic(page, KM_USER0); |
| 124 | btrfs_memcpy(root, path->nodes[0]->b_data, | 124 | write_extent_buffer(leaf, kaddr + page_offset, ptr, size); |
| 125 | ptr, kaddr + page_offset, size); | ||
| 126 | kunmap_atomic(kaddr, KM_USER0); | 125 | kunmap_atomic(kaddr, KM_USER0); |
| 127 | btrfs_mark_buffer_dirty(path->nodes[0]); | 126 | btrfs_mark_buffer_dirty(leaf); |
| 128 | fail: | 127 | fail: |
| 129 | btrfs_free_path(path); | 128 | btrfs_free_path(path); |
| 130 | return err; | 129 | return err; |
| @@ -156,8 +155,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
| 156 | 155 | ||
| 157 | em->bdev = inode->i_sb->s_bdev; | 156 | em->bdev = inode->i_sb->s_bdev; |
| 158 | 157 | ||
| 159 | start_pos = pos & ~((u64)root->blocksize - 1); | 158 | start_pos = pos & ~((u64)root->sectorsize - 1); |
| 160 | num_blocks = (write_bytes + pos - start_pos + root->blocksize - 1) >> | 159 | num_blocks = (write_bytes + pos - start_pos + root->sectorsize - 1) >> |
| 161 | inode->i_blkbits; | 160 | inode->i_blkbits; |
| 162 | 161 | ||
| 163 | down_read(&BTRFS_I(inode)->root->snap_sem); | 162 | down_read(&BTRFS_I(inode)->root->snap_sem); |
| @@ -184,7 +183,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
| 184 | if (inode->i_size < start_pos) { | 183 | if (inode->i_size < start_pos) { |
| 185 | u64 last_pos_in_file; | 184 | u64 last_pos_in_file; |
| 186 | u64 hole_size; | 185 | u64 hole_size; |
| 187 | u64 mask = root->blocksize - 1; | 186 | u64 mask = root->sectorsize - 1; |
| 188 | last_pos_in_file = (isize + mask) & ~mask; | 187 | last_pos_in_file = (isize + mask) & ~mask; |
| 189 | hole_size = (start_pos - last_pos_in_file + mask) & ~mask; | 188 | hole_size = (start_pos - last_pos_in_file + mask) & ~mask; |
| 190 | 189 | ||
| @@ -227,8 +226,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
| 227 | /* step one, delete the existing extents in this range */ | 226 | /* step one, delete the existing extents in this range */ |
| 228 | /* FIXME blocksize != pagesize */ | 227 | /* FIXME blocksize != pagesize */ |
| 229 | err = btrfs_drop_extents(trans, root, inode, start_pos, | 228 | err = btrfs_drop_extents(trans, root, inode, start_pos, |
| 230 | (pos + write_bytes + root->blocksize -1) & | 229 | (pos + write_bytes + root->sectorsize -1) & |
| 231 | ~((u64)root->blocksize - 1), &hint_block); | 230 | ~((u64)root->sectorsize - 1), &hint_block); |
| 232 | if (err) | 231 | if (err) |
| 233 | goto failed; | 232 | goto failed; |
| 234 | 233 | ||
| @@ -288,7 +287,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, | |||
| 288 | { | 287 | { |
| 289 | int ret; | 288 | int ret; |
| 290 | struct btrfs_key key; | 289 | struct btrfs_key key; |
| 291 | struct btrfs_leaf *leaf; | 290 | struct extent_buffer *leaf; |
| 292 | int slot; | 291 | int slot; |
| 293 | struct btrfs_file_extent_item *extent; | 292 | struct btrfs_file_extent_item *extent; |
| 294 | u64 extent_end = 0; | 293 | u64 extent_end = 0; |
| @@ -327,10 +326,10 @@ next_slot: | |||
| 327 | found_extent = 0; | 326 | found_extent = 0; |
| 328 | found_inline = 0; | 327 | found_inline = 0; |
| 329 | extent = NULL; | 328 | extent = NULL; |
| 330 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 329 | leaf = path->nodes[0]; |
| 331 | slot = path->slots[0]; | 330 | slot = path->slots[0]; |
| 332 | ret = 0; | 331 | ret = 0; |
| 333 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); | 332 | btrfs_item_key_to_cpu(leaf, &key, slot); |
| 334 | if (key.offset >= end || key.objectid != inode->i_ino) { | 333 | if (key.offset >= end || key.objectid != inode->i_ino) { |
| 335 | goto out; | 334 | goto out; |
| 336 | } | 335 | } |
| @@ -344,17 +343,18 @@ next_slot: | |||
| 344 | if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) { | 343 | if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) { |
| 345 | extent = btrfs_item_ptr(leaf, slot, | 344 | extent = btrfs_item_ptr(leaf, slot, |
| 346 | struct btrfs_file_extent_item); | 345 | struct btrfs_file_extent_item); |
| 347 | found_type = btrfs_file_extent_type(extent); | 346 | found_type = btrfs_file_extent_type(leaf, extent); |
| 348 | if (found_type == BTRFS_FILE_EXTENT_REG) { | 347 | if (found_type == BTRFS_FILE_EXTENT_REG) { |
| 349 | extent_end = key.offset + | 348 | extent_end = key.offset + |
| 350 | (btrfs_file_extent_num_blocks(extent) << | 349 | (btrfs_file_extent_num_blocks(leaf, extent) << |
| 351 | inode->i_blkbits); | 350 | inode->i_blkbits); |
| 352 | found_extent = 1; | 351 | found_extent = 1; |
| 353 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | 352 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { |
| 353 | struct btrfs_item *item; | ||
| 354 | item = btrfs_item_nr(leaf, slot); | ||
| 354 | found_inline = 1; | 355 | found_inline = 1; |
| 355 | extent_end = key.offset + | 356 | extent_end = key.offset + |
| 356 | btrfs_file_extent_inline_len(leaf->items + | 357 | btrfs_file_extent_inline_len(leaf, item); |
| 357 | slot); | ||
| 358 | } | 358 | } |
| 359 | } else { | 359 | } else { |
| 360 | extent_end = search_start; | 360 | extent_end = search_start; |
| @@ -365,8 +365,7 @@ next_slot: | |||
| 365 | search_start >= extent_end) { | 365 | search_start >= extent_end) { |
| 366 | int nextret; | 366 | int nextret; |
| 367 | u32 nritems; | 367 | u32 nritems; |
| 368 | nritems = btrfs_header_nritems( | 368 | nritems = btrfs_header_nritems(leaf); |
| 369 | btrfs_buffer_header(path->nodes[0])); | ||
| 370 | if (slot >= nritems - 1) { | 369 | if (slot >= nritems - 1) { |
| 371 | nextret = btrfs_next_leaf(root, path); | 370 | nextret = btrfs_next_leaf(root, path); |
| 372 | if (nextret) | 371 | if (nextret) |
| @@ -380,7 +379,7 @@ next_slot: | |||
| 380 | 379 | ||
| 381 | /* FIXME, there's only one inline extent allowed right now */ | 380 | /* FIXME, there's only one inline extent allowed right now */ |
| 382 | if (found_inline) { | 381 | if (found_inline) { |
| 383 | u64 mask = root->blocksize - 1; | 382 | u64 mask = root->sectorsize - 1; |
| 384 | search_start = (extent_end + mask) & ~mask; | 383 | search_start = (extent_end + mask) & ~mask; |
| 385 | } else | 384 | } else |
| 386 | search_start = extent_end; | 385 | search_start = extent_end; |
| @@ -388,10 +387,13 @@ next_slot: | |||
| 388 | if (end < extent_end && end >= key.offset) { | 387 | if (end < extent_end && end >= key.offset) { |
| 389 | if (found_extent) { | 388 | if (found_extent) { |
| 390 | u64 disk_blocknr = | 389 | u64 disk_blocknr = |
| 391 | btrfs_file_extent_disk_blocknr(extent); | 390 | btrfs_file_extent_disk_blocknr(leaf,extent); |
| 392 | u64 disk_num_blocks = | 391 | u64 disk_num_blocks = |
| 393 | btrfs_file_extent_disk_num_blocks(extent); | 392 | btrfs_file_extent_disk_num_blocks(leaf, |
| 394 | memcpy(&old, extent, sizeof(old)); | 393 | extent); |
| 394 | read_extent_buffer(leaf, &old, | ||
| 395 | (unsigned long)extent, | ||
| 396 | sizeof(old)); | ||
| 395 | if (disk_blocknr != 0) { | 397 | if (disk_blocknr != 0) { |
| 396 | ret = btrfs_inc_extent_ref(trans, root, | 398 | ret = btrfs_inc_extent_ref(trans, root, |
| 397 | disk_blocknr, disk_num_blocks); | 399 | disk_blocknr, disk_num_blocks); |
| @@ -406,20 +408,24 @@ next_slot: | |||
| 406 | u64 new_num; | 408 | u64 new_num; |
| 407 | u64 old_num; | 409 | u64 old_num; |
| 408 | keep = 1; | 410 | keep = 1; |
| 409 | WARN_ON(start & (root->blocksize - 1)); | 411 | WARN_ON(start & (root->sectorsize - 1)); |
| 410 | if (found_extent) { | 412 | if (found_extent) { |
| 411 | new_num = (start - key.offset) >> | 413 | new_num = (start - key.offset) >> |
| 412 | inode->i_blkbits; | 414 | inode->i_blkbits; |
| 413 | old_num = btrfs_file_extent_num_blocks(extent); | 415 | old_num = btrfs_file_extent_num_blocks(leaf, |
| 416 | extent); | ||
| 414 | *hint_block = | 417 | *hint_block = |
| 415 | btrfs_file_extent_disk_blocknr(extent); | 418 | btrfs_file_extent_disk_blocknr(leaf, |
| 416 | if (btrfs_file_extent_disk_blocknr(extent)) { | 419 | extent); |
| 420 | if (btrfs_file_extent_disk_blocknr(leaf, | ||
| 421 | extent)) { | ||
| 417 | inode->i_blocks -= | 422 | inode->i_blocks -= |
| 418 | (old_num - new_num) << 3; | 423 | (old_num - new_num) << 3; |
| 419 | } | 424 | } |
| 420 | btrfs_set_file_extent_num_blocks(extent, | 425 | btrfs_set_file_extent_num_blocks(leaf, |
| 426 | extent, | ||
| 421 | new_num); | 427 | new_num); |
| 422 | btrfs_mark_buffer_dirty(path->nodes[0]); | 428 | btrfs_mark_buffer_dirty(leaf); |
| 423 | } else { | 429 | } else { |
| 424 | WARN_ON(1); | 430 | WARN_ON(1); |
| 425 | } | 431 | } |
| @@ -431,13 +437,17 @@ next_slot: | |||
| 431 | u64 extent_num_blocks = 0; | 437 | u64 extent_num_blocks = 0; |
| 432 | if (found_extent) { | 438 | if (found_extent) { |
| 433 | disk_blocknr = | 439 | disk_blocknr = |
| 434 | btrfs_file_extent_disk_blocknr(extent); | 440 | btrfs_file_extent_disk_blocknr(leaf, |
| 441 | extent); | ||
| 435 | disk_num_blocks = | 442 | disk_num_blocks = |
| 436 | btrfs_file_extent_disk_num_blocks(extent); | 443 | btrfs_file_extent_disk_num_blocks(leaf, |
| 444 | extent); | ||
| 437 | extent_num_blocks = | 445 | extent_num_blocks = |
| 438 | btrfs_file_extent_num_blocks(extent); | 446 | btrfs_file_extent_num_blocks(leaf, |
| 447 | extent); | ||
| 439 | *hint_block = | 448 | *hint_block = |
| 440 | btrfs_file_extent_disk_blocknr(extent); | 449 | btrfs_file_extent_disk_blocknr(leaf, |
| 450 | extent); | ||
| 441 | } | 451 | } |
| 442 | ret = btrfs_del_item(trans, root, path); | 452 | ret = btrfs_del_item(trans, root, path); |
| 443 | /* TODO update progress marker and return */ | 453 | /* TODO update progress marker and return */ |
| @@ -464,42 +474,37 @@ next_slot: | |||
| 464 | struct btrfs_key ins; | 474 | struct btrfs_key ins; |
| 465 | ins.objectid = inode->i_ino; | 475 | ins.objectid = inode->i_ino; |
| 466 | ins.offset = end; | 476 | ins.offset = end; |
| 467 | ins.flags = 0; | ||
| 468 | btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); | 477 | btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); |
| 469 | btrfs_release_path(root, path); | 478 | btrfs_release_path(root, path); |
| 470 | ret = btrfs_insert_empty_item(trans, root, path, &ins, | 479 | ret = btrfs_insert_empty_item(trans, root, path, &ins, |
| 471 | sizeof(*extent)); | 480 | sizeof(*extent)); |
| 472 | 481 | ||
| 482 | leaf = path->nodes[0]; | ||
| 473 | if (ret) { | 483 | if (ret) { |
| 474 | btrfs_print_leaf(root, btrfs_buffer_leaf(path->nodes[0])); | 484 | btrfs_print_leaf(root, leaf); |
| 475 | printk("got %d on inserting %Lu %u %Lu start %Lu end %Lu found %Lu %Lu keep was %d\n", ret , ins.objectid, ins.flags, ins.offset, start, end, key.offset, extent_end, keep); | 485 | printk("got %d on inserting %Lu %u %Lu start %Lu end %Lu found %Lu %Lu keep was %d\n", ret , ins.objectid, ins.type, ins.offset, start, end, key.offset, extent_end, keep); |
| 476 | } | 486 | } |
| 477 | BUG_ON(ret); | 487 | BUG_ON(ret); |
| 478 | extent = btrfs_item_ptr( | 488 | extent = btrfs_item_ptr(leaf, path->slots[0], |
| 479 | btrfs_buffer_leaf(path->nodes[0]), | 489 | struct btrfs_file_extent_item); |
| 480 | path->slots[0], | 490 | write_extent_buffer(leaf, &old, |
| 481 | struct btrfs_file_extent_item); | 491 | (unsigned long)extent, sizeof(old)); |
| 482 | btrfs_set_file_extent_disk_blocknr(extent, | 492 | |
| 483 | btrfs_file_extent_disk_blocknr(&old)); | 493 | btrfs_set_file_extent_offset(leaf, extent, |
| 484 | btrfs_set_file_extent_disk_num_blocks(extent, | 494 | le64_to_cpu(old.offset) + |
| 485 | btrfs_file_extent_disk_num_blocks(&old)); | ||
| 486 | |||
| 487 | btrfs_set_file_extent_offset(extent, | ||
| 488 | btrfs_file_extent_offset(&old) + | ||
| 489 | ((end - key.offset) >> inode->i_blkbits)); | 495 | ((end - key.offset) >> inode->i_blkbits)); |
| 490 | WARN_ON(btrfs_file_extent_num_blocks(&old) < | 496 | WARN_ON(le64_to_cpu(old.num_blocks) < |
| 491 | (extent_end - end) >> inode->i_blkbits); | 497 | (extent_end - end) >> inode->i_blkbits); |
| 492 | btrfs_set_file_extent_num_blocks(extent, | 498 | btrfs_set_file_extent_num_blocks(leaf, extent, |
| 493 | (extent_end - end) >> inode->i_blkbits); | 499 | (extent_end - end) >> inode->i_blkbits); |
| 494 | 500 | ||
| 495 | btrfs_set_file_extent_type(extent, | 501 | btrfs_set_file_extent_type(leaf, extent, |
| 496 | BTRFS_FILE_EXTENT_REG); | 502 | BTRFS_FILE_EXTENT_REG); |
| 497 | btrfs_set_file_extent_generation(extent, | ||
| 498 | btrfs_file_extent_generation(&old)); | ||
| 499 | btrfs_mark_buffer_dirty(path->nodes[0]); | 503 | btrfs_mark_buffer_dirty(path->nodes[0]); |
| 500 | if (btrfs_file_extent_disk_blocknr(&old) != 0) { | 504 | if (le64_to_cpu(old.disk_blocknr) != 0) { |
| 501 | inode->i_blocks += | 505 | inode->i_blocks += |
| 502 | btrfs_file_extent_num_blocks(extent) << 3; | 506 | btrfs_file_extent_num_blocks(leaf, |
| 507 | extent) << 3; | ||
| 503 | } | 508 | } |
| 504 | ret = 0; | 509 | ret = 0; |
| 505 | goto out; | 510 | goto out; |
| @@ -529,8 +534,8 @@ static int prepare_pages(struct btrfs_root *root, | |||
| 529 | u64 num_blocks; | 534 | u64 num_blocks; |
| 530 | u64 start_pos; | 535 | u64 start_pos; |
| 531 | 536 | ||
| 532 | start_pos = pos & ~((u64)root->blocksize - 1); | 537 | start_pos = pos & ~((u64)root->sectorsize - 1); |
| 533 | num_blocks = (write_bytes + pos - start_pos + root->blocksize - 1) >> | 538 | num_blocks = (write_bytes + pos - start_pos + root->sectorsize - 1) >> |
| 534 | inode->i_blkbits; | 539 | inode->i_blkbits; |
| 535 | 540 | ||
| 536 | memset(pages, 0, num_pages * sizeof(struct page *)); | 541 | memset(pages, 0, num_pages * sizeof(struct page *)); |
diff --git a/fs/btrfs/inode-item.c b/fs/btrfs/inode-item.c index b78346177539..35d2608f8918 100644 --- a/fs/btrfs/inode-item.c +++ b/fs/btrfs/inode-item.c | |||
| @@ -20,24 +20,18 @@ | |||
| 20 | #include "disk-io.h" | 20 | #include "disk-io.h" |
| 21 | #include "transaction.h" | 21 | #include "transaction.h" |
| 22 | 22 | ||
| 23 | int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root | 23 | int btrfs_insert_empty_inode(struct btrfs_trans_handle *trans, |
| 24 | *root, u64 objectid, struct btrfs_inode_item | 24 | struct btrfs_root *root, |
| 25 | *inode_item) | 25 | struct btrfs_path *path, u64 objectid) |
| 26 | { | 26 | { |
| 27 | struct btrfs_path *path; | ||
| 28 | struct btrfs_key key; | 27 | struct btrfs_key key; |
| 29 | int ret; | 28 | int ret; |
| 30 | key.objectid = objectid; | 29 | key.objectid = objectid; |
| 31 | key.flags = 0; | ||
| 32 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | 30 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); |
| 33 | key.offset = 0; | 31 | key.offset = 0; |
| 34 | 32 | ||
| 35 | path = btrfs_alloc_path(); | 33 | ret = btrfs_insert_empty_item(trans, root, path, &key, |
| 36 | BUG_ON(!path); | 34 | sizeof(struct btrfs_inode_item)); |
| 37 | ret = btrfs_insert_item(trans, root, &key, inode_item, | ||
| 38 | sizeof(*inode_item)); | ||
| 39 | btrfs_release_path(root, path); | ||
| 40 | btrfs_free_path(path); | ||
| 41 | if (ret == 0 && objectid > root->highest_inode) | 35 | if (ret == 0 && objectid > root->highest_inode) |
| 42 | root->highest_inode = objectid; | 36 | root->highest_inode = objectid; |
| 43 | return ret; | 37 | return ret; |
| @@ -51,15 +45,15 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 51 | int cow = mod != 0; | 45 | int cow = mod != 0; |
| 52 | int ret; | 46 | int ret; |
| 53 | int slot; | 47 | int slot; |
| 54 | struct btrfs_leaf *leaf; | 48 | struct extent_buffer *leaf; |
| 55 | struct btrfs_key found_key; | 49 | struct btrfs_key found_key; |
| 56 | 50 | ||
| 57 | ret = btrfs_search_slot(trans, root, location, path, ins_len, cow); | 51 | ret = btrfs_search_slot(trans, root, location, path, ins_len, cow); |
| 58 | if (ret > 0 && btrfs_key_type(location) == BTRFS_ROOT_ITEM_KEY && | 52 | if (ret > 0 && btrfs_key_type(location) == BTRFS_ROOT_ITEM_KEY && |
| 59 | location->offset == (u64)-1 && path->slots[0] != 0) { | 53 | location->offset == (u64)-1 && path->slots[0] != 0) { |
| 60 | slot = path->slots[0] - 1; | 54 | slot = path->slots[0] - 1; |
| 61 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 55 | leaf = path->nodes[0]; |
| 62 | btrfs_disk_key_to_cpu(&found_key, &leaf->items[slot].key); | 56 | btrfs_item_key_to_cpu(leaf, &found_key, slot); |
| 63 | if (found_key.objectid == location->objectid && | 57 | if (found_key.objectid == location->objectid && |
| 64 | btrfs_key_type(&found_key) == btrfs_key_type(location)) { | 58 | btrfs_key_type(&found_key) == btrfs_key_type(location)) { |
| 65 | path->slots[0]--; | 59 | path->slots[0]--; |
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index 405470866254..ab74977adf5c 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c | |||
| @@ -24,8 +24,9 @@ int btrfs_find_highest_inode(struct btrfs_root *root, u64 *objectid) | |||
| 24 | { | 24 | { |
| 25 | struct btrfs_path *path; | 25 | struct btrfs_path *path; |
| 26 | int ret; | 26 | int ret; |
| 27 | struct btrfs_leaf *l; | 27 | struct extent_buffer *l; |
| 28 | struct btrfs_key search_key; | 28 | struct btrfs_key search_key; |
| 29 | struct btrfs_key found_key; | ||
| 29 | int slot; | 30 | int slot; |
| 30 | 31 | ||
| 31 | path = btrfs_alloc_path(); | 32 | path = btrfs_alloc_path(); |
| @@ -39,8 +40,9 @@ int btrfs_find_highest_inode(struct btrfs_root *root, u64 *objectid) | |||
| 39 | BUG_ON(ret == 0); | 40 | BUG_ON(ret == 0); |
| 40 | if (path->slots[0] > 0) { | 41 | if (path->slots[0] > 0) { |
| 41 | slot = path->slots[0] - 1; | 42 | slot = path->slots[0] - 1; |
| 42 | l = btrfs_buffer_leaf(path->nodes[0]); | 43 | l = path->nodes[0]; |
| 43 | *objectid = btrfs_disk_key_objectid(&l->items[slot].key); | 44 | btrfs_item_key_to_cpu(l, &found_key, slot); |
| 45 | *objectid = found_key.objectid; | ||
| 44 | } else { | 46 | } else { |
| 45 | *objectid = BTRFS_FIRST_FREE_OBJECTID; | 47 | *objectid = BTRFS_FIRST_FREE_OBJECTID; |
| 46 | } | 48 | } |
| @@ -64,13 +66,12 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | |||
| 64 | int slot = 0; | 66 | int slot = 0; |
| 65 | u64 last_ino = 0; | 67 | u64 last_ino = 0; |
| 66 | int start_found; | 68 | int start_found; |
| 67 | struct btrfs_leaf *l; | 69 | struct extent_buffer *l; |
| 68 | struct btrfs_key search_key; | 70 | struct btrfs_key search_key; |
| 69 | u64 search_start = dirid; | 71 | u64 search_start = dirid; |
| 70 | 72 | ||
| 71 | path = btrfs_alloc_path(); | 73 | path = btrfs_alloc_path(); |
| 72 | BUG_ON(!path); | 74 | BUG_ON(!path); |
| 73 | search_key.flags = 0; | ||
| 74 | search_start = root->last_inode_alloc; | 75 | search_start = root->last_inode_alloc; |
| 75 | search_start = max(search_start, BTRFS_FIRST_FREE_OBJECTID); | 76 | search_start = max(search_start, BTRFS_FIRST_FREE_OBJECTID); |
| 76 | search_key.objectid = search_start; | 77 | search_key.objectid = search_start; |
| @@ -86,9 +87,9 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | |||
| 86 | path->slots[0]--; | 87 | path->slots[0]--; |
| 87 | 88 | ||
| 88 | while (1) { | 89 | while (1) { |
| 89 | l = btrfs_buffer_leaf(path->nodes[0]); | 90 | l = path->nodes[0]; |
| 90 | slot = path->slots[0]; | 91 | slot = path->slots[0]; |
| 91 | if (slot >= btrfs_header_nritems(&l->header)) { | 92 | if (slot >= btrfs_header_nritems(l)) { |
| 92 | ret = btrfs_next_leaf(root, path); | 93 | ret = btrfs_next_leaf(root, path); |
| 93 | if (ret == 0) | 94 | if (ret == 0) |
| 94 | continue; | 95 | continue; |
| @@ -103,7 +104,7 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | |||
| 103 | last_ino : search_start; | 104 | last_ino : search_start; |
| 104 | goto found; | 105 | goto found; |
| 105 | } | 106 | } |
| 106 | btrfs_disk_key_to_cpu(&key, &l->items[slot].key); | 107 | btrfs_item_key_to_cpu(l, &key, slot); |
| 107 | if (key.objectid >= search_start) { | 108 | if (key.objectid >= search_start) { |
| 108 | if (start_found) { | 109 | if (start_found) { |
| 109 | if (last_ino < search_start) | 110 | if (last_ino < search_start) |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index b03d40a907ca..fbe2836364e0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -159,10 +159,8 @@ out: | |||
| 159 | 159 | ||
| 160 | int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end) | 160 | int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end) |
| 161 | { | 161 | { |
| 162 | char csum[BTRFS_CRC32_SIZE]; | ||
| 163 | size_t offset = start - (page->index << PAGE_CACHE_SHIFT); | 162 | size_t offset = start - (page->index << PAGE_CACHE_SHIFT); |
| 164 | struct inode *inode = page->mapping->host; | 163 | struct inode *inode = page->mapping->host; |
| 165 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
| 166 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 164 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
| 167 | char *kaddr; | 165 | char *kaddr; |
| 168 | u64 private; | 166 | u64 private; |
| @@ -173,11 +171,15 @@ int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end) | |||
| 173 | if (ret) { | 171 | if (ret) { |
| 174 | goto zeroit; | 172 | goto zeroit; |
| 175 | } | 173 | } |
| 174 | /* | ||
| 175 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
| 176 | char csum[BTRFS_CRC32_SIZE]; | ||
| 176 | ret = btrfs_csum_data(root, kaddr + offset, end - start + 1, csum); | 177 | ret = btrfs_csum_data(root, kaddr + offset, end - start + 1, csum); |
| 177 | BUG_ON(ret); | 178 | BUG_ON(ret); |
| 178 | if (memcmp(csum, &private, BTRFS_CRC32_SIZE)) { | 179 | if (memcmp(csum, &private, BTRFS_CRC32_SIZE)) { |
| 179 | goto zeroit; | 180 | goto zeroit; |
| 180 | } | 181 | } |
| 182 | */ | ||
| 181 | kunmap_atomic(kaddr, KM_IRQ0); | 183 | kunmap_atomic(kaddr, KM_IRQ0); |
| 182 | return 0; | 184 | return 0; |
| 183 | 185 | ||
| @@ -192,7 +194,9 @@ zeroit: | |||
| 192 | void btrfs_read_locked_inode(struct inode *inode) | 194 | void btrfs_read_locked_inode(struct inode *inode) |
| 193 | { | 195 | { |
| 194 | struct btrfs_path *path; | 196 | struct btrfs_path *path; |
| 197 | struct extent_buffer *leaf; | ||
| 195 | struct btrfs_inode_item *inode_item; | 198 | struct btrfs_inode_item *inode_item; |
| 199 | struct btrfs_inode_timespec *tspec; | ||
| 196 | struct btrfs_root *root = BTRFS_I(inode)->root; | 200 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 197 | struct btrfs_key location; | 201 | struct btrfs_key location; |
| 198 | u64 alloc_group_block; | 202 | u64 alloc_group_block; |
| @@ -205,29 +209,37 @@ void btrfs_read_locked_inode(struct inode *inode) | |||
| 205 | 209 | ||
| 206 | memcpy(&location, &BTRFS_I(inode)->location, sizeof(location)); | 210 | memcpy(&location, &BTRFS_I(inode)->location, sizeof(location)); |
| 207 | ret = btrfs_lookup_inode(NULL, root, path, &location, 0); | 211 | ret = btrfs_lookup_inode(NULL, root, path, &location, 0); |
| 208 | if (ret) { | 212 | if (ret) |
| 209 | goto make_bad; | 213 | goto make_bad; |
| 210 | } | ||
| 211 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
| 212 | path->slots[0], | ||
| 213 | struct btrfs_inode_item); | ||
| 214 | 214 | ||
| 215 | inode->i_mode = btrfs_inode_mode(inode_item); | 215 | leaf = path->nodes[0]; |
| 216 | inode->i_nlink = btrfs_inode_nlink(inode_item); | 216 | inode_item = btrfs_item_ptr(leaf, path->slots[0], |
| 217 | inode->i_uid = btrfs_inode_uid(inode_item); | 217 | struct btrfs_inode_item); |
| 218 | inode->i_gid = btrfs_inode_gid(inode_item); | 218 | |
| 219 | inode->i_size = btrfs_inode_size(inode_item); | 219 | inode->i_mode = btrfs_inode_mode(leaf, inode_item); |
| 220 | inode->i_atime.tv_sec = btrfs_timespec_sec(&inode_item->atime); | 220 | inode->i_nlink = btrfs_inode_nlink(leaf, inode_item); |
| 221 | inode->i_atime.tv_nsec = btrfs_timespec_nsec(&inode_item->atime); | 221 | inode->i_uid = btrfs_inode_uid(leaf, inode_item); |
| 222 | inode->i_mtime.tv_sec = btrfs_timespec_sec(&inode_item->mtime); | 222 | inode->i_gid = btrfs_inode_gid(leaf, inode_item); |
| 223 | inode->i_mtime.tv_nsec = btrfs_timespec_nsec(&inode_item->mtime); | 223 | inode->i_size = btrfs_inode_size(leaf, inode_item); |
| 224 | inode->i_ctime.tv_sec = btrfs_timespec_sec(&inode_item->ctime); | 224 | |
| 225 | inode->i_ctime.tv_nsec = btrfs_timespec_nsec(&inode_item->ctime); | 225 | tspec = btrfs_inode_atime(inode_item); |
| 226 | inode->i_blocks = btrfs_inode_nblocks(inode_item); | 226 | inode->i_atime.tv_sec = btrfs_timespec_sec(leaf, tspec); |
| 227 | inode->i_generation = btrfs_inode_generation(inode_item); | 227 | inode->i_atime.tv_nsec = btrfs_timespec_nsec(leaf, tspec); |
| 228 | |||
| 229 | tspec = btrfs_inode_mtime(inode_item); | ||
| 230 | inode->i_mtime.tv_sec = btrfs_timespec_sec(leaf, tspec); | ||
| 231 | inode->i_mtime.tv_nsec = btrfs_timespec_nsec(leaf, tspec); | ||
| 232 | |||
| 233 | tspec = btrfs_inode_ctime(inode_item); | ||
| 234 | inode->i_ctime.tv_sec = btrfs_timespec_sec(leaf, tspec); | ||
| 235 | inode->i_ctime.tv_nsec = btrfs_timespec_nsec(leaf, tspec); | ||
| 236 | |||
| 237 | inode->i_blocks = btrfs_inode_nblocks(leaf, inode_item); | ||
| 238 | inode->i_generation = btrfs_inode_generation(leaf, inode_item); | ||
| 228 | inode->i_rdev = 0; | 239 | inode->i_rdev = 0; |
| 229 | rdev = btrfs_inode_rdev(inode_item); | 240 | rdev = btrfs_inode_rdev(leaf, inode_item); |
| 230 | alloc_group_block = btrfs_inode_block_group(inode_item); | 241 | |
| 242 | alloc_group_block = btrfs_inode_block_group(leaf, inode_item); | ||
| 231 | BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info, | 243 | BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info, |
| 232 | alloc_group_block); | 244 | alloc_group_block); |
| 233 | 245 | ||
| @@ -267,24 +279,35 @@ make_bad: | |||
| 267 | make_bad_inode(inode); | 279 | make_bad_inode(inode); |
| 268 | } | 280 | } |
| 269 | 281 | ||
| 270 | static void fill_inode_item(struct btrfs_inode_item *item, | 282 | static void fill_inode_item(struct extent_buffer *leaf, |
| 283 | struct btrfs_inode_item *item, | ||
| 271 | struct inode *inode) | 284 | struct inode *inode) |
| 272 | { | 285 | { |
| 273 | btrfs_set_inode_uid(item, inode->i_uid); | 286 | btrfs_set_inode_uid(leaf, item, inode->i_uid); |
| 274 | btrfs_set_inode_gid(item, inode->i_gid); | 287 | btrfs_set_inode_gid(leaf, item, inode->i_gid); |
| 275 | btrfs_set_inode_size(item, inode->i_size); | 288 | btrfs_set_inode_size(leaf, item, inode->i_size); |
| 276 | btrfs_set_inode_mode(item, inode->i_mode); | 289 | btrfs_set_inode_mode(leaf, item, inode->i_mode); |
| 277 | btrfs_set_inode_nlink(item, inode->i_nlink); | 290 | btrfs_set_inode_nlink(leaf, item, inode->i_nlink); |
| 278 | btrfs_set_timespec_sec(&item->atime, inode->i_atime.tv_sec); | 291 | |
| 279 | btrfs_set_timespec_nsec(&item->atime, inode->i_atime.tv_nsec); | 292 | btrfs_set_timespec_sec(leaf, btrfs_inode_atime(item), |
| 280 | btrfs_set_timespec_sec(&item->mtime, inode->i_mtime.tv_sec); | 293 | inode->i_atime.tv_sec); |
| 281 | btrfs_set_timespec_nsec(&item->mtime, inode->i_mtime.tv_nsec); | 294 | btrfs_set_timespec_nsec(leaf, btrfs_inode_atime(item), |
| 282 | btrfs_set_timespec_sec(&item->ctime, inode->i_ctime.tv_sec); | 295 | inode->i_atime.tv_nsec); |
| 283 | btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec); | 296 | |
| 284 | btrfs_set_inode_nblocks(item, inode->i_blocks); | 297 | btrfs_set_timespec_sec(leaf, btrfs_inode_mtime(item), |
| 285 | btrfs_set_inode_generation(item, inode->i_generation); | 298 | inode->i_mtime.tv_sec); |
| 286 | btrfs_set_inode_rdev(item, inode->i_rdev); | 299 | btrfs_set_timespec_nsec(leaf, btrfs_inode_mtime(item), |
| 287 | btrfs_set_inode_block_group(item, | 300 | inode->i_mtime.tv_nsec); |
| 301 | |||
| 302 | btrfs_set_timespec_sec(leaf, btrfs_inode_ctime(item), | ||
| 303 | inode->i_ctime.tv_sec); | ||
| 304 | btrfs_set_timespec_nsec(leaf, btrfs_inode_ctime(item), | ||
| 305 | inode->i_ctime.tv_nsec); | ||
| 306 | |||
| 307 | btrfs_set_inode_nblocks(leaf, item, inode->i_blocks); | ||
| 308 | btrfs_set_inode_generation(leaf, item, inode->i_generation); | ||
| 309 | btrfs_set_inode_rdev(leaf, item, inode->i_rdev); | ||
| 310 | btrfs_set_inode_block_group(leaf, item, | ||
| 288 | BTRFS_I(inode)->block_group->key.objectid); | 311 | BTRFS_I(inode)->block_group->key.objectid); |
| 289 | } | 312 | } |
| 290 | 313 | ||
| @@ -294,6 +317,7 @@ int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
| 294 | { | 317 | { |
| 295 | struct btrfs_inode_item *inode_item; | 318 | struct btrfs_inode_item *inode_item; |
| 296 | struct btrfs_path *path; | 319 | struct btrfs_path *path; |
| 320 | struct extent_buffer *leaf; | ||
| 297 | int ret; | 321 | int ret; |
| 298 | 322 | ||
| 299 | path = btrfs_alloc_path(); | 323 | path = btrfs_alloc_path(); |
| @@ -306,12 +330,12 @@ int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
| 306 | goto failed; | 330 | goto failed; |
| 307 | } | 331 | } |
| 308 | 332 | ||
| 309 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | 333 | leaf = path->nodes[0]; |
| 310 | path->slots[0], | 334 | inode_item = btrfs_item_ptr(leaf, path->slots[0], |
| 311 | struct btrfs_inode_item); | 335 | struct btrfs_inode_item); |
| 312 | 336 | ||
| 313 | fill_inode_item(inode_item, inode); | 337 | fill_inode_item(leaf, inode_item, inode); |
| 314 | btrfs_mark_buffer_dirty(path->nodes[0]); | 338 | btrfs_mark_buffer_dirty(leaf); |
| 315 | btrfs_set_inode_last_trans(trans, inode); | 339 | btrfs_set_inode_last_trans(trans, inode); |
| 316 | ret = 0; | 340 | ret = 0; |
| 317 | failed: | 341 | failed: |
| @@ -330,8 +354,9 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | |||
| 330 | const char *name = dentry->d_name.name; | 354 | const char *name = dentry->d_name.name; |
| 331 | int name_len = dentry->d_name.len; | 355 | int name_len = dentry->d_name.len; |
| 332 | int ret = 0; | 356 | int ret = 0; |
| 333 | u64 objectid; | 357 | struct extent_buffer *leaf; |
| 334 | struct btrfs_dir_item *di; | 358 | struct btrfs_dir_item *di; |
| 359 | struct btrfs_key key; | ||
| 335 | 360 | ||
| 336 | path = btrfs_alloc_path(); | 361 | path = btrfs_alloc_path(); |
| 337 | if (!path) { | 362 | if (!path) { |
| @@ -349,14 +374,15 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | |||
| 349 | ret = -ENOENT; | 374 | ret = -ENOENT; |
| 350 | goto err; | 375 | goto err; |
| 351 | } | 376 | } |
| 352 | objectid = btrfs_disk_key_objectid(&di->location); | 377 | leaf = path->nodes[0]; |
| 378 | btrfs_dir_item_key_to_cpu(leaf, di, &key); | ||
| 353 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | 379 | ret = btrfs_delete_one_dir_name(trans, root, path, di); |
| 354 | if (ret) | 380 | if (ret) |
| 355 | goto err; | 381 | goto err; |
| 356 | btrfs_release_path(root, path); | 382 | btrfs_release_path(root, path); |
| 357 | 383 | ||
| 358 | di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, | 384 | di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, |
| 359 | objectid, name, name_len, -1); | 385 | key.objectid, name, name_len, -1); |
| 360 | if (IS_ERR(di)) { | 386 | if (IS_ERR(di)) { |
| 361 | ret = PTR_ERR(di); | 387 | ret = PTR_ERR(di); |
| 362 | goto err; | 388 | goto err; |
| @@ -391,12 +417,15 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 391 | root = BTRFS_I(dir)->root; | 417 | root = BTRFS_I(dir)->root; |
| 392 | mutex_lock(&root->fs_info->fs_mutex); | 418 | mutex_lock(&root->fs_info->fs_mutex); |
| 393 | trans = btrfs_start_transaction(root, 1); | 419 | trans = btrfs_start_transaction(root, 1); |
| 420 | |||
| 394 | btrfs_set_trans_block_group(trans, dir); | 421 | btrfs_set_trans_block_group(trans, dir); |
| 395 | ret = btrfs_unlink_trans(trans, root, dir, dentry); | 422 | ret = btrfs_unlink_trans(trans, root, dir, dentry); |
| 396 | nr = trans->blocks_used; | 423 | nr = trans->blocks_used; |
| 424 | |||
| 397 | btrfs_end_transaction(trans, root); | 425 | btrfs_end_transaction(trans, root); |
| 398 | mutex_unlock(&root->fs_info->fs_mutex); | 426 | mutex_unlock(&root->fs_info->fs_mutex); |
| 399 | btrfs_btree_balance_dirty(root, nr); | 427 | btrfs_btree_balance_dirty(root, nr); |
| 428 | |||
| 400 | return ret; | 429 | return ret; |
| 401 | } | 430 | } |
| 402 | 431 | ||
| @@ -411,7 +440,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 411 | struct btrfs_trans_handle *trans; | 440 | struct btrfs_trans_handle *trans; |
| 412 | struct btrfs_key found_key; | 441 | struct btrfs_key found_key; |
| 413 | int found_type; | 442 | int found_type; |
| 414 | struct btrfs_leaf *leaf; | 443 | struct extent_buffer *leaf; |
| 415 | char *goodnames = ".."; | 444 | char *goodnames = ".."; |
| 416 | unsigned long nr; | 445 | unsigned long nr; |
| 417 | 446 | ||
| @@ -419,10 +448,11 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 419 | BUG_ON(!path); | 448 | BUG_ON(!path); |
| 420 | mutex_lock(&root->fs_info->fs_mutex); | 449 | mutex_lock(&root->fs_info->fs_mutex); |
| 421 | trans = btrfs_start_transaction(root, 1); | 450 | trans = btrfs_start_transaction(root, 1); |
| 451 | |||
| 422 | btrfs_set_trans_block_group(trans, dir); | 452 | btrfs_set_trans_block_group(trans, dir); |
| 423 | key.objectid = inode->i_ino; | 453 | key.objectid = inode->i_ino; |
| 424 | key.offset = (u64)-1; | 454 | key.offset = (u64)-1; |
| 425 | key.flags = (u32)-1; | 455 | key.type = (u8)-1; |
| 426 | while(1) { | 456 | while(1) { |
| 427 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 457 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
| 428 | if (ret < 0) { | 458 | if (ret < 0) { |
| @@ -435,9 +465,8 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 435 | goto out; | 465 | goto out; |
| 436 | } | 466 | } |
| 437 | path->slots[0]--; | 467 | path->slots[0]--; |
| 438 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 468 | leaf = path->nodes[0]; |
| 439 | btrfs_disk_key_to_cpu(&found_key, | 469 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
| 440 | &leaf->items[path->slots[0]].key); | ||
| 441 | found_type = btrfs_key_type(&found_key); | 470 | found_type = btrfs_key_type(&found_key); |
| 442 | if (found_key.objectid != inode->i_ino) { | 471 | if (found_key.objectid != inode->i_ino) { |
| 443 | err = -ENOENT; | 472 | err = -ENOENT; |
| @@ -513,9 +542,9 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
| 513 | int ret; | 542 | int ret; |
| 514 | struct btrfs_path *path; | 543 | struct btrfs_path *path; |
| 515 | struct btrfs_key key; | 544 | struct btrfs_key key; |
| 516 | struct btrfs_disk_key *found_key; | 545 | struct btrfs_key found_key; |
| 517 | u32 found_type; | 546 | u32 found_type; |
| 518 | struct btrfs_leaf *leaf; | 547 | struct extent_buffer *leaf; |
| 519 | struct btrfs_file_extent_item *fi; | 548 | struct btrfs_file_extent_item *fi; |
| 520 | u64 extent_start = 0; | 549 | u64 extent_start = 0; |
| 521 | u64 extent_num_blocks = 0; | 550 | u64 extent_num_blocks = 0; |
| @@ -527,10 +556,12 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
| 527 | path = btrfs_alloc_path(); | 556 | path = btrfs_alloc_path(); |
| 528 | path->reada = -1; | 557 | path->reada = -1; |
| 529 | BUG_ON(!path); | 558 | BUG_ON(!path); |
| 559 | |||
| 530 | /* FIXME, add redo link to tree so we don't leak on crash */ | 560 | /* FIXME, add redo link to tree so we don't leak on crash */ |
| 531 | key.objectid = inode->i_ino; | 561 | key.objectid = inode->i_ino; |
| 532 | key.offset = (u64)-1; | 562 | key.offset = (u64)-1; |
| 533 | key.flags = (u32)-1; | 563 | key.type = (u8)-1; |
| 564 | |||
| 534 | while(1) { | 565 | while(1) { |
| 535 | btrfs_init_path(path); | 566 | btrfs_init_path(path); |
| 536 | fi = NULL; | 567 | fi = NULL; |
| @@ -542,27 +573,28 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
| 542 | BUG_ON(path->slots[0] == 0); | 573 | BUG_ON(path->slots[0] == 0); |
| 543 | path->slots[0]--; | 574 | path->slots[0]--; |
| 544 | } | 575 | } |
| 545 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 576 | leaf = path->nodes[0]; |
| 546 | found_key = &leaf->items[path->slots[0]].key; | 577 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
| 547 | found_type = btrfs_disk_key_type(found_key); | 578 | found_type = btrfs_key_type(&found_key); |
| 548 | 579 | ||
| 549 | if (btrfs_disk_key_objectid(found_key) != inode->i_ino) | 580 | if (found_key.objectid != inode->i_ino) |
| 550 | break; | 581 | break; |
| 582 | |||
| 551 | if (found_type != BTRFS_CSUM_ITEM_KEY && | 583 | if (found_type != BTRFS_CSUM_ITEM_KEY && |
| 552 | found_type != BTRFS_DIR_ITEM_KEY && | 584 | found_type != BTRFS_DIR_ITEM_KEY && |
| 553 | found_type != BTRFS_DIR_INDEX_KEY && | 585 | found_type != BTRFS_DIR_INDEX_KEY && |
| 554 | found_type != BTRFS_EXTENT_DATA_KEY) | 586 | found_type != BTRFS_EXTENT_DATA_KEY) |
| 555 | break; | 587 | break; |
| 556 | 588 | ||
| 557 | item_end = btrfs_disk_key_offset(found_key); | 589 | item_end = found_key.offset; |
| 558 | if (found_type == BTRFS_EXTENT_DATA_KEY) { | 590 | if (found_type == BTRFS_EXTENT_DATA_KEY) { |
| 559 | fi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | 591 | fi = btrfs_item_ptr(leaf, path->slots[0], |
| 560 | path->slots[0], | ||
| 561 | struct btrfs_file_extent_item); | 592 | struct btrfs_file_extent_item); |
| 562 | if (btrfs_file_extent_type(fi) != | 593 | if (btrfs_file_extent_type(leaf, fi) != |
| 563 | BTRFS_FILE_EXTENT_INLINE) { | 594 | BTRFS_FILE_EXTENT_INLINE) { |
| 564 | item_end += btrfs_file_extent_num_blocks(fi) << | 595 | item_end += |
| 565 | inode->i_blkbits; | 596 | btrfs_file_extent_num_blocks(leaf, fi) << |
| 597 | inode->i_blkbits; | ||
| 566 | } | 598 | } |
| 567 | } | 599 | } |
| 568 | if (found_type == BTRFS_CSUM_ITEM_KEY) { | 600 | if (found_type == BTRFS_CSUM_ITEM_KEY) { |
| @@ -583,7 +615,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
| 583 | btrfs_set_key_type(&key, found_type); | 615 | btrfs_set_key_type(&key, found_type); |
| 584 | continue; | 616 | continue; |
| 585 | } | 617 | } |
| 586 | if (btrfs_disk_key_offset(found_key) >= inode->i_size) | 618 | if (found_key.offset >= inode->i_size) |
| 587 | del_item = 1; | 619 | del_item = 1; |
| 588 | else | 620 | else |
| 589 | del_item = 0; | 621 | del_item = 0; |
| @@ -591,30 +623,31 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
| 591 | 623 | ||
| 592 | /* FIXME, shrink the extent if the ref count is only 1 */ | 624 | /* FIXME, shrink the extent if the ref count is only 1 */ |
| 593 | if (found_type == BTRFS_EXTENT_DATA_KEY && | 625 | if (found_type == BTRFS_EXTENT_DATA_KEY && |
| 594 | btrfs_file_extent_type(fi) != | 626 | btrfs_file_extent_type(leaf, fi) != |
| 595 | BTRFS_FILE_EXTENT_INLINE) { | 627 | BTRFS_FILE_EXTENT_INLINE) { |
| 596 | u64 num_dec; | 628 | u64 num_dec; |
| 597 | extent_start = btrfs_file_extent_disk_blocknr(fi); | 629 | extent_start = btrfs_file_extent_disk_blocknr(leaf, fi); |
| 598 | if (!del_item) { | 630 | if (!del_item) { |
| 599 | u64 orig_num_blocks = | 631 | u64 orig_num_blocks = |
| 600 | btrfs_file_extent_num_blocks(fi); | 632 | btrfs_file_extent_num_blocks(leaf, fi); |
| 601 | extent_num_blocks = inode->i_size - | 633 | extent_num_blocks = inode->i_size - |
| 602 | btrfs_disk_key_offset(found_key) + | 634 | found_key.offset + root->sectorsize - 1; |
| 603 | root->blocksize - 1; | ||
| 604 | extent_num_blocks >>= inode->i_blkbits; | 635 | extent_num_blocks >>= inode->i_blkbits; |
| 605 | btrfs_set_file_extent_num_blocks(fi, | 636 | btrfs_set_file_extent_num_blocks(leaf, fi, |
| 606 | extent_num_blocks); | 637 | extent_num_blocks); |
| 607 | num_dec = (orig_num_blocks - | 638 | num_dec = (orig_num_blocks - |
| 608 | extent_num_blocks) << 3; | 639 | extent_num_blocks) << 3; |
| 609 | if (extent_start != 0) { | 640 | if (extent_start != 0) { |
| 610 | inode->i_blocks -= num_dec; | 641 | inode->i_blocks -= num_dec; |
| 611 | } | 642 | } |
| 612 | btrfs_mark_buffer_dirty(path->nodes[0]); | 643 | btrfs_mark_buffer_dirty(leaf); |
| 613 | } else { | 644 | } else { |
| 614 | extent_num_blocks = | 645 | extent_num_blocks = |
| 615 | btrfs_file_extent_disk_num_blocks(fi); | 646 | btrfs_file_extent_disk_num_blocks(leaf, |
| 647 | fi); | ||
| 616 | /* FIXME blocksize != 4096 */ | 648 | /* FIXME blocksize != 4096 */ |
| 617 | num_dec = btrfs_file_extent_num_blocks(fi) << 3; | 649 | num_dec = btrfs_file_extent_num_blocks(leaf, |
| 650 | fi) << 3; | ||
| 618 | if (extent_start != 0) { | 651 | if (extent_start != 0) { |
| 619 | found_extent = 1; | 652 | found_extent = 1; |
| 620 | inode->i_blocks -= num_dec; | 653 | inode->i_blocks -= num_dec; |
| @@ -725,7 +758,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 725 | struct btrfs_root *root = BTRFS_I(inode)->root; | 758 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 726 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 759 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
| 727 | 760 | ||
| 728 | u64 mask = root->blocksize - 1; | 761 | u64 mask = root->sectorsize - 1; |
| 729 | u64 pos = (inode->i_size + mask) & ~mask; | 762 | u64 pos = (inode->i_size + mask) & ~mask; |
| 730 | u64 block_end = attr->ia_size | mask; | 763 | u64 block_end = attr->ia_size | mask; |
| 731 | u64 hole_size; | 764 | u64 hole_size; |
| @@ -771,9 +804,11 @@ void btrfs_delete_inode(struct inode *inode) | |||
| 771 | if (is_bad_inode(inode)) { | 804 | if (is_bad_inode(inode)) { |
| 772 | goto no_delete; | 805 | goto no_delete; |
| 773 | } | 806 | } |
| 807 | |||
| 774 | inode->i_size = 0; | 808 | inode->i_size = 0; |
| 775 | mutex_lock(&root->fs_info->fs_mutex); | 809 | mutex_lock(&root->fs_info->fs_mutex); |
| 776 | trans = btrfs_start_transaction(root, 1); | 810 | trans = btrfs_start_transaction(root, 1); |
| 811 | |||
| 777 | btrfs_set_trans_block_group(trans, inode); | 812 | btrfs_set_trans_block_group(trans, inode); |
| 778 | ret = btrfs_truncate_in_trans(trans, root, inode); | 813 | ret = btrfs_truncate_in_trans(trans, root, inode); |
| 779 | if (ret) | 814 | if (ret) |
| @@ -782,6 +817,7 @@ void btrfs_delete_inode(struct inode *inode) | |||
| 782 | if (ret) | 817 | if (ret) |
| 783 | goto no_delete_lock; | 818 | goto no_delete_lock; |
| 784 | nr = trans->blocks_used; | 819 | nr = trans->blocks_used; |
| 820 | |||
| 785 | btrfs_end_transaction(trans, root); | 821 | btrfs_end_transaction(trans, root); |
| 786 | mutex_unlock(&root->fs_info->fs_mutex); | 822 | mutex_unlock(&root->fs_info->fs_mutex); |
| 787 | btrfs_btree_balance_dirty(root, nr); | 823 | btrfs_btree_balance_dirty(root, nr); |
| @@ -819,7 +855,7 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, | |||
| 819 | ret = 0; | 855 | ret = 0; |
| 820 | goto out; | 856 | goto out; |
| 821 | } | 857 | } |
| 822 | btrfs_disk_key_to_cpu(location, &di->location); | 858 | btrfs_dir_item_key_to_cpu(path->nodes[0], di, location); |
| 823 | out: | 859 | out: |
| 824 | btrfs_release_path(root, path); | 860 | btrfs_release_path(root, path); |
| 825 | btrfs_free_path(path); | 861 | btrfs_free_path(path); |
| @@ -856,7 +892,6 @@ static int fixup_tree_root_location(struct btrfs_root *root, | |||
| 856 | 892 | ||
| 857 | ri = &(*sub_root)->root_item; | 893 | ri = &(*sub_root)->root_item; |
| 858 | location->objectid = btrfs_root_dirid(ri); | 894 | location->objectid = btrfs_root_dirid(ri); |
| 859 | location->flags = 0; | ||
| 860 | btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY); | 895 | btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY); |
| 861 | location->offset = 0; | 896 | location->offset = 0; |
| 862 | 897 | ||
| @@ -908,11 +943,14 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 908 | 943 | ||
| 909 | if (dentry->d_name.len > BTRFS_NAME_LEN) | 944 | if (dentry->d_name.len > BTRFS_NAME_LEN) |
| 910 | return ERR_PTR(-ENAMETOOLONG); | 945 | return ERR_PTR(-ENAMETOOLONG); |
| 946 | |||
| 911 | mutex_lock(&root->fs_info->fs_mutex); | 947 | mutex_lock(&root->fs_info->fs_mutex); |
| 912 | ret = btrfs_inode_by_name(dir, dentry, &location); | 948 | ret = btrfs_inode_by_name(dir, dentry, &location); |
| 913 | mutex_unlock(&root->fs_info->fs_mutex); | 949 | mutex_unlock(&root->fs_info->fs_mutex); |
| 950 | |||
| 914 | if (ret < 0) | 951 | if (ret < 0) |
| 915 | return ERR_PTR(ret); | 952 | return ERR_PTR(ret); |
| 953 | |||
| 916 | inode = NULL; | 954 | inode = NULL; |
| 917 | if (location.objectid) { | 955 | if (location.objectid) { |
| 918 | ret = fixup_tree_root_location(root, &location, &sub_root, | 956 | ret = fixup_tree_root_location(root, &location, &sub_root, |
| @@ -952,10 +990,11 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 952 | struct btrfs_item *item; | 990 | struct btrfs_item *item; |
| 953 | struct btrfs_dir_item *di; | 991 | struct btrfs_dir_item *di; |
| 954 | struct btrfs_key key; | 992 | struct btrfs_key key; |
| 993 | struct btrfs_key found_key; | ||
| 955 | struct btrfs_path *path; | 994 | struct btrfs_path *path; |
| 956 | int ret; | 995 | int ret; |
| 957 | u32 nritems; | 996 | u32 nritems; |
| 958 | struct btrfs_leaf *leaf; | 997 | struct extent_buffer *leaf; |
| 959 | int slot; | 998 | int slot; |
| 960 | int advance; | 999 | int advance; |
| 961 | unsigned char d_type; | 1000 | unsigned char d_type; |
| @@ -964,15 +1003,19 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 964 | u32 di_total; | 1003 | u32 di_total; |
| 965 | u32 di_len; | 1004 | u32 di_len; |
| 966 | int key_type = BTRFS_DIR_INDEX_KEY; | 1005 | int key_type = BTRFS_DIR_INDEX_KEY; |
| 1006 | char tmp_name[32]; | ||
| 1007 | char *name_ptr; | ||
| 1008 | int name_len; | ||
| 967 | 1009 | ||
| 968 | /* FIXME, use a real flag for deciding about the key type */ | 1010 | /* FIXME, use a real flag for deciding about the key type */ |
| 969 | if (root->fs_info->tree_root == root) | 1011 | if (root->fs_info->tree_root == root) |
| 970 | key_type = BTRFS_DIR_ITEM_KEY; | 1012 | key_type = BTRFS_DIR_ITEM_KEY; |
| 1013 | |||
| 971 | mutex_lock(&root->fs_info->fs_mutex); | 1014 | mutex_lock(&root->fs_info->fs_mutex); |
| 972 | key.objectid = inode->i_ino; | 1015 | key.objectid = inode->i_ino; |
| 973 | key.flags = 0; | ||
| 974 | btrfs_set_key_type(&key, key_type); | 1016 | btrfs_set_key_type(&key, key_type); |
| 975 | key.offset = filp->f_pos; | 1017 | key.offset = filp->f_pos; |
| 1018 | |||
| 976 | path = btrfs_alloc_path(); | 1019 | path = btrfs_alloc_path(); |
| 977 | path->reada = 2; | 1020 | path->reada = 2; |
| 978 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 1021 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
| @@ -980,16 +1023,16 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 980 | goto err; | 1023 | goto err; |
| 981 | advance = 0; | 1024 | advance = 0; |
| 982 | while(1) { | 1025 | while(1) { |
| 983 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 1026 | leaf = path->nodes[0]; |
| 984 | nritems = btrfs_header_nritems(&leaf->header); | 1027 | nritems = btrfs_header_nritems(leaf); |
| 985 | slot = path->slots[0]; | 1028 | slot = path->slots[0]; |
| 986 | if (advance || slot >= nritems) { | 1029 | if (advance || slot >= nritems) { |
| 987 | if (slot >= nritems -1) { | 1030 | if (slot >= nritems -1) { |
| 988 | ret = btrfs_next_leaf(root, path); | 1031 | ret = btrfs_next_leaf(root, path); |
| 989 | if (ret) | 1032 | if (ret) |
| 990 | break; | 1033 | break; |
| 991 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 1034 | leaf = path->nodes[0]; |
| 992 | nritems = btrfs_header_nritems(&leaf->header); | 1035 | nritems = btrfs_header_nritems(leaf); |
| 993 | slot = path->slots[0]; | 1036 | slot = path->slots[0]; |
| 994 | } else { | 1037 | } else { |
| 995 | slot++; | 1038 | slot++; |
| @@ -997,28 +1040,48 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 997 | } | 1040 | } |
| 998 | } | 1041 | } |
| 999 | advance = 1; | 1042 | advance = 1; |
| 1000 | item = leaf->items + slot; | 1043 | item = btrfs_item_nr(leaf, slot); |
| 1001 | if (btrfs_disk_key_objectid(&item->key) != key.objectid) | 1044 | btrfs_item_key_to_cpu(leaf, &found_key, slot); |
| 1045 | |||
| 1046 | if (found_key.objectid != key.objectid) | ||
| 1002 | break; | 1047 | break; |
| 1003 | if (btrfs_disk_key_type(&item->key) != key_type) | 1048 | if (btrfs_key_type(&found_key) != key_type) |
| 1004 | break; | 1049 | break; |
| 1005 | if (btrfs_disk_key_offset(&item->key) < filp->f_pos) | 1050 | if (found_key.offset < filp->f_pos) |
| 1006 | continue; | 1051 | continue; |
| 1007 | filp->f_pos = btrfs_disk_key_offset(&item->key); | 1052 | |
| 1053 | filp->f_pos = found_key.offset; | ||
| 1008 | advance = 1; | 1054 | advance = 1; |
| 1009 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); | 1055 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); |
| 1010 | di_cur = 0; | 1056 | di_cur = 0; |
| 1011 | di_total = btrfs_item_size(leaf->items + slot); | 1057 | di_total = btrfs_item_size(leaf, item); |
| 1012 | while(di_cur < di_total) { | 1058 | while(di_cur < di_total) { |
| 1013 | d_type = btrfs_filetype_table[btrfs_dir_type(di)]; | 1059 | struct btrfs_key location; |
| 1014 | over = filldir(dirent, (const char *)(di + 1), | 1060 | |
| 1015 | btrfs_dir_name_len(di), | 1061 | name_len = btrfs_dir_name_len(leaf, di); |
| 1016 | btrfs_disk_key_offset(&item->key), | 1062 | if (name_len < 32) { |
| 1017 | btrfs_disk_key_objectid(&di->location), | 1063 | name_ptr = tmp_name; |
| 1064 | } else { | ||
| 1065 | name_ptr = kmalloc(name_len, GFP_NOFS); | ||
| 1066 | BUG_ON(!name_ptr); | ||
| 1067 | } | ||
| 1068 | read_extent_buffer(leaf, name_ptr, | ||
| 1069 | (unsigned long)(di + 1), name_len); | ||
| 1070 | |||
| 1071 | d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)]; | ||
| 1072 | btrfs_dir_item_key_to_cpu(leaf, di, &location); | ||
| 1073 | |||
| 1074 | over = filldir(dirent, name_ptr, name_len, | ||
| 1075 | found_key.offset, | ||
| 1076 | location.objectid, | ||
| 1018 | d_type); | 1077 | d_type); |
| 1078 | |||
| 1079 | if (name_ptr != tmp_name) | ||
| 1080 | kfree(name_ptr); | ||
| 1081 | |||
| 1019 | if (over) | 1082 | if (over) |
| 1020 | goto nopos; | 1083 | goto nopos; |
| 1021 | di_len = btrfs_dir_name_len(di) + sizeof(*di); | 1084 | di_len = btrfs_dir_name_len(leaf, di) + sizeof(*di); |
| 1022 | di_cur += di_len; | 1085 | di_cur += di_len; |
| 1023 | di = (struct btrfs_dir_item *)((char *)di + di_len); | 1086 | di = (struct btrfs_dir_item *)((char *)di + di_len); |
| 1024 | } | 1087 | } |
| @@ -1075,11 +1138,15 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
| 1075 | int mode) | 1138 | int mode) |
| 1076 | { | 1139 | { |
| 1077 | struct inode *inode; | 1140 | struct inode *inode; |
| 1078 | struct btrfs_inode_item inode_item; | 1141 | struct btrfs_inode_item *inode_item; |
| 1079 | struct btrfs_key *location; | 1142 | struct btrfs_key *location; |
| 1143 | struct btrfs_path *path; | ||
| 1080 | int ret; | 1144 | int ret; |
| 1081 | int owner; | 1145 | int owner; |
| 1082 | 1146 | ||
| 1147 | path = btrfs_alloc_path(); | ||
| 1148 | BUG_ON(!path); | ||
| 1149 | |||
| 1083 | inode = new_inode(root->fs_info->sb); | 1150 | inode = new_inode(root->fs_info->sb); |
| 1084 | if (!inode) | 1151 | if (!inode) |
| 1085 | return ERR_PTR(-ENOMEM); | 1152 | return ERR_PTR(-ENOMEM); |
| @@ -1095,24 +1162,32 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
| 1095 | group = btrfs_find_block_group(root, group, 0, 0, owner); | 1162 | group = btrfs_find_block_group(root, group, 0, 0, owner); |
| 1096 | BTRFS_I(inode)->block_group = group; | 1163 | BTRFS_I(inode)->block_group = group; |
| 1097 | 1164 | ||
| 1165 | ret = btrfs_insert_empty_inode(trans, root, path, objectid); | ||
| 1166 | if (ret) | ||
| 1167 | goto fail; | ||
| 1168 | |||
| 1098 | inode->i_uid = current->fsuid; | 1169 | inode->i_uid = current->fsuid; |
| 1099 | inode->i_gid = current->fsgid; | 1170 | inode->i_gid = current->fsgid; |
| 1100 | inode->i_mode = mode; | 1171 | inode->i_mode = mode; |
| 1101 | inode->i_ino = objectid; | 1172 | inode->i_ino = objectid; |
| 1102 | inode->i_blocks = 0; | 1173 | inode->i_blocks = 0; |
| 1103 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 1174 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
| 1104 | fill_inode_item(&inode_item, inode); | 1175 | inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0], |
| 1176 | struct btrfs_inode_item); | ||
| 1177 | fill_inode_item(path->nodes[0], inode_item, inode); | ||
| 1178 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
| 1179 | btrfs_free_path(path); | ||
| 1180 | |||
| 1105 | location = &BTRFS_I(inode)->location; | 1181 | location = &BTRFS_I(inode)->location; |
| 1106 | location->objectid = objectid; | 1182 | location->objectid = objectid; |
| 1107 | location->flags = 0; | ||
| 1108 | location->offset = 0; | 1183 | location->offset = 0; |
| 1109 | btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY); | 1184 | btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY); |
| 1110 | 1185 | ||
| 1111 | ret = btrfs_insert_inode(trans, root, objectid, &inode_item); | ||
| 1112 | if (ret) | ||
| 1113 | return ERR_PTR(ret); | ||
| 1114 | insert_inode_hash(inode); | 1186 | insert_inode_hash(inode); |
| 1115 | return inode; | 1187 | return inode; |
| 1188 | fail: | ||
| 1189 | btrfs_free_path(path); | ||
| 1190 | return ERR_PTR(ret); | ||
| 1116 | } | 1191 | } |
| 1117 | 1192 | ||
| 1118 | static inline u8 btrfs_inode_type(struct inode *inode) | 1193 | static inline u8 btrfs_inode_type(struct inode *inode) |
| @@ -1127,8 +1202,8 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
| 1127 | struct btrfs_key key; | 1202 | struct btrfs_key key; |
| 1128 | struct btrfs_root *root = BTRFS_I(dentry->d_parent->d_inode)->root; | 1203 | struct btrfs_root *root = BTRFS_I(dentry->d_parent->d_inode)->root; |
| 1129 | struct inode *parent_inode; | 1204 | struct inode *parent_inode; |
| 1205 | |||
| 1130 | key.objectid = inode->i_ino; | 1206 | key.objectid = inode->i_ino; |
| 1131 | key.flags = 0; | ||
| 1132 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | 1207 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); |
| 1133 | key.offset = 0; | 1208 | key.offset = 0; |
| 1134 | 1209 | ||
| @@ -1285,14 +1360,18 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
| 1285 | inc_nlink(inode); | 1360 | inc_nlink(inode); |
| 1286 | mutex_lock(&root->fs_info->fs_mutex); | 1361 | mutex_lock(&root->fs_info->fs_mutex); |
| 1287 | trans = btrfs_start_transaction(root, 1); | 1362 | trans = btrfs_start_transaction(root, 1); |
| 1363 | |||
| 1288 | btrfs_set_trans_block_group(trans, dir); | 1364 | btrfs_set_trans_block_group(trans, dir); |
| 1289 | atomic_inc(&inode->i_count); | 1365 | atomic_inc(&inode->i_count); |
| 1290 | err = btrfs_add_nondir(trans, dentry, inode); | 1366 | err = btrfs_add_nondir(trans, dentry, inode); |
| 1367 | |||
| 1291 | if (err) | 1368 | if (err) |
| 1292 | drop_inode = 1; | 1369 | drop_inode = 1; |
| 1370 | |||
| 1293 | dir->i_sb->s_dirt = 1; | 1371 | dir->i_sb->s_dirt = 1; |
| 1294 | btrfs_update_inode_block_group(trans, dir); | 1372 | btrfs_update_inode_block_group(trans, dir); |
| 1295 | err = btrfs_update_inode(trans, root, inode); | 1373 | err = btrfs_update_inode(trans, root, inode); |
| 1374 | |||
| 1296 | if (err) | 1375 | if (err) |
| 1297 | drop_inode = 1; | 1376 | drop_inode = 1; |
| 1298 | 1377 | ||
| @@ -1321,13 +1400,13 @@ static int btrfs_make_empty_dir(struct btrfs_trans_handle *trans, | |||
| 1321 | 1400 | ||
| 1322 | key.objectid = objectid; | 1401 | key.objectid = objectid; |
| 1323 | key.offset = 0; | 1402 | key.offset = 0; |
| 1324 | key.flags = 0; | ||
| 1325 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | 1403 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); |
| 1326 | 1404 | ||
| 1327 | ret = btrfs_insert_dir_item(trans, root, buf, 1, objectid, | 1405 | ret = btrfs_insert_dir_item(trans, root, buf, 1, objectid, |
| 1328 | &key, BTRFS_FT_DIR); | 1406 | &key, BTRFS_FT_DIR); |
| 1329 | if (ret) | 1407 | if (ret) |
| 1330 | goto error; | 1408 | goto error; |
| 1409 | |||
| 1331 | key.objectid = dirid; | 1410 | key.objectid = dirid; |
| 1332 | ret = btrfs_insert_dir_item(trans, root, buf, 2, objectid, | 1411 | ret = btrfs_insert_dir_item(trans, root, buf, 2, objectid, |
| 1333 | &key, BTRFS_FT_DIR); | 1412 | &key, BTRFS_FT_DIR); |
| @@ -1350,6 +1429,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 1350 | mutex_lock(&root->fs_info->fs_mutex); | 1429 | mutex_lock(&root->fs_info->fs_mutex); |
| 1351 | trans = btrfs_start_transaction(root, 1); | 1430 | trans = btrfs_start_transaction(root, 1); |
| 1352 | btrfs_set_trans_block_group(trans, dir); | 1431 | btrfs_set_trans_block_group(trans, dir); |
| 1432 | |||
| 1353 | if (IS_ERR(trans)) { | 1433 | if (IS_ERR(trans)) { |
| 1354 | err = PTR_ERR(trans); | 1434 | err = PTR_ERR(trans); |
| 1355 | goto out_unlock; | 1435 | goto out_unlock; |
| @@ -1367,6 +1447,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 1367 | err = PTR_ERR(inode); | 1447 | err = PTR_ERR(inode); |
| 1368 | goto out_fail; | 1448 | goto out_fail; |
| 1369 | } | 1449 | } |
| 1450 | |||
| 1370 | drop_on_err = 1; | 1451 | drop_on_err = 1; |
| 1371 | inode->i_op = &btrfs_dir_inode_operations; | 1452 | inode->i_op = &btrfs_dir_inode_operations; |
| 1372 | inode->i_fop = &btrfs_dir_file_operations; | 1453 | inode->i_fop = &btrfs_dir_file_operations; |
| @@ -1380,9 +1461,11 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 1380 | err = btrfs_update_inode(trans, root, inode); | 1461 | err = btrfs_update_inode(trans, root, inode); |
| 1381 | if (err) | 1462 | if (err) |
| 1382 | goto out_fail; | 1463 | goto out_fail; |
| 1464 | |||
| 1383 | err = btrfs_add_link(trans, dentry, inode); | 1465 | err = btrfs_add_link(trans, dentry, inode); |
| 1384 | if (err) | 1466 | if (err) |
| 1385 | goto out_fail; | 1467 | goto out_fail; |
| 1468 | |||
| 1386 | d_instantiate(dentry, inode); | 1469 | d_instantiate(dentry, inode); |
| 1387 | drop_on_err = 0; | 1470 | drop_on_err = 0; |
| 1388 | dir->i_sb->s_dirt = 1; | 1471 | dir->i_sb->s_dirt = 1; |
| @@ -1392,6 +1475,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 1392 | out_fail: | 1475 | out_fail: |
| 1393 | nr = trans->blocks_used; | 1476 | nr = trans->blocks_used; |
| 1394 | btrfs_end_transaction(trans, root); | 1477 | btrfs_end_transaction(trans, root); |
| 1478 | |||
| 1395 | out_unlock: | 1479 | out_unlock: |
| 1396 | mutex_unlock(&root->fs_info->fs_mutex); | 1480 | mutex_unlock(&root->fs_info->fs_mutex); |
| 1397 | if (drop_on_err) | 1481 | if (drop_on_err) |
| @@ -1415,8 +1499,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, | |||
| 1415 | struct btrfs_path *path; | 1499 | struct btrfs_path *path; |
| 1416 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1500 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 1417 | struct btrfs_file_extent_item *item; | 1501 | struct btrfs_file_extent_item *item; |
| 1418 | struct btrfs_leaf *leaf; | 1502 | struct extent_buffer *leaf; |
| 1419 | struct btrfs_disk_key *found_key; | 1503 | struct btrfs_key found_key; |
| 1420 | struct extent_map *em = NULL; | 1504 | struct extent_map *em = NULL; |
| 1421 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 1505 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
| 1422 | struct btrfs_trans_handle *trans = NULL; | 1506 | struct btrfs_trans_handle *trans = NULL; |
| @@ -1436,8 +1520,8 @@ again: | |||
| 1436 | err = -ENOMEM; | 1520 | err = -ENOMEM; |
| 1437 | goto out; | 1521 | goto out; |
| 1438 | } | 1522 | } |
| 1439 | em->start = 0; | 1523 | em->start = EXTENT_MAP_HOLE; |
| 1440 | em->end = 0; | 1524 | em->end = EXTENT_MAP_HOLE; |
| 1441 | } | 1525 | } |
| 1442 | em->bdev = inode->i_sb->s_bdev; | 1526 | em->bdev = inode->i_sb->s_bdev; |
| 1443 | ret = btrfs_lookup_file_extent(NULL, root, path, | 1527 | ret = btrfs_lookup_file_extent(NULL, root, path, |
| @@ -1453,25 +1537,27 @@ again: | |||
| 1453 | path->slots[0]--; | 1537 | path->slots[0]--; |
| 1454 | } | 1538 | } |
| 1455 | 1539 | ||
| 1456 | item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | 1540 | leaf = path->nodes[0]; |
| 1541 | item = btrfs_item_ptr(leaf, path->slots[0], | ||
| 1457 | struct btrfs_file_extent_item); | 1542 | struct btrfs_file_extent_item); |
| 1458 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 1543 | |
| 1459 | blocknr = btrfs_file_extent_disk_blocknr(item); | 1544 | blocknr = btrfs_file_extent_disk_blocknr(leaf, item); |
| 1460 | blocknr += btrfs_file_extent_offset(item); | 1545 | blocknr += btrfs_file_extent_offset(leaf, item); |
| 1461 | 1546 | ||
| 1462 | /* are we inside the extent that was found? */ | 1547 | /* are we inside the extent that was found? */ |
| 1463 | found_key = &leaf->items[path->slots[0]].key; | 1548 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
| 1464 | found_type = btrfs_disk_key_type(found_key); | 1549 | found_type = btrfs_key_type(&found_key); |
| 1465 | if (btrfs_disk_key_objectid(found_key) != objectid || | 1550 | if (found_key.objectid != objectid || |
| 1466 | found_type != BTRFS_EXTENT_DATA_KEY) { | 1551 | found_type != BTRFS_EXTENT_DATA_KEY) { |
| 1467 | goto not_found; | 1552 | goto not_found; |
| 1468 | } | 1553 | } |
| 1469 | 1554 | ||
| 1470 | found_type = btrfs_file_extent_type(item); | 1555 | found_type = btrfs_file_extent_type(leaf, item); |
| 1471 | extent_start = btrfs_disk_key_offset(&leaf->items[path->slots[0]].key); | 1556 | extent_start = found_key.offset; |
| 1472 | if (found_type == BTRFS_FILE_EXTENT_REG) { | 1557 | if (found_type == BTRFS_FILE_EXTENT_REG) { |
| 1473 | extent_end = extent_start + | 1558 | extent_end = extent_start + |
| 1474 | (btrfs_file_extent_num_blocks(item) << inode->i_blkbits); | 1559 | (btrfs_file_extent_num_blocks(leaf, item) << |
| 1560 | inode->i_blkbits); | ||
| 1475 | err = 0; | 1561 | err = 0; |
| 1476 | if (start < extent_start || start >= extent_end) { | 1562 | if (start < extent_start || start >= extent_end) { |
| 1477 | em->start = start; | 1563 | em->start = start; |
| @@ -1484,28 +1570,29 @@ again: | |||
| 1484 | } | 1570 | } |
| 1485 | goto not_found_em; | 1571 | goto not_found_em; |
| 1486 | } | 1572 | } |
| 1487 | if (btrfs_file_extent_disk_blocknr(item) == 0) { | 1573 | if (btrfs_file_extent_disk_blocknr(leaf, item) == 0) { |
| 1488 | em->start = extent_start; | 1574 | em->start = extent_start; |
| 1489 | em->end = extent_end - 1; | 1575 | em->end = extent_end - 1; |
| 1490 | em->block_start = 0; | 1576 | em->block_start = EXTENT_MAP_HOLE; |
| 1491 | em->block_end = 0; | 1577 | em->block_end = EXTENT_MAP_HOLE; |
| 1492 | goto insert; | 1578 | goto insert; |
| 1493 | } | 1579 | } |
| 1494 | em->block_start = blocknr << inode->i_blkbits; | 1580 | em->block_start = blocknr << inode->i_blkbits; |
| 1495 | em->block_end = em->block_start + | 1581 | em->block_end = em->block_start + |
| 1496 | (btrfs_file_extent_num_blocks(item) << | 1582 | (btrfs_file_extent_num_blocks(leaf, item) << |
| 1497 | inode->i_blkbits) - 1; | 1583 | inode->i_blkbits) - 1; |
| 1498 | em->start = extent_start; | 1584 | em->start = extent_start; |
| 1499 | em->end = extent_end - 1; | 1585 | em->end = extent_end - 1; |
| 1500 | goto insert; | 1586 | goto insert; |
| 1501 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | 1587 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { |
| 1502 | char *ptr; | 1588 | unsigned long ptr; |
| 1503 | char *map; | 1589 | char *map; |
| 1504 | u32 size; | 1590 | u32 size; |
| 1505 | 1591 | ||
| 1506 | size = btrfs_file_extent_inline_len(leaf->items + | 1592 | size = btrfs_file_extent_inline_len(leaf, btrfs_item_nr(leaf, |
| 1507 | path->slots[0]); | 1593 | path->slots[0])); |
| 1508 | extent_end = extent_start | ((u64)root->blocksize - 1); | 1594 | |
| 1595 | extent_end = extent_start | ((u64)root->sectorsize - 1); | ||
| 1509 | if (start < extent_start || start >= extent_end) { | 1596 | if (start < extent_start || start >= extent_end) { |
| 1510 | em->start = start; | 1597 | em->start = start; |
| 1511 | if (start < extent_start) { | 1598 | if (start < extent_start) { |
| @@ -1517,18 +1604,21 @@ again: | |||
| 1517 | } | 1604 | } |
| 1518 | goto not_found_em; | 1605 | goto not_found_em; |
| 1519 | } | 1606 | } |
| 1607 | |||
| 1520 | em->block_start = EXTENT_MAP_INLINE; | 1608 | em->block_start = EXTENT_MAP_INLINE; |
| 1521 | em->block_end = EXTENT_MAP_INLINE; | 1609 | em->block_end = EXTENT_MAP_INLINE; |
| 1522 | em->start = extent_start; | 1610 | em->start = extent_start; |
| 1523 | em->end = extent_end; | 1611 | em->end = extent_end; |
| 1612 | |||
| 1524 | if (!page) { | 1613 | if (!page) { |
| 1525 | goto insert; | 1614 | goto insert; |
| 1526 | } | 1615 | } |
| 1616 | |||
| 1527 | ptr = btrfs_file_extent_inline_start(item); | 1617 | ptr = btrfs_file_extent_inline_start(item); |
| 1528 | map = kmap(page); | 1618 | map = kmap(page); |
| 1529 | memcpy(map + page_offset, ptr, size); | 1619 | read_extent_buffer(leaf, map + page_offset, ptr, size); |
| 1530 | memset(map + page_offset + size, 0, | 1620 | memset(map + page_offset + size, 0, |
| 1531 | root->blocksize - (page_offset + size)); | 1621 | root->sectorsize - (page_offset + size)); |
| 1532 | flush_dcache_page(page); | 1622 | flush_dcache_page(page); |
| 1533 | kunmap(page); | 1623 | kunmap(page); |
| 1534 | set_extent_uptodate(em_tree, extent_start, | 1624 | set_extent_uptodate(em_tree, extent_start, |
| @@ -1542,8 +1632,8 @@ not_found: | |||
| 1542 | em->start = start; | 1632 | em->start = start; |
| 1543 | em->end = end; | 1633 | em->end = end; |
| 1544 | not_found_em: | 1634 | not_found_em: |
| 1545 | em->block_start = 0; | 1635 | em->block_start = EXTENT_MAP_HOLE; |
| 1546 | em->block_end = 0; | 1636 | em->block_end = EXTENT_MAP_HOLE; |
| 1547 | insert: | 1637 | insert: |
| 1548 | btrfs_release_path(root, path); | 1638 | btrfs_release_path(root, path); |
| 1549 | if (em->start > start || em->end < start) { | 1639 | if (em->start > start || em->end < start) { |
| @@ -1712,6 +1802,7 @@ static void btrfs_truncate(struct inode *inode) | |||
| 1712 | ret = btrfs_truncate_in_trans(trans, root, inode); | 1802 | ret = btrfs_truncate_in_trans(trans, root, inode); |
| 1713 | btrfs_update_inode(trans, root, inode); | 1803 | btrfs_update_inode(trans, root, inode); |
| 1714 | nr = trans->blocks_used; | 1804 | nr = trans->blocks_used; |
| 1805 | |||
| 1715 | ret = btrfs_end_transaction(trans, root); | 1806 | ret = btrfs_end_transaction(trans, root); |
| 1716 | BUG_ON(ret); | 1807 | BUG_ON(ret); |
| 1717 | mutex_unlock(&root->fs_info->fs_mutex); | 1808 | mutex_unlock(&root->fs_info->fs_mutex); |
| @@ -1731,8 +1822,7 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
| 1731 | struct btrfs_key key; | 1822 | struct btrfs_key key; |
| 1732 | struct btrfs_root_item root_item; | 1823 | struct btrfs_root_item root_item; |
| 1733 | struct btrfs_inode_item *inode_item; | 1824 | struct btrfs_inode_item *inode_item; |
| 1734 | struct buffer_head *subvol; | 1825 | struct extent_buffer *leaf; |
| 1735 | struct btrfs_leaf *leaf; | ||
| 1736 | struct btrfs_root *new_root; | 1826 | struct btrfs_root *new_root; |
| 1737 | struct inode *inode; | 1827 | struct inode *inode; |
| 1738 | struct inode *dir; | 1828 | struct inode *dir; |
| @@ -1746,34 +1836,37 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
| 1746 | trans = btrfs_start_transaction(root, 1); | 1836 | trans = btrfs_start_transaction(root, 1); |
| 1747 | BUG_ON(!trans); | 1837 | BUG_ON(!trans); |
| 1748 | 1838 | ||
| 1749 | subvol = btrfs_alloc_free_block(trans, root, 0, 0); | 1839 | leaf = btrfs_alloc_free_block(trans, root, 0, 0); |
| 1750 | if (IS_ERR(subvol)) | 1840 | if (IS_ERR(leaf)) |
| 1751 | return PTR_ERR(subvol); | 1841 | return PTR_ERR(leaf); |
| 1752 | leaf = btrfs_buffer_leaf(subvol); | 1842 | |
| 1753 | btrfs_set_header_nritems(&leaf->header, 0); | 1843 | btrfs_set_header_nritems(leaf, 0); |
| 1754 | btrfs_set_header_level(&leaf->header, 0); | 1844 | btrfs_set_header_level(leaf, 0); |
| 1755 | btrfs_set_header_blocknr(&leaf->header, bh_blocknr(subvol)); | 1845 | btrfs_set_header_blocknr(leaf, extent_buffer_blocknr(leaf)); |
| 1756 | btrfs_set_header_generation(&leaf->header, trans->transid); | 1846 | btrfs_set_header_generation(leaf, trans->transid); |
| 1757 | btrfs_set_header_owner(&leaf->header, root->root_key.objectid); | 1847 | btrfs_set_header_owner(leaf, root->root_key.objectid); |
| 1758 | memcpy(leaf->header.fsid, root->fs_info->disk_super->fsid, | 1848 | write_extent_buffer(leaf, root->fs_info->fsid, |
| 1759 | sizeof(leaf->header.fsid)); | 1849 | (unsigned long)btrfs_header_fsid(leaf), |
| 1760 | btrfs_mark_buffer_dirty(subvol); | 1850 | BTRFS_FSID_SIZE); |
| 1851 | btrfs_mark_buffer_dirty(leaf); | ||
| 1761 | 1852 | ||
| 1762 | inode_item = &root_item.inode; | 1853 | inode_item = &root_item.inode; |
| 1763 | memset(inode_item, 0, sizeof(*inode_item)); | 1854 | memset(inode_item, 0, sizeof(*inode_item)); |
| 1764 | btrfs_set_inode_generation(inode_item, 1); | 1855 | inode_item->generation = cpu_to_le64(1); |
| 1765 | btrfs_set_inode_size(inode_item, 3); | 1856 | inode_item->size = cpu_to_le64(3); |
| 1766 | btrfs_set_inode_nlink(inode_item, 1); | 1857 | inode_item->nlink = cpu_to_le32(1); |
| 1767 | btrfs_set_inode_nblocks(inode_item, 1); | 1858 | inode_item->nblocks = cpu_to_le64(1); |
| 1768 | btrfs_set_inode_mode(inode_item, S_IFDIR | 0755); | 1859 | inode_item->mode = cpu_to_le32(S_IFDIR | 0755); |
| 1769 | 1860 | ||
| 1770 | btrfs_set_root_blocknr(&root_item, bh_blocknr(subvol)); | 1861 | btrfs_set_root_blocknr(&root_item, extent_buffer_blocknr(leaf)); |
| 1771 | btrfs_set_root_refs(&root_item, 1); | 1862 | btrfs_set_root_refs(&root_item, 1); |
| 1772 | btrfs_set_root_blocks_used(&root_item, 0); | 1863 | btrfs_set_root_used(&root_item, 0); |
| 1864 | |||
| 1773 | memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); | 1865 | memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); |
| 1774 | root_item.drop_level = 0; | 1866 | root_item.drop_level = 0; |
| 1775 | brelse(subvol); | 1867 | |
| 1776 | subvol = NULL; | 1868 | free_extent_buffer(leaf); |
| 1869 | leaf = NULL; | ||
| 1777 | 1870 | ||
| 1778 | ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, | 1871 | ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, |
| 1779 | 0, &objectid); | 1872 | 0, &objectid); |
| @@ -1784,7 +1877,6 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
| 1784 | 1877 | ||
| 1785 | key.objectid = objectid; | 1878 | key.objectid = objectid; |
| 1786 | key.offset = 1; | 1879 | key.offset = 1; |
| 1787 | key.flags = 0; | ||
| 1788 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | 1880 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); |
| 1789 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | 1881 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, |
| 1790 | &root_item); | 1882 | &root_item); |
| @@ -1845,7 +1937,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
| 1845 | struct btrfs_trans_handle *trans; | 1937 | struct btrfs_trans_handle *trans; |
| 1846 | struct btrfs_key key; | 1938 | struct btrfs_key key; |
| 1847 | struct btrfs_root_item new_root_item; | 1939 | struct btrfs_root_item new_root_item; |
| 1848 | struct buffer_head *tmp; | 1940 | struct extent_buffer *tmp; |
| 1849 | int ret; | 1941 | int ret; |
| 1850 | int err; | 1942 | int err; |
| 1851 | u64 objectid; | 1943 | u64 objectid; |
| @@ -1876,10 +1968,11 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
| 1876 | 1968 | ||
| 1877 | key.objectid = objectid; | 1969 | key.objectid = objectid; |
| 1878 | key.offset = 1; | 1970 | key.offset = 1; |
| 1879 | key.flags = 0; | ||
| 1880 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | 1971 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); |
| 1972 | |||
| 1881 | btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); | 1973 | btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); |
| 1882 | btrfs_set_root_blocknr(&new_root_item, bh_blocknr(root->node)); | 1974 | btrfs_set_root_blocknr(&new_root_item, |
| 1975 | extent_buffer_blocknr(root->node)); | ||
| 1883 | 1976 | ||
| 1884 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | 1977 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, |
| 1885 | &new_root_item); | 1978 | &new_root_item); |
| @@ -1904,8 +1997,10 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
| 1904 | fail: | 1997 | fail: |
| 1905 | nr = trans->blocks_used; | 1998 | nr = trans->blocks_used; |
| 1906 | err = btrfs_commit_transaction(trans, root); | 1999 | err = btrfs_commit_transaction(trans, root); |
| 2000 | |||
| 1907 | if (err && !ret) | 2001 | if (err && !ret) |
| 1908 | ret = err; | 2002 | ret = err; |
| 2003 | |||
| 1909 | mutex_unlock(&root->fs_info->fs_mutex); | 2004 | mutex_unlock(&root->fs_info->fs_mutex); |
| 1910 | up_write(&root->snap_sem); | 2005 | up_write(&root->snap_sem); |
| 1911 | btrfs_btree_balance_dirty(root, nr); | 2006 | btrfs_btree_balance_dirty(root, nr); |
| @@ -1986,7 +2081,7 @@ static int btrfs_ioctl_snap_create(struct btrfs_root *root, void __user *arg) | |||
| 1986 | 2081 | ||
| 1987 | if (copy_from_user(&vol_args, arg, sizeof(vol_args))) | 2082 | if (copy_from_user(&vol_args, arg, sizeof(vol_args))) |
| 1988 | return -EFAULT; | 2083 | return -EFAULT; |
| 1989 | 2084 | ||
| 1990 | namelen = strlen(vol_args.name); | 2085 | namelen = strlen(vol_args.name); |
| 1991 | if (namelen > BTRFS_VOL_NAME_MAX) | 2086 | if (namelen > BTRFS_VOL_NAME_MAX) |
| 1992 | return -EINVAL; | 2087 | return -EINVAL; |
| @@ -2164,8 +2259,10 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
| 2164 | new_inode->i_size > BTRFS_EMPTY_DIR_SIZE) { | 2259 | new_inode->i_size > BTRFS_EMPTY_DIR_SIZE) { |
| 2165 | return -ENOTEMPTY; | 2260 | return -ENOTEMPTY; |
| 2166 | } | 2261 | } |
| 2262 | |||
| 2167 | mutex_lock(&root->fs_info->fs_mutex); | 2263 | mutex_lock(&root->fs_info->fs_mutex); |
| 2168 | trans = btrfs_start_transaction(root, 1); | 2264 | trans = btrfs_start_transaction(root, 1); |
| 2265 | |||
| 2169 | btrfs_set_trans_block_group(trans, new_dir); | 2266 | btrfs_set_trans_block_group(trans, new_dir); |
| 2170 | path = btrfs_alloc_path(); | 2267 | path = btrfs_alloc_path(); |
| 2171 | if (!path) { | 2268 | if (!path) { |
| @@ -2177,9 +2274,10 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
| 2177 | old_dir->i_ctime = old_dir->i_mtime = ctime; | 2274 | old_dir->i_ctime = old_dir->i_mtime = ctime; |
| 2178 | new_dir->i_ctime = new_dir->i_mtime = ctime; | 2275 | new_dir->i_ctime = new_dir->i_mtime = ctime; |
| 2179 | old_inode->i_ctime = ctime; | 2276 | old_inode->i_ctime = ctime; |
| 2277 | |||
| 2180 | if (S_ISDIR(old_inode->i_mode) && old_dir != new_dir) { | 2278 | if (S_ISDIR(old_inode->i_mode) && old_dir != new_dir) { |
| 2181 | struct btrfs_key *location = &BTRFS_I(new_dir)->location; | 2279 | struct btrfs_key *location = &BTRFS_I(new_dir)->location; |
| 2182 | u64 old_parent_oid; | 2280 | struct btrfs_key old_parent_key; |
| 2183 | di = btrfs_lookup_dir_item(trans, root, path, old_inode->i_ino, | 2281 | di = btrfs_lookup_dir_item(trans, root, path, old_inode->i_ino, |
| 2184 | "..", 2, -1); | 2282 | "..", 2, -1); |
| 2185 | if (IS_ERR(di)) { | 2283 | if (IS_ERR(di)) { |
| @@ -2190,7 +2288,7 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
| 2190 | ret = -ENOENT; | 2288 | ret = -ENOENT; |
| 2191 | goto out_fail; | 2289 | goto out_fail; |
| 2192 | } | 2290 | } |
| 2193 | old_parent_oid = btrfs_disk_key_objectid(&di->location); | 2291 | btrfs_dir_item_key_to_cpu(path->nodes[0], di, &old_parent_key); |
| 2194 | ret = btrfs_del_item(trans, root, path); | 2292 | ret = btrfs_del_item(trans, root, path); |
| 2195 | if (ret) { | 2293 | if (ret) { |
| 2196 | goto out_fail; | 2294 | goto out_fail; |
| @@ -2199,7 +2297,7 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
| 2199 | 2297 | ||
| 2200 | di = btrfs_lookup_dir_index_item(trans, root, path, | 2298 | di = btrfs_lookup_dir_index_item(trans, root, path, |
| 2201 | old_inode->i_ino, | 2299 | old_inode->i_ino, |
| 2202 | old_parent_oid, | 2300 | old_parent_key.objectid, |
| 2203 | "..", 2, -1); | 2301 | "..", 2, -1); |
| 2204 | if (IS_ERR(di)) { | 2302 | if (IS_ERR(di)) { |
| 2205 | ret = PTR_ERR(di); | 2303 | ret = PTR_ERR(di); |
| @@ -2257,8 +2355,9 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 2257 | u64 objectid; | 2355 | u64 objectid; |
| 2258 | int name_len; | 2356 | int name_len; |
| 2259 | int datasize; | 2357 | int datasize; |
| 2260 | char *ptr; | 2358 | unsigned long ptr; |
| 2261 | struct btrfs_file_extent_item *ei; | 2359 | struct btrfs_file_extent_item *ei; |
| 2360 | struct extent_buffer *leaf; | ||
| 2262 | unsigned long nr; | 2361 | unsigned long nr; |
| 2263 | 2362 | ||
| 2264 | name_len = strlen(symname) + 1; | 2363 | name_len = strlen(symname) + 1; |
| @@ -2302,7 +2401,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 2302 | BUG_ON(!path); | 2401 | BUG_ON(!path); |
| 2303 | key.objectid = inode->i_ino; | 2402 | key.objectid = inode->i_ino; |
| 2304 | key.offset = 0; | 2403 | key.offset = 0; |
| 2305 | key.flags = 0; | ||
| 2306 | btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY); | 2404 | btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY); |
| 2307 | datasize = btrfs_file_extent_calc_inline_size(name_len); | 2405 | datasize = btrfs_file_extent_calc_inline_size(name_len); |
| 2308 | err = btrfs_insert_empty_item(trans, root, path, &key, | 2406 | err = btrfs_insert_empty_item(trans, root, path, &key, |
| @@ -2311,16 +2409,17 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 2311 | drop_inode = 1; | 2409 | drop_inode = 1; |
| 2312 | goto out_unlock; | 2410 | goto out_unlock; |
| 2313 | } | 2411 | } |
| 2314 | ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | 2412 | leaf = path->nodes[0]; |
| 2315 | path->slots[0], struct btrfs_file_extent_item); | 2413 | ei = btrfs_item_ptr(leaf, path->slots[0], |
| 2316 | btrfs_set_file_extent_generation(ei, trans->transid); | 2414 | struct btrfs_file_extent_item); |
| 2317 | btrfs_set_file_extent_type(ei, | 2415 | btrfs_set_file_extent_generation(leaf, ei, trans->transid); |
| 2416 | btrfs_set_file_extent_type(leaf, ei, | ||
| 2318 | BTRFS_FILE_EXTENT_INLINE); | 2417 | BTRFS_FILE_EXTENT_INLINE); |
| 2319 | ptr = btrfs_file_extent_inline_start(ei); | 2418 | ptr = btrfs_file_extent_inline_start(ei); |
| 2320 | btrfs_memcpy(root, path->nodes[0]->b_data, | 2419 | write_extent_buffer(leaf, symname, ptr, name_len); |
| 2321 | ptr, symname, name_len); | 2420 | btrfs_mark_buffer_dirty(leaf); |
| 2322 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
| 2323 | btrfs_free_path(path); | 2421 | btrfs_free_path(path); |
| 2422 | |||
| 2324 | inode->i_op = &btrfs_symlink_inode_operations; | 2423 | inode->i_op = &btrfs_symlink_inode_operations; |
| 2325 | inode->i_mapping->a_ops = &btrfs_symlink_aops; | 2424 | inode->i_mapping->a_ops = &btrfs_symlink_aops; |
| 2326 | inode->i_size = name_len - 1; | 2425 | inode->i_size = name_len - 1; |
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index bafa78603bd2..a825ce078a54 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c | |||
| @@ -20,10 +20,10 @@ | |||
| 20 | #include "disk-io.h" | 20 | #include "disk-io.h" |
| 21 | #include "print-tree.h" | 21 | #include "print-tree.h" |
| 22 | 22 | ||
| 23 | void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | 23 | void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) |
| 24 | { | 24 | { |
| 25 | int i; | 25 | int i; |
| 26 | u32 nr = btrfs_header_nritems(&l->header); | 26 | u32 nr = btrfs_header_nritems(l); |
| 27 | struct btrfs_item *item; | 27 | struct btrfs_item *item; |
| 28 | struct btrfs_extent_item *ei; | 28 | struct btrfs_extent_item *ei; |
| 29 | struct btrfs_root_item *ri; | 29 | struct btrfs_root_item *ri; |
| @@ -31,119 +31,113 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
| 31 | struct btrfs_inode_item *ii; | 31 | struct btrfs_inode_item *ii; |
| 32 | struct btrfs_block_group_item *bi; | 32 | struct btrfs_block_group_item *bi; |
| 33 | struct btrfs_file_extent_item *fi; | 33 | struct btrfs_file_extent_item *fi; |
| 34 | struct btrfs_key key; | ||
| 35 | struct btrfs_key found_key; | ||
| 34 | u32 type; | 36 | u32 type; |
| 35 | 37 | ||
| 36 | printk("leaf %llu total ptrs %d free space %d\n", | 38 | printk("leaf %llu total ptrs %d free space %d\n", |
| 37 | (unsigned long long)btrfs_header_blocknr(&l->header), nr, | 39 | (unsigned long long)btrfs_header_blocknr(l), nr, |
| 38 | btrfs_leaf_free_space(root, l)); | 40 | btrfs_leaf_free_space(root, l)); |
| 39 | for (i = 0 ; i < nr ; i++) { | 41 | for (i = 0 ; i < nr ; i++) { |
| 40 | item = l->items + i; | 42 | item = btrfs_item_nr(l, i); |
| 41 | type = btrfs_disk_key_type(&item->key); | 43 | btrfs_item_key_to_cpu(l, &key, i); |
| 44 | type = btrfs_key_type(&key); | ||
| 42 | printk("\titem %d key (%llu %x %llu) itemoff %d itemsize %d\n", | 45 | printk("\titem %d key (%llu %x %llu) itemoff %d itemsize %d\n", |
| 43 | i, | 46 | i, |
| 44 | (unsigned long long)btrfs_disk_key_objectid(&item->key), | 47 | (unsigned long long)key.objectid, type, |
| 45 | btrfs_disk_key_flags(&item->key), | 48 | (unsigned long long)key.offset, |
| 46 | (unsigned long long)btrfs_disk_key_offset(&item->key), | 49 | btrfs_item_offset(l, item), btrfs_item_size(l, item)); |
| 47 | btrfs_item_offset(item), | ||
| 48 | btrfs_item_size(item)); | ||
| 49 | switch (type) { | 50 | switch (type) { |
| 50 | case BTRFS_INODE_ITEM_KEY: | 51 | case BTRFS_INODE_ITEM_KEY: |
| 51 | ii = btrfs_item_ptr(l, i, struct btrfs_inode_item); | 52 | ii = btrfs_item_ptr(l, i, struct btrfs_inode_item); |
| 52 | printk("\t\tinode generation %llu size %llu mode %o\n", | 53 | printk("\t\tinode generation %llu size %llu mode %o\n", |
| 53 | (unsigned long long)btrfs_inode_generation(ii), | 54 | (unsigned long long)btrfs_inode_generation(l, ii), |
| 54 | (unsigned long long)btrfs_inode_size(ii), | 55 | (unsigned long long)btrfs_inode_size(l, ii), |
| 55 | btrfs_inode_mode(ii)); | 56 | btrfs_inode_mode(l, ii)); |
| 56 | break; | 57 | break; |
| 57 | case BTRFS_DIR_ITEM_KEY: | 58 | case BTRFS_DIR_ITEM_KEY: |
| 58 | di = btrfs_item_ptr(l, i, struct btrfs_dir_item); | 59 | di = btrfs_item_ptr(l, i, struct btrfs_dir_item); |
| 60 | btrfs_dir_item_key_to_cpu(l, di, &found_key); | ||
| 59 | printk("\t\tdir oid %llu flags %u type %u\n", | 61 | printk("\t\tdir oid %llu flags %u type %u\n", |
| 60 | (unsigned long long)btrfs_disk_key_objectid( | 62 | (unsigned long long)found_key.objectid, |
| 61 | &di->location), | 63 | btrfs_dir_flags(l, di), |
| 62 | btrfs_dir_flags(di), | 64 | btrfs_dir_type(l, di)); |
| 63 | btrfs_dir_type(di)); | ||
| 64 | printk("\t\tname %.*s\n", | ||
| 65 | btrfs_dir_name_len(di),(char *)(di + 1)); | ||
| 66 | break; | 65 | break; |
| 67 | case BTRFS_ROOT_ITEM_KEY: | 66 | case BTRFS_ROOT_ITEM_KEY: |
| 68 | ri = btrfs_item_ptr(l, i, struct btrfs_root_item); | 67 | ri = btrfs_item_ptr(l, i, struct btrfs_root_item); |
| 69 | printk("\t\troot data blocknr %llu refs %u\n", | 68 | printk("\t\troot data blocknr %llu refs %u\n", |
| 70 | (unsigned long long)btrfs_root_blocknr(ri), | 69 | (unsigned long long)btrfs_disk_root_blocknr(l, ri), |
| 71 | btrfs_root_refs(ri)); | 70 | btrfs_disk_root_refs(l, ri)); |
| 72 | break; | 71 | break; |
| 73 | case BTRFS_EXTENT_ITEM_KEY: | 72 | case BTRFS_EXTENT_ITEM_KEY: |
| 74 | ei = btrfs_item_ptr(l, i, struct btrfs_extent_item); | 73 | ei = btrfs_item_ptr(l, i, struct btrfs_extent_item); |
| 75 | printk("\t\textent data refs %u\n", | 74 | printk("\t\textent data refs %u\n", |
| 76 | btrfs_extent_refs(ei)); | 75 | btrfs_extent_refs(l, ei)); |
| 77 | break; | 76 | break; |
| 78 | 77 | ||
| 79 | case BTRFS_EXTENT_DATA_KEY: | 78 | case BTRFS_EXTENT_DATA_KEY: |
| 80 | fi = btrfs_item_ptr(l, i, | 79 | fi = btrfs_item_ptr(l, i, |
| 81 | struct btrfs_file_extent_item); | 80 | struct btrfs_file_extent_item); |
| 82 | if (btrfs_file_extent_type(fi) == | 81 | if (btrfs_file_extent_type(l, fi) == |
| 83 | BTRFS_FILE_EXTENT_INLINE) { | 82 | BTRFS_FILE_EXTENT_INLINE) { |
| 84 | printk("\t\tinline extent data size %u\n", | 83 | printk("\t\tinline extent data size %u\n", |
| 85 | btrfs_file_extent_inline_len(l->items + i)); | 84 | btrfs_file_extent_inline_len(l, item)); |
| 86 | break; | 85 | break; |
| 87 | } | 86 | } |
| 88 | printk("\t\textent data disk block %llu nr %llu\n", | 87 | printk("\t\textent data disk block %llu nr %llu\n", |
| 89 | (unsigned long long)btrfs_file_extent_disk_blocknr(fi), | 88 | (unsigned long long)btrfs_file_extent_disk_blocknr(l, fi), |
| 90 | (unsigned long long)btrfs_file_extent_disk_num_blocks(fi)); | 89 | (unsigned long long)btrfs_file_extent_disk_num_blocks(l, fi)); |
| 91 | printk("\t\textent data offset %llu nr %llu\n", | 90 | printk("\t\textent data offset %llu nr %llu\n", |
| 92 | (unsigned long long)btrfs_file_extent_offset(fi), | 91 | (unsigned long long)btrfs_file_extent_offset(l, fi), |
| 93 | (unsigned long long)btrfs_file_extent_num_blocks(fi)); | 92 | (unsigned long long)btrfs_file_extent_num_blocks(l, fi)); |
| 94 | break; | 93 | break; |
| 95 | case BTRFS_BLOCK_GROUP_ITEM_KEY: | 94 | case BTRFS_BLOCK_GROUP_ITEM_KEY: |
| 96 | bi = btrfs_item_ptr(l, i, | 95 | bi = btrfs_item_ptr(l, i, |
| 97 | struct btrfs_block_group_item); | 96 | struct btrfs_block_group_item); |
| 98 | printk("\t\tblock group used %llu\n", | 97 | printk("\t\tblock group used %llu\n", |
| 99 | (unsigned long long)btrfs_block_group_used(bi)); | 98 | (unsigned long long)btrfs_disk_block_group_used(l, bi)); |
| 100 | break; | ||
| 101 | case BTRFS_STRING_ITEM_KEY: | ||
| 102 | printk("\t\titem data %.*s\n", btrfs_item_size(item), | ||
| 103 | btrfs_leaf_data(l) + btrfs_item_offset(item)); | ||
| 104 | break; | 99 | break; |
| 105 | }; | 100 | }; |
| 106 | } | 101 | } |
| 107 | } | 102 | } |
| 108 | 103 | ||
| 109 | void btrfs_print_tree(struct btrfs_root *root, struct buffer_head *t) | 104 | void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c) |
| 110 | { | 105 | { |
| 111 | int i; | 106 | int i; |
| 112 | u32 nr; | 107 | u32 nr; |
| 113 | struct btrfs_node *c; | 108 | struct btrfs_key key; |
| 114 | 109 | ||
| 115 | if (!t) | 110 | if (!c) |
| 116 | return; | 111 | return; |
| 117 | c = btrfs_buffer_node(t); | 112 | nr = btrfs_header_nritems(c); |
| 118 | nr = btrfs_header_nritems(&c->header); | ||
| 119 | if (btrfs_is_leaf(c)) { | 113 | if (btrfs_is_leaf(c)) { |
| 120 | btrfs_print_leaf(root, (struct btrfs_leaf *)c); | 114 | btrfs_print_leaf(root, c); |
| 121 | return; | 115 | return; |
| 122 | } | 116 | } |
| 123 | printk("node %llu level %d total ptrs %d free spc %u\n", | 117 | printk("node %llu level %d total ptrs %d free spc %u\n", |
| 124 | (unsigned long long)btrfs_header_blocknr(&c->header), | 118 | (unsigned long long)btrfs_header_blocknr(c), |
| 125 | btrfs_header_level(&c->header), nr, | 119 | btrfs_header_level(c), nr, |
| 126 | (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr); | 120 | (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr); |
| 127 | for (i = 0; i < nr; i++) { | 121 | for (i = 0; i < nr; i++) { |
| 122 | btrfs_node_key_to_cpu(c, &key, i); | ||
| 128 | printk("\tkey %d (%llu %u %llu) block %llu\n", | 123 | printk("\tkey %d (%llu %u %llu) block %llu\n", |
| 129 | i, | 124 | i, |
| 130 | (unsigned long long)c->ptrs[i].key.objectid, | 125 | (unsigned long long)key.objectid, |
| 131 | c->ptrs[i].key.flags, | 126 | key.type, |
| 132 | (unsigned long long)c->ptrs[i].key.offset, | 127 | (unsigned long long)key.offset, |
| 133 | (unsigned long long)btrfs_node_blockptr(c, i)); | 128 | (unsigned long long)btrfs_node_blockptr(c, i)); |
| 134 | } | 129 | } |
| 135 | for (i = 0; i < nr; i++) { | 130 | for (i = 0; i < nr; i++) { |
| 136 | struct buffer_head *next_buf = read_tree_block(root, | 131 | struct extent_buffer *next = read_tree_block(root, |
| 137 | btrfs_node_blockptr(c, i)); | 132 | btrfs_node_blockptr(c, i)); |
| 138 | struct btrfs_node *next = btrfs_buffer_node(next_buf); | ||
| 139 | if (btrfs_is_leaf(next) && | 133 | if (btrfs_is_leaf(next) && |
| 140 | btrfs_header_level(&c->header) != 1) | 134 | btrfs_header_level(c) != 1) |
| 141 | BUG(); | 135 | BUG(); |
| 142 | if (btrfs_header_level(&next->header) != | 136 | if (btrfs_header_level(next) != |
| 143 | btrfs_header_level(&c->header) - 1) | 137 | btrfs_header_level(c) - 1) |
| 144 | BUG(); | 138 | BUG(); |
| 145 | btrfs_print_tree(root, next_buf); | 139 | btrfs_print_tree(root, next); |
| 146 | btrfs_block_release(root, next_buf); | 140 | free_extent_buffer(next); |
| 147 | } | 141 | } |
| 148 | } | 142 | } |
| 149 | 143 | ||
diff --git a/fs/btrfs/print-tree.h b/fs/btrfs/print-tree.h index 205cd03601ab..da75efe534d5 100644 --- a/fs/btrfs/print-tree.h +++ b/fs/btrfs/print-tree.h | |||
| @@ -18,6 +18,6 @@ | |||
| 18 | 18 | ||
| 19 | #ifndef __PRINT_TREE_ | 19 | #ifndef __PRINT_TREE_ |
| 20 | #define __PRINT_TREE_ | 20 | #define __PRINT_TREE_ |
| 21 | void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l); | 21 | void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l); |
| 22 | void btrfs_print_tree(struct btrfs_root *root, struct buffer_head *t); | 22 | void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *t); |
| 23 | #endif | 23 | #endif |
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 3b5926dfbeba..88bcdd33f56e 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
| @@ -26,12 +26,13 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, | |||
| 26 | { | 26 | { |
| 27 | struct btrfs_path *path; | 27 | struct btrfs_path *path; |
| 28 | struct btrfs_key search_key; | 28 | struct btrfs_key search_key; |
| 29 | struct btrfs_leaf *l; | 29 | struct btrfs_key found_key; |
| 30 | struct extent_buffer *l; | ||
| 30 | int ret; | 31 | int ret; |
| 31 | int slot; | 32 | int slot; |
| 32 | 33 | ||
| 33 | search_key.objectid = objectid; | 34 | search_key.objectid = objectid; |
| 34 | search_key.flags = (u32)-1; | 35 | search_key.type = (u8)-1; |
| 35 | search_key.offset = (u64)-1; | 36 | search_key.offset = (u64)-1; |
| 36 | 37 | ||
| 37 | path = btrfs_alloc_path(); | 38 | path = btrfs_alloc_path(); |
| @@ -39,17 +40,19 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, | |||
| 39 | ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); | 40 | ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); |
| 40 | if (ret < 0) | 41 | if (ret < 0) |
| 41 | goto out; | 42 | goto out; |
| 43 | |||
| 42 | BUG_ON(ret == 0); | 44 | BUG_ON(ret == 0); |
| 43 | l = btrfs_buffer_leaf(path->nodes[0]); | 45 | l = path->nodes[0]; |
| 44 | BUG_ON(path->slots[0] == 0); | 46 | BUG_ON(path->slots[0] == 0); |
| 45 | slot = path->slots[0] - 1; | 47 | slot = path->slots[0] - 1; |
| 46 | if (btrfs_disk_key_objectid(&l->items[slot].key) != objectid) { | 48 | btrfs_item_key_to_cpu(l, &found_key, slot); |
| 49 | if (found_key.objectid != objectid) { | ||
| 47 | ret = 1; | 50 | ret = 1; |
| 48 | goto out; | 51 | goto out; |
| 49 | } | 52 | } |
| 50 | memcpy(item, btrfs_item_ptr(l, slot, struct btrfs_root_item), | 53 | read_extent_buffer(l, item, btrfs_item_ptr_offset(l, slot), |
| 51 | sizeof(*item)); | 54 | sizeof(*item)); |
| 52 | btrfs_disk_key_to_cpu(key, &l->items[slot].key); | 55 | memcpy(key, &found_key, sizeof(found_key)); |
| 53 | ret = 0; | 56 | ret = 0; |
| 54 | out: | 57 | out: |
| 55 | btrfs_release_path(root, path); | 58 | btrfs_release_path(root, path); |
| @@ -62,10 +65,10 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 62 | *item) | 65 | *item) |
| 63 | { | 66 | { |
| 64 | struct btrfs_path *path; | 67 | struct btrfs_path *path; |
| 65 | struct btrfs_leaf *l; | 68 | struct extent_buffer *l; |
| 66 | int ret; | 69 | int ret; |
| 67 | int slot; | 70 | int slot; |
| 68 | struct btrfs_root_item *update_item; | 71 | unsigned long ptr; |
| 69 | 72 | ||
| 70 | path = btrfs_alloc_path(); | 73 | path = btrfs_alloc_path(); |
| 71 | BUG_ON(!path); | 74 | BUG_ON(!path); |
| @@ -73,10 +76,10 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 73 | if (ret < 0) | 76 | if (ret < 0) |
| 74 | goto out; | 77 | goto out; |
| 75 | BUG_ON(ret != 0); | 78 | BUG_ON(ret != 0); |
| 76 | l = btrfs_buffer_leaf(path->nodes[0]); | 79 | l = path->nodes[0]; |
| 77 | slot = path->slots[0]; | 80 | slot = path->slots[0]; |
| 78 | update_item = btrfs_item_ptr(l, slot, struct btrfs_root_item); | 81 | ptr = btrfs_item_ptr_offset(l, slot); |
| 79 | btrfs_memcpy(root, l, update_item, item, sizeof(*item)); | 82 | write_extent_buffer(l, item, ptr, sizeof(*item)); |
| 80 | btrfs_mark_buffer_dirty(path->nodes[0]); | 83 | btrfs_mark_buffer_dirty(path->nodes[0]); |
| 81 | out: | 84 | out: |
| 82 | btrfs_release_path(root, path); | 85 | btrfs_release_path(root, path); |
| @@ -103,11 +106,10 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid, | |||
| 103 | struct btrfs_path *path; | 106 | struct btrfs_path *path; |
| 104 | int ret; | 107 | int ret; |
| 105 | u32 nritems; | 108 | u32 nritems; |
| 106 | struct btrfs_leaf *leaf; | 109 | struct extent_buffer *leaf; |
| 107 | int slot; | 110 | int slot; |
| 108 | 111 | ||
| 109 | key.objectid = objectid; | 112 | key.objectid = objectid; |
| 110 | key.flags = 0; | ||
| 111 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | 113 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); |
| 112 | key.offset = 0; | 114 | key.offset = 0; |
| 113 | path = btrfs_alloc_path(); | 115 | path = btrfs_alloc_path(); |
| @@ -117,19 +119,19 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid, | |||
| 117 | if (ret < 0) | 119 | if (ret < 0) |
| 118 | goto err; | 120 | goto err; |
| 119 | while(1) { | 121 | while(1) { |
| 120 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 122 | leaf = path->nodes[0]; |
| 121 | nritems = btrfs_header_nritems(&leaf->header); | 123 | nritems = btrfs_header_nritems(leaf); |
| 122 | slot = path->slots[0]; | 124 | slot = path->slots[0]; |
| 123 | if (slot >= nritems) { | 125 | if (slot >= nritems) { |
| 124 | ret = btrfs_next_leaf(root, path); | 126 | ret = btrfs_next_leaf(root, path); |
| 125 | if (ret) | 127 | if (ret) |
| 126 | break; | 128 | break; |
| 127 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 129 | leaf = path->nodes[0]; |
| 128 | nritems = btrfs_header_nritems(&leaf->header); | 130 | nritems = btrfs_header_nritems(leaf); |
| 129 | slot = path->slots[0]; | 131 | slot = path->slots[0]; |
| 130 | } | 132 | } |
| 131 | item = leaf->items + slot; | 133 | item = btrfs_item_nr(leaf, slot); |
| 132 | btrfs_disk_key_to_cpu(&key, &item->key); | 134 | btrfs_item_key_to_cpu(leaf, &key, slot); |
| 133 | if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY) | 135 | if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY) |
| 134 | goto next; | 136 | goto next; |
| 135 | 137 | ||
| @@ -140,7 +142,7 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid, | |||
| 140 | break; | 142 | break; |
| 141 | 143 | ||
| 142 | ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item); | 144 | ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item); |
| 143 | if (btrfs_root_refs(ri) != 0) | 145 | if (btrfs_disk_root_refs(leaf, ri) != 0) |
| 144 | goto next; | 146 | goto next; |
| 145 | 147 | ||
| 146 | dead_root = btrfs_read_fs_root_no_radix(root->fs_info, &key); | 148 | dead_root = btrfs_read_fs_root_no_radix(root->fs_info, &key); |
| @@ -170,6 +172,7 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 170 | int ret; | 172 | int ret; |
| 171 | u32 refs; | 173 | u32 refs; |
| 172 | struct btrfs_root_item *ri; | 174 | struct btrfs_root_item *ri; |
| 175 | struct extent_buffer *leaf; | ||
| 173 | 176 | ||
| 174 | path = btrfs_alloc_path(); | 177 | path = btrfs_alloc_path(); |
| 175 | BUG_ON(!path); | 178 | BUG_ON(!path); |
| @@ -177,10 +180,10 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 177 | if (ret < 0) | 180 | if (ret < 0) |
| 178 | goto out; | 181 | goto out; |
| 179 | BUG_ON(ret != 0); | 182 | BUG_ON(ret != 0); |
| 180 | ri = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | 183 | leaf = path->nodes[0]; |
| 181 | path->slots[0], struct btrfs_root_item); | 184 | ri = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_item); |
| 182 | 185 | ||
| 183 | refs = btrfs_root_refs(ri); | 186 | refs = btrfs_disk_root_refs(leaf, ri); |
| 184 | BUG_ON(refs != 0); | 187 | BUG_ON(refs != 0); |
| 185 | ret = btrfs_del_item(trans, root, path); | 188 | ret = btrfs_del_item(trans, root, path); |
| 186 | out: | 189 | out: |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 66a01cbbbea1..39a1435c68f1 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -41,7 +41,7 @@ | |||
| 41 | #include "ioctl.h" | 41 | #include "ioctl.h" |
| 42 | #include "print-tree.h" | 42 | #include "print-tree.h" |
| 43 | 43 | ||
| 44 | #define BTRFS_SUPER_MAGIC 0x9123682E | 44 | #define BTRFS_SUPER_MAGIC 0x9123683E |
| 45 | 45 | ||
| 46 | static struct super_operations btrfs_super_ops; | 46 | static struct super_operations btrfs_super_ops; |
| 47 | 47 | ||
| @@ -115,13 +115,12 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent) | |||
| 115 | return -EIO; | 115 | return -EIO; |
| 116 | } | 116 | } |
| 117 | sb->s_fs_info = tree_root; | 117 | sb->s_fs_info = tree_root; |
| 118 | disk_super = tree_root->fs_info->disk_super; | 118 | disk_super = &tree_root->fs_info->super_copy; |
| 119 | inode = btrfs_iget_locked(sb, btrfs_super_root_dir(disk_super), | 119 | inode = btrfs_iget_locked(sb, btrfs_super_root_dir(disk_super), |
| 120 | tree_root); | 120 | tree_root); |
| 121 | bi = BTRFS_I(inode); | 121 | bi = BTRFS_I(inode); |
| 122 | bi->location.objectid = inode->i_ino; | 122 | bi->location.objectid = inode->i_ino; |
| 123 | bi->location.offset = 0; | 123 | bi->location.offset = 0; |
| 124 | bi->location.flags = 0; | ||
| 125 | bi->root = tree_root; | 124 | bi->root = tree_root; |
| 126 | 125 | ||
| 127 | btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY); | 126 | btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY); |
| @@ -281,6 +280,7 @@ error_s: | |||
| 281 | error_bdev: | 280 | error_bdev: |
| 282 | close_bdev_excl(bdev); | 281 | close_bdev_excl(bdev); |
| 283 | error: | 282 | error: |
| 283 | printk("get_sb failed\n"); | ||
| 284 | return error; | 284 | return error; |
| 285 | } | 285 | } |
| 286 | /* end copy & paste */ | 286 | /* end copy & paste */ |
| @@ -295,6 +295,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, | |||
| 295 | ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data, | 295 | ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data, |
| 296 | btrfs_fill_super, mnt, | 296 | btrfs_fill_super, mnt, |
| 297 | subvol_name ? subvol_name : "default"); | 297 | subvol_name ? subvol_name : "default"); |
| 298 | printk("btrfs_get_sb returns %d\n", ret); | ||
| 298 | return ret; | 299 | return ret; |
| 299 | } | 300 | } |
| 300 | 301 | ||
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 2058783373eb..9654e90eec89 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c | |||
| @@ -31,31 +31,31 @@ | |||
| 31 | static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf) | 31 | static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf) |
| 32 | { | 32 | { |
| 33 | return snprintf(buf, PAGE_SIZE, "%llu\n", | 33 | return snprintf(buf, PAGE_SIZE, "%llu\n", |
| 34 | (unsigned long long)btrfs_root_blocks_used(&root->root_item)); | 34 | (unsigned long long)btrfs_root_used(&root->root_item)); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf) | 37 | static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf) |
| 38 | { | 38 | { |
| 39 | return snprintf(buf, PAGE_SIZE, "%llu\n", | 39 | return snprintf(buf, PAGE_SIZE, "%llu\n", |
| 40 | (unsigned long long)btrfs_root_block_limit(&root->root_item)); | 40 | (unsigned long long)btrfs_root_limit(&root->root_item)); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static ssize_t super_blocks_used_show(struct btrfs_fs_info *fs, char *buf) | 43 | static ssize_t super_blocks_used_show(struct btrfs_fs_info *fs, char *buf) |
| 44 | { | 44 | { |
| 45 | return snprintf(buf, PAGE_SIZE, "%llu\n", | 45 | return snprintf(buf, PAGE_SIZE, "%llu\n", |
| 46 | (unsigned long long)btrfs_super_blocks_used(fs->disk_super)); | 46 | (unsigned long long)btrfs_super_blocks_used(&fs->super_copy)); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf) | 49 | static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf) |
| 50 | { | 50 | { |
| 51 | return snprintf(buf, PAGE_SIZE, "%llu\n", | 51 | return snprintf(buf, PAGE_SIZE, "%llu\n", |
| 52 | (unsigned long long)btrfs_super_total_blocks(fs->disk_super)); | 52 | (unsigned long long)btrfs_super_total_blocks(&fs->super_copy)); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | static ssize_t super_blocksize_show(struct btrfs_fs_info *fs, char *buf) | 55 | static ssize_t super_blocksize_show(struct btrfs_fs_info *fs, char *buf) |
| 56 | { | 56 | { |
| 57 | return snprintf(buf, PAGE_SIZE, "%llu\n", | 57 | return snprintf(buf, PAGE_SIZE, "%llu\n", |
| 58 | (unsigned long long)btrfs_super_blocksize(fs->disk_super)); | 58 | (unsigned long long)btrfs_super_sectorsize(&fs->super_copy)); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | /* this is for root attrs (subvols/snapshots) */ | 61 | /* this is for root attrs (subvols/snapshots) */ |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 087074db0bd5..750f35a37aae 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
| 20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
| 21 | #include <linux/writeback.h> | 21 | #include <linux/writeback.h> |
| 22 | #include <linux/pagemap.h> | ||
| 22 | #include "ctree.h" | 23 | #include "ctree.h" |
| 23 | #include "disk-io.h" | 24 | #include "disk-io.h" |
| 24 | #include "transaction.h" | 25 | #include "transaction.h" |
| @@ -66,7 +67,9 @@ static int join_transaction(struct btrfs_root *root) | |||
| 66 | cur_trans->commit_done = 0; | 67 | cur_trans->commit_done = 0; |
| 67 | cur_trans->start_time = get_seconds(); | 68 | cur_trans->start_time = get_seconds(); |
| 68 | list_add_tail(&cur_trans->list, &root->fs_info->trans_list); | 69 | list_add_tail(&cur_trans->list, &root->fs_info->trans_list); |
| 69 | init_bit_radix(&cur_trans->dirty_pages); | 70 | extent_map_tree_init(&cur_trans->dirty_pages, |
| 71 | root->fs_info->btree_inode->i_mapping, | ||
| 72 | GFP_NOFS); | ||
| 70 | } else { | 73 | } else { |
| 71 | cur_trans->num_writers++; | 74 | cur_trans->num_writers++; |
| 72 | cur_trans->num_joined++; | 75 | cur_trans->num_joined++; |
| @@ -88,7 +91,7 @@ static int record_root_in_trans(struct btrfs_root *root) | |||
| 88 | (unsigned long)root->root_key.objectid, | 91 | (unsigned long)root->root_key.objectid, |
| 89 | BTRFS_ROOT_DEFRAG_TAG); | 92 | BTRFS_ROOT_DEFRAG_TAG); |
| 90 | root->commit_root = root->node; | 93 | root->commit_root = root->node; |
| 91 | get_bh(root->node); | 94 | extent_buffer_get(root->node); |
| 92 | } else { | 95 | } else { |
| 93 | WARN_ON(1); | 96 | WARN_ON(1); |
| 94 | } | 97 | } |
| @@ -144,29 +147,30 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
| 144 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, | 147 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, |
| 145 | struct btrfs_root *root) | 148 | struct btrfs_root *root) |
| 146 | { | 149 | { |
| 147 | unsigned long gang[16]; | ||
| 148 | int ret; | 150 | int ret; |
| 149 | int i; | ||
| 150 | int err; | 151 | int err; |
| 151 | int werr = 0; | 152 | int werr = 0; |
| 153 | struct extent_map_tree *dirty_pages; | ||
| 152 | struct page *page; | 154 | struct page *page; |
| 153 | struct radix_tree_root *dirty_pages; | ||
| 154 | struct inode *btree_inode = root->fs_info->btree_inode; | 155 | struct inode *btree_inode = root->fs_info->btree_inode; |
| 156 | u64 start; | ||
| 157 | u64 end; | ||
| 158 | unsigned long index; | ||
| 155 | 159 | ||
| 156 | if (!trans || !trans->transaction) { | 160 | if (!trans || !trans->transaction) { |
| 157 | return filemap_write_and_wait(btree_inode->i_mapping); | 161 | return filemap_write_and_wait(btree_inode->i_mapping); |
| 158 | } | 162 | } |
| 159 | dirty_pages = &trans->transaction->dirty_pages; | 163 | dirty_pages = &trans->transaction->dirty_pages; |
| 160 | while(1) { | 164 | while(1) { |
| 161 | ret = find_first_radix_bit(dirty_pages, gang, | 165 | ret = find_first_extent_bit(dirty_pages, 0, &start, &end, |
| 162 | 0, ARRAY_SIZE(gang)); | 166 | EXTENT_DIRTY); |
| 163 | if (!ret) | 167 | if (ret) |
| 164 | break; | 168 | break; |
| 165 | for (i = 0; i < ret; i++) { | 169 | clear_extent_dirty(dirty_pages, start, end, GFP_NOFS); |
| 166 | /* FIXME EIO */ | 170 | while(start <= end) { |
| 167 | clear_radix_bit(dirty_pages, gang[i]); | 171 | index = start >> PAGE_CACHE_SHIFT; |
| 168 | page = find_lock_page(btree_inode->i_mapping, | 172 | start = (index + 1) << PAGE_CACHE_SHIFT; |
| 169 | gang[i]); | 173 | page = find_lock_page(btree_inode->i_mapping, index); |
| 170 | if (!page) | 174 | if (!page) |
| 171 | continue; | 175 | continue; |
| 172 | if (PageWriteback(page)) { | 176 | if (PageWriteback(page)) { |
| @@ -202,10 +206,11 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, | |||
| 202 | btrfs_write_dirty_block_groups(trans, extent_root); | 206 | btrfs_write_dirty_block_groups(trans, extent_root); |
| 203 | while(1) { | 207 | while(1) { |
| 204 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); | 208 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); |
| 205 | if (old_extent_block == bh_blocknr(extent_root->node)) | 209 | if (old_extent_block == |
| 210 | extent_buffer_blocknr(extent_root->node)) | ||
| 206 | break; | 211 | break; |
| 207 | btrfs_set_root_blocknr(&extent_root->root_item, | 212 | btrfs_set_root_blocknr(&extent_root->root_item, |
| 208 | bh_blocknr(extent_root->node)); | 213 | extent_buffer_blocknr(extent_root->node)); |
| 209 | ret = btrfs_update_root(trans, tree_root, | 214 | ret = btrfs_update_root(trans, tree_root, |
| 210 | &extent_root->root_key, | 215 | &extent_root->root_key, |
| 211 | &extent_root->root_item); | 216 | &extent_root->root_item); |
| @@ -279,9 +284,9 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans, | |||
| 279 | (unsigned long)root->root_key.objectid, | 284 | (unsigned long)root->root_key.objectid, |
| 280 | BTRFS_ROOT_TRANS_TAG); | 285 | BTRFS_ROOT_TRANS_TAG); |
| 281 | if (root->commit_root == root->node) { | 286 | if (root->commit_root == root->node) { |
| 282 | WARN_ON(bh_blocknr(root->node) != | 287 | WARN_ON(extent_buffer_blocknr(root->node) != |
| 283 | btrfs_root_blocknr(&root->root_item)); | 288 | btrfs_root_blocknr(&root->root_item)); |
| 284 | brelse(root->commit_root); | 289 | free_extent_buffer(root->commit_root); |
| 285 | root->commit_root = NULL; | 290 | root->commit_root = NULL; |
| 286 | 291 | ||
| 287 | /* make sure to update the root on disk | 292 | /* make sure to update the root on disk |
| @@ -310,7 +315,7 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans, | |||
| 310 | 315 | ||
| 311 | root->root_key.offset = root->fs_info->generation; | 316 | root->root_key.offset = root->fs_info->generation; |
| 312 | btrfs_set_root_blocknr(&root->root_item, | 317 | btrfs_set_root_blocknr(&root->root_item, |
| 313 | bh_blocknr(root->node)); | 318 | extent_buffer_blocknr(root->node)); |
| 314 | err = btrfs_insert_root(trans, root->fs_info->tree_root, | 319 | err = btrfs_insert_root(trans, root->fs_info->tree_root, |
| 315 | &root->root_key, | 320 | &root->root_key, |
| 316 | &root->root_item); | 321 | &root->root_item); |
| @@ -389,10 +394,10 @@ int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info) | |||
| 389 | for (i = 0; i < ret; i++) { | 394 | for (i = 0; i < ret; i++) { |
| 390 | root = gang[i]; | 395 | root = gang[i]; |
| 391 | last = root->root_key.objectid + 1; | 396 | last = root->root_key.objectid + 1; |
| 392 | btrfs_defrag_root(root, 1); | 397 | // btrfs_defrag_root(root, 1); |
| 393 | } | 398 | } |
| 394 | } | 399 | } |
| 395 | btrfs_defrag_root(info->extent_root, 1); | 400 | // btrfs_defrag_root(info->extent_root, 1); |
| 396 | return err; | 401 | return err; |
| 397 | } | 402 | } |
| 398 | 403 | ||
| @@ -414,7 +419,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root, | |||
| 414 | dirty = list_entry(list->next, struct dirty_root, list); | 419 | dirty = list_entry(list->next, struct dirty_root, list); |
| 415 | list_del_init(&dirty->list); | 420 | list_del_init(&dirty->list); |
| 416 | 421 | ||
| 417 | num_blocks = btrfs_root_blocks_used(&dirty->root->root_item); | 422 | num_blocks = btrfs_root_used(&dirty->root->root_item); |
| 418 | root = dirty->latest_root; | 423 | root = dirty->latest_root; |
| 419 | 424 | ||
| 420 | while(1) { | 425 | while(1) { |
| @@ -441,11 +446,11 @@ static int drop_dirty_roots(struct btrfs_root *tree_root, | |||
| 441 | } | 446 | } |
| 442 | BUG_ON(ret); | 447 | BUG_ON(ret); |
| 443 | 448 | ||
| 444 | num_blocks -= btrfs_root_blocks_used(&dirty->root->root_item); | 449 | num_blocks -= btrfs_root_used(&dirty->root->root_item); |
| 445 | blocks_used = btrfs_root_blocks_used(&root->root_item); | 450 | blocks_used = btrfs_root_used(&root->root_item); |
| 446 | if (num_blocks) { | 451 | if (num_blocks) { |
| 447 | record_root_in_trans(root); | 452 | record_root_in_trans(root); |
| 448 | btrfs_set_root_blocks_used(&root->root_item, | 453 | btrfs_set_root_used(&root->root_item, |
| 449 | blocks_used - num_blocks); | 454 | blocks_used - num_blocks); |
| 450 | } | 455 | } |
| 451 | ret = btrfs_del_root(trans, tree_root, &dirty->root->root_key); | 456 | ret = btrfs_del_root(trans, tree_root, &dirty->root->root_key); |
| @@ -553,9 +558,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 553 | btrfs_set_super_generation(&root->fs_info->super_copy, | 558 | btrfs_set_super_generation(&root->fs_info->super_copy, |
| 554 | cur_trans->transid); | 559 | cur_trans->transid); |
| 555 | btrfs_set_super_root(&root->fs_info->super_copy, | 560 | btrfs_set_super_root(&root->fs_info->super_copy, |
| 556 | bh_blocknr(root->fs_info->tree_root->node)); | 561 | extent_buffer_blocknr(root->fs_info->tree_root->node)); |
| 557 | memcpy(root->fs_info->disk_super, &root->fs_info->super_copy, | 562 | |
| 558 | sizeof(root->fs_info->super_copy)); | 563 | write_extent_buffer(root->fs_info->sb_buffer, |
| 564 | &root->fs_info->super_copy, 0, | ||
| 565 | sizeof(root->fs_info->super_copy)); | ||
| 559 | 566 | ||
| 560 | btrfs_copy_pinned(root, &pinned_copy); | 567 | btrfs_copy_pinned(root, &pinned_copy); |
| 561 | 568 | ||
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 4bc328cbb24c..ae39fcfc169a 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
| @@ -28,7 +28,7 @@ struct btrfs_transaction { | |||
| 28 | int use_count; | 28 | int use_count; |
| 29 | int commit_done; | 29 | int commit_done; |
| 30 | struct list_head list; | 30 | struct list_head list; |
| 31 | struct radix_tree_root dirty_pages; | 31 | struct extent_map_tree dirty_pages; |
| 32 | unsigned long start_time; | 32 | unsigned long start_time; |
| 33 | wait_queue_head_t writer_wait; | 33 | wait_queue_head_t writer_wait; |
| 34 | wait_queue_head_t commit_wait; | 34 | wait_queue_head_t commit_wait; |
| @@ -83,5 +83,6 @@ int btrfs_add_dead_root(struct btrfs_root *root, struct btrfs_root *latest, | |||
| 83 | int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info); | 83 | int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info); |
| 84 | int btrfs_defrag_root(struct btrfs_root *root, int cacheonly); | 84 | int btrfs_defrag_root(struct btrfs_root *root, int cacheonly); |
| 85 | int btrfs_clean_old_snapshots(struct btrfs_root *root); | 85 | int btrfs_clean_old_snapshots(struct btrfs_root *root); |
| 86 | 86 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |
| 87 | struct btrfs_root *root); | ||
| 87 | #endif | 88 | #endif |
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index 420597127ed1..daf019afa0a1 100644 --- a/fs/btrfs/tree-defrag.c +++ b/fs/btrfs/tree-defrag.c | |||
| @@ -23,14 +23,14 @@ | |||
| 23 | #include "transaction.h" | 23 | #include "transaction.h" |
| 24 | 24 | ||
| 25 | static void reada_defrag(struct btrfs_root *root, | 25 | static void reada_defrag(struct btrfs_root *root, |
| 26 | struct btrfs_node *node) | 26 | struct extent_buffer *node) |
| 27 | { | 27 | { |
| 28 | int i; | 28 | int i; |
| 29 | u32 nritems; | 29 | u32 nritems; |
| 30 | u64 blocknr; | 30 | u64 blocknr; |
| 31 | int ret; | 31 | int ret; |
| 32 | 32 | ||
| 33 | nritems = btrfs_header_nritems(&node->header); | 33 | nritems = btrfs_header_nritems(node); |
| 34 | for (i = 0; i < nritems; i++) { | 34 | for (i = 0; i < nritems; i++) { |
| 35 | blocknr = btrfs_node_blockptr(node, i); | 35 | blocknr = btrfs_node_blockptr(node, i); |
| 36 | ret = readahead_tree_block(root, blocknr); | 36 | ret = readahead_tree_block(root, blocknr); |
| @@ -44,8 +44,8 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans, | |||
| 44 | struct btrfs_path *path, int *level, | 44 | struct btrfs_path *path, int *level, |
| 45 | int cache_only, u64 *last_ret) | 45 | int cache_only, u64 *last_ret) |
| 46 | { | 46 | { |
| 47 | struct buffer_head *next; | 47 | struct extent_buffer *next; |
| 48 | struct buffer_head *cur; | 48 | struct extent_buffer *cur; |
| 49 | u64 blocknr; | 49 | u64 blocknr; |
| 50 | int ret = 0; | 50 | int ret = 0; |
| 51 | int is_extent = 0; | 51 | int is_extent = 0; |
| @@ -62,13 +62,13 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans, | |||
| 62 | cur = path->nodes[*level]; | 62 | cur = path->nodes[*level]; |
| 63 | 63 | ||
| 64 | if (!cache_only && *level > 1 && path->slots[*level] == 0) | 64 | if (!cache_only && *level > 1 && path->slots[*level] == 0) |
| 65 | reada_defrag(root, btrfs_buffer_node(cur)); | 65 | reada_defrag(root, cur); |
| 66 | 66 | ||
| 67 | if (btrfs_header_level(btrfs_buffer_header(cur)) != *level) | 67 | if (btrfs_header_level(cur) != *level) |
| 68 | WARN_ON(1); | 68 | WARN_ON(1); |
| 69 | 69 | ||
| 70 | if (path->slots[*level] >= | 70 | if (path->slots[*level] >= |
| 71 | btrfs_header_nritems(btrfs_buffer_header(cur))) | 71 | btrfs_header_nritems(cur)) |
| 72 | break; | 72 | break; |
| 73 | 73 | ||
| 74 | if (*level == 1) { | 74 | if (*level == 1) { |
| @@ -80,14 +80,13 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans, | |||
| 80 | 80 | ||
| 81 | break; | 81 | break; |
| 82 | } | 82 | } |
| 83 | blocknr = btrfs_node_blockptr(btrfs_buffer_node(cur), | 83 | blocknr = btrfs_node_blockptr(cur, path->slots[*level]); |
| 84 | path->slots[*level]); | ||
| 85 | 84 | ||
| 86 | if (cache_only) { | 85 | if (cache_only) { |
| 87 | next = btrfs_find_tree_block(root, blocknr); | 86 | next = btrfs_find_tree_block(root, blocknr); |
| 88 | if (!next || !buffer_uptodate(next) || | 87 | /* FIXME, test for defrag */ |
| 89 | buffer_locked(next) || !buffer_defrag(next)) { | 88 | if (!next || !btrfs_buffer_uptodate(next)) { |
| 90 | brelse(next); | 89 | free_extent_buffer(next); |
| 91 | path->slots[*level]++; | 90 | path->slots[*level]++; |
| 92 | continue; | 91 | continue; |
| 93 | } | 92 | } |
| @@ -106,16 +105,18 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans, | |||
| 106 | 105 | ||
| 107 | WARN_ON(*level <= 0); | 106 | WARN_ON(*level <= 0); |
| 108 | if (path->nodes[*level-1]) | 107 | if (path->nodes[*level-1]) |
| 109 | btrfs_block_release(root, path->nodes[*level-1]); | 108 | free_extent_buffer(path->nodes[*level-1]); |
| 110 | path->nodes[*level-1] = next; | 109 | path->nodes[*level-1] = next; |
| 111 | *level = btrfs_header_level(btrfs_buffer_header(next)); | 110 | *level = btrfs_header_level(next); |
| 112 | path->slots[*level] = 0; | 111 | path->slots[*level] = 0; |
| 113 | } | 112 | } |
| 114 | WARN_ON(*level < 0); | 113 | WARN_ON(*level < 0); |
| 115 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | 114 | WARN_ON(*level >= BTRFS_MAX_LEVEL); |
| 115 | #if 0 | ||
| 116 | clear_buffer_defrag(path->nodes[*level]); | 116 | clear_buffer_defrag(path->nodes[*level]); |
| 117 | clear_buffer_defrag_done(path->nodes[*level]); | 117 | clear_buffer_defrag_done(path->nodes[*level]); |
| 118 | btrfs_block_release(root, path->nodes[*level]); | 118 | #endif |
| 119 | free_extent_buffer(path->nodes[*level]); | ||
| 119 | path->nodes[*level] = NULL; | 120 | path->nodes[*level] = NULL; |
| 120 | *level += 1; | 121 | *level += 1; |
| 121 | WARN_ON(ret); | 122 | WARN_ON(ret); |
| @@ -129,24 +130,25 @@ static int defrag_walk_up(struct btrfs_trans_handle *trans, | |||
| 129 | { | 130 | { |
| 130 | int i; | 131 | int i; |
| 131 | int slot; | 132 | int slot; |
| 132 | struct btrfs_node *node; | 133 | struct extent_buffer *node; |
| 133 | 134 | ||
| 134 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { | 135 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { |
| 135 | slot = path->slots[i]; | 136 | slot = path->slots[i]; |
| 136 | if (slot < btrfs_header_nritems( | 137 | if (slot < btrfs_header_nritems(path->nodes[i]) - 1) { |
| 137 | btrfs_buffer_header(path->nodes[i])) - 1) { | ||
| 138 | path->slots[i]++; | 138 | path->slots[i]++; |
| 139 | *level = i; | 139 | *level = i; |
| 140 | node = btrfs_buffer_node(path->nodes[i]); | 140 | node = path->nodes[i]; |
| 141 | WARN_ON(i == 0); | 141 | WARN_ON(i == 0); |
| 142 | btrfs_disk_key_to_cpu(&root->defrag_progress, | 142 | btrfs_node_key_to_cpu(node, &root->defrag_progress, |
| 143 | &node->ptrs[path->slots[i]].key); | 143 | path->slots[i]); |
| 144 | root->defrag_level = i; | 144 | root->defrag_level = i; |
| 145 | return 0; | 145 | return 0; |
| 146 | } else { | 146 | } else { |
| 147 | /* | ||
| 147 | clear_buffer_defrag(path->nodes[*level]); | 148 | clear_buffer_defrag(path->nodes[*level]); |
| 148 | clear_buffer_defrag_done(path->nodes[*level]); | 149 | clear_buffer_defrag_done(path->nodes[*level]); |
| 149 | btrfs_block_release(root, path->nodes[*level]); | 150 | */ |
| 151 | free_extent_buffer(path->nodes[*level]); | ||
| 150 | path->nodes[*level] = NULL; | 152 | path->nodes[*level] = NULL; |
| 151 | *level = i + 1; | 153 | *level = i + 1; |
| 152 | } | 154 | } |
| @@ -158,7 +160,7 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
| 158 | struct btrfs_root *root, int cache_only) | 160 | struct btrfs_root *root, int cache_only) |
| 159 | { | 161 | { |
| 160 | struct btrfs_path *path = NULL; | 162 | struct btrfs_path *path = NULL; |
| 161 | struct buffer_head *tmp; | 163 | struct extent_buffer *tmp; |
| 162 | int ret = 0; | 164 | int ret = 0; |
| 163 | int wret; | 165 | int wret; |
| 164 | int level; | 166 | int level; |
| @@ -172,17 +174,18 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
| 172 | 174 | ||
| 173 | if (root->ref_cows == 0 && !is_extent) | 175 | if (root->ref_cows == 0 && !is_extent) |
| 174 | goto out; | 176 | goto out; |
| 177 | |||
| 175 | path = btrfs_alloc_path(); | 178 | path = btrfs_alloc_path(); |
| 176 | if (!path) | 179 | if (!path) |
| 177 | return -ENOMEM; | 180 | return -ENOMEM; |
| 178 | 181 | ||
| 179 | level = btrfs_header_level(btrfs_buffer_header(root->node)); | 182 | level = btrfs_header_level(root->node); |
| 180 | orig_level = level; | 183 | orig_level = level; |
| 181 | if (level == 0) { | 184 | if (level == 0) { |
| 182 | goto out; | 185 | goto out; |
| 183 | } | 186 | } |
| 184 | if (root->defrag_progress.objectid == 0) { | 187 | if (root->defrag_progress.objectid == 0) { |
| 185 | get_bh(root->node); | 188 | extent_buffer_get(root->node); |
| 186 | ret = btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); | 189 | ret = btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); |
| 187 | BUG_ON(ret); | 190 | BUG_ON(ret); |
| 188 | ret = btrfs_realloc_node(trans, root, root->node, cache_only, | 191 | ret = btrfs_realloc_node(trans, root, root->node, cache_only, |
| @@ -200,12 +203,15 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
| 200 | 203 | ||
| 201 | if (is_extent) | 204 | if (is_extent) |
| 202 | btrfs_extent_post_op(trans, root); | 205 | btrfs_extent_post_op(trans, root); |
| 206 | |||
| 203 | if (wret < 0) { | 207 | if (wret < 0) { |
| 204 | ret = wret; | 208 | ret = wret; |
| 205 | goto out; | 209 | goto out; |
| 206 | } | 210 | } |
| 211 | |||
| 207 | while(level > 0 && !path->nodes[level]) | 212 | while(level > 0 && !path->nodes[level]) |
| 208 | level--; | 213 | level--; |
| 214 | |||
| 209 | if (!path->nodes[level]) { | 215 | if (!path->nodes[level]) { |
| 210 | ret = 0; | 216 | ret = 0; |
| 211 | goto out; | 217 | goto out; |
| @@ -230,7 +236,7 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
| 230 | } | 236 | } |
| 231 | for (i = 0; i <= orig_level; i++) { | 237 | for (i = 0; i <= orig_level; i++) { |
| 232 | if (path->nodes[i]) { | 238 | if (path->nodes[i]) { |
| 233 | btrfs_block_release(root, path->nodes[i]); | 239 | free_extent_buffer(path->nodes[i]); |
| 234 | path->nodes[i] = 0; | 240 | path->nodes[i] = 0; |
| 235 | } | 241 | } |
| 236 | } | 242 | } |
