1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000,2005 Silicon Graphics, Inc.
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_trans_resv.h"
13 #include "xfs_mount.h"
14 #include "xfs_defer.h"
15 #include "xfs_trans.h"
16 #include "xfs_trans_priv.h"
17 #include "xfs_extfree_item.h"
18 #include "xfs_alloc.h"
20 #include "xfs_trace.h"
23 * This routine is called to allocate an "extent free done"
24 * log item that will hold nextents worth of extents. The
25 * caller must use all nextents extents, because we are not
26 * flexible about this at all.
28 struct xfs_efd_log_item *
29 xfs_trans_get_efd(struct xfs_trans *tp,
30 struct xfs_efi_log_item *efip,
33 struct xfs_efd_log_item *efdp;
38 efdp = xfs_efd_init(tp->t_mountp, efip, nextents);
42 * Get a log_item_desc to point at the new item.
44 xfs_trans_add_item(tp, &efdp->efd_item);
49 * Free an extent and log it to the EFD. Note that the transaction is marked
50 * dirty regardless of whether the extent free succeeds or fails to support the
51 * EFI/EFD lifecycle rules.
54 xfs_trans_free_extent(
56 struct xfs_efd_log_item *efdp,
57 xfs_fsblock_t start_block,
59 const struct xfs_owner_info *oinfo,
62 struct xfs_mount *mp = tp->t_mountp;
63 struct xfs_extent *extp;
65 xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, start_block);
66 xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp,
70 trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, ext_len);
72 error = __xfs_free_extent(tp, start_block, ext_len,
73 oinfo, XFS_AG_RESV_NONE, skip_discard);
75 * Mark the transaction dirty, even on error. This ensures the
76 * transaction is aborted, which:
78 * 1.) releases the EFI and frees the EFD
79 * 2.) shuts down the filesystem
81 tp->t_flags |= XFS_TRANS_DIRTY;
82 set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags);
84 next_extent = efdp->efd_next_extent;
85 ASSERT(next_extent < efdp->efd_format.efd_nextents);
86 extp = &(efdp->efd_format.efd_extents[next_extent]);
87 extp->ext_start = start_block;
88 extp->ext_len = ext_len;
89 efdp->efd_next_extent++;
94 /* Sort bmap items by AG. */
96 xfs_extent_free_diff_items(
101 struct xfs_mount *mp = priv;
102 struct xfs_extent_free_item *ra;
103 struct xfs_extent_free_item *rb;
105 ra = container_of(a, struct xfs_extent_free_item, xefi_list);
106 rb = container_of(b, struct xfs_extent_free_item, xefi_list);
107 return XFS_FSB_TO_AGNO(mp, ra->xefi_startblock) -
108 XFS_FSB_TO_AGNO(mp, rb->xefi_startblock);
113 xfs_extent_free_create_intent(
114 struct xfs_trans *tp,
117 struct xfs_efi_log_item *efip;
122 efip = xfs_efi_init(tp->t_mountp, count);
123 ASSERT(efip != NULL);
126 * Get a log_item_desc to point at the new item.
128 xfs_trans_add_item(tp, &efip->efi_item);
132 /* Log a free extent to the intent item. */
134 xfs_extent_free_log_item(
135 struct xfs_trans *tp,
137 struct list_head *item)
139 struct xfs_efi_log_item *efip = intent;
140 struct xfs_extent_free_item *free;
142 struct xfs_extent *extp;
144 free = container_of(item, struct xfs_extent_free_item, xefi_list);
146 tp->t_flags |= XFS_TRANS_DIRTY;
147 set_bit(XFS_LI_DIRTY, &efip->efi_item.li_flags);
150 * atomic_inc_return gives us the value after the increment;
151 * we want to use it as an array index so we need to subtract 1 from
154 next_extent = atomic_inc_return(&efip->efi_next_extent) - 1;
155 ASSERT(next_extent < efip->efi_format.efi_nextents);
156 extp = &efip->efi_format.efi_extents[next_extent];
157 extp->ext_start = free->xefi_startblock;
158 extp->ext_len = free->xefi_blockcount;
161 /* Get an EFD so we can process all the free extents. */
163 xfs_extent_free_create_done(
164 struct xfs_trans *tp,
168 return xfs_trans_get_efd(tp, intent, count);
171 /* Process a free extent. */
173 xfs_extent_free_finish_item(
174 struct xfs_trans *tp,
175 struct list_head *item,
179 struct xfs_extent_free_item *free;
182 free = container_of(item, struct xfs_extent_free_item, xefi_list);
183 error = xfs_trans_free_extent(tp, done_item,
184 free->xefi_startblock,
185 free->xefi_blockcount,
186 &free->xefi_oinfo, free->xefi_skip_discard);
191 /* Abort all pending EFIs. */
193 xfs_extent_free_abort_intent(
196 xfs_efi_release(intent);
199 /* Cancel a free extent. */
201 xfs_extent_free_cancel_item(
202 struct list_head *item)
204 struct xfs_extent_free_item *free;
206 free = container_of(item, struct xfs_extent_free_item, xefi_list);
210 const struct xfs_defer_op_type xfs_extent_free_defer_type = {
211 .max_items = XFS_EFI_MAX_FAST_EXTENTS,
212 .diff_items = xfs_extent_free_diff_items,
213 .create_intent = xfs_extent_free_create_intent,
214 .abort_intent = xfs_extent_free_abort_intent,
215 .log_item = xfs_extent_free_log_item,
216 .create_done = xfs_extent_free_create_done,
217 .finish_item = xfs_extent_free_finish_item,
218 .cancel_item = xfs_extent_free_cancel_item,
222 * AGFL blocks are accounted differently in the reserve pools and are not
223 * inserted into the busy extent list.
226 xfs_agfl_free_finish_item(
227 struct xfs_trans *tp,
228 struct list_head *item,
232 struct xfs_mount *mp = tp->t_mountp;
233 struct xfs_efd_log_item *efdp = done_item;
234 struct xfs_extent_free_item *free;
235 struct xfs_extent *extp;
236 struct xfs_buf *agbp;
242 free = container_of(item, struct xfs_extent_free_item, xefi_list);
243 ASSERT(free->xefi_blockcount == 1);
244 agno = XFS_FSB_TO_AGNO(mp, free->xefi_startblock);
245 agbno = XFS_FSB_TO_AGBNO(mp, free->xefi_startblock);
247 trace_xfs_agfl_free_deferred(mp, agno, 0, agbno, free->xefi_blockcount);
249 error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
251 error = xfs_free_agfl_block(tp, agno, agbno, agbp,
255 * Mark the transaction dirty, even on error. This ensures the
256 * transaction is aborted, which:
258 * 1.) releases the EFI and frees the EFD
259 * 2.) shuts down the filesystem
261 tp->t_flags |= XFS_TRANS_DIRTY;
262 set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags);
264 next_extent = efdp->efd_next_extent;
265 ASSERT(next_extent < efdp->efd_format.efd_nextents);
266 extp = &(efdp->efd_format.efd_extents[next_extent]);
267 extp->ext_start = free->xefi_startblock;
268 extp->ext_len = free->xefi_blockcount;
269 efdp->efd_next_extent++;
276 /* sub-type with special handling for AGFL deferred frees */
277 const struct xfs_defer_op_type xfs_agfl_free_defer_type = {
278 .max_items = XFS_EFI_MAX_FAST_EXTENTS,
279 .diff_items = xfs_extent_free_diff_items,
280 .create_intent = xfs_extent_free_create_intent,
281 .abort_intent = xfs_extent_free_abort_intent,
282 .log_item = xfs_extent_free_log_item,
283 .create_done = xfs_extent_free_create_done,
284 .finish_item = xfs_agfl_free_finish_item,
285 .cancel_item = xfs_extent_free_cancel_item,