raid-stripe-tree.c 7.0 KB

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