Commit 1d4f6404de26df49eb8452f8fdf7672b59f407fc
Committed by
David Woodhouse
1 parent
24af03ea5e
Exists in
master
and in
7 other branches
Btrfs: directory testing code and dir item fixes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Showing 5 changed files with 477 additions and 74 deletions Side-by-side Diff
fs/btrfs/Makefile
1 | - | |
2 | 1 | CC=gcc |
3 | 2 | CFLAGS = -g -Wall |
4 | 3 | headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h |
... | ... | @@ -15,7 +14,7 @@ |
15 | 14 | $(check) $< |
16 | 15 | $(CC) $(CFLAGS) -c $< |
17 | 16 | |
18 | -all: tester debug-tree quick-test | |
17 | +all: tester debug-tree quick-test dir-test | |
19 | 18 | |
20 | 19 | debug-tree: $(objects) debug-tree.o |
21 | 20 | gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o |
... | ... | @@ -23,6 +22,8 @@ |
23 | 22 | tester: $(objects) random-test.o |
24 | 23 | gcc $(CFLAGS) -o tester $(objects) random-test.o |
25 | 24 | |
25 | +dir-test: $(objects) dir-test.o | |
26 | + gcc $(CFLAGS) -o dir-test $(objects) dir-test.o | |
26 | 27 | quick-test: $(objects) quick-test.o |
27 | 28 | gcc $(CFLAGS) -o quick-test $(objects) quick-test.o |
28 | 29 |
fs/btrfs/ctree.h
... | ... | @@ -180,37 +180,6 @@ |
180 | 180 | #define BTRFS_EXTENT_ITEM_KEY 4 |
181 | 181 | #define BTRFS_STRING_ITEM_KEY 5 |
182 | 182 | |
183 | -static inline u64 btrfs_dir_objectid(struct btrfs_dir_item *d) | |
184 | -{ | |
185 | - return le64_to_cpu(d->objectid); | |
186 | -} | |
187 | - | |
188 | -static inline void btrfs_set_dir_objectid(struct btrfs_dir_item *d, u64 val) | |
189 | -{ | |
190 | - d->objectid = cpu_to_le64(val); | |
191 | -} | |
192 | - | |
193 | -static inline u16 btrfs_dir_flags(struct btrfs_dir_item *d) | |
194 | -{ | |
195 | - return le16_to_cpu(d->flags); | |
196 | -} | |
197 | - | |
198 | -static inline void btrfs_set_dir_flags(struct btrfs_dir_item *d, u16 val) | |
199 | -{ | |
200 | - d->flags = cpu_to_le16(val); | |
201 | -} | |
202 | - | |
203 | -static inline u8 btrfs_dir_type(struct btrfs_dir_item *d) | |
204 | -{ | |
205 | - return d->type; | |
206 | -} | |
207 | - | |
208 | -static inline void btrfs_set_dir_type(struct btrfs_dir_item *d, u8 val) | |
209 | -{ | |
210 | - d->type = val; | |
211 | -} | |
212 | - | |
213 | - | |
214 | 183 | static inline u64 btrfs_extent_owner(struct btrfs_extent_item *ei) |
215 | 184 | { |
216 | 185 | return le64_to_cpu(ei->owner); |
... | ... | @@ -267,6 +236,41 @@ |
267 | 236 | item->size = cpu_to_le16(val); |
268 | 237 | } |
269 | 238 | |
239 | +static inline u64 btrfs_dir_objectid(struct btrfs_dir_item *d) | |
240 | +{ | |
241 | + return le64_to_cpu(d->objectid); | |
242 | +} | |
243 | + | |
244 | +static inline void btrfs_set_dir_objectid(struct btrfs_dir_item *d, u64 val) | |
245 | +{ | |
246 | + d->objectid = cpu_to_le64(val); | |
247 | +} | |
248 | + | |
249 | +static inline u16 btrfs_dir_flags(struct btrfs_dir_item *d) | |
250 | +{ | |
251 | + return le16_to_cpu(d->flags); | |
252 | +} | |
253 | + | |
254 | +static inline void btrfs_set_dir_flags(struct btrfs_dir_item *d, u16 val) | |
255 | +{ | |
256 | + d->flags = cpu_to_le16(val); | |
257 | +} | |
258 | + | |
259 | +static inline u8 btrfs_dir_type(struct btrfs_dir_item *d) | |
260 | +{ | |
261 | + return d->type; | |
262 | +} | |
263 | + | |
264 | +static inline void btrfs_set_dir_type(struct btrfs_dir_item *d, u8 val) | |
265 | +{ | |
266 | + d->type = val; | |
267 | +} | |
268 | + | |
269 | +static inline u32 btrfs_dir_name_len(struct btrfs_item *i) | |
270 | +{ | |
271 | + return btrfs_item_size(i) - sizeof(struct btrfs_dir_item); | |
272 | +} | |
273 | + | |
270 | 274 | static inline void btrfs_disk_key_to_cpu(struct btrfs_key *cpu, |
271 | 275 | struct btrfs_disk_key *disk) |
272 | 276 | { |
... | ... | @@ -506,5 +510,11 @@ |
506 | 510 | struct btrfs_root_item *item); |
507 | 511 | int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, |
508 | 512 | struct btrfs_root_item *item, struct btrfs_key *key); |
513 | +int btrfs_insert_dir_item(struct btrfs_root *root, char *name, int name_len, | |
514 | + u64 dir, u64 objectid, u8 type); | |
515 | +int btrfs_lookup_dir_item(struct btrfs_root *root, struct btrfs_path *path, | |
516 | + u64 dir, char *name, int name_len, int mod); | |
517 | +int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, | |
518 | + char *name, int name_len); | |
509 | 519 | #endif |
fs/btrfs/dir-item.c
... | ... | @@ -18,6 +18,7 @@ |
18 | 18 | |
19 | 19 | key.objectid = dir; |
20 | 20 | key.flags = 0; |
21 | + btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); | |
21 | 22 | ret = btrfs_name_hash(name, name_len, &key.offset); |
22 | 23 | BUG_ON(ret); |
23 | 24 | btrfs_init_path(&path); |
24 | 25 | |
25 | 26 | |
26 | 27 | |
27 | 28 | |
28 | 29 | |
29 | 30 | |
30 | 31 | |
31 | 32 | |
32 | 33 | |
33 | 34 | |
34 | 35 | |
35 | 36 | |
... | ... | @@ -38,66 +39,41 @@ |
38 | 39 | return ret; |
39 | 40 | } |
40 | 41 | |
41 | -int btrfs_del_dir_item(struct btrfs_root *root, u64 dir, char *name, | |
42 | - int name_len) | |
42 | +int btrfs_lookup_dir_item(struct btrfs_root *root, struct btrfs_path *path, | |
43 | + u64 dir, char *name, int name_len, int mod) | |
43 | 44 | { |
44 | - int ret = 0; | |
45 | - struct btrfs_path path; | |
45 | + int ret; | |
46 | 46 | struct btrfs_key key; |
47 | + int ins_len = mod < 0 ? -1 : 0; | |
48 | + int cow = mod != 0; | |
47 | 49 | |
48 | 50 | key.objectid = dir; |
49 | 51 | key.flags = 0; |
52 | + btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); | |
50 | 53 | ret = btrfs_name_hash(name, name_len, &key.offset); |
51 | 54 | BUG_ON(ret); |
52 | - btrfs_init_path(&path); | |
53 | - ret = btrfs_search_slot(root, &key, &path, 0, 1); | |
54 | - if (ret) | |
55 | - goto out; | |
56 | - ret = btrfs_del_item(root, &path); | |
57 | -out: | |
58 | - btrfs_release_path(root, &path); | |
55 | + ret = btrfs_search_slot(root, &key, path, ins_len, cow); | |
59 | 56 | return ret; |
60 | 57 | } |
61 | 58 | |
62 | -int btrfs_lookup_dir_item(struct btrfs_root *root, u64 dir, char *name, | |
63 | - int name_len, u64 *objectid) | |
59 | +int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, | |
60 | + char *name, int name_len) | |
64 | 61 | { |
65 | - int ret = 0; | |
66 | - struct btrfs_path path; | |
62 | + struct btrfs_item *item; | |
67 | 63 | struct btrfs_dir_item *dir_item; |
68 | 64 | char *name_ptr; |
69 | - struct btrfs_key key; | |
70 | 65 | u32 item_len; |
71 | - struct btrfs_item *item; | |
72 | - | |
73 | - key.objectid = dir; | |
74 | - key.flags = 0; | |
75 | - ret = btrfs_name_hash(name, name_len, &key.offset); | |
76 | - BUG_ON(ret); | |
77 | - btrfs_init_path(&path); | |
78 | - ret = btrfs_search_slot(root, &key, &path, 0, 0); | |
79 | - if (ret) | |
80 | - goto out; | |
81 | - | |
82 | - dir_item = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], | |
83 | - struct btrfs_dir_item); | |
84 | - | |
85 | - item = path.nodes[0]->leaf.items + path.slots[0]; | |
66 | + item = path->nodes[0]->leaf.items + path->slots[0]; | |
86 | 67 | item_len = btrfs_item_size(item); |
87 | 68 | if (item_len != name_len + sizeof(struct btrfs_dir_item)) { |
88 | - BUG(); | |
89 | - ret = 1; | |
90 | - goto out; | |
69 | + return 0; | |
91 | 70 | } |
71 | + dir_item = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0], | |
72 | + struct btrfs_dir_item); | |
92 | 73 | name_ptr = (char *)(dir_item + 1); |
93 | 74 | if (memcmp(name_ptr, name, name_len)) { |
94 | - BUG(); | |
95 | - ret = 1; | |
96 | - goto out; | |
75 | + return 0; | |
97 | 76 | } |
98 | - *objectid = btrfs_dir_objectid(dir_item); | |
99 | -out: | |
100 | - btrfs_release_path(root, &path); | |
101 | - return ret; | |
77 | + return 1; | |
102 | 78 | } |
fs/btrfs/dir-test.c
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <signal.h> | |
4 | +#include <unistd.h> | |
5 | +#include "kerncompat.h" | |
6 | +#include "radix-tree.h" | |
7 | +#include "ctree.h" | |
8 | +#include "disk-io.h" | |
9 | +#include "print-tree.h" | |
10 | +#include "hash.h" | |
11 | + | |
12 | +int keep_running = 1; | |
13 | +struct btrfs_super_block super; | |
14 | +static u64 dir_oid = 44556; | |
15 | +static u64 file_oid = 33778; | |
16 | + | |
17 | +static int find_num(struct radix_tree_root *root, unsigned long *num_ret, | |
18 | + int exists) | |
19 | +{ | |
20 | + unsigned long num = rand(); | |
21 | + unsigned long res[2]; | |
22 | + int ret; | |
23 | + | |
24 | +again: | |
25 | + ret = radix_tree_gang_lookup(root, (void **)res, num, 2); | |
26 | + if (exists) { | |
27 | + if (ret == 0) | |
28 | + return -1; | |
29 | + num = res[0]; | |
30 | + } else if (ret != 0 && num == res[0]) { | |
31 | + num++; | |
32 | + if (ret > 1 && num == res[1]) { | |
33 | + num++; | |
34 | + goto again; | |
35 | + } | |
36 | + } | |
37 | + *num_ret = num; | |
38 | + return 0; | |
39 | +} | |
40 | + | |
41 | +static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix) | |
42 | +{ | |
43 | + int ret; | |
44 | + char buf[128]; | |
45 | + unsigned long oid; | |
46 | + struct btrfs_path path; | |
47 | + | |
48 | + find_num(radix, &oid, 0); | |
49 | + sprintf(buf, "str-%lu", oid); | |
50 | + | |
51 | + ret = btrfs_insert_dir_item(root, buf, strlen(buf), dir_oid, file_oid, | |
52 | + 1); | |
53 | + if (ret) | |
54 | + goto error; | |
55 | + | |
56 | + radix_tree_preload(GFP_KERNEL); | |
57 | + ret = radix_tree_insert(radix, oid, (void *)oid); | |
58 | + radix_tree_preload_end(); | |
59 | + if (ret) | |
60 | + goto error; | |
61 | + return ret; | |
62 | +error: | |
63 | + if (ret != -EEXIST) | |
64 | + goto fatal; | |
65 | + | |
66 | + /* | |
67 | + * if we got an EEXIST, it may be due to hash collision, double | |
68 | + * check | |
69 | + */ | |
70 | + btrfs_init_path(&path); | |
71 | + ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0); | |
72 | + if (ret) | |
73 | + goto fatal_release; | |
74 | + if (!btrfs_match_dir_item_name(root, &path, buf, strlen(buf))) { | |
75 | + struct btrfs_dir_item *di; | |
76 | + char *found; | |
77 | + u32 found_len; | |
78 | + u64 myhash; | |
79 | + u64 foundhash; | |
80 | + | |
81 | + di = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], | |
82 | + struct btrfs_dir_item); | |
83 | + found = (char *)(di + 1); | |
84 | + found_len = btrfs_dir_name_len(path.nodes[0]->leaf.items + | |
85 | + path.slots[0]); | |
86 | + btrfs_name_hash(buf, strlen(buf), &myhash); | |
87 | + btrfs_name_hash(found, found_len, &foundhash); | |
88 | + if (myhash != foundhash) | |
89 | + goto fatal_release; | |
90 | + btrfs_release_path(root, &path); | |
91 | + return 0; | |
92 | + } | |
93 | +fatal_release: | |
94 | + btrfs_release_path(root, &path); | |
95 | +fatal: | |
96 | + printf("failed to insert %lu ret %d\n", oid, ret); | |
97 | + return -1; | |
98 | +} | |
99 | + | |
100 | +static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix) | |
101 | +{ | |
102 | + int ret; | |
103 | + char buf[128]; | |
104 | + unsigned long oid; | |
105 | + | |
106 | + ret = find_num(radix, &oid, 1); | |
107 | + if (ret < 0) | |
108 | + return 0; | |
109 | + sprintf(buf, "str-%lu", oid); | |
110 | + | |
111 | + ret = btrfs_insert_dir_item(root, buf, strlen(buf), dir_oid, file_oid, | |
112 | + 1); | |
113 | + if (ret != -EEXIST) { | |
114 | + printf("insert on %s gave us %d\n", buf, ret); | |
115 | + return 1; | |
116 | + } | |
117 | + return 0; | |
118 | +} | |
119 | + | |
120 | +static int del_one(struct btrfs_root *root, struct radix_tree_root *radix) | |
121 | +{ | |
122 | + int ret; | |
123 | + char buf[128]; | |
124 | + unsigned long oid; | |
125 | + struct btrfs_path path; | |
126 | + unsigned long *ptr; | |
127 | + | |
128 | + ret = find_num(radix, &oid, 1); | |
129 | + if (ret < 0) | |
130 | + return 0; | |
131 | + sprintf(buf, "str-%lu", oid); | |
132 | + btrfs_init_path(&path); | |
133 | + ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), -1); | |
134 | + if (ret) | |
135 | + goto out_release; | |
136 | + ret = btrfs_del_item(root, &path); | |
137 | + if (ret) | |
138 | + goto out_release; | |
139 | + btrfs_release_path(root, &path); | |
140 | + ptr = radix_tree_delete(radix, oid); | |
141 | + if (!ptr) { | |
142 | + ret = -5555; | |
143 | + goto out; | |
144 | + } | |
145 | + return 0; | |
146 | +out_release: | |
147 | + btrfs_release_path(root, &path); | |
148 | +out: | |
149 | + printf("failed to delete %lu %d\n", oid, ret); | |
150 | + return -1; | |
151 | +} | |
152 | + | |
153 | +static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix) | |
154 | +{ | |
155 | + struct btrfs_path path; | |
156 | + char buf[128]; | |
157 | + int ret; | |
158 | + unsigned long oid; | |
159 | + | |
160 | + ret = find_num(radix, &oid, 1); | |
161 | + if (ret < 0) | |
162 | + return 0; | |
163 | + sprintf(buf, "str-%lu", oid); | |
164 | + btrfs_init_path(&path); | |
165 | + ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0); | |
166 | + btrfs_release_path(root, &path); | |
167 | + if (ret) { | |
168 | + printf("unable to find key %lu\n", oid); | |
169 | + return -1; | |
170 | + } | |
171 | + return 0; | |
172 | +} | |
173 | + | |
174 | +static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix) | |
175 | +{ | |
176 | + struct btrfs_path path; | |
177 | + char buf[128]; | |
178 | + int ret; | |
179 | + unsigned long oid; | |
180 | + | |
181 | + ret = find_num(radix, &oid, 0); | |
182 | + if (ret < 0) | |
183 | + return 0; | |
184 | + sprintf(buf, "str-%lu", oid); | |
185 | + btrfs_init_path(&path); | |
186 | + ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0); | |
187 | + btrfs_release_path(root, &path); | |
188 | + if (!ret) { | |
189 | + printf("able to find key that should not exist %lu\n", oid); | |
190 | + return -1; | |
191 | + } | |
192 | + return 0; | |
193 | +} | |
194 | + | |
195 | +static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix, | |
196 | + int nr) | |
197 | +{ | |
198 | + struct btrfs_path path; | |
199 | + struct btrfs_key key; | |
200 | + unsigned long found = 0; | |
201 | + u32 found_len; | |
202 | + int ret; | |
203 | + int slot; | |
204 | + int *ptr; | |
205 | + int count = 0; | |
206 | + char buf[128]; | |
207 | + struct btrfs_dir_item *di; | |
208 | + | |
209 | + key.offset = (u64)-1; | |
210 | + key.flags = 0; | |
211 | + btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); | |
212 | + key.objectid = dir_oid; | |
213 | + while(nr-- >= 0) { | |
214 | + btrfs_init_path(&path); | |
215 | + ret = btrfs_search_slot(root, &key, &path, -1, 1); | |
216 | + if (ret < 0) { | |
217 | + btrfs_release_path(root, &path); | |
218 | + return ret; | |
219 | + } | |
220 | + if (ret != 0) { | |
221 | + if (path.slots[0] == 0) { | |
222 | + btrfs_release_path(root, &path); | |
223 | + break; | |
224 | + } | |
225 | + path.slots[0] -= 1; | |
226 | + } | |
227 | + slot = path.slots[0]; | |
228 | + di = btrfs_item_ptr(&path.nodes[0]->leaf, slot, | |
229 | + struct btrfs_dir_item); | |
230 | + found_len = btrfs_dir_name_len(path.nodes[0]->leaf.items + | |
231 | + slot); | |
232 | + memcpy(buf, (char *)(di + 1), found_len); | |
233 | + BUG_ON(found_len > 128); | |
234 | + buf[found_len] = '\0'; | |
235 | + found = atoi(buf + 4); | |
236 | + ret = btrfs_del_item(root, &path); | |
237 | + count++; | |
238 | + if (ret) { | |
239 | + fprintf(stderr, | |
240 | + "failed to remove %lu from tree\n", | |
241 | + found); | |
242 | + return -1; | |
243 | + } | |
244 | + btrfs_release_path(root, &path); | |
245 | + ptr = radix_tree_delete(radix, found); | |
246 | + if (!ptr) | |
247 | + goto error; | |
248 | + if (!keep_running) | |
249 | + break; | |
250 | + } | |
251 | + return 0; | |
252 | +error: | |
253 | + fprintf(stderr, "failed to delete from the radix %lu\n", found); | |
254 | + return -1; | |
255 | +} | |
256 | + | |
257 | +static int fill_tree(struct btrfs_root *root, struct radix_tree_root *radix, | |
258 | + int count) | |
259 | +{ | |
260 | + int i; | |
261 | + int ret = 0; | |
262 | + for (i = 0; i < count; i++) { | |
263 | + ret = ins_one(root, radix); | |
264 | + if (ret) { | |
265 | + fprintf(stderr, "fill failed\n"); | |
266 | + goto out; | |
267 | + } | |
268 | + if (i % 1000 == 0) { | |
269 | + ret = btrfs_commit_transaction(root, &super); | |
270 | + if (ret) { | |
271 | + fprintf(stderr, "fill commit failed\n"); | |
272 | + return ret; | |
273 | + } | |
274 | + } | |
275 | + if (i && i % 10000 == 0) { | |
276 | + printf("bigfill %d\n", i); | |
277 | + } | |
278 | + if (!keep_running) | |
279 | + break; | |
280 | + } | |
281 | +out: | |
282 | + return ret; | |
283 | +} | |
284 | + | |
285 | +static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix) | |
286 | +{ | |
287 | + int ret; | |
288 | + int nr = rand() % 5000; | |
289 | + static int run_nr = 0; | |
290 | + | |
291 | + /* do the bulk op much less frequently */ | |
292 | + if (run_nr++ % 100) | |
293 | + return 0; | |
294 | + ret = empty_tree(root, radix, nr); | |
295 | + if (ret) | |
296 | + return ret; | |
297 | + ret = fill_tree(root, radix, nr); | |
298 | + if (ret) | |
299 | + return ret; | |
300 | + return 0; | |
301 | +} | |
302 | + | |
303 | + | |
304 | +int (*ops[])(struct btrfs_root *root, struct radix_tree_root *radix) = | |
305 | + { ins_one, insert_dup, del_one, lookup_item, | |
306 | + lookup_enoent, bulk_op }; | |
307 | + | |
308 | +void sigstopper(int ignored) | |
309 | +{ | |
310 | + keep_running = 0; | |
311 | + fprintf(stderr, "caught exit signal, stopping\n"); | |
312 | +} | |
313 | + | |
314 | +int print_usage(void) | |
315 | +{ | |
316 | + printf("usage: tester [-ih] [-c count] [-f count]\n"); | |
317 | + printf("\t -c count -- iteration count after filling\n"); | |
318 | + printf("\t -f count -- run this many random inserts before starting\n"); | |
319 | + printf("\t -i -- only do initial fill\n"); | |
320 | + printf("\t -h -- this help text\n"); | |
321 | + exit(1); | |
322 | +} | |
323 | +int main(int ac, char **av) | |
324 | +{ | |
325 | + RADIX_TREE(radix, GFP_KERNEL); | |
326 | + struct btrfs_root *root; | |
327 | + int i; | |
328 | + int ret; | |
329 | + int count; | |
330 | + int op; | |
331 | + int iterations = 20000; | |
332 | + int init_fill_count = 800000; | |
333 | + int err = 0; | |
334 | + int initial_only = 0; | |
335 | + radix_tree_init(); | |
336 | + | |
337 | + printf("removing old tree\n"); | |
338 | + unlink("dbfile"); | |
339 | + root = open_ctree("dbfile", &super); | |
340 | + | |
341 | + signal(SIGTERM, sigstopper); | |
342 | + signal(SIGINT, sigstopper); | |
343 | + | |
344 | + for (i = 1 ; i < ac ; i++) { | |
345 | + if (strcmp(av[i], "-i") == 0) { | |
346 | + initial_only = 1; | |
347 | + } else if (strcmp(av[i], "-c") == 0) { | |
348 | + iterations = atoi(av[i+1]); | |
349 | + i++; | |
350 | + } else if (strcmp(av[i], "-f") == 0) { | |
351 | + init_fill_count = atoi(av[i+1]); | |
352 | + i++; | |
353 | + } else { | |
354 | + print_usage(); | |
355 | + } | |
356 | + } | |
357 | + printf("initial fill\n"); | |
358 | + ret = fill_tree(root, &radix, init_fill_count); | |
359 | + printf("starting run\n"); | |
360 | + if (ret) { | |
361 | + err = ret; | |
362 | + goto out; | |
363 | + } | |
364 | + if (initial_only == 1) { | |
365 | + goto out; | |
366 | + } | |
367 | + for (i = 0; i < iterations; i++) { | |
368 | + op = rand() % ARRAY_SIZE(ops); | |
369 | + count = rand() % 128; | |
370 | + if (i % 2000 == 0) { | |
371 | + printf("%d\n", i); | |
372 | + fflush(stdout); | |
373 | + } | |
374 | + if (i && i % 5000 == 0) { | |
375 | + printf("open & close, root level %d nritems %d\n", | |
376 | + btrfs_header_level(&root->node->node.header), | |
377 | + btrfs_header_nritems(&root->node->node.header)); | |
378 | + close_ctree(root, &super); | |
379 | + root = open_ctree("dbfile", &super); | |
380 | + } | |
381 | + while(count--) { | |
382 | + ret = ops[op](root, &radix); | |
383 | + if (ret) { | |
384 | + fprintf(stderr, "op %d failed %d:%d\n", | |
385 | + op, i, iterations); | |
386 | + btrfs_print_tree(root, root->node); | |
387 | + fprintf(stderr, "op %d failed %d:%d\n", | |
388 | + op, i, iterations); | |
389 | + err = ret; | |
390 | + goto out; | |
391 | + } | |
392 | + if (ops[op] == bulk_op) | |
393 | + break; | |
394 | + if (keep_running == 0) { | |
395 | + err = 0; | |
396 | + goto out; | |
397 | + } | |
398 | + } | |
399 | + } | |
400 | +out: | |
401 | + close_ctree(root, &super); | |
402 | + return err; | |
403 | +} |
fs/btrfs/print-tree.c
... | ... | @@ -12,7 +12,10 @@ |
12 | 12 | struct btrfs_item *item; |
13 | 13 | struct btrfs_extent_item *ei; |
14 | 14 | struct btrfs_root_item *ri; |
15 | + struct btrfs_dir_item *di; | |
15 | 16 | u32 type; |
17 | + u32 namelen; | |
18 | + | |
16 | 19 | printf("leaf %Lu total ptrs %d free space %d\n", |
17 | 20 | btrfs_header_blocknr(&l->header), nr, |
18 | 21 | btrfs_leaf_free_space(root, l)); |
... | ... | @@ -31,6 +34,15 @@ |
31 | 34 | case BTRFS_INODE_ITEM_KEY: |
32 | 35 | break; |
33 | 36 | case BTRFS_DIR_ITEM_KEY: |
37 | + namelen = btrfs_item_size(l->items + i) - sizeof(*di); | |
38 | + di = btrfs_item_ptr(l, i, struct btrfs_dir_item); | |
39 | + printf("\t\tdir oid %Lu flags %u type %u\n", | |
40 | + btrfs_dir_objectid(di), | |
41 | + btrfs_dir_flags(di), | |
42 | + btrfs_dir_type(di)); | |
43 | + printf("\t\tname %.*s\n", | |
44 | + namelen, (char *)(di + 1)); | |
45 | + | |
34 | 46 | break; |
35 | 47 | case BTRFS_ROOT_ITEM_KEY: |
36 | 48 | ri = btrfs_item_ptr(l, i, struct btrfs_root_item); |