xref: /openbmc/linux/fs/xfs/xfs_extfree_item.c (revision 680776e5)
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 
EFI_ITEM(struct xfs_log_item * lip)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
xfs_efi_item_free(struct xfs_efi_log_item * efip)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
xfs_efi_release(struct xfs_efi_log_item * efip)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
xfs_efi_item_size(struct xfs_log_item * lip,int * nvecs,int * nbytes)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
xfs_efi_item_format(struct xfs_log_item * lip,struct xfs_log_vec * lv)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
xfs_efi_item_unpin(struct xfs_log_item * lip,int remove)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
xfs_efi_item_release(struct xfs_log_item * lip)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 *
xfs_efi_init(struct xfs_mount * mp,uint nextents)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
xfs_efi_copy_format(xfs_log_iovec_t * buf,xfs_efi_log_format_t * dst_efi_fmt)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 
EFD_ITEM(struct xfs_log_item * lip)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
xfs_efd_item_free(struct xfs_efd_log_item * efdp)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
xfs_efd_item_size(struct xfs_log_item * lip,int * nvecs,int * nbytes)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
xfs_efd_item_format(struct xfs_log_item * lip,struct xfs_log_vec * lv)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
xfs_efd_item_release(struct xfs_log_item * lip)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 *
xfs_efd_item_intent(struct xfs_log_item * lip)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 *
xfs_trans_get_efd(struct xfs_trans * tp,struct xfs_efi_log_item * efip,unsigned int nextents)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 /*
3400853b5deSDave Chinner  * Fill the EFD with all extents from the EFI when we need to roll the
3410853b5deSDave Chinner  * transaction and continue with a new EFI.
3420853b5deSDave Chinner  *
3430853b5deSDave Chinner  * This simply copies all the extents in the EFI to the EFD rather than make
3440853b5deSDave Chinner  * assumptions about which extents in the EFI have already been processed. We
3450853b5deSDave Chinner  * currently keep the xefi list in the same order as the EFI extent list, but
3460853b5deSDave Chinner  * that may not always be the case. Copying everything avoids leaving a landmine
3470853b5deSDave Chinner  * were we fail to cancel all the extents in an EFI if the xefi list is
3480853b5deSDave Chinner  * processed in a different order to the extents in the EFI.
3490853b5deSDave Chinner  */
3500853b5deSDave Chinner static void
xfs_efd_from_efi(struct xfs_efd_log_item * efdp)3510853b5deSDave Chinner xfs_efd_from_efi(
3520853b5deSDave Chinner 	struct xfs_efd_log_item	*efdp)
3530853b5deSDave Chinner {
3540853b5deSDave Chinner 	struct xfs_efi_log_item *efip = efdp->efd_efip;
3550853b5deSDave Chinner 	uint                    i;
3560853b5deSDave Chinner 
3570853b5deSDave Chinner 	ASSERT(efip->efi_format.efi_nextents > 0);
3580853b5deSDave Chinner 	ASSERT(efdp->efd_next_extent < efip->efi_format.efi_nextents);
3590853b5deSDave Chinner 
3600853b5deSDave Chinner 	for (i = 0; i < efip->efi_format.efi_nextents; i++) {
3610853b5deSDave Chinner 	       efdp->efd_format.efd_extents[i] =
3620853b5deSDave Chinner 		       efip->efi_format.efi_extents[i];
3630853b5deSDave Chinner 	}
3640853b5deSDave Chinner 	efdp->efd_next_extent = efip->efi_format.efi_nextents;
3650853b5deSDave Chinner }
3660853b5deSDave Chinner 
3670853b5deSDave Chinner /*
36881f40041SChristoph Hellwig  * Free an extent and log it to the EFD. Note that the transaction is marked
36981f40041SChristoph Hellwig  * dirty regardless of whether the extent free succeeds or fails to support the
37081f40041SChristoph Hellwig  * EFI/EFD lifecycle rules.
37181f40041SChristoph Hellwig  */
37281f40041SChristoph Hellwig static int
xfs_trans_free_extent(struct xfs_trans * tp,struct xfs_efd_log_item * efdp,struct xfs_extent_free_item * xefi)37381f40041SChristoph Hellwig xfs_trans_free_extent(
37481f40041SChristoph Hellwig 	struct xfs_trans		*tp,
37581f40041SChristoph Hellwig 	struct xfs_efd_log_item		*efdp,
376578c714bSDarrick J. Wong 	struct xfs_extent_free_item	*xefi)
37781f40041SChristoph Hellwig {
37872ba4555SDarrick J. Wong 	struct xfs_owner_info		oinfo = { };
37981f40041SChristoph Hellwig 	struct xfs_mount		*mp = tp->t_mountp;
38081f40041SChristoph Hellwig 	struct xfs_extent		*extp;
38181f40041SChristoph Hellwig 	uint				next_extent;
38281f40041SChristoph Hellwig 	xfs_agblock_t			agbno = XFS_FSB_TO_AGBNO(mp,
383578c714bSDarrick J. Wong 							xefi->xefi_startblock);
38481f40041SChristoph Hellwig 	int				error;
38581f40041SChristoph Hellwig 
386578c714bSDarrick J. Wong 	oinfo.oi_owner = xefi->xefi_owner;
387578c714bSDarrick J. Wong 	if (xefi->xefi_flags & XFS_EFI_ATTR_FORK)
38872ba4555SDarrick J. Wong 		oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
389578c714bSDarrick J. Wong 	if (xefi->xefi_flags & XFS_EFI_BMBT_BLOCK)
39072ba4555SDarrick J. Wong 		oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
39181f40041SChristoph Hellwig 
392f6b38463SDarrick J. Wong 	trace_xfs_bmap_free_deferred(tp->t_mountp, xefi->xefi_pag->pag_agno, 0,
393f6b38463SDarrick J. Wong 			agbno, xefi->xefi_blockcount);
39472ba4555SDarrick J. Wong 
395f6b38463SDarrick J. Wong 	error = __xfs_free_extent(tp, xefi->xefi_pag, agbno,
396b742d7b4SDave Chinner 			xefi->xefi_blockcount, &oinfo, xefi->xefi_agresv,
397578c714bSDarrick J. Wong 			xefi->xefi_flags & XFS_EFI_SKIP_DISCARD);
398b2ccab31SDarrick J. Wong 
39981f40041SChristoph Hellwig 	/*
40081f40041SChristoph Hellwig 	 * Mark the transaction dirty, even on error. This ensures the
40181f40041SChristoph Hellwig 	 * transaction is aborted, which:
40281f40041SChristoph Hellwig 	 *
40381f40041SChristoph Hellwig 	 * 1.) releases the EFI and frees the EFD
40481f40041SChristoph Hellwig 	 * 2.) shuts down the filesystem
40581f40041SChristoph Hellwig 	 */
406bb7b1c9cSDave Chinner 	tp->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE;
40781f40041SChristoph Hellwig 	set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags);
40881f40041SChristoph Hellwig 
4090853b5deSDave Chinner 	/*
4100853b5deSDave Chinner 	 * If we need a new transaction to make progress, the caller will log a
4110853b5deSDave Chinner 	 * new EFI with the current contents. It will also log an EFD to cancel
4120853b5deSDave Chinner 	 * the existing EFI, and so we need to copy all the unprocessed extents
4130853b5deSDave Chinner 	 * in this EFI to the EFD so this works correctly.
4140853b5deSDave Chinner 	 */
4150853b5deSDave Chinner 	if (error == -EAGAIN) {
4160853b5deSDave Chinner 		xfs_efd_from_efi(efdp);
4170853b5deSDave Chinner 		return error;
4180853b5deSDave Chinner 	}
4190853b5deSDave Chinner 
42081f40041SChristoph Hellwig 	next_extent = efdp->efd_next_extent;
42181f40041SChristoph Hellwig 	ASSERT(next_extent < efdp->efd_format.efd_nextents);
42281f40041SChristoph Hellwig 	extp = &(efdp->efd_format.efd_extents[next_extent]);
423578c714bSDarrick J. Wong 	extp->ext_start = xefi->xefi_startblock;
424578c714bSDarrick J. Wong 	extp->ext_len = xefi->xefi_blockcount;
42581f40041SChristoph Hellwig 	efdp->efd_next_extent++;
42681f40041SChristoph Hellwig 
42781f40041SChristoph Hellwig 	return error;
42881f40041SChristoph Hellwig }
42981f40041SChristoph Hellwig 
43081f40041SChristoph Hellwig /* Sort bmap items by AG. */
43181f40041SChristoph Hellwig static int
xfs_extent_free_diff_items(void * priv,const struct list_head * a,const struct list_head * b)43281f40041SChristoph Hellwig xfs_extent_free_diff_items(
43381f40041SChristoph Hellwig 	void				*priv,
4344f0f586bSSami Tolvanen 	const struct list_head		*a,
4354f0f586bSSami Tolvanen 	const struct list_head		*b)
43681f40041SChristoph Hellwig {
43781f40041SChristoph Hellwig 	struct xfs_extent_free_item	*ra;
43881f40041SChristoph Hellwig 	struct xfs_extent_free_item	*rb;
43981f40041SChristoph Hellwig 
44081f40041SChristoph Hellwig 	ra = container_of(a, struct xfs_extent_free_item, xefi_list);
44181f40041SChristoph Hellwig 	rb = container_of(b, struct xfs_extent_free_item, xefi_list);
442f6b38463SDarrick J. Wong 
443f6b38463SDarrick J. Wong 	return ra->xefi_pag->pag_agno - rb->xefi_pag->pag_agno;
44481f40041SChristoph Hellwig }
44581f40041SChristoph Hellwig 
44681f40041SChristoph Hellwig /* Log a free extent to the intent item. */
44781f40041SChristoph Hellwig STATIC void
xfs_extent_free_log_item(struct xfs_trans * tp,struct xfs_efi_log_item * efip,struct xfs_extent_free_item * xefi)44881f40041SChristoph Hellwig xfs_extent_free_log_item(
44981f40041SChristoph Hellwig 	struct xfs_trans		*tp,
450c1f09188SChristoph Hellwig 	struct xfs_efi_log_item		*efip,
451578c714bSDarrick J. Wong 	struct xfs_extent_free_item	*xefi)
45281f40041SChristoph Hellwig {
45381f40041SChristoph Hellwig 	uint				next_extent;
45481f40041SChristoph Hellwig 	struct xfs_extent		*extp;
45581f40041SChristoph Hellwig 
45681f40041SChristoph Hellwig 	tp->t_flags |= XFS_TRANS_DIRTY;
45781f40041SChristoph Hellwig 	set_bit(XFS_LI_DIRTY, &efip->efi_item.li_flags);
45881f40041SChristoph Hellwig 
45981f40041SChristoph Hellwig 	/*
46081f40041SChristoph Hellwig 	 * atomic_inc_return gives us the value after the increment;
46181f40041SChristoph Hellwig 	 * we want to use it as an array index so we need to subtract 1 from
46281f40041SChristoph Hellwig 	 * it.
46381f40041SChristoph Hellwig 	 */
46481f40041SChristoph Hellwig 	next_extent = atomic_inc_return(&efip->efi_next_extent) - 1;
46581f40041SChristoph Hellwig 	ASSERT(next_extent < efip->efi_format.efi_nextents);
46681f40041SChristoph Hellwig 	extp = &efip->efi_format.efi_extents[next_extent];
467578c714bSDarrick J. Wong 	extp->ext_start = xefi->xefi_startblock;
468578c714bSDarrick J. Wong 	extp->ext_len = xefi->xefi_blockcount;
46981f40041SChristoph Hellwig }
47081f40041SChristoph Hellwig 
47113a83333SChristoph Hellwig static struct xfs_log_item *
xfs_extent_free_create_intent(struct xfs_trans * tp,struct list_head * items,unsigned int count,bool sort)472c1f09188SChristoph Hellwig xfs_extent_free_create_intent(
473c1f09188SChristoph Hellwig 	struct xfs_trans		*tp,
474c1f09188SChristoph Hellwig 	struct list_head		*items,
475d367a868SChristoph Hellwig 	unsigned int			count,
476d367a868SChristoph Hellwig 	bool				sort)
477c1f09188SChristoph Hellwig {
478c1f09188SChristoph Hellwig 	struct xfs_mount		*mp = tp->t_mountp;
479c1f09188SChristoph Hellwig 	struct xfs_efi_log_item		*efip = xfs_efi_init(mp, count);
480578c714bSDarrick J. Wong 	struct xfs_extent_free_item	*xefi;
481c1f09188SChristoph Hellwig 
482c1f09188SChristoph Hellwig 	ASSERT(count > 0);
483c1f09188SChristoph Hellwig 
484c1f09188SChristoph Hellwig 	xfs_trans_add_item(tp, &efip->efi_item);
485d367a868SChristoph Hellwig 	if (sort)
486d367a868SChristoph Hellwig 		list_sort(mp, items, xfs_extent_free_diff_items);
487578c714bSDarrick J. Wong 	list_for_each_entry(xefi, items, xefi_list)
488578c714bSDarrick J. Wong 		xfs_extent_free_log_item(tp, efip, xefi);
48913a83333SChristoph Hellwig 	return &efip->efi_item;
490c1f09188SChristoph Hellwig }
491c1f09188SChristoph Hellwig 
49281f40041SChristoph Hellwig /* Get an EFD so we can process all the free extents. */
493f09d167cSChristoph Hellwig static struct xfs_log_item *
xfs_extent_free_create_done(struct xfs_trans * tp,struct xfs_log_item * intent,unsigned int count)49481f40041SChristoph Hellwig xfs_extent_free_create_done(
49581f40041SChristoph Hellwig 	struct xfs_trans		*tp,
49613a83333SChristoph Hellwig 	struct xfs_log_item		*intent,
49781f40041SChristoph Hellwig 	unsigned int			count)
49881f40041SChristoph Hellwig {
499f09d167cSChristoph Hellwig 	return &xfs_trans_get_efd(tp, EFI_ITEM(intent), count)->efd_item;
50081f40041SChristoph Hellwig }
50181f40041SChristoph Hellwig 
502f6b38463SDarrick J. Wong /* Take a passive ref to the AG containing the space we're freeing. */
503f6b38463SDarrick J. Wong void
xfs_extent_free_get_group(struct xfs_mount * mp,struct xfs_extent_free_item * xefi)504f6b38463SDarrick J. Wong xfs_extent_free_get_group(
505f6b38463SDarrick J. Wong 	struct xfs_mount		*mp,
506f6b38463SDarrick J. Wong 	struct xfs_extent_free_item	*xefi)
507f6b38463SDarrick J. Wong {
508f6b38463SDarrick J. Wong 	xfs_agnumber_t			agno;
509f6b38463SDarrick J. Wong 
510f6b38463SDarrick J. Wong 	agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock);
511d5c88131SDarrick J. Wong 	xefi->xefi_pag = xfs_perag_intent_get(mp, agno);
512f6b38463SDarrick J. Wong }
513f6b38463SDarrick J. Wong 
514f6b38463SDarrick J. Wong /* Release a passive AG ref after some freeing work. */
515f6b38463SDarrick J. Wong static inline void
xfs_extent_free_put_group(struct xfs_extent_free_item * xefi)516f6b38463SDarrick J. Wong xfs_extent_free_put_group(
517f6b38463SDarrick J. Wong 	struct xfs_extent_free_item	*xefi)
518f6b38463SDarrick J. Wong {
519d5c88131SDarrick J. Wong 	xfs_perag_intent_put(xefi->xefi_pag);
520f6b38463SDarrick J. Wong }
521f6b38463SDarrick J. Wong 
52281f40041SChristoph Hellwig /* Process a free extent. */
52381f40041SChristoph Hellwig STATIC int
xfs_extent_free_finish_item(struct xfs_trans * tp,struct xfs_log_item * done,struct list_head * item,struct xfs_btree_cur ** state)52481f40041SChristoph Hellwig xfs_extent_free_finish_item(
52581f40041SChristoph Hellwig 	struct xfs_trans		*tp,
526f09d167cSChristoph Hellwig 	struct xfs_log_item		*done,
52781f40041SChristoph Hellwig 	struct list_head		*item,
5283ec1b26cSChristoph Hellwig 	struct xfs_btree_cur		**state)
52981f40041SChristoph Hellwig {
530578c714bSDarrick J. Wong 	struct xfs_extent_free_item	*xefi;
53181f40041SChristoph Hellwig 	int				error;
53281f40041SChristoph Hellwig 
533578c714bSDarrick J. Wong 	xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
53472ba4555SDarrick J. Wong 
535578c714bSDarrick J. Wong 	error = xfs_trans_free_extent(tp, EFD_ITEM(done), xefi);
536f6b38463SDarrick J. Wong 
5370853b5deSDave Chinner 	/*
5380853b5deSDave Chinner 	 * Don't free the XEFI if we need a new transaction to complete
5390853b5deSDave Chinner 	 * processing of it.
5400853b5deSDave Chinner 	 */
5410853b5deSDave Chinner 	if (error == -EAGAIN)
5420853b5deSDave Chinner 		return error;
5430853b5deSDave Chinner 
544f6b38463SDarrick J. Wong 	xfs_extent_free_put_group(xefi);
545578c714bSDarrick J. Wong 	kmem_cache_free(xfs_extfree_item_cache, xefi);
54681f40041SChristoph Hellwig 	return error;
54781f40041SChristoph Hellwig }
54881f40041SChristoph Hellwig 
54981f40041SChristoph Hellwig /* Abort all pending EFIs. */
55081f40041SChristoph Hellwig STATIC void
xfs_extent_free_abort_intent(struct xfs_log_item * intent)55181f40041SChristoph Hellwig xfs_extent_free_abort_intent(
55213a83333SChristoph Hellwig 	struct xfs_log_item		*intent)
55381f40041SChristoph Hellwig {
55413a83333SChristoph Hellwig 	xfs_efi_release(EFI_ITEM(intent));
55581f40041SChristoph Hellwig }
55681f40041SChristoph Hellwig 
55781f40041SChristoph Hellwig /* Cancel a free extent. */
55881f40041SChristoph Hellwig STATIC void
xfs_extent_free_cancel_item(struct list_head * item)55981f40041SChristoph Hellwig xfs_extent_free_cancel_item(
56081f40041SChristoph Hellwig 	struct list_head		*item)
56181f40041SChristoph Hellwig {
562578c714bSDarrick J. Wong 	struct xfs_extent_free_item	*xefi;
56381f40041SChristoph Hellwig 
564578c714bSDarrick J. Wong 	xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
565f6b38463SDarrick J. Wong 
566f6b38463SDarrick J. Wong 	xfs_extent_free_put_group(xefi);
567578c714bSDarrick J. Wong 	kmem_cache_free(xfs_extfree_item_cache, xefi);
56881f40041SChristoph Hellwig }
56981f40041SChristoph Hellwig 
57081f40041SChristoph Hellwig const struct xfs_defer_op_type xfs_extent_free_defer_type = {
57181f40041SChristoph Hellwig 	.max_items	= XFS_EFI_MAX_FAST_EXTENTS,
57281f40041SChristoph Hellwig 	.create_intent	= xfs_extent_free_create_intent,
57381f40041SChristoph Hellwig 	.abort_intent	= xfs_extent_free_abort_intent,
57481f40041SChristoph Hellwig 	.create_done	= xfs_extent_free_create_done,
57581f40041SChristoph Hellwig 	.finish_item	= xfs_extent_free_finish_item,
57681f40041SChristoph Hellwig 	.cancel_item	= xfs_extent_free_cancel_item,
57781f40041SChristoph Hellwig };
57881f40041SChristoph Hellwig 
57981f40041SChristoph Hellwig /*
58081f40041SChristoph Hellwig  * AGFL blocks are accounted differently in the reserve pools and are not
58181f40041SChristoph Hellwig  * inserted into the busy extent list.
58281f40041SChristoph Hellwig  */
58381f40041SChristoph Hellwig STATIC int
xfs_agfl_free_finish_item(struct xfs_trans * tp,struct xfs_log_item * done,struct list_head * item,struct xfs_btree_cur ** state)58481f40041SChristoph Hellwig xfs_agfl_free_finish_item(
58581f40041SChristoph Hellwig 	struct xfs_trans		*tp,
586f09d167cSChristoph Hellwig 	struct xfs_log_item		*done,
58781f40041SChristoph Hellwig 	struct list_head		*item,
5883ec1b26cSChristoph Hellwig 	struct xfs_btree_cur		**state)
58981f40041SChristoph Hellwig {
590b3b5ff41SDarrick J. Wong 	struct xfs_owner_info		oinfo = { };
59181f40041SChristoph Hellwig 	struct xfs_mount		*mp = tp->t_mountp;
592f09d167cSChristoph Hellwig 	struct xfs_efd_log_item		*efdp = EFD_ITEM(done);
593578c714bSDarrick J. Wong 	struct xfs_extent_free_item	*xefi;
59481f40041SChristoph Hellwig 	struct xfs_extent		*extp;
59581f40041SChristoph Hellwig 	struct xfs_buf			*agbp;
59681f40041SChristoph Hellwig 	int				error;
59781f40041SChristoph Hellwig 	xfs_agblock_t			agbno;
59881f40041SChristoph Hellwig 	uint				next_extent;
59981f40041SChristoph Hellwig 
600578c714bSDarrick J. Wong 	xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
601578c714bSDarrick J. Wong 	ASSERT(xefi->xefi_blockcount == 1);
602578c714bSDarrick J. Wong 	agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock);
603578c714bSDarrick J. Wong 	oinfo.oi_owner = xefi->xefi_owner;
60481f40041SChristoph Hellwig 
605f6b38463SDarrick J. Wong 	trace_xfs_agfl_free_deferred(mp, xefi->xefi_pag->pag_agno, 0, agbno,
606f6b38463SDarrick J. Wong 			xefi->xefi_blockcount);
60781f40041SChristoph Hellwig 
608f6b38463SDarrick J. Wong 	error = xfs_alloc_read_agf(xefi->xefi_pag, tp, 0, &agbp);
60981f40041SChristoph Hellwig 	if (!error)
610f6b38463SDarrick J. Wong 		error = xfs_free_agfl_block(tp, xefi->xefi_pag->pag_agno,
611f6b38463SDarrick J. Wong 				agbno, agbp, &oinfo);
61281f40041SChristoph Hellwig 
61381f40041SChristoph Hellwig 	/*
61481f40041SChristoph Hellwig 	 * Mark the transaction dirty, even on error. This ensures the
61581f40041SChristoph Hellwig 	 * transaction is aborted, which:
61681f40041SChristoph Hellwig 	 *
61781f40041SChristoph Hellwig 	 * 1.) releases the EFI and frees the EFD
61881f40041SChristoph Hellwig 	 * 2.) shuts down the filesystem
61981f40041SChristoph Hellwig 	 */
62081f40041SChristoph Hellwig 	tp->t_flags |= XFS_TRANS_DIRTY;
62181f40041SChristoph Hellwig 	set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags);
62281f40041SChristoph Hellwig 
62381f40041SChristoph Hellwig 	next_extent = efdp->efd_next_extent;
62481f40041SChristoph Hellwig 	ASSERT(next_extent < efdp->efd_format.efd_nextents);
62581f40041SChristoph Hellwig 	extp = &(efdp->efd_format.efd_extents[next_extent]);
626578c714bSDarrick J. Wong 	extp->ext_start = xefi->xefi_startblock;
627578c714bSDarrick J. Wong 	extp->ext_len = xefi->xefi_blockcount;
62881f40041SChristoph Hellwig 	efdp->efd_next_extent++;
62981f40041SChristoph Hellwig 
630f6b38463SDarrick J. Wong 	xfs_extent_free_put_group(xefi);
631578c714bSDarrick J. Wong 	kmem_cache_free(xfs_extfree_item_cache, xefi);
63281f40041SChristoph Hellwig 	return error;
63381f40041SChristoph Hellwig }
63481f40041SChristoph Hellwig 
63581f40041SChristoph Hellwig /* sub-type with special handling for AGFL deferred frees */
63681f40041SChristoph Hellwig const struct xfs_defer_op_type xfs_agfl_free_defer_type = {
63781f40041SChristoph Hellwig 	.max_items	= XFS_EFI_MAX_FAST_EXTENTS,
63881f40041SChristoph Hellwig 	.create_intent	= xfs_extent_free_create_intent,
63981f40041SChristoph Hellwig 	.abort_intent	= xfs_extent_free_abort_intent,
64081f40041SChristoph Hellwig 	.create_done	= xfs_extent_free_create_done,
64181f40041SChristoph Hellwig 	.finish_item	= xfs_agfl_free_finish_item,
64281f40041SChristoph Hellwig 	.cancel_item	= xfs_extent_free_cancel_item,
64381f40041SChristoph Hellwig };
64481f40041SChristoph Hellwig 
6453c15df3dSDarrick J. Wong /* Is this recovered EFI ok? */
6463c15df3dSDarrick J. Wong static inline bool
xfs_efi_validate_ext(struct xfs_mount * mp,struct xfs_extent * extp)6473c15df3dSDarrick J. Wong xfs_efi_validate_ext(
6483c15df3dSDarrick J. Wong 	struct xfs_mount		*mp,
6493c15df3dSDarrick J. Wong 	struct xfs_extent		*extp)
6503c15df3dSDarrick J. Wong {
65167457eb0SDarrick J. Wong 	return xfs_verify_fsbext(mp, extp->ext_start, extp->ext_len);
6523c15df3dSDarrick J. Wong }
6533c15df3dSDarrick J. Wong 
65481f40041SChristoph Hellwig /*
655dc42375dSDarrick J. Wong  * Process an extent free intent item that was recovered from
656dc42375dSDarrick J. Wong  * the log.  We need to free the extents that it describes.
657dc42375dSDarrick J. Wong  */
65810d0c6e0SDarrick J. Wong STATIC int
xfs_efi_item_recover(struct xfs_defer_pending * dfp,struct list_head * capture_list)65996b60f82SDarrick J. Wong xfs_efi_item_recover(
66087db24c8SDarrick J. Wong 	struct xfs_defer_pending	*dfp,
661e6fff81eSDarrick J. Wong 	struct list_head		*capture_list)
662dc42375dSDarrick J. Wong {
6633c919b09SDarrick J. Wong 	struct xfs_trans_res		resv;
66487db24c8SDarrick J. Wong 	struct xfs_log_item		*lip = dfp->dfp_intent;
66596b60f82SDarrick J. Wong 	struct xfs_efi_log_item		*efip = EFI_ITEM(lip);
666d86142ddSDave Chinner 	struct xfs_mount		*mp = lip->li_log->l_mp;
667dc42375dSDarrick J. Wong 	struct xfs_efd_log_item		*efdp;
668dc42375dSDarrick J. Wong 	struct xfs_trans		*tp;
669dc42375dSDarrick J. Wong 	int				i;
670dc42375dSDarrick J. Wong 	int				error = 0;
6710853b5deSDave Chinner 	bool				requeue_only = false;
672dc42375dSDarrick J. Wong 
673dc42375dSDarrick J. Wong 	/*
674dc42375dSDarrick J. Wong 	 * First check the validity of the extents described by the
675dc42375dSDarrick J. Wong 	 * EFI.  If any are bad, then assume that all are bad and
676dc42375dSDarrick J. Wong 	 * just toss the EFI.
677dc42375dSDarrick J. Wong 	 */
678dc42375dSDarrick J. Wong 	for (i = 0; i < efip->efi_format.efi_nextents; i++) {
6793c15df3dSDarrick J. Wong 		if (!xfs_efi_validate_ext(mp,
6803c15df3dSDarrick J. Wong 					&efip->efi_format.efi_extents[i])) {
6813c15df3dSDarrick J. Wong 			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
6823c15df3dSDarrick J. Wong 					&efip->efi_format,
6833c15df3dSDarrick J. Wong 					sizeof(efip->efi_format));
684895e196fSDarrick J. Wong 			return -EFSCORRUPTED;
685dc42375dSDarrick J. Wong 		}
6863c15df3dSDarrick J. Wong 	}
687dc42375dSDarrick J. Wong 
6883c919b09SDarrick J. Wong 	resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate);
6893c919b09SDarrick J. Wong 	error = xfs_trans_alloc(mp, &resv, 0, 0, 0, &tp);
690dc42375dSDarrick J. Wong 	if (error)
691dc42375dSDarrick J. Wong 		return error;
692680776e5SDarrick J. Wong 
693dc42375dSDarrick J. Wong 	efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
694680776e5SDarrick J. Wong 	xlog_recover_transfer_intent(tp, dfp);
695dc42375dSDarrick J. Wong 
696dc42375dSDarrick J. Wong 	for (i = 0; i < efip->efi_format.efi_nextents; i++) {
69772ba4555SDarrick J. Wong 		struct xfs_extent_free_item	fake = {
69872ba4555SDarrick J. Wong 			.xefi_owner		= XFS_RMAP_OWN_UNKNOWN,
699b742d7b4SDave Chinner 			.xefi_agresv		= XFS_AG_RESV_NONE,
70072ba4555SDarrick J. Wong 		};
70172ba4555SDarrick J. Wong 		struct xfs_extent		*extp;
70272ba4555SDarrick J. Wong 
703e127fafdSDarrick J. Wong 		extp = &efip->efi_format.efi_extents[i];
70472ba4555SDarrick J. Wong 
70572ba4555SDarrick J. Wong 		fake.xefi_startblock = extp->ext_start;
70672ba4555SDarrick J. Wong 		fake.xefi_blockcount = extp->ext_len;
70772ba4555SDarrick J. Wong 
7080853b5deSDave Chinner 		if (!requeue_only) {
709f6b38463SDarrick J. Wong 			xfs_extent_free_get_group(mp, &fake);
71072ba4555SDarrick J. Wong 			error = xfs_trans_free_extent(tp, efdp, &fake);
711f6b38463SDarrick J. Wong 			xfs_extent_free_put_group(&fake);
7120853b5deSDave Chinner 		}
7130853b5deSDave Chinner 
7140853b5deSDave Chinner 		/*
7150853b5deSDave Chinner 		 * If we can't free the extent without potentially deadlocking,
7160853b5deSDave Chinner 		 * requeue the rest of the extents to a new so that they get
7170853b5deSDave Chinner 		 * run again later with a new transaction context.
7180853b5deSDave Chinner 		 */
7190853b5deSDave Chinner 		if (error == -EAGAIN || requeue_only) {
7200853b5deSDave Chinner 			error = xfs_free_extent_later(tp, fake.xefi_startblock,
7210853b5deSDave Chinner 					fake.xefi_blockcount,
7220853b5deSDave Chinner 					&XFS_RMAP_OINFO_ANY_OWNER,
7230853b5deSDave Chinner 					fake.xefi_agresv);
7240853b5deSDave Chinner 			if (!error) {
7250853b5deSDave Chinner 				requeue_only = true;
7260853b5deSDave Chinner 				continue;
7270853b5deSDave Chinner 			}
72834acceaaSYang Li 		}
7290853b5deSDave Chinner 
73043059d54SDarrick J. Wong 		if (error == -EFSCORRUPTED)
73143059d54SDarrick J. Wong 			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
73243059d54SDarrick J. Wong 					extp, sizeof(*extp));
733dc42375dSDarrick J. Wong 		if (error)
734dc42375dSDarrick J. Wong 			goto abort_error;
735dc42375dSDarrick J. Wong 
736dc42375dSDarrick J. Wong 	}
737dc42375dSDarrick J. Wong 
738512edfacSDarrick J. Wong 	return xfs_defer_ops_capture_and_commit(tp, capture_list);
739dc42375dSDarrick J. Wong 
740dc42375dSDarrick J. Wong abort_error:
741dc42375dSDarrick J. Wong 	xfs_trans_cancel(tp);
742dc42375dSDarrick J. Wong 	return error;
743dc42375dSDarrick J. Wong }
74486ffa471SDarrick J. Wong 
745154c733aSDarrick J. Wong STATIC bool
xfs_efi_item_match(struct xfs_log_item * lip,uint64_t intent_id)746154c733aSDarrick J. Wong xfs_efi_item_match(
747154c733aSDarrick J. Wong 	struct xfs_log_item	*lip,
748154c733aSDarrick J. Wong 	uint64_t		intent_id)
749154c733aSDarrick J. Wong {
750154c733aSDarrick J. Wong 	return EFI_ITEM(lip)->efi_format.efi_id == intent_id;
751154c733aSDarrick J. Wong }
752154c733aSDarrick J. Wong 
7534e919af7SDarrick J. Wong /* Relog an intent item to push the log tail forward. */
7544e919af7SDarrick J. Wong static struct xfs_log_item *
xfs_efi_item_relog(struct xfs_log_item * intent,struct xfs_trans * tp)7554e919af7SDarrick J. Wong xfs_efi_item_relog(
7564e919af7SDarrick J. Wong 	struct xfs_log_item		*intent,
7574e919af7SDarrick J. Wong 	struct xfs_trans		*tp)
7584e919af7SDarrick J. Wong {
7594e919af7SDarrick J. Wong 	struct xfs_efd_log_item		*efdp;
7604e919af7SDarrick J. Wong 	struct xfs_efi_log_item		*efip;
7614e919af7SDarrick J. Wong 	struct xfs_extent		*extp;
7624e919af7SDarrick J. Wong 	unsigned int			count;
7634e919af7SDarrick J. Wong 
7644e919af7SDarrick J. Wong 	count = EFI_ITEM(intent)->efi_format.efi_nextents;
7654e919af7SDarrick J. Wong 	extp = EFI_ITEM(intent)->efi_format.efi_extents;
7664e919af7SDarrick J. Wong 
7674e919af7SDarrick J. Wong 	tp->t_flags |= XFS_TRANS_DIRTY;
7684e919af7SDarrick J. Wong 	efdp = xfs_trans_get_efd(tp, EFI_ITEM(intent), count);
7694e919af7SDarrick J. Wong 	efdp->efd_next_extent = count;
7704e919af7SDarrick J. Wong 	memcpy(efdp->efd_format.efd_extents, extp, count * sizeof(*extp));
7714e919af7SDarrick J. Wong 	set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags);
7724e919af7SDarrick J. Wong 
7734e919af7SDarrick J. Wong 	efip = xfs_efi_init(tp->t_mountp, count);
7744e919af7SDarrick J. Wong 	memcpy(efip->efi_format.efi_extents, extp, count * sizeof(*extp));
7754e919af7SDarrick J. Wong 	atomic_set(&efip->efi_next_extent, count);
7764e919af7SDarrick J. Wong 	xfs_trans_add_item(tp, &efip->efi_item);
7774e919af7SDarrick J. Wong 	set_bit(XFS_LI_DIRTY, &efip->efi_item.li_flags);
7784e919af7SDarrick J. Wong 	return &efip->efi_item;
7794e919af7SDarrick J. Wong }
7804e919af7SDarrick J. Wong 
78110d0c6e0SDarrick J. Wong static const struct xfs_item_ops xfs_efi_item_ops = {
782f5b81200SDave Chinner 	.flags		= XFS_ITEM_INTENT,
78310d0c6e0SDarrick J. Wong 	.iop_size	= xfs_efi_item_size,
78410d0c6e0SDarrick J. Wong 	.iop_format	= xfs_efi_item_format,
78510d0c6e0SDarrick J. Wong 	.iop_unpin	= xfs_efi_item_unpin,
78610d0c6e0SDarrick J. Wong 	.iop_release	= xfs_efi_item_release,
78710d0c6e0SDarrick J. Wong 	.iop_recover	= xfs_efi_item_recover,
788154c733aSDarrick J. Wong 	.iop_match	= xfs_efi_item_match,
7894e919af7SDarrick J. Wong 	.iop_relog	= xfs_efi_item_relog,
79010d0c6e0SDarrick J. Wong };
79110d0c6e0SDarrick J. Wong 
7929817aa80SDarrick J. Wong /*
7939817aa80SDarrick J. Wong  * This routine is called to create an in-core extent free intent
7949817aa80SDarrick J. Wong  * item from the efi format structure which was logged on disk.
7959817aa80SDarrick J. Wong  * It allocates an in-core efi, copies the extents from the format
7969817aa80SDarrick J. Wong  * structure into it, and adds the efi to the AIL with the given
7979817aa80SDarrick J. Wong  * LSN.
7989817aa80SDarrick J. Wong  */
7999817aa80SDarrick J. Wong STATIC int
xlog_recover_efi_commit_pass2(struct xlog * log,struct list_head * buffer_list,struct xlog_recover_item * item,xfs_lsn_t lsn)8009817aa80SDarrick J. Wong xlog_recover_efi_commit_pass2(
8019817aa80SDarrick J. Wong 	struct xlog			*log,
8029817aa80SDarrick J. Wong 	struct list_head		*buffer_list,
8039817aa80SDarrick J. Wong 	struct xlog_recover_item	*item,
8049817aa80SDarrick J. Wong 	xfs_lsn_t			lsn)
8059817aa80SDarrick J. Wong {
8069817aa80SDarrick J. Wong 	struct xfs_mount		*mp = log->l_mp;
8079817aa80SDarrick J. Wong 	struct xfs_efi_log_item		*efip;
8089817aa80SDarrick J. Wong 	struct xfs_efi_log_format	*efi_formatp;
8099817aa80SDarrick J. Wong 	int				error;
8109817aa80SDarrick J. Wong 
8119817aa80SDarrick J. Wong 	efi_formatp = item->ri_buf[0].i_addr;
8129817aa80SDarrick J. Wong 
8133c5aaaceSDarrick J. Wong 	if (item->ri_buf[0].i_len < xfs_efi_log_format_sizeof(0)) {
814950f0d50SDarrick J. Wong 		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
815950f0d50SDarrick J. Wong 				item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
81603a7485cSDarrick J. Wong 		return -EFSCORRUPTED;
81703a7485cSDarrick J. Wong 	}
81803a7485cSDarrick J. Wong 
8199817aa80SDarrick J. Wong 	efip = xfs_efi_init(mp, efi_formatp->efi_nextents);
8209817aa80SDarrick J. Wong 	error = xfs_efi_copy_format(&item->ri_buf[0], &efip->efi_format);
8219817aa80SDarrick J. Wong 	if (error) {
8229817aa80SDarrick J. Wong 		xfs_efi_item_free(efip);
8239817aa80SDarrick J. Wong 		return error;
8249817aa80SDarrick J. Wong 	}
8259817aa80SDarrick J. Wong 	atomic_set(&efip->efi_next_extent, efi_formatp->efi_nextents);
826cd3c2cf3SDarrick J. Wong 
827cd3c2cf3SDarrick J. Wong 	xlog_recover_intent_item(log, &efip->efi_item, lsn,
828cd3c2cf3SDarrick J. Wong 			XFS_DEFER_OPS_TYPE_FREE);
8299817aa80SDarrick J. Wong 	return 0;
8309817aa80SDarrick J. Wong }
8319817aa80SDarrick J. Wong 
83286ffa471SDarrick J. Wong const struct xlog_recover_item_ops xlog_efi_item_ops = {
83386ffa471SDarrick J. Wong 	.item_type		= XFS_LI_EFI,
8349817aa80SDarrick J. Wong 	.commit_pass2		= xlog_recover_efi_commit_pass2,
83586ffa471SDarrick J. Wong };
83686ffa471SDarrick J. Wong 
8379817aa80SDarrick J. Wong /*
8389817aa80SDarrick J. Wong  * This routine is called when an EFD format structure is found in a committed
8399817aa80SDarrick J. Wong  * transaction in the log. Its purpose is to cancel the corresponding EFI if it
8409817aa80SDarrick J. Wong  * was still in the log. To do this it searches the AIL for the EFI with an id
8419817aa80SDarrick J. Wong  * equal to that in the EFD format structure. If we find it we drop the EFD
8429817aa80SDarrick J. Wong  * reference, which removes the EFI from the AIL and frees it.
8439817aa80SDarrick J. Wong  */
8449817aa80SDarrick J. Wong STATIC int
xlog_recover_efd_commit_pass2(struct xlog * log,struct list_head * buffer_list,struct xlog_recover_item * item,xfs_lsn_t lsn)8459817aa80SDarrick J. Wong xlog_recover_efd_commit_pass2(
8469817aa80SDarrick J. Wong 	struct xlog			*log,
8479817aa80SDarrick J. Wong 	struct list_head		*buffer_list,
8489817aa80SDarrick J. Wong 	struct xlog_recover_item	*item,
8499817aa80SDarrick J. Wong 	xfs_lsn_t			lsn)
8509817aa80SDarrick J. Wong {
8519817aa80SDarrick J. Wong 	struct xfs_efd_log_format	*efd_formatp;
852921ed96bSDarrick J. Wong 	int				buflen = item->ri_buf[0].i_len;
8539817aa80SDarrick J. Wong 
8549817aa80SDarrick J. Wong 	efd_formatp = item->ri_buf[0].i_addr;
855921ed96bSDarrick J. Wong 
856921ed96bSDarrick J. Wong 	if (buflen < sizeof(struct xfs_efd_log_format)) {
857921ed96bSDarrick J. Wong 		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
858921ed96bSDarrick J. Wong 				efd_formatp, buflen);
859921ed96bSDarrick J. Wong 		return -EFSCORRUPTED;
860921ed96bSDarrick J. Wong 	}
861921ed96bSDarrick J. Wong 
862921ed96bSDarrick J. Wong 	if (item->ri_buf[0].i_len != xfs_efd_log_format32_sizeof(
863921ed96bSDarrick J. Wong 						efd_formatp->efd_nextents) &&
864921ed96bSDarrick J. Wong 	    item->ri_buf[0].i_len != xfs_efd_log_format64_sizeof(
865921ed96bSDarrick J. Wong 						efd_formatp->efd_nextents)) {
866921ed96bSDarrick J. Wong 		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
867921ed96bSDarrick J. Wong 				efd_formatp, buflen);
868921ed96bSDarrick J. Wong 		return -EFSCORRUPTED;
869921ed96bSDarrick J. Wong 	}
8709817aa80SDarrick J. Wong 
871154c733aSDarrick J. Wong 	xlog_recover_release_intent(log, XFS_LI_EFI, efd_formatp->efd_efi_id);
8729817aa80SDarrick J. Wong 	return 0;
8739817aa80SDarrick J. Wong }
8749817aa80SDarrick J. Wong 
87586ffa471SDarrick J. Wong const struct xlog_recover_item_ops xlog_efd_item_ops = {
87686ffa471SDarrick J. Wong 	.item_type		= XFS_LI_EFD,
8779817aa80SDarrick J. Wong 	.commit_pass2		= xlog_recover_efd_commit_pass2,
87886ffa471SDarrick J. Wong };
879