xfs_trans_refcount.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2016 Oracle. All Rights Reserved.
  4. * Author: Darrick J. Wong <darrick.wong@oracle.com>
  5. */
  6. #include "xfs.h"
  7. #include "xfs_fs.h"
  8. #include "xfs_shared.h"
  9. #include "xfs_format.h"
  10. #include "xfs_log_format.h"
  11. #include "xfs_trans_resv.h"
  12. #include "xfs_mount.h"
  13. #include "xfs_defer.h"
  14. #include "xfs_trans.h"
  15. #include "xfs_trans_priv.h"
  16. #include "xfs_refcount_item.h"
  17. #include "xfs_alloc.h"
  18. #include "xfs_refcount.h"
  19. /*
  20. * This routine is called to allocate a "refcount update done"
  21. * log item.
  22. */
  23. struct xfs_cud_log_item *
  24. xfs_trans_get_cud(
  25. struct xfs_trans *tp,
  26. struct xfs_cui_log_item *cuip)
  27. {
  28. struct xfs_cud_log_item *cudp;
  29. cudp = xfs_cud_init(tp->t_mountp, cuip);
  30. xfs_trans_add_item(tp, &cudp->cud_item);
  31. return cudp;
  32. }
  33. /*
  34. * Finish an refcount update and log it to the CUD. Note that the
  35. * transaction is marked dirty regardless of whether the refcount
  36. * update succeeds or fails to support the CUI/CUD lifecycle rules.
  37. */
  38. int
  39. xfs_trans_log_finish_refcount_update(
  40. struct xfs_trans *tp,
  41. struct xfs_cud_log_item *cudp,
  42. struct xfs_defer_ops *dop,
  43. enum xfs_refcount_intent_type type,
  44. xfs_fsblock_t startblock,
  45. xfs_extlen_t blockcount,
  46. xfs_fsblock_t *new_fsb,
  47. xfs_extlen_t *new_len,
  48. struct xfs_btree_cur **pcur)
  49. {
  50. int error;
  51. error = xfs_refcount_finish_one(tp, dop, type, startblock,
  52. blockcount, new_fsb, new_len, pcur);
  53. /*
  54. * Mark the transaction dirty, even on error. This ensures the
  55. * transaction is aborted, which:
  56. *
  57. * 1.) releases the CUI and frees the CUD
  58. * 2.) shuts down the filesystem
  59. */
  60. tp->t_flags |= XFS_TRANS_DIRTY;
  61. set_bit(XFS_LI_DIRTY, &cudp->cud_item.li_flags);
  62. return error;
  63. }
  64. /* Sort refcount intents by AG. */
  65. static int
  66. xfs_refcount_update_diff_items(
  67. void *priv,
  68. struct list_head *a,
  69. struct list_head *b)
  70. {
  71. struct xfs_mount *mp = priv;
  72. struct xfs_refcount_intent *ra;
  73. struct xfs_refcount_intent *rb;
  74. ra = container_of(a, struct xfs_refcount_intent, ri_list);
  75. rb = container_of(b, struct xfs_refcount_intent, ri_list);
  76. return XFS_FSB_TO_AGNO(mp, ra->ri_startblock) -
  77. XFS_FSB_TO_AGNO(mp, rb->ri_startblock);
  78. }
  79. /* Get an CUI. */
  80. STATIC void *
  81. xfs_refcount_update_create_intent(
  82. struct xfs_trans *tp,
  83. unsigned int count)
  84. {
  85. struct xfs_cui_log_item *cuip;
  86. ASSERT(tp != NULL);
  87. ASSERT(count > 0);
  88. cuip = xfs_cui_init(tp->t_mountp, count);
  89. ASSERT(cuip != NULL);
  90. /*
  91. * Get a log_item_desc to point at the new item.
  92. */
  93. xfs_trans_add_item(tp, &cuip->cui_item);
  94. return cuip;
  95. }
  96. /* Set the phys extent flags for this reverse mapping. */
  97. static void
  98. xfs_trans_set_refcount_flags(
  99. struct xfs_phys_extent *refc,
  100. enum xfs_refcount_intent_type type)
  101. {
  102. refc->pe_flags = 0;
  103. switch (type) {
  104. case XFS_REFCOUNT_INCREASE:
  105. case XFS_REFCOUNT_DECREASE:
  106. case XFS_REFCOUNT_ALLOC_COW:
  107. case XFS_REFCOUNT_FREE_COW:
  108. refc->pe_flags |= type;
  109. break;
  110. default:
  111. ASSERT(0);
  112. }
  113. }
  114. /* Log refcount updates in the intent item. */
  115. STATIC void
  116. xfs_refcount_update_log_item(
  117. struct xfs_trans *tp,
  118. void *intent,
  119. struct list_head *item)
  120. {
  121. struct xfs_cui_log_item *cuip = intent;
  122. struct xfs_refcount_intent *refc;
  123. uint next_extent;
  124. struct xfs_phys_extent *ext;
  125. refc = container_of(item, struct xfs_refcount_intent, ri_list);
  126. tp->t_flags |= XFS_TRANS_DIRTY;
  127. set_bit(XFS_LI_DIRTY, &cuip->cui_item.li_flags);
  128. /*
  129. * atomic_inc_return gives us the value after the increment;
  130. * we want to use it as an array index so we need to subtract 1 from
  131. * it.
  132. */
  133. next_extent = atomic_inc_return(&cuip->cui_next_extent) - 1;
  134. ASSERT(next_extent < cuip->cui_format.cui_nextents);
  135. ext = &cuip->cui_format.cui_extents[next_extent];
  136. ext->pe_startblock = refc->ri_startblock;
  137. ext->pe_len = refc->ri_blockcount;
  138. xfs_trans_set_refcount_flags(ext, refc->ri_type);
  139. }
  140. /* Get an CUD so we can process all the deferred refcount updates. */
  141. STATIC void *
  142. xfs_refcount_update_create_done(
  143. struct xfs_trans *tp,
  144. void *intent,
  145. unsigned int count)
  146. {
  147. return xfs_trans_get_cud(tp, intent);
  148. }
  149. /* Process a deferred refcount update. */
  150. STATIC int
  151. xfs_refcount_update_finish_item(
  152. struct xfs_trans *tp,
  153. struct xfs_defer_ops *dop,
  154. struct list_head *item,
  155. void *done_item,
  156. void **state)
  157. {
  158. struct xfs_refcount_intent *refc;
  159. xfs_fsblock_t new_fsb;
  160. xfs_extlen_t new_aglen;
  161. int error;
  162. refc = container_of(item, struct xfs_refcount_intent, ri_list);
  163. error = xfs_trans_log_finish_refcount_update(tp, done_item, dop,
  164. refc->ri_type,
  165. refc->ri_startblock,
  166. refc->ri_blockcount,
  167. &new_fsb, &new_aglen,
  168. (struct xfs_btree_cur **)state);
  169. /* Did we run out of reservation? Requeue what we didn't finish. */
  170. if (!error && new_aglen > 0) {
  171. ASSERT(refc->ri_type == XFS_REFCOUNT_INCREASE ||
  172. refc->ri_type == XFS_REFCOUNT_DECREASE);
  173. refc->ri_startblock = new_fsb;
  174. refc->ri_blockcount = new_aglen;
  175. return -EAGAIN;
  176. }
  177. kmem_free(refc);
  178. return error;
  179. }
  180. /* Clean up after processing deferred refcounts. */
  181. STATIC void
  182. xfs_refcount_update_finish_cleanup(
  183. struct xfs_trans *tp,
  184. void *state,
  185. int error)
  186. {
  187. struct xfs_btree_cur *rcur = state;
  188. xfs_refcount_finish_one_cleanup(tp, rcur, error);
  189. }
  190. /* Abort all pending CUIs. */
  191. STATIC void
  192. xfs_refcount_update_abort_intent(
  193. void *intent)
  194. {
  195. xfs_cui_release(intent);
  196. }
  197. /* Cancel a deferred refcount update. */
  198. STATIC void
  199. xfs_refcount_update_cancel_item(
  200. struct list_head *item)
  201. {
  202. struct xfs_refcount_intent *refc;
  203. refc = container_of(item, struct xfs_refcount_intent, ri_list);
  204. kmem_free(refc);
  205. }
  206. static const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
  207. .type = XFS_DEFER_OPS_TYPE_REFCOUNT,
  208. .max_items = XFS_CUI_MAX_FAST_EXTENTS,
  209. .diff_items = xfs_refcount_update_diff_items,
  210. .create_intent = xfs_refcount_update_create_intent,
  211. .abort_intent = xfs_refcount_update_abort_intent,
  212. .log_item = xfs_refcount_update_log_item,
  213. .create_done = xfs_refcount_update_create_done,
  214. .finish_item = xfs_refcount_update_finish_item,
  215. .finish_cleanup = xfs_refcount_update_finish_cleanup,
  216. .cancel_item = xfs_refcount_update_cancel_item,
  217. };
  218. /* Register the deferred op type. */
  219. void
  220. xfs_refcount_update_init_defer_op(void)
  221. {
  222. xfs_defer_init_op_type(&xfs_refcount_update_defer_type);
  223. }