diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-02 10:50:19 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-02 10:50:19 -0400 |
commit | 2c90e5d658424bc71b111eb5a972240d5d06fe86 (patch) | |
tree | f46b830654af0f67ef1691353fe4d79943a05465 | |
parent | d6025579531b7ea170ba283b171ff7a6bf7d0e12 (diff) |
Btrfs: still corruption hunting
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/bit-radix.c | 7 | ||||
-rw-r--r-- | fs/btrfs/btrfs_inode.h | 14 | ||||
-rw-r--r-- | fs/btrfs/ctree.c | 42 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 84 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 4 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 18 | ||||
-rw-r--r-- | fs/btrfs/super.c | 146 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 39 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 3 |
10 files changed, 265 insertions, 95 deletions
diff --git a/fs/btrfs/bit-radix.c b/fs/btrfs/bit-radix.c index 845422368f48..a50a1c44eabd 100644 --- a/fs/btrfs/bit-radix.c +++ b/fs/btrfs/bit-radix.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #define BIT_ARRAY_BYTES 256 | 4 | #define BIT_ARRAY_BYTES 256 |
5 | #define BIT_RADIX_BITS_PER_ARRAY ((BIT_ARRAY_BYTES - sizeof(unsigned long)) * 8) | 5 | #define BIT_RADIX_BITS_PER_ARRAY ((BIT_ARRAY_BYTES - sizeof(unsigned long)) * 8) |
6 | 6 | ||
7 | extern struct kmem_cache *btrfs_bit_radix_cachep; | ||
7 | int set_radix_bit(struct radix_tree_root *radix, unsigned long bit) | 8 | int set_radix_bit(struct radix_tree_root *radix, unsigned long bit) |
8 | { | 9 | { |
9 | unsigned long *bits; | 10 | unsigned long *bits; |
@@ -16,7 +17,7 @@ int set_radix_bit(struct radix_tree_root *radix, unsigned long bit) | |||
16 | 17 | ||
17 | bits = radix_tree_lookup(radix, slot); | 18 | bits = radix_tree_lookup(radix, slot); |
18 | if (!bits) { | 19 | if (!bits) { |
19 | bits = kmalloc(BIT_ARRAY_BYTES, GFP_NOFS); | 20 | bits = kmem_cache_alloc(btrfs_bit_radix_cachep, GFP_NOFS); |
20 | if (!bits) | 21 | if (!bits) |
21 | return -ENOMEM; | 22 | return -ENOMEM; |
22 | memset(bits + 1, 0, BIT_ARRAY_BYTES - sizeof(unsigned long)); | 23 | memset(bits + 1, 0, BIT_ARRAY_BYTES - sizeof(unsigned long)); |
@@ -68,12 +69,10 @@ int clear_radix_bit(struct radix_tree_root *radix, unsigned long bit) | |||
68 | break; | 69 | break; |
69 | } | 70 | } |
70 | } | 71 | } |
71 | |||
72 | if (empty) { | 72 | if (empty) { |
73 | bits = radix_tree_delete(radix, slot); | 73 | bits = radix_tree_delete(radix, slot); |
74 | synchronize_rcu(); | ||
75 | BUG_ON(!bits); | 74 | BUG_ON(!bits); |
76 | kfree(bits); | 75 | kmem_cache_free(btrfs_bit_radix_cachep, bits); |
77 | } | 76 | } |
78 | #endif | 77 | #endif |
79 | return 0; | 78 | return 0; |
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h new file mode 100644 index 000000000000..e159841650a4 --- /dev/null +++ b/fs/btrfs/btrfs_inode.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef __BTRFS_I__ | ||
2 | #define __BTRFS_I__ | ||
3 | |||
4 | struct btrfs_inode { | ||
5 | u32 magic; | ||
6 | struct inode vfs_inode; | ||
7 | u32 magic2; | ||
8 | }; | ||
9 | static inline struct btrfs_inode *BTRFS_I(struct inode *inode) | ||
10 | { | ||
11 | return container_of(inode, struct btrfs_inode, vfs_inode); | ||
12 | } | ||
13 | |||
14 | #endif | ||
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index a0dfa2d6cb9b..453ce835209a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -16,6 +16,16 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct | |||
16 | static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 16 | static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
17 | struct btrfs_path *path, int level, int slot); | 17 | struct btrfs_path *path, int level, int slot); |
18 | 18 | ||
19 | struct btrfs_path *btrfs_alloc_path(void) | ||
20 | { | ||
21 | return kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS); | ||
22 | } | ||
23 | |||
24 | void btrfs_free_path(struct btrfs_path *p) | ||
25 | { | ||
26 | kmem_cache_free(btrfs_path_cachep, p); | ||
27 | } | ||
28 | |||
19 | inline void btrfs_init_path(struct btrfs_path *p) | 29 | inline void btrfs_init_path(struct btrfs_path *p) |
20 | { | 30 | { |
21 | memset(p, 0, sizeof(*p)); | 31 | memset(p, 0, sizeof(*p)); |
@@ -47,17 +57,18 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
47 | } | 57 | } |
48 | cow = btrfs_alloc_free_block(trans, root); | 58 | cow = btrfs_alloc_free_block(trans, root); |
49 | cow_node = btrfs_buffer_node(cow); | 59 | cow_node = btrfs_buffer_node(cow); |
60 | if (buf->b_size != root->blocksize || cow->b_size != root->blocksize) | ||
61 | WARN_ON(1); | ||
50 | memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize); | 62 | memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize); |
51 | btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr); | 63 | btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr); |
52 | btrfs_set_header_generation(&cow_node->header, trans->transid); | 64 | btrfs_set_header_generation(&cow_node->header, trans->transid); |
53 | *cow_ret = cow; | ||
54 | btrfs_mark_buffer_dirty(cow); | ||
55 | btrfs_inc_ref(trans, root, buf); | 65 | btrfs_inc_ref(trans, root, buf); |
56 | if (buf == root->node) { | 66 | if (buf == root->node) { |
57 | root->node = cow; | 67 | root->node = cow; |
58 | get_bh(cow); | 68 | get_bh(cow); |
59 | if (buf != root->commit_root) | 69 | if (buf != root->commit_root) { |
60 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); | 70 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); |
71 | } | ||
61 | btrfs_block_release(root, buf); | 72 | btrfs_block_release(root, buf); |
62 | } else { | 73 | } else { |
63 | btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot, | 74 | btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot, |
@@ -66,6 +77,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
66 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); | 77 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); |
67 | } | 78 | } |
68 | btrfs_block_release(root, buf); | 79 | btrfs_block_release(root, buf); |
80 | *cow_ret = cow; | ||
69 | return 0; | 81 | return 0; |
70 | } | 82 | } |
71 | 83 | ||
@@ -477,9 +489,12 @@ again: | |||
477 | p->slots[level + 1], | 489 | p->slots[level + 1], |
478 | &cow_buf); | 490 | &cow_buf); |
479 | b = cow_buf; | 491 | b = cow_buf; |
492 | c = btrfs_buffer_node(b); | ||
480 | } | 493 | } |
481 | BUG_ON(!cow && ins_len); | 494 | BUG_ON(!cow && ins_len); |
482 | c = btrfs_buffer_node(b); | 495 | if (level != btrfs_header_level(&c->header)) |
496 | WARN_ON(1); | ||
497 | level = btrfs_header_level(&c->header); | ||
483 | p->nodes[level] = b; | 498 | p->nodes[level] = b; |
484 | ret = check_block(root, p, level); | 499 | ret = check_block(root, p, level); |
485 | if (ret) | 500 | if (ret) |
@@ -1257,19 +1272,22 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1257 | data_size) | 1272 | data_size) |
1258 | { | 1273 | { |
1259 | int ret = 0; | 1274 | int ret = 0; |
1260 | struct btrfs_path path; | 1275 | struct btrfs_path *path; |
1261 | u8 *ptr; | 1276 | u8 *ptr; |
1262 | 1277 | ||
1263 | btrfs_init_path(&path); | 1278 | path = btrfs_alloc_path(); |
1264 | ret = btrfs_insert_empty_item(trans, root, &path, cpu_key, data_size); | 1279 | BUG_ON(!path); |
1280 | btrfs_init_path(path); | ||
1281 | ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); | ||
1265 | if (!ret) { | 1282 | if (!ret) { |
1266 | ptr = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), | 1283 | ptr = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), |
1267 | path.slots[0], u8); | 1284 | path->slots[0], u8); |
1268 | btrfs_memcpy(root, path.nodes[0]->b_data, | 1285 | btrfs_memcpy(root, path->nodes[0]->b_data, |
1269 | ptr, data, data_size); | 1286 | ptr, data, data_size); |
1270 | btrfs_mark_buffer_dirty(path.nodes[0]); | 1287 | btrfs_mark_buffer_dirty(path->nodes[0]); |
1271 | } | 1288 | } |
1272 | btrfs_release_path(root, &path); | 1289 | btrfs_release_path(root, path); |
1290 | btrfs_free_path(path); | ||
1273 | return ret; | 1291 | return ret; |
1274 | } | 1292 | } |
1275 | 1293 | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 9ec0d65ebe9b..d8e03bd797ff 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -7,6 +7,7 @@ | |||
7 | 7 | ||
8 | struct btrfs_trans_handle; | 8 | struct btrfs_trans_handle; |
9 | struct btrfs_transaction; | 9 | struct btrfs_transaction; |
10 | extern struct kmem_cache *btrfs_path_cachep; | ||
10 | 11 | ||
11 | #define BTRFS_MAGIC "_BtRfS_M" | 12 | #define BTRFS_MAGIC "_BtRfS_M" |
12 | 13 | ||
@@ -888,6 +889,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
888 | *root, struct btrfs_key *key, struct btrfs_path *p, int | 889 | *root, struct btrfs_key *key, struct btrfs_path *p, int |
889 | ins_len, int cow); | 890 | ins_len, int cow); |
890 | void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p); | 891 | void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p); |
892 | struct btrfs_path *btrfs_alloc_path(void); | ||
893 | void btrfs_free_path(struct btrfs_path *p); | ||
891 | void btrfs_init_path(struct btrfs_path *p); | 894 | void btrfs_init_path(struct btrfs_path *p); |
892 | int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 895 | int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
893 | struct btrfs_path *path); | 896 | struct btrfs_path *path); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index bb133104e2e9..2dbd55084a4e 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -8,18 +8,6 @@ | |||
8 | #include "disk-io.h" | 8 | #include "disk-io.h" |
9 | #include "transaction.h" | 9 | #include "transaction.h" |
10 | 10 | ||
11 | #define PATTERN 0xDEADBEEFUL | ||
12 | static inline void check_pattern(struct buffer_head *buf) | ||
13 | { | ||
14 | if (buf->b_private != (void *)PATTERN) | ||
15 | WARN_ON(1); | ||
16 | } | ||
17 | |||
18 | static inline void set_pattern(struct buffer_head *buf) | ||
19 | { | ||
20 | buf->b_private = (void *)PATTERN; | ||
21 | } | ||
22 | |||
23 | static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) | 11 | static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) |
24 | { | 12 | { |
25 | struct btrfs_node *node = btrfs_buffer_node(buf); | 13 | struct btrfs_node *node = btrfs_buffer_node(buf); |
@@ -35,6 +23,8 @@ static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) | |||
35 | 23 | ||
36 | struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) | 24 | struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) |
37 | { | 25 | { |
26 | return sb_find_get_block(root->fs_info->sb, blocknr); | ||
27 | #if 0 | ||
38 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; | 28 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; |
39 | int blockbits = root->fs_info->sb->s_blocksize_bits; | 29 | int blockbits = root->fs_info->sb->s_blocksize_bits; |
40 | unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); | 30 | unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); |
@@ -43,6 +33,7 @@ struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) | |||
43 | struct buffer_head *head; | 33 | struct buffer_head *head; |
44 | struct buffer_head *ret = NULL; | 34 | struct buffer_head *ret = NULL; |
45 | 35 | ||
36 | |||
46 | page = find_lock_page(mapping, index); | 37 | page = find_lock_page(mapping, index); |
47 | if (!page) | 38 | if (!page) |
48 | return NULL; | 39 | return NULL; |
@@ -64,15 +55,17 @@ out_unlock: | |||
64 | unlock_page(page); | 55 | unlock_page(page); |
65 | if (ret) { | 56 | if (ret) { |
66 | touch_buffer(ret); | 57 | touch_buffer(ret); |
67 | check_pattern(ret); | ||
68 | } | 58 | } |
69 | page_cache_release(page); | 59 | page_cache_release(page); |
70 | return ret; | 60 | return ret; |
61 | #endif | ||
71 | } | 62 | } |
72 | 63 | ||
73 | struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, | 64 | struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, |
74 | u64 blocknr) | 65 | u64 blocknr) |
75 | { | 66 | { |
67 | return sb_getblk(root->fs_info->sb, blocknr); | ||
68 | #if 0 | ||
76 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; | 69 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; |
77 | int blockbits = root->fs_info->sb->s_blocksize_bits; | 70 | int blockbits = root->fs_info->sb->s_blocksize_bits; |
78 | unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); | 71 | unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); |
@@ -95,7 +88,6 @@ struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, | |||
95 | bh->b_bdev = root->fs_info->sb->s_bdev; | 88 | bh->b_bdev = root->fs_info->sb->s_bdev; |
96 | bh->b_blocknr = first_block; | 89 | bh->b_blocknr = first_block; |
97 | set_buffer_mapped(bh); | 90 | set_buffer_mapped(bh); |
98 | set_pattern(bh); | ||
99 | } | 91 | } |
100 | if (bh->b_blocknr == blocknr) { | 92 | if (bh->b_blocknr == blocknr) { |
101 | ret = bh; | 93 | ret = bh; |
@@ -111,6 +103,7 @@ out_unlock: | |||
111 | touch_buffer(ret); | 103 | touch_buffer(ret); |
112 | page_cache_release(page); | 104 | page_cache_release(page); |
113 | return ret; | 105 | return ret; |
106 | #endif | ||
114 | } | 107 | } |
115 | 108 | ||
116 | static sector_t max_block(struct block_device *bdev) | 109 | static sector_t max_block(struct block_device *bdev) |
@@ -225,6 +218,8 @@ static struct address_space_operations btree_aops = { | |||
225 | 218 | ||
226 | struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) | 219 | struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) |
227 | { | 220 | { |
221 | return sb_bread(root->fs_info->sb, blocknr); | ||
222 | #if 0 | ||
228 | struct buffer_head *bh = NULL; | 223 | struct buffer_head *bh = NULL; |
229 | 224 | ||
230 | bh = btrfs_find_create_tree_block(root, blocknr); | 225 | bh = btrfs_find_create_tree_block(root, blocknr); |
@@ -239,7 +234,6 @@ struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) | |||
239 | if (!buffer_uptodate(bh)) | 234 | if (!buffer_uptodate(bh)) |
240 | goto fail; | 235 | goto fail; |
241 | csum_tree_block(root, bh, 1); | 236 | csum_tree_block(root, bh, 1); |
242 | set_pattern(bh); | ||
243 | } else { | 237 | } else { |
244 | unlock_buffer(bh); | 238 | unlock_buffer(bh); |
245 | } | 239 | } |
@@ -250,6 +244,7 @@ fail: | |||
250 | brelse(bh); | 244 | brelse(bh); |
251 | return NULL; | 245 | return NULL; |
252 | 246 | ||
247 | #endif | ||
253 | } | 248 | } |
254 | 249 | ||
255 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 250 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
@@ -268,14 +263,14 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
268 | return 0; | 263 | return 0; |
269 | } | 264 | } |
270 | 265 | ||
271 | static int __setup_root(struct btrfs_super_block *super, | 266 | static int __setup_root(int blocksize, |
272 | struct btrfs_root *root, | 267 | struct btrfs_root *root, |
273 | struct btrfs_fs_info *fs_info, | 268 | struct btrfs_fs_info *fs_info, |
274 | u64 objectid) | 269 | u64 objectid) |
275 | { | 270 | { |
276 | root->node = NULL; | 271 | root->node = NULL; |
277 | root->commit_root = NULL; | 272 | root->commit_root = NULL; |
278 | root->blocksize = btrfs_super_blocksize(super); | 273 | root->blocksize = blocksize; |
279 | root->ref_cows = 0; | 274 | root->ref_cows = 0; |
280 | root->fs_info = fs_info; | 275 | root->fs_info = fs_info; |
281 | memset(&root->root_key, 0, sizeof(root->root_key)); | 276 | memset(&root->root_key, 0, sizeof(root->root_key)); |
@@ -283,7 +278,7 @@ static int __setup_root(struct btrfs_super_block *super, | |||
283 | return 0; | 278 | return 0; |
284 | } | 279 | } |
285 | 280 | ||
286 | static int find_and_setup_root(struct btrfs_super_block *super, | 281 | static int find_and_setup_root(int blocksize, |
287 | struct btrfs_root *tree_root, | 282 | struct btrfs_root *tree_root, |
288 | struct btrfs_fs_info *fs_info, | 283 | struct btrfs_fs_info *fs_info, |
289 | u64 objectid, | 284 | u64 objectid, |
@@ -291,7 +286,7 @@ static int find_and_setup_root(struct btrfs_super_block *super, | |||
291 | { | 286 | { |
292 | int ret; | 287 | int ret; |
293 | 288 | ||
294 | __setup_root(super, root, fs_info, objectid); | 289 | __setup_root(blocksize, root, fs_info, objectid); |
295 | ret = btrfs_find_last_root(tree_root, objectid, | 290 | ret = btrfs_find_last_root(tree_root, objectid, |
296 | &root->root_item, &root->root_key); | 291 | &root->root_item, &root->root_key); |
297 | BUG_ON(ret); | 292 | BUG_ON(ret); |
@@ -302,9 +297,7 @@ static int find_and_setup_root(struct btrfs_super_block *super, | |||
302 | return 0; | 297 | return 0; |
303 | } | 298 | } |
304 | 299 | ||
305 | struct btrfs_root *open_ctree(struct super_block *sb, | 300 | struct btrfs_root *open_ctree(struct super_block *sb) |
306 | struct buffer_head *sb_buffer, | ||
307 | struct btrfs_super_block *disk_super) | ||
308 | { | 301 | { |
309 | struct btrfs_root *root = kmalloc(sizeof(struct btrfs_root), | 302 | struct btrfs_root *root = kmalloc(sizeof(struct btrfs_root), |
310 | GFP_NOFS); | 303 | GFP_NOFS); |
@@ -317,13 +310,11 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
317 | struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), | 310 | struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), |
318 | GFP_NOFS); | 311 | GFP_NOFS); |
319 | int ret; | 312 | int ret; |
313 | struct btrfs_super_block *disk_super; | ||
320 | 314 | ||
321 | if (!btrfs_super_root(disk_super)) { | ||
322 | return NULL; | ||
323 | } | ||
324 | init_bit_radix(&fs_info->pinned_radix); | 315 | init_bit_radix(&fs_info->pinned_radix); |
325 | init_bit_radix(&fs_info->pending_del_radix); | 316 | init_bit_radix(&fs_info->pending_del_radix); |
326 | sb_set_blocksize(sb, sb_buffer->b_size); | 317 | sb_set_blocksize(sb, 4096); |
327 | fs_info->running_transaction = NULL; | 318 | fs_info->running_transaction = NULL; |
328 | fs_info->fs_root = root; | 319 | fs_info->fs_root = root; |
329 | fs_info->tree_root = tree_root; | 320 | fs_info->tree_root = tree_root; |
@@ -331,55 +322,59 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
331 | fs_info->inode_root = inode_root; | 322 | fs_info->inode_root = inode_root; |
332 | fs_info->last_inode_alloc = 0; | 323 | fs_info->last_inode_alloc = 0; |
333 | fs_info->last_inode_alloc_dirid = 0; | 324 | fs_info->last_inode_alloc_dirid = 0; |
334 | fs_info->disk_super = disk_super; | ||
335 | fs_info->sb = sb; | 325 | fs_info->sb = sb; |
326 | fs_info->btree_inode = NULL; | ||
327 | #if 0 | ||
336 | fs_info->btree_inode = new_inode(sb); | 328 | fs_info->btree_inode = new_inode(sb); |
337 | fs_info->btree_inode->i_ino = 1; | 329 | fs_info->btree_inode->i_ino = 1; |
330 | fs_info->btree_inode->i_nlink = 1; | ||
338 | fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; | 331 | fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; |
339 | fs_info->btree_inode->i_mapping->a_ops = &btree_aops; | 332 | fs_info->btree_inode->i_mapping->a_ops = &btree_aops; |
340 | insert_inode_hash(fs_info->btree_inode); | 333 | insert_inode_hash(fs_info->btree_inode); |
341 | |||
342 | mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); | 334 | mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); |
335 | #endif | ||
343 | fs_info->hash_tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); | 336 | fs_info->hash_tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); |
344 | spin_lock_init(&fs_info->hash_lock); | 337 | spin_lock_init(&fs_info->hash_lock); |
345 | |||
346 | if (!fs_info->hash_tfm || IS_ERR(fs_info->hash_tfm)) { | 338 | if (!fs_info->hash_tfm || IS_ERR(fs_info->hash_tfm)) { |
347 | printk("failed to allocate sha256 hash\n"); | 339 | printk("failed to allocate sha256 hash\n"); |
348 | return NULL; | 340 | return NULL; |
349 | } | 341 | } |
350 | |||
351 | mutex_init(&fs_info->trans_mutex); | 342 | mutex_init(&fs_info->trans_mutex); |
352 | mutex_init(&fs_info->fs_mutex); | 343 | mutex_init(&fs_info->fs_mutex); |
353 | memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert)); | 344 | memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert)); |
354 | memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); | 345 | memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); |
355 | 346 | ||
356 | __setup_root(disk_super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID); | 347 | __setup_root(sb->s_blocksize, tree_root, |
357 | 348 | fs_info, BTRFS_ROOT_TREE_OBJECTID); | |
358 | fs_info->sb_buffer = read_tree_block(tree_root, sb_buffer->b_blocknr); | 349 | fs_info->sb_buffer = read_tree_block(tree_root, |
350 | BTRFS_SUPER_INFO_OFFSET / | ||
351 | sb->s_blocksize); | ||
359 | 352 | ||
360 | if (!fs_info->sb_buffer) { | 353 | if (!fs_info->sb_buffer) { |
361 | printk("failed2\n"); | 354 | printk("failed2\n"); |
362 | return NULL; | 355 | return NULL; |
363 | } | 356 | } |
364 | brelse(sb_buffer); | ||
365 | sb_buffer = NULL; | ||
366 | disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data; | 357 | disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data; |
358 | if (!btrfs_super_root(disk_super)) { | ||
359 | return NULL; | ||
360 | } | ||
367 | fs_info->disk_super = disk_super; | 361 | fs_info->disk_super = disk_super; |
368 | |||
369 | tree_root->node = read_tree_block(tree_root, | 362 | tree_root->node = read_tree_block(tree_root, |
370 | btrfs_super_root(disk_super)); | 363 | btrfs_super_root(disk_super)); |
371 | BUG_ON(!tree_root->node); | 364 | BUG_ON(!tree_root->node); |
372 | 365 | ||
373 | ret = find_and_setup_root(disk_super, tree_root, fs_info, | 366 | mutex_lock(&fs_info->fs_mutex); |
367 | ret = find_and_setup_root(sb->s_blocksize, tree_root, fs_info, | ||
374 | BTRFS_EXTENT_TREE_OBJECTID, extent_root); | 368 | BTRFS_EXTENT_TREE_OBJECTID, extent_root); |
375 | BUG_ON(ret); | 369 | BUG_ON(ret); |
376 | 370 | ||
377 | ret = find_and_setup_root(disk_super, tree_root, fs_info, | 371 | ret = find_and_setup_root(sb->s_blocksize, tree_root, fs_info, |
378 | BTRFS_INODE_MAP_OBJECTID, inode_root); | 372 | BTRFS_INODE_MAP_OBJECTID, inode_root); |
379 | BUG_ON(ret); | 373 | BUG_ON(ret); |
380 | 374 | ||
381 | ret = find_and_setup_root(disk_super, tree_root, fs_info, | 375 | ret = find_and_setup_root(sb->s_blocksize, tree_root, fs_info, |
382 | BTRFS_FS_TREE_OBJECTID, root); | 376 | BTRFS_FS_TREE_OBJECTID, root); |
377 | mutex_unlock(&fs_info->fs_mutex); | ||
383 | BUG_ON(ret); | 378 | BUG_ON(ret); |
384 | root->commit_root = root->node; | 379 | root->commit_root = root->node; |
385 | get_bh(root->node); | 380 | get_bh(root->node); |
@@ -392,9 +387,11 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | |||
392 | *root) | 387 | *root) |
393 | { | 388 | { |
394 | struct buffer_head *bh = root->fs_info->sb_buffer; | 389 | struct buffer_head *bh = root->fs_info->sb_buffer; |
390 | |||
395 | btrfs_set_super_root(root->fs_info->disk_super, | 391 | btrfs_set_super_root(root->fs_info->disk_super, |
396 | root->fs_info->tree_root->node->b_blocknr); | 392 | root->fs_info->tree_root->node->b_blocknr); |
397 | lock_buffer(bh); | 393 | lock_buffer(bh); |
394 | WARN_ON(atomic_read(&bh->b_count) < 1); | ||
398 | clear_buffer_dirty(bh); | 395 | clear_buffer_dirty(bh); |
399 | csum_tree_block(root, bh, 0); | 396 | csum_tree_block(root, bh, 0); |
400 | bh->b_end_io = end_buffer_write_sync; | 397 | bh->b_end_io = end_buffer_write_sync; |
@@ -413,6 +410,7 @@ int close_ctree(struct btrfs_root *root) | |||
413 | int ret; | 410 | int ret; |
414 | struct btrfs_trans_handle *trans; | 411 | struct btrfs_trans_handle *trans; |
415 | 412 | ||
413 | mutex_lock(&root->fs_info->fs_mutex); | ||
416 | trans = btrfs_start_transaction(root, 1); | 414 | trans = btrfs_start_transaction(root, 1); |
417 | btrfs_commit_transaction(trans, root); | 415 | btrfs_commit_transaction(trans, root); |
418 | /* run commit again to drop the original snapshot */ | 416 | /* run commit again to drop the original snapshot */ |
@@ -421,6 +419,7 @@ int close_ctree(struct btrfs_root *root) | |||
421 | ret = btrfs_write_and_wait_transaction(NULL, root); | 419 | ret = btrfs_write_and_wait_transaction(NULL, root); |
422 | BUG_ON(ret); | 420 | BUG_ON(ret); |
423 | write_ctree_super(NULL, root); | 421 | write_ctree_super(NULL, root); |
422 | mutex_unlock(&root->fs_info->fs_mutex); | ||
424 | 423 | ||
425 | if (root->node) | 424 | if (root->node) |
426 | btrfs_block_release(root, root->node); | 425 | btrfs_block_release(root, root->node); |
@@ -436,8 +435,8 @@ int close_ctree(struct btrfs_root *root) | |||
436 | btrfs_block_release(root, root->commit_root); | 435 | btrfs_block_release(root, root->commit_root); |
437 | btrfs_block_release(root, root->fs_info->sb_buffer); | 436 | btrfs_block_release(root, root->fs_info->sb_buffer); |
438 | crypto_free_hash(root->fs_info->hash_tfm); | 437 | crypto_free_hash(root->fs_info->hash_tfm); |
439 | truncate_inode_pages(root->fs_info->btree_inode->i_mapping, 0); | 438 | // truncate_inode_pages(root->fs_info->btree_inode->i_mapping, 0); |
440 | iput(root->fs_info->btree_inode); | 439 | // iput(root->fs_info->btree_inode); |
441 | kfree(root->fs_info->extent_root); | 440 | kfree(root->fs_info->extent_root); |
442 | kfree(root->fs_info->inode_root); | 441 | kfree(root->fs_info->inode_root); |
443 | kfree(root->fs_info->tree_root); | 442 | kfree(root->fs_info->tree_root); |
@@ -448,7 +447,6 @@ int close_ctree(struct btrfs_root *root) | |||
448 | 447 | ||
449 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf) | 448 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf) |
450 | { | 449 | { |
451 | check_pattern(buf); | 450 | // brelse(buf); |
452 | brelse(buf); | ||
453 | } | 451 | } |
454 | 452 | ||
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index f6998e2192ce..ac6764ba8aa6 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -31,9 +31,7 @@ int clean_tree_block(struct btrfs_trans_handle *trans, | |||
31 | struct btrfs_root *root, struct buffer_head *buf); | 31 | struct btrfs_root *root, struct buffer_head *buf); |
32 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | 32 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, |
33 | struct btrfs_root *root); | 33 | struct btrfs_root *root); |
34 | struct btrfs_root *open_ctree(struct super_block *sb, | 34 | struct btrfs_root *open_ctree(struct super_block *sb); |
35 | struct buffer_head *sb_buffer, | ||
36 | struct btrfs_super_block *disk_super); | ||
37 | int close_ctree(struct btrfs_root *root); | 35 | int close_ctree(struct btrfs_root *root); |
38 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf); | 36 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf); |
39 | int write_ctree_super(struct btrfs_trans_handle *trans, | 37 | int write_ctree_super(struct btrfs_trans_handle *trans, |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c4194dab7a33..37b87e28a2f3 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -173,12 +173,16 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) | |||
173 | 173 | ||
174 | if (!pending) { | 174 | if (!pending) { |
175 | bh = btrfs_find_tree_block(root, blocknr); | 175 | bh = btrfs_find_tree_block(root, blocknr); |
176 | if (bh && buffer_uptodate(bh)) { | 176 | if (bh) { |
177 | header = btrfs_buffer_header(bh); | 177 | if (buffer_uptodate(bh)) { |
178 | if (btrfs_header_generation(header) == | 178 | u64 transid = |
179 | root->fs_info->running_transaction->transid) { | 179 | root->fs_info->running_transaction->transid; |
180 | btrfs_block_release(root, bh); | 180 | header = btrfs_buffer_header(bh); |
181 | return 0; | 181 | if (btrfs_header_generation(header) == |
182 | transid) { | ||
183 | btrfs_block_release(root, bh); | ||
184 | return 0; | ||
185 | } | ||
182 | } | 186 | } |
183 | btrfs_block_release(root, bh); | 187 | btrfs_block_release(root, bh); |
184 | } | 188 | } |
@@ -539,6 +543,8 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
539 | */ | 543 | */ |
540 | while(*level >= 0) { | 544 | while(*level >= 0) { |
541 | cur = path->nodes[*level]; | 545 | cur = path->nodes[*level]; |
546 | if (btrfs_header_level(btrfs_buffer_header(cur)) != *level) | ||
547 | WARN_ON(1); | ||
542 | if (path->slots[*level] >= | 548 | if (path->slots[*level] >= |
543 | btrfs_header_nritems(btrfs_buffer_header(cur))) | 549 | btrfs_header_nritems(btrfs_buffer_header(cur))) |
544 | break; | 550 | break; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 894a70bf26d2..6969b672b570 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include "ctree.h" | 14 | #include "ctree.h" |
15 | #include "disk-io.h" | 15 | #include "disk-io.h" |
16 | #include "transaction.h" | 16 | #include "transaction.h" |
17 | #include "btrfs_inode.h" | ||
17 | 18 | ||
18 | #define BTRFS_SUPER_MAGIC 0x9123682E | 19 | #define BTRFS_SUPER_MAGIC 0x9123682E |
19 | 20 | ||
@@ -24,6 +25,14 @@ static struct inode_operations btrfs_file_inode_operations; | |||
24 | static struct address_space_operations btrfs_aops; | 25 | static struct address_space_operations btrfs_aops; |
25 | static struct file_operations btrfs_file_operations; | 26 | static struct file_operations btrfs_file_operations; |
26 | 27 | ||
28 | static int check_inode(struct inode *inode) | ||
29 | { | ||
30 | struct btrfs_inode *ei = BTRFS_I(inode); | ||
31 | WARN_ON(ei->magic != 0xDEADBEEF); | ||
32 | WARN_ON(ei->magic2 != 0xDEADBEAF); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
27 | static void btrfs_read_locked_inode(struct inode *inode) | 36 | static void btrfs_read_locked_inode(struct inode *inode) |
28 | { | 37 | { |
29 | struct btrfs_path path; | 38 | struct btrfs_path path; |
@@ -34,6 +43,7 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
34 | btrfs_init_path(&path); | 43 | btrfs_init_path(&path); |
35 | mutex_lock(&root->fs_info->fs_mutex); | 44 | mutex_lock(&root->fs_info->fs_mutex); |
36 | 45 | ||
46 | check_inode(inode); | ||
37 | ret = btrfs_lookup_inode(NULL, root, &path, inode->i_ino, 0); | 47 | ret = btrfs_lookup_inode(NULL, root, &path, inode->i_ino, 0); |
38 | if (ret) { | 48 | if (ret) { |
39 | btrfs_release_path(root, &path); | 49 | btrfs_release_path(root, &path); |
@@ -41,6 +51,7 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
41 | make_bad_inode(inode); | 51 | make_bad_inode(inode); |
42 | return; | 52 | return; |
43 | } | 53 | } |
54 | check_inode(inode); | ||
44 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), | 55 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), |
45 | path.slots[0], | 56 | path.slots[0], |
46 | struct btrfs_inode_item); | 57 | struct btrfs_inode_item); |
@@ -60,6 +71,7 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
60 | inode->i_generation = btrfs_inode_generation(inode_item); | 71 | inode->i_generation = btrfs_inode_generation(inode_item); |
61 | btrfs_release_path(root, &path); | 72 | btrfs_release_path(root, &path); |
62 | mutex_unlock(&root->fs_info->fs_mutex); | 73 | mutex_unlock(&root->fs_info->fs_mutex); |
74 | check_inode(inode); | ||
63 | switch (inode->i_mode & S_IFMT) { | 75 | switch (inode->i_mode & S_IFMT) { |
64 | #if 0 | 76 | #if 0 |
65 | default: | 77 | default: |
@@ -80,6 +92,7 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
80 | // inode->i_op = &page_symlink_inode_operations; | 92 | // inode->i_op = &page_symlink_inode_operations; |
81 | break; | 93 | break; |
82 | } | 94 | } |
95 | check_inode(inode); | ||
83 | return; | 96 | return; |
84 | } | 97 | } |
85 | 98 | ||
@@ -347,6 +360,7 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, | |||
347 | namelen, 0); | 360 | namelen, 0); |
348 | if (ret || !btrfs_match_dir_item_name(root, &path, name, namelen)) { | 361 | if (ret || !btrfs_match_dir_item_name(root, &path, name, namelen)) { |
349 | *ino = 0; | 362 | *ino = 0; |
363 | ret = 0; | ||
350 | goto out; | 364 | goto out; |
351 | } | 365 | } |
352 | di = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], | 366 | di = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], |
@@ -354,6 +368,7 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, | |||
354 | *ino = btrfs_dir_objectid(di); | 368 | *ino = btrfs_dir_objectid(di); |
355 | out: | 369 | out: |
356 | btrfs_release_path(root, &path); | 370 | btrfs_release_path(root, &path); |
371 | check_inode(dir); | ||
357 | return ret; | 372 | return ret; |
358 | } | 373 | } |
359 | 374 | ||
@@ -367,7 +382,6 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
367 | 382 | ||
368 | if (dentry->d_name.len > BTRFS_NAME_LEN) | 383 | if (dentry->d_name.len > BTRFS_NAME_LEN) |
369 | return ERR_PTR(-ENAMETOOLONG); | 384 | return ERR_PTR(-ENAMETOOLONG); |
370 | |||
371 | mutex_lock(&root->fs_info->fs_mutex); | 385 | mutex_lock(&root->fs_info->fs_mutex); |
372 | ret = btrfs_inode_by_name(dir, dentry, &ino); | 386 | ret = btrfs_inode_by_name(dir, dentry, &ino); |
373 | mutex_unlock(&root->fs_info->fs_mutex); | 387 | mutex_unlock(&root->fs_info->fs_mutex); |
@@ -378,7 +392,9 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
378 | inode = iget(dir->i_sb, ino); | 392 | inode = iget(dir->i_sb, ino); |
379 | if (!inode) | 393 | if (!inode) |
380 | return ERR_PTR(-EACCES); | 394 | return ERR_PTR(-EACCES); |
395 | check_inode(inode); | ||
381 | } | 396 | } |
397 | check_inode(dir); | ||
382 | return d_splice_alias(inode, dentry); | 398 | return d_splice_alias(inode, dentry); |
383 | } | 399 | } |
384 | 400 | ||
@@ -471,23 +487,14 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent) | |||
471 | struct inode * inode; | 487 | struct inode * inode; |
472 | struct dentry * root_dentry; | 488 | struct dentry * root_dentry; |
473 | struct btrfs_super_block *disk_super; | 489 | struct btrfs_super_block *disk_super; |
474 | struct buffer_head *bh; | ||
475 | struct btrfs_root *root; | 490 | struct btrfs_root *root; |
476 | 491 | ||
477 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 492 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
478 | sb->s_blocksize = PAGE_CACHE_SIZE; | ||
479 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | ||
480 | sb->s_magic = BTRFS_SUPER_MAGIC; | 493 | sb->s_magic = BTRFS_SUPER_MAGIC; |
481 | sb->s_op = &btrfs_super_ops; | 494 | sb->s_op = &btrfs_super_ops; |
482 | sb->s_time_gran = 1; | 495 | sb->s_time_gran = 1; |
483 | 496 | ||
484 | bh = sb_bread(sb, BTRFS_SUPER_INFO_OFFSET / sb->s_blocksize); | 497 | root = open_ctree(sb); |
485 | if (!bh) { | ||
486 | printk("btrfs: unable to read on disk super\n"); | ||
487 | return -EIO; | ||
488 | } | ||
489 | disk_super = (struct btrfs_super_block *)bh->b_data; | ||
490 | root = open_ctree(sb, bh, disk_super); | ||
491 | 498 | ||
492 | if (!root) { | 499 | if (!root) { |
493 | printk("btrfs: open_ctree failed\n"); | 500 | printk("btrfs: open_ctree failed\n"); |
@@ -533,6 +540,7 @@ static void fill_inode_item(struct btrfs_inode_item *item, | |||
533 | btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec); | 540 | btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec); |
534 | btrfs_set_inode_nblocks(item, inode->i_blocks); | 541 | btrfs_set_inode_nblocks(item, inode->i_blocks); |
535 | btrfs_set_inode_generation(item, inode->i_generation); | 542 | btrfs_set_inode_generation(item, inode->i_generation); |
543 | check_inode(inode); | ||
536 | } | 544 | } |
537 | 545 | ||
538 | static int btrfs_update_inode(struct btrfs_trans_handle *trans, | 546 | static int btrfs_update_inode(struct btrfs_trans_handle *trans, |
@@ -560,6 +568,7 @@ static int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
560 | btrfs_mark_buffer_dirty(path.nodes[0]); | 568 | btrfs_mark_buffer_dirty(path.nodes[0]); |
561 | failed: | 569 | failed: |
562 | btrfs_release_path(root, &path); | 570 | btrfs_release_path(root, &path); |
571 | check_inode(inode); | ||
563 | return 0; | 572 | return 0; |
564 | } | 573 | } |
565 | 574 | ||
@@ -577,6 +586,7 @@ static int btrfs_write_inode(struct inode *inode, int wait) | |||
577 | else | 586 | else |
578 | btrfs_end_transaction(trans, root); | 587 | btrfs_end_transaction(trans, root); |
579 | mutex_unlock(&root->fs_info->fs_mutex); | 588 | mutex_unlock(&root->fs_info->fs_mutex); |
589 | check_inode(inode); | ||
580 | return ret; | 590 | return ret; |
581 | } | 591 | } |
582 | 592 | ||
@@ -594,6 +604,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
594 | if (!inode) | 604 | if (!inode) |
595 | return ERR_PTR(-ENOMEM); | 605 | return ERR_PTR(-ENOMEM); |
596 | 606 | ||
607 | check_inode(inode); | ||
597 | ret = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid); | 608 | ret = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid); |
598 | BUG_ON(ret); | 609 | BUG_ON(ret); |
599 | 610 | ||
@@ -616,6 +627,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
616 | BUG_ON(ret); | 627 | BUG_ON(ret); |
617 | 628 | ||
618 | insert_inode_hash(inode); | 629 | insert_inode_hash(inode); |
630 | check_inode(inode); | ||
631 | check_inode(dir); | ||
619 | return inode; | 632 | return inode; |
620 | } | 633 | } |
621 | 634 | ||
@@ -632,7 +645,8 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
632 | ret = btrfs_update_inode(trans, btrfs_sb(inode->i_sb), | 645 | ret = btrfs_update_inode(trans, btrfs_sb(inode->i_sb), |
633 | dentry->d_parent->d_inode); | 646 | dentry->d_parent->d_inode); |
634 | } | 647 | } |
635 | 648 | check_inode(inode); | |
649 | check_inode(dentry->d_parent->d_inode); | ||
636 | return ret; | 650 | return ret; |
637 | } | 651 | } |
638 | 652 | ||
@@ -644,6 +658,9 @@ static int btrfs_add_nondir(struct btrfs_trans_handle *trans, | |||
644 | d_instantiate(dentry, inode); | 658 | d_instantiate(dentry, inode); |
645 | return 0; | 659 | return 0; |
646 | } | 660 | } |
661 | if (err > 0) | ||
662 | err = -EEXIST; | ||
663 | check_inode(inode); | ||
647 | return err; | 664 | return err; |
648 | } | 665 | } |
649 | 666 | ||
@@ -675,6 +692,9 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
675 | out_unlock: | 692 | out_unlock: |
676 | btrfs_end_transaction(trans, root); | 693 | btrfs_end_transaction(trans, root); |
677 | mutex_unlock(&root->fs_info->fs_mutex); | 694 | mutex_unlock(&root->fs_info->fs_mutex); |
695 | check_inode(inode); | ||
696 | check_inode(dir); | ||
697 | |||
678 | if (drop_inode) { | 698 | if (drop_inode) { |
679 | inode_dec_link_count(inode); | 699 | inode_dec_link_count(inode); |
680 | iput(inode); | 700 | iput(inode); |
@@ -755,11 +775,11 @@ static int btrfs_sync_fs(struct super_block *sb, int wait) | |||
755 | 775 | ||
756 | sb->s_dirt = 0; | 776 | sb->s_dirt = 0; |
757 | if (!wait) { | 777 | if (!wait) { |
758 | filemap_flush(root->fs_info->btree_inode->i_mapping); | 778 | // filemap_flush(root->fs_info->btree_inode->i_mapping); |
779 | filemap_flush(root->fs_info->sb->s_bdev->bd_inode->i_mapping); | ||
759 | return 0; | 780 | return 0; |
760 | } | 781 | } |
761 | filemap_write_and_wait(root->fs_info->btree_inode->i_mapping); | 782 | filemap_write_and_wait(root->fs_info->sb->s_bdev->bd_inode->i_mapping); |
762 | |||
763 | mutex_lock(&root->fs_info->fs_mutex); | 783 | mutex_lock(&root->fs_info->fs_mutex); |
764 | trans = btrfs_start_transaction(root, 1); | 784 | trans = btrfs_start_transaction(root, 1); |
765 | ret = btrfs_commit_transaction(trans, root); | 785 | ret = btrfs_commit_transaction(trans, root); |
@@ -1242,6 +1262,95 @@ static ssize_t btrfs_file_aio_read(struct kiocb *iocb, const struct iovec *iov, | |||
1242 | return retval; | 1262 | return retval; |
1243 | } | 1263 | } |
1244 | 1264 | ||
1265 | static struct kmem_cache *btrfs_inode_cachep; | ||
1266 | struct kmem_cache *btrfs_trans_handle_cachep; | ||
1267 | struct kmem_cache *btrfs_transaction_cachep; | ||
1268 | struct kmem_cache *btrfs_bit_radix_cachep; | ||
1269 | struct kmem_cache *btrfs_path_cachep; | ||
1270 | |||
1271 | /* | ||
1272 | * Called inside transaction, so use GFP_NOFS | ||
1273 | */ | ||
1274 | static struct inode *btrfs_alloc_inode(struct super_block *sb) | ||
1275 | { | ||
1276 | struct btrfs_inode *ei; | ||
1277 | |||
1278 | ei = kmem_cache_alloc(btrfs_inode_cachep, GFP_NOFS); | ||
1279 | if (!ei) | ||
1280 | return NULL; | ||
1281 | ei->magic = 0xDEADBEEF; | ||
1282 | ei->magic2 = 0xDEADBEAF; | ||
1283 | return &ei->vfs_inode; | ||
1284 | } | ||
1285 | |||
1286 | static void btrfs_destroy_inode(struct inode *inode) | ||
1287 | { | ||
1288 | struct btrfs_inode *ei = BTRFS_I(inode); | ||
1289 | WARN_ON(ei->magic != 0xDEADBEEF); | ||
1290 | WARN_ON(ei->magic2 != 0xDEADBEAF); | ||
1291 | WARN_ON(!list_empty(&inode->i_dentry)); | ||
1292 | WARN_ON(inode->i_ino == 1); | ||
1293 | WARN_ON(inode->i_data.nrpages); | ||
1294 | |||
1295 | ei->magic = 0; | ||
1296 | ei->magic2 = 0; | ||
1297 | kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode)); | ||
1298 | } | ||
1299 | |||
1300 | static void init_once(void * foo, struct kmem_cache * cachep, | ||
1301 | unsigned long flags) | ||
1302 | { | ||
1303 | struct btrfs_inode *ei = (struct btrfs_inode *) foo; | ||
1304 | |||
1305 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | ||
1306 | SLAB_CTOR_CONSTRUCTOR) { | ||
1307 | inode_init_once(&ei->vfs_inode); | ||
1308 | } | ||
1309 | } | ||
1310 | |||
1311 | static int init_inodecache(void) | ||
1312 | { | ||
1313 | btrfs_inode_cachep = kmem_cache_create("btrfs_inode_cache", | ||
1314 | sizeof(struct btrfs_inode), | ||
1315 | 0, (SLAB_RECLAIM_ACCOUNT| | ||
1316 | SLAB_MEM_SPREAD), | ||
1317 | init_once, NULL); | ||
1318 | btrfs_trans_handle_cachep = kmem_cache_create("btrfs_trans_handle_cache", | ||
1319 | sizeof(struct btrfs_trans_handle), | ||
1320 | 0, (SLAB_RECLAIM_ACCOUNT| | ||
1321 | SLAB_MEM_SPREAD), | ||
1322 | NULL, NULL); | ||
1323 | btrfs_transaction_cachep = kmem_cache_create("btrfs_transaction_cache", | ||
1324 | sizeof(struct btrfs_transaction), | ||
1325 | 0, (SLAB_RECLAIM_ACCOUNT| | ||
1326 | SLAB_MEM_SPREAD), | ||
1327 | NULL, NULL); | ||
1328 | btrfs_path_cachep = kmem_cache_create("btrfs_path_cache", | ||
1329 | sizeof(struct btrfs_transaction), | ||
1330 | 0, (SLAB_RECLAIM_ACCOUNT| | ||
1331 | SLAB_MEM_SPREAD), | ||
1332 | NULL, NULL); | ||
1333 | btrfs_bit_radix_cachep = kmem_cache_create("btrfs_radix", | ||
1334 | 256, | ||
1335 | 0, (SLAB_RECLAIM_ACCOUNT| | ||
1336 | SLAB_MEM_SPREAD | | ||
1337 | SLAB_DESTROY_BY_RCU), | ||
1338 | NULL, NULL); | ||
1339 | if (btrfs_inode_cachep == NULL || btrfs_trans_handle_cachep == NULL || | ||
1340 | btrfs_transaction_cachep == NULL || btrfs_bit_radix_cachep == NULL) | ||
1341 | return -ENOMEM; | ||
1342 | return 0; | ||
1343 | } | ||
1344 | |||
1345 | static void destroy_inodecache(void) | ||
1346 | { | ||
1347 | kmem_cache_destroy(btrfs_inode_cachep); | ||
1348 | kmem_cache_destroy(btrfs_trans_handle_cachep); | ||
1349 | kmem_cache_destroy(btrfs_transaction_cachep); | ||
1350 | kmem_cache_destroy(btrfs_bit_radix_cachep); | ||
1351 | kmem_cache_destroy(btrfs_path_cachep); | ||
1352 | } | ||
1353 | |||
1245 | static int btrfs_get_sb(struct file_system_type *fs_type, | 1354 | static int btrfs_get_sb(struct file_system_type *fs_type, |
1246 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 1355 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
1247 | { | 1356 | { |
@@ -1265,6 +1374,8 @@ static struct super_operations btrfs_super_ops = { | |||
1265 | .write_super = btrfs_write_super, | 1374 | .write_super = btrfs_write_super, |
1266 | .sync_fs = btrfs_sync_fs, | 1375 | .sync_fs = btrfs_sync_fs, |
1267 | .write_inode = btrfs_write_inode, | 1376 | .write_inode = btrfs_write_inode, |
1377 | .alloc_inode = btrfs_alloc_inode, | ||
1378 | .destroy_inode = btrfs_destroy_inode, | ||
1268 | }; | 1379 | }; |
1269 | 1380 | ||
1270 | static struct inode_operations btrfs_dir_inode_operations = { | 1381 | static struct inode_operations btrfs_dir_inode_operations = { |
@@ -1305,12 +1416,17 @@ static struct file_operations btrfs_file_operations = { | |||
1305 | 1416 | ||
1306 | static int __init init_btrfs_fs(void) | 1417 | static int __init init_btrfs_fs(void) |
1307 | { | 1418 | { |
1419 | int err; | ||
1308 | printk("btrfs loaded!\n"); | 1420 | printk("btrfs loaded!\n"); |
1421 | err = init_inodecache(); | ||
1422 | if (err) | ||
1423 | return err; | ||
1309 | return register_filesystem(&btrfs_fs_type); | 1424 | return register_filesystem(&btrfs_fs_type); |
1310 | } | 1425 | } |
1311 | 1426 | ||
1312 | static void __exit exit_btrfs_fs(void) | 1427 | static void __exit exit_btrfs_fs(void) |
1313 | { | 1428 | { |
1429 | destroy_inodecache(); | ||
1314 | unregister_filesystem(&btrfs_fs_type); | 1430 | unregister_filesystem(&btrfs_fs_type); |
1315 | printk("btrfs unloaded\n"); | 1431 | printk("btrfs unloaded\n"); |
1316 | } | 1432 | } |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 84c4e278ce2e..72b52e1e0b1b 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -5,13 +5,20 @@ | |||
5 | #include "transaction.h" | 5 | #include "transaction.h" |
6 | 6 | ||
7 | static int total_trans = 0; | 7 | static int total_trans = 0; |
8 | extern struct kmem_cache *btrfs_trans_handle_cachep; | ||
9 | extern struct kmem_cache *btrfs_transaction_cachep; | ||
10 | |||
11 | #define TRANS_MAGIC 0xE1E10E | ||
8 | static void put_transaction(struct btrfs_transaction *transaction) | 12 | static void put_transaction(struct btrfs_transaction *transaction) |
9 | { | 13 | { |
14 | WARN_ON(transaction->use_count == 0); | ||
10 | transaction->use_count--; | 15 | transaction->use_count--; |
16 | WARN_ON(transaction->magic != TRANS_MAGIC); | ||
11 | if (transaction->use_count == 0) { | 17 | if (transaction->use_count == 0) { |
12 | WARN_ON(total_trans == 0); | 18 | WARN_ON(total_trans == 0); |
13 | total_trans--; | 19 | total_trans--; |
14 | kfree(transaction); | 20 | memset(transaction, 0, sizeof(*transaction)); |
21 | kmem_cache_free(btrfs_transaction_cachep, transaction); | ||
15 | } | 22 | } |
16 | } | 23 | } |
17 | 24 | ||
@@ -20,7 +27,8 @@ static int join_transaction(struct btrfs_root *root) | |||
20 | struct btrfs_transaction *cur_trans; | 27 | struct btrfs_transaction *cur_trans; |
21 | cur_trans = root->fs_info->running_transaction; | 28 | cur_trans = root->fs_info->running_transaction; |
22 | if (!cur_trans) { | 29 | if (!cur_trans) { |
23 | cur_trans = kmalloc(sizeof(*cur_trans), GFP_NOFS); | 30 | cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, |
31 | GFP_NOFS); | ||
24 | total_trans++; | 32 | total_trans++; |
25 | BUG_ON(!cur_trans); | 33 | BUG_ON(!cur_trans); |
26 | root->fs_info->running_transaction = cur_trans; | 34 | root->fs_info->running_transaction = cur_trans; |
@@ -28,6 +36,7 @@ static int join_transaction(struct btrfs_root *root) | |||
28 | cur_trans->transid = root->root_key.offset + 1; | 36 | cur_trans->transid = root->root_key.offset + 1; |
29 | init_waitqueue_head(&cur_trans->writer_wait); | 37 | init_waitqueue_head(&cur_trans->writer_wait); |
30 | init_waitqueue_head(&cur_trans->commit_wait); | 38 | init_waitqueue_head(&cur_trans->commit_wait); |
39 | cur_trans->magic = TRANS_MAGIC; | ||
31 | cur_trans->in_commit = 0; | 40 | cur_trans->in_commit = 0; |
32 | cur_trans->use_count = 1; | 41 | cur_trans->use_count = 1; |
33 | cur_trans->commit_done = 0; | 42 | cur_trans->commit_done = 0; |
@@ -39,7 +48,8 @@ static int join_transaction(struct btrfs_root *root) | |||
39 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | 48 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, |
40 | int num_blocks) | 49 | int num_blocks) |
41 | { | 50 | { |
42 | struct btrfs_trans_handle *h = kmalloc(sizeof(*h), GFP_NOFS); | 51 | struct btrfs_trans_handle *h = |
52 | kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); | ||
43 | int ret; | 53 | int ret; |
44 | 54 | ||
45 | mutex_lock(&root->fs_info->trans_mutex); | 55 | mutex_lock(&root->fs_info->trans_mutex); |
@@ -51,6 +61,7 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | |||
51 | h->blocks_used = 0; | 61 | h->blocks_used = 0; |
52 | root->fs_info->running_transaction->use_count++; | 62 | root->fs_info->running_transaction->use_count++; |
53 | mutex_unlock(&root->fs_info->trans_mutex); | 63 | mutex_unlock(&root->fs_info->trans_mutex); |
64 | h->magic = h->magic2 = TRANS_MAGIC; | ||
54 | return h; | 65 | return h; |
55 | } | 66 | } |
56 | 67 | ||
@@ -58,6 +69,8 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
58 | struct btrfs_root *root) | 69 | struct btrfs_root *root) |
59 | { | 70 | { |
60 | struct btrfs_transaction *cur_trans; | 71 | struct btrfs_transaction *cur_trans; |
72 | WARN_ON(trans->magic != TRANS_MAGIC); | ||
73 | WARN_ON(trans->magic2 != TRANS_MAGIC); | ||
61 | mutex_lock(&root->fs_info->trans_mutex); | 74 | mutex_lock(&root->fs_info->trans_mutex); |
62 | cur_trans = root->fs_info->running_transaction; | 75 | cur_trans = root->fs_info->running_transaction; |
63 | WARN_ON(cur_trans->num_writers < 1); | 76 | WARN_ON(cur_trans->num_writers < 1); |
@@ -67,7 +80,7 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
67 | put_transaction(cur_trans); | 80 | put_transaction(cur_trans); |
68 | mutex_unlock(&root->fs_info->trans_mutex); | 81 | mutex_unlock(&root->fs_info->trans_mutex); |
69 | memset(trans, 0, sizeof(*trans)); | 82 | memset(trans, 0, sizeof(*trans)); |
70 | kfree(trans); | 83 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
71 | return 0; | 84 | return 0; |
72 | } | 85 | } |
73 | 86 | ||
@@ -75,7 +88,7 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
75 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, | 88 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, |
76 | struct btrfs_root *root) | 89 | struct btrfs_root *root) |
77 | { | 90 | { |
78 | filemap_write_and_wait(root->fs_info->btree_inode->i_mapping); | 91 | filemap_write_and_wait(root->fs_info->sb->s_bdev->bd_inode->i_mapping); |
79 | return 0; | 92 | return 0; |
80 | } | 93 | } |
81 | 94 | ||
@@ -137,6 +150,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
137 | 150 | ||
138 | mutex_lock(&root->fs_info->trans_mutex); | 151 | mutex_lock(&root->fs_info->trans_mutex); |
139 | if (trans->transaction->in_commit) { | 152 | if (trans->transaction->in_commit) { |
153 | printk("already in commit!, waiting\n"); | ||
140 | cur_trans = trans->transaction; | 154 | cur_trans = trans->transaction; |
141 | trans->transaction->use_count++; | 155 | trans->transaction->use_count++; |
142 | btrfs_end_transaction(trans, root); | 156 | btrfs_end_transaction(trans, root); |
@@ -146,7 +160,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
146 | mutex_unlock(&root->fs_info->trans_mutex); | 160 | mutex_unlock(&root->fs_info->trans_mutex); |
147 | return 0; | 161 | return 0; |
148 | } | 162 | } |
163 | cur_trans = trans->transaction; | ||
164 | trans->transaction->in_commit = 1; | ||
149 | while (trans->transaction->num_writers > 1) { | 165 | while (trans->transaction->num_writers > 1) { |
166 | WARN_ON(cur_trans != trans->transaction); | ||
150 | prepare_to_wait(&trans->transaction->writer_wait, &wait, | 167 | prepare_to_wait(&trans->transaction->writer_wait, &wait, |
151 | TASK_UNINTERRUPTIBLE); | 168 | TASK_UNINTERRUPTIBLE); |
152 | if (trans->transaction->num_writers <= 1) | 169 | if (trans->transaction->num_writers <= 1) |
@@ -154,15 +171,15 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
154 | mutex_unlock(&root->fs_info->trans_mutex); | 171 | mutex_unlock(&root->fs_info->trans_mutex); |
155 | schedule(); | 172 | schedule(); |
156 | mutex_lock(&root->fs_info->trans_mutex); | 173 | mutex_lock(&root->fs_info->trans_mutex); |
174 | finish_wait(&trans->transaction->writer_wait, &wait); | ||
157 | } | 175 | } |
158 | finish_wait(&trans->transaction->writer_wait, &wait); | 176 | finish_wait(&trans->transaction->writer_wait, &wait); |
159 | 177 | WARN_ON(cur_trans != trans->transaction); | |
160 | if (root->node != root->commit_root) { | 178 | if (root->node != root->commit_root) { |
161 | memcpy(&snap_key, &root->root_key, sizeof(snap_key)); | 179 | memcpy(&snap_key, &root->root_key, sizeof(snap_key)); |
162 | root->root_key.offset++; | 180 | root->root_key.offset++; |
163 | } | 181 | } |
164 | 182 | ||
165 | |||
166 | if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) { | 183 | if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) { |
167 | btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr); | 184 | btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr); |
168 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, | 185 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, |
@@ -172,22 +189,21 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
172 | 189 | ||
173 | ret = btrfs_commit_tree_roots(trans, root); | 190 | ret = btrfs_commit_tree_roots(trans, root); |
174 | BUG_ON(ret); | 191 | BUG_ON(ret); |
175 | |||
176 | cur_trans = root->fs_info->running_transaction; | 192 | cur_trans = root->fs_info->running_transaction; |
177 | root->fs_info->running_transaction = NULL; | 193 | root->fs_info->running_transaction = NULL; |
178 | mutex_unlock(&root->fs_info->trans_mutex); | 194 | mutex_unlock(&root->fs_info->trans_mutex); |
179 | |||
180 | ret = btrfs_write_and_wait_transaction(trans, root); | 195 | ret = btrfs_write_and_wait_transaction(trans, root); |
181 | BUG_ON(ret); | 196 | BUG_ON(ret); |
182 | 197 | ||
183 | write_ctree_super(trans, root); | 198 | write_ctree_super(trans, root); |
184 | btrfs_finish_extent_commit(trans, root); | 199 | btrfs_finish_extent_commit(trans, root); |
185 | mutex_lock(&root->fs_info->trans_mutex); | 200 | mutex_lock(&root->fs_info->trans_mutex); |
201 | cur_trans->commit_done = 1; | ||
202 | wake_up(&cur_trans->commit_wait); | ||
186 | put_transaction(cur_trans); | 203 | put_transaction(cur_trans); |
187 | put_transaction(cur_trans); | 204 | put_transaction(cur_trans); |
188 | mutex_unlock(&root->fs_info->trans_mutex); | 205 | mutex_unlock(&root->fs_info->trans_mutex); |
189 | kfree(trans); | 206 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
190 | |||
191 | if (root->node != root->commit_root) { | 207 | if (root->node != root->commit_root) { |
192 | trans = btrfs_start_transaction(root, 1); | 208 | trans = btrfs_start_transaction(root, 1); |
193 | snap = root->commit_root; | 209 | snap = root->commit_root; |
@@ -203,7 +219,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
203 | ret = btrfs_end_transaction(trans, root); | 219 | ret = btrfs_end_transaction(trans, root); |
204 | BUG_ON(ret); | 220 | BUG_ON(ret); |
205 | } | 221 | } |
206 | |||
207 | return ret; | 222 | return ret; |
208 | } | 223 | } |
209 | 224 | ||
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 7e6c08a0accd..4f1496ae6f24 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -7,15 +7,18 @@ struct btrfs_transaction { | |||
7 | int in_commit; | 7 | int in_commit; |
8 | int use_count; | 8 | int use_count; |
9 | int commit_done; | 9 | int commit_done; |
10 | int magic; | ||
10 | wait_queue_head_t writer_wait; | 11 | wait_queue_head_t writer_wait; |
11 | wait_queue_head_t commit_wait; | 12 | wait_queue_head_t commit_wait; |
12 | }; | 13 | }; |
13 | 14 | ||
14 | struct btrfs_trans_handle { | 15 | struct btrfs_trans_handle { |
16 | int magic; | ||
15 | u64 transid; | 17 | u64 transid; |
16 | unsigned long blocks_reserved; | 18 | unsigned long blocks_reserved; |
17 | unsigned long blocks_used; | 19 | unsigned long blocks_used; |
18 | struct btrfs_transaction *transaction; | 20 | struct btrfs_transaction *transaction; |
21 | int magic2; | ||
19 | }; | 22 | }; |
20 | 23 | ||
21 | 24 | ||