diff options
| author | Chris Mason <chris.mason@oracle.com> | 2007-03-23 15:56:19 -0400 |
|---|---|---|
| committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-23 15:56:19 -0400 |
| commit | 7f5c15160e1436a53d01f9190db11c2a3a4d788a (patch) | |
| tree | ae9894ab743aca4ff4c1f50ada5a5ed665a88c21 | |
| parent | df2ce34c8801af8e00c7f82435fcb1e4b45a2759 (diff) | |
Add generation number to btrfs_header, readdir fixes, hash collision fixes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
| -rw-r--r-- | fs/btrfs/ctree.c | 8 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 14 | ||||
| -rw-r--r-- | fs/btrfs/dir-item.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 14 |
5 files changed, 32 insertions, 14 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 052434a328ec..b33a6bfaf327 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include <linux/module.h> | 1 | #include <linux/module.h> |
| 2 | #include "ctree.h" | 2 | #include "ctree.h" |
| 3 | #include "disk-io.h" | 3 | #include "disk-io.h" |
| 4 | #include "transaction.h" | ||
| 4 | 5 | ||
| 5 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | 6 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root |
| 6 | *root, struct btrfs_path *path, int level); | 7 | *root, struct btrfs_path *path, int level); |
| @@ -39,7 +40,8 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 39 | struct buffer_head *cow; | 40 | struct buffer_head *cow; |
| 40 | struct btrfs_node *cow_node; | 41 | struct btrfs_node *cow_node; |
| 41 | 42 | ||
| 42 | if (buffer_dirty(buf)) { | 43 | if (btrfs_header_generation(btrfs_buffer_header(buf)) == |
| 44 | trans->transid) { | ||
| 43 | *cow_ret = buf; | 45 | *cow_ret = buf; |
| 44 | return 0; | 46 | return 0; |
| 45 | } | 47 | } |
| @@ -47,6 +49,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 47 | cow_node = btrfs_buffer_node(cow); | 49 | cow_node = btrfs_buffer_node(cow); |
| 48 | memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize); | 50 | memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize); |
| 49 | btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr); | 51 | btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr); |
| 52 | btrfs_set_header_generation(&cow_node->header, trans->transid); | ||
| 50 | *cow_ret = cow; | 53 | *cow_ret = cow; |
| 51 | mark_buffer_dirty(cow); | 54 | mark_buffer_dirty(cow); |
| 52 | btrfs_inc_ref(trans, root, buf); | 55 | btrfs_inc_ref(trans, root, buf); |
| @@ -661,6 +664,7 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 661 | btrfs_set_header_nritems(&c->header, 1); | 664 | btrfs_set_header_nritems(&c->header, 1); |
| 662 | btrfs_set_header_level(&c->header, level); | 665 | btrfs_set_header_level(&c->header, level); |
| 663 | btrfs_set_header_blocknr(&c->header, t->b_blocknr); | 666 | btrfs_set_header_blocknr(&c->header, t->b_blocknr); |
| 667 | btrfs_set_header_generation(&c->header, trans->transid); | ||
| 664 | btrfs_set_header_parentid(&c->header, | 668 | btrfs_set_header_parentid(&c->header, |
| 665 | btrfs_header_parentid(btrfs_buffer_header(root->node))); | 669 | btrfs_header_parentid(btrfs_buffer_header(root->node))); |
| 666 | lower = btrfs_buffer_node(path->nodes[level-1]); | 670 | lower = btrfs_buffer_node(path->nodes[level-1]); |
| @@ -750,6 +754,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 750 | split = btrfs_buffer_node(split_buffer); | 754 | split = btrfs_buffer_node(split_buffer); |
| 751 | btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header)); | 755 | btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header)); |
| 752 | btrfs_set_header_blocknr(&split->header, split_buffer->b_blocknr); | 756 | btrfs_set_header_blocknr(&split->header, split_buffer->b_blocknr); |
| 757 | btrfs_set_header_generation(&split->header, trans->transid); | ||
| 753 | btrfs_set_header_parentid(&split->header, | 758 | btrfs_set_header_parentid(&split->header, |
| 754 | btrfs_header_parentid(btrfs_buffer_header(root->node))); | 759 | btrfs_header_parentid(btrfs_buffer_header(root->node))); |
| 755 | mid = (c_nritems + 1) / 2; | 760 | mid = (c_nritems + 1) / 2; |
| @@ -1096,6 +1101,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1096 | } | 1101 | } |
| 1097 | btrfs_set_header_nritems(&right->header, nritems - mid); | 1102 | btrfs_set_header_nritems(&right->header, nritems - mid); |
| 1098 | btrfs_set_header_blocknr(&right->header, right_buffer->b_blocknr); | 1103 | btrfs_set_header_blocknr(&right->header, right_buffer->b_blocknr); |
| 1104 | btrfs_set_header_generation(&right->header, trans->transid); | ||
| 1099 | btrfs_set_header_level(&right->header, 0); | 1105 | btrfs_set_header_level(&right->header, 0); |
| 1100 | btrfs_set_header_parentid(&right->header, | 1106 | btrfs_set_header_parentid(&right->header, |
| 1101 | btrfs_header_parentid(btrfs_buffer_header(root->node))); | 1107 | btrfs_header_parentid(btrfs_buffer_header(root->node))); |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 983e3cc9ae9f..96cec6352f12 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -52,6 +52,7 @@ struct btrfs_key { | |||
| 52 | struct btrfs_header { | 52 | struct btrfs_header { |
| 53 | u8 fsid[16]; /* FS specific uuid */ | 53 | u8 fsid[16]; /* FS specific uuid */ |
| 54 | __le64 blocknr; /* which block this node is supposed to live in */ | 54 | __le64 blocknr; /* which block this node is supposed to live in */ |
| 55 | __le64 generation; | ||
| 55 | __le64 parentid; /* objectid of the tree root */ | 56 | __le64 parentid; /* objectid of the tree root */ |
| 56 | __le32 csum; | 57 | __le32 csum; |
| 57 | __le32 ham; | 58 | __le32 ham; |
| @@ -600,6 +601,17 @@ static inline void btrfs_set_header_blocknr(struct btrfs_header *h, u64 blocknr) | |||
| 600 | h->blocknr = cpu_to_le64(blocknr); | 601 | h->blocknr = cpu_to_le64(blocknr); |
| 601 | } | 602 | } |
| 602 | 603 | ||
| 604 | static inline u64 btrfs_header_generation(struct btrfs_header *h) | ||
| 605 | { | ||
| 606 | return le64_to_cpu(h->generation); | ||
| 607 | } | ||
| 608 | |||
| 609 | static inline void btrfs_set_header_generation(struct btrfs_header *h, | ||
| 610 | u64 val) | ||
| 611 | { | ||
| 612 | h->generation = cpu_to_le64(val); | ||
| 613 | } | ||
| 614 | |||
| 603 | static inline u64 btrfs_header_parentid(struct btrfs_header *h) | 615 | static inline u64 btrfs_header_parentid(struct btrfs_header *h) |
| 604 | { | 616 | { |
| 605 | return le64_to_cpu(h->parentid); | 617 | return le64_to_cpu(h->parentid); |
| @@ -839,7 +851,7 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 839 | *root, struct btrfs_path *path, u64 dir, | 851 | *root, struct btrfs_path *path, u64 dir, |
| 840 | const char *name, int name_len, int mod); | 852 | const char *name, int name_len, int mod); |
| 841 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, | 853 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, |
| 842 | char *name, int name_len); | 854 | const char *name, int name_len); |
| 843 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | 855 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, |
| 844 | struct btrfs_root *fs_root, | 856 | struct btrfs_root *fs_root, |
| 845 | u64 dirid, u64 *objectid); | 857 | u64 dirid, u64 *objectid); |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index f81cbcc83b66..c18f81797a88 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
| @@ -60,8 +60,8 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | int btrfs_match_dir_item_name(struct btrfs_root *root, | 62 | int btrfs_match_dir_item_name(struct btrfs_root *root, |
| 63 | struct btrfs_path *path, char | 63 | struct btrfs_path *path, |
| 64 | *name, int name_len) | 64 | const char *name, int name_len) |
| 65 | { | 65 | { |
| 66 | struct btrfs_dir_item *dir_item; | 66 | struct btrfs_dir_item *dir_item; |
| 67 | char *name_ptr; | 67 | char *name_ptr; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 2f1eb4ae4e1d..3dea757d4cbb 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -11,11 +11,7 @@ static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) | |||
| 11 | BUG(); | 11 | BUG(); |
| 12 | if (root->node && btrfs_header_parentid(&node->header) != | 12 | if (root->node && btrfs_header_parentid(&node->header) != |
| 13 | btrfs_header_parentid(btrfs_buffer_header(root->node))) { | 13 | btrfs_header_parentid(btrfs_buffer_header(root->node))) { |
| 14 | printk("block %Lu parentids don't match buf %Lu, root %Lu\n", | 14 | BUG(); |
| 15 | buf->b_blocknr, | ||
| 16 | btrfs_header_parentid(&node->header), | ||
| 17 | btrfs_header_parentid(btrfs_buffer_header(root->node))); | ||
| 18 | WARN_ON(1); | ||
| 19 | } | 15 | } |
| 20 | return 0; | 16 | return 0; |
| 21 | } | 17 | } |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8970e9a82156..a2db05594695 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -199,7 +199,7 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, | |||
| 199 | btrfs_init_path(&path); | 199 | btrfs_init_path(&path); |
| 200 | ret = btrfs_lookup_dir_item(NULL, root, &path, dir->i_ino, name, | 200 | ret = btrfs_lookup_dir_item(NULL, root, &path, dir->i_ino, name, |
| 201 | namelen, 0); | 201 | namelen, 0); |
| 202 | if (ret) { | 202 | if (ret || !btrfs_match_dir_item_name(root, &path, name, namelen)) { |
| 203 | *ino = 0; | 203 | *ino = 0; |
| 204 | goto out; | 204 | goto out; |
| 205 | } | 205 | } |
| @@ -247,7 +247,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 247 | int slot; | 247 | int slot; |
| 248 | int advance; | 248 | int advance; |
| 249 | unsigned char d_type = DT_UNKNOWN; | 249 | unsigned char d_type = DT_UNKNOWN; |
| 250 | int over; | 250 | int over = 0; |
| 251 | 251 | ||
| 252 | key.objectid = inode->i_ino; | 252 | key.objectid = inode->i_ino; |
| 253 | key.flags = 0; | 253 | key.flags = 0; |
| @@ -258,7 +258,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 258 | if (ret < 0) { | 258 | if (ret < 0) { |
| 259 | goto err; | 259 | goto err; |
| 260 | } | 260 | } |
| 261 | advance = filp->f_pos > 0 && ret != 0; | 261 | advance = 0; |
| 262 | while(1) { | 262 | while(1) { |
| 263 | leaf = btrfs_buffer_leaf(path.nodes[0]); | 263 | leaf = btrfs_buffer_leaf(path.nodes[0]); |
| 264 | nritems = btrfs_header_nritems(&leaf->header); | 264 | nritems = btrfs_header_nritems(&leaf->header); |
| @@ -282,13 +282,17 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 282 | break; | 282 | break; |
| 283 | if (btrfs_disk_key_type(&item->key) != BTRFS_DIR_ITEM_KEY) | 283 | if (btrfs_disk_key_type(&item->key) != BTRFS_DIR_ITEM_KEY) |
| 284 | continue; | 284 | continue; |
| 285 | if (btrfs_disk_key_offset(&item->key) < filp->f_pos) | ||
| 286 | continue; | ||
| 285 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); | 287 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); |
| 286 | over = filldir(dirent, (const char *)(di + 1), | 288 | over = filldir(dirent, (const char *)(di + 1), |
| 287 | btrfs_dir_name_len(di), | 289 | btrfs_dir_name_len(di), |
| 288 | btrfs_disk_key_offset(&item->key), | 290 | btrfs_disk_key_offset(&item->key), |
| 289 | btrfs_dir_objectid(di), d_type); | 291 | btrfs_dir_objectid(di), d_type); |
| 290 | if (over) | 292 | if (over) { |
| 293 | filp->f_pos = btrfs_disk_key_offset(&item->key); | ||
| 291 | break; | 294 | break; |
| 295 | } | ||
| 292 | filp->f_pos = btrfs_disk_key_offset(&item->key) + 1; | 296 | filp->f_pos = btrfs_disk_key_offset(&item->key) + 1; |
| 293 | } | 297 | } |
| 294 | ret = 0; | 298 | ret = 0; |
| @@ -425,7 +429,6 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
| 425 | dentry->d_name.name, dentry->d_name.len, | 429 | dentry->d_name.name, dentry->d_name.len, |
| 426 | dentry->d_parent->d_inode->i_ino, | 430 | dentry->d_parent->d_inode->i_ino, |
| 427 | inode->i_ino, 0); | 431 | inode->i_ino, 0); |
| 428 | BUG_ON(ret); | ||
| 429 | return ret; | 432 | return ret; |
| 430 | } | 433 | } |
| 431 | 434 | ||
| @@ -466,6 +469,7 @@ static void btrfs_write_super(struct super_block *sb) | |||
| 466 | { | 469 | { |
| 467 | sb->s_dirt = 0; | 470 | sb->s_dirt = 0; |
| 468 | printk("btrfs write_super!\n"); | 471 | printk("btrfs write_super!\n"); |
| 472 | filemap_flush(sb->s_bdev->bd_inode->i_mapping); | ||
| 469 | } | 473 | } |
| 470 | 474 | ||
| 471 | static int btrfs_sync_fs(struct super_block *sb, int wait) | 475 | static int btrfs_sync_fs(struct super_block *sb, int wait) |
