xfs_trans_rmap.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. * Copyright (C) 2016 Oracle. All Rights Reserved.
  3. *
  4. * Author: Darrick J. Wong <darrick.wong@oracle.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it would be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write the Free Software Foundation,
  18. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. #include "xfs.h"
  21. #include "xfs_fs.h"
  22. #include "xfs_shared.h"
  23. #include "xfs_format.h"
  24. #include "xfs_log_format.h"
  25. #include "xfs_trans_resv.h"
  26. #include "xfs_mount.h"
  27. #include "xfs_defer.h"
  28. #include "xfs_trans.h"
  29. #include "xfs_trans_priv.h"
  30. #include "xfs_rmap_item.h"
  31. #include "xfs_alloc.h"
  32. #include "xfs_rmap.h"
  33. /* Set the map extent flags for this reverse mapping. */
  34. static void
  35. xfs_trans_set_rmap_flags(
  36. struct xfs_map_extent *rmap,
  37. enum xfs_rmap_intent_type type,
  38. int whichfork,
  39. xfs_exntst_t state)
  40. {
  41. rmap->me_flags = 0;
  42. if (state == XFS_EXT_UNWRITTEN)
  43. rmap->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN;
  44. if (whichfork == XFS_ATTR_FORK)
  45. rmap->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK;
  46. switch (type) {
  47. case XFS_RMAP_MAP:
  48. rmap->me_flags |= XFS_RMAP_EXTENT_MAP;
  49. break;
  50. case XFS_RMAP_MAP_SHARED:
  51. rmap->me_flags |= XFS_RMAP_EXTENT_MAP_SHARED;
  52. break;
  53. case XFS_RMAP_UNMAP:
  54. rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP;
  55. break;
  56. case XFS_RMAP_UNMAP_SHARED:
  57. rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP_SHARED;
  58. break;
  59. case XFS_RMAP_CONVERT:
  60. rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT;
  61. break;
  62. case XFS_RMAP_CONVERT_SHARED:
  63. rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT_SHARED;
  64. break;
  65. case XFS_RMAP_ALLOC:
  66. rmap->me_flags |= XFS_RMAP_EXTENT_ALLOC;
  67. break;
  68. case XFS_RMAP_FREE:
  69. rmap->me_flags |= XFS_RMAP_EXTENT_FREE;
  70. break;
  71. default:
  72. ASSERT(0);
  73. }
  74. }
  75. struct xfs_rud_log_item *
  76. xfs_trans_get_rud(
  77. struct xfs_trans *tp,
  78. struct xfs_rui_log_item *ruip)
  79. {
  80. struct xfs_rud_log_item *rudp;
  81. rudp = xfs_rud_init(tp->t_mountp, ruip);
  82. xfs_trans_add_item(tp, &rudp->rud_item);
  83. return rudp;
  84. }
  85. /*
  86. * Finish an rmap update and log it to the RUD. Note that the transaction is
  87. * marked dirty regardless of whether the rmap update succeeds or fails to
  88. * support the RUI/RUD lifecycle rules.
  89. */
  90. int
  91. xfs_trans_log_finish_rmap_update(
  92. struct xfs_trans *tp,
  93. struct xfs_rud_log_item *rudp,
  94. enum xfs_rmap_intent_type type,
  95. __uint64_t owner,
  96. int whichfork,
  97. xfs_fileoff_t startoff,
  98. xfs_fsblock_t startblock,
  99. xfs_filblks_t blockcount,
  100. xfs_exntst_t state,
  101. struct xfs_btree_cur **pcur)
  102. {
  103. int error;
  104. error = xfs_rmap_finish_one(tp, type, owner, whichfork, startoff,
  105. startblock, blockcount, state, pcur);
  106. /*
  107. * Mark the transaction dirty, even on error. This ensures the
  108. * transaction is aborted, which:
  109. *
  110. * 1.) releases the RUI and frees the RUD
  111. * 2.) shuts down the filesystem
  112. */
  113. tp->t_flags |= XFS_TRANS_DIRTY;
  114. rudp->rud_item.li_desc->lid_flags |= XFS_LID_DIRTY;
  115. return error;
  116. }
  117. /* Sort rmap intents by AG. */
  118. static int
  119. xfs_rmap_update_diff_items(
  120. void *priv,
  121. struct list_head *a,
  122. struct list_head *b)
  123. {
  124. struct xfs_mount *mp = priv;
  125. struct xfs_rmap_intent *ra;
  126. struct xfs_rmap_intent *rb;
  127. ra = container_of(a, struct xfs_rmap_intent, ri_list);
  128. rb = container_of(b, struct xfs_rmap_intent, ri_list);
  129. return XFS_FSB_TO_AGNO(mp, ra->ri_bmap.br_startblock) -
  130. XFS_FSB_TO_AGNO(mp, rb->ri_bmap.br_startblock);
  131. }
  132. /* Get an RUI. */
  133. STATIC void *
  134. xfs_rmap_update_create_intent(
  135. struct xfs_trans *tp,
  136. unsigned int count)
  137. {
  138. struct xfs_rui_log_item *ruip;
  139. ASSERT(tp != NULL);
  140. ASSERT(count > 0);
  141. ruip = xfs_rui_init(tp->t_mountp, count);
  142. ASSERT(ruip != NULL);
  143. /*
  144. * Get a log_item_desc to point at the new item.
  145. */
  146. xfs_trans_add_item(tp, &ruip->rui_item);
  147. return ruip;
  148. }
  149. /* Log rmap updates in the intent item. */
  150. STATIC void
  151. xfs_rmap_update_log_item(
  152. struct xfs_trans *tp,
  153. void *intent,
  154. struct list_head *item)
  155. {
  156. struct xfs_rui_log_item *ruip = intent;
  157. struct xfs_rmap_intent *rmap;
  158. uint next_extent;
  159. struct xfs_map_extent *map;
  160. rmap = container_of(item, struct xfs_rmap_intent, ri_list);
  161. tp->t_flags |= XFS_TRANS_DIRTY;
  162. ruip->rui_item.li_desc->lid_flags |= XFS_LID_DIRTY;
  163. /*
  164. * atomic_inc_return gives us the value after the increment;
  165. * we want to use it as an array index so we need to subtract 1 from
  166. * it.
  167. */
  168. next_extent = atomic_inc_return(&ruip->rui_next_extent) - 1;
  169. ASSERT(next_extent < ruip->rui_format.rui_nextents);
  170. map = &ruip->rui_format.rui_extents[next_extent];
  171. map->me_owner = rmap->ri_owner;
  172. map->me_startblock = rmap->ri_bmap.br_startblock;
  173. map->me_startoff = rmap->ri_bmap.br_startoff;
  174. map->me_len = rmap->ri_bmap.br_blockcount;
  175. xfs_trans_set_rmap_flags(map, rmap->ri_type, rmap->ri_whichfork,
  176. rmap->ri_bmap.br_state);
  177. }
  178. /* Get an RUD so we can process all the deferred rmap updates. */
  179. STATIC void *
  180. xfs_rmap_update_create_done(
  181. struct xfs_trans *tp,
  182. void *intent,
  183. unsigned int count)
  184. {
  185. return xfs_trans_get_rud(tp, intent);
  186. }
  187. /* Process a deferred rmap update. */
  188. STATIC int
  189. xfs_rmap_update_finish_item(
  190. struct xfs_trans *tp,
  191. struct xfs_defer_ops *dop,
  192. struct list_head *item,
  193. void *done_item,
  194. void **state)
  195. {
  196. struct xfs_rmap_intent *rmap;
  197. int error;
  198. rmap = container_of(item, struct xfs_rmap_intent, ri_list);
  199. error = xfs_trans_log_finish_rmap_update(tp, done_item,
  200. rmap->ri_type,
  201. rmap->ri_owner, rmap->ri_whichfork,
  202. rmap->ri_bmap.br_startoff,
  203. rmap->ri_bmap.br_startblock,
  204. rmap->ri_bmap.br_blockcount,
  205. rmap->ri_bmap.br_state,
  206. (struct xfs_btree_cur **)state);
  207. kmem_free(rmap);
  208. return error;
  209. }
  210. /* Clean up after processing deferred rmaps. */
  211. STATIC void
  212. xfs_rmap_update_finish_cleanup(
  213. struct xfs_trans *tp,
  214. void *state,
  215. int error)
  216. {
  217. struct xfs_btree_cur *rcur = state;
  218. xfs_rmap_finish_one_cleanup(tp, rcur, error);
  219. }
  220. /* Abort all pending RUIs. */
  221. STATIC void
  222. xfs_rmap_update_abort_intent(
  223. void *intent)
  224. {
  225. xfs_rui_release(intent);
  226. }
  227. /* Cancel a deferred rmap update. */
  228. STATIC void
  229. xfs_rmap_update_cancel_item(
  230. struct list_head *item)
  231. {
  232. struct xfs_rmap_intent *rmap;
  233. rmap = container_of(item, struct xfs_rmap_intent, ri_list);
  234. kmem_free(rmap);
  235. }
  236. static const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
  237. .type = XFS_DEFER_OPS_TYPE_RMAP,
  238. .max_items = XFS_RUI_MAX_FAST_EXTENTS,
  239. .diff_items = xfs_rmap_update_diff_items,
  240. .create_intent = xfs_rmap_update_create_intent,
  241. .abort_intent = xfs_rmap_update_abort_intent,
  242. .log_item = xfs_rmap_update_log_item,
  243. .create_done = xfs_rmap_update_create_done,
  244. .finish_item = xfs_rmap_update_finish_item,
  245. .finish_cleanup = xfs_rmap_update_finish_cleanup,
  246. .cancel_item = xfs_rmap_update_cancel_item,
  247. };
  248. /* Register the deferred op type. */
  249. void
  250. xfs_rmap_update_init_defer_op(void)
  251. {
  252. xfs_defer_init_op_type(&xfs_rmap_update_defer_type);
  253. }