diff options
-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) |