brintos

brintos / linux-shallow public Read only

0
0
Text · 22.0 KiB · abffc74 Raw
794 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.4 * All Rights Reserved.5 */6#include "xfs.h"7#include "xfs_fs.h"8#include "xfs_format.h"9#include "xfs_log_format.h"10#include "xfs_trans_resv.h"11#include "xfs_bit.h"12#include "xfs_shared.h"13#include "xfs_mount.h"14#include "xfs_ag.h"15#include "xfs_defer.h"16#include "xfs_trans.h"17#include "xfs_trans_priv.h"18#include "xfs_extfree_item.h"19#include "xfs_log.h"20#include "xfs_btree.h"21#include "xfs_rmap.h"22#include "xfs_alloc.h"23#include "xfs_bmap.h"24#include "xfs_trace.h"25#include "xfs_error.h"26#include "xfs_log_priv.h"27#include "xfs_log_recover.h"28 29struct kmem_cache	*xfs_efi_cache;30struct kmem_cache	*xfs_efd_cache;31 32static const struct xfs_item_ops xfs_efi_item_ops;33 34static inline struct xfs_efi_log_item *EFI_ITEM(struct xfs_log_item *lip)35{36	return container_of(lip, struct xfs_efi_log_item, efi_item);37}38 39STATIC void40xfs_efi_item_free(41	struct xfs_efi_log_item	*efip)42{43	kvfree(efip->efi_item.li_lv_shadow);44	if (efip->efi_format.efi_nextents > XFS_EFI_MAX_FAST_EXTENTS)45		kfree(efip);46	else47		kmem_cache_free(xfs_efi_cache, efip);48}49 50/*51 * Freeing the efi requires that we remove it from the AIL if it has already52 * been placed there. However, the EFI may not yet have been placed in the AIL53 * when called by xfs_efi_release() from EFD processing due to the ordering of54 * committed vs unpin operations in bulk insert operations. Hence the reference55 * count to ensure only the last caller frees the EFI.56 */57STATIC void58xfs_efi_release(59	struct xfs_efi_log_item	*efip)60{61	ASSERT(atomic_read(&efip->efi_refcount) > 0);62	if (!atomic_dec_and_test(&efip->efi_refcount))63		return;64 65	xfs_trans_ail_delete(&efip->efi_item, 0);66	xfs_efi_item_free(efip);67}68 69STATIC void70xfs_efi_item_size(71	struct xfs_log_item	*lip,72	int			*nvecs,73	int			*nbytes)74{75	struct xfs_efi_log_item	*efip = EFI_ITEM(lip);76 77	*nvecs += 1;78	*nbytes += xfs_efi_log_format_sizeof(efip->efi_format.efi_nextents);79}80 81/*82 * This is called to fill in the vector of log iovecs for the83 * given efi log item. We use only 1 iovec, and we point that84 * at the efi_log_format structure embedded in the efi item.85 * It is at this point that we assert that all of the extent86 * slots in the efi item have been filled.87 */88STATIC void89xfs_efi_item_format(90	struct xfs_log_item	*lip,91	struct xfs_log_vec	*lv)92{93	struct xfs_efi_log_item	*efip = EFI_ITEM(lip);94	struct xfs_log_iovec	*vecp = NULL;95 96	ASSERT(atomic_read(&efip->efi_next_extent) ==97				efip->efi_format.efi_nextents);98 99	efip->efi_format.efi_type = XFS_LI_EFI;100	efip->efi_format.efi_size = 1;101 102	xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFI_FORMAT,103			&efip->efi_format,104			xfs_efi_log_format_sizeof(efip->efi_format.efi_nextents));105}106 107 108/*109 * The unpin operation is the last place an EFI is manipulated in the log. It is110 * either inserted in the AIL or aborted in the event of a log I/O error. In111 * either case, the EFI transaction has been successfully committed to make it112 * this far. Therefore, we expect whoever committed the EFI to either construct113 * and commit the EFD or drop the EFD's reference in the event of error. Simply114 * drop the log's EFI reference now that the log is done with it.115 */116STATIC void117xfs_efi_item_unpin(118	struct xfs_log_item	*lip,119	int			remove)120{121	struct xfs_efi_log_item	*efip = EFI_ITEM(lip);122	xfs_efi_release(efip);123}124 125/*126 * The EFI has been either committed or aborted if the transaction has been127 * cancelled. If the transaction was cancelled, an EFD isn't going to be128 * constructed and thus we free the EFI here directly.129 */130STATIC void131xfs_efi_item_release(132	struct xfs_log_item	*lip)133{134	xfs_efi_release(EFI_ITEM(lip));135}136 137/*138 * Allocate and initialize an efi item with the given number of extents.139 */140STATIC struct xfs_efi_log_item *141xfs_efi_init(142	struct xfs_mount	*mp,143	uint			nextents)144 145{146	struct xfs_efi_log_item	*efip;147 148	ASSERT(nextents > 0);149	if (nextents > XFS_EFI_MAX_FAST_EXTENTS) {150		efip = kzalloc(xfs_efi_log_item_sizeof(nextents),151				GFP_KERNEL | __GFP_NOFAIL);152	} else {153		efip = kmem_cache_zalloc(xfs_efi_cache,154					 GFP_KERNEL | __GFP_NOFAIL);155	}156 157	xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops);158	efip->efi_format.efi_nextents = nextents;159	efip->efi_format.efi_id = (uintptr_t)(void *)efip;160	atomic_set(&efip->efi_next_extent, 0);161	atomic_set(&efip->efi_refcount, 2);162 163	return efip;164}165 166/*167 * Copy an EFI format buffer from the given buf, and into the destination168 * EFI format structure.169 * The given buffer can be in 32 bit or 64 bit form (which has different padding),170 * one of which will be the native format for this kernel.171 * It will handle the conversion of formats if necessary.172 */173STATIC int174xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)175{176	xfs_efi_log_format_t *src_efi_fmt = buf->i_addr;177	uint i;178	uint len = xfs_efi_log_format_sizeof(src_efi_fmt->efi_nextents);179	uint len32 = xfs_efi_log_format32_sizeof(src_efi_fmt->efi_nextents);180	uint len64 = xfs_efi_log_format64_sizeof(src_efi_fmt->efi_nextents);181 182	if (buf->i_len == len) {183		memcpy(dst_efi_fmt, src_efi_fmt,184		       offsetof(struct xfs_efi_log_format, efi_extents));185		for (i = 0; i < src_efi_fmt->efi_nextents; i++)186			memcpy(&dst_efi_fmt->efi_extents[i],187			       &src_efi_fmt->efi_extents[i],188			       sizeof(struct xfs_extent));189		return 0;190	} else if (buf->i_len == len32) {191		xfs_efi_log_format_32_t *src_efi_fmt_32 = buf->i_addr;192 193		dst_efi_fmt->efi_type     = src_efi_fmt_32->efi_type;194		dst_efi_fmt->efi_size     = src_efi_fmt_32->efi_size;195		dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents;196		dst_efi_fmt->efi_id       = src_efi_fmt_32->efi_id;197		for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {198			dst_efi_fmt->efi_extents[i].ext_start =199				src_efi_fmt_32->efi_extents[i].ext_start;200			dst_efi_fmt->efi_extents[i].ext_len =201				src_efi_fmt_32->efi_extents[i].ext_len;202		}203		return 0;204	} else if (buf->i_len == len64) {205		xfs_efi_log_format_64_t *src_efi_fmt_64 = buf->i_addr;206 207		dst_efi_fmt->efi_type     = src_efi_fmt_64->efi_type;208		dst_efi_fmt->efi_size     = src_efi_fmt_64->efi_size;209		dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents;210		dst_efi_fmt->efi_id       = src_efi_fmt_64->efi_id;211		for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {212			dst_efi_fmt->efi_extents[i].ext_start =213				src_efi_fmt_64->efi_extents[i].ext_start;214			dst_efi_fmt->efi_extents[i].ext_len =215				src_efi_fmt_64->efi_extents[i].ext_len;216		}217		return 0;218	}219	XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, NULL, buf->i_addr,220			buf->i_len);221	return -EFSCORRUPTED;222}223 224static inline struct xfs_efd_log_item *EFD_ITEM(struct xfs_log_item *lip)225{226	return container_of(lip, struct xfs_efd_log_item, efd_item);227}228 229STATIC void230xfs_efd_item_free(struct xfs_efd_log_item *efdp)231{232	kvfree(efdp->efd_item.li_lv_shadow);233	if (efdp->efd_format.efd_nextents > XFS_EFD_MAX_FAST_EXTENTS)234		kfree(efdp);235	else236		kmem_cache_free(xfs_efd_cache, efdp);237}238 239STATIC void240xfs_efd_item_size(241	struct xfs_log_item	*lip,242	int			*nvecs,243	int			*nbytes)244{245	struct xfs_efd_log_item	*efdp = EFD_ITEM(lip);246 247	*nvecs += 1;248	*nbytes += xfs_efd_log_format_sizeof(efdp->efd_format.efd_nextents);249}250 251/*252 * This is called to fill in the vector of log iovecs for the253 * given efd log item. We use only 1 iovec, and we point that254 * at the efd_log_format structure embedded in the efd item.255 * It is at this point that we assert that all of the extent256 * slots in the efd item have been filled.257 */258STATIC void259xfs_efd_item_format(260	struct xfs_log_item	*lip,261	struct xfs_log_vec	*lv)262{263	struct xfs_efd_log_item	*efdp = EFD_ITEM(lip);264	struct xfs_log_iovec	*vecp = NULL;265 266	ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents);267 268	efdp->efd_format.efd_type = XFS_LI_EFD;269	efdp->efd_format.efd_size = 1;270 271	xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFD_FORMAT,272			&efdp->efd_format,273			xfs_efd_log_format_sizeof(efdp->efd_format.efd_nextents));274}275 276/*277 * The EFD is either committed or aborted if the transaction is cancelled. If278 * the transaction is cancelled, drop our reference to the EFI and free the EFD.279 */280STATIC void281xfs_efd_item_release(282	struct xfs_log_item	*lip)283{284	struct xfs_efd_log_item	*efdp = EFD_ITEM(lip);285 286	xfs_efi_release(efdp->efd_efip);287	xfs_efd_item_free(efdp);288}289 290static struct xfs_log_item *291xfs_efd_item_intent(292	struct xfs_log_item	*lip)293{294	return &EFD_ITEM(lip)->efd_efip->efi_item;295}296 297static const struct xfs_item_ops xfs_efd_item_ops = {298	.flags		= XFS_ITEM_RELEASE_WHEN_COMMITTED |299			  XFS_ITEM_INTENT_DONE,300	.iop_size	= xfs_efd_item_size,301	.iop_format	= xfs_efd_item_format,302	.iop_release	= xfs_efd_item_release,303	.iop_intent	= xfs_efd_item_intent,304};305 306static inline struct xfs_extent_free_item *xefi_entry(const struct list_head *e)307{308	return list_entry(e, struct xfs_extent_free_item, xefi_list);309}310 311/*312 * Fill the EFD with all extents from the EFI when we need to roll the313 * transaction and continue with a new EFI.314 *315 * This simply copies all the extents in the EFI to the EFD rather than make316 * assumptions about which extents in the EFI have already been processed. We317 * currently keep the xefi list in the same order as the EFI extent list, but318 * that may not always be the case. Copying everything avoids leaving a landmine319 * were we fail to cancel all the extents in an EFI if the xefi list is320 * processed in a different order to the extents in the EFI.321 */322static void323xfs_efd_from_efi(324	struct xfs_efd_log_item	*efdp)325{326	struct xfs_efi_log_item *efip = efdp->efd_efip;327	uint                    i;328 329	ASSERT(efip->efi_format.efi_nextents > 0);330	ASSERT(efdp->efd_next_extent < efip->efi_format.efi_nextents);331 332	for (i = 0; i < efip->efi_format.efi_nextents; i++) {333	       efdp->efd_format.efd_extents[i] =334		       efip->efi_format.efi_extents[i];335	}336	efdp->efd_next_extent = efip->efi_format.efi_nextents;337}338 339static void340xfs_efd_add_extent(341	struct xfs_efd_log_item		*efdp,342	struct xfs_extent_free_item	*xefi)343{344	struct xfs_extent		*extp;345 346	ASSERT(efdp->efd_next_extent < efdp->efd_format.efd_nextents);347 348	extp = &efdp->efd_format.efd_extents[efdp->efd_next_extent];349	extp->ext_start = xefi->xefi_startblock;350	extp->ext_len = xefi->xefi_blockcount;351 352	efdp->efd_next_extent++;353}354 355/* Sort bmap items by AG. */356static int357xfs_extent_free_diff_items(358	void				*priv,359	const struct list_head		*a,360	const struct list_head		*b)361{362	struct xfs_extent_free_item	*ra = xefi_entry(a);363	struct xfs_extent_free_item	*rb = xefi_entry(b);364 365	return ra->xefi_pag->pag_agno - rb->xefi_pag->pag_agno;366}367 368/* Log a free extent to the intent item. */369STATIC void370xfs_extent_free_log_item(371	struct xfs_trans		*tp,372	struct xfs_efi_log_item		*efip,373	struct xfs_extent_free_item	*xefi)374{375	uint				next_extent;376	struct xfs_extent		*extp;377 378	/*379	 * atomic_inc_return gives us the value after the increment;380	 * we want to use it as an array index so we need to subtract 1 from381	 * it.382	 */383	next_extent = atomic_inc_return(&efip->efi_next_extent) - 1;384	ASSERT(next_extent < efip->efi_format.efi_nextents);385	extp = &efip->efi_format.efi_extents[next_extent];386	extp->ext_start = xefi->xefi_startblock;387	extp->ext_len = xefi->xefi_blockcount;388}389 390static struct xfs_log_item *391xfs_extent_free_create_intent(392	struct xfs_trans		*tp,393	struct list_head		*items,394	unsigned int			count,395	bool				sort)396{397	struct xfs_mount		*mp = tp->t_mountp;398	struct xfs_efi_log_item		*efip = xfs_efi_init(mp, count);399	struct xfs_extent_free_item	*xefi;400 401	ASSERT(count > 0);402 403	if (sort)404		list_sort(mp, items, xfs_extent_free_diff_items);405	list_for_each_entry(xefi, items, xefi_list)406		xfs_extent_free_log_item(tp, efip, xefi);407	return &efip->efi_item;408}409 410/* Get an EFD so we can process all the free extents. */411static struct xfs_log_item *412xfs_extent_free_create_done(413	struct xfs_trans		*tp,414	struct xfs_log_item		*intent,415	unsigned int			count)416{417	struct xfs_efi_log_item		*efip = EFI_ITEM(intent);418	struct xfs_efd_log_item		*efdp;419 420	ASSERT(count > 0);421 422	if (count > XFS_EFD_MAX_FAST_EXTENTS) {423		efdp = kzalloc(xfs_efd_log_item_sizeof(count),424				GFP_KERNEL | __GFP_NOFAIL);425	} else {426		efdp = kmem_cache_zalloc(xfs_efd_cache,427					GFP_KERNEL | __GFP_NOFAIL);428	}429 430	xfs_log_item_init(tp->t_mountp, &efdp->efd_item, XFS_LI_EFD,431			  &xfs_efd_item_ops);432	efdp->efd_efip = efip;433	efdp->efd_format.efd_nextents = count;434	efdp->efd_format.efd_efi_id = efip->efi_format.efi_id;435 436	return &efdp->efd_item;437}438 439/* Add this deferred EFI to the transaction. */440void441xfs_extent_free_defer_add(442	struct xfs_trans		*tp,443	struct xfs_extent_free_item	*xefi,444	struct xfs_defer_pending	**dfpp)445{446	struct xfs_mount		*mp = tp->t_mountp;447 448	trace_xfs_extent_free_defer(mp, xefi);449 450	xefi->xefi_pag = xfs_perag_intent_get(mp, xefi->xefi_startblock);451	if (xefi->xefi_agresv == XFS_AG_RESV_AGFL)452		*dfpp = xfs_defer_add(tp, &xefi->xefi_list,453				&xfs_agfl_free_defer_type);454	else455		*dfpp = xfs_defer_add(tp, &xefi->xefi_list,456				&xfs_extent_free_defer_type);457}458 459/* Cancel a free extent. */460STATIC void461xfs_extent_free_cancel_item(462	struct list_head		*item)463{464	struct xfs_extent_free_item	*xefi = xefi_entry(item);465 466	xfs_perag_intent_put(xefi->xefi_pag);467	kmem_cache_free(xfs_extfree_item_cache, xefi);468}469 470/* Process a free extent. */471STATIC int472xfs_extent_free_finish_item(473	struct xfs_trans		*tp,474	struct xfs_log_item		*done,475	struct list_head		*item,476	struct xfs_btree_cur		**state)477{478	struct xfs_owner_info		oinfo = { };479	struct xfs_extent_free_item	*xefi = xefi_entry(item);480	struct xfs_efd_log_item		*efdp = EFD_ITEM(done);481	struct xfs_mount		*mp = tp->t_mountp;482	xfs_agblock_t			agbno;483	int				error = 0;484 485	agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock);486 487	oinfo.oi_owner = xefi->xefi_owner;488	if (xefi->xefi_flags & XFS_EFI_ATTR_FORK)489		oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;490	if (xefi->xefi_flags & XFS_EFI_BMBT_BLOCK)491		oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;492 493	trace_xfs_extent_free_deferred(mp, xefi);494 495	/*496	 * If we need a new transaction to make progress, the caller will log a497	 * new EFI with the current contents. It will also log an EFD to cancel498	 * the existing EFI, and so we need to copy all the unprocessed extents499	 * in this EFI to the EFD so this works correctly.500	 */501	if (!(xefi->xefi_flags & XFS_EFI_CANCELLED))502		error = __xfs_free_extent(tp, xefi->xefi_pag, agbno,503				xefi->xefi_blockcount, &oinfo, xefi->xefi_agresv,504				xefi->xefi_flags & XFS_EFI_SKIP_DISCARD);505	if (error == -EAGAIN) {506		xfs_efd_from_efi(efdp);507		return error;508	}509 510	xfs_efd_add_extent(efdp, xefi);511	xfs_extent_free_cancel_item(item);512	return error;513}514 515/* Abort all pending EFIs. */516STATIC void517xfs_extent_free_abort_intent(518	struct xfs_log_item		*intent)519{520	xfs_efi_release(EFI_ITEM(intent));521}522 523/*524 * AGFL blocks are accounted differently in the reserve pools and are not525 * inserted into the busy extent list.526 */527STATIC int528xfs_agfl_free_finish_item(529	struct xfs_trans		*tp,530	struct xfs_log_item		*done,531	struct list_head		*item,532	struct xfs_btree_cur		**state)533{534	struct xfs_owner_info		oinfo = { };535	struct xfs_mount		*mp = tp->t_mountp;536	struct xfs_efd_log_item		*efdp = EFD_ITEM(done);537	struct xfs_extent_free_item	*xefi = xefi_entry(item);538	struct xfs_buf			*agbp;539	int				error;540	xfs_agblock_t			agbno;541 542	ASSERT(xefi->xefi_blockcount == 1);543	agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock);544	oinfo.oi_owner = xefi->xefi_owner;545 546	trace_xfs_agfl_free_deferred(mp, xefi);547 548	error = xfs_alloc_read_agf(xefi->xefi_pag, tp, 0, &agbp);549	if (!error)550		error = xfs_free_ag_extent(tp, agbp, xefi->xefi_pag->pag_agno,551				agbno, 1, &oinfo, XFS_AG_RESV_AGFL);552 553	xfs_efd_add_extent(efdp, xefi);554	xfs_extent_free_cancel_item(&xefi->xefi_list);555	return error;556}557 558/* Is this recovered EFI ok? */559static inline bool560xfs_efi_validate_ext(561	struct xfs_mount		*mp,562	struct xfs_extent		*extp)563{564	return xfs_verify_fsbext(mp, extp->ext_start, extp->ext_len);565}566 567static inline void568xfs_efi_recover_work(569	struct xfs_mount		*mp,570	struct xfs_defer_pending	*dfp,571	struct xfs_extent		*extp)572{573	struct xfs_extent_free_item	*xefi;574 575	xefi = kmem_cache_zalloc(xfs_extfree_item_cache,576			       GFP_KERNEL | __GFP_NOFAIL);577	xefi->xefi_startblock = extp->ext_start;578	xefi->xefi_blockcount = extp->ext_len;579	xefi->xefi_agresv = XFS_AG_RESV_NONE;580	xefi->xefi_owner = XFS_RMAP_OWN_UNKNOWN;581	xefi->xefi_pag = xfs_perag_intent_get(mp, extp->ext_start);582 583	xfs_defer_add_item(dfp, &xefi->xefi_list);584}585 586/*587 * Process an extent free intent item that was recovered from588 * the log.  We need to free the extents that it describes.589 */590STATIC int591xfs_extent_free_recover_work(592	struct xfs_defer_pending	*dfp,593	struct list_head		*capture_list)594{595	struct xfs_trans_res		resv;596	struct xfs_log_item		*lip = dfp->dfp_intent;597	struct xfs_efi_log_item		*efip = EFI_ITEM(lip);598	struct xfs_mount		*mp = lip->li_log->l_mp;599	struct xfs_trans		*tp;600	int				i;601	int				error = 0;602 603	/*604	 * First check the validity of the extents described by the605	 * EFI.  If any are bad, then assume that all are bad and606	 * just toss the EFI.607	 */608	for (i = 0; i < efip->efi_format.efi_nextents; i++) {609		if (!xfs_efi_validate_ext(mp,610					&efip->efi_format.efi_extents[i])) {611			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,612					&efip->efi_format,613					sizeof(efip->efi_format));614			return -EFSCORRUPTED;615		}616 617		xfs_efi_recover_work(mp, dfp, &efip->efi_format.efi_extents[i]);618	}619 620	resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate);621	error = xfs_trans_alloc(mp, &resv, 0, 0, 0, &tp);622	if (error)623		return error;624 625	error = xlog_recover_finish_intent(tp, dfp);626	if (error == -EFSCORRUPTED)627		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,628				&efip->efi_format,629				sizeof(efip->efi_format));630	if (error)631		goto abort_error;632 633	return xfs_defer_ops_capture_and_commit(tp, capture_list);634 635abort_error:636	xfs_trans_cancel(tp);637	return error;638}639 640/* Relog an intent item to push the log tail forward. */641static struct xfs_log_item *642xfs_extent_free_relog_intent(643	struct xfs_trans		*tp,644	struct xfs_log_item		*intent,645	struct xfs_log_item		*done_item)646{647	struct xfs_efd_log_item		*efdp = EFD_ITEM(done_item);648	struct xfs_efi_log_item		*efip;649	struct xfs_extent		*extp;650	unsigned int			count;651 652	count = EFI_ITEM(intent)->efi_format.efi_nextents;653	extp = EFI_ITEM(intent)->efi_format.efi_extents;654 655	efdp->efd_next_extent = count;656	memcpy(efdp->efd_format.efd_extents, extp, count * sizeof(*extp));657 658	efip = xfs_efi_init(tp->t_mountp, count);659	memcpy(efip->efi_format.efi_extents, extp, count * sizeof(*extp));660	atomic_set(&efip->efi_next_extent, count);661 662	return &efip->efi_item;663}664 665const struct xfs_defer_op_type xfs_extent_free_defer_type = {666	.name		= "extent_free",667	.max_items	= XFS_EFI_MAX_FAST_EXTENTS,668	.create_intent	= xfs_extent_free_create_intent,669	.abort_intent	= xfs_extent_free_abort_intent,670	.create_done	= xfs_extent_free_create_done,671	.finish_item	= xfs_extent_free_finish_item,672	.cancel_item	= xfs_extent_free_cancel_item,673	.recover_work	= xfs_extent_free_recover_work,674	.relog_intent	= xfs_extent_free_relog_intent,675};676 677/* sub-type with special handling for AGFL deferred frees */678const struct xfs_defer_op_type xfs_agfl_free_defer_type = {679	.name		= "agfl_free",680	.max_items	= XFS_EFI_MAX_FAST_EXTENTS,681	.create_intent	= xfs_extent_free_create_intent,682	.abort_intent	= xfs_extent_free_abort_intent,683	.create_done	= xfs_extent_free_create_done,684	.finish_item	= xfs_agfl_free_finish_item,685	.cancel_item	= xfs_extent_free_cancel_item,686	.recover_work	= xfs_extent_free_recover_work,687	.relog_intent	= xfs_extent_free_relog_intent,688};689 690STATIC bool691xfs_efi_item_match(692	struct xfs_log_item	*lip,693	uint64_t		intent_id)694{695	return EFI_ITEM(lip)->efi_format.efi_id == intent_id;696}697 698static const struct xfs_item_ops xfs_efi_item_ops = {699	.flags		= XFS_ITEM_INTENT,700	.iop_size	= xfs_efi_item_size,701	.iop_format	= xfs_efi_item_format,702	.iop_unpin	= xfs_efi_item_unpin,703	.iop_release	= xfs_efi_item_release,704	.iop_match	= xfs_efi_item_match,705};706 707/*708 * This routine is called to create an in-core extent free intent709 * item from the efi format structure which was logged on disk.710 * It allocates an in-core efi, copies the extents from the format711 * structure into it, and adds the efi to the AIL with the given712 * LSN.713 */714STATIC int715xlog_recover_efi_commit_pass2(716	struct xlog			*log,717	struct list_head		*buffer_list,718	struct xlog_recover_item	*item,719	xfs_lsn_t			lsn)720{721	struct xfs_mount		*mp = log->l_mp;722	struct xfs_efi_log_item		*efip;723	struct xfs_efi_log_format	*efi_formatp;724	int				error;725 726	efi_formatp = item->ri_buf[0].i_addr;727 728	if (item->ri_buf[0].i_len < xfs_efi_log_format_sizeof(0)) {729		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,730				item->ri_buf[0].i_addr, item->ri_buf[0].i_len);731		return -EFSCORRUPTED;732	}733 734	efip = xfs_efi_init(mp, efi_formatp->efi_nextents);735	error = xfs_efi_copy_format(&item->ri_buf[0], &efip->efi_format);736	if (error) {737		xfs_efi_item_free(efip);738		return error;739	}740	atomic_set(&efip->efi_next_extent, efi_formatp->efi_nextents);741 742	xlog_recover_intent_item(log, &efip->efi_item, lsn,743			&xfs_extent_free_defer_type);744	return 0;745}746 747const struct xlog_recover_item_ops xlog_efi_item_ops = {748	.item_type		= XFS_LI_EFI,749	.commit_pass2		= xlog_recover_efi_commit_pass2,750};751 752/*753 * This routine is called when an EFD format structure is found in a committed754 * transaction in the log. Its purpose is to cancel the corresponding EFI if it755 * was still in the log. To do this it searches the AIL for the EFI with an id756 * equal to that in the EFD format structure. If we find it we drop the EFD757 * reference, which removes the EFI from the AIL and frees it.758 */759STATIC int760xlog_recover_efd_commit_pass2(761	struct xlog			*log,762	struct list_head		*buffer_list,763	struct xlog_recover_item	*item,764	xfs_lsn_t			lsn)765{766	struct xfs_efd_log_format	*efd_formatp;767	int				buflen = item->ri_buf[0].i_len;768 769	efd_formatp = item->ri_buf[0].i_addr;770 771	if (buflen < sizeof(struct xfs_efd_log_format)) {772		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,773				efd_formatp, buflen);774		return -EFSCORRUPTED;775	}776 777	if (item->ri_buf[0].i_len != xfs_efd_log_format32_sizeof(778						efd_formatp->efd_nextents) &&779	    item->ri_buf[0].i_len != xfs_efd_log_format64_sizeof(780						efd_formatp->efd_nextents)) {781		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,782				efd_formatp, buflen);783		return -EFSCORRUPTED;784	}785 786	xlog_recover_release_intent(log, XFS_LI_EFI, efd_formatp->efd_efi_id);787	return 0;788}789 790const struct xlog_recover_item_ops xlog_efd_item_ops = {791	.item_type		= XFS_LI_EFD,792	.commit_pass2		= xlog_recover_efd_commit_pass2,793};794