Merge tag 'gpio-v4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux...
[cascardo/linux.git] / fs / btrfs / tests / extent-buffer-tests.c
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
25 static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
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(sectorsize, nodesize);
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(NULL, nodesize,
57                                                         nodesize);
58         if (!eb) {
59                 test_msg("Could not allocate dummy buffer\n");
60                 ret = -ENOMEM;
61                 goto out;
62         }
63         path->slots[0] = 0;
64
65         key.objectid = 0;
66         key.type = BTRFS_EXTENT_CSUM_KEY;
67         key.offset = 0;
68
69         setup_items_for_insert(root, path, &key, &value_len, value_len,
70                                value_len + sizeof(struct btrfs_item), 1);
71         item = btrfs_item_nr(0);
72         write_extent_buffer(eb, value, btrfs_item_ptr_offset(eb, 0),
73                             value_len);
74
75         key.offset = 3;
76
77         /*
78          * Passing NULL trans here should be safe because we have plenty of
79          * space in this leaf to split the item without having to split the
80          * leaf.
81          */
82         ret = btrfs_split_item(NULL, root, path, &key, 17);
83         if (ret) {
84                 test_msg("Split item failed %d\n", ret);
85                 goto out;
86         }
87
88         /*
89          * Read the first slot, it should have the original key and contain only
90          * 'mary had a little'
91          */
92         btrfs_item_key_to_cpu(eb, &key, 0);
93         if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
94             key.offset != 0) {
95                 test_msg("Invalid key at slot 0\n");
96                 ret = -EINVAL;
97                 goto out;
98         }
99
100         item = btrfs_item_nr(0);
101         if (btrfs_item_size(eb, item) != strlen(split1)) {
102                 test_msg("Invalid len in the first split\n");
103                 ret = -EINVAL;
104                 goto out;
105         }
106
107         read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 0),
108                            strlen(split1));
109         if (memcmp(buf, split1, strlen(split1))) {
110                 test_msg("Data in the buffer doesn't match what it should "
111                          "in the first split have='%.*s' want '%s'\n",
112                          (int)strlen(split1), buf, split1);
113                 ret = -EINVAL;
114                 goto out;
115         }
116
117         btrfs_item_key_to_cpu(eb, &key, 1);
118         if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
119             key.offset != 3) {
120                 test_msg("Invalid key at slot 1\n");
121                 ret = -EINVAL;
122                 goto out;
123         }
124
125         item = btrfs_item_nr(1);
126         if (btrfs_item_size(eb, item) != strlen(split2)) {
127                 test_msg("Invalid len in the second split\n");
128                 ret = -EINVAL;
129                 goto out;
130         }
131
132         read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 1),
133                            strlen(split2));
134         if (memcmp(buf, split2, strlen(split2))) {
135                 test_msg("Data in the buffer doesn't match what it should "
136                          "in the second split\n");
137                 ret = -EINVAL;
138                 goto out;
139         }
140
141         key.offset = 1;
142         /* Do it again so we test memmoving the other items in the leaf */
143         ret = btrfs_split_item(NULL, root, path, &key, 4);
144         if (ret) {
145                 test_msg("Second split item failed %d\n", ret);
146                 goto out;
147         }
148
149         btrfs_item_key_to_cpu(eb, &key, 0);
150         if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
151             key.offset != 0) {
152                 test_msg("Invalid key at slot 0\n");
153                 ret = -EINVAL;
154                 goto out;
155         }
156
157         item = btrfs_item_nr(0);
158         if (btrfs_item_size(eb, item) != strlen(split3)) {
159                 test_msg("Invalid len in the first split\n");
160                 ret = -EINVAL;
161                 goto out;
162         }
163
164         read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 0),
165                            strlen(split3));
166         if (memcmp(buf, split3, strlen(split3))) {
167                 test_msg("Data in the buffer doesn't match what it should "
168                          "in the third split");
169                 ret = -EINVAL;
170                 goto out;
171         }
172
173         btrfs_item_key_to_cpu(eb, &key, 1);
174         if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
175             key.offset != 1) {
176                 test_msg("Invalid key at slot 1\n");
177                 ret = -EINVAL;
178                 goto out;
179         }
180
181         item = btrfs_item_nr(1);
182         if (btrfs_item_size(eb, item) != strlen(split4)) {
183                 test_msg("Invalid len in the second split\n");
184                 ret = -EINVAL;
185                 goto out;
186         }
187
188         read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 1),
189                            strlen(split4));
190         if (memcmp(buf, split4, strlen(split4))) {
191                 test_msg("Data in the buffer doesn't match what it should "
192                          "in the fourth split\n");
193                 ret = -EINVAL;
194                 goto out;
195         }
196
197         btrfs_item_key_to_cpu(eb, &key, 2);
198         if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
199             key.offset != 3) {
200                 test_msg("Invalid key at slot 2\n");
201                 ret = -EINVAL;
202                 goto out;
203         }
204
205         item = btrfs_item_nr(2);
206         if (btrfs_item_size(eb, item) != strlen(split2)) {
207                 test_msg("Invalid len in the second split\n");
208                 ret = -EINVAL;
209                 goto out;
210         }
211
212         read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 2),
213                            strlen(split2));
214         if (memcmp(buf, split2, strlen(split2))) {
215                 test_msg("Data in the buffer doesn't match what it should "
216                          "in the last chunk\n");
217                 ret = -EINVAL;
218                 goto out;
219         }
220 out:
221         btrfs_free_path(path);
222         kfree(root);
223         return ret;
224 }
225
226 int btrfs_test_extent_buffer_operations(u32 sectorsize, u32 nodesize)
227 {
228         test_msg("Running extent buffer operation tests\n");
229         return test_btrfs_split_item(sectorsize, nodesize);
230 }