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