Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (C) 2016 Oracle.  All Rights Reserved.
0004  * Author: Darrick J. Wong <darrick.wong@oracle.com>
0005  */
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_format.h"
0009 #include "xfs_log_format.h"
0010 #include "xfs_trans_resv.h"
0011 #include "xfs_bit.h"
0012 #include "xfs_shared.h"
0013 #include "xfs_mount.h"
0014 #include "xfs_defer.h"
0015 #include "xfs_inode.h"
0016 #include "xfs_trans.h"
0017 #include "xfs_trans_priv.h"
0018 #include "xfs_bmap_item.h"
0019 #include "xfs_log.h"
0020 #include "xfs_bmap.h"
0021 #include "xfs_icache.h"
0022 #include "xfs_bmap_btree.h"
0023 #include "xfs_trans_space.h"
0024 #include "xfs_error.h"
0025 #include "xfs_log_priv.h"
0026 #include "xfs_log_recover.h"
0027 
0028 struct kmem_cache   *xfs_bui_cache;
0029 struct kmem_cache   *xfs_bud_cache;
0030 
0031 static const struct xfs_item_ops xfs_bui_item_ops;
0032 
0033 static inline struct xfs_bui_log_item *BUI_ITEM(struct xfs_log_item *lip)
0034 {
0035     return container_of(lip, struct xfs_bui_log_item, bui_item);
0036 }
0037 
0038 STATIC void
0039 xfs_bui_item_free(
0040     struct xfs_bui_log_item *buip)
0041 {
0042     kmem_free(buip->bui_item.li_lv_shadow);
0043     kmem_cache_free(xfs_bui_cache, buip);
0044 }
0045 
0046 /*
0047  * Freeing the BUI requires that we remove it from the AIL if it has already
0048  * been placed there. However, the BUI may not yet have been placed in the AIL
0049  * when called by xfs_bui_release() from BUD processing due to the ordering of
0050  * committed vs unpin operations in bulk insert operations. Hence the reference
0051  * count to ensure only the last caller frees the BUI.
0052  */
0053 STATIC void
0054 xfs_bui_release(
0055     struct xfs_bui_log_item *buip)
0056 {
0057     ASSERT(atomic_read(&buip->bui_refcount) > 0);
0058     if (!atomic_dec_and_test(&buip->bui_refcount))
0059         return;
0060 
0061     xfs_trans_ail_delete(&buip->bui_item, 0);
0062     xfs_bui_item_free(buip);
0063 }
0064 
0065 
0066 STATIC void
0067 xfs_bui_item_size(
0068     struct xfs_log_item *lip,
0069     int         *nvecs,
0070     int         *nbytes)
0071 {
0072     struct xfs_bui_log_item *buip = BUI_ITEM(lip);
0073 
0074     *nvecs += 1;
0075     *nbytes += xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents);
0076 }
0077 
0078 /*
0079  * This is called to fill in the vector of log iovecs for the
0080  * given bui log item. We use only 1 iovec, and we point that
0081  * at the bui_log_format structure embedded in the bui item.
0082  * It is at this point that we assert that all of the extent
0083  * slots in the bui item have been filled.
0084  */
0085 STATIC void
0086 xfs_bui_item_format(
0087     struct xfs_log_item *lip,
0088     struct xfs_log_vec  *lv)
0089 {
0090     struct xfs_bui_log_item *buip = BUI_ITEM(lip);
0091     struct xfs_log_iovec    *vecp = NULL;
0092 
0093     ASSERT(atomic_read(&buip->bui_next_extent) ==
0094             buip->bui_format.bui_nextents);
0095 
0096     buip->bui_format.bui_type = XFS_LI_BUI;
0097     buip->bui_format.bui_size = 1;
0098 
0099     xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUI_FORMAT, &buip->bui_format,
0100             xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents));
0101 }
0102 
0103 /*
0104  * The unpin operation is the last place an BUI is manipulated in the log. It is
0105  * either inserted in the AIL or aborted in the event of a log I/O error. In
0106  * either case, the BUI transaction has been successfully committed to make it
0107  * this far. Therefore, we expect whoever committed the BUI to either construct
0108  * and commit the BUD or drop the BUD's reference in the event of error. Simply
0109  * drop the log's BUI reference now that the log is done with it.
0110  */
0111 STATIC void
0112 xfs_bui_item_unpin(
0113     struct xfs_log_item *lip,
0114     int         remove)
0115 {
0116     struct xfs_bui_log_item *buip = BUI_ITEM(lip);
0117 
0118     xfs_bui_release(buip);
0119 }
0120 
0121 /*
0122  * The BUI has been either committed or aborted if the transaction has been
0123  * cancelled. If the transaction was cancelled, an BUD isn't going to be
0124  * constructed and thus we free the BUI here directly.
0125  */
0126 STATIC void
0127 xfs_bui_item_release(
0128     struct xfs_log_item *lip)
0129 {
0130     xfs_bui_release(BUI_ITEM(lip));
0131 }
0132 
0133 /*
0134  * Allocate and initialize an bui item with the given number of extents.
0135  */
0136 STATIC struct xfs_bui_log_item *
0137 xfs_bui_init(
0138     struct xfs_mount        *mp)
0139 
0140 {
0141     struct xfs_bui_log_item     *buip;
0142 
0143     buip = kmem_cache_zalloc(xfs_bui_cache, GFP_KERNEL | __GFP_NOFAIL);
0144 
0145     xfs_log_item_init(mp, &buip->bui_item, XFS_LI_BUI, &xfs_bui_item_ops);
0146     buip->bui_format.bui_nextents = XFS_BUI_MAX_FAST_EXTENTS;
0147     buip->bui_format.bui_id = (uintptr_t)(void *)buip;
0148     atomic_set(&buip->bui_next_extent, 0);
0149     atomic_set(&buip->bui_refcount, 2);
0150 
0151     return buip;
0152 }
0153 
0154 static inline struct xfs_bud_log_item *BUD_ITEM(struct xfs_log_item *lip)
0155 {
0156     return container_of(lip, struct xfs_bud_log_item, bud_item);
0157 }
0158 
0159 STATIC void
0160 xfs_bud_item_size(
0161     struct xfs_log_item *lip,
0162     int         *nvecs,
0163     int         *nbytes)
0164 {
0165     *nvecs += 1;
0166     *nbytes += sizeof(struct xfs_bud_log_format);
0167 }
0168 
0169 /*
0170  * This is called to fill in the vector of log iovecs for the
0171  * given bud log item. We use only 1 iovec, and we point that
0172  * at the bud_log_format structure embedded in the bud item.
0173  * It is at this point that we assert that all of the extent
0174  * slots in the bud item have been filled.
0175  */
0176 STATIC void
0177 xfs_bud_item_format(
0178     struct xfs_log_item *lip,
0179     struct xfs_log_vec  *lv)
0180 {
0181     struct xfs_bud_log_item *budp = BUD_ITEM(lip);
0182     struct xfs_log_iovec    *vecp = NULL;
0183 
0184     budp->bud_format.bud_type = XFS_LI_BUD;
0185     budp->bud_format.bud_size = 1;
0186 
0187     xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUD_FORMAT, &budp->bud_format,
0188             sizeof(struct xfs_bud_log_format));
0189 }
0190 
0191 /*
0192  * The BUD is either committed or aborted if the transaction is cancelled. If
0193  * the transaction is cancelled, drop our reference to the BUI and free the
0194  * BUD.
0195  */
0196 STATIC void
0197 xfs_bud_item_release(
0198     struct xfs_log_item *lip)
0199 {
0200     struct xfs_bud_log_item *budp = BUD_ITEM(lip);
0201 
0202     xfs_bui_release(budp->bud_buip);
0203     kmem_free(budp->bud_item.li_lv_shadow);
0204     kmem_cache_free(xfs_bud_cache, budp);
0205 }
0206 
0207 static struct xfs_log_item *
0208 xfs_bud_item_intent(
0209     struct xfs_log_item *lip)
0210 {
0211     return &BUD_ITEM(lip)->bud_buip->bui_item;
0212 }
0213 
0214 static const struct xfs_item_ops xfs_bud_item_ops = {
0215     .flags      = XFS_ITEM_RELEASE_WHEN_COMMITTED |
0216               XFS_ITEM_INTENT_DONE,
0217     .iop_size   = xfs_bud_item_size,
0218     .iop_format = xfs_bud_item_format,
0219     .iop_release    = xfs_bud_item_release,
0220     .iop_intent = xfs_bud_item_intent,
0221 };
0222 
0223 static struct xfs_bud_log_item *
0224 xfs_trans_get_bud(
0225     struct xfs_trans        *tp,
0226     struct xfs_bui_log_item     *buip)
0227 {
0228     struct xfs_bud_log_item     *budp;
0229 
0230     budp = kmem_cache_zalloc(xfs_bud_cache, GFP_KERNEL | __GFP_NOFAIL);
0231     xfs_log_item_init(tp->t_mountp, &budp->bud_item, XFS_LI_BUD,
0232               &xfs_bud_item_ops);
0233     budp->bud_buip = buip;
0234     budp->bud_format.bud_bui_id = buip->bui_format.bui_id;
0235 
0236     xfs_trans_add_item(tp, &budp->bud_item);
0237     return budp;
0238 }
0239 
0240 /*
0241  * Finish an bmap update and log it to the BUD. Note that the
0242  * transaction is marked dirty regardless of whether the bmap update
0243  * succeeds or fails to support the BUI/BUD lifecycle rules.
0244  */
0245 static int
0246 xfs_trans_log_finish_bmap_update(
0247     struct xfs_trans        *tp,
0248     struct xfs_bud_log_item     *budp,
0249     enum xfs_bmap_intent_type   type,
0250     struct xfs_inode        *ip,
0251     int             whichfork,
0252     xfs_fileoff_t           startoff,
0253     xfs_fsblock_t           startblock,
0254     xfs_filblks_t           *blockcount,
0255     xfs_exntst_t            state)
0256 {
0257     int             error;
0258 
0259     error = xfs_bmap_finish_one(tp, ip, type, whichfork, startoff,
0260             startblock, blockcount, state);
0261 
0262     /*
0263      * Mark the transaction dirty, even on error. This ensures the
0264      * transaction is aborted, which:
0265      *
0266      * 1.) releases the BUI and frees the BUD
0267      * 2.) shuts down the filesystem
0268      */
0269     tp->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE;
0270     set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags);
0271 
0272     return error;
0273 }
0274 
0275 /* Sort bmap intents by inode. */
0276 static int
0277 xfs_bmap_update_diff_items(
0278     void                *priv,
0279     const struct list_head      *a,
0280     const struct list_head      *b)
0281 {
0282     struct xfs_bmap_intent      *ba;
0283     struct xfs_bmap_intent      *bb;
0284 
0285     ba = container_of(a, struct xfs_bmap_intent, bi_list);
0286     bb = container_of(b, struct xfs_bmap_intent, bi_list);
0287     return ba->bi_owner->i_ino - bb->bi_owner->i_ino;
0288 }
0289 
0290 /* Set the map extent flags for this mapping. */
0291 static void
0292 xfs_trans_set_bmap_flags(
0293     struct xfs_map_extent       *bmap,
0294     enum xfs_bmap_intent_type   type,
0295     int             whichfork,
0296     xfs_exntst_t            state)
0297 {
0298     bmap->me_flags = 0;
0299     switch (type) {
0300     case XFS_BMAP_MAP:
0301     case XFS_BMAP_UNMAP:
0302         bmap->me_flags = type;
0303         break;
0304     default:
0305         ASSERT(0);
0306     }
0307     if (state == XFS_EXT_UNWRITTEN)
0308         bmap->me_flags |= XFS_BMAP_EXTENT_UNWRITTEN;
0309     if (whichfork == XFS_ATTR_FORK)
0310         bmap->me_flags |= XFS_BMAP_EXTENT_ATTR_FORK;
0311 }
0312 
0313 /* Log bmap updates in the intent item. */
0314 STATIC void
0315 xfs_bmap_update_log_item(
0316     struct xfs_trans        *tp,
0317     struct xfs_bui_log_item     *buip,
0318     struct xfs_bmap_intent      *bmap)
0319 {
0320     uint                next_extent;
0321     struct xfs_map_extent       *map;
0322 
0323     tp->t_flags |= XFS_TRANS_DIRTY;
0324     set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags);
0325 
0326     /*
0327      * atomic_inc_return gives us the value after the increment;
0328      * we want to use it as an array index so we need to subtract 1 from
0329      * it.
0330      */
0331     next_extent = atomic_inc_return(&buip->bui_next_extent) - 1;
0332     ASSERT(next_extent < buip->bui_format.bui_nextents);
0333     map = &buip->bui_format.bui_extents[next_extent];
0334     map->me_owner = bmap->bi_owner->i_ino;
0335     map->me_startblock = bmap->bi_bmap.br_startblock;
0336     map->me_startoff = bmap->bi_bmap.br_startoff;
0337     map->me_len = bmap->bi_bmap.br_blockcount;
0338     xfs_trans_set_bmap_flags(map, bmap->bi_type, bmap->bi_whichfork,
0339             bmap->bi_bmap.br_state);
0340 }
0341 
0342 static struct xfs_log_item *
0343 xfs_bmap_update_create_intent(
0344     struct xfs_trans        *tp,
0345     struct list_head        *items,
0346     unsigned int            count,
0347     bool                sort)
0348 {
0349     struct xfs_mount        *mp = tp->t_mountp;
0350     struct xfs_bui_log_item     *buip = xfs_bui_init(mp);
0351     struct xfs_bmap_intent      *bmap;
0352 
0353     ASSERT(count == XFS_BUI_MAX_FAST_EXTENTS);
0354 
0355     xfs_trans_add_item(tp, &buip->bui_item);
0356     if (sort)
0357         list_sort(mp, items, xfs_bmap_update_diff_items);
0358     list_for_each_entry(bmap, items, bi_list)
0359         xfs_bmap_update_log_item(tp, buip, bmap);
0360     return &buip->bui_item;
0361 }
0362 
0363 /* Get an BUD so we can process all the deferred rmap updates. */
0364 static struct xfs_log_item *
0365 xfs_bmap_update_create_done(
0366     struct xfs_trans        *tp,
0367     struct xfs_log_item     *intent,
0368     unsigned int            count)
0369 {
0370     return &xfs_trans_get_bud(tp, BUI_ITEM(intent))->bud_item;
0371 }
0372 
0373 /* Process a deferred rmap update. */
0374 STATIC int
0375 xfs_bmap_update_finish_item(
0376     struct xfs_trans        *tp,
0377     struct xfs_log_item     *done,
0378     struct list_head        *item,
0379     struct xfs_btree_cur        **state)
0380 {
0381     struct xfs_bmap_intent      *bmap;
0382     xfs_filblks_t           count;
0383     int             error;
0384 
0385     bmap = container_of(item, struct xfs_bmap_intent, bi_list);
0386     count = bmap->bi_bmap.br_blockcount;
0387     error = xfs_trans_log_finish_bmap_update(tp, BUD_ITEM(done),
0388             bmap->bi_type,
0389             bmap->bi_owner, bmap->bi_whichfork,
0390             bmap->bi_bmap.br_startoff,
0391             bmap->bi_bmap.br_startblock,
0392             &count,
0393             bmap->bi_bmap.br_state);
0394     if (!error && count > 0) {
0395         ASSERT(bmap->bi_type == XFS_BMAP_UNMAP);
0396         bmap->bi_bmap.br_blockcount = count;
0397         return -EAGAIN;
0398     }
0399     kmem_cache_free(xfs_bmap_intent_cache, bmap);
0400     return error;
0401 }
0402 
0403 /* Abort all pending BUIs. */
0404 STATIC void
0405 xfs_bmap_update_abort_intent(
0406     struct xfs_log_item     *intent)
0407 {
0408     xfs_bui_release(BUI_ITEM(intent));
0409 }
0410 
0411 /* Cancel a deferred rmap update. */
0412 STATIC void
0413 xfs_bmap_update_cancel_item(
0414     struct list_head        *item)
0415 {
0416     struct xfs_bmap_intent      *bmap;
0417 
0418     bmap = container_of(item, struct xfs_bmap_intent, bi_list);
0419     kmem_cache_free(xfs_bmap_intent_cache, bmap);
0420 }
0421 
0422 const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
0423     .max_items  = XFS_BUI_MAX_FAST_EXTENTS,
0424     .create_intent  = xfs_bmap_update_create_intent,
0425     .abort_intent   = xfs_bmap_update_abort_intent,
0426     .create_done    = xfs_bmap_update_create_done,
0427     .finish_item    = xfs_bmap_update_finish_item,
0428     .cancel_item    = xfs_bmap_update_cancel_item,
0429 };
0430 
0431 /* Is this recovered BUI ok? */
0432 static inline bool
0433 xfs_bui_validate(
0434     struct xfs_mount        *mp,
0435     struct xfs_bui_log_item     *buip)
0436 {
0437     struct xfs_map_extent       *bmap;
0438 
0439     /* Only one mapping operation per BUI... */
0440     if (buip->bui_format.bui_nextents != XFS_BUI_MAX_FAST_EXTENTS)
0441         return false;
0442 
0443     bmap = &buip->bui_format.bui_extents[0];
0444 
0445     if (bmap->me_flags & ~XFS_BMAP_EXTENT_FLAGS)
0446         return false;
0447 
0448     switch (bmap->me_flags & XFS_BMAP_EXTENT_TYPE_MASK) {
0449     case XFS_BMAP_MAP:
0450     case XFS_BMAP_UNMAP:
0451         break;
0452     default:
0453         return false;
0454     }
0455 
0456     if (!xfs_verify_ino(mp, bmap->me_owner))
0457         return false;
0458 
0459     if (!xfs_verify_fileext(mp, bmap->me_startoff, bmap->me_len))
0460         return false;
0461 
0462     return xfs_verify_fsbext(mp, bmap->me_startblock, bmap->me_len);
0463 }
0464 
0465 /*
0466  * Process a bmap update intent item that was recovered from the log.
0467  * We need to update some inode's bmbt.
0468  */
0469 STATIC int
0470 xfs_bui_item_recover(
0471     struct xfs_log_item     *lip,
0472     struct list_head        *capture_list)
0473 {
0474     struct xfs_bmbt_irec        irec;
0475     struct xfs_bui_log_item     *buip = BUI_ITEM(lip);
0476     struct xfs_trans        *tp;
0477     struct xfs_inode        *ip = NULL;
0478     struct xfs_mount        *mp = lip->li_log->l_mp;
0479     struct xfs_map_extent       *bmap;
0480     struct xfs_bud_log_item     *budp;
0481     xfs_filblks_t           count;
0482     xfs_exntst_t            state;
0483     unsigned int            bui_type;
0484     int             whichfork;
0485     int             iext_delta;
0486     int             error = 0;
0487 
0488     if (!xfs_bui_validate(mp, buip)) {
0489         XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
0490                 &buip->bui_format, sizeof(buip->bui_format));
0491         return -EFSCORRUPTED;
0492     }
0493 
0494     bmap = &buip->bui_format.bui_extents[0];
0495     state = (bmap->me_flags & XFS_BMAP_EXTENT_UNWRITTEN) ?
0496             XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
0497     whichfork = (bmap->me_flags & XFS_BMAP_EXTENT_ATTR_FORK) ?
0498             XFS_ATTR_FORK : XFS_DATA_FORK;
0499     bui_type = bmap->me_flags & XFS_BMAP_EXTENT_TYPE_MASK;
0500 
0501     error = xlog_recover_iget(mp, bmap->me_owner, &ip);
0502     if (error)
0503         return error;
0504 
0505     /* Allocate transaction and do the work. */
0506     error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
0507             XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
0508     if (error)
0509         goto err_rele;
0510 
0511     budp = xfs_trans_get_bud(tp, buip);
0512     xfs_ilock(ip, XFS_ILOCK_EXCL);
0513     xfs_trans_ijoin(tp, ip, 0);
0514 
0515     if (bui_type == XFS_BMAP_MAP)
0516         iext_delta = XFS_IEXT_ADD_NOSPLIT_CNT;
0517     else
0518         iext_delta = XFS_IEXT_PUNCH_HOLE_CNT;
0519 
0520     error = xfs_iext_count_may_overflow(ip, whichfork, iext_delta);
0521     if (error == -EFBIG)
0522         error = xfs_iext_count_upgrade(tp, ip, iext_delta);
0523     if (error)
0524         goto err_cancel;
0525 
0526     count = bmap->me_len;
0527     error = xfs_trans_log_finish_bmap_update(tp, budp, bui_type, ip,
0528             whichfork, bmap->me_startoff, bmap->me_startblock,
0529             &count, state);
0530     if (error == -EFSCORRUPTED)
0531         XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bmap,
0532                 sizeof(*bmap));
0533     if (error)
0534         goto err_cancel;
0535 
0536     if (count > 0) {
0537         ASSERT(bui_type == XFS_BMAP_UNMAP);
0538         irec.br_startblock = bmap->me_startblock;
0539         irec.br_blockcount = count;
0540         irec.br_startoff = bmap->me_startoff;
0541         irec.br_state = state;
0542         xfs_bmap_unmap_extent(tp, ip, &irec);
0543     }
0544 
0545     /*
0546      * Commit transaction, which frees the transaction and saves the inode
0547      * for later replay activities.
0548      */
0549     error = xfs_defer_ops_capture_and_commit(tp, capture_list);
0550     if (error)
0551         goto err_unlock;
0552 
0553     xfs_iunlock(ip, XFS_ILOCK_EXCL);
0554     xfs_irele(ip);
0555     return 0;
0556 
0557 err_cancel:
0558     xfs_trans_cancel(tp);
0559 err_unlock:
0560     xfs_iunlock(ip, XFS_ILOCK_EXCL);
0561 err_rele:
0562     xfs_irele(ip);
0563     return error;
0564 }
0565 
0566 STATIC bool
0567 xfs_bui_item_match(
0568     struct xfs_log_item *lip,
0569     uint64_t        intent_id)
0570 {
0571     return BUI_ITEM(lip)->bui_format.bui_id == intent_id;
0572 }
0573 
0574 /* Relog an intent item to push the log tail forward. */
0575 static struct xfs_log_item *
0576 xfs_bui_item_relog(
0577     struct xfs_log_item     *intent,
0578     struct xfs_trans        *tp)
0579 {
0580     struct xfs_bud_log_item     *budp;
0581     struct xfs_bui_log_item     *buip;
0582     struct xfs_map_extent       *extp;
0583     unsigned int            count;
0584 
0585     count = BUI_ITEM(intent)->bui_format.bui_nextents;
0586     extp = BUI_ITEM(intent)->bui_format.bui_extents;
0587 
0588     tp->t_flags |= XFS_TRANS_DIRTY;
0589     budp = xfs_trans_get_bud(tp, BUI_ITEM(intent));
0590     set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags);
0591 
0592     buip = xfs_bui_init(tp->t_mountp);
0593     memcpy(buip->bui_format.bui_extents, extp, count * sizeof(*extp));
0594     atomic_set(&buip->bui_next_extent, count);
0595     xfs_trans_add_item(tp, &buip->bui_item);
0596     set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags);
0597     return &buip->bui_item;
0598 }
0599 
0600 static const struct xfs_item_ops xfs_bui_item_ops = {
0601     .flags      = XFS_ITEM_INTENT,
0602     .iop_size   = xfs_bui_item_size,
0603     .iop_format = xfs_bui_item_format,
0604     .iop_unpin  = xfs_bui_item_unpin,
0605     .iop_release    = xfs_bui_item_release,
0606     .iop_recover    = xfs_bui_item_recover,
0607     .iop_match  = xfs_bui_item_match,
0608     .iop_relog  = xfs_bui_item_relog,
0609 };
0610 
0611 /*
0612  * Copy an BUI format buffer from the given buf, and into the destination
0613  * BUI format structure.  The BUI/BUD items were designed not to need any
0614  * special alignment handling.
0615  */
0616 static int
0617 xfs_bui_copy_format(
0618     struct xfs_log_iovec        *buf,
0619     struct xfs_bui_log_format   *dst_bui_fmt)
0620 {
0621     struct xfs_bui_log_format   *src_bui_fmt;
0622     uint                len;
0623 
0624     src_bui_fmt = buf->i_addr;
0625     len = xfs_bui_log_format_sizeof(src_bui_fmt->bui_nextents);
0626 
0627     if (buf->i_len == len) {
0628         memcpy(dst_bui_fmt, src_bui_fmt, len);
0629         return 0;
0630     }
0631     XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
0632     return -EFSCORRUPTED;
0633 }
0634 
0635 /*
0636  * This routine is called to create an in-core extent bmap update
0637  * item from the bui format structure which was logged on disk.
0638  * It allocates an in-core bui, copies the extents from the format
0639  * structure into it, and adds the bui to the AIL with the given
0640  * LSN.
0641  */
0642 STATIC int
0643 xlog_recover_bui_commit_pass2(
0644     struct xlog         *log,
0645     struct list_head        *buffer_list,
0646     struct xlog_recover_item    *item,
0647     xfs_lsn_t           lsn)
0648 {
0649     int             error;
0650     struct xfs_mount        *mp = log->l_mp;
0651     struct xfs_bui_log_item     *buip;
0652     struct xfs_bui_log_format   *bui_formatp;
0653 
0654     bui_formatp = item->ri_buf[0].i_addr;
0655 
0656     if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) {
0657         XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
0658         return -EFSCORRUPTED;
0659     }
0660     buip = xfs_bui_init(mp);
0661     error = xfs_bui_copy_format(&item->ri_buf[0], &buip->bui_format);
0662     if (error) {
0663         xfs_bui_item_free(buip);
0664         return error;
0665     }
0666     atomic_set(&buip->bui_next_extent, bui_formatp->bui_nextents);
0667     /*
0668      * Insert the intent into the AIL directly and drop one reference so
0669      * that finishing or canceling the work will drop the other.
0670      */
0671     xfs_trans_ail_insert(log->l_ailp, &buip->bui_item, lsn);
0672     xfs_bui_release(buip);
0673     return 0;
0674 }
0675 
0676 const struct xlog_recover_item_ops xlog_bui_item_ops = {
0677     .item_type      = XFS_LI_BUI,
0678     .commit_pass2       = xlog_recover_bui_commit_pass2,
0679 };
0680 
0681 /*
0682  * This routine is called when an BUD format structure is found in a committed
0683  * transaction in the log. Its purpose is to cancel the corresponding BUI if it
0684  * was still in the log. To do this it searches the AIL for the BUI with an id
0685  * equal to that in the BUD format structure. If we find it we drop the BUD
0686  * reference, which removes the BUI from the AIL and frees it.
0687  */
0688 STATIC int
0689 xlog_recover_bud_commit_pass2(
0690     struct xlog         *log,
0691     struct list_head        *buffer_list,
0692     struct xlog_recover_item    *item,
0693     xfs_lsn_t           lsn)
0694 {
0695     struct xfs_bud_log_format   *bud_formatp;
0696 
0697     bud_formatp = item->ri_buf[0].i_addr;
0698     if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) {
0699         XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
0700         return -EFSCORRUPTED;
0701     }
0702 
0703     xlog_recover_release_intent(log, XFS_LI_BUI, bud_formatp->bud_bui_id);
0704     return 0;
0705 }
0706 
0707 const struct xlog_recover_item_ops xlog_bud_item_ops = {
0708     .item_type      = XFS_LI_BUD,
0709     .commit_pass2       = xlog_recover_bud_commit_pass2,
0710 };