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-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 233 269 86.6 %
Date: 2023-07-31 20:08:17 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    54814146 : xfs_bui_item_free(
      41             :         struct xfs_bui_log_item *buip)
      42             : {
      43    54814146 :         kmem_free(buip->bui_item.li_lv_shadow);
      44    54814146 :         kmem_cache_free(xfs_bui_cache, buip);
      45    54814145 : }
      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   109587994 : xfs_bui_release(
      56             :         struct xfs_bui_log_item *buip)
      57             : {
      58   109587994 :         ASSERT(atomic_read(&buip->bui_refcount) > 0);
      59   219205117 :         if (!atomic_dec_and_test(&buip->bui_refcount))
      60             :                 return;
      61             : 
      62    54814145 :         xfs_trans_ail_delete(&buip->bui_item, 0);
      63    54814146 :         xfs_bui_item_free(buip);
      64             : }
      65             : 
      66             : 
      67             : STATIC void
      68    54811619 : xfs_bui_item_size(
      69             :         struct xfs_log_item     *lip,
      70             :         int                     *nvecs,
      71             :         int                     *nbytes)
      72             : {
      73    54811619 :         struct xfs_bui_log_item *buip = BUI_ITEM(lip);
      74             : 
      75    54811619 :         *nvecs += 1;
      76    54811619 :         *nbytes += xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents);
      77    54811619 : }
      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    54811619 : xfs_bui_item_format(
      88             :         struct xfs_log_item     *lip,
      89             :         struct xfs_log_vec      *lv)
      90             : {
      91    54811619 :         struct xfs_bui_log_item *buip = BUI_ITEM(lip);
      92    54811619 :         struct xfs_log_iovec    *vecp = NULL;
      93             : 
      94    54811619 :         ASSERT(atomic_read(&buip->bui_next_extent) ==
      95             :                         buip->bui_format.bui_nextents);
      96             : 
      97    54811619 :         buip->bui_format.bui_type = XFS_LI_BUI;
      98    54811619 :         buip->bui_format.bui_size = 1;
      99             : 
     100    54811619 :         xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUI_FORMAT, &buip->bui_format,
     101    54811619 :                         xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents));
     102    54811619 : }
     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    54811593 : xfs_bui_item_unpin(
     114             :         struct xfs_log_item     *lip,
     115             :         int                     remove)
     116             : {
     117    54811593 :         struct xfs_bui_log_item *buip = BUI_ITEM(lip);
     118             : 
     119    54811593 :         xfs_bui_release(buip);
     120    54811618 : }
     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        2175 : xfs_bui_item_release(
     129             :         struct xfs_log_item     *lip)
     130             : {
     131        2175 :         xfs_bui_release(BUI_ITEM(lip));
     132        2175 : }
     133             : 
     134             : /*
     135             :  * Allocate and initialize an bui item with the given number of extents.
     136             :  */
     137             : STATIC struct xfs_bui_log_item *
     138    54814135 : xfs_bui_init(
     139             :         struct xfs_mount                *mp)
     140             : 
     141             : {
     142    54814135 :         struct xfs_bui_log_item         *buip;
     143             : 
     144    54814135 :         buip = kmem_cache_zalloc(xfs_bui_cache, GFP_KERNEL | __GFP_NOFAIL);
     145             : 
     146    54814135 :         xfs_log_item_init(mp, &buip->bui_item, XFS_LI_BUI, &xfs_bui_item_ops);
     147    54814136 :         buip->bui_format.bui_nextents = XFS_BUI_MAX_FAST_EXTENTS;
     148    54814136 :         buip->bui_format.bui_id = (uintptr_t)(void *)buip;
     149    54814136 :         atomic_set(&buip->bui_next_extent, 0);
     150    54814136 :         atomic_set(&buip->bui_refcount, 2);
     151             : 
     152    54814136 :         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    54811706 : xfs_bud_item_size(
     162             :         struct xfs_log_item     *lip,
     163             :         int                     *nvecs,
     164             :         int                     *nbytes)
     165             : {
     166    54811706 :         *nvecs += 1;
     167    54811706 :         *nbytes += sizeof(struct xfs_bud_log_format);
     168    54811706 : }
     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        6503 : xfs_bud_item_format(
     179             :         struct xfs_log_item     *lip,
     180             :         struct xfs_log_vec      *lv)
     181             : {
     182        6503 :         struct xfs_bud_log_item *budp = BUD_ITEM(lip);
     183        6503 :         struct xfs_log_iovec    *vecp = NULL;
     184             : 
     185        6503 :         budp->bud_format.bud_type = XFS_LI_BUD;
     186        6503 :         budp->bud_format.bud_size = 1;
     187             : 
     188        6503 :         xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUD_FORMAT, &budp->bud_format,
     189             :                         sizeof(struct xfs_bud_log_format));
     190        6503 : }
     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    54811754 : xfs_bud_item_release(
     199             :         struct xfs_log_item     *lip)
     200             : {
     201    54811754 :         struct xfs_bud_log_item *budp = BUD_ITEM(lip);
     202             : 
     203    54811754 :         xfs_bui_release(budp->bud_buip);
     204    54811754 :         kmem_free(budp->bud_item.li_lv_shadow);
     205    54811754 :         kmem_cache_free(xfs_bud_cache, budp);
     206    54811754 : }
     207             : 
     208             : static struct xfs_log_item *
     209    54811680 : xfs_bud_item_intent(
     210             :         struct xfs_log_item     *lip)
     211             : {
     212    54811680 :         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    54811741 : xfs_trans_get_bud(
     226             :         struct xfs_trans                *tp,
     227             :         struct xfs_bui_log_item         *buip)
     228             : {
     229    54811741 :         struct xfs_bud_log_item         *budp;
     230             : 
     231    54811741 :         budp = kmem_cache_zalloc(xfs_bud_cache, GFP_KERNEL | __GFP_NOFAIL);
     232    54811751 :         xfs_log_item_init(tp->t_mountp, &budp->bud_item, XFS_LI_BUD,
     233             :                           &xfs_bud_item_ops);
     234    54811750 :         budp->bud_buip = buip;
     235    54811750 :         budp->bud_format.bud_bui_id = buip->bui_format.bui_id;
     236             : 
     237    54811750 :         xfs_trans_add_item(tp, &budp->bud_item);
     238    54811751 :         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    54811725 : 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    54811725 :         int                             error;
     253             : 
     254    54811725 :         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    54811723 :         tp->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE;
     264    54811723 :         set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags);
     265             : 
     266    54811722 :         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             : /* Set the map extent flags for this mapping. */
     285             : static void
     286    54811591 : xfs_trans_set_bmap_flags(
     287             :         struct xfs_map_extent           *map,
     288             :         enum xfs_bmap_intent_type       type,
     289             :         int                             whichfork,
     290             :         xfs_exntst_t                    state)
     291             : {
     292    54811591 :         map->me_flags = 0;
     293    54811591 :         switch (type) {
     294    54811591 :         case XFS_BMAP_MAP:
     295             :         case XFS_BMAP_UNMAP:
     296    54811591 :                 map->me_flags = type;
     297    54811591 :                 break;
     298           0 :         default:
     299           0 :                 ASSERT(0);
     300             :         }
     301    54811591 :         if (state == XFS_EXT_UNWRITTEN)
     302     1964269 :                 map->me_flags |= XFS_BMAP_EXTENT_UNWRITTEN;
     303    54811591 :         if (whichfork == XFS_ATTR_FORK)
     304           0 :                 map->me_flags |= XFS_BMAP_EXTENT_ATTR_FORK;
     305    54811591 : }
     306             : 
     307             : /* Log bmap updates in the intent item. */
     308             : STATIC void
     309    54811582 : xfs_bmap_update_log_item(
     310             :         struct xfs_trans                *tp,
     311             :         struct xfs_bui_log_item         *buip,
     312             :         struct xfs_bmap_intent          *bi)
     313             : {
     314    54811582 :         uint                            next_extent;
     315    54811582 :         struct xfs_map_extent           *map;
     316             : 
     317    54811582 :         tp->t_flags |= XFS_TRANS_DIRTY;
     318    54811582 :         set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags);
     319             : 
     320             :         /*
     321             :          * atomic_inc_return gives us the value after the increment;
     322             :          * we want to use it as an array index so we need to subtract 1 from
     323             :          * it.
     324             :          */
     325    54811590 :         next_extent = atomic_inc_return(&buip->bui_next_extent) - 1;
     326    54811592 :         ASSERT(next_extent < buip->bui_format.bui_nextents);
     327    54811592 :         map = &buip->bui_format.bui_extents[next_extent];
     328    54811592 :         map->me_owner = bi->bi_owner->i_ino;
     329    54811592 :         map->me_startblock = bi->bi_bmap.br_startblock;
     330    54811592 :         map->me_startoff = bi->bi_bmap.br_startoff;
     331    54811592 :         map->me_len = bi->bi_bmap.br_blockcount;
     332    54811592 :         xfs_trans_set_bmap_flags(map, bi->bi_type, bi->bi_whichfork,
     333             :                         bi->bi_bmap.br_state);
     334    54811590 : }
     335             : 
     336             : static struct xfs_log_item *
     337    54811575 : xfs_bmap_update_create_intent(
     338             :         struct xfs_trans                *tp,
     339             :         struct list_head                *items,
     340             :         unsigned int                    count,
     341             :         bool                            sort)
     342             : {
     343    54811575 :         struct xfs_mount                *mp = tp->t_mountp;
     344    54811575 :         struct xfs_bui_log_item         *buip = xfs_bui_init(mp);
     345    54811582 :         struct xfs_bmap_intent          *bi;
     346             : 
     347    54811582 :         ASSERT(count == XFS_BUI_MAX_FAST_EXTENTS);
     348             : 
     349    54811582 :         xfs_trans_add_item(tp, &buip->bui_item);
     350    54811586 :         if (sort)
     351    54811587 :                 list_sort(mp, items, xfs_bmap_update_diff_items);
     352   109623176 :         list_for_each_entry(bi, items, bi_list)
     353    54811584 :                 xfs_bmap_update_log_item(tp, buip, bi);
     354    54811592 :         return &buip->bui_item;
     355             : }
     356             : 
     357             : /* Get an BUD so we can process all the deferred rmap updates. */
     358             : static struct xfs_log_item *
     359    54811368 : xfs_bmap_update_create_done(
     360             :         struct xfs_trans                *tp,
     361             :         struct xfs_log_item             *intent,
     362             :         unsigned int                    count)
     363             : {
     364    54811368 :         return &xfs_trans_get_bud(tp, BUI_ITEM(intent))->bud_item;
     365             : }
     366             : 
     367             : /* Take a passive ref to the AG containing the space we're mapping. */
     368             : void
     369    54811932 : xfs_bmap_update_get_group(
     370             :         struct xfs_mount        *mp,
     371             :         struct xfs_bmap_intent  *bi)
     372             : {
     373    54811932 :         xfs_agnumber_t          agno;
     374             : 
     375    54811932 :         agno = XFS_FSB_TO_AGNO(mp, bi->bi_bmap.br_startblock);
     376             : 
     377             :         /*
     378             :          * Bump the intent count on behalf of the deferred rmap and refcount
     379             :          * intent items that that we can queue when we finish this bmap work.
     380             :          * This new intent item will bump the intent count before the bmap
     381             :          * intent drops the intent count, ensuring that the intent count
     382             :          * remains nonzero across the transaction roll.
     383             :          */
     384    54811932 :         bi->bi_pag = xfs_perag_intent_get(mp, agno);
     385    54811939 : }
     386             : 
     387             : /* Release a passive AG ref after finishing mapping work. */
     388             : static inline void
     389             : xfs_bmap_update_put_group(
     390             :         struct xfs_bmap_intent  *bi)
     391             : {
     392    54811939 :         xfs_perag_intent_put(bi->bi_pag);
     393             : }
     394             : 
     395             : /* Process a deferred rmap update. */
     396             : STATIC int
     397    54811373 : xfs_bmap_update_finish_item(
     398             :         struct xfs_trans                *tp,
     399             :         struct xfs_log_item             *done,
     400             :         struct list_head                *item,
     401             :         struct xfs_btree_cur            **state)
     402             : {
     403    54811373 :         struct xfs_bmap_intent          *bi;
     404    54811373 :         int                             error;
     405             : 
     406    54811373 :         bi = container_of(item, struct xfs_bmap_intent, bi_list);
     407             : 
     408    54811373 :         error = xfs_trans_log_finish_bmap_update(tp, BUD_ITEM(done), bi);
     409    54811368 :         if (!error && bi->bi_bmap.br_blockcount > 0) {
     410           0 :                 ASSERT(bi->bi_type == XFS_BMAP_UNMAP);
     411           0 :                 return -EAGAIN;
     412             :         }
     413             : 
     414    54811368 :         xfs_bmap_update_put_group(bi);
     415    54811369 :         kmem_cache_free(xfs_bmap_intent_cache, bi);
     416    54811369 :         return error;
     417             : }
     418             : 
     419             : /* Abort all pending BUIs. */
     420             : STATIC void
     421         219 : xfs_bmap_update_abort_intent(
     422             :         struct xfs_log_item             *intent)
     423             : {
     424         219 :         xfs_bui_release(BUI_ITEM(intent));
     425         219 : }
     426             : 
     427             : /* Cancel a deferred bmap update. */
     428             : STATIC void
     429         219 : xfs_bmap_update_cancel_item(
     430             :         struct list_head                *item)
     431             : {
     432         219 :         struct xfs_bmap_intent          *bi;
     433             : 
     434         219 :         bi = container_of(item, struct xfs_bmap_intent, bi_list);
     435             : 
     436         219 :         xfs_bmap_update_put_group(bi);
     437         219 :         kmem_cache_free(xfs_bmap_intent_cache, bi);
     438         219 : }
     439             : 
     440             : const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
     441             :         .max_items      = XFS_BUI_MAX_FAST_EXTENTS,
     442             :         .create_intent  = xfs_bmap_update_create_intent,
     443             :         .abort_intent   = xfs_bmap_update_abort_intent,
     444             :         .create_done    = xfs_bmap_update_create_done,
     445             :         .finish_item    = xfs_bmap_update_finish_item,
     446             :         .cancel_item    = xfs_bmap_update_cancel_item,
     447             : };
     448             : 
     449             : /* Is this recovered BUI ok? */
     450             : static inline bool
     451         352 : xfs_bui_validate(
     452             :         struct xfs_mount                *mp,
     453             :         struct xfs_bui_log_item         *buip)
     454             : {
     455         352 :         struct xfs_map_extent           *map;
     456             : 
     457             :         /* Only one mapping operation per BUI... */
     458         352 :         if (buip->bui_format.bui_nextents != XFS_BUI_MAX_FAST_EXTENTS)
     459             :                 return false;
     460             : 
     461         352 :         map = &buip->bui_format.bui_extents[0];
     462             : 
     463         352 :         if (map->me_flags & ~XFS_BMAP_EXTENT_FLAGS)
     464             :                 return false;
     465             : 
     466         352 :         switch (map->me_flags & XFS_BMAP_EXTENT_TYPE_MASK) {
     467             :         case XFS_BMAP_MAP:
     468             :         case XFS_BMAP_UNMAP:
     469         352 :                 break;
     470             :         default:
     471             :                 return false;
     472             :         }
     473             : 
     474         352 :         if (!xfs_verify_ino(mp, map->me_owner))
     475             :                 return false;
     476             : 
     477         352 :         if (!xfs_verify_fileext(mp, map->me_startoff, map->me_len))
     478             :                 return false;
     479             : 
     480         352 :         return xfs_verify_fsbext(mp, map->me_startblock, map->me_len);
     481             : }
     482             : 
     483             : /*
     484             :  * Process a bmap update intent item that was recovered from the log.
     485             :  * We need to update some inode's bmbt.
     486             :  */
     487             : STATIC int
     488         352 : xfs_bui_item_recover(
     489             :         struct xfs_log_item             *lip,
     490             :         struct list_head                *capture_list)
     491             : {
     492         352 :         struct xfs_bmap_intent          fake = { };
     493         352 :         struct xfs_bui_log_item         *buip = BUI_ITEM(lip);
     494         352 :         struct xfs_trans                *tp;
     495         352 :         struct xfs_inode                *ip = NULL;
     496         352 :         struct xfs_mount                *mp = lip->li_log->l_mp;
     497         352 :         struct xfs_map_extent           *map;
     498         352 :         struct xfs_bud_log_item         *budp;
     499         352 :         int                             iext_delta;
     500         352 :         int                             error = 0;
     501             : 
     502         352 :         if (!xfs_bui_validate(mp, buip)) {
     503           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     504             :                                 &buip->bui_format, sizeof(buip->bui_format));
     505           0 :                 return -EFSCORRUPTED;
     506             :         }
     507             : 
     508         352 :         map = &buip->bui_format.bui_extents[0];
     509         352 :         fake.bi_whichfork = (map->me_flags & XFS_BMAP_EXTENT_ATTR_FORK) ?
     510         352 :                         XFS_ATTR_FORK : XFS_DATA_FORK;
     511         352 :         fake.bi_type = map->me_flags & XFS_BMAP_EXTENT_TYPE_MASK;
     512             : 
     513         352 :         error = xlog_recover_iget(mp, map->me_owner, &ip);
     514         352 :         if (error)
     515             :                 return error;
     516             : 
     517             :         /* Allocate transaction and do the work. */
     518         352 :         error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
     519         352 :                         XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
     520         352 :         if (error)
     521           0 :                 goto err_rele;
     522             : 
     523         352 :         budp = xfs_trans_get_bud(tp, buip);
     524         352 :         xfs_ilock(ip, XFS_ILOCK_EXCL);
     525         352 :         xfs_trans_ijoin(tp, ip, 0);
     526             : 
     527         352 :         if (fake.bi_type == XFS_BMAP_MAP)
     528             :                 iext_delta = XFS_IEXT_ADD_NOSPLIT_CNT;
     529             :         else
     530             :                 iext_delta = XFS_IEXT_PUNCH_HOLE_CNT;
     531             : 
     532         352 :         error = xfs_iext_count_may_overflow(ip, fake.bi_whichfork, iext_delta);
     533         352 :         if (error == -EFBIG)
     534           0 :                 error = xfs_iext_count_upgrade(tp, ip, iext_delta);
     535         352 :         if (error)
     536           0 :                 goto err_cancel;
     537             : 
     538         352 :         fake.bi_owner = ip;
     539         352 :         fake.bi_bmap.br_startblock = map->me_startblock;
     540         352 :         fake.bi_bmap.br_startoff = map->me_startoff;
     541         352 :         fake.bi_bmap.br_blockcount = map->me_len;
     542         352 :         fake.bi_bmap.br_state = (map->me_flags & XFS_BMAP_EXTENT_UNWRITTEN) ?
     543         352 :                         XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
     544             : 
     545         352 :         xfs_bmap_update_get_group(mp, &fake);
     546         352 :         error = xfs_trans_log_finish_bmap_update(tp, budp, &fake);
     547         352 :         if (error == -EFSCORRUPTED)
     548           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, map,
     549             :                                 sizeof(*map));
     550         352 :         xfs_bmap_update_put_group(&fake);
     551         352 :         if (error)
     552           0 :                 goto err_cancel;
     553             : 
     554         352 :         if (fake.bi_bmap.br_blockcount > 0) {
     555           0 :                 ASSERT(fake.bi_type == XFS_BMAP_UNMAP);
     556           0 :                 xfs_bmap_unmap_extent(tp, ip, &fake.bi_bmap);
     557             :         }
     558             : 
     559             :         /*
     560             :          * Commit transaction, which frees the transaction and saves the inode
     561             :          * for later replay activities.
     562             :          */
     563         352 :         error = xfs_defer_ops_capture_and_commit(tp, capture_list);
     564         352 :         if (error)
     565           0 :                 goto err_unlock;
     566             : 
     567         352 :         xfs_iunlock(ip, XFS_ILOCK_EXCL);
     568         352 :         xfs_irele(ip);
     569         352 :         return 0;
     570             : 
     571           0 : err_cancel:
     572           0 :         xfs_trans_cancel(tp);
     573           0 : err_unlock:
     574           0 :         xfs_iunlock(ip, XFS_ILOCK_EXCL);
     575           0 : err_rele:
     576           0 :         xfs_irele(ip);
     577           0 :         return error;
     578             : }
     579             : 
     580             : STATIC bool
     581        2179 : xfs_bui_item_match(
     582             :         struct xfs_log_item     *lip,
     583             :         uint64_t                intent_id)
     584             : {
     585        2179 :         return BUI_ITEM(lip)->bui_format.bui_id == intent_id;
     586             : }
     587             : 
     588             : /* Relog an intent item to push the log tail forward. */
     589             : static struct xfs_log_item *
     590          29 : xfs_bui_item_relog(
     591             :         struct xfs_log_item             *intent,
     592             :         struct xfs_trans                *tp)
     593             : {
     594          29 :         struct xfs_bud_log_item         *budp;
     595          29 :         struct xfs_bui_log_item         *buip;
     596          29 :         struct xfs_map_extent           *map;
     597          29 :         unsigned int                    count;
     598             : 
     599          29 :         count = BUI_ITEM(intent)->bui_format.bui_nextents;
     600          29 :         map = BUI_ITEM(intent)->bui_format.bui_extents;
     601             : 
     602          29 :         tp->t_flags |= XFS_TRANS_DIRTY;
     603          29 :         budp = xfs_trans_get_bud(tp, BUI_ITEM(intent));
     604          29 :         set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags);
     605             : 
     606          29 :         buip = xfs_bui_init(tp->t_mountp);
     607          58 :         memcpy(buip->bui_format.bui_extents, map, count * sizeof(*map));
     608          29 :         atomic_set(&buip->bui_next_extent, count);
     609          29 :         xfs_trans_add_item(tp, &buip->bui_item);
     610          29 :         set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags);
     611          29 :         return &buip->bui_item;
     612             : }
     613             : 
     614             : static const struct xfs_item_ops xfs_bui_item_ops = {
     615             :         .flags          = XFS_ITEM_INTENT,
     616             :         .iop_size       = xfs_bui_item_size,
     617             :         .iop_format     = xfs_bui_item_format,
     618             :         .iop_unpin      = xfs_bui_item_unpin,
     619             :         .iop_release    = xfs_bui_item_release,
     620             :         .iop_recover    = xfs_bui_item_recover,
     621             :         .iop_match      = xfs_bui_item_match,
     622             :         .iop_relog      = xfs_bui_item_relog,
     623             : };
     624             : 
     625             : static inline void
     626        2526 : xfs_bui_copy_format(
     627             :         struct xfs_bui_log_format       *dst,
     628             :         const struct xfs_bui_log_format *src)
     629             : {
     630        2526 :         unsigned int                    i;
     631             : 
     632        5052 :         memcpy(dst, src, offsetof(struct xfs_bui_log_format, bui_extents));
     633             : 
     634        5052 :         for (i = 0; i < src->bui_nextents; i++)
     635        5052 :                 memcpy(&dst->bui_extents[i], &src->bui_extents[i],
     636             :                                 sizeof(struct xfs_map_extent));
     637        2526 : }
     638             : 
     639             : /*
     640             :  * This routine is called to create an in-core extent bmap update
     641             :  * item from the bui format structure which was logged on disk.
     642             :  * It allocates an in-core bui, copies the extents from the format
     643             :  * structure into it, and adds the bui to the AIL with the given
     644             :  * LSN.
     645             :  */
     646             : STATIC int
     647        2526 : xlog_recover_bui_commit_pass2(
     648             :         struct xlog                     *log,
     649             :         struct list_head                *buffer_list,
     650             :         struct xlog_recover_item        *item,
     651             :         xfs_lsn_t                       lsn)
     652             : {
     653        2526 :         struct xfs_mount                *mp = log->l_mp;
     654        2526 :         struct xfs_bui_log_item         *buip;
     655        2526 :         struct xfs_bui_log_format       *bui_formatp;
     656        2526 :         size_t                          len;
     657             : 
     658        2526 :         bui_formatp = item->ri_buf[0].i_addr;
     659             : 
     660        2526 :         if (item->ri_buf[0].i_len < xfs_bui_log_format_sizeof(0)) {
     661           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     662             :                                 item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
     663           0 :                 return -EFSCORRUPTED;
     664             :         }
     665             : 
     666        2526 :         if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) {
     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        2526 :         len = xfs_bui_log_format_sizeof(bui_formatp->bui_nextents);
     673        2526 :         if (item->ri_buf[0].i_len != len) {
     674           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     675             :                                 item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
     676           0 :                 return -EFSCORRUPTED;
     677             :         }
     678             : 
     679        2526 :         buip = xfs_bui_init(mp);
     680        2526 :         xfs_bui_copy_format(&buip->bui_format, bui_formatp);
     681        2526 :         atomic_set(&buip->bui_next_extent, bui_formatp->bui_nextents);
     682             :         /*
     683             :          * Insert the intent into the AIL directly and drop one reference so
     684             :          * that finishing or canceling the work will drop the other.
     685             :          */
     686        2526 :         xfs_trans_ail_insert(log->l_ailp, &buip->bui_item, lsn);
     687        2526 :         xfs_bui_release(buip);
     688        2526 :         return 0;
     689             : }
     690             : 
     691             : const struct xlog_recover_item_ops xlog_bui_item_ops = {
     692             :         .item_type              = XFS_LI_BUI,
     693             :         .commit_pass2           = xlog_recover_bui_commit_pass2,
     694             : };
     695             : 
     696             : /*
     697             :  * This routine is called when an BUD format structure is found in a committed
     698             :  * transaction in the log. Its purpose is to cancel the corresponding BUI if it
     699             :  * was still in the log. To do this it searches the AIL for the BUI with an id
     700             :  * equal to that in the BUD format structure. If we find it we drop the BUD
     701             :  * reference, which removes the BUI from the AIL and frees it.
     702             :  */
     703             : STATIC int
     704        2233 : xlog_recover_bud_commit_pass2(
     705             :         struct xlog                     *log,
     706             :         struct list_head                *buffer_list,
     707             :         struct xlog_recover_item        *item,
     708             :         xfs_lsn_t                       lsn)
     709             : {
     710        2233 :         struct xfs_bud_log_format       *bud_formatp;
     711             : 
     712        2233 :         bud_formatp = item->ri_buf[0].i_addr;
     713        2233 :         if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) {
     714           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
     715             :                                 item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
     716           0 :                 return -EFSCORRUPTED;
     717             :         }
     718             : 
     719        2233 :         xlog_recover_release_intent(log, XFS_LI_BUI, bud_formatp->bud_bui_id);
     720        2233 :         return 0;
     721             : }
     722             : 
     723             : const struct xlog_recover_item_ops xlog_bud_item_ops = {
     724             :         .item_type              = XFS_LI_BUD,
     725             :         .commit_pass2           = xlog_recover_bud_commit_pass2,
     726             : };

Generated by: LCOV version 1.14