aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tests
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-09-19 16:07:01 -0400
committerChris Mason <chris.mason@fusionio.com>2013-11-11 21:51:02 -0500
commit06ea65a398a2501e94beee3a425d07e1846ff25a (patch)
treeda8445a365ceecd4df89a9d6a3da79afaa320765 /fs/btrfs/tests
parentdd3cc16b8750251ea9b1a843ce7806e82b015d5e (diff)
Btrfs: add a sanity test for btrfs_split_item
While looking at somebodys corruption I became completely convinced that btrfs_split_item was broken, so I wrote this test to verify that it was working as it was supposed to. Thankfully it appears to be working as intended, so just add this test to make sure nobody breaks it in the future. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs/tests')
-rw-r--r--fs/btrfs/tests/btrfs-tests.h5
-rw-r--r--fs/btrfs/tests/extent-buffer-tests.c229
2 files changed, 234 insertions, 0 deletions
diff --git a/fs/btrfs/tests/btrfs-tests.h b/fs/btrfs/tests/btrfs-tests.h
index 580877625776..04f2cd2ca568 100644
--- a/fs/btrfs/tests/btrfs-tests.h
+++ b/fs/btrfs/tests/btrfs-tests.h
@@ -24,11 +24,16 @@
24#define test_msg(fmt, ...) pr_info("btrfs: selftest: " fmt, ##__VA_ARGS__) 24#define test_msg(fmt, ...) pr_info("btrfs: selftest: " fmt, ##__VA_ARGS__)
25 25
26int btrfs_test_free_space_cache(void); 26int btrfs_test_free_space_cache(void);
27int btrfs_test_extent_buffer_operations(void);
27#else 28#else
28static inline int btrfs_test_free_space_cache(void) 29static inline int btrfs_test_free_space_cache(void)
29{ 30{
30 return 0; 31 return 0;
31} 32}
33static inline int btrfs_test_extent_buffer_operations(void)
34{
35 return 0;
36}
32#endif 37#endif
33 38
34#endif 39#endif
diff --git a/fs/btrfs/tests/extent-buffer-tests.c b/fs/btrfs/tests/extent-buffer-tests.c
new file mode 100644
index 000000000000..cc286ce97d1e
--- /dev/null
+++ b/fs/btrfs/tests/extent-buffer-tests.c
@@ -0,0 +1,229 @@
1/*
2 * Copyright (C) 2013 Fusion IO. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
17 */
18
19#include <linux/slab.h>
20#include "btrfs-tests.h"
21#include "../ctree.h"
22#include "../extent_io.h"
23#include "../disk-io.h"
24
25static int test_btrfs_split_item(void)
26{
27 struct btrfs_path *path;
28 struct btrfs_root *root;
29 struct extent_buffer *eb;
30 struct btrfs_item *item;
31 char *value = "mary had a little lamb";
32 char *split1 = "mary had a little";
33 char *split2 = " lamb";
34 char *split3 = "mary";
35 char *split4 = " had a little";
36 char buf[32];
37 struct btrfs_key key;
38 u32 value_len = strlen(value);
39 int ret = 0;
40
41 test_msg("Running btrfs_split_item tests\n");
42
43 root = btrfs_alloc_dummy_root();
44 if (IS_ERR(root)) {
45 test_msg("Could not allocate root\n");
46 return PTR_ERR(root);
47 }
48
49 path = btrfs_alloc_path();
50 if (!path) {
51 test_msg("Could not allocate path\n");
52 kfree(root);
53 return -ENOMEM;
54 }
55
56 path->nodes[0] = eb = alloc_dummy_extent_buffer(0, 4096);
57 if (!eb) {
58 test_msg("Could not allocate dummy buffer\n");
59 ret = -ENOMEM;
60 goto out;
61 }
62 path->slots[0] = 0;
63
64 key.objectid = 0;
65 key.type = BTRFS_EXTENT_CSUM_KEY;
66 key.offset = 0;
67
68 setup_items_for_insert(root, path, &key, &value_len, value_len,
69 value_len + sizeof(struct btrfs_item), 1);
70 item = btrfs_item_nr(0);
71 write_extent_buffer(eb, value, btrfs_item_ptr_offset(eb, 0),
72 value_len);
73
74 key.offset = 3;
75
76 /*
77 * Passing NULL trans here should be safe because we have plenty of
78 * space in this leaf to split the item without having to split the
79 * leaf.
80 */
81 ret = btrfs_split_item(NULL, root, path, &key, 17);
82 if (ret) {
83 test_msg("Split item failed %d\n", ret);
84 goto out;
85 }
86
87 /*
88 * Read the first slot, it should have the original key and contain only
89 * 'mary had a little'
90 */
91 btrfs_item_key_to_cpu(eb, &key, 0);
92 if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
93 key.offset != 0) {
94 test_msg("Invalid key at slot 0\n");
95 ret = -EINVAL;
96 goto out;
97 }
98
99 item = btrfs_item_nr(0);
100 if (btrfs_item_size(eb, item) != strlen(split1)) {
101 test_msg("Invalid len in the first split\n");
102 ret = -EINVAL;
103 goto out;
104 }
105
106 read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 0),
107 strlen(split1));
108 if (memcmp(buf, split1, strlen(split1))) {
109 test_msg("Data in the buffer doesn't match what it should "
110 "in the first split have='%.*s' want '%s'\n",
111 (int)strlen(split1), buf, split1);
112 ret = -EINVAL;
113 goto out;
114 }
115
116 btrfs_item_key_to_cpu(eb, &key, 1);
117 if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
118 key.offset != 3) {
119 test_msg("Invalid key at slot 1\n");
120 ret = -EINVAL;
121 goto out;
122 }
123
124 item = btrfs_item_nr(1);
125 if (btrfs_item_size(eb, item) != strlen(split2)) {
126 test_msg("Invalid len in the second split\n");
127 ret = -EINVAL;
128 goto out;
129 }
130
131 read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 1),
132 strlen(split2));
133 if (memcmp(buf, split2, strlen(split2))) {
134 test_msg("Data in the buffer doesn't match what it should "
135 "in the second split\n");
136 ret = -EINVAL;
137 goto out;
138 }
139
140 key.offset = 1;
141 /* Do it again so we test memmoving the other items in the leaf */
142 ret = btrfs_split_item(NULL, root, path, &key, 4);
143 if (ret) {
144 test_msg("Second split item failed %d\n", ret);
145 goto out;
146 }
147
148 btrfs_item_key_to_cpu(eb, &key, 0);
149 if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
150 key.offset != 0) {
151 test_msg("Invalid key at slot 0\n");
152 ret = -EINVAL;
153 goto out;
154 }
155
156 item = btrfs_item_nr(0);
157 if (btrfs_item_size(eb, item) != strlen(split3)) {
158 test_msg("Invalid len in the first split\n");
159 ret = -EINVAL;
160 goto out;
161 }
162
163 read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 0),
164 strlen(split3));
165 if (memcmp(buf, split3, strlen(split3))) {
166 test_msg("Data in the buffer doesn't match what it should "
167 "in the third split");
168 ret = -EINVAL;
169 goto out;
170 }
171
172 btrfs_item_key_to_cpu(eb, &key, 1);
173 if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
174 key.offset != 1) {
175 test_msg("Invalid key at slot 1\n");
176 ret = -EINVAL;
177 goto out;
178 }
179
180 item = btrfs_item_nr(1);
181 if (btrfs_item_size(eb, item) != strlen(split4)) {
182 test_msg("Invalid len in the second split\n");
183 ret = -EINVAL;
184 goto out;
185 }
186
187 read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 1),
188 strlen(split4));
189 if (memcmp(buf, split4, strlen(split4))) {
190 test_msg("Data in the buffer doesn't match what it should "
191 "in the fourth split\n");
192 ret = -EINVAL;
193 goto out;
194 }
195
196 btrfs_item_key_to_cpu(eb, &key, 2);
197 if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
198 key.offset != 3) {
199 test_msg("Invalid key at slot 2\n");
200 ret = -EINVAL;
201 goto out;
202 }
203
204 item = btrfs_item_nr(2);
205 if (btrfs_item_size(eb, item) != strlen(split2)) {
206 test_msg("Invalid len in the second split\n");
207 ret = -EINVAL;
208 goto out;
209 }
210
211 read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 2),
212 strlen(split2));
213 if (memcmp(buf, split2, strlen(split2))) {
214 test_msg("Data in the buffer doesn't match what it should "
215 "in the last chunk\n");
216 ret = -EINVAL;
217 goto out;
218 }
219out:
220 btrfs_free_path(path);
221 kfree(root);
222 return ret;
223}
224
225int btrfs_test_extent_buffer_operations(void)
226{
227 test_msg("Running extent buffer operation tests");
228 return test_btrfs_split_item();
229}