diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-19 15:36:27 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-19 15:36:27 -0400 |
commit | 7e38180e207c8707691c12395e990a5d583c5e71 (patch) | |
tree | 50fc0973873f7bc9455a1faf536a5a5b4681fe56 /fs | |
parent | 236454dfffb64a95ee01c50a215153f5de61c475 (diff) |
Btrfs: directory inode index is back
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/TODO | 4 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 58 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 204 | ||||
-rw-r--r-- | fs/btrfs/super.c | 302 |
4 files changed, 206 insertions, 362 deletions
diff --git a/fs/btrfs/TODO b/fs/btrfs/TODO index 1c3acfcf146e..8d7e5a3ed629 100644 --- a/fs/btrfs/TODO +++ b/fs/btrfs/TODO | |||
@@ -1,12 +1,12 @@ | |||
1 | * cleanup, add more error checking, get rid of BUG_ONs | 1 | * cleanup, add more error checking, get rid of BUG_ONs |
2 | * Fix ENOSPC handling | 2 | * Fix ENOSPC handling |
3 | * Add block mapping tree (simple dm layer) | ||
4 | * Make allocator smarter | 3 | * Make allocator smarter |
5 | * add a block group to struct inode | 4 | * add a block group to struct inode |
6 | * Make sure nobh stuff is working properly for cows | ||
7 | * Do actual block accounting | 5 | * Do actual block accounting |
8 | * Check compat and incompat flags on the inode | 6 | * Check compat and incompat flags on the inode |
9 | * Get rid of struct ctree_path, limiting tree levels held at one time | 7 | * Get rid of struct ctree_path, limiting tree levels held at one time |
8 | * Add generation number to key pointer in nodes | ||
9 | * Add parent pointer back to extent map. | ||
10 | * Release | 10 | * Release |
11 | * Do real tree locking | 11 | * Do real tree locking |
12 | * Add extent mirroring (backup copies of blocks) | 12 | * Add extent mirroring (backup copies of blocks) |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index f1800008be34..d628a3b9441c 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -185,11 +185,6 @@ struct btrfs_inode_item { | |||
185 | struct btrfs_inode_timespec otime; | 185 | struct btrfs_inode_timespec otime; |
186 | } __attribute__ ((__packed__)); | 186 | } __attribute__ ((__packed__)); |
187 | 187 | ||
188 | /* inline data is just a blob of bytes */ | ||
189 | struct btrfs_inline_data_item { | ||
190 | u8 data; | ||
191 | } __attribute__ ((__packed__)); | ||
192 | |||
193 | struct btrfs_dir_item { | 188 | struct btrfs_dir_item { |
194 | struct btrfs_disk_key location; | 189 | struct btrfs_disk_key location; |
195 | __le16 flags; | 190 | __le16 flags; |
@@ -293,9 +288,6 @@ struct btrfs_root { | |||
293 | #define BTRFS_KEY_TYPE_MASK (((u32)BTRFS_KEY_TYPE_MAX - 1) << \ | 288 | #define BTRFS_KEY_TYPE_MASK (((u32)BTRFS_KEY_TYPE_MAX - 1) << \ |
294 | BTRFS_KEY_TYPE_SHIFT) | 289 | BTRFS_KEY_TYPE_SHIFT) |
295 | 290 | ||
296 | #define BTRFS_KEY_OVERFLOW_MAX 128 | ||
297 | #define BTRFS_KEY_OVERFLOW_MASK ((u32)BTRFS_KEY_OVERFLOW_MAX - 1) | ||
298 | |||
299 | /* | 291 | /* |
300 | * inode items have the data typically returned from stat and store other | 292 | * inode items have the data typically returned from stat and store other |
301 | * info about object characteristics. There is one for every file and dir in | 293 | * info about object characteristics. There is one for every file and dir in |
@@ -621,31 +613,6 @@ static inline void btrfs_set_key_type(struct btrfs_key *key, u32 val) | |||
621 | key->flags = (key->flags & ~(BTRFS_KEY_TYPE_MASK)) | val; | 613 | key->flags = (key->flags & ~(BTRFS_KEY_TYPE_MASK)) | val; |
622 | } | 614 | } |
623 | 615 | ||
624 | static inline u32 btrfs_key_overflow(struct btrfs_key *key) | ||
625 | { | ||
626 | return key->flags & BTRFS_KEY_OVERFLOW_MASK; | ||
627 | } | ||
628 | |||
629 | static inline void btrfs_set_key_overflow(struct btrfs_key *key, u32 over) | ||
630 | { | ||
631 | BUG_ON(over >= BTRFS_KEY_OVERFLOW_MAX); | ||
632 | key->flags = (key->flags & ~BTRFS_KEY_OVERFLOW_MASK) | over; | ||
633 | } | ||
634 | |||
635 | static inline u32 btrfs_disk_key_overflow(struct btrfs_disk_key *key) | ||
636 | { | ||
637 | return le32_to_cpu(key->flags) & BTRFS_KEY_OVERFLOW_MASK; | ||
638 | } | ||
639 | |||
640 | static inline void btrfs_set_disk_key_overflow(struct btrfs_disk_key *key, | ||
641 | u32 over) | ||
642 | { | ||
643 | u32 flags = btrfs_disk_key_flags(key); | ||
644 | BUG_ON(over >= BTRFS_KEY_OVERFLOW_MAX); | ||
645 | flags = (flags & ~BTRFS_KEY_OVERFLOW_MASK) | over; | ||
646 | btrfs_set_disk_key_flags(key, flags); | ||
647 | } | ||
648 | |||
649 | static inline u64 btrfs_header_blocknr(struct btrfs_header *h) | 616 | static inline u64 btrfs_header_blocknr(struct btrfs_header *h) |
650 | { | 617 | { |
651 | return le64_to_cpu(h->blocknr); | 618 | return le64_to_cpu(h->blocknr); |
@@ -1079,15 +1046,24 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct | |||
1079 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 1046 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
1080 | *root, const char *name, int name_len, u64 dir, | 1047 | *root, const char *name, int name_len, u64 dir, |
1081 | struct btrfs_key *location, u8 type); | 1048 | struct btrfs_key *location, u8 type); |
1082 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 1049 | struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, |
1083 | *root, struct btrfs_path *path, u64 dir, | 1050 | struct btrfs_root *root, |
1084 | const char *name, int name_len, int mod); | 1051 | struct btrfs_path *path, u64 dir, |
1085 | int btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, | 1052 | const char *name, int name_len, |
1086 | struct btrfs_root *root, | 1053 | int mod); |
1087 | struct btrfs_path *path, u64 dir, | 1054 | struct btrfs_dir_item * |
1088 | u64 objectid, int mod); | 1055 | btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, |
1089 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, | 1056 | struct btrfs_root *root, |
1057 | struct btrfs_path *path, u64 dir, | ||
1058 | u64 objectid, const char *name, int name_len, | ||
1059 | int mod); | ||
1060 | struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, | ||
1061 | struct btrfs_path *path, | ||
1090 | const char *name, int name_len); | 1062 | const char *name, int name_len); |
1063 | int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, | ||
1064 | struct btrfs_root *root, | ||
1065 | struct btrfs_path *path, | ||
1066 | struct btrfs_dir_item *di); | ||
1091 | /* inode-map.c */ | 1067 | /* inode-map.c */ |
1092 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | 1068 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, |
1093 | struct btrfs_root *fs_root, | 1069 | struct btrfs_root *fs_root, |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index a43deb726486..7a7e9846860a 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -4,24 +4,31 @@ | |||
4 | #include "hash.h" | 4 | #include "hash.h" |
5 | #include "transaction.h" | 5 | #include "transaction.h" |
6 | 6 | ||
7 | int insert_with_overflow(struct btrfs_trans_handle *trans, struct btrfs_root | 7 | struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle *trans, |
8 | *root, struct btrfs_path *path, struct btrfs_key | 8 | struct btrfs_root *root, |
9 | *cpu_key, u32 data_size) | 9 | struct btrfs_path *path, |
10 | struct btrfs_key *cpu_key, | ||
11 | u32 data_size) | ||
10 | { | 12 | { |
11 | int overflow; | ||
12 | int ret; | 13 | int ret; |
14 | char *ptr; | ||
15 | struct btrfs_item *item; | ||
16 | struct btrfs_leaf *leaf; | ||
13 | 17 | ||
14 | ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); | 18 | ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); |
15 | overflow = btrfs_key_overflow(cpu_key); | 19 | if (ret == -EEXIST) { |
16 | 20 | ret = btrfs_extend_item(trans, root, path, data_size); | |
17 | while(ret == -EEXIST && overflow < BTRFS_KEY_OVERFLOW_MAX) { | 21 | WARN_ON(ret > 0); |
18 | overflow++; | 22 | if (ret) |
19 | btrfs_set_key_overflow(cpu_key, overflow); | 23 | return ERR_PTR(ret); |
20 | btrfs_release_path(root, path); | ||
21 | ret = btrfs_insert_empty_item(trans, root, path, cpu_key, | ||
22 | data_size); | ||
23 | } | 24 | } |
24 | return ret; | 25 | WARN_ON(ret > 0); |
26 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
27 | item = leaf->items + path->slots[0]; | ||
28 | ptr = btrfs_item_ptr(leaf, path->slots[0], char); | ||
29 | BUG_ON(data_size > btrfs_item_size(item)); | ||
30 | ptr += btrfs_item_size(item) - data_size; | ||
31 | return (struct btrfs_dir_item *)ptr; | ||
25 | } | 32 | } |
26 | 33 | ||
27 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 34 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
@@ -43,13 +50,12 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
43 | path = btrfs_alloc_path(); | 50 | path = btrfs_alloc_path(); |
44 | btrfs_init_path(path); | 51 | btrfs_init_path(path); |
45 | data_size = sizeof(*dir_item) + name_len; | 52 | data_size = sizeof(*dir_item) + name_len; |
46 | ret = insert_with_overflow(trans, root, path, &key, data_size); | 53 | dir_item = insert_with_overflow(trans, root, path, &key, data_size); |
47 | if (ret) | 54 | if (IS_ERR(dir_item)) { |
55 | ret = PTR_ERR(dir_item); | ||
48 | goto out; | 56 | goto out; |
57 | } | ||
49 | 58 | ||
50 | dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
51 | path->slots[0], | ||
52 | struct btrfs_dir_item); | ||
53 | btrfs_cpu_key_to_disk(&dir_item->location, location); | 59 | btrfs_cpu_key_to_disk(&dir_item->location, location); |
54 | btrfs_set_dir_type(dir_item, type); | 60 | btrfs_set_dir_type(dir_item, type); |
55 | btrfs_set_dir_flags(dir_item, 0); | 61 | btrfs_set_dir_flags(dir_item, 0); |
@@ -58,15 +64,39 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
58 | 64 | ||
59 | btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); | 65 | btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); |
60 | btrfs_mark_buffer_dirty(path->nodes[0]); | 66 | btrfs_mark_buffer_dirty(path->nodes[0]); |
61 | out: | 67 | |
68 | /* FIXME, use some real flag for selecting the extra index */ | ||
69 | if (root == root->fs_info->tree_root) { | ||
70 | ret = 0; | ||
71 | goto out; | ||
72 | } | ||
73 | |||
62 | btrfs_release_path(root, path); | 74 | btrfs_release_path(root, path); |
75 | |||
76 | btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); | ||
77 | key.offset = location->objectid; | ||
78 | dir_item = insert_with_overflow(trans, root, path, &key, data_size); | ||
79 | if (IS_ERR(dir_item)) { | ||
80 | ret = PTR_ERR(dir_item); | ||
81 | goto out; | ||
82 | } | ||
83 | btrfs_cpu_key_to_disk(&dir_item->location, location); | ||
84 | btrfs_set_dir_type(dir_item, type); | ||
85 | btrfs_set_dir_flags(dir_item, 0); | ||
86 | btrfs_set_dir_name_len(dir_item, name_len); | ||
87 | name_ptr = (char *)(dir_item + 1); | ||
88 | btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); | ||
89 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
90 | out: | ||
63 | btrfs_free_path(path); | 91 | btrfs_free_path(path); |
64 | return ret; | 92 | return ret; |
65 | } | 93 | } |
66 | 94 | ||
67 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 95 | struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, |
68 | *root, struct btrfs_path *path, u64 dir, | 96 | struct btrfs_root *root, |
69 | const char *name, int name_len, int mod) | 97 | struct btrfs_path *path, u64 dir, |
98 | const char *name, int name_len, | ||
99 | int mod) | ||
70 | { | 100 | { |
71 | int ret; | 101 | int ret; |
72 | struct btrfs_key key; | 102 | struct btrfs_key key; |
@@ -74,57 +104,111 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
74 | int cow = mod != 0; | 104 | int cow = mod != 0; |
75 | struct btrfs_disk_key *found_key; | 105 | struct btrfs_disk_key *found_key; |
76 | struct btrfs_leaf *leaf; | 106 | struct btrfs_leaf *leaf; |
77 | u32 overflow; | ||
78 | 107 | ||
79 | key.objectid = dir; | 108 | key.objectid = dir; |
80 | key.flags = 0; | 109 | key.flags = 0; |
81 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); | 110 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); |
82 | // btrfs_set_key_overflow(&key, BTRFS_KEY_OVERFLOW_MAX - 1); | ||
83 | ret = btrfs_name_hash(name, name_len, &key.offset); | 111 | ret = btrfs_name_hash(name, name_len, &key.offset); |
84 | BUG_ON(ret); | 112 | BUG_ON(ret); |
85 | while(1) { | 113 | ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); |
86 | ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); | 114 | if (ret < 0) |
87 | if (ret < 0) | 115 | return ERR_PTR(ret); |
88 | return ret; | 116 | if (ret > 0) { |
89 | if (ret > 0) { | 117 | if (path->slots[0] == 0) |
90 | if (path->slots[0] == 0) | 118 | return NULL; |
91 | return 1; | 119 | path->slots[0]--; |
92 | path->slots[0]--; | ||
93 | } | ||
94 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
95 | found_key = &leaf->items[path->slots[0]].key; | ||
96 | |||
97 | if (btrfs_disk_key_objectid(found_key) != dir || | ||
98 | btrfs_disk_key_type(found_key) != BTRFS_DIR_ITEM_KEY || | ||
99 | btrfs_disk_key_offset(found_key) != key.offset) | ||
100 | return 1; | ||
101 | |||
102 | if (btrfs_match_dir_item_name(root, path, name, name_len)) | ||
103 | return 0; | ||
104 | |||
105 | overflow = btrfs_disk_key_overflow(found_key); | ||
106 | if (overflow == 0) | ||
107 | return 1; | ||
108 | btrfs_set_key_overflow(&key, overflow - 1); | ||
109 | btrfs_release_path(root, path); | ||
110 | } | 120 | } |
111 | return 1; | 121 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
122 | found_key = &leaf->items[path->slots[0]].key; | ||
123 | |||
124 | if (btrfs_disk_key_objectid(found_key) != dir || | ||
125 | btrfs_disk_key_type(found_key) != BTRFS_DIR_ITEM_KEY || | ||
126 | btrfs_disk_key_offset(found_key) != key.offset) | ||
127 | return NULL; | ||
128 | |||
129 | return btrfs_match_dir_item_name(root, path, name, name_len); | ||
112 | } | 130 | } |
113 | 131 | ||
114 | int btrfs_match_dir_item_name(struct btrfs_root *root, | 132 | struct btrfs_dir_item * |
133 | btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, | ||
134 | struct btrfs_root *root, | ||
135 | struct btrfs_path *path, u64 dir, | ||
136 | u64 objectid, const char *name, int name_len, | ||
137 | int mod) | ||
138 | { | ||
139 | int ret; | ||
140 | struct btrfs_key key; | ||
141 | int ins_len = mod < 0 ? -1 : 0; | ||
142 | int cow = mod != 0; | ||
143 | |||
144 | key.objectid = dir; | ||
145 | key.flags = 0; | ||
146 | btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); | ||
147 | key.offset = objectid; | ||
148 | |||
149 | ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); | ||
150 | if (ret < 0) | ||
151 | return ERR_PTR(ret); | ||
152 | if (ret > 0) | ||
153 | return ERR_PTR(-ENOENT); | ||
154 | return btrfs_match_dir_item_name(root, path, name, name_len); | ||
155 | } | ||
156 | |||
157 | struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, | ||
115 | struct btrfs_path *path, | 158 | struct btrfs_path *path, |
116 | const char *name, int name_len) | 159 | const char *name, int name_len) |
117 | { | 160 | { |
118 | struct btrfs_dir_item *dir_item; | 161 | struct btrfs_dir_item *dir_item; |
119 | char *name_ptr; | 162 | char *name_ptr; |
163 | u32 total_len; | ||
164 | u32 cur = 0; | ||
165 | u32 this_len; | ||
166 | struct btrfs_leaf *leaf; | ||
120 | 167 | ||
121 | dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | 168 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
122 | path->slots[0], | 169 | dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); |
123 | struct btrfs_dir_item); | 170 | total_len = btrfs_item_size(leaf->items + path->slots[0]); |
124 | if (btrfs_dir_name_len(dir_item) != name_len) | 171 | while(cur < total_len) { |
125 | return 0; | 172 | this_len = sizeof(*dir_item) + btrfs_dir_name_len(dir_item); |
126 | name_ptr = (char *)(dir_item + 1); | 173 | name_ptr = (char *)(dir_item + 1); |
127 | if (memcmp(name_ptr, name, name_len)) | 174 | |
128 | return 0; | 175 | if (btrfs_dir_name_len(dir_item) == name_len && |
129 | return 1; | 176 | memcmp(name_ptr, name, name_len) == 0) |
177 | return dir_item; | ||
178 | |||
179 | cur += this_len; | ||
180 | dir_item = (struct btrfs_dir_item *)((char *)dir_item + | ||
181 | this_len); | ||
182 | } | ||
183 | return NULL; | ||
130 | } | 184 | } |
185 | |||
186 | int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, | ||
187 | struct btrfs_root *root, | ||
188 | struct btrfs_path *path, | ||
189 | struct btrfs_dir_item *di) | ||
190 | { | ||
191 | |||
192 | struct btrfs_leaf *leaf; | ||
193 | u32 sub_item_len; | ||
194 | u32 item_len; | ||
195 | int ret; | ||
196 | |||
197 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
198 | sub_item_len = sizeof(*di) + btrfs_dir_name_len(di); | ||
199 | item_len = btrfs_item_size(leaf->items + path->slots[0]); | ||
200 | if (sub_item_len == btrfs_item_size(leaf->items + path->slots[0])) { | ||
201 | ret = btrfs_del_item(trans, root, path); | ||
202 | BUG_ON(ret); | ||
203 | } else { | ||
204 | char *ptr = (char *)di; | ||
205 | char *start = btrfs_item_ptr(leaf, path->slots[0], char); | ||
206 | btrfs_memmove(root, leaf, ptr, ptr + sub_item_len, | ||
207 | item_len - (ptr + sub_item_len - start)); | ||
208 | ret = btrfs_truncate_item(trans, root, path, | ||
209 | item_len - sub_item_len); | ||
210 | BUG_ON(ret); | ||
211 | } | ||
212 | return 0; | ||
213 | } | ||
214 | |||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 1b286bb26f12..dff2db0d1dc2 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -127,32 +127,43 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | |||
127 | struct btrfs_path *path; | 127 | struct btrfs_path *path; |
128 | const char *name = dentry->d_name.name; | 128 | const char *name = dentry->d_name.name; |
129 | int name_len = dentry->d_name.len; | 129 | int name_len = dentry->d_name.len; |
130 | int ret; | 130 | int ret = 0; |
131 | u64 objectid; | 131 | u64 objectid; |
132 | struct btrfs_dir_item *di; | 132 | struct btrfs_dir_item *di; |
133 | 133 | ||
134 | path = btrfs_alloc_path(); | 134 | path = btrfs_alloc_path(); |
135 | BUG_ON(!path); | 135 | BUG_ON(!path); |
136 | btrfs_init_path(path); | 136 | btrfs_init_path(path); |
137 | ret = btrfs_lookup_dir_item(trans, root, path, dir->i_ino, | 137 | di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino, |
138 | name, name_len, -1); | 138 | name, name_len, -1); |
139 | if (ret < 0) | 139 | if (IS_ERR(di)) { |
140 | ret = PTR_ERR(di); | ||
140 | goto err; | 141 | goto err; |
141 | if (ret > 0) { | 142 | } |
143 | if (!di) { | ||
142 | ret = -ENOENT; | 144 | ret = -ENOENT; |
143 | goto err; | 145 | goto err; |
144 | } | 146 | } |
145 | di = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | ||
146 | struct btrfs_dir_item); | ||
147 | objectid = btrfs_disk_key_objectid(&di->location); | 147 | objectid = btrfs_disk_key_objectid(&di->location); |
148 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | ||
149 | BUG_ON(ret); | ||
150 | btrfs_release_path(root, path); | ||
148 | 151 | ||
149 | ret = btrfs_del_item(trans, root, path); | 152 | di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, |
153 | objectid, name, name_len, -1); | ||
154 | if (IS_ERR(di)) { | ||
155 | ret = PTR_ERR(di); | ||
156 | goto err; | ||
157 | } | ||
158 | if (!di) { | ||
159 | ret = -ENOENT; | ||
160 | goto err; | ||
161 | } | ||
162 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | ||
150 | BUG_ON(ret); | 163 | BUG_ON(ret); |
151 | 164 | ||
152 | btrfs_release_path(root, path); | ||
153 | dentry->d_inode->i_ctime = dir->i_ctime; | 165 | dentry->d_inode->i_ctime = dir->i_ctime; |
154 | err: | 166 | err: |
155 | btrfs_release_path(root, path); | ||
156 | btrfs_free_path(path); | 167 | btrfs_free_path(path); |
157 | if (ret == 0) { | 168 | if (ret == 0) { |
158 | inode_dec_link_count(dentry->d_inode); | 169 | inode_dec_link_count(dentry->d_inode); |
@@ -388,15 +399,13 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, | |||
388 | path = btrfs_alloc_path(); | 399 | path = btrfs_alloc_path(); |
389 | BUG_ON(!path); | 400 | BUG_ON(!path); |
390 | btrfs_init_path(path); | 401 | btrfs_init_path(path); |
391 | ret = btrfs_lookup_dir_item(NULL, root, path, dir->i_ino, name, | 402 | di = btrfs_lookup_dir_item(NULL, root, path, dir->i_ino, name, |
392 | namelen, 0); | 403 | namelen, 0); |
393 | if (ret || !btrfs_match_dir_item_name(root, path, name, namelen)) { | 404 | if (!di || IS_ERR(di)) { |
394 | location->objectid = 0; | 405 | location->objectid = 0; |
395 | ret = 0; | 406 | ret = 0; |
396 | goto out; | 407 | goto out; |
397 | } | 408 | } |
398 | di = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | ||
399 | struct btrfs_dir_item); | ||
400 | btrfs_disk_key_to_cpu(location, &di->location); | 409 | btrfs_disk_key_to_cpu(location, &di->location); |
401 | out: | 410 | out: |
402 | btrfs_release_path(root, path); | 411 | btrfs_release_path(root, path); |
@@ -523,7 +532,10 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
523 | int advance; | 532 | int advance; |
524 | unsigned char d_type = DT_UNKNOWN; | 533 | unsigned char d_type = DT_UNKNOWN; |
525 | int over = 0; | 534 | int over = 0; |
526 | int key_type = BTRFS_DIR_ITEM_KEY; | 535 | u32 di_cur; |
536 | u32 di_total; | ||
537 | u32 di_len; | ||
538 | int key_type = BTRFS_DIR_INDEX_KEY; | ||
527 | 539 | ||
528 | /* FIXME, use a real flag for deciding about the key type */ | 540 | /* FIXME, use a real flag for deciding about the key type */ |
529 | if (root->fs_info->tree_root == root) | 541 | if (root->fs_info->tree_root == root) |
@@ -567,12 +579,20 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
567 | filp->f_pos = btrfs_disk_key_offset(&item->key); | 579 | filp->f_pos = btrfs_disk_key_offset(&item->key); |
568 | advance = 1; | 580 | advance = 1; |
569 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); | 581 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); |
570 | over = filldir(dirent, (const char *)(di + 1), | 582 | di_cur = 0; |
571 | btrfs_dir_name_len(di), | 583 | di_total = btrfs_item_size(leaf->items + slot); |
572 | btrfs_disk_key_offset(&item->key), | 584 | while(di_cur < di_total) { |
573 | btrfs_disk_key_objectid(&di->location), d_type); | 585 | over = filldir(dirent, (const char *)(di + 1), |
574 | if (over) | 586 | btrfs_dir_name_len(di), |
575 | goto nopos; | 587 | btrfs_disk_key_offset(&item->key), |
588 | btrfs_disk_key_objectid(&di->location), | ||
589 | d_type); | ||
590 | if (over) | ||
591 | goto nopos; | ||
592 | di_len = btrfs_dir_name_len(di) + sizeof(*di); | ||
593 | di_cur += di_len; | ||
594 | di = (struct btrfs_dir_item *)((char *)di + di_len); | ||
595 | } | ||
576 | } | 596 | } |
577 | filp->f_pos++; | 597 | filp->f_pos++; |
578 | nopos: | 598 | nopos: |
@@ -935,75 +955,6 @@ printk("btrfs sync_fs\n"); | |||
935 | return 0; | 955 | return 0; |
936 | } | 956 | } |
937 | 957 | ||
938 | #if 0 | ||
939 | static int btrfs_get_block_inline(struct inode *inode, sector_t iblock, | ||
940 | struct buffer_head *result, int create) | ||
941 | { | ||
942 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | ||
943 | struct btrfs_path *path; | ||
944 | struct btrfs_key key; | ||
945 | struct btrfs_leaf *leaf; | ||
946 | int num_bytes = result->b_size; | ||
947 | int item_size; | ||
948 | int ret; | ||
949 | u64 pos; | ||
950 | char *ptr; | ||
951 | int copy_size; | ||
952 | int err = 0; | ||
953 | char *safe_ptr; | ||
954 | char *data_ptr; | ||
955 | |||
956 | path = btrfs_alloc_path(); | ||
957 | BUG_ON(!path); | ||
958 | |||
959 | WARN_ON(create); | ||
960 | if (create) { | ||
961 | return 0; | ||
962 | } | ||
963 | pos = iblock << inode->i_blkbits; | ||
964 | key.objectid = inode->i_ino; | ||
965 | key.flags = 0; | ||
966 | btrfs_set_key_type(&key, BTRFS_INLINE_DATA_KEY); | ||
967 | ptr = kmap(result->b_page); | ||
968 | safe_ptr = ptr; | ||
969 | ptr += (pos & (PAGE_CACHE_SIZE -1)); | ||
970 | again: | ||
971 | key.offset = pos; | ||
972 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
973 | if (ret) { | ||
974 | if (ret < 0) | ||
975 | err = ret; | ||
976 | else | ||
977 | err = 0; | ||
978 | goto out; | ||
979 | } | ||
980 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
981 | item_size = btrfs_item_size(leaf->items + path->slots[0]); | ||
982 | copy_size = min(num_bytes, item_size); | ||
983 | data_ptr = btrfs_item_ptr(leaf, path->slots[0], char); | ||
984 | WARN_ON(safe_ptr + PAGE_CACHE_SIZE < ptr + copy_size); | ||
985 | memcpy(ptr, data_ptr, copy_size); | ||
986 | pos += copy_size; | ||
987 | num_bytes -= copy_size; | ||
988 | WARN_ON(num_bytes < 0); | ||
989 | ptr += copy_size; | ||
990 | btrfs_release_path(root, path); | ||
991 | if (num_bytes != 0) { | ||
992 | if (pos >= i_size_read(inode)) | ||
993 | memset(ptr, 0, num_bytes); | ||
994 | else | ||
995 | goto again; | ||
996 | } | ||
997 | set_buffer_uptodate(result); | ||
998 | map_bh(result, inode->i_sb, 0); | ||
999 | err = 0; | ||
1000 | out: | ||
1001 | btrfs_free_path(path); | ||
1002 | kunmap(result->b_page); | ||
1003 | return err; | ||
1004 | } | ||
1005 | #endif | ||
1006 | |||
1007 | static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | 958 | static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, |
1008 | struct buffer_head *result, int create) | 959 | struct buffer_head *result, int create) |
1009 | { | 960 | { |
@@ -1907,174 +1858,6 @@ out: | |||
1907 | return num_written ? num_written : err; | 1858 | return num_written ? num_written : err; |
1908 | } | 1859 | } |
1909 | 1860 | ||
1910 | #if 0 | ||
1911 | static ssize_t inline_one_page(struct btrfs_root *root, struct inode *inode, | ||
1912 | struct page *page, loff_t pos, | ||
1913 | size_t offset, size_t write_bytes) | ||
1914 | { | ||
1915 | struct btrfs_path *path; | ||
1916 | struct btrfs_trans_handle *trans; | ||
1917 | struct btrfs_key key; | ||
1918 | struct btrfs_leaf *leaf; | ||
1919 | struct btrfs_key found_key; | ||
1920 | int ret; | ||
1921 | size_t copy_size = 0; | ||
1922 | char *dst = NULL; | ||
1923 | int err = 0; | ||
1924 | size_t num_written = 0; | ||
1925 | |||
1926 | path = btrfs_alloc_path(); | ||
1927 | BUG_ON(!path); | ||
1928 | mutex_lock(&root->fs_info->fs_mutex); | ||
1929 | trans = btrfs_start_transaction(root, 1); | ||
1930 | key.objectid = inode->i_ino; | ||
1931 | key.flags = 0; | ||
1932 | btrfs_set_key_type(&key, BTRFS_INLINE_DATA_KEY); | ||
1933 | |||
1934 | again: | ||
1935 | key.offset = pos; | ||
1936 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); | ||
1937 | if (ret < 0) { | ||
1938 | err = ret; | ||
1939 | goto out; | ||
1940 | } | ||
1941 | if (ret == 0) { | ||
1942 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
1943 | btrfs_disk_key_to_cpu(&found_key, | ||
1944 | &leaf->items[path->slots[0]].key); | ||
1945 | copy_size = btrfs_item_size(leaf->items + path->slots[0]); | ||
1946 | dst = btrfs_item_ptr(leaf, path->slots[0], char); | ||
1947 | copy_size = min(write_bytes, copy_size); | ||
1948 | goto copyit; | ||
1949 | } else { | ||
1950 | int slot = path->slots[0]; | ||
1951 | if (slot > 0) { | ||
1952 | slot--; | ||
1953 | } | ||
1954 | // FIXME find max key | ||
1955 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
1956 | btrfs_disk_key_to_cpu(&found_key, | ||
1957 | &leaf->items[slot].key); | ||
1958 | if (found_key.objectid != inode->i_ino) | ||
1959 | goto insert; | ||
1960 | if (btrfs_key_type(&found_key) != BTRFS_INLINE_DATA_KEY) | ||
1961 | goto insert; | ||
1962 | copy_size = btrfs_item_size(leaf->items + slot); | ||
1963 | if (found_key.offset + copy_size <= pos) | ||
1964 | goto insert; | ||
1965 | dst = btrfs_item_ptr(leaf, path->slots[0], char); | ||
1966 | dst += pos - found_key.offset; | ||
1967 | copy_size = copy_size - (pos - found_key.offset); | ||
1968 | BUG_ON(copy_size < 0); | ||
1969 | copy_size = min(write_bytes, copy_size); | ||
1970 | WARN_ON(copy_size == 0); | ||
1971 | goto copyit; | ||
1972 | } | ||
1973 | insert: | ||
1974 | btrfs_release_path(root, path); | ||
1975 | copy_size = min(write_bytes, | ||
1976 | (size_t)BTRFS_LEAF_DATA_SIZE(root) - | ||
1977 | sizeof(struct btrfs_item) * 4); | ||
1978 | ret = btrfs_insert_empty_item(trans, root, path, &key, copy_size); | ||
1979 | BUG_ON(ret); | ||
1980 | dst = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
1981 | path->slots[0], char); | ||
1982 | copyit: | ||
1983 | WARN_ON(copy_size == 0); | ||
1984 | WARN_ON(dst + copy_size > | ||
1985 | btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
1986 | path->slots[0], char) + | ||
1987 | btrfs_item_size(btrfs_buffer_leaf(path->nodes[0])->items + | ||
1988 | path->slots[0])); | ||
1989 | btrfs_memcpy(root, path->nodes[0]->b_data, dst, | ||
1990 | page_address(page) + offset, copy_size); | ||
1991 | mark_buffer_dirty(path->nodes[0]); | ||
1992 | btrfs_release_path(root, path); | ||
1993 | pos += copy_size; | ||
1994 | offset += copy_size; | ||
1995 | num_written += copy_size; | ||
1996 | write_bytes -= copy_size; | ||
1997 | if (write_bytes) | ||
1998 | goto again; | ||
1999 | out: | ||
2000 | btrfs_free_path(path); | ||
2001 | ret = btrfs_end_transaction(trans, root); | ||
2002 | BUG_ON(ret); | ||
2003 | mutex_unlock(&root->fs_info->fs_mutex); | ||
2004 | return num_written ? num_written : err; | ||
2005 | } | ||
2006 | |||
2007 | static ssize_t btrfs_file_inline_write(struct file *file, | ||
2008 | const char __user *buf, | ||
2009 | size_t count, loff_t *ppos) | ||
2010 | { | ||
2011 | loff_t pos; | ||
2012 | size_t num_written = 0; | ||
2013 | int err = 0; | ||
2014 | int ret = 0; | ||
2015 | struct inode *inode = file->f_path.dentry->d_inode; | ||
2016 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
2017 | unsigned long page_index; | ||
2018 | |||
2019 | if (file->f_flags & O_DIRECT) | ||
2020 | return -EINVAL; | ||
2021 | pos = *ppos; | ||
2022 | |||
2023 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | ||
2024 | current->backing_dev_info = inode->i_mapping->backing_dev_info; | ||
2025 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); | ||
2026 | if (err) | ||
2027 | goto out; | ||
2028 | if (count == 0) | ||
2029 | goto out; | ||
2030 | err = remove_suid(file->f_path.dentry); | ||
2031 | if (err) | ||
2032 | goto out; | ||
2033 | file_update_time(file); | ||
2034 | mutex_lock(&inode->i_mutex); | ||
2035 | while(count > 0) { | ||
2036 | size_t offset = pos & (PAGE_CACHE_SIZE - 1); | ||
2037 | size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset); | ||
2038 | struct page *page; | ||
2039 | |||
2040 | page_index = pos >> PAGE_CACHE_SHIFT; | ||
2041 | page = grab_cache_page(inode->i_mapping, page_index); | ||
2042 | if (!PageUptodate(page)) { | ||
2043 | ret = mpage_readpage(page, btrfs_get_block); | ||
2044 | BUG_ON(ret); | ||
2045 | lock_page(page); | ||
2046 | } | ||
2047 | ret = btrfs_copy_from_user(pos, 1, | ||
2048 | write_bytes, &page, buf); | ||
2049 | BUG_ON(ret); | ||
2050 | write_bytes = inline_one_page(root, inode, page, pos, | ||
2051 | offset, write_bytes); | ||
2052 | SetPageUptodate(page); | ||
2053 | if (write_bytes > 0 && pos + write_bytes > inode->i_size) { | ||
2054 | i_size_write(inode, pos + write_bytes); | ||
2055 | mark_inode_dirty(inode); | ||
2056 | } | ||
2057 | page_cache_release(page); | ||
2058 | unlock_page(page); | ||
2059 | if (write_bytes < 0) | ||
2060 | goto out_unlock; | ||
2061 | buf += write_bytes; | ||
2062 | count -= write_bytes; | ||
2063 | pos += write_bytes; | ||
2064 | num_written += write_bytes; | ||
2065 | |||
2066 | balance_dirty_pages_ratelimited(inode->i_mapping); | ||
2067 | cond_resched(); | ||
2068 | } | ||
2069 | out_unlock: | ||
2070 | mutex_unlock(&inode->i_mutex); | ||
2071 | out: | ||
2072 | *ppos = pos; | ||
2073 | current->backing_dev_info = NULL; | ||
2074 | return num_written ? num_written : err; | ||
2075 | } | ||
2076 | #endif | ||
2077 | |||
2078 | static int btrfs_read_actor(read_descriptor_t *desc, struct page *page, | 1861 | static int btrfs_read_actor(read_descriptor_t *desc, struct page *page, |
2079 | unsigned long offset, unsigned long size) | 1862 | unsigned long offset, unsigned long size) |
2080 | { | 1863 | { |
@@ -2422,6 +2205,7 @@ static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int | |||
2422 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2205 | struct btrfs_root *root = BTRFS_I(inode)->root; |
2423 | struct btrfs_ioctl_vol_args vol_args; | 2206 | struct btrfs_ioctl_vol_args vol_args; |
2424 | int ret = 0; | 2207 | int ret = 0; |
2208 | struct btrfs_dir_item *di; | ||
2425 | int namelen; | 2209 | int namelen; |
2426 | struct btrfs_path *path; | 2210 | struct btrfs_path *path; |
2427 | u64 root_dirid; | 2211 | u64 root_dirid; |
@@ -2440,12 +2224,12 @@ static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int | |||
2440 | return -ENOMEM; | 2224 | return -ENOMEM; |
2441 | root_dirid = root->fs_info->sb->s_root->d_inode->i_ino, | 2225 | root_dirid = root->fs_info->sb->s_root->d_inode->i_ino, |
2442 | mutex_lock(&root->fs_info->fs_mutex); | 2226 | mutex_lock(&root->fs_info->fs_mutex); |
2443 | ret = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root, | 2227 | di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root, |
2444 | path, root_dirid, | 2228 | path, root_dirid, |
2445 | vol_args.name, namelen, 0); | 2229 | vol_args.name, namelen, 0); |
2446 | mutex_unlock(&root->fs_info->fs_mutex); | 2230 | mutex_unlock(&root->fs_info->fs_mutex); |
2447 | btrfs_free_path(path); | 2231 | btrfs_free_path(path); |
2448 | if (ret == 0) | 2232 | if (di && !IS_ERR(di)) |
2449 | return -EEXIST; | 2233 | return -EEXIST; |
2450 | 2234 | ||
2451 | if (root == root->fs_info->tree_root) | 2235 | if (root == root->fs_info->tree_root) |