LCOV - code coverage report
Current view: top level - fs/xfs - xfs_rmap_item.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 276 292 94.5 %
Date: 2023-07-31 20:08:12 Functions: 29 29 100.0 %

          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_trans.h"
      16             : #include "xfs_trans_priv.h"
      17             : #include "xfs_rmap_item.h"
      18             : #include "xfs_log.h"
      19             : #include "xfs_rmap.h"
      20             : #include "xfs_error.h"
      21             : #include "xfs_log_priv.h"
      22             : #include "xfs_log_recover.h"
      23             : #include "xfs_ag.h"
      24             : 
      25             : struct kmem_cache       *xfs_rui_cache;
      26             : struct kmem_cache       *xfs_rud_cache;
      27             : 
      28             : static const struct xfs_item_ops xfs_rui_item_ops;
      29             : 
      30             : static inline struct xfs_rui_log_item *RUI_ITEM(struct xfs_log_item *lip)
      31             : {
      32             :         return container_of(lip, struct xfs_rui_log_item, rui_item);
      33             : }
      34             : 
      35             : STATIC void
      36   406728264 : xfs_rui_item_free(
      37             :         struct xfs_rui_log_item *ruip)
      38             : {
      39   406728264 :         kmem_free(ruip->rui_item.li_lv_shadow);
      40   406728033 :         if (ruip->rui_format.rui_nextents > XFS_RUI_MAX_FAST_EXTENTS)
      41           0 :                 kmem_free(ruip);
      42             :         else
      43   406728033 :                 kmem_cache_free(xfs_rui_cache, ruip);
      44   406726736 : }
      45             : 
      46             : /*
      47             :  * Freeing the RUI requires that we remove it from the AIL if it has already
      48             :  * been placed there. However, the RUI may not yet have been placed in the AIL
      49             :  * when called by xfs_rui_release() from RUD processing due to the ordering of
      50             :  * committed vs unpin operations in bulk insert operations. Hence the reference
      51             :  * count to ensure only the last caller frees the RUI.
      52             :  */
      53             : STATIC void
      54   813413033 : xfs_rui_release(
      55             :         struct xfs_rui_log_item *ruip)
      56             : {
      57   813413033 :         ASSERT(atomic_read(&ruip->rui_refcount) > 0);
      58   813413033 :         if (!atomic_dec_and_test(&ruip->rui_refcount))
      59             :                 return;
      60             : 
      61   406725805 :         xfs_trans_ail_delete(&ruip->rui_item, 0);
      62   406729199 :         xfs_rui_item_free(ruip);
      63             : }
      64             : 
      65             : STATIC void
      66   406671052 : xfs_rui_item_size(
      67             :         struct xfs_log_item     *lip,
      68             :         int                     *nvecs,
      69             :         int                     *nbytes)
      70             : {
      71   406671052 :         struct xfs_rui_log_item *ruip = RUI_ITEM(lip);
      72             : 
      73   406671052 :         *nvecs += 1;
      74   406671052 :         *nbytes += xfs_rui_log_format_sizeof(ruip->rui_format.rui_nextents);
      75   406671052 : }
      76             : 
      77             : /*
      78             :  * This is called to fill in the vector of log iovecs for the
      79             :  * given rui log item. We use only 1 iovec, and we point that
      80             :  * at the rui_log_format structure embedded in the rui item.
      81             :  * It is at this point that we assert that all of the extent
      82             :  * slots in the rui item have been filled.
      83             :  */
      84             : STATIC void
      85   406673354 : xfs_rui_item_format(
      86             :         struct xfs_log_item     *lip,
      87             :         struct xfs_log_vec      *lv)
      88             : {
      89   406673354 :         struct xfs_rui_log_item *ruip = RUI_ITEM(lip);
      90   406673354 :         struct xfs_log_iovec    *vecp = NULL;
      91             : 
      92   406673354 :         ASSERT(atomic_read(&ruip->rui_next_extent) ==
      93             :                         ruip->rui_format.rui_nextents);
      94             : 
      95   406673354 :         ruip->rui_format.rui_type = XFS_LI_RUI;
      96   406673354 :         ruip->rui_format.rui_size = 1;
      97             : 
      98   406673354 :         xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_RUI_FORMAT, &ruip->rui_format,
      99   406673354 :                         xfs_rui_log_format_sizeof(ruip->rui_format.rui_nextents));
     100   406665214 : }
     101             : 
     102             : /*
     103             :  * The unpin operation is the last place an RUI is manipulated in the log. It is
     104             :  * either inserted in the AIL or aborted in the event of a log I/O error. In
     105             :  * either case, the RUI transaction has been successfully committed to make it
     106             :  * this far. Therefore, we expect whoever committed the RUI to either construct
     107             :  * and commit the RUD or drop the RUD's reference in the event of error. Simply
     108             :  * drop the log's RUI reference now that the log is done with it.
     109             :  */
     110             : STATIC void
     111   406662059 : xfs_rui_item_unpin(
     112             :         struct xfs_log_item     *lip,
     113             :         int                     remove)
     114             : {
     115   406662059 :         struct xfs_rui_log_item *ruip = RUI_ITEM(lip);
     116             : 
     117   406662059 :         xfs_rui_release(ruip);
     118   406670087 : }
     119             : 
     120             : /*
     121             :  * The RUI has been either committed or aborted if the transaction has been
     122             :  * cancelled. If the transaction was cancelled, an RUD isn't going to be
     123             :  * constructed and thus we free the RUI here directly.
     124             :  */
     125             : STATIC void
     126       52836 : xfs_rui_item_release(
     127             :         struct xfs_log_item     *lip)
     128             : {
     129       52836 :         xfs_rui_release(RUI_ITEM(lip));
     130       52836 : }
     131             : 
     132             : /*
     133             :  * Allocate and initialize an rui item with the given number of extents.
     134             :  */
     135             : STATIC struct xfs_rui_log_item *
     136   406497031 : xfs_rui_init(
     137             :         struct xfs_mount                *mp,
     138             :         uint                            nextents)
     139             : 
     140             : {
     141   406497031 :         struct xfs_rui_log_item         *ruip;
     142             : 
     143   406497031 :         ASSERT(nextents > 0);
     144   406497031 :         if (nextents > XFS_RUI_MAX_FAST_EXTENTS)
     145           0 :                 ruip = kmem_zalloc(xfs_rui_log_item_sizeof(nextents), 0);
     146             :         else
     147   406497031 :                 ruip = kmem_cache_zalloc(xfs_rui_cache,
     148             :                                          GFP_KERNEL | __GFP_NOFAIL);
     149             : 
     150   406678328 :         xfs_log_item_init(mp, &ruip->rui_item, XFS_LI_RUI, &xfs_rui_item_ops);
     151   406629631 :         ruip->rui_format.rui_nextents = nextents;
     152   406629631 :         ruip->rui_format.rui_id = (uintptr_t)(void *)ruip;
     153   406629631 :         atomic_set(&ruip->rui_next_extent, 0);
     154   406629631 :         atomic_set(&ruip->rui_refcount, 2);
     155             : 
     156   406629631 :         return ruip;
     157             : }
     158             : 
     159             : static inline struct xfs_rud_log_item *RUD_ITEM(struct xfs_log_item *lip)
     160             : {
     161             :         return container_of(lip, struct xfs_rud_log_item, rud_item);
     162             : }
     163             : 
     164             : STATIC void
     165   406666912 : xfs_rud_item_size(
     166             :         struct xfs_log_item     *lip,
     167             :         int                     *nvecs,
     168             :         int                     *nbytes)
     169             : {
     170   406666912 :         *nvecs += 1;
     171   406666912 :         *nbytes += sizeof(struct xfs_rud_log_format);
     172   406666912 : }
     173             : 
     174             : /*
     175             :  * This is called to fill in the vector of log iovecs for the
     176             :  * given rud log item. We use only 1 iovec, and we point that
     177             :  * at the rud_log_format structure embedded in the rud item.
     178             :  * It is at this point that we assert that all of the extent
     179             :  * slots in the rud item have been filled.
     180             :  */
     181             : STATIC void
     182      421613 : xfs_rud_item_format(
     183             :         struct xfs_log_item     *lip,
     184             :         struct xfs_log_vec      *lv)
     185             : {
     186      421613 :         struct xfs_rud_log_item *rudp = RUD_ITEM(lip);
     187      421613 :         struct xfs_log_iovec    *vecp = NULL;
     188             : 
     189      421613 :         rudp->rud_format.rud_type = XFS_LI_RUD;
     190      421613 :         rudp->rud_format.rud_size = 1;
     191             : 
     192      421613 :         xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_RUD_FORMAT, &rudp->rud_format,
     193             :                         sizeof(struct xfs_rud_log_format));
     194      421602 : }
     195             : 
     196             : /*
     197             :  * The RUD is either committed or aborted if the transaction is cancelled. If
     198             :  * the transaction is cancelled, drop our reference to the RUI and free the
     199             :  * RUD.
     200             :  */
     201             : STATIC void
     202   406675165 : xfs_rud_item_release(
     203             :         struct xfs_log_item     *lip)
     204             : {
     205   406675165 :         struct xfs_rud_log_item *rudp = RUD_ITEM(lip);
     206             : 
     207   406675165 :         xfs_rui_release(rudp->rud_ruip);
     208   406677175 :         kmem_free(rudp->rud_item.li_lv_shadow);
     209   406672793 :         kmem_cache_free(xfs_rud_cache, rudp);
     210   406671487 : }
     211             : 
     212             : static struct xfs_log_item *
     213   406667071 : xfs_rud_item_intent(
     214             :         struct xfs_log_item     *lip)
     215             : {
     216   406667071 :         return &RUD_ITEM(lip)->rud_ruip->rui_item;
     217             : }
     218             : 
     219             : static const struct xfs_item_ops xfs_rud_item_ops = {
     220             :         .flags          = XFS_ITEM_RELEASE_WHEN_COMMITTED |
     221             :                           XFS_ITEM_INTENT_DONE,
     222             :         .iop_size       = xfs_rud_item_size,
     223             :         .iop_format     = xfs_rud_item_format,
     224             :         .iop_release    = xfs_rud_item_release,
     225             :         .iop_intent     = xfs_rud_item_intent,
     226             : };
     227             : 
     228             : static struct xfs_rud_log_item *
     229   406666202 : xfs_trans_get_rud(
     230             :         struct xfs_trans                *tp,
     231             :         struct xfs_rui_log_item         *ruip)
     232             : {
     233   406666202 :         struct xfs_rud_log_item         *rudp;
     234             : 
     235   406666202 :         rudp = kmem_cache_zalloc(xfs_rud_cache, GFP_KERNEL | __GFP_NOFAIL);
     236   406670754 :         xfs_log_item_init(tp->t_mountp, &rudp->rud_item, XFS_LI_RUD,
     237             :                           &xfs_rud_item_ops);
     238   406662907 :         rudp->rud_ruip = ruip;
     239   406662907 :         rudp->rud_format.rud_rui_id = ruip->rui_format.rui_id;
     240             : 
     241   406662907 :         xfs_trans_add_item(tp, &rudp->rud_item);
     242   406668544 :         return rudp;
     243             : }
     244             : 
     245             : /* Set the map extent flags for this reverse mapping. */
     246             : static void
     247   470568906 : xfs_trans_set_rmap_flags(
     248             :         struct xfs_map_extent           *map,
     249             :         enum xfs_rmap_intent_type       type,
     250             :         int                             whichfork,
     251             :         xfs_exntst_t                    state)
     252             : {
     253   470568906 :         map->me_flags = 0;
     254   470568906 :         if (state == XFS_EXT_UNWRITTEN)
     255    72885550 :                 map->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN;
     256   470568906 :         if (whichfork == XFS_ATTR_FORK)
     257     6220975 :                 map->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK;
     258   470568906 :         switch (type) {
     259    97476592 :         case XFS_RMAP_MAP:
     260    97476592 :                 map->me_flags |= XFS_RMAP_EXTENT_MAP;
     261    97476592 :                 break;
     262   125065425 :         case XFS_RMAP_MAP_SHARED:
     263   125065425 :                 map->me_flags |= XFS_RMAP_EXTENT_MAP_SHARED;
     264   125065425 :                 break;
     265    85315327 :         case XFS_RMAP_UNMAP:
     266    85315327 :                 map->me_flags |= XFS_RMAP_EXTENT_UNMAP;
     267    85315327 :                 break;
     268   111493542 :         case XFS_RMAP_UNMAP_SHARED:
     269   111493542 :                 map->me_flags |= XFS_RMAP_EXTENT_UNMAP_SHARED;
     270   111493542 :                 break;
     271    12955389 :         case XFS_RMAP_CONVERT:
     272    12955389 :                 map->me_flags |= XFS_RMAP_EXTENT_CONVERT;
     273    12955389 :                 break;
     274    18846754 :         case XFS_RMAP_CONVERT_SHARED:
     275    18846754 :                 map->me_flags |= XFS_RMAP_EXTENT_CONVERT_SHARED;
     276    18846754 :                 break;
     277     3824644 :         case XFS_RMAP_ALLOC:
     278     3824644 :                 map->me_flags |= XFS_RMAP_EXTENT_ALLOC;
     279     3824644 :                 break;
     280    15591233 :         case XFS_RMAP_FREE:
     281    15591233 :                 map->me_flags |= XFS_RMAP_EXTENT_FREE;
     282    15591233 :                 break;
     283           0 :         default:
     284           0 :                 ASSERT(0);
     285             :         }
     286   470568906 : }
     287             : 
     288             : /*
     289             :  * Finish an rmap update and log it to the RUD. Note that the transaction is
     290             :  * marked dirty regardless of whether the rmap update succeeds or fails to
     291             :  * support the RUI/RUD lifecycle rules.
     292             :  */
     293             : static int
     294   470624996 : xfs_trans_log_finish_rmap_update(
     295             :         struct xfs_trans                *tp,
     296             :         struct xfs_rud_log_item         *rudp,
     297             :         struct xfs_rmap_intent          *ri,
     298             :         struct xfs_btree_cur            **pcur)
     299             : {
     300   470624996 :         int                             error;
     301             : 
     302   470624996 :         error = xfs_rmap_finish_one(tp, ri, pcur);
     303             : 
     304             :         /*
     305             :          * Mark the transaction dirty, even on error. This ensures the
     306             :          * transaction is aborted, which:
     307             :          *
     308             :          * 1.) releases the RUI and frees the RUD
     309             :          * 2.) shuts down the filesystem
     310             :          */
     311   470616400 :         tp->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE;
     312   470616400 :         set_bit(XFS_LI_DIRTY, &rudp->rud_item.li_flags);
     313             : 
     314   470638237 :         return error;
     315             : }
     316             : 
     317             : /* Sort rmap intents by AG. */
     318             : static int
     319    63968111 : xfs_rmap_update_diff_items(
     320             :         void                            *priv,
     321             :         const struct list_head          *a,
     322             :         const struct list_head          *b)
     323             : {
     324    63968111 :         struct xfs_rmap_intent          *ra;
     325    63968111 :         struct xfs_rmap_intent          *rb;
     326             : 
     327    63968111 :         ra = container_of(a, struct xfs_rmap_intent, ri_list);
     328    63968111 :         rb = container_of(b, struct xfs_rmap_intent, ri_list);
     329             : 
     330    63968111 :         return ra->ri_pag->pag_agno - rb->ri_pag->pag_agno;
     331             : }
     332             : 
     333             : /* Log rmap updates in the intent item. */
     334             : STATIC void
     335   470555713 : xfs_rmap_update_log_item(
     336             :         struct xfs_trans                *tp,
     337             :         struct xfs_rui_log_item         *ruip,
     338             :         struct xfs_rmap_intent          *ri)
     339             : {
     340   470555713 :         uint                            next_extent;
     341   470555713 :         struct xfs_map_extent           *map;
     342             : 
     343   470555713 :         tp->t_flags |= XFS_TRANS_DIRTY;
     344   470555713 :         set_bit(XFS_LI_DIRTY, &ruip->rui_item.li_flags);
     345             : 
     346             :         /*
     347             :          * atomic_inc_return gives us the value after the increment;
     348             :          * we want to use it as an array index so we need to subtract 1 from
     349             :          * it.
     350             :          */
     351   470622067 :         next_extent = atomic_inc_return(&ruip->rui_next_extent) - 1;
     352   470579103 :         ASSERT(next_extent < ruip->rui_format.rui_nextents);
     353   470579103 :         map = &ruip->rui_format.rui_extents[next_extent];
     354   470579103 :         map->me_owner = ri->ri_owner;
     355   470579103 :         map->me_startblock = ri->ri_bmap.br_startblock;
     356   470579103 :         map->me_startoff = ri->ri_bmap.br_startoff;
     357   470579103 :         map->me_len = ri->ri_bmap.br_blockcount;
     358   470579103 :         xfs_trans_set_rmap_flags(map, ri->ri_type, ri->ri_whichfork,
     359             :                         ri->ri_bmap.br_state);
     360   470553818 : }
     361             : 
     362             : static struct xfs_log_item *
     363   406517998 : xfs_rmap_update_create_intent(
     364             :         struct xfs_trans                *tp,
     365             :         struct list_head                *items,
     366             :         unsigned int                    count,
     367             :         bool                            sort)
     368             : {
     369   406517998 :         struct xfs_mount                *mp = tp->t_mountp;
     370   406517998 :         struct xfs_rui_log_item         *ruip = xfs_rui_init(mp, count);
     371   406580894 :         struct xfs_rmap_intent          *ri;
     372             : 
     373   406580894 :         ASSERT(count > 0);
     374             : 
     375   406580894 :         xfs_trans_add_item(tp, &ruip->rui_item);
     376   406587845 :         if (sort)
     377   406593650 :                 list_sort(mp, items, xfs_rmap_update_diff_items);
     378   877138308 :         list_for_each_entry(ri, items, ri_list)
     379   470551879 :                 xfs_rmap_update_log_item(tp, ruip, ri);
     380   406586429 :         return &ruip->rui_item;
     381             : }
     382             : 
     383             : /* Get an RUD so we can process all the deferred rmap updates. */
     384             : static struct xfs_log_item *
     385   406665944 : xfs_rmap_update_create_done(
     386             :         struct xfs_trans                *tp,
     387             :         struct xfs_log_item             *intent,
     388             :         unsigned int                    count)
     389             : {
     390   406665944 :         return &xfs_trans_get_rud(tp, RUI_ITEM(intent))->rud_item;
     391             : }
     392             : 
     393             : /* Take a passive ref to the AG containing the space we're rmapping. */
     394             : void
     395   470583141 : xfs_rmap_update_get_group(
     396             :         struct xfs_mount        *mp,
     397             :         struct xfs_rmap_intent  *ri)
     398             : {
     399   470583141 :         xfs_agnumber_t          agno;
     400             : 
     401   470583141 :         agno = XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock);
     402   470583141 :         ri->ri_pag = xfs_perag_intent_get(mp, agno);
     403   470619473 : }
     404             : 
     405             : /* Release a passive AG ref after finishing rmapping work. */
     406             : static inline void
     407             : xfs_rmap_update_put_group(
     408             :         struct xfs_rmap_intent  *ri)
     409             : {
     410   470637316 :         xfs_perag_intent_put(ri->ri_pag);
     411             : }
     412             : 
     413             : /* Process a deferred rmap update. */
     414             : STATIC int
     415   470624873 : xfs_rmap_update_finish_item(
     416             :         struct xfs_trans                *tp,
     417             :         struct xfs_log_item             *done,
     418             :         struct list_head                *item,
     419             :         struct xfs_btree_cur            **state)
     420             : {
     421   470624873 :         struct xfs_rmap_intent          *ri;
     422   470624873 :         int                             error;
     423             : 
     424   470624873 :         ri = container_of(item, struct xfs_rmap_intent, ri_list);
     425             : 
     426   470624873 :         error = xfs_trans_log_finish_rmap_update(tp, RUD_ITEM(done), ri,
     427             :                         state);
     428             : 
     429   470634299 :         xfs_rmap_update_put_group(ri);
     430   470631902 :         kmem_cache_free(xfs_rmap_intent_cache, ri);
     431   470621610 :         return error;
     432             : }
     433             : 
     434             : /* Abort all pending RUIs. */
     435             : STATIC void
     436         877 : xfs_rmap_update_abort_intent(
     437             :         struct xfs_log_item     *intent)
     438             : {
     439         877 :         xfs_rui_release(RUI_ITEM(intent));
     440         877 : }
     441             : 
     442             : /* Cancel a deferred rmap update. */
     443             : STATIC void
     444         998 : xfs_rmap_update_cancel_item(
     445             :         struct list_head                *item)
     446             : {
     447         998 :         struct xfs_rmap_intent          *ri;
     448             : 
     449         998 :         ri = container_of(item, struct xfs_rmap_intent, ri_list);
     450             : 
     451         998 :         xfs_rmap_update_put_group(ri);
     452         998 :         kmem_cache_free(xfs_rmap_intent_cache, ri);
     453         998 : }
     454             : 
     455             : const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
     456             :         .max_items      = XFS_RUI_MAX_FAST_EXTENTS,
     457             :         .create_intent  = xfs_rmap_update_create_intent,
     458             :         .abort_intent   = xfs_rmap_update_abort_intent,
     459             :         .create_done    = xfs_rmap_update_create_done,
     460             :         .finish_item    = xfs_rmap_update_finish_item,
     461             :         .finish_cleanup = xfs_rmap_finish_one_cleanup,
     462             :         .cancel_item    = xfs_rmap_update_cancel_item,
     463             : };
     464             : 
     465             : /* Is this recovered RUI ok? */
     466             : static inline bool
     467        2019 : xfs_rui_validate_map(
     468             :         struct xfs_mount                *mp,
     469             :         struct xfs_map_extent           *map)
     470             : {
     471        2019 :         if (!xfs_has_rmapbt(mp))
     472             :                 return false;
     473             : 
     474        2019 :         if (map->me_flags & ~XFS_RMAP_EXTENT_FLAGS)
     475             :                 return false;
     476             : 
     477        2019 :         switch (map->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {
     478             :         case XFS_RMAP_EXTENT_MAP:
     479             :         case XFS_RMAP_EXTENT_MAP_SHARED:
     480             :         case XFS_RMAP_EXTENT_UNMAP:
     481             :         case XFS_RMAP_EXTENT_UNMAP_SHARED:
     482             :         case XFS_RMAP_EXTENT_CONVERT:
     483             :         case XFS_RMAP_EXTENT_CONVERT_SHARED:
     484             :         case XFS_RMAP_EXTENT_ALLOC:
     485             :         case XFS_RMAP_EXTENT_FREE:
     486        2019 :                 break;
     487             :         default:
     488             :                 return false;
     489             :         }
     490             : 
     491        4003 :         if (!XFS_RMAP_NON_INODE_OWNER(map->me_owner) &&
     492        1984 :             !xfs_verify_ino(mp, map->me_owner))
     493             :                 return false;
     494             : 
     495        2019 :         if (!xfs_verify_fileext(mp, map->me_startoff, map->me_len))
     496             :                 return false;
     497             : 
     498        2019 :         return xfs_verify_fsbext(mp, map->me_startblock, map->me_len);
     499             : }
     500             : 
     501             : /*
     502             :  * Process an rmap update intent item that was recovered from the log.
     503             :  * We need to update the rmapbt.
     504             :  */
     505             : STATIC int
     506        2011 : xfs_rui_item_recover(
     507             :         struct xfs_log_item             *lip,
     508             :         struct list_head                *capture_list)
     509             : {
     510        2011 :         struct xfs_rui_log_item         *ruip = RUI_ITEM(lip);
     511        2011 :         struct xfs_rud_log_item         *rudp;
     512        2011 :         struct xfs_trans                *tp;
     513        2011 :         struct xfs_btree_cur            *rcur = NULL;
     514        2011 :         struct xfs_mount                *mp = lip->li_log->l_mp;
     515        2011 :         int                             i;
     516        2011 :         int                             error = 0;
     517             : 
     518             :         /*
     519             :          * First check the validity of the extents described by the
     520             :          * RUI.  If any are bad, then assume that all are bad and
     521             :          * just toss the RUI.
     522             :          */
     523        4030 :         for (i = 0; i < ruip->rui_format.rui_nextents; i++) {
     524        2019 :                 if (!xfs_rui_validate_map(mp,
     525             :                                         &ruip->rui_format.rui_extents[i])) {
     526           0 :                         XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     527             :                                         &ruip->rui_format,
     528             :                                         sizeof(ruip->rui_format));
     529           0 :                         return -EFSCORRUPTED;
     530             :                 }
     531             :         }
     532             : 
     533        2011 :         error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
     534             :                         mp->m_rmap_maxlevels, 0, XFS_TRANS_RESERVE, &tp);
     535        2011 :         if (error)
     536             :                 return error;
     537        2011 :         rudp = xfs_trans_get_rud(tp, ruip);
     538             : 
     539        6035 :         for (i = 0; i < ruip->rui_format.rui_nextents; i++) {
     540        2019 :                 struct xfs_rmap_intent  fake = { };
     541        2019 :                 struct xfs_map_extent   *map;
     542             : 
     543        2019 :                 map = &ruip->rui_format.rui_extents[i];
     544        2019 :                 switch (map->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {
     545             :                 case XFS_RMAP_EXTENT_MAP:
     546             :                         fake.ri_type = XFS_RMAP_MAP;
     547             :                         break;
     548         461 :                 case XFS_RMAP_EXTENT_MAP_SHARED:
     549         461 :                         fake.ri_type = XFS_RMAP_MAP_SHARED;
     550         461 :                         break;
     551          65 :                 case XFS_RMAP_EXTENT_UNMAP:
     552          65 :                         fake.ri_type = XFS_RMAP_UNMAP;
     553          65 :                         break;
     554        1021 :                 case XFS_RMAP_EXTENT_UNMAP_SHARED:
     555        1021 :                         fake.ri_type = XFS_RMAP_UNMAP_SHARED;
     556        1021 :                         break;
     557          28 :                 case XFS_RMAP_EXTENT_CONVERT:
     558          28 :                         fake.ri_type = XFS_RMAP_CONVERT;
     559          28 :                         break;
     560          83 :                 case XFS_RMAP_EXTENT_CONVERT_SHARED:
     561          83 :                         fake.ri_type = XFS_RMAP_CONVERT_SHARED;
     562          83 :                         break;
     563          15 :                 case XFS_RMAP_EXTENT_ALLOC:
     564          15 :                         fake.ri_type = XFS_RMAP_ALLOC;
     565          15 :                         break;
     566          20 :                 case XFS_RMAP_EXTENT_FREE:
     567          20 :                         fake.ri_type = XFS_RMAP_FREE;
     568          20 :                         break;
     569           0 :                 default:
     570           0 :                         XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     571             :                                         &ruip->rui_format,
     572             :                                         sizeof(ruip->rui_format));
     573           0 :                         error = -EFSCORRUPTED;
     574           0 :                         goto abort_error;
     575             :                 }
     576             : 
     577        2019 :                 fake.ri_owner = map->me_owner;
     578        2019 :                 fake.ri_whichfork = (map->me_flags & XFS_RMAP_EXTENT_ATTR_FORK) ?
     579        2019 :                                 XFS_ATTR_FORK : XFS_DATA_FORK;
     580        2019 :                 fake.ri_bmap.br_startblock = map->me_startblock;
     581        2019 :                 fake.ri_bmap.br_startoff = map->me_startoff;
     582        2019 :                 fake.ri_bmap.br_blockcount = map->me_len;
     583        2019 :                 fake.ri_bmap.br_state = (map->me_flags & XFS_RMAP_EXTENT_UNWRITTEN) ?
     584        2019 :                                 XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
     585             : 
     586        2019 :                 xfs_rmap_update_get_group(mp, &fake);
     587        2019 :                 error = xfs_trans_log_finish_rmap_update(tp, rudp, &fake,
     588             :                                 &rcur);
     589        2019 :                 if (error == -EFSCORRUPTED)
     590           6 :                         XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     591             :                                         map, sizeof(*map));
     592        2019 :                 xfs_rmap_update_put_group(&fake);
     593        2019 :                 if (error)
     594           6 :                         goto abort_error;
     595             : 
     596             :         }
     597             : 
     598        2005 :         xfs_rmap_finish_one_cleanup(tp, rcur, error);
     599        2005 :         return xfs_defer_ops_capture_and_commit(tp, capture_list);
     600             : 
     601             : abort_error:
     602           6 :         xfs_rmap_finish_one_cleanup(tp, rcur, error);
     603           6 :         xfs_trans_cancel(tp);
     604           6 :         return error;
     605             : }
     606             : 
     607             : STATIC bool
     608       57517 : xfs_rui_item_match(
     609             :         struct xfs_log_item     *lip,
     610             :         uint64_t                intent_id)
     611             : {
     612       57517 :         return RUI_ITEM(lip)->rui_format.rui_id == intent_id;
     613             : }
     614             : 
     615             : /* Relog an intent item to push the log tail forward. */
     616             : static struct xfs_log_item *
     617        2742 : xfs_rui_item_relog(
     618             :         struct xfs_log_item             *intent,
     619             :         struct xfs_trans                *tp)
     620             : {
     621        2742 :         struct xfs_rud_log_item         *rudp;
     622        2742 :         struct xfs_rui_log_item         *ruip;
     623        2742 :         struct xfs_map_extent           *map;
     624        2742 :         unsigned int                    count;
     625             : 
     626        2742 :         count = RUI_ITEM(intent)->rui_format.rui_nextents;
     627        2742 :         map = RUI_ITEM(intent)->rui_format.rui_extents;
     628             : 
     629        2742 :         tp->t_flags |= XFS_TRANS_DIRTY;
     630        2742 :         rudp = xfs_trans_get_rud(tp, RUI_ITEM(intent));
     631        2742 :         set_bit(XFS_LI_DIRTY, &rudp->rud_item.li_flags);
     632             : 
     633        2742 :         ruip = xfs_rui_init(tp->t_mountp, count);
     634        5484 :         memcpy(ruip->rui_format.rui_extents, map, count * sizeof(*map));
     635        2742 :         atomic_set(&ruip->rui_next_extent, count);
     636        2742 :         xfs_trans_add_item(tp, &ruip->rui_item);
     637        2742 :         set_bit(XFS_LI_DIRTY, &ruip->rui_item.li_flags);
     638        2742 :         return &ruip->rui_item;
     639             : }
     640             : 
     641             : static const struct xfs_item_ops xfs_rui_item_ops = {
     642             :         .flags          = XFS_ITEM_INTENT,
     643             :         .iop_size       = xfs_rui_item_size,
     644             :         .iop_format     = xfs_rui_item_format,
     645             :         .iop_unpin      = xfs_rui_item_unpin,
     646             :         .iop_release    = xfs_rui_item_release,
     647             :         .iop_recover    = xfs_rui_item_recover,
     648             :         .iop_match      = xfs_rui_item_match,
     649             :         .iop_relog      = xfs_rui_item_relog,
     650             : };
     651             : 
     652             : static inline void
     653       54827 : xfs_rui_copy_format(
     654             :         struct xfs_rui_log_format       *dst,
     655             :         const struct xfs_rui_log_format *src)
     656             : {
     657       54827 :         unsigned int                    i;
     658             : 
     659      109654 :         memcpy(dst, src, offsetof(struct xfs_rui_log_format, rui_extents));
     660             : 
     661      110016 :         for (i = 0; i < src->rui_nextents; i++)
     662      110378 :                 memcpy(&dst->rui_extents[i], &src->rui_extents[i],
     663             :                                 sizeof(struct xfs_map_extent));
     664       54827 : }
     665             : 
     666             : /*
     667             :  * This routine is called to create an in-core extent rmap update
     668             :  * item from the rui format structure which was logged on disk.
     669             :  * It allocates an in-core rui, copies the extents from the format
     670             :  * structure into it, and adds the rui to the AIL with the given
     671             :  * LSN.
     672             :  */
     673             : STATIC int
     674       54827 : xlog_recover_rui_commit_pass2(
     675             :         struct xlog                     *log,
     676             :         struct list_head                *buffer_list,
     677             :         struct xlog_recover_item        *item,
     678             :         xfs_lsn_t                       lsn)
     679             : {
     680       54827 :         struct xfs_mount                *mp = log->l_mp;
     681       54827 :         struct xfs_rui_log_item         *ruip;
     682       54827 :         struct xfs_rui_log_format       *rui_formatp;
     683       54827 :         size_t                          len;
     684             : 
     685       54827 :         rui_formatp = item->ri_buf[0].i_addr;
     686             : 
     687       54827 :         if (item->ri_buf[0].i_len < xfs_rui_log_format_sizeof(0)) {
     688           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     689             :                                 item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
     690           0 :                 return -EFSCORRUPTED;
     691             :         }
     692             : 
     693       54827 :         len = xfs_rui_log_format_sizeof(rui_formatp->rui_nextents);
     694       54827 :         if (item->ri_buf[0].i_len != len) {
     695           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     696             :                                 item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
     697           0 :                 return -EFSCORRUPTED;
     698             :         }
     699             : 
     700       54827 :         ruip = xfs_rui_init(mp, rui_formatp->rui_nextents);
     701       54827 :         xfs_rui_copy_format(&ruip->rui_format, rui_formatp);
     702       54827 :         atomic_set(&ruip->rui_next_extent, rui_formatp->rui_nextents);
     703             :         /*
     704             :          * Insert the intent into the AIL directly and drop one reference so
     705             :          * that finishing or canceling the work will drop the other.
     706             :          */
     707       54827 :         xfs_trans_ail_insert(log->l_ailp, &ruip->rui_item, lsn);
     708       54827 :         xfs_rui_release(ruip);
     709       54827 :         return 0;
     710             : }
     711             : 
     712             : const struct xlog_recover_item_ops xlog_rui_item_ops = {
     713             :         .item_type              = XFS_LI_RUI,
     714             :         .commit_pass2           = xlog_recover_rui_commit_pass2,
     715             : };
     716             : 
     717             : /*
     718             :  * This routine is called when an RUD format structure is found in a committed
     719             :  * transaction in the log. Its purpose is to cancel the corresponding RUI if it
     720             :  * was still in the log. To do this it searches the AIL for the RUI with an id
     721             :  * equal to that in the RUD format structure. If we find it we drop the RUD
     722             :  * reference, which removes the RUI from the AIL and frees it.
     723             :  */
     724             : STATIC int
     725       53148 : xlog_recover_rud_commit_pass2(
     726             :         struct xlog                     *log,
     727             :         struct list_head                *buffer_list,
     728             :         struct xlog_recover_item        *item,
     729             :         xfs_lsn_t                       lsn)
     730             : {
     731       53148 :         struct xfs_rud_log_format       *rud_formatp;
     732             : 
     733       53148 :         rud_formatp = item->ri_buf[0].i_addr;
     734       53148 :         if (item->ri_buf[0].i_len != sizeof(struct xfs_rud_log_format)) {
     735           0 :                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
     736             :                                 rud_formatp, item->ri_buf[0].i_len);
     737           0 :                 return -EFSCORRUPTED;
     738             :         }
     739             : 
     740       53148 :         xlog_recover_release_intent(log, XFS_LI_RUI, rud_formatp->rud_rui_id);
     741       53148 :         return 0;
     742             : }
     743             : 
     744             : const struct xlog_recover_item_ops xlog_rud_item_ops = {
     745             :         .item_type              = XFS_LI_RUD,
     746             :         .commit_pass2           = xlog_recover_rud_commit_pass2,
     747             : };

Generated by: LCOV version 1.14