xref: /openbmc/linux/fs/xfs/xfs_extfree_item.c (revision b742d7b4)
10b61f8a4SDave Chinner // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
37b718769SNathan Scott  * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
47b718769SNathan Scott  * All Rights Reserved.
51da177e4SLinus Torvalds  */
61da177e4SLinus Torvalds #include "xfs.h"
7a844f451SNathan Scott #include "xfs_fs.h"
84fb6e8adSChristoph Hellwig #include "xfs_format.h"
9239880efSDave Chinner #include "xfs_log_format.h"
10239880efSDave Chinner #include "xfs_trans_resv.h"
11dc42375dSDarrick J. Wong #include "xfs_bit.h"
125467b34bSDarrick J. Wong #include "xfs_shared.h"
131da177e4SLinus Torvalds #include "xfs_mount.h"
1408d3e84fSDave Chinner #include "xfs_ag.h"
1581f40041SChristoph Hellwig #include "xfs_defer.h"
16239880efSDave Chinner #include "xfs_trans.h"
171da177e4SLinus Torvalds #include "xfs_trans_priv.h"
181da177e4SLinus Torvalds #include "xfs_extfree_item.h"
191234351cSChristoph Hellwig #include "xfs_log.h"
20340785ccSDarrick J. Wong #include "xfs_btree.h"
21340785ccSDarrick J. Wong #include "xfs_rmap.h"
2281f40041SChristoph Hellwig #include "xfs_alloc.h"
2381f40041SChristoph Hellwig #include "xfs_bmap.h"
2481f40041SChristoph Hellwig #include "xfs_trace.h"
25a5155b87SDarrick J. Wong #include "xfs_error.h"
269817aa80SDarrick J. Wong #include "xfs_log_priv.h"
2786ffa471SDarrick J. Wong #include "xfs_log_recover.h"
281da177e4SLinus Torvalds 
29182696fbSDarrick J. Wong struct kmem_cache	*xfs_efi_cache;
30182696fbSDarrick J. Wong struct kmem_cache	*xfs_efd_cache;
311da177e4SLinus Torvalds 
3210d0c6e0SDarrick J. Wong static const struct xfs_item_ops xfs_efi_item_ops;
3310d0c6e0SDarrick J. Wong 
347bfa31d8SChristoph Hellwig static inline struct xfs_efi_log_item *EFI_ITEM(struct xfs_log_item *lip)
357bfa31d8SChristoph Hellwig {
367bfa31d8SChristoph Hellwig 	return container_of(lip, struct xfs_efi_log_item, efi_item);
377bfa31d8SChristoph Hellwig }
381da177e4SLinus Torvalds 
399817aa80SDarrick J. Wong STATIC void
407bfa31d8SChristoph Hellwig xfs_efi_item_free(
417bfa31d8SChristoph Hellwig 	struct xfs_efi_log_item	*efip)
427d795ca3SChristoph Hellwig {
43b1c5ebb2SDave Chinner 	kmem_free(efip->efi_item.li_lv_shadow);
447bfa31d8SChristoph Hellwig 	if (efip->efi_format.efi_nextents > XFS_EFI_MAX_FAST_EXTENTS)
45f0e2d93cSDenys Vlasenko 		kmem_free(efip);
467bfa31d8SChristoph Hellwig 	else
47182696fbSDarrick J. Wong 		kmem_cache_free(xfs_efi_cache, efip);
487d795ca3SChristoph Hellwig }
491da177e4SLinus Torvalds 
501da177e4SLinus Torvalds /*
510612d116SDave Chinner  * Freeing the efi requires that we remove it from the AIL if it has already
520612d116SDave Chinner  * been placed there. However, the EFI may not yet have been placed in the AIL
530612d116SDave Chinner  * when called by xfs_efi_release() from EFD processing due to the ordering of
540612d116SDave Chinner  * committed vs unpin operations in bulk insert operations. Hence the reference
550612d116SDave Chinner  * count to ensure only the last caller frees the EFI.
560612d116SDave Chinner  */
5710d0c6e0SDarrick J. Wong STATIC void
580612d116SDave Chinner xfs_efi_release(
590612d116SDave Chinner 	struct xfs_efi_log_item	*efip)
600612d116SDave Chinner {
610612d116SDave Chinner 	ASSERT(atomic_read(&efip->efi_refcount) > 0);
623512fc1eSDave Chinner 	if (!atomic_dec_and_test(&efip->efi_refcount))
633512fc1eSDave Chinner 		return;
643512fc1eSDave Chinner 
653512fc1eSDave Chinner 	xfs_trans_ail_delete(&efip->efi_item, 0);
660612d116SDave Chinner 	xfs_efi_item_free(efip);
670612d116SDave Chinner }
680612d116SDave Chinner 
69166d1368SDave Chinner STATIC void
70166d1368SDave Chinner xfs_efi_item_size(
71166d1368SDave Chinner 	struct xfs_log_item	*lip,
72166d1368SDave Chinner 	int			*nvecs,
73166d1368SDave Chinner 	int			*nbytes)
74166d1368SDave Chinner {
753c5aaaceSDarrick J. Wong 	struct xfs_efi_log_item	*efip = EFI_ITEM(lip);
763c5aaaceSDarrick J. Wong 
77166d1368SDave Chinner 	*nvecs += 1;
783c5aaaceSDarrick J. Wong 	*nbytes += xfs_efi_log_format_sizeof(efip->efi_format.efi_nextents);
791da177e4SLinus Torvalds }
801da177e4SLinus Torvalds 
811da177e4SLinus Torvalds /*
821da177e4SLinus Torvalds  * This is called to fill in the vector of log iovecs for the
831da177e4SLinus Torvalds  * given efi log item. We use only 1 iovec, and we point that
841da177e4SLinus Torvalds  * at the efi_log_format structure embedded in the efi item.
851da177e4SLinus Torvalds  * It is at this point that we assert that all of the extent
861da177e4SLinus Torvalds  * slots in the efi item have been filled.
871da177e4SLinus Torvalds  */
881da177e4SLinus Torvalds STATIC void
897bfa31d8SChristoph Hellwig xfs_efi_item_format(
907bfa31d8SChristoph Hellwig 	struct xfs_log_item	*lip,
91bde7cff6SChristoph Hellwig 	struct xfs_log_vec	*lv)
921da177e4SLinus Torvalds {
937bfa31d8SChristoph Hellwig 	struct xfs_efi_log_item	*efip = EFI_ITEM(lip);
94bde7cff6SChristoph Hellwig 	struct xfs_log_iovec	*vecp = NULL;
951da177e4SLinus Torvalds 
96b199c8a4SDave Chinner 	ASSERT(atomic_read(&efip->efi_next_extent) ==
97b199c8a4SDave Chinner 				efip->efi_format.efi_nextents);
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds 	efip->efi_format.efi_type = XFS_LI_EFI;
1001da177e4SLinus Torvalds 	efip->efi_format.efi_size = 1;
1011da177e4SLinus Torvalds 
102bde7cff6SChristoph Hellwig 	xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFI_FORMAT,
1031234351cSChristoph Hellwig 			&efip->efi_format,
1043c5aaaceSDarrick J. Wong 			xfs_efi_log_format_sizeof(efip->efi_format.efi_nextents));
1051da177e4SLinus Torvalds }
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds 
1081da177e4SLinus Torvalds /*
1098d99fe92SBrian Foster  * The unpin operation is the last place an EFI is manipulated in the log. It is
1108d99fe92SBrian Foster  * either inserted in the AIL or aborted in the event of a log I/O error. In
1118d99fe92SBrian Foster  * either case, the EFI transaction has been successfully committed to make it
1128d99fe92SBrian Foster  * this far. Therefore, we expect whoever committed the EFI to either construct
1138d99fe92SBrian Foster  * and commit the EFD or drop the EFD's reference in the event of error. Simply
1148d99fe92SBrian Foster  * drop the log's EFI reference now that the log is done with it.
1151da177e4SLinus Torvalds  */
1161da177e4SLinus Torvalds STATIC void
1177bfa31d8SChristoph Hellwig xfs_efi_item_unpin(
1187bfa31d8SChristoph Hellwig 	struct xfs_log_item	*lip,
1197bfa31d8SChristoph Hellwig 	int			remove)
1201da177e4SLinus Torvalds {
1217bfa31d8SChristoph Hellwig 	struct xfs_efi_log_item	*efip = EFI_ITEM(lip);
1225e4b5386SBrian Foster 	xfs_efi_release(efip);
1231da177e4SLinus Torvalds }
1241da177e4SLinus Torvalds 
1251da177e4SLinus Torvalds /*
1268d99fe92SBrian Foster  * The EFI has been either committed or aborted if the transaction has been
1278d99fe92SBrian Foster  * cancelled. If the transaction was cancelled, an EFD isn't going to be
1288d99fe92SBrian Foster  * constructed and thus we free the EFI here directly.
1298d99fe92SBrian Foster  */
1301da177e4SLinus Torvalds STATIC void
131ddf92053SChristoph Hellwig xfs_efi_item_release(
1327bfa31d8SChristoph Hellwig 	struct xfs_log_item	*lip)
1331da177e4SLinus Torvalds {
1340612d116SDave Chinner 	xfs_efi_release(EFI_ITEM(lip));
1351da177e4SLinus Torvalds }
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds /*
1381da177e4SLinus Torvalds  * Allocate and initialize an efi item with the given number of extents.
1391da177e4SLinus Torvalds  */
1409817aa80SDarrick J. Wong STATIC struct xfs_efi_log_item *
1417bfa31d8SChristoph Hellwig xfs_efi_init(
1427bfa31d8SChristoph Hellwig 	struct xfs_mount	*mp,
1431da177e4SLinus Torvalds 	uint			nextents)
1441da177e4SLinus Torvalds 
1451da177e4SLinus Torvalds {
1467bfa31d8SChristoph Hellwig 	struct xfs_efi_log_item	*efip;
1471da177e4SLinus Torvalds 
1481da177e4SLinus Torvalds 	ASSERT(nextents > 0);
1491da177e4SLinus Torvalds 	if (nextents > XFS_EFI_MAX_FAST_EXTENTS) {
1503c5aaaceSDarrick J. Wong 		efip = kzalloc(xfs_efi_log_item_sizeof(nextents),
1513c5aaaceSDarrick J. Wong 				GFP_KERNEL | __GFP_NOFAIL);
1521da177e4SLinus Torvalds 	} else {
153182696fbSDarrick J. Wong 		efip = kmem_cache_zalloc(xfs_efi_cache,
15432a2b11fSCarlos Maiolino 					 GFP_KERNEL | __GFP_NOFAIL);
1551da177e4SLinus Torvalds 	}
1561da177e4SLinus Torvalds 
15743f5efc5SDave Chinner 	xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops);
1581da177e4SLinus Torvalds 	efip->efi_format.efi_nextents = nextents;
159db9d67d6SChristoph Hellwig 	efip->efi_format.efi_id = (uintptr_t)(void *)efip;
160b199c8a4SDave Chinner 	atomic_set(&efip->efi_next_extent, 0);
161666d644cSDave Chinner 	atomic_set(&efip->efi_refcount, 2);
1621da177e4SLinus Torvalds 
1637bfa31d8SChristoph Hellwig 	return efip;
1641da177e4SLinus Torvalds }
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds /*
1676d192a9bSTim Shimmin  * Copy an EFI format buffer from the given buf, and into the destination
1686d192a9bSTim Shimmin  * EFI format structure.
1696d192a9bSTim Shimmin  * The given buffer can be in 32 bit or 64 bit form (which has different padding),
1706d192a9bSTim Shimmin  * one of which will be the native format for this kernel.
1716d192a9bSTim Shimmin  * It will handle the conversion of formats if necessary.
1726d192a9bSTim Shimmin  */
1739817aa80SDarrick J. Wong STATIC int
1746d192a9bSTim Shimmin xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)
1756d192a9bSTim Shimmin {
1764e0d5f92SChristoph Hellwig 	xfs_efi_log_format_t *src_efi_fmt = buf->i_addr;
1776d192a9bSTim Shimmin 	uint i;
1783c5aaaceSDarrick J. Wong 	uint len = xfs_efi_log_format_sizeof(src_efi_fmt->efi_nextents);
1793c5aaaceSDarrick J. Wong 	uint len32 = xfs_efi_log_format32_sizeof(src_efi_fmt->efi_nextents);
1803c5aaaceSDarrick J. Wong 	uint len64 = xfs_efi_log_format64_sizeof(src_efi_fmt->efi_nextents);
1816d192a9bSTim Shimmin 
1826d192a9bSTim Shimmin 	if (buf->i_len == len) {
18303a7485cSDarrick J. Wong 		memcpy(dst_efi_fmt, src_efi_fmt,
18403a7485cSDarrick J. Wong 		       offsetof(struct xfs_efi_log_format, efi_extents));
18503a7485cSDarrick J. Wong 		for (i = 0; i < src_efi_fmt->efi_nextents; i++)
18603a7485cSDarrick J. Wong 			memcpy(&dst_efi_fmt->efi_extents[i],
18703a7485cSDarrick J. Wong 			       &src_efi_fmt->efi_extents[i],
18803a7485cSDarrick J. Wong 			       sizeof(struct xfs_extent));
1896d192a9bSTim Shimmin 		return 0;
1906d192a9bSTim Shimmin 	} else if (buf->i_len == len32) {
1914e0d5f92SChristoph Hellwig 		xfs_efi_log_format_32_t *src_efi_fmt_32 = buf->i_addr;
1926d192a9bSTim Shimmin 
1936d192a9bSTim Shimmin 		dst_efi_fmt->efi_type     = src_efi_fmt_32->efi_type;
1946d192a9bSTim Shimmin 		dst_efi_fmt->efi_size     = src_efi_fmt_32->efi_size;
1956d192a9bSTim Shimmin 		dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents;
1966d192a9bSTim Shimmin 		dst_efi_fmt->efi_id       = src_efi_fmt_32->efi_id;
1976d192a9bSTim Shimmin 		for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
1986d192a9bSTim Shimmin 			dst_efi_fmt->efi_extents[i].ext_start =
1996d192a9bSTim Shimmin 				src_efi_fmt_32->efi_extents[i].ext_start;
2006d192a9bSTim Shimmin 			dst_efi_fmt->efi_extents[i].ext_len =
2016d192a9bSTim Shimmin 				src_efi_fmt_32->efi_extents[i].ext_len;
2026d192a9bSTim Shimmin 		}
2036d192a9bSTim Shimmin 		return 0;
2046d192a9bSTim Shimmin 	} else if (buf->i_len == len64) {
2054e0d5f92SChristoph Hellwig 		xfs_efi_log_format_64_t *src_efi_fmt_64 = buf->i_addr;
2066d192a9bSTim Shimmin 
2076d192a9bSTim Shimmin 		dst_efi_fmt->efi_type     = src_efi_fmt_64->efi_type;
2086d192a9bSTim Shimmin 		dst_efi_fmt->efi_size     = src_efi_fmt_64->efi_size;
2096d192a9bSTim Shimmin 		dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents;
2106d192a9bSTim Shimmin 		dst_efi_fmt->efi_id       = src_efi_fmt_64->efi_id;
2116d192a9bSTim Shimmin 		for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
2126d192a9bSTim Shimmin 			dst_efi_fmt->efi_extents[i].ext_start =
2136d192a9bSTim Shimmin 				src_efi_fmt_64->efi_extents[i].ext_start;
2146d192a9bSTim Shimmin 			dst_efi_fmt->efi_extents[i].ext_len =
2156d192a9bSTim Shimmin 				src_efi_fmt_64->efi_extents[i].ext_len;
2166d192a9bSTim Shimmin 		}
2176d192a9bSTim Shimmin 		return 0;
2186d192a9bSTim Shimmin 	}
219950f0d50SDarrick J. Wong 	XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, NULL, buf->i_addr,
220950f0d50SDarrick J. Wong 			buf->i_len);
2212451337dSDave Chinner 	return -EFSCORRUPTED;
2226d192a9bSTim Shimmin }
2236d192a9bSTim Shimmin 
2247bfa31d8SChristoph Hellwig static inline struct xfs_efd_log_item *EFD_ITEM(struct xfs_log_item *lip)
2257d795ca3SChristoph Hellwig {
2267bfa31d8SChristoph Hellwig 	return container_of(lip, struct xfs_efd_log_item, efd_item);
2277d795ca3SChristoph Hellwig }
2287bfa31d8SChristoph Hellwig 
2297bfa31d8SChristoph Hellwig STATIC void
2307bfa31d8SChristoph Hellwig xfs_efd_item_free(struct xfs_efd_log_item *efdp)
2317bfa31d8SChristoph Hellwig {
232b1c5ebb2SDave Chinner 	kmem_free(efdp->efd_item.li_lv_shadow);
2337bfa31d8SChristoph Hellwig 	if (efdp->efd_format.efd_nextents > XFS_EFD_MAX_FAST_EXTENTS)
2347bfa31d8SChristoph Hellwig 		kmem_free(efdp);
2357bfa31d8SChristoph Hellwig 	else
236182696fbSDarrick J. Wong 		kmem_cache_free(xfs_efd_cache, efdp);
2377d795ca3SChristoph Hellwig }
2381da177e4SLinus Torvalds 
239166d1368SDave Chinner STATIC void
240166d1368SDave Chinner xfs_efd_item_size(
241166d1368SDave Chinner 	struct xfs_log_item	*lip,
242166d1368SDave Chinner 	int			*nvecs,
243166d1368SDave Chinner 	int			*nbytes)
244166d1368SDave Chinner {
2453c5aaaceSDarrick J. Wong 	struct xfs_efd_log_item	*efdp = EFD_ITEM(lip);
2463c5aaaceSDarrick J. Wong 
247166d1368SDave Chinner 	*nvecs += 1;
2483c5aaaceSDarrick J. Wong 	*nbytes += xfs_efd_log_format_sizeof(efdp->efd_format.efd_nextents);
2491da177e4SLinus Torvalds }
2501da177e4SLinus Torvalds 
2511da177e4SLinus Torvalds /*
2521da177e4SLinus Torvalds  * This is called to fill in the vector of log iovecs for the
2531da177e4SLinus Torvalds  * given efd log item. We use only 1 iovec, and we point that
2541da177e4SLinus Torvalds  * at the efd_log_format structure embedded in the efd item.
2551da177e4SLinus Torvalds  * It is at this point that we assert that all of the extent
2561da177e4SLinus Torvalds  * slots in the efd item have been filled.
2571da177e4SLinus Torvalds  */
2581da177e4SLinus Torvalds STATIC void
2597bfa31d8SChristoph Hellwig xfs_efd_item_format(
2607bfa31d8SChristoph Hellwig 	struct xfs_log_item	*lip,
261bde7cff6SChristoph Hellwig 	struct xfs_log_vec	*lv)
2621da177e4SLinus Torvalds {
2637bfa31d8SChristoph Hellwig 	struct xfs_efd_log_item	*efdp = EFD_ITEM(lip);
264bde7cff6SChristoph Hellwig 	struct xfs_log_iovec	*vecp = NULL;
2651da177e4SLinus Torvalds 
2661da177e4SLinus Torvalds 	ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents);
2671da177e4SLinus Torvalds 
2681da177e4SLinus Torvalds 	efdp->efd_format.efd_type = XFS_LI_EFD;
2691da177e4SLinus Torvalds 	efdp->efd_format.efd_size = 1;
2701da177e4SLinus Torvalds 
271bde7cff6SChristoph Hellwig 	xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFD_FORMAT,
2721234351cSChristoph Hellwig 			&efdp->efd_format,
2733c5aaaceSDarrick J. Wong 			xfs_efd_log_format_sizeof(efdp->efd_format.efd_nextents));
2741da177e4SLinus Torvalds }
2751da177e4SLinus Torvalds 
2761da177e4SLinus Torvalds /*
2778d99fe92SBrian Foster  * The EFD is either committed or aborted if the transaction is cancelled. If
2788d99fe92SBrian Foster  * the transaction is cancelled, drop our reference to the EFI and free the EFD.
2798d99fe92SBrian Foster  */
2801da177e4SLinus Torvalds STATIC void
281ddf92053SChristoph Hellwig xfs_efd_item_release(
2827bfa31d8SChristoph Hellwig 	struct xfs_log_item	*lip)
2831da177e4SLinus Torvalds {
2848d99fe92SBrian Foster 	struct xfs_efd_log_item	*efdp = EFD_ITEM(lip);
2858d99fe92SBrian Foster 
2868d99fe92SBrian Foster 	xfs_efi_release(efdp->efd_efip);
2878d99fe92SBrian Foster 	xfs_efd_item_free(efdp);
2888d99fe92SBrian Foster }
2891da177e4SLinus Torvalds 
290c23ab603SDave Chinner static struct xfs_log_item *
291c23ab603SDave Chinner xfs_efd_item_intent(
292c23ab603SDave Chinner 	struct xfs_log_item	*lip)
293c23ab603SDave Chinner {
294c23ab603SDave Chinner 	return &EFD_ITEM(lip)->efd_efip->efi_item;
295c23ab603SDave Chinner }
296c23ab603SDave Chinner 
297272e42b2SChristoph Hellwig static const struct xfs_item_ops xfs_efd_item_ops = {
298f5b81200SDave Chinner 	.flags		= XFS_ITEM_RELEASE_WHEN_COMMITTED |
299f5b81200SDave Chinner 			  XFS_ITEM_INTENT_DONE,
3007bfa31d8SChristoph Hellwig 	.iop_size	= xfs_efd_item_size,
3017bfa31d8SChristoph Hellwig 	.iop_format	= xfs_efd_item_format,
302ddf92053SChristoph Hellwig 	.iop_release	= xfs_efd_item_release,
303c23ab603SDave Chinner 	.iop_intent	= xfs_efd_item_intent,
3041da177e4SLinus Torvalds };
3051da177e4SLinus Torvalds 
3061da177e4SLinus Torvalds /*
3079c5e7c2aSChristoph Hellwig  * Allocate an "extent free done" log item that will hold nextents worth of
3089c5e7c2aSChristoph Hellwig  * extents.  The caller must use all nextents extents, because we are not
3099c5e7c2aSChristoph Hellwig  * flexible about this at all.
3101da177e4SLinus Torvalds  */
31181f40041SChristoph Hellwig static struct xfs_efd_log_item *
3129c5e7c2aSChristoph Hellwig xfs_trans_get_efd(
3139c5e7c2aSChristoph Hellwig 	struct xfs_trans		*tp,
3147bfa31d8SChristoph Hellwig 	struct xfs_efi_log_item		*efip,
3159c5e7c2aSChristoph Hellwig 	unsigned int			nextents)
3161da177e4SLinus Torvalds {
3177bfa31d8SChristoph Hellwig 	struct xfs_efd_log_item		*efdp;
3181da177e4SLinus Torvalds 
3191da177e4SLinus Torvalds 	ASSERT(nextents > 0);
3209c5e7c2aSChristoph Hellwig 
3211da177e4SLinus Torvalds 	if (nextents > XFS_EFD_MAX_FAST_EXTENTS) {
3223c5aaaceSDarrick J. Wong 		efdp = kzalloc(xfs_efd_log_item_sizeof(nextents),
3233c5aaaceSDarrick J. Wong 				GFP_KERNEL | __GFP_NOFAIL);
3241da177e4SLinus Torvalds 	} else {
325182696fbSDarrick J. Wong 		efdp = kmem_cache_zalloc(xfs_efd_cache,
32632a2b11fSCarlos Maiolino 					GFP_KERNEL | __GFP_NOFAIL);
3271da177e4SLinus Torvalds 	}
3281da177e4SLinus Torvalds 
3299c5e7c2aSChristoph Hellwig 	xfs_log_item_init(tp->t_mountp, &efdp->efd_item, XFS_LI_EFD,
3309c5e7c2aSChristoph Hellwig 			  &xfs_efd_item_ops);
3311da177e4SLinus Torvalds 	efdp->efd_efip = efip;
3321da177e4SLinus Torvalds 	efdp->efd_format.efd_nextents = nextents;
3331da177e4SLinus Torvalds 	efdp->efd_format.efd_efi_id = efip->efi_format.efi_id;
3341da177e4SLinus Torvalds 
3359c5e7c2aSChristoph Hellwig 	xfs_trans_add_item(tp, &efdp->efd_item);
3367bfa31d8SChristoph Hellwig 	return efdp;
3371da177e4SLinus Torvalds }
338dc42375dSDarrick J. Wong 
339dc42375dSDarrick J. Wong /*
34081f40041SChristoph Hellwig  * Free an extent and log it to the EFD. Note that the transaction is marked
34181f40041SChristoph Hellwig  * dirty regardless of whether the extent free succeeds or fails to support the
34281f40041SChristoph Hellwig  * EFI/EFD lifecycle rules.
34381f40041SChristoph Hellwig  */
34481f40041SChristoph Hellwig static int
34581f40041SChristoph Hellwig xfs_trans_free_extent(
34681f40041SChristoph Hellwig 	struct xfs_trans		*tp,
34781f40041SChristoph Hellwig 	struct xfs_efd_log_item		*efdp,
348578c714bSDarrick J. Wong 	struct xfs_extent_free_item	*xefi)
34981f40041SChristoph Hellwig {
35072ba4555SDarrick J. Wong 	struct xfs_owner_info		oinfo = { };
35181f40041SChristoph Hellwig 	struct xfs_mount		*mp = tp->t_mountp;
35281f40041SChristoph Hellwig 	struct xfs_extent		*extp;
35381f40041SChristoph Hellwig 	uint				next_extent;
35481f40041SChristoph Hellwig 	xfs_agblock_t			agbno = XFS_FSB_TO_AGBNO(mp,
355578c714bSDarrick J. Wong 							xefi->xefi_startblock);
35681f40041SChristoph Hellwig 	int				error;
35781f40041SChristoph Hellwig 
358578c714bSDarrick J. Wong 	oinfo.oi_owner = xefi->xefi_owner;
359578c714bSDarrick J. Wong 	if (xefi->xefi_flags & XFS_EFI_ATTR_FORK)
36072ba4555SDarrick J. Wong 		oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
361578c714bSDarrick J. Wong 	if (xefi->xefi_flags & XFS_EFI_BMBT_BLOCK)
36272ba4555SDarrick J. Wong 		oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
36381f40041SChristoph Hellwig 
364f6b38463SDarrick J. Wong 	trace_xfs_bmap_free_deferred(tp->t_mountp, xefi->xefi_pag->pag_agno, 0,
365f6b38463SDarrick J. Wong 			agbno, xefi->xefi_blockcount);
36672ba4555SDarrick J. Wong 
367f6b38463SDarrick J. Wong 	error = __xfs_free_extent(tp, xefi->xefi_pag, agbno,
368*b742d7b4SDave Chinner 			xefi->xefi_blockcount, &oinfo, xefi->xefi_agresv,
369578c714bSDarrick J. Wong 			xefi->xefi_flags & XFS_EFI_SKIP_DISCARD);
370b2ccab31SDarrick J. Wong 
37181f40041SChristoph Hellwig 	/*
37281f40041SChristoph Hellwig 	 * Mark the transaction dirty, even on error. This ensures the
37381f40041SChristoph Hellwig 	 * transaction is aborted, which:
37481f40041SChristoph Hellwig 	 *
37581f40041SChristoph Hellwig 	 * 1.) releases the EFI and frees the EFD
37681f40041SChristoph Hellwig 	 * 2.) shuts down the filesystem
37781f40041SChristoph Hellwig 	 */
378bb7b1c9cSDave Chinner 	tp->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE;
37981f40041SChristoph Hellwig 	set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags);
38081f40041SChristoph Hellwig 
38181f40041SChristoph Hellwig 	next_extent = efdp->efd_next_extent;
38281f40041SChristoph Hellwig 	ASSERT(next_extent < efdp->efd_format.efd_nextents);
38381f40041SChristoph Hellwig 	extp = &(efdp->efd_format.efd_extents[next_extent]);
384578c714bSDarrick J. Wong 	extp->ext_start = xefi->xefi_startblock;
385578c714bSDarrick J. Wong 	extp->ext_len = xefi->xefi_blockcount;
38681f40041SChristoph Hellwig 	efdp->efd_next_extent++;
38781f40041SChristoph Hellwig 
38881f40041SChristoph Hellwig 	return error;
38981f40041SChristoph Hellwig }
39081f40041SChristoph Hellwig 
39181f40041SChristoph Hellwig /* Sort bmap items by AG. */
39281f40041SChristoph Hellwig static int
39381f40041SChristoph Hellwig xfs_extent_free_diff_items(
39481f40041SChristoph Hellwig 	void				*priv,
3954f0f586bSSami Tolvanen 	const struct list_head		*a,
3964f0f586bSSami Tolvanen 	const struct list_head		*b)
39781f40041SChristoph Hellwig {
39881f40041SChristoph Hellwig 	struct xfs_extent_free_item	*ra;
39981f40041SChristoph Hellwig 	struct xfs_extent_free_item	*rb;
40081f40041SChristoph Hellwig 
40181f40041SChristoph Hellwig 	ra = container_of(a, struct xfs_extent_free_item, xefi_list);
40281f40041SChristoph Hellwig 	rb = container_of(b, struct xfs_extent_free_item, xefi_list);
403f6b38463SDarrick J. Wong 
404f6b38463SDarrick J. Wong 	return ra->xefi_pag->pag_agno - rb->xefi_pag->pag_agno;
40581f40041SChristoph Hellwig }
40681f40041SChristoph Hellwig 
40781f40041SChristoph Hellwig /* Log a free extent to the intent item. */
40881f40041SChristoph Hellwig STATIC void
40981f40041SChristoph Hellwig xfs_extent_free_log_item(
41081f40041SChristoph Hellwig 	struct xfs_trans		*tp,
411c1f09188SChristoph Hellwig 	struct xfs_efi_log_item		*efip,
412578c714bSDarrick J. Wong 	struct xfs_extent_free_item	*xefi)
41381f40041SChristoph Hellwig {
41481f40041SChristoph Hellwig 	uint				next_extent;
41581f40041SChristoph Hellwig 	struct xfs_extent		*extp;
41681f40041SChristoph Hellwig 
41781f40041SChristoph Hellwig 	tp->t_flags |= XFS_TRANS_DIRTY;
41881f40041SChristoph Hellwig 	set_bit(XFS_LI_DIRTY, &efip->efi_item.li_flags);
41981f40041SChristoph Hellwig 
42081f40041SChristoph Hellwig 	/*
42181f40041SChristoph Hellwig 	 * atomic_inc_return gives us the value after the increment;
42281f40041SChristoph Hellwig 	 * we want to use it as an array index so we need to subtract 1 from
42381f40041SChristoph Hellwig 	 * it.
42481f40041SChristoph Hellwig 	 */
42581f40041SChristoph Hellwig 	next_extent = atomic_inc_return(&efip->efi_next_extent) - 1;
42681f40041SChristoph Hellwig 	ASSERT(next_extent < efip->efi_format.efi_nextents);
42781f40041SChristoph Hellwig 	extp = &efip->efi_format.efi_extents[next_extent];
428578c714bSDarrick J. Wong 	extp->ext_start = xefi->xefi_startblock;
429578c714bSDarrick J. Wong 	extp->ext_len = xefi->xefi_blockcount;
43081f40041SChristoph Hellwig }
43181f40041SChristoph Hellwig 
43213a83333SChristoph Hellwig static struct xfs_log_item *
433c1f09188SChristoph Hellwig xfs_extent_free_create_intent(
434c1f09188SChristoph Hellwig 	struct xfs_trans		*tp,
435c1f09188SChristoph Hellwig 	struct list_head		*items,
436d367a868SChristoph Hellwig 	unsigned int			count,
437d367a868SChristoph Hellwig 	bool				sort)
438c1f09188SChristoph Hellwig {
439c1f09188SChristoph Hellwig 	struct xfs_mount		*mp = tp->t_mountp;
440c1f09188SChristoph Hellwig 	struct xfs_efi_log_item		*efip = xfs_efi_init(mp, count);
441578c714bSDarrick J. Wong 	struct xfs_extent_free_item	*xefi;
442c1f09188SChristoph Hellwig 
443c1f09188SChristoph Hellwig 	ASSERT(count > 0);
444c1f09188SChristoph Hellwig 
445c1f09188SChristoph Hellwig 	xfs_trans_add_item(tp, &efip->efi_item);
446d367a868SChristoph Hellwig 	if (sort)
447d367a868SChristoph Hellwig 		list_sort(mp, items, xfs_extent_free_diff_items);
448578c714bSDarrick J. Wong 	list_for_each_entry(xefi, items, xefi_list)
449578c714bSDarrick J. Wong 		xfs_extent_free_log_item(tp, efip, xefi);
45013a83333SChristoph Hellwig 	return &efip->efi_item;
451c1f09188SChristoph Hellwig }
452c1f09188SChristoph Hellwig 
45381f40041SChristoph Hellwig /* Get an EFD so we can process all the free extents. */
454f09d167cSChristoph Hellwig static struct xfs_log_item *
45581f40041SChristoph Hellwig xfs_extent_free_create_done(
45681f40041SChristoph Hellwig 	struct xfs_trans		*tp,
45713a83333SChristoph Hellwig 	struct xfs_log_item		*intent,
45881f40041SChristoph Hellwig 	unsigned int			count)
45981f40041SChristoph Hellwig {
460f09d167cSChristoph Hellwig 	return &xfs_trans_get_efd(tp, EFI_ITEM(intent), count)->efd_item;
46181f40041SChristoph Hellwig }
46281f40041SChristoph Hellwig 
463f6b38463SDarrick J. Wong /* Take a passive ref to the AG containing the space we're freeing. */
464f6b38463SDarrick J. Wong void
465f6b38463SDarrick J. Wong xfs_extent_free_get_group(
466f6b38463SDarrick J. Wong 	struct xfs_mount		*mp,
467f6b38463SDarrick J. Wong 	struct xfs_extent_free_item	*xefi)
468f6b38463SDarrick J. Wong {
469f6b38463SDarrick J. Wong 	xfs_agnumber_t			agno;
470f6b38463SDarrick J. Wong 
471f6b38463SDarrick J. Wong 	agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock);
472d5c88131SDarrick J. Wong 	xefi->xefi_pag = xfs_perag_intent_get(mp, agno);
473f6b38463SDarrick J. Wong }
474f6b38463SDarrick J. Wong 
475f6b38463SDarrick J. Wong /* Release a passive AG ref after some freeing work. */
476f6b38463SDarrick J. Wong static inline void
477f6b38463SDarrick J. Wong xfs_extent_free_put_group(
478f6b38463SDarrick J. Wong 	struct xfs_extent_free_item	*xefi)
479f6b38463SDarrick J. Wong {
480d5c88131SDarrick J. Wong 	xfs_perag_intent_put(xefi->xefi_pag);
481f6b38463SDarrick J. Wong }
482f6b38463SDarrick J. Wong 
48381f40041SChristoph Hellwig /* Process a free extent. */
48481f40041SChristoph Hellwig STATIC int
48581f40041SChristoph Hellwig xfs_extent_free_finish_item(
48681f40041SChristoph Hellwig 	struct xfs_trans		*tp,
487f09d167cSChristoph Hellwig 	struct xfs_log_item		*done,
48881f40041SChristoph Hellwig 	struct list_head		*item,
4893ec1b26cSChristoph Hellwig 	struct xfs_btree_cur		**state)
49081f40041SChristoph Hellwig {
491578c714bSDarrick J. Wong 	struct xfs_extent_free_item	*xefi;
49281f40041SChristoph Hellwig 	int				error;
49381f40041SChristoph Hellwig 
494578c714bSDarrick J. Wong 	xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
49572ba4555SDarrick J. Wong 
496578c714bSDarrick J. Wong 	error = xfs_trans_free_extent(tp, EFD_ITEM(done), xefi);
497f6b38463SDarrick J. Wong 
498f6b38463SDarrick J. Wong 	xfs_extent_free_put_group(xefi);
499578c714bSDarrick J. Wong 	kmem_cache_free(xfs_extfree_item_cache, xefi);
50081f40041SChristoph Hellwig 	return error;
50181f40041SChristoph Hellwig }
50281f40041SChristoph Hellwig 
50381f40041SChristoph Hellwig /* Abort all pending EFIs. */
50481f40041SChristoph Hellwig STATIC void
50581f40041SChristoph Hellwig xfs_extent_free_abort_intent(
50613a83333SChristoph Hellwig 	struct xfs_log_item		*intent)
50781f40041SChristoph Hellwig {
50813a83333SChristoph Hellwig 	xfs_efi_release(EFI_ITEM(intent));
50981f40041SChristoph Hellwig }
51081f40041SChristoph Hellwig 
51181f40041SChristoph Hellwig /* Cancel a free extent. */
51281f40041SChristoph Hellwig STATIC void
51381f40041SChristoph Hellwig xfs_extent_free_cancel_item(
51481f40041SChristoph Hellwig 	struct list_head		*item)
51581f40041SChristoph Hellwig {
516578c714bSDarrick J. Wong 	struct xfs_extent_free_item	*xefi;
51781f40041SChristoph Hellwig 
518578c714bSDarrick J. Wong 	xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
519f6b38463SDarrick J. Wong 
520f6b38463SDarrick J. Wong 	xfs_extent_free_put_group(xefi);
521578c714bSDarrick J. Wong 	kmem_cache_free(xfs_extfree_item_cache, xefi);
52281f40041SChristoph Hellwig }
52381f40041SChristoph Hellwig 
52481f40041SChristoph Hellwig const struct xfs_defer_op_type xfs_extent_free_defer_type = {
52581f40041SChristoph Hellwig 	.max_items	= XFS_EFI_MAX_FAST_EXTENTS,
52681f40041SChristoph Hellwig 	.create_intent	= xfs_extent_free_create_intent,
52781f40041SChristoph Hellwig 	.abort_intent	= xfs_extent_free_abort_intent,
52881f40041SChristoph Hellwig 	.create_done	= xfs_extent_free_create_done,
52981f40041SChristoph Hellwig 	.finish_item	= xfs_extent_free_finish_item,
53081f40041SChristoph Hellwig 	.cancel_item	= xfs_extent_free_cancel_item,
53181f40041SChristoph Hellwig };
53281f40041SChristoph Hellwig 
53381f40041SChristoph Hellwig /*
53481f40041SChristoph Hellwig  * AGFL blocks are accounted differently in the reserve pools and are not
53581f40041SChristoph Hellwig  * inserted into the busy extent list.
53681f40041SChristoph Hellwig  */
53781f40041SChristoph Hellwig STATIC int
53881f40041SChristoph Hellwig xfs_agfl_free_finish_item(
53981f40041SChristoph Hellwig 	struct xfs_trans		*tp,
540f09d167cSChristoph Hellwig 	struct xfs_log_item		*done,
54181f40041SChristoph Hellwig 	struct list_head		*item,
5423ec1b26cSChristoph Hellwig 	struct xfs_btree_cur		**state)
54381f40041SChristoph Hellwig {
544b3b5ff41SDarrick J. Wong 	struct xfs_owner_info		oinfo = { };
54581f40041SChristoph Hellwig 	struct xfs_mount		*mp = tp->t_mountp;
546f09d167cSChristoph Hellwig 	struct xfs_efd_log_item		*efdp = EFD_ITEM(done);
547578c714bSDarrick J. Wong 	struct xfs_extent_free_item	*xefi;
54881f40041SChristoph Hellwig 	struct xfs_extent		*extp;
54981f40041SChristoph Hellwig 	struct xfs_buf			*agbp;
55081f40041SChristoph Hellwig 	int				error;
55181f40041SChristoph Hellwig 	xfs_agblock_t			agbno;
55281f40041SChristoph Hellwig 	uint				next_extent;
55381f40041SChristoph Hellwig 
554578c714bSDarrick J. Wong 	xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
555578c714bSDarrick J. Wong 	ASSERT(xefi->xefi_blockcount == 1);
556578c714bSDarrick J. Wong 	agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock);
557578c714bSDarrick J. Wong 	oinfo.oi_owner = xefi->xefi_owner;
55881f40041SChristoph Hellwig 
559f6b38463SDarrick J. Wong 	trace_xfs_agfl_free_deferred(mp, xefi->xefi_pag->pag_agno, 0, agbno,
560f6b38463SDarrick J. Wong 			xefi->xefi_blockcount);
56181f40041SChristoph Hellwig 
562f6b38463SDarrick J. Wong 	error = xfs_alloc_read_agf(xefi->xefi_pag, tp, 0, &agbp);
56381f40041SChristoph Hellwig 	if (!error)
564f6b38463SDarrick J. Wong 		error = xfs_free_agfl_block(tp, xefi->xefi_pag->pag_agno,
565f6b38463SDarrick J. Wong 				agbno, agbp, &oinfo);
56681f40041SChristoph Hellwig 
56781f40041SChristoph Hellwig 	/*
56881f40041SChristoph Hellwig 	 * Mark the transaction dirty, even on error. This ensures the
56981f40041SChristoph Hellwig 	 * transaction is aborted, which:
57081f40041SChristoph Hellwig 	 *
57181f40041SChristoph Hellwig 	 * 1.) releases the EFI and frees the EFD
57281f40041SChristoph Hellwig 	 * 2.) shuts down the filesystem
57381f40041SChristoph Hellwig 	 */
57481f40041SChristoph Hellwig 	tp->t_flags |= XFS_TRANS_DIRTY;
57581f40041SChristoph Hellwig 	set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags);
57681f40041SChristoph Hellwig 
57781f40041SChristoph Hellwig 	next_extent = efdp->efd_next_extent;
57881f40041SChristoph Hellwig 	ASSERT(next_extent < efdp->efd_format.efd_nextents);
57981f40041SChristoph Hellwig 	extp = &(efdp->efd_format.efd_extents[next_extent]);
580578c714bSDarrick J. Wong 	extp->ext_start = xefi->xefi_startblock;
581578c714bSDarrick J. Wong 	extp->ext_len = xefi->xefi_blockcount;
58281f40041SChristoph Hellwig 	efdp->efd_next_extent++;
58381f40041SChristoph Hellwig 
584f6b38463SDarrick J. Wong 	xfs_extent_free_put_group(xefi);
585578c714bSDarrick J. Wong 	kmem_cache_free(xfs_extfree_item_cache, xefi);
58681f40041SChristoph Hellwig 	return error;
58781f40041SChristoph Hellwig }
58881f40041SChristoph Hellwig 
58981f40041SChristoph Hellwig /* sub-type with special handling for AGFL deferred frees */
59081f40041SChristoph Hellwig const struct xfs_defer_op_type xfs_agfl_free_defer_type = {
59181f40041SChristoph Hellwig 	.max_items	= XFS_EFI_MAX_FAST_EXTENTS,
59281f40041SChristoph Hellwig 	.create_intent	= xfs_extent_free_create_intent,
59381f40041SChristoph Hellwig 	.abort_intent	= xfs_extent_free_abort_intent,
59481f40041SChristoph Hellwig 	.create_done	= xfs_extent_free_create_done,
59581f40041SChristoph Hellwig 	.finish_item	= xfs_agfl_free_finish_item,
59681f40041SChristoph Hellwig 	.cancel_item	= xfs_extent_free_cancel_item,
59781f40041SChristoph Hellwig };
59881f40041SChristoph Hellwig 
5993c15df3dSDarrick J. Wong /* Is this recovered EFI ok? */
6003c15df3dSDarrick J. Wong static inline bool
6013c15df3dSDarrick J. Wong xfs_efi_validate_ext(
6023c15df3dSDarrick J. Wong 	struct xfs_mount		*mp,
6033c15df3dSDarrick J. Wong 	struct xfs_extent		*extp)
6043c15df3dSDarrick J. Wong {
60567457eb0SDarrick J. Wong 	return xfs_verify_fsbext(mp, extp->ext_start, extp->ext_len);
6063c15df3dSDarrick J. Wong }
6073c15df3dSDarrick J. Wong 
60881f40041SChristoph Hellwig /*
609dc42375dSDarrick J. Wong  * Process an extent free intent item that was recovered from
610dc42375dSDarrick J. Wong  * the log.  We need to free the extents that it describes.
611dc42375dSDarrick J. Wong  */
61210d0c6e0SDarrick J. Wong STATIC int
61396b60f82SDarrick J. Wong xfs_efi_item_recover(
61496b60f82SDarrick J. Wong 	struct xfs_log_item		*lip,
615e6fff81eSDarrick J. Wong 	struct list_head		*capture_list)
616dc42375dSDarrick J. Wong {
61796b60f82SDarrick J. Wong 	struct xfs_efi_log_item		*efip = EFI_ITEM(lip);
618d86142ddSDave Chinner 	struct xfs_mount		*mp = lip->li_log->l_mp;
619dc42375dSDarrick J. Wong 	struct xfs_efd_log_item		*efdp;
620dc42375dSDarrick J. Wong 	struct xfs_trans		*tp;
621dc42375dSDarrick J. Wong 	int				i;
622dc42375dSDarrick J. Wong 	int				error = 0;
623dc42375dSDarrick J. Wong 
624dc42375dSDarrick J. Wong 	/*
625dc42375dSDarrick J. Wong 	 * First check the validity of the extents described by the
626dc42375dSDarrick J. Wong 	 * EFI.  If any are bad, then assume that all are bad and
627dc42375dSDarrick J. Wong 	 * just toss the EFI.
628dc42375dSDarrick J. Wong 	 */
629dc42375dSDarrick J. Wong 	for (i = 0; i < efip->efi_format.efi_nextents; i++) {
6303c15df3dSDarrick J. Wong 		if (!xfs_efi_validate_ext(mp,
6313c15df3dSDarrick J. Wong 					&efip->efi_format.efi_extents[i])) {
6323c15df3dSDarrick J. Wong 			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
6333c15df3dSDarrick J. Wong 					&efip->efi_format,
6343c15df3dSDarrick J. Wong 					sizeof(efip->efi_format));
635895e196fSDarrick J. Wong 			return -EFSCORRUPTED;
636dc42375dSDarrick J. Wong 		}
6373c15df3dSDarrick J. Wong 	}
638dc42375dSDarrick J. Wong 
639dc42375dSDarrick J. Wong 	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
640dc42375dSDarrick J. Wong 	if (error)
641dc42375dSDarrick J. Wong 		return error;
642dc42375dSDarrick J. Wong 	efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
643dc42375dSDarrick J. Wong 
644dc42375dSDarrick J. Wong 	for (i = 0; i < efip->efi_format.efi_nextents; i++) {
64572ba4555SDarrick J. Wong 		struct xfs_extent_free_item	fake = {
64672ba4555SDarrick J. Wong 			.xefi_owner		= XFS_RMAP_OWN_UNKNOWN,
647*b742d7b4SDave Chinner 			.xefi_agresv		= XFS_AG_RESV_NONE,
64872ba4555SDarrick J. Wong 		};
64972ba4555SDarrick J. Wong 		struct xfs_extent		*extp;
65072ba4555SDarrick J. Wong 
651e127fafdSDarrick J. Wong 		extp = &efip->efi_format.efi_extents[i];
65272ba4555SDarrick J. Wong 
65372ba4555SDarrick J. Wong 		fake.xefi_startblock = extp->ext_start;
65472ba4555SDarrick J. Wong 		fake.xefi_blockcount = extp->ext_len;
65572ba4555SDarrick J. Wong 
656f6b38463SDarrick J. Wong 		xfs_extent_free_get_group(mp, &fake);
65772ba4555SDarrick J. Wong 		error = xfs_trans_free_extent(tp, efdp, &fake);
658f6b38463SDarrick J. Wong 		xfs_extent_free_put_group(&fake);
65943059d54SDarrick J. Wong 		if (error == -EFSCORRUPTED)
66043059d54SDarrick J. Wong 			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
66143059d54SDarrick J. Wong 					extp, sizeof(*extp));
662dc42375dSDarrick J. Wong 		if (error)
663dc42375dSDarrick J. Wong 			goto abort_error;
664dc42375dSDarrick J. Wong 
665dc42375dSDarrick J. Wong 	}
666dc42375dSDarrick J. Wong 
667512edfacSDarrick J. Wong 	return xfs_defer_ops_capture_and_commit(tp, capture_list);
668dc42375dSDarrick J. Wong 
669dc42375dSDarrick J. Wong abort_error:
670dc42375dSDarrick J. Wong 	xfs_trans_cancel(tp);
671dc42375dSDarrick J. Wong 	return error;
672dc42375dSDarrick J. Wong }
67386ffa471SDarrick J. Wong 
674154c733aSDarrick J. Wong STATIC bool
675154c733aSDarrick J. Wong xfs_efi_item_match(
676154c733aSDarrick J. Wong 	struct xfs_log_item	*lip,
677154c733aSDarrick J. Wong 	uint64_t		intent_id)
678154c733aSDarrick J. Wong {
679154c733aSDarrick J. Wong 	return EFI_ITEM(lip)->efi_format.efi_id == intent_id;
680154c733aSDarrick J. Wong }
681154c733aSDarrick J. Wong 
6824e919af7SDarrick J. Wong /* Relog an intent item to push the log tail forward. */
6834e919af7SDarrick J. Wong static struct xfs_log_item *
6844e919af7SDarrick J. Wong xfs_efi_item_relog(
6854e919af7SDarrick J. Wong 	struct xfs_log_item		*intent,
6864e919af7SDarrick J. Wong 	struct xfs_trans		*tp)
6874e919af7SDarrick J. Wong {
6884e919af7SDarrick J. Wong 	struct xfs_efd_log_item		*efdp;
6894e919af7SDarrick J. Wong 	struct xfs_efi_log_item		*efip;
6904e919af7SDarrick J. Wong 	struct xfs_extent		*extp;
6914e919af7SDarrick J. Wong 	unsigned int			count;
6924e919af7SDarrick J. Wong 
6934e919af7SDarrick J. Wong 	count = EFI_ITEM(intent)->efi_format.efi_nextents;
6944e919af7SDarrick J. Wong 	extp = EFI_ITEM(intent)->efi_format.efi_extents;
6954e919af7SDarrick J. Wong 
6964e919af7SDarrick J. Wong 	tp->t_flags |= XFS_TRANS_DIRTY;
6974e919af7SDarrick J. Wong 	efdp = xfs_trans_get_efd(tp, EFI_ITEM(intent), count);
6984e919af7SDarrick J. Wong 	efdp->efd_next_extent = count;
6994e919af7SDarrick J. Wong 	memcpy(efdp->efd_format.efd_extents, extp, count * sizeof(*extp));
7004e919af7SDarrick J. Wong 	set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags);
7014e919af7SDarrick J. Wong 
7024e919af7SDarrick J. Wong 	efip = xfs_efi_init(tp->t_mountp, count);
7034e919af7SDarrick J. Wong 	memcpy(efip->efi_format.efi_extents, extp, count * sizeof(*extp));
7044e919af7SDarrick J. Wong 	atomic_set(&efip->efi_next_extent, count);
7054e919af7SDarrick J. Wong 	xfs_trans_add_item(tp, &efip->efi_item);
7064e919af7SDarrick J. Wong 	set_bit(XFS_LI_DIRTY, &efip->efi_item.li_flags);
7074e919af7SDarrick J. Wong 	return &efip->efi_item;
7084e919af7SDarrick J. Wong }
7094e919af7SDarrick J. Wong 
71010d0c6e0SDarrick J. Wong static const struct xfs_item_ops xfs_efi_item_ops = {
711f5b81200SDave Chinner 	.flags		= XFS_ITEM_INTENT,
71210d0c6e0SDarrick J. Wong 	.iop_size	= xfs_efi_item_size,
71310d0c6e0SDarrick J. Wong 	.iop_format	= xfs_efi_item_format,
71410d0c6e0SDarrick J. Wong 	.iop_unpin	= xfs_efi_item_unpin,
71510d0c6e0SDarrick J. Wong 	.iop_release	= xfs_efi_item_release,
71610d0c6e0SDarrick J. Wong 	.iop_recover	= xfs_efi_item_recover,
717154c733aSDarrick J. Wong 	.iop_match	= xfs_efi_item_match,
7184e919af7SDarrick J. Wong 	.iop_relog	= xfs_efi_item_relog,
71910d0c6e0SDarrick J. Wong };
72010d0c6e0SDarrick J. Wong 
7219817aa80SDarrick J. Wong /*
7229817aa80SDarrick J. Wong  * This routine is called to create an in-core extent free intent
7239817aa80SDarrick J. Wong  * item from the efi format structure which was logged on disk.
7249817aa80SDarrick J. Wong  * It allocates an in-core efi, copies the extents from the format
7259817aa80SDarrick J. Wong  * structure into it, and adds the efi to the AIL with the given
7269817aa80SDarrick J. Wong  * LSN.
7279817aa80SDarrick J. Wong  */
7289817aa80SDarrick J. Wong STATIC int
7299817aa80SDarrick J. Wong xlog_recover_efi_commit_pass2(
7309817aa80SDarrick J. Wong 	struct xlog			*log,
7319817aa80SDarrick J. Wong 	struct list_head		*buffer_list,
7329817aa80SDarrick J. Wong 	struct xlog_recover_item	*item,
7339817aa80SDarrick J. Wong 	xfs_lsn_t			lsn)
7349817aa80SDarrick J. Wong {
7359817aa80SDarrick J. Wong 	struct xfs_mount		*mp = log->l_mp;
7369817aa80SDarrick J. Wong 	struct xfs_efi_log_item		*efip;
7379817aa80SDarrick J. Wong 	struct xfs_efi_log_format	*efi_formatp;
7389817aa80SDarrick J. Wong 	int				error;
7399817aa80SDarrick J. Wong 
7409817aa80SDarrick J. Wong 	efi_formatp = item->ri_buf[0].i_addr;
7419817aa80SDarrick J. Wong 
7423c5aaaceSDarrick J. Wong 	if (item->ri_buf[0].i_len < xfs_efi_log_format_sizeof(0)) {
743950f0d50SDarrick J. Wong 		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
744950f0d50SDarrick J. Wong 				item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
74503a7485cSDarrick J. Wong 		return -EFSCORRUPTED;
74603a7485cSDarrick J. Wong 	}
74703a7485cSDarrick J. Wong 
7489817aa80SDarrick J. Wong 	efip = xfs_efi_init(mp, efi_formatp->efi_nextents);
7499817aa80SDarrick J. Wong 	error = xfs_efi_copy_format(&item->ri_buf[0], &efip->efi_format);
7509817aa80SDarrick J. Wong 	if (error) {
7519817aa80SDarrick J. Wong 		xfs_efi_item_free(efip);
7529817aa80SDarrick J. Wong 		return error;
7539817aa80SDarrick J. Wong 	}
7549817aa80SDarrick J. Wong 	atomic_set(&efip->efi_next_extent, efi_formatp->efi_nextents);
7559817aa80SDarrick J. Wong 	/*
75686a37174SDarrick J. Wong 	 * Insert the intent into the AIL directly and drop one reference so
75786a37174SDarrick J. Wong 	 * that finishing or canceling the work will drop the other.
7589817aa80SDarrick J. Wong 	 */
75986a37174SDarrick J. Wong 	xfs_trans_ail_insert(log->l_ailp, &efip->efi_item, lsn);
7609817aa80SDarrick J. Wong 	xfs_efi_release(efip);
7619817aa80SDarrick J. Wong 	return 0;
7629817aa80SDarrick J. Wong }
7639817aa80SDarrick J. Wong 
76486ffa471SDarrick J. Wong const struct xlog_recover_item_ops xlog_efi_item_ops = {
76586ffa471SDarrick J. Wong 	.item_type		= XFS_LI_EFI,
7669817aa80SDarrick J. Wong 	.commit_pass2		= xlog_recover_efi_commit_pass2,
76786ffa471SDarrick J. Wong };
76886ffa471SDarrick J. Wong 
7699817aa80SDarrick J. Wong /*
7709817aa80SDarrick J. Wong  * This routine is called when an EFD format structure is found in a committed
7719817aa80SDarrick J. Wong  * transaction in the log. Its purpose is to cancel the corresponding EFI if it
7729817aa80SDarrick J. Wong  * was still in the log. To do this it searches the AIL for the EFI with an id
7739817aa80SDarrick J. Wong  * equal to that in the EFD format structure. If we find it we drop the EFD
7749817aa80SDarrick J. Wong  * reference, which removes the EFI from the AIL and frees it.
7759817aa80SDarrick J. Wong  */
7769817aa80SDarrick J. Wong STATIC int
7779817aa80SDarrick J. Wong xlog_recover_efd_commit_pass2(
7789817aa80SDarrick J. Wong 	struct xlog			*log,
7799817aa80SDarrick J. Wong 	struct list_head		*buffer_list,
7809817aa80SDarrick J. Wong 	struct xlog_recover_item	*item,
7819817aa80SDarrick J. Wong 	xfs_lsn_t			lsn)
7829817aa80SDarrick J. Wong {
7839817aa80SDarrick J. Wong 	struct xfs_efd_log_format	*efd_formatp;
784921ed96bSDarrick J. Wong 	int				buflen = item->ri_buf[0].i_len;
7859817aa80SDarrick J. Wong 
7869817aa80SDarrick J. Wong 	efd_formatp = item->ri_buf[0].i_addr;
787921ed96bSDarrick J. Wong 
788921ed96bSDarrick J. Wong 	if (buflen < sizeof(struct xfs_efd_log_format)) {
789921ed96bSDarrick J. Wong 		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
790921ed96bSDarrick J. Wong 				efd_formatp, buflen);
791921ed96bSDarrick J. Wong 		return -EFSCORRUPTED;
792921ed96bSDarrick J. Wong 	}
793921ed96bSDarrick J. Wong 
794921ed96bSDarrick J. Wong 	if (item->ri_buf[0].i_len != xfs_efd_log_format32_sizeof(
795921ed96bSDarrick J. Wong 						efd_formatp->efd_nextents) &&
796921ed96bSDarrick J. Wong 	    item->ri_buf[0].i_len != xfs_efd_log_format64_sizeof(
797921ed96bSDarrick J. Wong 						efd_formatp->efd_nextents)) {
798921ed96bSDarrick J. Wong 		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
799921ed96bSDarrick J. Wong 				efd_formatp, buflen);
800921ed96bSDarrick J. Wong 		return -EFSCORRUPTED;
801921ed96bSDarrick J. Wong 	}
8029817aa80SDarrick J. Wong 
803154c733aSDarrick J. Wong 	xlog_recover_release_intent(log, XFS_LI_EFI, efd_formatp->efd_efi_id);
8049817aa80SDarrick J. Wong 	return 0;
8059817aa80SDarrick J. Wong }
8069817aa80SDarrick J. Wong 
80786ffa471SDarrick J. Wong const struct xlog_recover_item_ops xlog_efd_item_ops = {
80886ffa471SDarrick J. Wong 	.item_type		= XFS_LI_EFD,
8099817aa80SDarrick J. Wong 	.commit_pass2		= xlog_recover_efd_commit_pass2,
81086ffa471SDarrick J. Wong };
811