1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2023 Western Digital Corporation or its affiliates. 4 */ 5 6 #include <linux/btrfs_tree.h> 7 #include "ctree.h" 8 #include "fs.h" 9 #include "accessors.h" 10 #include "transaction.h" 11 #include "disk-io.h" 12 #include "raid-stripe-tree.h" 13 #include "volumes.h" 14 #include "print-tree.h" 15 16 int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 length) 17 { 18 struct btrfs_fs_info *fs_info = trans->fs_info; 19 struct btrfs_root *stripe_root = fs_info->stripe_root; 20 struct btrfs_path *path; 21 struct btrfs_key key; 22 struct extent_buffer *leaf; 23 u64 found_start; 24 u64 found_end; 25 u64 end = start + length; 26 int slot; 27 int ret; 28 29 if (!stripe_root) 30 return 0; 31 32 path = btrfs_alloc_path(); 33 if (!path) 34 return -ENOMEM; 35 36 while (1) { 37 key.objectid = start; 38 key.type = BTRFS_RAID_STRIPE_KEY; 39 key.offset = length; 40 41 ret = btrfs_search_slot(trans, stripe_root, &key, path, -1, 1); 42 if (ret < 0) 43 break; 44 if (ret > 0) { 45 ret = 0; 46 if (path->slots[0] == 0) 47 break; 48 path->slots[0]--; 49 } 50 51 leaf = path->nodes[0]; 52 slot = path->slots[0]; 53 btrfs_item_key_to_cpu(leaf, &key, slot); 54 found_start = key.objectid; 55 found_end = found_start + key.offset; 56 57 /* That stripe ends before we start, we're done. */ 58 if (found_end <= start) 59 break; 60 61 trace_btrfs_raid_extent_delete(fs_info, start, end, 62 found_start, found_end); 63 64 ASSERT(found_start >= start && found_end <= end); 65 ret = btrfs_del_item(trans, stripe_root, path); 66 if (ret) 67 break; 68 69 btrfs_release_path(path); 70 } 71 72 btrfs_free_path(path); 73 return ret; 74 } 75 76 static int btrfs_insert_one_raid_extent(struct btrfs_trans_handle *trans, 77 struct btrfs_io_context *bioc) 78 { 79 struct btrfs_fs_info *fs_info = trans->fs_info; 80 struct btrfs_key stripe_key; 81 struct btrfs_root *stripe_root = fs_info->stripe_root; 82 const int num_stripes = btrfs_bg_type_to_factor(bioc->map_type); 83 u8 encoding = btrfs_bg_flags_to_raid_index(bioc->map_type); 84 struct btrfs_stripe_extent *stripe_extent; 85 const size_t item_size = struct_size(stripe_extent, strides, num_stripes); 86 int ret; 87 88 stripe_extent = kzalloc(item_size, GFP_NOFS); 89 if (!stripe_extent) { 90 btrfs_abort_transaction(trans, -ENOMEM); 91 btrfs_end_transaction(trans); 92 return -ENOMEM; 93 } 94 95 trace_btrfs_insert_one_raid_extent(fs_info, bioc->logical, bioc->size, 96 num_stripes); 97 btrfs_set_stack_stripe_extent_encoding(stripe_extent, encoding); 98 for (int i = 0; i < num_stripes; i++) { 99 u64 devid = bioc->stripes[i].dev->devid; 100 u64 physical = bioc->stripes[i].physical; 101 u64 length = bioc->stripes[i].length; 102 struct btrfs_raid_stride *raid_stride = &stripe_extent->strides[i]; 103 104 if (length == 0) 105 length = bioc->size; 106 107 btrfs_set_stack_raid_stride_devid(raid_stride, devid); 108 btrfs_set_stack_raid_stride_physical(raid_stride, physical); 109 } 110 111 stripe_key.objectid = bioc->logical; 112 stripe_key.type = BTRFS_RAID_STRIPE_KEY; 113 stripe_key.offset = bioc->size; 114 115 ret = btrfs_insert_item(trans, stripe_root, &stripe_key, stripe_extent, 116 item_size); 117 if (ret) 118 btrfs_abort_transaction(trans, ret); 119 120 kfree(stripe_extent); 121 122 return ret; 123 } 124 125 int btrfs_insert_raid_extent(struct btrfs_trans_handle *trans, 126 struct btrfs_ordered_extent *ordered_extent) 127 { 128 struct btrfs_io_context *bioc; 129 int ret; 130 131 if (!btrfs_fs_incompat(trans->fs_info, RAID_STRIPE_TREE)) 132 return 0; 133 134 list_for_each_entry(bioc, &ordered_extent->bioc_list, rst_ordered_entry) { 135 ret = btrfs_insert_one_raid_extent(trans, bioc); 136 if (ret) 137 return ret; 138 } 139 140 while (!list_empty(&ordered_extent->bioc_list)) { 141 bioc = list_first_entry(&ordered_extent->bioc_list, 142 typeof(*bioc), rst_ordered_entry); 143 list_del(&bioc->rst_ordered_entry); 144 btrfs_put_bioc(bioc); 145 } 146 147 return 0; 148 } 149 150 int btrfs_get_raid_extent_offset(struct btrfs_fs_info *fs_info, 151 u64 logical, u64 *length, u64 map_type, 152 u32 stripe_index, struct btrfs_io_stripe *stripe) 153 { 154 struct btrfs_root *stripe_root = fs_info->stripe_root; 155 struct btrfs_stripe_extent *stripe_extent; 156 struct btrfs_key stripe_key; 157 struct btrfs_key found_key; 158 struct btrfs_path *path; 159 struct extent_buffer *leaf; 160 const u64 end = logical + *length; 161 int num_stripes; 162 u8 encoding; 163 u64 offset; 164 u64 found_logical; 165 u64 found_length; 166 u64 found_end; 167 int slot; 168 int ret; 169 170 stripe_key.objectid = logical; 171 stripe_key.type = BTRFS_RAID_STRIPE_KEY; 172 stripe_key.offset = 0; 173 174 path = btrfs_alloc_path(); 175 if (!path) 176 return -ENOMEM; 177 178 if (stripe->is_scrub) { 179 path->skip_locking = 1; 180 path->search_commit_root = 1; 181 } 182 183 ret = btrfs_search_slot(NULL, stripe_root, &stripe_key, path, 0, 0); 184 if (ret < 0) 185 goto free_path; 186 if (ret) { 187 if (path->slots[0] != 0) 188 path->slots[0]--; 189 } 190 191 while (1) { 192 leaf = path->nodes[0]; 193 slot = path->slots[0]; 194 195 btrfs_item_key_to_cpu(leaf, &found_key, slot); 196 found_logical = found_key.objectid; 197 found_length = found_key.offset; 198 found_end = found_logical + found_length; 199 200 if (found_logical > end) { 201 ret = -ENOENT; 202 goto out; 203 } 204 205 if (in_range(logical, found_logical, found_length)) 206 break; 207 208 ret = btrfs_next_item(stripe_root, path); 209 if (ret) 210 goto out; 211 } 212 213 offset = logical - found_logical; 214 215 /* 216 * If we have a logically contiguous, but physically non-continuous 217 * range, we need to split the bio. Record the length after which we 218 * must split the bio. 219 */ 220 if (end > found_end) 221 *length -= end - found_end; 222 223 num_stripes = btrfs_num_raid_stripes(btrfs_item_size(leaf, slot)); 224 stripe_extent = btrfs_item_ptr(leaf, slot, struct btrfs_stripe_extent); 225 encoding = btrfs_stripe_extent_encoding(leaf, stripe_extent); 226 227 if (encoding != btrfs_bg_flags_to_raid_index(map_type)) { 228 ret = -EUCLEAN; 229 btrfs_handle_fs_error(fs_info, ret, 230 "on-disk stripe encoding %d doesn't match RAID index %d", 231 encoding, 232 btrfs_bg_flags_to_raid_index(map_type)); 233 goto out; 234 } 235 236 for (int i = 0; i < num_stripes; i++) { 237 struct btrfs_raid_stride *stride = &stripe_extent->strides[i]; 238 u64 devid = btrfs_raid_stride_devid(leaf, stride); 239 u64 physical = btrfs_raid_stride_physical(leaf, stride); 240 241 if (devid != stripe->dev->devid) 242 continue; 243 244 if ((map_type & BTRFS_BLOCK_GROUP_DUP) && stripe_index != i) 245 continue; 246 247 stripe->physical = physical + offset; 248 249 trace_btrfs_get_raid_extent_offset(fs_info, logical, *length, 250 stripe->physical, devid); 251 252 ret = 0; 253 goto free_path; 254 } 255 256 /* If we're here, we haven't found the requested devid in the stripe. */ 257 ret = -ENOENT; 258 out: 259 if (ret > 0) 260 ret = -ENOENT; 261 if (ret && ret != -EIO && !stripe->is_scrub) { 262 if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) 263 btrfs_print_tree(leaf, 1); 264 btrfs_err(fs_info, 265 "cannot find raid-stripe for logical [%llu, %llu] devid %llu, profile %s", 266 logical, logical + *length, stripe->dev->devid, 267 btrfs_bg_type_to_raid_name(map_type)); 268 } 269 free_path: 270 btrfs_free_path(path); 271 272 return ret; 273 } 274