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