xfs_trans_extfree.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. * Copyright (c) 2000,2005 Silicon Graphics, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it would be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write the Free Software Foundation,
  16. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "xfs.h"
  19. #include "xfs_fs.h"
  20. #include "xfs_shared.h"
  21. #include "xfs_format.h"
  22. #include "xfs_log_format.h"
  23. #include "xfs_trans_resv.h"
  24. #include "xfs_bit.h"
  25. #include "xfs_mount.h"
  26. #include "xfs_defer.h"
  27. #include "xfs_trans.h"
  28. #include "xfs_trans_priv.h"
  29. #include "xfs_extfree_item.h"
  30. #include "xfs_alloc.h"
  31. #include "xfs_bmap.h"
  32. #include "xfs_trace.h"
  33. /*
  34. * This routine is called to allocate an "extent free done"
  35. * log item that will hold nextents worth of extents. The
  36. * caller must use all nextents extents, because we are not
  37. * flexible about this at all.
  38. */
  39. struct xfs_efd_log_item *
  40. xfs_trans_get_efd(struct xfs_trans *tp,
  41. struct xfs_efi_log_item *efip,
  42. uint nextents)
  43. {
  44. struct xfs_efd_log_item *efdp;
  45. ASSERT(tp != NULL);
  46. ASSERT(nextents > 0);
  47. efdp = xfs_efd_init(tp->t_mountp, efip, nextents);
  48. ASSERT(efdp != NULL);
  49. /*
  50. * Get a log_item_desc to point at the new item.
  51. */
  52. xfs_trans_add_item(tp, &efdp->efd_item);
  53. return efdp;
  54. }
  55. /*
  56. * Free an extent and log it to the EFD. Note that the transaction is marked
  57. * dirty regardless of whether the extent free succeeds or fails to support the
  58. * EFI/EFD lifecycle rules.
  59. */
  60. int
  61. xfs_trans_free_extent(
  62. struct xfs_trans *tp,
  63. struct xfs_efd_log_item *efdp,
  64. xfs_fsblock_t start_block,
  65. xfs_extlen_t ext_len,
  66. struct xfs_owner_info *oinfo)
  67. {
  68. struct xfs_mount *mp = tp->t_mountp;
  69. uint next_extent;
  70. xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, start_block);
  71. xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, start_block);
  72. struct xfs_extent *extp;
  73. int error;
  74. trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, ext_len);
  75. error = xfs_free_extent(tp, start_block, ext_len, oinfo);
  76. /*
  77. * Mark the transaction dirty, even on error. This ensures the
  78. * transaction is aborted, which:
  79. *
  80. * 1.) releases the EFI and frees the EFD
  81. * 2.) shuts down the filesystem
  82. */
  83. tp->t_flags |= XFS_TRANS_DIRTY;
  84. efdp->efd_item.li_desc->lid_flags |= XFS_LID_DIRTY;
  85. next_extent = efdp->efd_next_extent;
  86. ASSERT(next_extent < efdp->efd_format.efd_nextents);
  87. extp = &(efdp->efd_format.efd_extents[next_extent]);
  88. extp->ext_start = start_block;
  89. extp->ext_len = ext_len;
  90. efdp->efd_next_extent++;
  91. return error;
  92. }
  93. /* Sort bmap items by AG. */
  94. static int
  95. xfs_extent_free_diff_items(
  96. void *priv,
  97. struct list_head *a,
  98. struct list_head *b)
  99. {
  100. struct xfs_mount *mp = priv;
  101. struct xfs_extent_free_item *ra;
  102. struct xfs_extent_free_item *rb;
  103. ra = container_of(a, struct xfs_extent_free_item, xefi_list);
  104. rb = container_of(b, struct xfs_extent_free_item, xefi_list);
  105. return XFS_FSB_TO_AGNO(mp, ra->xefi_startblock) -
  106. XFS_FSB_TO_AGNO(mp, rb->xefi_startblock);
  107. }
  108. /* Get an EFI. */
  109. STATIC void *
  110. xfs_extent_free_create_intent(
  111. struct xfs_trans *tp,
  112. unsigned int count)
  113. {
  114. struct xfs_efi_log_item *efip;
  115. ASSERT(tp != NULL);
  116. ASSERT(count > 0);
  117. efip = xfs_efi_init(tp->t_mountp, count);
  118. ASSERT(efip != NULL);
  119. /*
  120. * Get a log_item_desc to point at the new item.
  121. */
  122. xfs_trans_add_item(tp, &efip->efi_item);
  123. return efip;
  124. }
  125. /* Log a free extent to the intent item. */
  126. STATIC void
  127. xfs_extent_free_log_item(
  128. struct xfs_trans *tp,
  129. void *intent,
  130. struct list_head *item)
  131. {
  132. struct xfs_efi_log_item *efip = intent;
  133. struct xfs_extent_free_item *free;
  134. uint next_extent;
  135. struct xfs_extent *extp;
  136. free = container_of(item, struct xfs_extent_free_item, xefi_list);
  137. tp->t_flags |= XFS_TRANS_DIRTY;
  138. efip->efi_item.li_desc->lid_flags |= XFS_LID_DIRTY;
  139. /*
  140. * atomic_inc_return gives us the value after the increment;
  141. * we want to use it as an array index so we need to subtract 1 from
  142. * it.
  143. */
  144. next_extent = atomic_inc_return(&efip->efi_next_extent) - 1;
  145. ASSERT(next_extent < efip->efi_format.efi_nextents);
  146. extp = &efip->efi_format.efi_extents[next_extent];
  147. extp->ext_start = free->xefi_startblock;
  148. extp->ext_len = free->xefi_blockcount;
  149. }
  150. /* Get an EFD so we can process all the free extents. */
  151. STATIC void *
  152. xfs_extent_free_create_done(
  153. struct xfs_trans *tp,
  154. void *intent,
  155. unsigned int count)
  156. {
  157. return xfs_trans_get_efd(tp, intent, count);
  158. }
  159. /* Process a free extent. */
  160. STATIC int
  161. xfs_extent_free_finish_item(
  162. struct xfs_trans *tp,
  163. struct xfs_defer_ops *dop,
  164. struct list_head *item,
  165. void *done_item,
  166. void **state)
  167. {
  168. struct xfs_extent_free_item *free;
  169. int error;
  170. free = container_of(item, struct xfs_extent_free_item, xefi_list);
  171. error = xfs_trans_free_extent(tp, done_item,
  172. free->xefi_startblock,
  173. free->xefi_blockcount,
  174. &free->xefi_oinfo);
  175. kmem_free(free);
  176. return error;
  177. }
  178. /* Abort all pending EFIs. */
  179. STATIC void
  180. xfs_extent_free_abort_intent(
  181. void *intent)
  182. {
  183. xfs_efi_release(intent);
  184. }
  185. /* Cancel a free extent. */
  186. STATIC void
  187. xfs_extent_free_cancel_item(
  188. struct list_head *item)
  189. {
  190. struct xfs_extent_free_item *free;
  191. free = container_of(item, struct xfs_extent_free_item, xefi_list);
  192. kmem_free(free);
  193. }
  194. static const struct xfs_defer_op_type xfs_extent_free_defer_type = {
  195. .type = XFS_DEFER_OPS_TYPE_FREE,
  196. .max_items = XFS_EFI_MAX_FAST_EXTENTS,
  197. .diff_items = xfs_extent_free_diff_items,
  198. .create_intent = xfs_extent_free_create_intent,
  199. .abort_intent = xfs_extent_free_abort_intent,
  200. .log_item = xfs_extent_free_log_item,
  201. .create_done = xfs_extent_free_create_done,
  202. .finish_item = xfs_extent_free_finish_item,
  203. .cancel_item = xfs_extent_free_cancel_item,
  204. };
  205. /* Register the deferred op type. */
  206. void
  207. xfs_extent_free_init_defer_op(void)
  208. {
  209. xfs_defer_init_op_type(&xfs_extent_free_defer_type);
  210. }