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-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 276 292 94.5 %
Date: 2023-07-31 20:08:07 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   214742733 : xfs_rui_item_free(
      37             :         struct xfs_rui_log_item *ruip)
      38             : {
      39   214742733 :         kmem_free(ruip->rui_item.li_lv_shadow);
      40   214742379 :         if (ruip->rui_format.rui_nextents > XFS_RUI_MAX_FAST_EXTENTS)
      41           0 :                 kmem_free(ruip);
      42             :         else
      43   214742379 :                 kmem_cache_free(xfs_rui_cache, ruip);
      44   214733070 : }
      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   429350148 : xfs_rui_release(
      55             :         struct xfs_rui_log_item *ruip)
      56             : {
      57   429350148 :         ASSERT(atomic_read(&ruip->rui_refcount) > 0);
      58   858773791 :         if (!atomic_dec_and_test(&ruip->rui_refcount))
      59             :                 return;
      60             : 
      61   214737086 :         xfs_trans_ail_delete(&ruip->rui_item, 0);
      62   214742276 :         xfs_rui_item_free(ruip);
      63             : }
      64             : 
      65             : STATIC void
      66   214697395 : xfs_rui_item_size(
      67             :         struct xfs_log_item     *lip,
      68             :         int                     *nvecs,
      69             :         int                     *nbytes)
      70             : {
      71   214697395 :         struct xfs_rui_log_item *ruip = RUI_ITEM(lip);
      72             : 
      73   214697395 :         *nvecs += 1;
      74   214697395 :         *nbytes += xfs_rui_log_format_sizeof(ruip->rui_format.rui_nextents);
      75   214697395 : }
      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   214697436 : xfs_rui_item_format(
      86             :         struct xfs_log_item     *lip,
      87             :         struct xfs_log_vec      *lv)
      88             : {
      89   214697436 :         struct xfs_rui_log_item *ruip = RUI_ITEM(lip);
      90   214697436 :         struct xfs_log_iovec    *vecp = NULL;
      91             : 
      92   214697436 :         ASSERT(atomic_read(&ruip->rui_next_extent) ==
      93             :                         ruip->rui_format.rui_nextents);
      94             : 
      95   214697436 :         ruip->rui_format.rui_type = XFS_LI_RUI;
      96   214697436 :         ruip->rui_format.rui_size = 1;
      97             : 
      98   214697436 :         xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_RUI_FORMAT, &ruip->rui_format,
      99   214697436 :                         xfs_rui_log_format_sizeof(ruip->rui_format.rui_nextents));
     100   214697685 : }
     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   214679026 : xfs_rui_item_unpin(
     112             :         struct xfs_log_item     *lip,
     113             :         int                     remove)
     114             : {
     115   214679026 :         struct xfs_rui_log_item *ruip = RUI_ITEM(lip);
     116             : 
     117   214679026 :         xfs_rui_release(ruip);
     118   214695227 : }
     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       43381 : xfs_rui_item_release(
     127             :         struct xfs_log_item     *lip)
     128             : {
     129       43381 :         xfs_rui_release(RUI_ITEM(lip));
     130       43381 : }
     131             : 
     132             : /*
     133             :  * Allocate and initialize an rui item with the given number of extents.
     134             :  */
     135             : STATIC struct xfs_rui_log_item *
     136   214705354 : xfs_rui_init(
     137             :         struct xfs_mount                *mp,
     138             :         uint                            nextents)
     139             : 
     140             : {
     141   214705354 :         struct xfs_rui_log_item         *ruip;
     142             : 
     143   214705354 :         ASSERT(nextents > 0);
     144   214705354 :         if (nextents > XFS_RUI_MAX_FAST_EXTENTS)
     145           0 :                 ruip = kmem_zalloc(xfs_rui_log_item_sizeof(nextents), 0);
     146             :         else
     147   214705354 :                 ruip = kmem_cache_zalloc(xfs_rui_cache,
     148             :                                          GFP_KERNEL | __GFP_NOFAIL);
     149             : 
     150   214665921 :         xfs_log_item_init(mp, &ruip->rui_item, XFS_LI_RUI, &xfs_rui_item_ops);
     151   214705588 :         ruip->rui_format.rui_nextents = nextents;
     152   214705588 :         ruip->rui_format.rui_id = (uintptr_t)(void *)ruip;
     153   214705588 :         atomic_set(&ruip->rui_next_extent, 0);
     154   214705588 :         atomic_set(&ruip->rui_refcount, 2);
     155             : 
     156   214705588 :         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   214696491 : xfs_rud_item_size(
     166             :         struct xfs_log_item     *lip,
     167             :         int                     *nvecs,
     168             :         int                     *nbytes)
     169             : {
     170   214696491 :         *nvecs += 1;
     171   214696491 :         *nbytes += sizeof(struct xfs_rud_log_format);
     172   214696491 : }
     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      292983 : xfs_rud_item_format(
     183             :         struct xfs_log_item     *lip,
     184             :         struct xfs_log_vec      *lv)
     185             : {
     186      292983 :         struct xfs_rud_log_item *rudp = RUD_ITEM(lip);
     187      292983 :         struct xfs_log_iovec    *vecp = NULL;
     188             : 
     189      292983 :         rudp->rud_format.rud_type = XFS_LI_RUD;
     190      292983 :         rudp->rud_format.rud_size = 1;
     191             : 
     192      292983 :         xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_RUD_FORMAT, &rudp->rud_format,
     193             :                         sizeof(struct xfs_rud_log_format));
     194      292983 : }
     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   214698513 : xfs_rud_item_release(
     203             :         struct xfs_log_item     *lip)
     204             : {
     205   214698513 :         struct xfs_rud_log_item *rudp = RUD_ITEM(lip);
     206             : 
     207   214698513 :         xfs_rui_release(rudp->rud_ruip);
     208   214698764 :         kmem_free(rudp->rud_item.li_lv_shadow);
     209   214698805 :         kmem_cache_free(xfs_rud_cache, rudp);
     210   214698698 : }
     211             : 
     212             : static struct xfs_log_item *
     213   214695894 : xfs_rud_item_intent(
     214             :         struct xfs_log_item     *lip)
     215             : {
     216   214695894 :         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   214697099 : xfs_trans_get_rud(
     230             :         struct xfs_trans                *tp,
     231             :         struct xfs_rui_log_item         *ruip)
     232             : {
     233   214697099 :         struct xfs_rud_log_item         *rudp;
     234             : 
     235   214697099 :         rudp = kmem_cache_zalloc(xfs_rud_cache, GFP_KERNEL | __GFP_NOFAIL);
     236   214698132 :         xfs_log_item_init(tp->t_mountp, &rudp->rud_item, XFS_LI_RUD,
     237             :                           &xfs_rud_item_ops);
     238   214698434 :         rudp->rud_ruip = ruip;
     239   214698434 :         rudp->rud_format.rud_rui_id = ruip->rui_format.rui_id;
     240             : 
     241   214698434 :         xfs_trans_add_item(tp, &rudp->rud_item);
     242   214698424 :         return rudp;
     243             : }
     244             : 
     245             : /* Set the map extent flags for this reverse mapping. */
     246             : static void
     247   234290316 : 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   234290316 :         map->me_flags = 0;
     254   234290316 :         if (state == XFS_EXT_UNWRITTEN)
     255    32067274 :                 map->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN;
     256   234290316 :         if (whichfork == XFS_ATTR_FORK)
     257     5529629 :                 map->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK;
     258   234290316 :         switch (type) {
     259    46924730 :         case XFS_RMAP_MAP:
     260    46924730 :                 map->me_flags |= XFS_RMAP_EXTENT_MAP;
     261    46924730 :                 break;
     262    68738887 :         case XFS_RMAP_MAP_SHARED:
     263    68738887 :                 map->me_flags |= XFS_RMAP_EXTENT_MAP_SHARED;
     264    68738887 :                 break;
     265    40392979 :         case XFS_RMAP_UNMAP:
     266    40392979 :                 map->me_flags |= XFS_RMAP_EXTENT_UNMAP;
     267    40392979 :                 break;
     268    57317595 :         case XFS_RMAP_UNMAP_SHARED:
     269    57317595 :                 map->me_flags |= XFS_RMAP_EXTENT_UNMAP_SHARED;
     270    57317595 :                 break;
     271     5979789 :         case XFS_RMAP_CONVERT:
     272     5979789 :                 map->me_flags |= XFS_RMAP_EXTENT_CONVERT;
     273     5979789 :                 break;
     274    12345975 :         case XFS_RMAP_CONVERT_SHARED:
     275    12345975 :                 map->me_flags |= XFS_RMAP_EXTENT_CONVERT_SHARED;
     276    12345975 :                 break;
     277      359535 :         case XFS_RMAP_ALLOC:
     278      359535 :                 map->me_flags |= XFS_RMAP_EXTENT_ALLOC;
     279      359535 :                 break;
     280     2230826 :         case XFS_RMAP_FREE:
     281     2230826 :                 map->me_flags |= XFS_RMAP_EXTENT_FREE;
     282     2230826 :                 break;
     283           0 :         default:
     284           0 :                 ASSERT(0);
     285             :         }
     286   234290316 : }
     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   234291649 : 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   234291649 :         int                             error;
     301             : 
     302   234291649 :         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   234291210 :         tp->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE;
     312   234291210 :         set_bit(XFS_LI_DIRTY, &rudp->rud_item.li_flags);
     313             : 
     314   234291570 :         return error;
     315             : }
     316             : 
     317             : /* Sort rmap intents by AG. */
     318             : static int
     319    19596353 : xfs_rmap_update_diff_items(
     320             :         void                            *priv,
     321             :         const struct list_head          *a,
     322             :         const struct list_head          *b)
     323             : {
     324    19596353 :         struct xfs_rmap_intent          *ra;
     325    19596353 :         struct xfs_rmap_intent          *rb;
     326             : 
     327    19596353 :         ra = container_of(a, struct xfs_rmap_intent, ri_list);
     328    19596353 :         rb = container_of(b, struct xfs_rmap_intent, ri_list);
     329             : 
     330    19596353 :         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   234269667 : 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   234269667 :         uint                            next_extent;
     341   234269667 :         struct xfs_map_extent           *map;
     342             : 
     343   234269667 :         tp->t_flags |= XFS_TRANS_DIRTY;
     344   234269667 :         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   234268478 :         next_extent = atomic_inc_return(&ruip->rui_next_extent) - 1;
     352   234284684 :         ASSERT(next_extent < ruip->rui_format.rui_nextents);
     353   234284684 :         map = &ruip->rui_format.rui_extents[next_extent];
     354   234284684 :         map->me_owner = ri->ri_owner;
     355   234284684 :         map->me_startblock = ri->ri_bmap.br_startblock;
     356   234284684 :         map->me_startoff = ri->ri_bmap.br_startoff;
     357   234284684 :         map->me_len = ri->ri_bmap.br_blockcount;
     358   234284684 :         xfs_trans_set_rmap_flags(map, ri->ri_type, ri->ri_whichfork,
     359             :                         ri->ri_bmap.br_state);
     360   234282232 : }
     361             : 
     362             : static struct xfs_log_item *
     363   214664361 : xfs_rmap_update_create_intent(
     364             :         struct xfs_trans                *tp,
     365             :         struct list_head                *items,
     366             :         unsigned int                    count,
     367             :         bool                            sort)
     368             : {
     369   214664361 :         struct xfs_mount                *mp = tp->t_mountp;
     370   214664361 :         struct xfs_rui_log_item         *ruip = xfs_rui_init(mp, count);
     371   214641122 :         struct xfs_rmap_intent          *ri;
     372             : 
     373   214641122 :         ASSERT(count > 0);
     374             : 
     375   214641122 :         xfs_trans_add_item(tp, &ruip->rui_item);
     376   214667129 :         if (sort)
     377   214669546 :                 list_sort(mp, items, xfs_rmap_update_diff_items);
     378   448951370 :         list_for_each_entry(ri, items, ri_list)
     379   234271565 :                 xfs_rmap_update_log_item(tp, ruip, ri);
     380   214679805 :         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   214694946 : xfs_rmap_update_create_done(
     386             :         struct xfs_trans                *tp,
     387             :         struct xfs_log_item             *intent,
     388             :         unsigned int                    count)
     389             : {
     390   214694946 :         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   234282107 : xfs_rmap_update_get_group(
     396             :         struct xfs_mount        *mp,
     397             :         struct xfs_rmap_intent  *ri)
     398             : {
     399   234282107 :         xfs_agnumber_t          agno;
     400             : 
     401   234282107 :         agno = XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock);
     402   234282107 :         ri->ri_pag = xfs_perag_intent_get(mp, agno);
     403   234276971 : }
     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   234291929 :         xfs_perag_intent_put(ri->ri_pag);
     411             : }
     412             : 
     413             : /* Process a deferred rmap update. */
     414             : STATIC int
     415   234290992 : 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   234290992 :         struct xfs_rmap_intent          *ri;
     422   234290992 :         int                             error;
     423             : 
     424   234290992 :         ri = container_of(item, struct xfs_rmap_intent, ri_list);
     425             : 
     426   234290992 :         error = xfs_trans_log_finish_rmap_update(tp, RUD_ITEM(done), ri,
     427             :                         state);
     428             : 
     429   234289732 :         xfs_rmap_update_put_group(ri);
     430   234290144 :         kmem_cache_free(xfs_rmap_intent_cache, ri);
     431   234290978 :         return error;
     432             : }
     433             : 
     434             : /* Abort all pending RUIs. */
     435             : STATIC void
     436         687 : xfs_rmap_update_abort_intent(
     437             :         struct xfs_log_item     *intent)
     438             : {
     439         687 :         xfs_rui_release(RUI_ITEM(intent));
     440         687 : }
     441             : 
     442             : /* Cancel a deferred rmap update. */
     443             : STATIC void
     444         769 : xfs_rmap_update_cancel_item(
     445             :         struct list_head                *item)
     446             : {
     447         769 :         struct xfs_rmap_intent          *ri;
     448             : 
     449         769 :         ri = container_of(item, struct xfs_rmap_intent, ri_list);
     450             : 
     451         769 :         xfs_rmap_update_put_group(ri);
     452         769 :         kmem_cache_free(xfs_rmap_intent_cache, ri);
     453         769 : }
     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        1428 : xfs_rui_validate_map(
     468             :         struct xfs_mount                *mp,
     469             :         struct xfs_map_extent           *map)
     470             : {
     471        1428 :         if (!xfs_has_rmapbt(mp))
     472             :                 return false;
     473             : 
     474        1428 :         if (map->me_flags & ~XFS_RMAP_EXTENT_FLAGS)
     475             :                 return false;
     476             : 
     477        1428 :         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        1428 :                 break;
     487             :         default:
     488             :                 return false;
     489             :         }
     490             : 
     491        2844 :         if (!XFS_RMAP_NON_INODE_OWNER(map->me_owner) &&
     492        1416 :             !xfs_verify_ino(mp, map->me_owner))
     493             :                 return false;
     494             : 
     495        1428 :         if (!xfs_verify_fileext(mp, map->me_startoff, map->me_len))
     496             :                 return false;
     497             : 
     498        1428 :         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        1423 : xfs_rui_item_recover(
     507             :         struct xfs_log_item             *lip,
     508             :         struct list_head                *capture_list)
     509             : {
     510        1423 :         struct xfs_rui_log_item         *ruip = RUI_ITEM(lip);
     511        1423 :         struct xfs_rud_log_item         *rudp;
     512        1423 :         struct xfs_trans                *tp;
     513        1423 :         struct xfs_btree_cur            *rcur = NULL;
     514        1423 :         struct xfs_mount                *mp = lip->li_log->l_mp;
     515        1423 :         int                             i;
     516        1423 :         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        2851 :         for (i = 0; i < ruip->rui_format.rui_nextents; i++) {
     524        1428 :                 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        1423 :         error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
     534             :                         mp->m_rmap_maxlevels, 0, XFS_TRANS_RESERVE, &tp);
     535        1423 :         if (error)
     536             :                 return error;
     537        1423 :         rudp = xfs_trans_get_rud(tp, ruip);
     538             : 
     539        4272 :         for (i = 0; i < ruip->rui_format.rui_nextents; i++) {
     540        1428 :                 struct xfs_rmap_intent  fake = { };
     541        1428 :                 struct xfs_map_extent   *map;
     542             : 
     543        1428 :                 map = &ruip->rui_format.rui_extents[i];
     544        1428 :                 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         350 :                 case XFS_RMAP_EXTENT_MAP_SHARED:
     549         350 :                         fake.ri_type = XFS_RMAP_MAP_SHARED;
     550         350 :                         break;
     551          33 :                 case XFS_RMAP_EXTENT_UNMAP:
     552          33 :                         fake.ri_type = XFS_RMAP_UNMAP;
     553          33 :                         break;
     554         812 :                 case XFS_RMAP_EXTENT_UNMAP_SHARED:
     555         812 :                         fake.ri_type = XFS_RMAP_UNMAP_SHARED;
     556         812 :                         break;
     557          18 :                 case XFS_RMAP_EXTENT_CONVERT:
     558          18 :                         fake.ri_type = XFS_RMAP_CONVERT;
     559          18 :                         break;
     560          74 :                 case XFS_RMAP_EXTENT_CONVERT_SHARED:
     561          74 :                         fake.ri_type = XFS_RMAP_CONVERT_SHARED;
     562          74 :                         break;
     563           4 :                 case XFS_RMAP_EXTENT_ALLOC:
     564           4 :                         fake.ri_type = XFS_RMAP_ALLOC;
     565           4 :                         break;
     566           8 :                 case XFS_RMAP_EXTENT_FREE:
     567           8 :                         fake.ri_type = XFS_RMAP_FREE;
     568           8 :                         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        1428 :                 fake.ri_owner = map->me_owner;
     578        1428 :                 fake.ri_whichfork = (map->me_flags & XFS_RMAP_EXTENT_ATTR_FORK) ?
     579        1428 :                                 XFS_ATTR_FORK : XFS_DATA_FORK;
     580        1428 :                 fake.ri_bmap.br_startblock = map->me_startblock;
     581        1428 :                 fake.ri_bmap.br_startoff = map->me_startoff;
     582        1428 :                 fake.ri_bmap.br_blockcount = map->me_len;
     583        1428 :                 fake.ri_bmap.br_state = (map->me_flags & XFS_RMAP_EXTENT_UNWRITTEN) ?
     584        1428 :                                 XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
     585             : 
     586        1428 :                 xfs_rmap_update_get_group(mp, &fake);
     587        1428 :                 error = xfs_trans_log_finish_rmap_update(tp, rudp, &fake,
     588             :                                 &rcur);
     589        1428 :                 if (error == -EFSCORRUPTED)
     590           2 :                         XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
     591             :                                         map, sizeof(*map));
     592        1428 :                 xfs_rmap_update_put_group(&fake);
     593        1428 :                 if (error)
     594           2 :                         goto abort_error;
     595             : 
     596             :         }
     597             : 
     598        1421 :         xfs_rmap_finish_one_cleanup(tp, rcur, error);
     599        1421 :         return xfs_defer_ops_capture_and_commit(tp, capture_list);
     600             : 
     601             : abort_error:
     602           2 :         xfs_rmap_finish_one_cleanup(tp, rcur, error);
     603           2 :         xfs_trans_cancel(tp);
     604           2 :         return error;
     605             : }
     606             : 
     607             : STATIC bool
     608       46986 : xfs_rui_item_match(
     609             :         struct xfs_log_item     *lip,
     610             :         uint64_t                intent_id)
     611             : {
     612       46986 :         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         655 : xfs_rui_item_relog(
     618             :         struct xfs_log_item             *intent,
     619             :         struct xfs_trans                *tp)
     620             : {
     621         655 :         struct xfs_rud_log_item         *rudp;
     622         655 :         struct xfs_rui_log_item         *ruip;
     623         655 :         struct xfs_map_extent           *map;
     624         655 :         unsigned int                    count;
     625             : 
     626         655 :         count = RUI_ITEM(intent)->rui_format.rui_nextents;
     627         655 :         map = RUI_ITEM(intent)->rui_format.rui_extents;
     628             : 
     629         655 :         tp->t_flags |= XFS_TRANS_DIRTY;
     630         655 :         rudp = xfs_trans_get_rud(tp, RUI_ITEM(intent));
     631         656 :         set_bit(XFS_LI_DIRTY, &rudp->rud_item.li_flags);
     632             : 
     633         656 :         ruip = xfs_rui_init(tp->t_mountp, count);
     634        1312 :         memcpy(ruip->rui_format.rui_extents, map, count * sizeof(*map));
     635         656 :         atomic_set(&ruip->rui_next_extent, count);
     636         656 :         xfs_trans_add_item(tp, &ruip->rui_item);
     637         656 :         set_bit(XFS_LI_DIRTY, &ruip->rui_item.li_flags);
     638         656 :         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       44762 : xfs_rui_copy_format(
     654             :         struct xfs_rui_log_format       *dst,
     655             :         const struct xfs_rui_log_format *src)
     656             : {
     657       44762 :         unsigned int                    i;
     658             : 
     659       89524 :         memcpy(dst, src, offsetof(struct xfs_rui_log_format, rui_extents));
     660             : 
     661       89770 :         for (i = 0; i < src->rui_nextents; i++)
     662       90016 :                 memcpy(&dst->rui_extents[i], &src->rui_extents[i],
     663             :                                 sizeof(struct xfs_map_extent));
     664       44762 : }
     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       44762 : 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       44762 :         struct xfs_mount                *mp = log->l_mp;
     681       44762 :         struct xfs_rui_log_item         *ruip;
     682       44762 :         struct xfs_rui_log_format       *rui_formatp;
     683       44762 :         size_t                          len;
     684             : 
     685       44762 :         rui_formatp = item->ri_buf[0].i_addr;
     686             : 
     687       44762 :         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       44762 :         len = xfs_rui_log_format_sizeof(rui_formatp->rui_nextents);
     694       44762 :         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       44762 :         ruip = xfs_rui_init(mp, rui_formatp->rui_nextents);
     701       44762 :         xfs_rui_copy_format(&ruip->rui_format, rui_formatp);
     702       44762 :         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       44762 :         xfs_trans_ail_insert(log->l_ailp, &ruip->rui_item, lsn);
     708       44762 :         xfs_rui_release(ruip);
     709       44762 :         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       43578 : 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       43578 :         struct xfs_rud_log_format       *rud_formatp;
     732             : 
     733       43578 :         rud_formatp = item->ri_buf[0].i_addr;
     734       43578 :         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       43578 :         xlog_recover_release_intent(log, XFS_LI_RUI, rud_formatp->rud_rui_id);
     741       43578 :         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