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 start += key.offset; 70 length -= key.offset; 71 if (length == 0) 72 break; 73 74 btrfs_release_path(path); 75 } 76 77 btrfs_free_path(path); 78 return ret; 79 } 80 81 static int update_raid_extent_item(struct btrfs_trans_handle *trans, 82 struct btrfs_key *key, 83 struct btrfs_stripe_extent *stripe_extent, 84 const size_t item_size) 85 { 86 struct btrfs_path *path; 87 struct extent_buffer *leaf; 88 int ret; 89 int slot; 90 91 path = btrfs_alloc_path(); 92 if (!path) 93 return -ENOMEM; 94 95 ret = btrfs_search_slot(trans, trans->fs_info->stripe_root, key, path, 96 0, 1); 97 if (ret) 98 return (ret == 1 ? ret : -EINVAL); 99 100 leaf = path->nodes[0]; 101 slot = path->slots[0]; 102 103 write_extent_buffer(leaf, stripe_extent, btrfs_item_ptr_offset(leaf, slot), 104 item_size); 105 btrfs_mark_buffer_dirty(trans, leaf); 106 btrfs_free_path(path); 107 108 return ret; 109 } 110 111 static int btrfs_insert_one_raid_extent(struct btrfs_trans_handle *trans, 112 struct btrfs_io_context *bioc) 113 { 114 struct btrfs_fs_info *fs_info = trans->fs_info; 115 struct btrfs_key stripe_key; 116 struct btrfs_root *stripe_root = fs_info->stripe_root; 117 const int num_stripes = btrfs_bg_type_to_factor(bioc->map_type); 118 struct btrfs_stripe_extent *stripe_extent; 119 const size_t item_size = struct_size(stripe_extent, strides, num_stripes); 120 int ret; 121 122 stripe_extent = kzalloc(item_size, GFP_NOFS); 123 if (!stripe_extent) { 124 btrfs_abort_transaction(trans, -ENOMEM); 125 btrfs_end_transaction(trans); 126 return -ENOMEM; 127 } 128 129 trace_btrfs_insert_one_raid_extent(fs_info, bioc->logical, bioc->size, 130 num_stripes); 131 for (int i = 0; i < num_stripes; i++) { 132 u64 devid = bioc->stripes[i].dev->devid; 133 u64 physical = bioc->stripes[i].physical; 134 u64 length = bioc->stripes[i].length; 135 struct btrfs_raid_stride *raid_stride = &stripe_extent->strides[i]; 136 137 if (length == 0) 138 length = bioc->size; 139 140 btrfs_set_stack_raid_stride_devid(raid_stride, devid); 141 btrfs_set_stack_raid_stride_physical(raid_stride, physical); 142 } 143 144 stripe_key.objectid = bioc->logical; 145 stripe_key.type = BTRFS_RAID_STRIPE_KEY; 146 stripe_key.offset = bioc->size; 147 148 ret = btrfs_insert_item(trans, stripe_root, &stripe_key, stripe_extent, 149 item_size); 150 if (ret == -EEXIST) 151 ret = update_raid_extent_item(trans, &stripe_key, stripe_extent, 152 item_size); 153 if (ret) 154 btrfs_abort_transaction(trans, ret); 155 156 kfree(stripe_extent); 157 158 return ret; 159 } 160 161 int btrfs_insert_raid_extent(struct btrfs_trans_handle *trans, 162 struct btrfs_ordered_extent *ordered_extent) 163 { 164 struct btrfs_io_context *bioc; 165 int ret; 166 167 if (!btrfs_fs_incompat(trans->fs_info, RAID_STRIPE_TREE)) 168 return 0; 169 170 list_for_each_entry(bioc, &ordered_extent->bioc_list, rst_ordered_entry) { 171 ret = btrfs_insert_one_raid_extent(trans, bioc); 172 if (ret) 173 return ret; 174 } 175 176 while (!list_empty(&ordered_extent->bioc_list)) { 177 bioc = list_first_entry(&ordered_extent->bioc_list, 178 typeof(*bioc), rst_ordered_entry); 179 list_del(&bioc->rst_ordered_entry); 180 btrfs_put_bioc(bioc); 181 } 182 183 return 0; 184 } 185 186 int btrfs_get_raid_extent_offset(struct btrfs_fs_info *fs_info, 187 u64 logical, u64 *length, u64 map_type, 188 u32 stripe_index, struct btrfs_io_stripe *stripe) 189 { 190 struct btrfs_root *stripe_root = fs_info->stripe_root; 191 struct btrfs_stripe_extent *stripe_extent; 192 struct btrfs_key stripe_key; 193 struct btrfs_key found_key; 194 struct btrfs_path *path; 195 struct extent_buffer *leaf; 196 const u64 end = logical + *length; 197 int num_stripes; 198 u64 offset; 199 u64 found_logical; 200 u64 found_length; 201 u64 found_end; 202 int slot; 203 int ret; 204 205 stripe_key.objectid = logical; 206 stripe_key.type = BTRFS_RAID_STRIPE_KEY; 207 stripe_key.offset = 0; 208 209 path = btrfs_alloc_path(); 210 if (!path) 211 return -ENOMEM; 212 213 if (stripe->rst_search_commit_root) { 214 path->skip_locking = 1; 215 path->search_commit_root = 1; 216 } 217 218 ret = btrfs_search_slot(NULL, stripe_root, &stripe_key, path, 0, 0); 219 if (ret < 0) 220 goto free_path; 221 if (ret) { 222 if (path->slots[0] != 0) 223 path->slots[0]--; 224 } 225 226 while (1) { 227 leaf = path->nodes[0]; 228 slot = path->slots[0]; 229 230 btrfs_item_key_to_cpu(leaf, &found_key, slot); 231 found_logical = found_key.objectid; 232 found_length = found_key.offset; 233 found_end = found_logical + found_length; 234 235 if (found_logical > end) { 236 ret = -ENOENT; 237 goto out; 238 } 239 240 if (in_range(logical, found_logical, found_length)) 241 break; 242 243 ret = btrfs_next_item(stripe_root, path); 244 if (ret) 245 goto out; 246 } 247 248 offset = logical - found_logical; 249 250 /* 251 * If we have a logically contiguous, but physically non-continuous 252 * range, we need to split the bio. Record the length after which we 253 * must split the bio. 254 */ 255 if (end > found_end) 256 *length -= end - found_end; 257 258 num_stripes = btrfs_num_raid_stripes(btrfs_item_size(leaf, slot)); 259 stripe_extent = btrfs_item_ptr(leaf, slot, struct btrfs_stripe_extent); 260 261 for (int i = 0; i < num_stripes; i++) { 262 struct btrfs_raid_stride *stride = &stripe_extent->strides[i]; 263 u64 devid = btrfs_raid_stride_devid(leaf, stride); 264 u64 physical = btrfs_raid_stride_physical(leaf, stride); 265 266 if (devid != stripe->dev->devid) 267 continue; 268 269 if ((map_type & BTRFS_BLOCK_GROUP_DUP) && stripe_index != i) 270 continue; 271 272 stripe->physical = physical + offset; 273 274 trace_btrfs_get_raid_extent_offset(fs_info, logical, *length, 275 stripe->physical, devid); 276 277 ret = 0; 278 goto free_path; 279 } 280 281 /* If we're here, we haven't found the requested devid in the stripe. */ 282 ret = -ENOENT; 283 out: 284 if (ret > 0) 285 ret = -ENOENT; 286 if (ret && ret != -EIO && !stripe->rst_search_commit_root) { 287 btrfs_debug(fs_info, 288 "cannot find raid-stripe for logical [%llu, %llu] devid %llu, profile %s", 289 logical, logical + *length, stripe->dev->devid, 290 btrfs_bg_type_to_raid_name(map_type)); 291 } 292 free_path: 293 btrfs_free_path(path); 294 295 return ret; 296 } 297