aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-12-11 09:25:06 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:58 -0400
commit74493f7a59bfd4d1c7029c74ab2cd0e400612c6b (patch)
treeb5fc75b08d2edcf8218c814ea02ab6c548e73652 /fs/btrfs
parent17636e03f42a1a42fed3834859de4702bd655fd1 (diff)
Btrfs: Implement generation numbers in block pointers
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.c16
-rw-r--r--fs/btrfs/ctree.h47
-rw-r--r--fs/btrfs/extent-tree.c60
3 files changed, 115 insertions, 8 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 3b16051b121b..5697705f7530 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -114,6 +114,9 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans,
114 } else { 114 } else {
115 btrfs_set_node_blockptr(parent, parent_slot, 115 btrfs_set_node_blockptr(parent, parent_slot,
116 cow->start); 116 cow->start);
117 WARN_ON(trans->transid == 0);
118 btrfs_set_node_ptr_generation(parent, parent_slot,
119 trans->transid);
117 btrfs_mark_buffer_dirty(parent); 120 btrfs_mark_buffer_dirty(parent);
118 WARN_ON(btrfs_header_generation(parent) != trans->transid); 121 WARN_ON(btrfs_header_generation(parent) != trans->transid);
119 btrfs_free_extent(trans, root, buf->start, buf->len, 1); 122 btrfs_free_extent(trans, root, buf->start, buf->len, 1);
@@ -967,6 +970,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
967{ 970{
968 struct extent_buffer *b; 971 struct extent_buffer *b;
969 u64 bytenr; 972 u64 bytenr;
973 u64 ptr_gen;
970 int slot; 974 int slot;
971 int ret; 975 int ret;
972 int level; 976 int level;
@@ -1031,10 +1035,18 @@ again:
1031 if (level == lowest_level) 1035 if (level == lowest_level)
1032 break; 1036 break;
1033 bytenr = btrfs_node_blockptr(b, slot); 1037 bytenr = btrfs_node_blockptr(b, slot);
1038 ptr_gen = btrfs_node_ptr_generation(b, slot);
1034 if (should_reada) 1039 if (should_reada)
1035 reada_for_search(root, p, level, slot); 1040 reada_for_search(root, p, level, slot);
1036 b = read_tree_block(root, bytenr, 1041 b = read_tree_block(root, bytenr,
1037 btrfs_level_size(root, level - 1)); 1042 btrfs_level_size(root, level - 1));
1043 if (ptr_gen != btrfs_header_generation(b)) {
1044 printk("block %llu bad gen wanted %llu "
1045 "found %llu\n",
1046 (unsigned long long)b->start,
1047 (unsigned long long)ptr_gen,
1048 (unsigned long long)btrfs_header_generation(b));
1049 }
1038 } else { 1050 } else {
1039 p->slots[level] = slot; 1051 p->slots[level] = slot;
1040 if (ins_len > 0 && btrfs_leaf_free_space(root, b) < 1052 if (ins_len > 0 && btrfs_leaf_free_space(root, b) <
@@ -1218,6 +1230,8 @@ static int insert_new_root(struct btrfs_trans_handle *trans,
1218 btrfs_node_key(lower, &lower_key, 0); 1230 btrfs_node_key(lower, &lower_key, 0);
1219 btrfs_set_node_key(c, &lower_key, 0); 1231 btrfs_set_node_key(c, &lower_key, 0);
1220 btrfs_set_node_blockptr(c, 0, lower->start); 1232 btrfs_set_node_blockptr(c, 0, lower->start);
1233 WARN_ON(btrfs_header_generation(lower) == 0);
1234 btrfs_set_node_ptr_generation(c, 0, btrfs_header_generation(lower));
1221 1235
1222 btrfs_mark_buffer_dirty(c); 1236 btrfs_mark_buffer_dirty(c);
1223 1237
@@ -1261,6 +1275,8 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
1261 } 1275 }
1262 btrfs_set_node_key(lower, key, slot); 1276 btrfs_set_node_key(lower, key, slot);
1263 btrfs_set_node_blockptr(lower, slot, bytenr); 1277 btrfs_set_node_blockptr(lower, slot, bytenr);
1278 WARN_ON(trans->transid == 0);
1279 btrfs_set_node_ptr_generation(lower, slot, trans->transid);
1264 btrfs_set_header_nritems(lower, nritems + 1); 1280 btrfs_set_header_nritems(lower, nritems + 1);
1265 btrfs_mark_buffer_dirty(lower); 1281 btrfs_mark_buffer_dirty(lower);
1266 return 0; 1282 return 0;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 9bc1b0a8615f..fd58dd846e61 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -110,7 +110,7 @@ struct btrfs_header {
110#define BTRFS_MAX_LEVEL 8 110#define BTRFS_MAX_LEVEL 8
111#define BTRFS_NODEPTRS_PER_BLOCK(r) (((r)->nodesize - \ 111#define BTRFS_NODEPTRS_PER_BLOCK(r) (((r)->nodesize - \
112 sizeof(struct btrfs_header)) / \ 112 sizeof(struct btrfs_header)) / \
113 (sizeof(struct btrfs_disk_key) + sizeof(u64))) 113 sizeof(struct btrfs_key_ptr))
114#define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header)) 114#define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header))
115#define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->leafsize)) 115#define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->leafsize))
116#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \ 116#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
@@ -168,6 +168,7 @@ struct btrfs_leaf {
168struct btrfs_key_ptr { 168struct btrfs_key_ptr {
169 struct btrfs_disk_key key; 169 struct btrfs_disk_key key;
170 __le64 blockptr; 170 __le64 blockptr;
171 __le64 generation;
171} __attribute__ ((__packed__)); 172} __attribute__ ((__packed__));
172 173
173struct btrfs_node { 174struct btrfs_node {
@@ -196,7 +197,13 @@ struct btrfs_path {
196 */ 197 */
197struct btrfs_extent_item { 198struct btrfs_extent_item {
198 __le32 refs; 199 __le32 refs;
199 __le64 owner; 200} __attribute__ ((__packed__));
201
202struct btrfs_extent_ref {
203 __le64 root;
204 __le64 generation;
205 __le64 objectid;
206 __le64 offset;
200} __attribute__ ((__packed__)); 207} __attribute__ ((__packed__));
201 208
202struct btrfs_inode_timespec { 209struct btrfs_inode_timespec {
@@ -402,12 +409,13 @@ struct btrfs_root {
402 * are used, and how many references there are to each block 409 * are used, and how many references there are to each block
403 */ 410 */
404#define BTRFS_EXTENT_ITEM_KEY 33 411#define BTRFS_EXTENT_ITEM_KEY 33
412#define BTRFS_EXTENT_REF_KEY 34
405 413
406/* 414/*
407 * block groups give us hints into the extent allocation trees. Which 415 * block groups give us hints into the extent allocation trees. Which
408 * blocks are free etc etc 416 * blocks are free etc etc
409 */ 417 */
410#define BTRFS_BLOCK_GROUP_ITEM_KEY 34 418#define BTRFS_BLOCK_GROUP_ITEM_KEY 50
411 419
412/* 420/*
413 * string items are for debugging. They just store a short string of 421 * string items are for debugging. They just store a short string of
@@ -529,15 +537,25 @@ BTRFS_SETGET_FUNCS(timespec_nsec, struct btrfs_inode_timespec, nsec, 32);
529 537
530/* struct btrfs_extent_item */ 538/* struct btrfs_extent_item */
531BTRFS_SETGET_FUNCS(extent_refs, struct btrfs_extent_item, refs, 32); 539BTRFS_SETGET_FUNCS(extent_refs, struct btrfs_extent_item, refs, 32);
532BTRFS_SETGET_FUNCS(extent_owner, struct btrfs_extent_item, owner, 64); 540
541/* struct btrfs_extent_ref */
542BTRFS_SETGET_FUNCS(ref_root, struct btrfs_extent_ref, root, 64);
543BTRFS_SETGET_FUNCS(ref_generation, struct btrfs_extent_ref, generation, 64);
544BTRFS_SETGET_FUNCS(ref_objectid, struct btrfs_extent_ref, objectid, 64);
545BTRFS_SETGET_FUNCS(ref_offset, struct btrfs_extent_ref, offset, 64);
546
547BTRFS_SETGET_STACK_FUNCS(ref_root, struct btrfs_extent_ref, root, 64);
548BTRFS_SETGET_STACK_FUNCS(ref_generation, struct btrfs_extent_ref,
549 generation, 64);
550BTRFS_SETGET_STACK_FUNCS(ref_objectid, struct btrfs_extent_ref, objectid, 64);
551BTRFS_SETGET_STACK_FUNCS(ref_offset, struct btrfs_extent_ref, offset, 64);
533 552
534BTRFS_SETGET_STACK_FUNCS(stack_extent_refs, struct btrfs_extent_item, 553BTRFS_SETGET_STACK_FUNCS(stack_extent_refs, struct btrfs_extent_item,
535 refs, 32); 554 refs, 32);
536BTRFS_SETGET_STACK_FUNCS(stack_extent_owner, struct btrfs_extent_item,
537 owner, 64);
538 555
539/* struct btrfs_node */ 556/* struct btrfs_node */
540BTRFS_SETGET_FUNCS(key_blockptr, struct btrfs_key_ptr, blockptr, 64); 557BTRFS_SETGET_FUNCS(key_blockptr, struct btrfs_key_ptr, blockptr, 64);
558BTRFS_SETGET_FUNCS(key_generation, struct btrfs_key_ptr, generation, 64);
541 559
542static inline u64 btrfs_node_blockptr(struct extent_buffer *eb, int nr) 560static inline u64 btrfs_node_blockptr(struct extent_buffer *eb, int nr)
543{ 561{
@@ -556,6 +574,23 @@ static inline void btrfs_set_node_blockptr(struct extent_buffer *eb,
556 btrfs_set_key_blockptr(eb, (struct btrfs_key_ptr *)ptr, val); 574 btrfs_set_key_blockptr(eb, (struct btrfs_key_ptr *)ptr, val);
557} 575}
558 576
577static inline u64 btrfs_node_ptr_generation(struct extent_buffer *eb, int nr)
578{
579 unsigned long ptr;
580 ptr = offsetof(struct btrfs_node, ptrs) +
581 sizeof(struct btrfs_key_ptr) * nr;
582 return btrfs_key_generation(eb, (struct btrfs_key_ptr *)ptr);
583}
584
585static inline void btrfs_set_node_ptr_generation(struct extent_buffer *eb,
586 int nr, u64 val)
587{
588 unsigned long ptr;
589 ptr = offsetof(struct btrfs_node, ptrs) +
590 sizeof(struct btrfs_key_ptr) * nr;
591 btrfs_set_key_generation(eb, (struct btrfs_key_ptr *)ptr, val);
592}
593
559static inline unsigned long btrfs_node_key_ptr_offset(int nr) 594static inline unsigned long btrfs_node_key_ptr_offset(int nr)
560{ 595{
561 return offsetof(struct btrfs_node, ptrs) + 596 return offsetof(struct btrfs_node, ptrs) +
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 8ab4954f6ad0..0f1ebdd4e925 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -17,6 +17,7 @@
17 */ 17 */
18 18
19#include <linux/sched.h> 19#include <linux/sched.h>
20#include "hash.h"
20#include "ctree.h" 21#include "ctree.h"
21#include "disk-io.h" 22#include "disk-io.h"
22#include "print-tree.h" 23#include "print-tree.h"
@@ -352,9 +353,63 @@ found:
352 return found_group; 353 return found_group;
353} 354}
354 355
356static u64 hash_extent_ref(u64 root_objectid, u64 root_generation,
357 u64 owner, u64 owner_offset)
358{
359 u32 high_crc = ~(u32)0;
360 u32 low_crc = ~(u32)0;
361 __le64 lenum;
362
363 lenum = cpu_to_le64(root_objectid);
364 high_crc = crc32c(high_crc, &lenum, sizeof(lenum));
365 lenum = cpu_to_le64(root_generation);
366 high_crc = crc32c(high_crc, &lenum, sizeof(lenum));
367
368 lenum = cpu_to_le64(owner);
369 low_crc = crc32c(low_crc, &lenum, sizeof(lenum));
370
371 lenum = cpu_to_le64(owner_offset);
372 low_crc = crc32c(low_crc, &lenum, sizeof(lenum));
373
374 return ((u64)high_crc << 32) | (u64)low_crc;
375}
376
377int insert_extent_ref(struct btrfs_trans_handle *trans,
378 struct btrfs_root *root,
379 struct btrfs_path *path,
380 u64 bytenr,
381 u64 root_objectid, u64 root_generation,
382 u64 owner, u64 owner_offset)
383{
384 u64 hash;
385 struct btrfs_key key;
386 struct btrfs_extent_ref ref;
387 struct extent_buffer *l;
388 struct btrfs_extent_item *item;
389 int ret;
390
391 btrfs_set_stack_ref_root(&ref, root_objectid);
392 btrfs_set_stack_ref_generation(&ref, root_generation);
393 btrfs_set_stack_ref_objectid(&ref, owner);
394 btrfs_set_stack_ref_offset(&ref, owner_offset);
395
396 ret = btrfs_name_hash(&ref, sizeof(ref), &hash);
397 key.offset = hash;
398 key.objectid = bytenr;
399 key.type = BTRFS_EXTENT_REF_KEY;
400
401 ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(ref));
402 while (ret == -EEXIST) {
403
404 }
405
406}
407
355int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, 408int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
356 struct btrfs_root *root, 409 struct btrfs_root *root,
357 u64 bytenr, u64 num_bytes) 410 u64 bytenr, u64 num_bytes,
411 u64 root_objectid, u64 root_generation,
412 u64 owner, u64 owner_offset)
358{ 413{
359 struct btrfs_path *path; 414 struct btrfs_path *path;
360 int ret; 415 int ret;
@@ -386,9 +441,10 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
386 btrfs_mark_buffer_dirty(path->nodes[0]); 441 btrfs_mark_buffer_dirty(path->nodes[0]);
387 442
388 btrfs_release_path(root->fs_info->extent_root, path); 443 btrfs_release_path(root->fs_info->extent_root, path);
389 btrfs_free_path(path);
390 finish_current_insert(trans, root->fs_info->extent_root); 444 finish_current_insert(trans, root->fs_info->extent_root);
391 del_pending_extents(trans, root->fs_info->extent_root); 445 del_pending_extents(trans, root->fs_info->extent_root);
446
447 btrfs_free_path(path);
392 return 0; 448 return 0;
393} 449}
394 450