diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-06 15:37:36 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-06 15:37:36 -0400 |
commit | d6e4a428eb8f92bbb3537ccabadfb1195efb432b (patch) | |
tree | ca408dbd20b38728412b58db5a6ec29aebbc0fe7 /fs/btrfs | |
parent | 3eb0314dc1053b1ae617dcc8d6d93f776c5baa31 (diff) |
Btrfs: start of support for many FS volumes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/TODO | 7 | ||||
-rw-r--r-- | fs/btrfs/btrfs_inode.h | 2 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 36 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 14 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 7 | ||||
-rw-r--r-- | fs/btrfs/inode-item.c | 26 | ||||
-rw-r--r-- | fs/btrfs/print-tree.c | 2 | ||||
-rw-r--r-- | fs/btrfs/super.c | 218 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 9 |
9 files changed, 242 insertions, 79 deletions
diff --git a/fs/btrfs/TODO b/fs/btrfs/TODO index ea4c38c790b4..73d4b842a316 100644 --- a/fs/btrfs/TODO +++ b/fs/btrfs/TODO | |||
@@ -19,3 +19,10 @@ | |||
19 | * fsck | 19 | * fsck |
20 | * Scrub & defrag | 20 | * Scrub & defrag |
21 | 21 | ||
22 | --- | ||
23 | metata FS ideas: | ||
24 | mount metadata FS on /sys/fs/btrfs/dev/ | ||
25 | subvolumes in /sys/fs/btrfs/dev/fs/ | ||
26 | snapshots in /sys/fs/btrfs/dev/fs/snapshots | ||
27 | mount -o bind | ||
28 | ioctl to create a snapshot | ||
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index e159841650a4..3439ffb467b5 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | struct btrfs_inode { | 4 | struct btrfs_inode { |
5 | u32 magic; | 5 | u32 magic; |
6 | struct btrfs_root *root; | ||
7 | struct btrfs_key location; | ||
6 | struct inode vfs_inode; | 8 | struct inode vfs_inode; |
7 | u32 magic2; | 9 | u32 magic2; |
8 | }; | 10 | }; |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 6d40758b893f..1ff5b99af682 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/fs.h> | 4 | #include <linux/fs.h> |
5 | #include <linux/buffer_head.h> | 5 | #include <linux/buffer_head.h> |
6 | #include <linux/kobject.h> | ||
6 | #include "bit-radix.h" | 7 | #include "bit-radix.h" |
7 | 8 | ||
8 | struct btrfs_trans_handle; | 9 | struct btrfs_trans_handle; |
@@ -183,13 +184,15 @@ struct btrfs_inline_data_item { | |||
183 | } __attribute__ ((__packed__)); | 184 | } __attribute__ ((__packed__)); |
184 | 185 | ||
185 | struct btrfs_dir_item { | 186 | struct btrfs_dir_item { |
186 | __le64 objectid; | 187 | struct btrfs_disk_key location; |
187 | __le16 flags; | 188 | __le16 flags; |
188 | __le16 name_len; | 189 | __le16 name_len; |
189 | u8 type; | 190 | u8 type; |
190 | } __attribute__ ((__packed__)); | 191 | } __attribute__ ((__packed__)); |
191 | 192 | ||
192 | struct btrfs_root_item { | 193 | struct btrfs_root_item { |
194 | struct btrfs_inode_item inode; | ||
195 | __le64 root_dirid; | ||
193 | __le64 blocknr; | 196 | __le64 blocknr; |
194 | __le32 flags; | 197 | __le32 flags; |
195 | __le64 block_limit; | 198 | __le64 block_limit; |
@@ -249,6 +252,7 @@ struct btrfs_fs_info { | |||
249 | struct mutex fs_mutex; | 252 | struct mutex fs_mutex; |
250 | struct crypto_hash *hash_tfm; | 253 | struct crypto_hash *hash_tfm; |
251 | spinlock_t hash_lock; | 254 | spinlock_t hash_lock; |
255 | struct kobject kobj; | ||
252 | }; | 256 | }; |
253 | 257 | ||
254 | /* | 258 | /* |
@@ -504,16 +508,6 @@ static inline void btrfs_set_item_size(struct btrfs_item *item, u16 val) | |||
504 | item->size = cpu_to_le16(val); | 508 | item->size = cpu_to_le16(val); |
505 | } | 509 | } |
506 | 510 | ||
507 | static inline u64 btrfs_dir_objectid(struct btrfs_dir_item *d) | ||
508 | { | ||
509 | return le64_to_cpu(d->objectid); | ||
510 | } | ||
511 | |||
512 | static inline void btrfs_set_dir_objectid(struct btrfs_dir_item *d, u64 val) | ||
513 | { | ||
514 | d->objectid = cpu_to_le64(val); | ||
515 | } | ||
516 | |||
517 | static inline u16 btrfs_dir_flags(struct btrfs_dir_item *d) | 511 | static inline u16 btrfs_dir_flags(struct btrfs_dir_item *d) |
518 | { | 512 | { |
519 | return le16_to_cpu(d->flags); | 513 | return le16_to_cpu(d->flags); |
@@ -724,6 +718,16 @@ static inline void btrfs_set_root_blocknr(struct btrfs_root_item *item, u64 val) | |||
724 | item->blocknr = cpu_to_le64(val); | 718 | item->blocknr = cpu_to_le64(val); |
725 | } | 719 | } |
726 | 720 | ||
721 | static inline u64 btrfs_root_dirid(struct btrfs_root_item *item) | ||
722 | { | ||
723 | return le64_to_cpu(item->root_dirid); | ||
724 | } | ||
725 | |||
726 | static inline void btrfs_set_root_dirid(struct btrfs_root_item *item, u64 val) | ||
727 | { | ||
728 | item->root_dirid = cpu_to_le64(val); | ||
729 | } | ||
730 | |||
727 | static inline u32 btrfs_root_refs(struct btrfs_root_item *item) | 731 | static inline u32 btrfs_root_refs(struct btrfs_root_item *item) |
728 | { | 732 | { |
729 | return le32_to_cpu(item->refs); | 733 | return le32_to_cpu(item->refs); |
@@ -950,8 +954,8 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct | |||
950 | btrfs_root_item *item, struct btrfs_key *key); | 954 | btrfs_root_item *item, struct btrfs_key *key); |
951 | /* dir-item.c */ | 955 | /* dir-item.c */ |
952 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 956 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
953 | *root, const char *name, int name_len, u64 dir, u64 | 957 | *root, const char *name, int name_len, u64 dir, |
954 | objectid, u8 type); | 958 | struct btrfs_key *location, u8 type); |
955 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 959 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
956 | *root, struct btrfs_path *path, u64 dir, | 960 | *root, struct btrfs_path *path, u64 dir, |
957 | const char *name, int name_len, int mod); | 961 | const char *name, int name_len, int mod); |
@@ -978,7 +982,8 @@ int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root | |||
978 | *root, u64 objectid, struct btrfs_inode_item | 982 | *root, u64 objectid, struct btrfs_inode_item |
979 | *inode_item); | 983 | *inode_item); |
980 | int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root | 984 | int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root |
981 | *root, struct btrfs_path *path, u64 objectid, int mod); | 985 | *root, struct btrfs_path *path, |
986 | struct btrfs_key *location, int mod); | ||
982 | 987 | ||
983 | /* file-item.c */ | 988 | /* file-item.c */ |
984 | int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans, | 989 | int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans, |
@@ -997,4 +1002,7 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
997 | int btrfs_csum_verify_file_block(struct btrfs_root *root, | 1002 | int btrfs_csum_verify_file_block(struct btrfs_root *root, |
998 | u64 objectid, u64 offset, | 1003 | u64 objectid, u64 offset, |
999 | char *data, size_t len); | 1004 | char *data, size_t len); |
1005 | /* super.c */ | ||
1006 | extern struct subsystem btrfs_subsys; | ||
1007 | |||
1000 | #endif | 1008 | #endif |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 0ee9945fb1b0..7aed9f015b55 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -25,8 +25,8 @@ int insert_with_overflow(struct btrfs_trans_handle *trans, struct btrfs_root | |||
25 | } | 25 | } |
26 | 26 | ||
27 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 27 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
28 | *root, const char *name, int name_len, u64 dir, u64 | 28 | *root, const char *name, int name_len, u64 dir, |
29 | objectid, u8 type) | 29 | struct btrfs_key *location, u8 type) |
30 | { | 30 | { |
31 | int ret = 0; | 31 | int ret = 0; |
32 | struct btrfs_path *path; | 32 | struct btrfs_path *path; |
@@ -50,17 +50,21 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
50 | dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | 50 | dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), |
51 | path->slots[0], | 51 | path->slots[0], |
52 | struct btrfs_dir_item); | 52 | struct btrfs_dir_item); |
53 | btrfs_set_dir_objectid(dir_item, objectid); | 53 | btrfs_cpu_key_to_disk(&dir_item->location, location); |
54 | btrfs_set_dir_type(dir_item, type); | 54 | btrfs_set_dir_type(dir_item, type); |
55 | btrfs_set_dir_flags(dir_item, 0); | 55 | btrfs_set_dir_flags(dir_item, 0); |
56 | btrfs_set_dir_name_len(dir_item, name_len); | 56 | btrfs_set_dir_name_len(dir_item, name_len); |
57 | name_ptr = (char *)(dir_item + 1); | 57 | name_ptr = (char *)(dir_item + 1); |
58 | /* FIXME, use some real flag for selecting the extra index */ | ||
59 | if (root == root->fs_info->tree_root) | ||
60 | goto out; | ||
61 | |||
58 | btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); | 62 | btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); |
59 | btrfs_mark_buffer_dirty(path->nodes[0]); | 63 | btrfs_mark_buffer_dirty(path->nodes[0]); |
60 | btrfs_release_path(root, path); | 64 | btrfs_release_path(root, path); |
61 | 65 | ||
62 | btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); | 66 | btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); |
63 | key.offset = objectid; | 67 | key.offset = location->objectid; |
64 | ret = insert_with_overflow(trans, root, path, &key, data_size); | 68 | ret = insert_with_overflow(trans, root, path, &key, data_size); |
65 | // FIXME clear the dirindex bit | 69 | // FIXME clear the dirindex bit |
66 | if (ret) | 70 | if (ret) |
@@ -69,7 +73,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
69 | dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | 73 | dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), |
70 | path->slots[0], | 74 | path->slots[0], |
71 | struct btrfs_dir_item); | 75 | struct btrfs_dir_item); |
72 | btrfs_set_dir_objectid(dir_item, objectid); | 76 | btrfs_cpu_key_to_disk(&dir_item->location, location); |
73 | btrfs_set_dir_type(dir_item, type); | 77 | btrfs_set_dir_type(dir_item, type); |
74 | btrfs_set_dir_flags(dir_item, 0); | 78 | btrfs_set_dir_flags(dir_item, 0); |
75 | btrfs_set_dir_name_len(dir_item, name_len); | 79 | btrfs_set_dir_name_len(dir_item, name_len); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 5230554380d1..b9301a5e4608 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -338,7 +338,6 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
338 | sb->s_blocksize); | 338 | sb->s_blocksize); |
339 | 339 | ||
340 | if (!fs_info->sb_buffer) { | 340 | if (!fs_info->sb_buffer) { |
341 | printk("failed2\n"); | ||
342 | return NULL; | 341 | return NULL; |
343 | } | 342 | } |
344 | disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data; | 343 | disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data; |
@@ -369,6 +368,10 @@ printk("failed2\n"); | |||
369 | ret = btrfs_find_highest_inode(root, &root->fs_info->last_inode_alloc); | 368 | ret = btrfs_find_highest_inode(root, &root->fs_info->last_inode_alloc); |
370 | if (ret == 0) | 369 | if (ret == 0) |
371 | fs_info->highest_inode = fs_info->last_inode_alloc; | 370 | fs_info->highest_inode = fs_info->last_inode_alloc; |
371 | memset(&fs_info->kobj, 0, sizeof(fs_info->kobj)); | ||
372 | kobj_set_kset_s(fs_info, btrfs_subsys); | ||
373 | kobject_set_name(&fs_info->kobj, "%s", sb->s_id); | ||
374 | kobject_register(&fs_info->kobj); | ||
372 | mutex_unlock(&fs_info->fs_mutex); | 375 | mutex_unlock(&fs_info->fs_mutex); |
373 | return root; | 376 | return root; |
374 | } | 377 | } |
@@ -430,7 +433,7 @@ int close_ctree(struct btrfs_root *root) | |||
430 | kfree(root->fs_info->extent_root); | 433 | kfree(root->fs_info->extent_root); |
431 | kfree(root->fs_info->inode_root); | 434 | kfree(root->fs_info->inode_root); |
432 | kfree(root->fs_info->tree_root); | 435 | kfree(root->fs_info->tree_root); |
433 | kfree(root->fs_info); | 436 | kobject_unregister(&root->fs_info->kobj); |
434 | kfree(root); | 437 | kfree(root); |
435 | return 0; | 438 | return 0; |
436 | } | 439 | } |
diff --git a/fs/btrfs/inode-item.c b/fs/btrfs/inode-item.c index 6bfa980790c2..b276a3b40a66 100644 --- a/fs/btrfs/inode-item.c +++ b/fs/btrfs/inode-item.c | |||
@@ -26,15 +26,27 @@ int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root | |||
26 | } | 26 | } |
27 | 27 | ||
28 | int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root | 28 | int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root |
29 | *root, struct btrfs_path *path, u64 objectid, int mod) | 29 | *root, struct btrfs_path *path, |
30 | struct btrfs_key *location, int mod) | ||
30 | { | 31 | { |
31 | struct btrfs_key key; | ||
32 | int ins_len = mod < 0 ? -1 : 0; | 32 | int ins_len = mod < 0 ? -1 : 0; |
33 | int cow = mod != 0; | 33 | int cow = mod != 0; |
34 | int ret; | ||
35 | int slot; | ||
36 | struct btrfs_leaf *leaf; | ||
37 | struct btrfs_key found_key; | ||
34 | 38 | ||
35 | key.objectid = objectid; | 39 | ret = btrfs_search_slot(trans, root, location, path, ins_len, cow); |
36 | key.flags = 0; | 40 | if (ret > 0 && btrfs_key_type(location) == BTRFS_ROOT_ITEM_KEY && |
37 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | 41 | location->offset == (u64)-1 && path->slots[0] != 0) { |
38 | key.offset = 0; | 42 | slot = path->slots[0] - 1; |
39 | return btrfs_search_slot(trans, root, &key, path, ins_len, cow); | 43 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
44 | btrfs_disk_key_to_cpu(&found_key, &leaf->items[slot].key); | ||
45 | if (found_key.objectid == location->objectid && | ||
46 | btrfs_key_type(&found_key) == btrfs_key_type(location)) { | ||
47 | path->slots[0]--; | ||
48 | return 0; | ||
49 | } | ||
50 | } | ||
51 | return ret; | ||
40 | } | 52 | } |
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index c8ee938c1251..f0da65c4f96b 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c | |||
@@ -38,7 +38,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
38 | case BTRFS_DIR_ITEM_KEY: | 38 | case BTRFS_DIR_ITEM_KEY: |
39 | di = btrfs_item_ptr(l, i, struct btrfs_dir_item); | 39 | di = btrfs_item_ptr(l, i, struct btrfs_dir_item); |
40 | printk("\t\tdir oid %Lu flags %u type %u\n", | 40 | printk("\t\tdir oid %Lu flags %u type %u\n", |
41 | btrfs_dir_objectid(di), | 41 | btrfs_disk_key_objectid(&di->location), |
42 | btrfs_dir_flags(di), | 42 | btrfs_dir_flags(di), |
43 | btrfs_dir_type(di)); | 43 | btrfs_dir_type(di)); |
44 | printk("\t\tname %.*s\n", | 44 | printk("\t\tname %.*s\n", |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 32224ffdcecd..66d9fb2288c3 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -16,9 +16,23 @@ | |||
16 | #include "transaction.h" | 16 | #include "transaction.h" |
17 | #include "btrfs_inode.h" | 17 | #include "btrfs_inode.h" |
18 | 18 | ||
19 | void btrfs_fsinfo_release(struct kobject *obj) | ||
20 | { | ||
21 | struct btrfs_fs_info *fsinfo = container_of(obj, | ||
22 | struct btrfs_fs_info, kobj); | ||
23 | kfree(fsinfo); | ||
24 | } | ||
25 | |||
26 | struct kobj_type btrfs_fsinfo_ktype = { | ||
27 | .release = btrfs_fsinfo_release, | ||
28 | }; | ||
29 | |||
30 | decl_subsys(btrfs, &btrfs_fsinfo_ktype, NULL); | ||
31 | |||
19 | #define BTRFS_SUPER_MAGIC 0x9123682E | 32 | #define BTRFS_SUPER_MAGIC 0x9123682E |
20 | 33 | ||
21 | static struct inode_operations btrfs_dir_inode_operations; | 34 | static struct inode_operations btrfs_dir_inode_operations; |
35 | static struct inode_operations btrfs_dir_ro_inode_operations; | ||
22 | static struct super_operations btrfs_super_ops; | 36 | static struct super_operations btrfs_super_ops; |
23 | static struct file_operations btrfs_dir_file_operations; | 37 | static struct file_operations btrfs_dir_file_operations; |
24 | static struct inode_operations btrfs_file_inode_operations; | 38 | static struct inode_operations btrfs_file_inode_operations; |
@@ -37,7 +51,8 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
37 | { | 51 | { |
38 | struct btrfs_path *path; | 52 | struct btrfs_path *path; |
39 | struct btrfs_inode_item *inode_item; | 53 | struct btrfs_inode_item *inode_item; |
40 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | 54 | struct btrfs_root *root = BTRFS_I(inode)->root; |
55 | struct btrfs_key location; | ||
41 | int ret; | 56 | int ret; |
42 | 57 | ||
43 | path = btrfs_alloc_path(); | 58 | path = btrfs_alloc_path(); |
@@ -46,13 +61,12 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
46 | mutex_lock(&root->fs_info->fs_mutex); | 61 | mutex_lock(&root->fs_info->fs_mutex); |
47 | 62 | ||
48 | check_inode(inode); | 63 | check_inode(inode); |
49 | ret = btrfs_lookup_inode(NULL, root, path, inode->i_ino, 0); | 64 | |
65 | memcpy(&location, &BTRFS_I(inode)->location, sizeof(location)); | ||
66 | ret = btrfs_lookup_inode(NULL, root, path, &location, 0); | ||
50 | if (ret) { | 67 | if (ret) { |
51 | btrfs_release_path(root, path); | ||
52 | btrfs_free_path(path); | 68 | btrfs_free_path(path); |
53 | mutex_unlock(&root->fs_info->fs_mutex); | 69 | goto make_bad; |
54 | make_bad_inode(inode); | ||
55 | return; | ||
56 | } | 70 | } |
57 | check_inode(inode); | 71 | check_inode(inode); |
58 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | 72 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), |
@@ -73,7 +87,6 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
73 | inode->i_blocks = btrfs_inode_nblocks(inode_item); | 87 | inode->i_blocks = btrfs_inode_nblocks(inode_item); |
74 | inode->i_generation = btrfs_inode_generation(inode_item); | 88 | inode->i_generation = btrfs_inode_generation(inode_item); |
75 | 89 | ||
76 | btrfs_release_path(root, path); | ||
77 | btrfs_free_path(path); | 90 | btrfs_free_path(path); |
78 | inode_item = NULL; | 91 | inode_item = NULL; |
79 | 92 | ||
@@ -92,8 +105,11 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
92 | inode->i_op = &btrfs_file_inode_operations; | 105 | inode->i_op = &btrfs_file_inode_operations; |
93 | break; | 106 | break; |
94 | case S_IFDIR: | 107 | case S_IFDIR: |
95 | inode->i_op = &btrfs_dir_inode_operations; | ||
96 | inode->i_fop = &btrfs_dir_file_operations; | 108 | inode->i_fop = &btrfs_dir_file_operations; |
109 | if (root == root->fs_info->tree_root) | ||
110 | inode->i_op = &btrfs_dir_ro_inode_operations; | ||
111 | else | ||
112 | inode->i_op = &btrfs_dir_inode_operations; | ||
97 | break; | 113 | break; |
98 | case S_IFLNK: | 114 | case S_IFLNK: |
99 | // inode->i_op = &page_symlink_inode_operations; | 115 | // inode->i_op = &page_symlink_inode_operations; |
@@ -101,6 +117,12 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
101 | } | 117 | } |
102 | check_inode(inode); | 118 | check_inode(inode); |
103 | return; | 119 | return; |
120 | |||
121 | make_bad: | ||
122 | btrfs_release_path(root, path); | ||
123 | btrfs_free_path(path); | ||
124 | mutex_unlock(&root->fs_info->fs_mutex); | ||
125 | make_bad_inode(inode); | ||
104 | } | 126 | } |
105 | 127 | ||
106 | static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | 128 | static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, |
@@ -128,7 +150,7 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | |||
128 | } | 150 | } |
129 | di = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | 151 | di = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], |
130 | struct btrfs_dir_item); | 152 | struct btrfs_dir_item); |
131 | objectid = btrfs_dir_objectid(di); | 153 | objectid = btrfs_disk_key_objectid(&di->location); |
132 | 154 | ||
133 | ret = btrfs_del_item(trans, root, path); | 155 | ret = btrfs_del_item(trans, root, path); |
134 | BUG_ON(ret); | 156 | BUG_ON(ret); |
@@ -157,7 +179,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
157 | struct btrfs_trans_handle *trans; | 179 | struct btrfs_trans_handle *trans; |
158 | int ret; | 180 | int ret; |
159 | 181 | ||
160 | root = btrfs_sb(dir->i_sb); | 182 | root = BTRFS_I(dir)->root; |
161 | mutex_lock(&root->fs_info->fs_mutex); | 183 | mutex_lock(&root->fs_info->fs_mutex); |
162 | trans = btrfs_start_transaction(root, 1); | 184 | trans = btrfs_start_transaction(root, 1); |
163 | ret = btrfs_unlink_trans(trans, root, dir, dentry); | 185 | ret = btrfs_unlink_trans(trans, root, dir, dentry); |
@@ -171,7 +193,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
171 | struct inode *inode = dentry->d_inode; | 193 | struct inode *inode = dentry->d_inode; |
172 | int err; | 194 | int err; |
173 | int ret; | 195 | int ret; |
174 | struct btrfs_root *root = btrfs_sb(dir->i_sb); | 196 | struct btrfs_root *root = BTRFS_I(dir)->root; |
175 | struct btrfs_path *path; | 197 | struct btrfs_path *path; |
176 | struct btrfs_key key; | 198 | struct btrfs_key key; |
177 | struct btrfs_trans_handle *trans; | 199 | struct btrfs_trans_handle *trans; |
@@ -268,7 +290,8 @@ static int btrfs_free_inode(struct btrfs_trans_handle *trans, | |||
268 | BUG_ON(ret); | 290 | BUG_ON(ret); |
269 | btrfs_release_path(root, path); | 291 | btrfs_release_path(root, path); |
270 | 292 | ||
271 | ret = btrfs_lookup_inode(trans, root, path, objectid, -1); | 293 | ret = btrfs_lookup_inode(trans, root, path, |
294 | &BTRFS_I(inode)->location, -1); | ||
272 | BUG_ON(ret); | 295 | BUG_ON(ret); |
273 | ret = btrfs_del_item(trans, root, path); | 296 | ret = btrfs_del_item(trans, root, path); |
274 | BUG_ON(ret); | 297 | BUG_ON(ret); |
@@ -355,7 +378,7 @@ error: | |||
355 | static void btrfs_delete_inode(struct inode *inode) | 378 | static void btrfs_delete_inode(struct inode *inode) |
356 | { | 379 | { |
357 | struct btrfs_trans_handle *trans; | 380 | struct btrfs_trans_handle *trans; |
358 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | 381 | struct btrfs_root *root = BTRFS_I(inode)->root; |
359 | int ret; | 382 | int ret; |
360 | 383 | ||
361 | truncate_inode_pages(&inode->i_data, 0); | 384 | truncate_inode_pages(&inode->i_data, 0); |
@@ -378,13 +401,13 @@ no_delete: | |||
378 | } | 401 | } |
379 | 402 | ||
380 | static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, | 403 | static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, |
381 | ino_t *ino) | 404 | struct btrfs_key *location) |
382 | { | 405 | { |
383 | const char *name = dentry->d_name.name; | 406 | const char *name = dentry->d_name.name; |
384 | int namelen = dentry->d_name.len; | 407 | int namelen = dentry->d_name.len; |
385 | struct btrfs_dir_item *di; | 408 | struct btrfs_dir_item *di; |
386 | struct btrfs_path *path; | 409 | struct btrfs_path *path; |
387 | struct btrfs_root *root = btrfs_sb(dir->i_sb); | 410 | struct btrfs_root *root = BTRFS_I(dir)->root; |
388 | int ret; | 411 | int ret; |
389 | 412 | ||
390 | path = btrfs_alloc_path(); | 413 | path = btrfs_alloc_path(); |
@@ -393,13 +416,13 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, | |||
393 | ret = btrfs_lookup_dir_item(NULL, root, path, dir->i_ino, name, | 416 | ret = btrfs_lookup_dir_item(NULL, root, path, dir->i_ino, name, |
394 | namelen, 0); | 417 | namelen, 0); |
395 | if (ret || !btrfs_match_dir_item_name(root, path, name, namelen)) { | 418 | if (ret || !btrfs_match_dir_item_name(root, path, name, namelen)) { |
396 | *ino = 0; | 419 | location->objectid = 0; |
397 | ret = 0; | 420 | ret = 0; |
398 | goto out; | 421 | goto out; |
399 | } | 422 | } |
400 | di = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | 423 | di = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], |
401 | struct btrfs_dir_item); | 424 | struct btrfs_dir_item); |
402 | *ino = btrfs_dir_objectid(di); | 425 | btrfs_disk_key_to_cpu(location, &di->location); |
403 | out: | 426 | out: |
404 | btrfs_release_path(root, path); | 427 | btrfs_release_path(root, path); |
405 | btrfs_free_path(path); | 428 | btrfs_free_path(path); |
@@ -407,26 +430,76 @@ out: | |||
407 | return ret; | 430 | return ret; |
408 | } | 431 | } |
409 | 432 | ||
433 | int fixup_tree_root_location(struct btrfs_root *root, | ||
434 | struct btrfs_key *location, | ||
435 | struct btrfs_root **sub_root) | ||
436 | { | ||
437 | struct btrfs_path *path; | ||
438 | struct btrfs_root_item *ri; | ||
439 | int ret; | ||
440 | |||
441 | if (btrfs_key_type(location) != BTRFS_ROOT_ITEM_KEY) | ||
442 | return 0; | ||
443 | if (location->objectid == BTRFS_ROOT_TREE_OBJECTID) | ||
444 | return 0; | ||
445 | |||
446 | path = btrfs_alloc_path(); | ||
447 | BUG_ON(!path); | ||
448 | mutex_lock(&root->fs_info->fs_mutex); | ||
449 | |||
450 | ret = btrfs_lookup_inode(NULL, root, path, location, 0); | ||
451 | if (ret) | ||
452 | goto out; | ||
453 | ri = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
454 | path->slots[0], | ||
455 | struct btrfs_root_item); | ||
456 | location->objectid = btrfs_root_dirid(ri); | ||
457 | location->flags = 0; | ||
458 | btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY); | ||
459 | location->offset = 0; | ||
460 | /* FIXME properly select the root */ | ||
461 | *sub_root = root->fs_info->fs_root; | ||
462 | out: | ||
463 | btrfs_free_path(path); | ||
464 | mutex_unlock(&root->fs_info->fs_mutex); | ||
465 | return ret; | ||
466 | } | ||
467 | |||
468 | |||
410 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | 469 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, |
411 | struct nameidata *nd) | 470 | struct nameidata *nd) |
412 | { | 471 | { |
413 | struct inode * inode; | 472 | struct inode * inode; |
414 | struct btrfs_root *root = btrfs_sb(dir->i_sb); | 473 | struct btrfs_inode *bi = BTRFS_I(dir); |
415 | ino_t ino; | 474 | struct btrfs_root *root = bi->root; |
475 | struct btrfs_root *sub_root = root; | ||
476 | struct btrfs_key location; | ||
416 | int ret; | 477 | int ret; |
417 | 478 | ||
418 | if (dentry->d_name.len > BTRFS_NAME_LEN) | 479 | if (dentry->d_name.len > BTRFS_NAME_LEN) |
419 | return ERR_PTR(-ENAMETOOLONG); | 480 | return ERR_PTR(-ENAMETOOLONG); |
420 | mutex_lock(&root->fs_info->fs_mutex); | 481 | mutex_lock(&root->fs_info->fs_mutex); |
421 | ret = btrfs_inode_by_name(dir, dentry, &ino); | 482 | ret = btrfs_inode_by_name(dir, dentry, &location); |
422 | mutex_unlock(&root->fs_info->fs_mutex); | 483 | mutex_unlock(&root->fs_info->fs_mutex); |
423 | if (ret < 0) | 484 | if (ret < 0) |
424 | return ERR_PTR(ret); | 485 | return ERR_PTR(ret); |
425 | inode = NULL; | 486 | inode = NULL; |
426 | if (ino) { | 487 | if (location.objectid) { |
427 | inode = iget(dir->i_sb, ino); | 488 | ret = fixup_tree_root_location(root, &location, &sub_root); |
489 | if (ret < 0) | ||
490 | return ERR_PTR(ret); | ||
491 | if (ret > 0) | ||
492 | return ERR_PTR(-ENOENT); | ||
493 | inode = iget_locked(dir->i_sb, location.objectid); | ||
428 | if (!inode) | 494 | if (!inode) |
429 | return ERR_PTR(-EACCES); | 495 | return ERR_PTR(-EACCES); |
496 | if (inode->i_state & I_NEW) { | ||
497 | BTRFS_I(inode)->root = sub_root; | ||
498 | memcpy(&BTRFS_I(inode)->location, &location, | ||
499 | sizeof(location)); | ||
500 | btrfs_read_locked_inode(inode); | ||
501 | unlock_new_inode(inode); | ||
502 | } | ||
430 | check_inode(inode); | 503 | check_inode(inode); |
431 | } | 504 | } |
432 | check_inode(dir); | 505 | check_inode(dir); |
@@ -436,7 +509,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
436 | static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 509 | static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) |
437 | { | 510 | { |
438 | struct inode *inode = filp->f_path.dentry->d_inode; | 511 | struct inode *inode = filp->f_path.dentry->d_inode; |
439 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | 512 | struct btrfs_root *root = BTRFS_I(inode)->root; |
440 | struct btrfs_item *item; | 513 | struct btrfs_item *item; |
441 | struct btrfs_dir_item *di; | 514 | struct btrfs_dir_item *di; |
442 | struct btrfs_key key; | 515 | struct btrfs_key key; |
@@ -448,11 +521,16 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
448 | int advance; | 521 | int advance; |
449 | unsigned char d_type = DT_UNKNOWN; | 522 | unsigned char d_type = DT_UNKNOWN; |
450 | int over = 0; | 523 | int over = 0; |
524 | int key_type = BTRFS_DIR_INDEX_KEY; | ||
525 | |||
526 | /* FIXME, use a real flag for deciding about the key type */ | ||
527 | if (root->fs_info->tree_root == root) | ||
528 | key_type = BTRFS_DIR_ITEM_KEY; | ||
451 | 529 | ||
452 | mutex_lock(&root->fs_info->fs_mutex); | 530 | mutex_lock(&root->fs_info->fs_mutex); |
453 | key.objectid = inode->i_ino; | 531 | key.objectid = inode->i_ino; |
454 | key.flags = 0; | 532 | key.flags = 0; |
455 | btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); | 533 | btrfs_set_key_type(&key, key_type); |
456 | key.offset = filp->f_pos; | 534 | key.offset = filp->f_pos; |
457 | path = btrfs_alloc_path(); | 535 | path = btrfs_alloc_path(); |
458 | btrfs_init_path(path); | 536 | btrfs_init_path(path); |
@@ -482,10 +560,11 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
482 | item = leaf->items + slot; | 560 | item = leaf->items + slot; |
483 | if (btrfs_disk_key_objectid(&item->key) != key.objectid) | 561 | if (btrfs_disk_key_objectid(&item->key) != key.objectid) |
484 | break; | 562 | break; |
485 | if (btrfs_disk_key_offset(&item->key) > | 563 | if (key_type == BTRFS_DIR_INDEX_KEY && |
564 | btrfs_disk_key_offset(&item->key) > | ||
486 | root->fs_info->highest_inode) | 565 | root->fs_info->highest_inode) |
487 | break; | 566 | break; |
488 | if (btrfs_disk_key_type(&item->key) != BTRFS_DIR_INDEX_KEY) | 567 | if (btrfs_disk_key_type(&item->key) != key_type) |
489 | continue; | 568 | continue; |
490 | if (btrfs_disk_key_offset(&item->key) < filp->f_pos) | 569 | if (btrfs_disk_key_offset(&item->key) < filp->f_pos) |
491 | continue; | 570 | continue; |
@@ -495,7 +574,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
495 | over = filldir(dirent, (const char *)(di + 1), | 574 | over = filldir(dirent, (const char *)(di + 1), |
496 | btrfs_dir_name_len(di), | 575 | btrfs_dir_name_len(di), |
497 | btrfs_disk_key_offset(&item->key), | 576 | btrfs_disk_key_offset(&item->key), |
498 | btrfs_dir_objectid(di), d_type); | 577 | btrfs_disk_key_objectid(&di->location), d_type); |
499 | if (over) | 578 | if (over) |
500 | goto nopos; | 579 | goto nopos; |
501 | } | 580 | } |
@@ -527,6 +606,7 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent) | |||
527 | struct dentry * root_dentry; | 606 | struct dentry * root_dentry; |
528 | struct btrfs_super_block *disk_super; | 607 | struct btrfs_super_block *disk_super; |
529 | struct btrfs_root *root; | 608 | struct btrfs_root *root; |
609 | struct btrfs_inode *bi; | ||
530 | 610 | ||
531 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 611 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
532 | sb->s_magic = BTRFS_SUPER_MAGIC; | 612 | sb->s_magic = BTRFS_SUPER_MAGIC; |
@@ -546,6 +626,13 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent) | |||
546 | btrfs_super_root_dir(disk_super)); | 626 | btrfs_super_root_dir(disk_super)); |
547 | 627 | ||
548 | inode = iget_locked(sb, btrfs_super_root_dir(disk_super)); | 628 | inode = iget_locked(sb, btrfs_super_root_dir(disk_super)); |
629 | bi = BTRFS_I(inode); | ||
630 | bi->location.objectid = inode->i_ino; | ||
631 | bi->location.offset = 0; | ||
632 | bi->location.flags = 0; | ||
633 | bi->root = root->fs_info->tree_root; | ||
634 | btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY); | ||
635 | |||
549 | if (!inode) | 636 | if (!inode) |
550 | return -ENOMEM; | 637 | return -ENOMEM; |
551 | if (inode->i_state & I_NEW) { | 638 | if (inode->i_state & I_NEW) { |
@@ -594,7 +681,8 @@ static int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
594 | BUG_ON(!path); | 681 | BUG_ON(!path); |
595 | btrfs_init_path(path); | 682 | btrfs_init_path(path); |
596 | 683 | ||
597 | ret = btrfs_lookup_inode(trans, root, path, inode->i_ino, 1); | 684 | ret = btrfs_lookup_inode(trans, root, path, |
685 | &BTRFS_I(inode)->location, 1); | ||
598 | if (ret) { | 686 | if (ret) { |
599 | if (ret > 0) | 687 | if (ret > 0) |
600 | ret = -ENOENT; | 688 | ret = -ENOENT; |
@@ -616,7 +704,7 @@ failed: | |||
616 | 704 | ||
617 | static int btrfs_write_inode(struct inode *inode, int wait) | 705 | static int btrfs_write_inode(struct inode *inode, int wait) |
618 | { | 706 | { |
619 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | 707 | struct btrfs_root *root = BTRFS_I(inode)->root; |
620 | struct btrfs_trans_handle *trans; | 708 | struct btrfs_trans_handle *trans; |
621 | int ret; | 709 | int ret; |
622 | 710 | ||
@@ -637,8 +725,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
637 | { | 725 | { |
638 | struct inode *inode; | 726 | struct inode *inode; |
639 | struct btrfs_inode_item inode_item; | 727 | struct btrfs_inode_item inode_item; |
640 | struct btrfs_root *root = btrfs_sb(dir->i_sb); | 728 | struct btrfs_root *root = BTRFS_I(dir)->root; |
641 | struct btrfs_key key; | 729 | struct btrfs_key *key; |
642 | int ret; | 730 | int ret; |
643 | u64 objectid; | 731 | u64 objectid; |
644 | 732 | ||
@@ -646,6 +734,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
646 | if (!inode) | 734 | if (!inode) |
647 | return ERR_PTR(-ENOMEM); | 735 | return ERR_PTR(-ENOMEM); |
648 | 736 | ||
737 | BTRFS_I(inode)->root = BTRFS_I(dir)->root; | ||
738 | key = &BTRFS_I(inode)->location; | ||
649 | check_inode(inode); | 739 | check_inode(inode); |
650 | ret = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid); | 740 | ret = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid); |
651 | BUG_ON(ret); | 741 | BUG_ON(ret); |
@@ -658,11 +748,11 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
658 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; | 748 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; |
659 | fill_inode_item(&inode_item, inode); | 749 | fill_inode_item(&inode_item, inode); |
660 | 750 | ||
661 | key.objectid = objectid; | 751 | key->objectid = objectid; |
662 | key.flags = 0; | 752 | key->flags = 0; |
663 | key.offset = 0; | 753 | key->offset = 0; |
664 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | 754 | btrfs_set_key_type(key, BTRFS_INODE_ITEM_KEY); |
665 | ret = btrfs_insert_inode_map(trans, root, objectid, &key); | 755 | ret = btrfs_insert_inode_map(trans, root, objectid, key); |
666 | BUG_ON(ret); | 756 | BUG_ON(ret); |
667 | 757 | ||
668 | ret = btrfs_insert_inode(trans, root, objectid, &inode_item); | 758 | ret = btrfs_insert_inode(trans, root, objectid, &inode_item); |
@@ -678,13 +768,20 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
678 | struct dentry *dentry, struct inode *inode) | 768 | struct dentry *dentry, struct inode *inode) |
679 | { | 769 | { |
680 | int ret; | 770 | int ret; |
681 | ret = btrfs_insert_dir_item(trans, btrfs_sb(inode->i_sb), | 771 | struct btrfs_key key; |
772 | struct btrfs_root *root = BTRFS_I(dentry->d_parent->d_inode)->root; | ||
773 | key.objectid = inode->i_ino; | ||
774 | key.flags = 0; | ||
775 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | ||
776 | key.offset = 0; | ||
777 | |||
778 | ret = btrfs_insert_dir_item(trans, root, | ||
682 | dentry->d_name.name, dentry->d_name.len, | 779 | dentry->d_name.name, dentry->d_name.len, |
683 | dentry->d_parent->d_inode->i_ino, | 780 | dentry->d_parent->d_inode->i_ino, |
684 | inode->i_ino, 0); | 781 | &key, 0); |
685 | if (ret == 0) { | 782 | if (ret == 0) { |
686 | dentry->d_parent->d_inode->i_size += dentry->d_name.len * 2; | 783 | dentry->d_parent->d_inode->i_size += dentry->d_name.len * 2; |
687 | ret = btrfs_update_inode(trans, btrfs_sb(inode->i_sb), | 784 | ret = btrfs_update_inode(trans, root, |
688 | dentry->d_parent->d_inode); | 785 | dentry->d_parent->d_inode); |
689 | } | 786 | } |
690 | check_inode(inode); | 787 | check_inode(inode); |
@@ -710,7 +807,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
710 | int mode, struct nameidata *nd) | 807 | int mode, struct nameidata *nd) |
711 | { | 808 | { |
712 | struct btrfs_trans_handle *trans; | 809 | struct btrfs_trans_handle *trans; |
713 | struct btrfs_root *root = btrfs_sb(dir->i_sb); | 810 | struct btrfs_root *root = BTRFS_I(dir)->root; |
714 | struct inode *inode; | 811 | struct inode *inode; |
715 | int err; | 812 | int err; |
716 | int drop_inode = 0; | 813 | int drop_inode = 0; |
@@ -747,18 +844,26 @@ out_unlock: | |||
747 | static int btrfs_make_empty_dir(struct btrfs_trans_handle *trans, | 844 | static int btrfs_make_empty_dir(struct btrfs_trans_handle *trans, |
748 | struct inode *inode, struct inode *dir) | 845 | struct inode *inode, struct inode *dir) |
749 | { | 846 | { |
750 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | 847 | struct btrfs_root *root = BTRFS_I(dir)->root; |
751 | int ret; | 848 | int ret; |
752 | char buf[2]; | 849 | char buf[2]; |
850 | struct btrfs_key key; | ||
851 | |||
753 | buf[0] = '.'; | 852 | buf[0] = '.'; |
754 | buf[1] = '.'; | 853 | buf[1] = '.'; |
755 | 854 | ||
855 | key.objectid = inode->i_ino; | ||
856 | key.offset = 0; | ||
857 | key.flags = 0; | ||
858 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | ||
859 | |||
756 | ret = btrfs_insert_dir_item(trans, root, buf, 1, inode->i_ino, | 860 | ret = btrfs_insert_dir_item(trans, root, buf, 1, inode->i_ino, |
757 | inode->i_ino, 1); | 861 | &key, 1); |
758 | if (ret) | 862 | if (ret) |
759 | goto error; | 863 | goto error; |
864 | key.objectid = dir->i_ino; | ||
760 | ret = btrfs_insert_dir_item(trans, root, buf, 2, inode->i_ino, | 865 | ret = btrfs_insert_dir_item(trans, root, buf, 2, inode->i_ino, |
761 | dir->i_ino, 1); | 866 | &key, 1); |
762 | if (ret) | 867 | if (ret) |
763 | goto error; | 868 | goto error; |
764 | inode->i_size = 6; | 869 | inode->i_size = 6; |
@@ -771,7 +876,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
771 | { | 876 | { |
772 | struct inode *inode; | 877 | struct inode *inode; |
773 | struct btrfs_trans_handle *trans; | 878 | struct btrfs_trans_handle *trans; |
774 | struct btrfs_root *root = btrfs_sb(dir->i_sb); | 879 | struct btrfs_root *root = BTRFS_I(dir)->root; |
775 | int err = 0; | 880 | int err = 0; |
776 | int drop_on_err = 0; | 881 | int drop_on_err = 0; |
777 | 882 | ||
@@ -910,7 +1015,7 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | |||
910 | u64 extent_end = 0; | 1015 | u64 extent_end = 0; |
911 | u64 objectid = inode->i_ino; | 1016 | u64 objectid = inode->i_ino; |
912 | struct btrfs_path *path; | 1017 | struct btrfs_path *path; |
913 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | 1018 | struct btrfs_root *root = BTRFS_I(inode)->root; |
914 | struct btrfs_trans_handle *trans = NULL; | 1019 | struct btrfs_trans_handle *trans = NULL; |
915 | struct btrfs_file_extent_item *item; | 1020 | struct btrfs_file_extent_item *item; |
916 | struct btrfs_leaf *leaf; | 1021 | struct btrfs_leaf *leaf; |
@@ -999,7 +1104,7 @@ static int btrfs_get_block(struct inode *inode, sector_t iblock, | |||
999 | struct buffer_head *result, int create) | 1104 | struct buffer_head *result, int create) |
1000 | { | 1105 | { |
1001 | int err; | 1106 | int err; |
1002 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | 1107 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1003 | mutex_lock(&root->fs_info->fs_mutex); | 1108 | mutex_lock(&root->fs_info->fs_mutex); |
1004 | err = btrfs_get_block_lock(inode, iblock, result, create); | 1109 | err = btrfs_get_block_lock(inode, iblock, result, create); |
1005 | // err = btrfs_get_block_inline(inode, iblock, result, create); | 1110 | // err = btrfs_get_block_inline(inode, iblock, result, create); |
@@ -1041,7 +1146,7 @@ static int btrfs_writepage(struct page *page, struct writeback_control *wbc) | |||
1041 | 1146 | ||
1042 | static void btrfs_truncate(struct inode *inode) | 1147 | static void btrfs_truncate(struct inode *inode) |
1043 | { | 1148 | { |
1044 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | 1149 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1045 | int ret; | 1150 | int ret; |
1046 | struct btrfs_trans_handle *trans; | 1151 | struct btrfs_trans_handle *trans; |
1047 | 1152 | ||
@@ -1208,7 +1313,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1208 | int err = 0; | 1313 | int err = 0; |
1209 | int ret = 0; | 1314 | int ret = 0; |
1210 | struct inode *inode = file->f_path.dentry->d_inode; | 1315 | struct inode *inode = file->f_path.dentry->d_inode; |
1211 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | 1316 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1212 | struct page *pages[1]; | 1317 | struct page *pages[1]; |
1213 | 1318 | ||
1214 | if (file->f_flags & O_DIRECT) | 1319 | if (file->f_flags & O_DIRECT) |
@@ -1365,7 +1470,7 @@ static ssize_t btrfs_file_inline_write(struct file *file, | |||
1365 | int err = 0; | 1470 | int err = 0; |
1366 | int ret = 0; | 1471 | int ret = 0; |
1367 | struct inode *inode = file->f_path.dentry->d_inode; | 1472 | struct inode *inode = file->f_path.dentry->d_inode; |
1368 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | 1473 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1369 | unsigned long page_index; | 1474 | unsigned long page_index; |
1370 | 1475 | ||
1371 | if (file->f_flags & O_DIRECT) | 1476 | if (file->f_flags & O_DIRECT) |
@@ -1432,13 +1537,14 @@ static int btrfs_read_actor(read_descriptor_t *desc, struct page *page, | |||
1432 | { | 1537 | { |
1433 | char *kaddr; | 1538 | char *kaddr; |
1434 | unsigned long left, count = desc->count; | 1539 | unsigned long left, count = desc->count; |
1540 | struct inode *inode = page->mapping->host; | ||
1435 | 1541 | ||
1436 | if (size > count) | 1542 | if (size > count) |
1437 | size = count; | 1543 | size = count; |
1438 | 1544 | ||
1439 | if (!PageChecked(page)) { | 1545 | if (!PageChecked(page)) { |
1440 | /* FIXME, do it per block */ | 1546 | /* FIXME, do it per block */ |
1441 | struct btrfs_root *root = btrfs_sb(page->mapping->host->i_sb); | 1547 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1442 | int ret = btrfs_csum_verify_file_block(root, | 1548 | int ret = btrfs_csum_verify_file_block(root, |
1443 | page->mapping->host->i_ino, | 1549 | page->mapping->host->i_ino, |
1444 | page->index << PAGE_CACHE_SHIFT, | 1550 | page->index << PAGE_CACHE_SHIFT, |
@@ -1662,6 +1768,10 @@ static struct inode_operations btrfs_dir_inode_operations = { | |||
1662 | .rmdir = btrfs_rmdir, | 1768 | .rmdir = btrfs_rmdir, |
1663 | }; | 1769 | }; |
1664 | 1770 | ||
1771 | static struct inode_operations btrfs_dir_ro_inode_operations = { | ||
1772 | .lookup = btrfs_lookup, | ||
1773 | }; | ||
1774 | |||
1665 | static struct file_operations btrfs_dir_file_operations = { | 1775 | static struct file_operations btrfs_dir_file_operations = { |
1666 | .llseek = generic_file_llseek, | 1776 | .llseek = generic_file_llseek, |
1667 | .read = generic_read_dir, | 1777 | .read = generic_read_dir, |
@@ -1697,13 +1807,21 @@ static int __init init_btrfs_fs(void) | |||
1697 | err = init_inodecache(); | 1807 | err = init_inodecache(); |
1698 | if (err) | 1808 | if (err) |
1699 | return err; | 1809 | return err; |
1810 | kset_set_kset_s(&btrfs_subsys, fs_subsys); | ||
1811 | err = subsystem_register(&btrfs_subsys); | ||
1812 | if (err) | ||
1813 | goto out; | ||
1700 | return register_filesystem(&btrfs_fs_type); | 1814 | return register_filesystem(&btrfs_fs_type); |
1815 | out: | ||
1816 | destroy_inodecache(); | ||
1817 | return err; | ||
1701 | } | 1818 | } |
1702 | 1819 | ||
1703 | static void __exit exit_btrfs_fs(void) | 1820 | static void __exit exit_btrfs_fs(void) |
1704 | { | 1821 | { |
1705 | destroy_inodecache(); | 1822 | destroy_inodecache(); |
1706 | unregister_filesystem(&btrfs_fs_type); | 1823 | unregister_filesystem(&btrfs_fs_type); |
1824 | subsystem_unregister(&btrfs_subsys); | ||
1707 | printk("btrfs unloaded\n"); | 1825 | printk("btrfs unloaded\n"); |
1708 | } | 1826 | } |
1709 | 1827 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 2b0f98c92123..20d84bd03223 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -52,6 +52,8 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | |||
52 | kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); | 52 | kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); |
53 | int ret; | 53 | int ret; |
54 | 54 | ||
55 | /* FIXME, use the right root */ | ||
56 | root = root->fs_info->fs_root; | ||
55 | mutex_lock(&root->fs_info->trans_mutex); | 57 | mutex_lock(&root->fs_info->trans_mutex); |
56 | ret = join_transaction(root); | 58 | ret = join_transaction(root); |
57 | BUG_ON(ret); | 59 | BUG_ON(ret); |
@@ -69,6 +71,10 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
69 | struct btrfs_root *root) | 71 | struct btrfs_root *root) |
70 | { | 72 | { |
71 | struct btrfs_transaction *cur_trans; | 73 | struct btrfs_transaction *cur_trans; |
74 | |||
75 | /* FIXME, use the right root */ | ||
76 | root = root->fs_info->fs_root; | ||
77 | |||
72 | WARN_ON(trans->magic != TRANS_MAGIC); | 78 | WARN_ON(trans->magic != TRANS_MAGIC); |
73 | WARN_ON(trans->magic2 != TRANS_MAGIC); | 79 | WARN_ON(trans->magic2 != TRANS_MAGIC); |
74 | mutex_lock(&root->fs_info->trans_mutex); | 80 | mutex_lock(&root->fs_info->trans_mutex); |
@@ -148,6 +154,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
148 | struct btrfs_transaction *cur_trans; | 154 | struct btrfs_transaction *cur_trans; |
149 | DEFINE_WAIT(wait); | 155 | DEFINE_WAIT(wait); |
150 | 156 | ||
157 | /* FIXME, use the right root */ | ||
158 | root = root->fs_info->fs_root; | ||
159 | |||
151 | mutex_lock(&root->fs_info->trans_mutex); | 160 | mutex_lock(&root->fs_info->trans_mutex); |
152 | if (trans->transaction->in_commit) { | 161 | if (trans->transaction->in_commit) { |
153 | printk("already in commit!, waiting\n"); | 162 | printk("already in commit!, waiting\n"); |