224 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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 13static 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 eb66 * 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 of76 * space in this leaf to split the item without having to split the77 * 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 only87 * '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 }212out:213 btrfs_free_path(path);214 btrfs_free_dummy_root(root);215 btrfs_free_dummy_fs_info(fs_info);216 return ret;217}218 219int 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