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;
692*680776e5SDarrick J. Wong
693dc42375dSDarrick J. Wong efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
694*680776e5SDarrick 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