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