LCOV - code coverage report
Current view: top level - fs/xfs - xfs_bmap_item.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 236 275 85.8 %
Date: 2023-07-31 20:08:07 Functions: 28 29 96.6 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0+
       2             : /*
       3             :  * Copyright (C) 2016 Oracle.  All Rights Reserved.
       4             :  * Author: Darrick J. Wong <darrick.wong@oracle.com>
       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_defer.h"
      15             : #include "xfs_inode.h"
      16             : #include "xfs_trans.h"
      17             : #include "xfs_trans_priv.h"
      18             : #include "xfs_bmap_item.h"
      19             : #include "xfs_log.h"
      20             : #include "xfs_bmap.h"
      21             : #include "xfs_icache.h"
      22             : #include "xfs_bmap_btree.h"
      23             : #include "xfs_trans_space.h"
      24             : #include "xfs_error.h"
      25             : #include "xfs_log_priv.h"
      26             : #include "xfs_log_recover.h"
      27             : #include "xfs_ag.h"
      28             : 
      29             : struct kmem_cache       *xfs_bui_cache;
      30             : struct kmem_cache       *xfs_bud_cache;
      31             : 
      32             : static const struct xfs_item_ops xfs_bui_item_ops;
      33             : 
      34             : static inline struct xfs_bui_log_item *BUI_ITEM(struct xfs_log_item *lip)
      35             : {
      36             :         return container_of(lip, struct xfs_bui_log_item, bui_item);
      37             : }
      38             : 
      39             : STATIC void
      40    59256534 : xfs_bui_item_free(
      41             :         struct xfs_bui_log_item *buip)
      42             : {
      43    59256534 :         kmem_free(buip->bui_item.li_lv_shadow);
      44    59256535 :         kmem_cache_free(xfs_bui_cache, buip);
      45    59256520 : }
      46             : 
      47             : /*
      48             :  * Freeing the BUI requires that we remove it from the AIL if it has already
      49             :  * been placed there. However, the BUI may not yet have been placed in the AIL
      50             :  * when called by xfs_bui_release() from BUD processing due to the ordering of
      51             :  * committed vs unpin operations in bulk insert operations. Hence the reference
      52             :  * count to ensure only the last caller frees the BUI.
      53             :  */
      54             : STATIC void
      55   118475016 : xfs_bui_release(
      56             :         struct xfs_bui_log_item *buip)
      57             : {
      58   118475016 :         ASSERT(atomic_read(&buip->bui_refcount) > 0);
      59   236970208 :         if (!atomic_dec_and_test(&buip->bui_refcount))
      60             :                 return;
      61             : 
      62    59256534 :         xfs_trans_ail_delete(&buip->bui_item, 0);
      63    59256534 :         xfs_bui_item_free(buip);
      64             : }
      65             : 
      66             : 
      67             : STATIC void
      68    59253997 : xfs_bui_item_size(
      69             :         struct xfs_log_item     *lip,
      70             :         int                     *nvecs,
      71             :         int                     *nbytes)
      72             : {
      73    59253997 :         struct xfs_bui_log_item *buip = BUI_ITEM(lip);
      74             : 
      75    59253997 :         *nvecs += 1;
      76    59253997 :         *nbytes += xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents);
      77    59253997 : }
      78             : 
      79             : /*
      80             :  * This is called to fill in the vector of log iovecs for the
      81             :  * given bui log item. We use only 1 iovec, and we point that
      82             :  * at the bui_log_format structure embedded in the bui item.
      83             :  * It is at this point that we assert that all of the extent
      84             :  * slots in the bui item have been filled.
      85             :  */
      86             : STATIC void
      87    59254000 : xfs_bui_item_format(
      88             :         struct xfs_log_item     *lip,
      89             :         struct xfs_log_vec      *lv)
      90             : {
      91    59254000 :         struct xfs_bui_log_item *buip = BUI_ITEM(lip);
      92    59254000 :         struct xfs_log_iovec    *vecp = NULL;
      93             : 
      94    59254000 :         ASSERT(atomic_read(&buip->bui_next_extent) ==
      95             :                         buip->bui_format.bui_nextents);
      96             : 
      97    59254000 :         buip->bui_format.bui_type = XFS_LI_BUI;
      98    59254000 :         buip->bui_format.bui_size = 1;
      99             : 
     100    59254000 :         xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUI_FORMAT, &buip->bui_format,
     101    59254000 :                         xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents));
     102    59253997 : }
     103             : 
     104             : /*
     105             :  * The unpin operation is the last place an BUI is manipulated in the log. It is
     106             :  * either inserted in the AIL or aborted in the event of a log I/O error. In
     107             :  * either case, the BUI transaction has been successfully committed to make it
     108             :  * this far. Therefore, we expect whoever committed the BUI to either construct
     109             :  * and commit the BUD or drop the BUD's reference in the event of error. Simply
     110             :  * drop the log's BUI reference now that the log is done with it.
     111             :  */
     112             : STATIC void
     113    59253949 : xfs_bui_item_unpin(
     114             :         struct xfs_log_item     *lip,
     115             :         int                     remove)
     116             : {
     117    59253949 :         struct xfs_bui_log_item *buip = BUI_ITEM(lip);
     118             : 
     119    59253949 :         xfs_bui_release(buip);
     120    59253997 : }
     121             : 
     122             : /*
     123             :  * The BUI has been either committed or aborted if the transaction has been
     124             :  * cancelled. If the transaction was cancelled, an BUD isn't going to be
     125             :  * constructed and thus we free the BUI here directly.
     126             :  */
     127             : STATIC void
     128        2213 : xfs_bui_item_release(
     129             :         struct xfs_log_item     *lip)
     130             : {
     131        2213 :         xfs_bui_release(BUI_ITEM(lip));
     132        2213 : }
     133             : 
     134             : /*
     135             :  * Allocate and initialize an bui item with the given number of extents.
     136             :  */
     137             : STATIC struct xfs_bui_log_item *
     138    59256436 : xfs_bui_init(
     139             :         struct xfs_mount                *mp)
     140             : 
     141             : {
     142    59256436 :         struct xfs_bui_log_item         *buip;
     143             : 
     144    59256436 :         buip = kmem_cache_zalloc(xfs_bui_cache, GFP_KERNEL | __GFP_NOFAIL);
     145             : 
     146    59256452 :         xfs_log_item_init(mp, &buip->bui_item, XFS_LI_BUI, &xfs_bui_item_ops);
     147    59256474 :         buip->bui_format.bui_nextents = XFS_BUI_MAX_FAST_EXTENTS;
     148    59256474 :         buip->bui_format.bui_id = (uintptr_t)(void *)buip;
     149    59256474 :         atomic_set(&buip->bui_next_extent, 0);
     150    59256474 :         atomic_set(&buip->bui_refcount, 2);
     151             : 
     152    59256474 :         return buip;
     153             : }
     154             : 
     155             : static inline struct xfs_bud_log_item *BUD_ITEM(struct xfs_log_item *lip)
     156             : {
     157             :         return container_of(lip, struct xfs_bud_log_item, bud_item);
     158             : }
     159             : 
     160             : STATIC void
     161    59254027 : xfs_bud_item_size(
     162             :         struct xfs_log_item     *lip,
     163             :         int                     *nvecs,
     164             :         int                     *nbytes)
     165             : {
     166    59254027 :         *nvecs += 1;
     167    59254027 :         *nbytes += sizeof(struct xfs_bud_log_format);
     168    59254027 : }
     169             : 
     170             : /*
     171             :  * This is called to fill in the vector of log iovecs for the
     172             :  * given bud log item. We use only 1 iovec, and we point that
     173             :  * at the bud_log_format structure embedded in the bud item.
     174             :  * It is at this point that we assert that all of the extent
     175             :  * slots in the bud item have been filled.
     176             :  */
     177             : STATIC void
     178       33261 : xfs_bud_item_format(
     179             :         struct xfs_log_item     *lip,
     180             :         struct xfs_log_vec      *lv)
     181             : {
     182       33261 :         struct xfs_bud_log_item *budp = BUD_ITEM(lip);
     183       33261 :         struct xfs_log_iovec    *vecp = NULL;
     184             : 
     185       33261 :         budp->bud_format.bud_type = XFS_LI_BUD;
     186       33261 :         budp->bud_format.bud_size = 1;
     187             : 
     188       33261 :         xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUD_FORMAT, &budp->bud_format,
     189             :                         sizeof(struct xfs_bud_log_format));
     190       33261 : }
     191             : 
     192             : /*
     193             :  * The BUD is either committed or aborted if the transaction is cancelled. If
     194             :  * the transaction is cancelled, drop our reference to the BUI and free the
     195             :  * BUD.
     196             :  */
     197             : STATIC void
     198    59254076 : xfs_bud_item_release(
     199             :         struct xfs_log_item     *lip)
     200             : {
     201    59254076 :         struct xfs_bud_log_item *budp = BUD_ITEM(lip);
     202             : 
     203    59254076 :         xfs_bui_release(budp->bud_buip);
     204    59254078 :         kmem_free(budp->bud_item.li_lv_shadow);
     205    59254074 :         kmem_cache_free(xfs_bud_cache, budp);
     206    59254072 : }
     207             : 
     208             : static struct xfs_log_item *
     209    59253969 : xfs_bud_item_intent(
     210             :         struct xfs_log_item     *lip)
     211             : {
     212    59253969 :         return &BUD_ITEM(lip)->bud_buip->bui_item;
     213             : }
     214             : 
     215             : static const struct xfs_item_ops xfs_bud_item_ops = {
     216             :         .flags          = XFS_ITEM_RELEASE_WHEN_COMMITTED |
     217             :                           XFS_ITEM_INTENT_DONE,
     218             :         .iop_size       = xfs_bud_item_size,
     219             :         .iop_format     = xfs_bud_item_format,
     220             :         .iop_release    = xfs_bud_item_release,
     221             :         .iop_intent     = xfs_bud_item_intent,
     222             : };
     223             : 
     224             : static struct xfs_bud_log_item *
     225    59254060 : xfs_trans_get_bud(
     226             :         struct xfs_trans                *tp,
     227             :         struct xfs_bui_log_item         *buip)
     228             : {
     229    59254060 :         struct xfs_bud_log_item         *budp;
     230             : 
     231    59254060 :         budp = kmem_cache_zalloc(xfs_bud_cache, GFP_KERNEL | __GFP_NOFAIL);
     232    59254074 :         xfs_log_item_init(tp->t_mountp, &budp->bud_item, XFS_LI_BUD,
     233             :                           &xfs_bud_item_ops);
     234    59254074 :         budp->bud_buip = buip;
     235    59254074 :         budp->bud_format.bud_bui_id = buip->bui_format.bui_id;
     236             : 
     237    59254074 :         xfs_trans_add_item(tp, &budp->bud_item);
     238    59254072 :         return budp;
     239             : }
     240             : 
     241             : /*
     242             :  * Finish an bmap update and log it to the BUD. Note that the
     243             :  * transaction is marked dirty regardless of whether the bmap update
     244             :  * succeeds or fails to support the BUI/BUD lifecycle rules.
     245             :  */
     246             : static int
     247    59254017 : xfs_trans_log_finish_bmap_update(
     248             :         struct xfs_trans                *tp,
     249             :         struct xfs_bud_log_item         *budp,
     250             :         struct xfs_bmap_intent          *bi)
     251             : {
     252    59254017 :         int                             error;
     253             : 
     254    59254017 :         error = xfs_bmap_finish_one(tp, bi);
     255             : 
     256             :         /*
     257             :          * Mark the transaction dirty, even on error. This ensures the
     258             :          * transaction is aborted, which:
     259             :          *
     260             :          * 1.) releases the BUI and frees the BUD
     261             :          * 2.) shuts down the filesystem
     262             :          */
     263    59254014 :         tp->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE;
     264    59254014 :         set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags);
     265             : 
     266    59254017 :         return error;
     267             : }
     268             : 
     269             : /* Sort bmap intents by inode. */
     270             : static int
     271           0 : xfs_bmap_update_diff_items(
     272             :         void                            *priv,
     273             :         const struct list_head          *a,
     274             :         const struct list_head          *b)
     275             : {
     276           0 :         struct xfs_bmap_intent          *ba;
     277           0 :         struct xfs_bmap_intent          *bb;
     278             : 
     279           0 :         ba = container_of(a, struct xfs_bmap_intent, bi_list);
     280           0 :         bb = container_of(b, struct xfs_bmap_intent, bi_list);
     281           0 :         return ba->bi_owner->i_ino - bb->bi_owner->i_ino;
     282             : }
     283             : 
     284             : /* Log bmap updates in the intent item. */
     285             : STATIC void
     286    59253914 : xfs_bmap_update_log_item(
     287             :         struct xfs_trans                *tp,
     288             :         struct xfs_bui_log_item         *buip,
     289             :         struct xfs_bmap_intent          *bi)
     290             : {
     291    59253914 :         uint                            next_extent;
     292    59253914 :         struct xfs_map_extent           *map;
     293             : 
     294    59253914 :         tp->t_flags |= XFS_TRANS_DIRTY;
     295    59253914 :         set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags);
     296             : 
     297             :         /*
     298             :          * atomic_inc_return gives us the value after the increment;
     299             :          * we want to use it as an array index so we need to subtract 1 from
     300             :          * it.
     301             :          */
     302    59253923 :         next_extent = atomic_inc_return(&buip->bui_next_extent) - 1;
     303    59253925 :         ASSERT(next_extent < buip->bui_format.bui_nextents);
     304    59253925 :         map = &buip->bui_format.bui_extents[next_extent];
     305    59253925 :         map->me_owner = bi->bi_owner->i_ino;
     306    59253925 :         map->me_startblock = bi->bi_bmap.br_startblock;
     307    59253925 :         map->me_startoff = bi->bi_bmap.br_startoff;
     308    59253925 :         map->me_len = bi->bi_bmap.br_blockcount;
     309             : 
     310    59253925 :         switch (bi->bi_type) {
     311    59253925 :         case XFS_BMAP_MAP:
     312             :         case XFS_BMAP_UNMAP:
     313    59253925 :                 map->me_flags = bi->bi_type;
     314    59253925 :                 break;
     315           0 :         default:
     316           0 :                 ASSERT(0);
     317             :         }
     318    59253925 :         if (bi->bi_bmap.br_state == XFS_EXT_UNWRITTEN)
     319     2841807 :                 map->me_flags |= XFS_BMAP_EXTENT_UNWRITTEN;
     320    59253925 :         if (bi->bi_whichfork == XFS_ATTR_FORK)
     321      218466 :                 map->me_flags |= XFS_BMAP_EXTENT_ATTR_FORK;
     322    59253925 :         if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork))
     323           0 :                 map->me_flags |= XFS_BMAP_EXTENT_REALTIME;
     324    59253924 : }
     325             : 
     326             : static struct xfs_log_item *
     327    59253850 : xfs_bmap_update_create_intent(
     328             :         struct xfs_trans                *tp,
     329             :         struct list_head                *items,
     330             :         unsigned int                    count,
     331             :         bool                            sort)
     332             : {
     333    59253850 :         struct xfs_mount                *mp = tp->t_mountp;
     334    59253850 :         struct xfs_bui_log_item         *buip = xfs_bui_init(mp);
     335    59253858 :         struct xfs_bmap_intent          *bi;
     336             : 
     337    59253858 :         ASSERT(count == XFS_BUI_MAX_FAST_EXTENTS);
     338             : 
     339    59253858 :         xfs_trans_add_item(tp, &buip->bui_item);
     340    59253900 :         if (sort)
     341    59253907 :                 list_sort(mp, items, xfs_bmap_update_diff_items);
     342   118507823 :         list_for_each_entry(bi, items, bi_list)
     343    59253898 :                 xfs_bmap_update_log_item(tp, buip, bi);
     344    59253925 :         return &buip->bui_item;
     345             : }
     346             : 
     347             : /* Get an BUD so we can process all the deferred rmap updates. */
     348             : static struct xfs_log_item *
     349    59253694 : xfs_bmap_update_create_done(
     350             :         struct xfs_trans                *tp,
     351             :         struct xfs_log_item             *intent,
     352             :         unsigned int                    count)
     353             : {
     354    59253694 :         return &xfs_trans_get_bud(tp, BUI_ITEM(intent))->bud_item;
     355             : }
     356             : 
     357             : /* Take a passive ref to the AG containing the space we're mapping. */
     358             : void
     359    59254220 : xfs_bmap_update_get_group(
     360             :         struct xfs_mount        *mp,
     361             :         struct xfs_bmap_intent  *bi)
     362             : {
     363    59254220 :         xfs_agnumber_t          agno;
     364             : 
     365    59254220 :         if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork))
     366             :                 return;
     367             : 
     368    59254209 :         agno = XFS_FSB_TO_AGNO(mp, bi->bi_bmap.br_startblock);
     369             : 
     370             :         /*
     371             :          * Bump the intent count on behalf of the deferred rmap and refcount
     372             :          * intent items that that we can queue when we finish this bmap work.
     373             :          * This new intent item will bump the intent count before the bmap
     374             :          * intent drops the intent count, ensuring that the intent count
     375             :          * remains nonzero across the transaction roll.
     376             :          */
     377    59254209 :         bi->bi_pag = xfs_perag_intent_get(mp, agno);
     378             : }
     379             : 
     380             : /* Release a passive AG ref after finishing mapping work. */
     381             : static inline void
     382    59254257 : xfs_bmap_update_put_group(
     383             :         struct xfs_bmap_intent  *bi)
     384             : {
     385    59254257 :         if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork))
     386             :                 return;
     387             : 
     388    59254257 :         xfs_perag_intent_put(bi->bi_pag);
     389             : }
     390             : 
     391             : /* Process a deferred rmap update. */
     392             : STATIC int
     393    59253690 : xfs_bmap_update_finish_item(
     394             :         struct xfs_trans                *tp,
     395             :         struct xfs_log_item             *done,
     396             :         struct list_head                *item,
     397             :         struct xfs_btree_cur            **state)
     398             : {
     399    59253690 :         struct xfs_bmap_intent          *bi;
     400    59253690 :         int                             error;
     401             : 
     402    59253690 :         bi = container_of(item, struct xfs_bmap_intent, bi_list);
     403             : 
     404    59253690 :         error = xfs_trans_log_finish_bmap_update(tp, BUD_ITEM(done), bi);
     405    59253693 :         if (!error && bi->bi_bmap.br_blockcount > 0) {
     406           0 :                 ASSERT(bi->bi_type == XFS_BMAP_UNMAP);
     407           0 :                 return -EAGAIN;
     408             :         }
     409             : 
     410    59253693 :         xfs_bmap_update_put_group(bi);
     411    59253690 :         kmem_cache_free(xfs_bmap_intent_cache, bi);
     412    59253690 :         return error;
     413             : }
     414             : 
     415             : /* Abort all pending BUIs. */
     416             : STATIC void
     417         246 : xfs_bmap_update_abort_intent(
     418             :         struct xfs_log_item             *intent)
     419             : {
     420         246 :         xfs_bui_release(BUI_ITEM(intent));
     421         246 : }
     422             : 
     423             : /* Cancel a deferred bmap update. */
     424             : STATIC void
     425         246 : xfs_bmap_update_cancel_item(
     426             :         struct list_head                *item)
     427             : {
     428         246 :         struct xfs_bmap_intent          *bi;
     429             : 
     430         246 :         bi = container_of(item, struct xfs_bmap_intent, bi_list);
     431             : 
     432         246 :         xfs_bmap_update_put_group(bi);
     433         246 :         kmem_cache_free(xfs_bmap_intent_cache, bi);
     434         246 : }
     435             : 
     436             : const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
     437             :         .max_items      = XFS_BUI_MAX_FAST_EXTENTS,
     438             :         .create_intent  = xfs_bmap_update_create_intent,
     439             :         .abort_intent   = xfs_bmap_update_abort_intent,
     440             :         .create_done    = xfs_bmap_update_create_done,
     441             :         .finish_item    = xfs_bmap_update_finish_item,
     442             :         .cancel_item    = xfs_bmap_update_cancel_item,
     443             : };
     444             : 
     445             : /* Is this recovered BUI ok? */
     446             : static inline bool
     447         321 : xfs_bui_validate(
     448             :         struct xfs_mount                *mp,
     449             :         struct xfs_bui_log_item         *buip)
     450             : {
     451         321 :         struct xfs_map_extent           *map;
     452             : 
     453             :         /* Only one mapping operation per BUI... */
     454         321 :         if (buip->bui_format.bui_nextents != XFS_BUI_MAX_FAST_EXTENTS)
     455             :                 return false;
     456             : 
     457         321 :         map = &buip->bui_format.bui_extents[0];
     458             : 
     459         321 :         if (map->me_flags & ~XFS_BMAP_EXTENT_FLAGS)
     460             :                 return false;
     461             : 
     462         321 :         switch (map->me_flags & XFS_BMAP_EXTENT_TYPE_MASK) {
     463             :         case XFS_BMAP_MAP:
     464             :         case XFS_BMAP_UNMAP:
     465         321 :                 break;
     466             :         default:
     467             :                 return false;
     468             :         }
     469             : 
     470         321 :         if (!xfs_verify_ino(mp, map->me_owner))
     471             :                 return false;
     472             : 
     473         321 :         if (!xfs_verify_fileext(mp, map->me_startoff, map->me_len))
     474             :                 return false;
     475             : 
     476         321 :         if (map->me_flags & XFS_BMAP_EXTENT_REALTIME)
     477           0 :                 return xfs_verify_rtext(mp, map->me_startblock, map->me_len);
     478             : 
     479         321 :         return xfs_verify_fsbext(mp, map->me_startblock, map->me_len);
     480             : }
     481             : 
     482             : /*
     483             :  * Process a bmap update intent item that was recovered from the log.
     484             :  * We need to update some inode's bmbt.
     485             :  */
     486             : STATIC int
     487         321 : xfs_bui_item_recover(
     488             :         struct xfs_log_item             *lip,
     489             :         struct list_head                *capture_list)
     490             : {
     491         321 :         struct xfs_bmap_intent          fake = { };
     492         321 :         struct xfs_bui_log_item         *buip = BUI_ITEM(lip);
     493         321 :         struct xfs_trans                *tp;
     494         321 :         struct xfs_inode                *ip = NULL;
     495         321 :         struct xfs_mount                *mp = lip->li_log->l_mp;
     496         321 :         struct xfs_map_extent           *map;
     497         321 :         struct xfs_bud_log_item         *budp;
     498         321 :         int                             iext_delta;
     499         321 :         int                             error = 0;
     500             : 
     501         321 :         if (!xfs_bui_validate(mp, buip)) {
     502           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     503             :                                 &buip->bui_format, sizeof(buip->bui_format));
     504           0 :                 return -EFSCORRUPTED;
     505             :         }
     506             : 
     507         321 :         map = &buip->bui_format.bui_extents[0];
     508         321 :         fake.bi_whichfork = (map->me_flags & XFS_BMAP_EXTENT_ATTR_FORK) ?
     509         321 :                         XFS_ATTR_FORK : XFS_DATA_FORK;
     510         321 :         fake.bi_type = map->me_flags & XFS_BMAP_EXTENT_TYPE_MASK;
     511             : 
     512         321 :         error = xlog_recover_iget(mp, map->me_owner, &ip);
     513         321 :         if (error)
     514             :                 return error;
     515             : 
     516             :         /* Allocate transaction and do the work. */
     517         321 :         error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
     518         321 :                         XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
     519         321 :         if (error)
     520           0 :                 goto err_rele;
     521             : 
     522         321 :         budp = xfs_trans_get_bud(tp, buip);
     523         321 :         xfs_ilock(ip, XFS_ILOCK_EXCL);
     524         321 :         xfs_trans_ijoin(tp, ip, 0);
     525             : 
     526         321 :         if (!!(map->me_flags & XFS_BMAP_EXTENT_REALTIME) !=
     527         321 :             xfs_ifork_is_realtime(ip, fake.bi_whichfork)) {
     528           0 :                 error = -EFSCORRUPTED;
     529           0 :                 goto err_cancel;
     530             :         }
     531             : 
     532         321 :         if (fake.bi_type == XFS_BMAP_MAP)
     533             :                 iext_delta = XFS_IEXT_ADD_NOSPLIT_CNT;
     534             :         else
     535             :                 iext_delta = XFS_IEXT_PUNCH_HOLE_CNT;
     536             : 
     537         321 :         error = xfs_iext_count_may_overflow(ip, fake.bi_whichfork, iext_delta);
     538         321 :         if (error == -EFBIG)
     539           0 :                 error = xfs_iext_count_upgrade(tp, ip, iext_delta);
     540         321 :         if (error)
     541           0 :                 goto err_cancel;
     542             : 
     543         321 :         fake.bi_owner = ip;
     544         321 :         fake.bi_bmap.br_startblock = map->me_startblock;
     545         321 :         fake.bi_bmap.br_startoff = map->me_startoff;
     546         321 :         fake.bi_bmap.br_blockcount = map->me_len;
     547         321 :         fake.bi_bmap.br_state = (map->me_flags & XFS_BMAP_EXTENT_UNWRITTEN) ?
     548         321 :                         XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
     549             : 
     550         321 :         xfs_bmap_update_get_group(mp, &fake);
     551         321 :         error = xfs_trans_log_finish_bmap_update(tp, budp, &fake);
     552         321 :         if (error == -EFSCORRUPTED)
     553           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, map,
     554             :                                 sizeof(*map));
     555         321 :         xfs_bmap_update_put_group(&fake);
     556         321 :         if (error)
     557           0 :                 goto err_cancel;
     558             : 
     559         321 :         if (fake.bi_bmap.br_blockcount > 0) {
     560           0 :                 ASSERT(fake.bi_type == XFS_BMAP_UNMAP);
     561           0 :                 xfs_bmap_unmap_extent(tp, fake.bi_owner, fake.bi_whichfork,
     562             :                                 &fake.bi_bmap);
     563             :         }
     564             : 
     565             :         /*
     566             :          * Commit transaction, which frees the transaction and saves the inode
     567             :          * for later replay activities.
     568             :          */
     569         321 :         error = xfs_defer_ops_capture_and_commit(tp, capture_list);
     570         321 :         if (error)
     571           0 :                 goto err_unlock;
     572             : 
     573         321 :         xfs_iunlock(ip, XFS_ILOCK_EXCL);
     574         321 :         xfs_irele(ip);
     575         321 :         return 0;
     576             : 
     577           0 : err_cancel:
     578           0 :         xfs_trans_cancel(tp);
     579           0 : err_unlock:
     580           0 :         xfs_iunlock(ip, XFS_ILOCK_EXCL);
     581           0 : err_rele:
     582           0 :         xfs_irele(ip);
     583           0 :         return error;
     584             : }
     585             : 
     586             : STATIC bool
     587        2266 : xfs_bui_item_match(
     588             :         struct xfs_log_item     *lip,
     589             :         uint64_t                intent_id)
     590             : {
     591        2266 :         return BUI_ITEM(lip)->bui_format.bui_id == intent_id;
     592             : }
     593             : 
     594             : /* Relog an intent item to push the log tail forward. */
     595             : static struct xfs_log_item *
     596          56 : xfs_bui_item_relog(
     597             :         struct xfs_log_item             *intent,
     598             :         struct xfs_trans                *tp)
     599             : {
     600          56 :         struct xfs_bud_log_item         *budp;
     601          56 :         struct xfs_bui_log_item         *buip;
     602          56 :         struct xfs_map_extent           *map;
     603          56 :         unsigned int                    count;
     604             : 
     605          56 :         count = BUI_ITEM(intent)->bui_format.bui_nextents;
     606          56 :         map = BUI_ITEM(intent)->bui_format.bui_extents;
     607             : 
     608          56 :         tp->t_flags |= XFS_TRANS_DIRTY;
     609          56 :         budp = xfs_trans_get_bud(tp, BUI_ITEM(intent));
     610          56 :         set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags);
     611             : 
     612          56 :         buip = xfs_bui_init(tp->t_mountp);
     613         112 :         memcpy(buip->bui_format.bui_extents, map, count * sizeof(*map));
     614          56 :         atomic_set(&buip->bui_next_extent, count);
     615          56 :         xfs_trans_add_item(tp, &buip->bui_item);
     616          56 :         set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags);
     617          56 :         return &buip->bui_item;
     618             : }
     619             : 
     620             : static const struct xfs_item_ops xfs_bui_item_ops = {
     621             :         .flags          = XFS_ITEM_INTENT,
     622             :         .iop_size       = xfs_bui_item_size,
     623             :         .iop_format     = xfs_bui_item_format,
     624             :         .iop_unpin      = xfs_bui_item_unpin,
     625             :         .iop_release    = xfs_bui_item_release,
     626             :         .iop_recover    = xfs_bui_item_recover,
     627             :         .iop_match      = xfs_bui_item_match,
     628             :         .iop_relog      = xfs_bui_item_relog,
     629             : };
     630             : 
     631             : static inline void
     632        2533 : xfs_bui_copy_format(
     633             :         struct xfs_bui_log_format       *dst,
     634             :         const struct xfs_bui_log_format *src)
     635             : {
     636        2533 :         unsigned int                    i;
     637             : 
     638        5066 :         memcpy(dst, src, offsetof(struct xfs_bui_log_format, bui_extents));
     639             : 
     640        5066 :         for (i = 0; i < src->bui_nextents; i++)
     641        5066 :                 memcpy(&dst->bui_extents[i], &src->bui_extents[i],
     642             :                                 sizeof(struct xfs_map_extent));
     643        2533 : }
     644             : 
     645             : /*
     646             :  * This routine is called to create an in-core extent bmap update
     647             :  * item from the bui format structure which was logged on disk.
     648             :  * It allocates an in-core bui, copies the extents from the format
     649             :  * structure into it, and adds the bui to the AIL with the given
     650             :  * LSN.
     651             :  */
     652             : STATIC int
     653        2533 : xlog_recover_bui_commit_pass2(
     654             :         struct xlog                     *log,
     655             :         struct list_head                *buffer_list,
     656             :         struct xlog_recover_item        *item,
     657             :         xfs_lsn_t                       lsn)
     658             : {
     659        2533 :         struct xfs_mount                *mp = log->l_mp;
     660        2533 :         struct xfs_bui_log_item         *buip;
     661        2533 :         struct xfs_bui_log_format       *bui_formatp;
     662        2533 :         size_t                          len;
     663             : 
     664        2533 :         bui_formatp = item->ri_buf[0].i_addr;
     665             : 
     666        2533 :         if (item->ri_buf[0].i_len < xfs_bui_log_format_sizeof(0)) {
     667           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     668             :                                 item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
     669           0 :                 return -EFSCORRUPTED;
     670             :         }
     671             : 
     672        2533 :         if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) {
     673           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     674             :                                 item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
     675           0 :                 return -EFSCORRUPTED;
     676             :         }
     677             : 
     678        2533 :         len = xfs_bui_log_format_sizeof(bui_formatp->bui_nextents);
     679        2533 :         if (item->ri_buf[0].i_len != len) {
     680           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     681             :                                 item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
     682           0 :                 return -EFSCORRUPTED;
     683             :         }
     684             : 
     685        2533 :         buip = xfs_bui_init(mp);
     686        2533 :         xfs_bui_copy_format(&buip->bui_format, bui_formatp);
     687        2533 :         atomic_set(&buip->bui_next_extent, bui_formatp->bui_nextents);
     688             :         /*
     689             :          * Insert the intent into the AIL directly and drop one reference so
     690             :          * that finishing or canceling the work will drop the other.
     691             :          */
     692        2533 :         xfs_trans_ail_insert(log->l_ailp, &buip->bui_item, lsn);
     693        2533 :         xfs_bui_release(buip);
     694        2533 :         return 0;
     695             : }
     696             : 
     697             : const struct xlog_recover_item_ops xlog_bui_item_ops = {
     698             :         .item_type              = XFS_LI_BUI,
     699             :         .commit_pass2           = xlog_recover_bui_commit_pass2,
     700             : };
     701             : 
     702             : /*
     703             :  * This routine is called when an BUD format structure is found in a committed
     704             :  * transaction in the log. Its purpose is to cancel the corresponding BUI if it
     705             :  * was still in the log. To do this it searches the AIL for the BUI with an id
     706             :  * equal to that in the BUD format structure. If we find it we drop the BUD
     707             :  * reference, which removes the BUI from the AIL and frees it.
     708             :  */
     709             : STATIC int
     710        2222 : xlog_recover_bud_commit_pass2(
     711             :         struct xlog                     *log,
     712             :         struct list_head                *buffer_list,
     713             :         struct xlog_recover_item        *item,
     714             :         xfs_lsn_t                       lsn)
     715             : {
     716        2222 :         struct xfs_bud_log_format       *bud_formatp;
     717             : 
     718        2222 :         bud_formatp = item->ri_buf[0].i_addr;
     719        2222 :         if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) {
     720           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
     721             :                                 item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
     722           0 :                 return -EFSCORRUPTED;
     723             :         }
     724             : 
     725        2222 :         xlog_recover_release_intent(log, XFS_LI_BUI, bud_formatp->bud_bui_id);
     726        2222 :         return 0;
     727             : }
     728             : 
     729             : const struct xlog_recover_item_ops xlog_bud_item_ops = {
     730             :         .item_type              = XFS_LI_BUD,
     731             :         .commit_pass2           = xlog_recover_bud_commit_pass2,
     732             : };

Generated by: LCOV version 1.14