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 /* 65 * Passing a NULL trans handle is fine here, we have a dummy root eb 66 * and the tree is a single node (level 0). 67 */ 68 btrfs_setup_item_for_insert(NULL, root, path, &key, value_len); 69 write_extent_buffer(eb, value, btrfs_item_ptr_offset(eb, 0), 70 value_len); 71 72 key.offset = 3; 73 74 /* 75 * Passing NULL trans here should be safe because we have plenty of 76 * space in this leaf to split the item without having to split the 77 * leaf. 78 */ 79 ret = btrfs_split_item(NULL, root, path, &key, 17); 80 if (ret) { 81 test_err("split item failed %d", ret); 82 goto out; 83 } 84 85 /* 86 * Read the first slot, it should have the original key and contain only 87 * 'mary had a little' 88 */ 89 btrfs_item_key_to_cpu(eb, &key, 0); 90 if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY || 91 key.offset != 0) { 92 test_err("invalid key at slot 0"); 93 ret = -EINVAL; 94 goto out; 95 } 96 97 if (btrfs_item_size(eb, 0) != strlen(split1)) { 98 test_err("invalid len in the first split"); 99 ret = -EINVAL; 100 goto out; 101 } 102 103 read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 0), 104 strlen(split1)); 105 if (memcmp(buf, split1, strlen(split1))) { 106 test_err( 107 "data in the buffer doesn't match what it should in the first split have='%.*s' want '%s'", 108 (int)strlen(split1), buf, split1); 109 ret = -EINVAL; 110 goto out; 111 } 112 113 btrfs_item_key_to_cpu(eb, &key, 1); 114 if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY || 115 key.offset != 3) { 116 test_err("invalid key at slot 1"); 117 ret = -EINVAL; 118 goto out; 119 } 120 121 if (btrfs_item_size(eb, 1) != strlen(split2)) { 122 test_err("invalid len in the second split"); 123 ret = -EINVAL; 124 goto out; 125 } 126 127 read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 1), 128 strlen(split2)); 129 if (memcmp(buf, split2, strlen(split2))) { 130 test_err( 131 "data in the buffer doesn't match what it should in the second split"); 132 ret = -EINVAL; 133 goto out; 134 } 135 136 key.offset = 1; 137 /* Do it again so we test memmoving the other items in the leaf */ 138 ret = btrfs_split_item(NULL, root, path, &key, 4); 139 if (ret) { 140 test_err("second split item failed %d", ret); 141 goto out; 142 } 143 144 btrfs_item_key_to_cpu(eb, &key, 0); 145 if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY || 146 key.offset != 0) { 147 test_err("invalid key at slot 0"); 148 ret = -EINVAL; 149 goto out; 150 } 151 152 if (btrfs_item_size(eb, 0) != strlen(split3)) { 153 test_err("invalid len in the first split"); 154 ret = -EINVAL; 155 goto out; 156 } 157 158 read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 0), 159 strlen(split3)); 160 if (memcmp(buf, split3, strlen(split3))) { 161 test_err( 162 "data in the buffer doesn't match what it should in the third split"); 163 ret = -EINVAL; 164 goto out; 165 } 166 167 btrfs_item_key_to_cpu(eb, &key, 1); 168 if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY || 169 key.offset != 1) { 170 test_err("invalid key at slot 1"); 171 ret = -EINVAL; 172 goto out; 173 } 174 175 if (btrfs_item_size(eb, 1) != strlen(split4)) { 176 test_err("invalid len in the second split"); 177 ret = -EINVAL; 178 goto out; 179 } 180 181 read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 1), 182 strlen(split4)); 183 if (memcmp(buf, split4, strlen(split4))) { 184 test_err( 185 "data in the buffer doesn't match what it should in the fourth split"); 186 ret = -EINVAL; 187 goto out; 188 } 189 190 btrfs_item_key_to_cpu(eb, &key, 2); 191 if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY || 192 key.offset != 3) { 193 test_err("invalid key at slot 2"); 194 ret = -EINVAL; 195 goto out; 196 } 197 198 if (btrfs_item_size(eb, 2) != strlen(split2)) { 199 test_err("invalid len in the second split"); 200 ret = -EINVAL; 201 goto out; 202 } 203 204 read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 2), 205 strlen(split2)); 206 if (memcmp(buf, split2, strlen(split2))) { 207 test_err( 208 "data in the buffer doesn't match what it should in the last chunk"); 209 ret = -EINVAL; 210 goto out; 211 } 212 out: 213 btrfs_free_path(path); 214 btrfs_free_dummy_root(root); 215 btrfs_free_dummy_fs_info(fs_info); 216 return ret; 217 } 218 219 int btrfs_test_extent_buffer_operations(u32 sectorsize, u32 nodesize) 220 { 221 test_msg("running extent buffer operation tests"); 222 return test_btrfs_split_item(sectorsize, nodesize); 223 } 224
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.