1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2013 Fusion IO. All rights reserved.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/slab.h>
7*4882a593Smuzhiyun #include "btrfs-tests.h"
8*4882a593Smuzhiyun #include "../ctree.h"
9*4882a593Smuzhiyun #include "../extent_io.h"
10*4882a593Smuzhiyun #include "../disk-io.h"
11*4882a593Smuzhiyun
test_btrfs_split_item(u32 sectorsize,u32 nodesize)12*4882a593Smuzhiyun static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
13*4882a593Smuzhiyun {
14*4882a593Smuzhiyun struct btrfs_fs_info *fs_info;
15*4882a593Smuzhiyun struct btrfs_path *path = NULL;
16*4882a593Smuzhiyun struct btrfs_root *root = NULL;
17*4882a593Smuzhiyun struct extent_buffer *eb;
18*4882a593Smuzhiyun struct btrfs_item *item;
19*4882a593Smuzhiyun char *value = "mary had a little lamb";
20*4882a593Smuzhiyun char *split1 = "mary had a little";
21*4882a593Smuzhiyun char *split2 = " lamb";
22*4882a593Smuzhiyun char *split3 = "mary";
23*4882a593Smuzhiyun char *split4 = " had a little";
24*4882a593Smuzhiyun char buf[32];
25*4882a593Smuzhiyun struct btrfs_key key;
26*4882a593Smuzhiyun u32 value_len = strlen(value);
27*4882a593Smuzhiyun int ret = 0;
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun test_msg("running btrfs_split_item tests");
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
32*4882a593Smuzhiyun if (!fs_info) {
33*4882a593Smuzhiyun test_std_err(TEST_ALLOC_FS_INFO);
34*4882a593Smuzhiyun return -ENOMEM;
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun root = btrfs_alloc_dummy_root(fs_info);
38*4882a593Smuzhiyun if (IS_ERR(root)) {
39*4882a593Smuzhiyun test_std_err(TEST_ALLOC_ROOT);
40*4882a593Smuzhiyun ret = PTR_ERR(root);
41*4882a593Smuzhiyun goto out;
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun path = btrfs_alloc_path();
45*4882a593Smuzhiyun if (!path) {
46*4882a593Smuzhiyun test_std_err(TEST_ALLOC_PATH);
47*4882a593Smuzhiyun ret = -ENOMEM;
48*4882a593Smuzhiyun goto out;
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun path->nodes[0] = eb = alloc_dummy_extent_buffer(fs_info, nodesize);
52*4882a593Smuzhiyun if (!eb) {
53*4882a593Smuzhiyun test_std_err(TEST_ALLOC_EXTENT_BUFFER);
54*4882a593Smuzhiyun ret = -ENOMEM;
55*4882a593Smuzhiyun goto out;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun path->slots[0] = 0;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun key.objectid = 0;
60*4882a593Smuzhiyun key.type = BTRFS_EXTENT_CSUM_KEY;
61*4882a593Smuzhiyun key.offset = 0;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun setup_items_for_insert(root, path, &key, &value_len, 1);
64*4882a593Smuzhiyun item = btrfs_item_nr(0);
65*4882a593Smuzhiyun write_extent_buffer(eb, value, btrfs_item_ptr_offset(eb, 0),
66*4882a593Smuzhiyun value_len);
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun key.offset = 3;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /*
71*4882a593Smuzhiyun * Passing NULL trans here should be safe because we have plenty of
72*4882a593Smuzhiyun * space in this leaf to split the item without having to split the
73*4882a593Smuzhiyun * leaf.
74*4882a593Smuzhiyun */
75*4882a593Smuzhiyun ret = btrfs_split_item(NULL, root, path, &key, 17);
76*4882a593Smuzhiyun if (ret) {
77*4882a593Smuzhiyun test_err("split item failed %d", ret);
78*4882a593Smuzhiyun goto out;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun /*
82*4882a593Smuzhiyun * Read the first slot, it should have the original key and contain only
83*4882a593Smuzhiyun * 'mary had a little'
84*4882a593Smuzhiyun */
85*4882a593Smuzhiyun btrfs_item_key_to_cpu(eb, &key, 0);
86*4882a593Smuzhiyun if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
87*4882a593Smuzhiyun key.offset != 0) {
88*4882a593Smuzhiyun test_err("invalid key at slot 0");
89*4882a593Smuzhiyun ret = -EINVAL;
90*4882a593Smuzhiyun goto out;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun item = btrfs_item_nr(0);
94*4882a593Smuzhiyun if (btrfs_item_size(eb, item) != strlen(split1)) {
95*4882a593Smuzhiyun test_err("invalid len in the first split");
96*4882a593Smuzhiyun ret = -EINVAL;
97*4882a593Smuzhiyun goto out;
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 0),
101*4882a593Smuzhiyun strlen(split1));
102*4882a593Smuzhiyun if (memcmp(buf, split1, strlen(split1))) {
103*4882a593Smuzhiyun test_err(
104*4882a593Smuzhiyun "data in the buffer doesn't match what it should in the first split have='%.*s' want '%s'",
105*4882a593Smuzhiyun (int)strlen(split1), buf, split1);
106*4882a593Smuzhiyun ret = -EINVAL;
107*4882a593Smuzhiyun goto out;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun btrfs_item_key_to_cpu(eb, &key, 1);
111*4882a593Smuzhiyun if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
112*4882a593Smuzhiyun key.offset != 3) {
113*4882a593Smuzhiyun test_err("invalid key at slot 1");
114*4882a593Smuzhiyun ret = -EINVAL;
115*4882a593Smuzhiyun goto out;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun item = btrfs_item_nr(1);
119*4882a593Smuzhiyun if (btrfs_item_size(eb, item) != strlen(split2)) {
120*4882a593Smuzhiyun test_err("invalid len in the second split");
121*4882a593Smuzhiyun ret = -EINVAL;
122*4882a593Smuzhiyun goto out;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 1),
126*4882a593Smuzhiyun strlen(split2));
127*4882a593Smuzhiyun if (memcmp(buf, split2, strlen(split2))) {
128*4882a593Smuzhiyun test_err(
129*4882a593Smuzhiyun "data in the buffer doesn't match what it should in the second split");
130*4882a593Smuzhiyun ret = -EINVAL;
131*4882a593Smuzhiyun goto out;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun key.offset = 1;
135*4882a593Smuzhiyun /* Do it again so we test memmoving the other items in the leaf */
136*4882a593Smuzhiyun ret = btrfs_split_item(NULL, root, path, &key, 4);
137*4882a593Smuzhiyun if (ret) {
138*4882a593Smuzhiyun test_err("second split item failed %d", ret);
139*4882a593Smuzhiyun goto out;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun btrfs_item_key_to_cpu(eb, &key, 0);
143*4882a593Smuzhiyun if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
144*4882a593Smuzhiyun key.offset != 0) {
145*4882a593Smuzhiyun test_err("invalid key at slot 0");
146*4882a593Smuzhiyun ret = -EINVAL;
147*4882a593Smuzhiyun goto out;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun item = btrfs_item_nr(0);
151*4882a593Smuzhiyun if (btrfs_item_size(eb, item) != strlen(split3)) {
152*4882a593Smuzhiyun test_err("invalid len in the first split");
153*4882a593Smuzhiyun ret = -EINVAL;
154*4882a593Smuzhiyun goto out;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 0),
158*4882a593Smuzhiyun strlen(split3));
159*4882a593Smuzhiyun if (memcmp(buf, split3, strlen(split3))) {
160*4882a593Smuzhiyun test_err(
161*4882a593Smuzhiyun "data in the buffer doesn't match what it should in the third split");
162*4882a593Smuzhiyun ret = -EINVAL;
163*4882a593Smuzhiyun goto out;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun btrfs_item_key_to_cpu(eb, &key, 1);
167*4882a593Smuzhiyun if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
168*4882a593Smuzhiyun key.offset != 1) {
169*4882a593Smuzhiyun test_err("invalid key at slot 1");
170*4882a593Smuzhiyun ret = -EINVAL;
171*4882a593Smuzhiyun goto out;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun item = btrfs_item_nr(1);
175*4882a593Smuzhiyun if (btrfs_item_size(eb, item) != strlen(split4)) {
176*4882a593Smuzhiyun test_err("invalid len in the second split");
177*4882a593Smuzhiyun ret = -EINVAL;
178*4882a593Smuzhiyun goto out;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 1),
182*4882a593Smuzhiyun strlen(split4));
183*4882a593Smuzhiyun if (memcmp(buf, split4, strlen(split4))) {
184*4882a593Smuzhiyun test_err(
185*4882a593Smuzhiyun "data in the buffer doesn't match what it should in the fourth split");
186*4882a593Smuzhiyun ret = -EINVAL;
187*4882a593Smuzhiyun goto out;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun btrfs_item_key_to_cpu(eb, &key, 2);
191*4882a593Smuzhiyun if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
192*4882a593Smuzhiyun key.offset != 3) {
193*4882a593Smuzhiyun test_err("invalid key at slot 2");
194*4882a593Smuzhiyun ret = -EINVAL;
195*4882a593Smuzhiyun goto out;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun item = btrfs_item_nr(2);
199*4882a593Smuzhiyun if (btrfs_item_size(eb, item) != strlen(split2)) {
200*4882a593Smuzhiyun test_err("invalid len in the second split");
201*4882a593Smuzhiyun ret = -EINVAL;
202*4882a593Smuzhiyun goto out;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 2),
206*4882a593Smuzhiyun strlen(split2));
207*4882a593Smuzhiyun if (memcmp(buf, split2, strlen(split2))) {
208*4882a593Smuzhiyun test_err(
209*4882a593Smuzhiyun "data in the buffer doesn't match what it should in the last chunk");
210*4882a593Smuzhiyun ret = -EINVAL;
211*4882a593Smuzhiyun goto out;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun out:
214*4882a593Smuzhiyun btrfs_free_path(path);
215*4882a593Smuzhiyun btrfs_free_dummy_root(root);
216*4882a593Smuzhiyun btrfs_free_dummy_fs_info(fs_info);
217*4882a593Smuzhiyun return ret;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
btrfs_test_extent_buffer_operations(u32 sectorsize,u32 nodesize)220*4882a593Smuzhiyun int btrfs_test_extent_buffer_operations(u32 sectorsize, u32 nodesize)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun test_msg("running extent buffer operation tests");
223*4882a593Smuzhiyun return test_btrfs_split_item(sectorsize, nodesize);
224*4882a593Smuzhiyun }
225