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

Generated by: LCOV version 1.14