LCOV - code coverage report
Current view: top level - fs/xfs/scrub - xfbtree.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsa @ Mon Jul 31 20:08:27 PDT 2023 Lines: 279 345 80.9 %
Date: 2023-07-31 20:08:27 Functions: 31 32 96.9 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 */
       2             : /*
       3             :  * Copyright (C) 2021-2023 Oracle.  All Rights Reserved.
       4             :  * Author: Darrick J. Wong <djwong@kernel.org>
       5             :  */
       6             : #include "xfs.h"
       7             : #include "xfs_fs.h"
       8             : #include "xfs_shared.h"
       9             : #include "xfs_format.h"
      10             : #include "xfs_log_format.h"
      11             : #include "xfs_trans_resv.h"
      12             : #include "xfs_bit.h"
      13             : #include "xfs_mount.h"
      14             : #include "xfs_trans.h"
      15             : #include "xfs_buf_item.h"
      16             : #include "xfs_btree.h"
      17             : #include "xfs_error.h"
      18             : #include "xfs_btree_mem.h"
      19             : #include "xfs_ag.h"
      20             : #include "xfs_rtgroup.h"
      21             : #include "scrub/scrub.h"
      22             : #include "scrub/xfile.h"
      23             : #include "scrub/xfbtree.h"
      24             : #include "scrub/bitmap.h"
      25             : #include "scrub/trace.h"
      26             : 
      27             : /* btree ops functions for in-memory btrees. */
      28             : 
      29             : static xfs_failaddr_t
      30       80276 : xfs_btree_mem_head_verify(
      31             :         struct xfs_buf                  *bp)
      32             : {
      33       80276 :         struct xfs_btree_mem_head       *mhead = bp->b_addr;
      34       80276 :         struct xfs_mount                *mp = bp->b_mount;
      35             : 
      36       80276 :         if (!xfs_verify_magic(bp, mhead->mh_magic))
      37           0 :                 return __this_address;
      38       80266 :         if (be32_to_cpu(mhead->mh_nlevels) == 0)
      39           0 :                 return __this_address;
      40       80267 :         if (!uuid_equal(&mhead->mh_uuid, &mp->m_sb.sb_meta_uuid))
      41           0 :                 return __this_address;
      42             : 
      43             :         return NULL;
      44             : }
      45             : 
      46             : static void
      47          93 : xfs_btree_mem_head_read_verify(
      48             :         struct xfs_buf          *bp)
      49             : {
      50          93 :         xfs_failaddr_t          fa = xfs_btree_mem_head_verify(bp);
      51             : 
      52          93 :         if (fa)
      53           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
      54          93 : }
      55             : 
      56             : static void
      57       78468 : xfs_btree_mem_head_write_verify(
      58             :         struct xfs_buf          *bp)
      59             : {
      60       78468 :         xfs_failaddr_t          fa = xfs_btree_mem_head_verify(bp);
      61             : 
      62       78465 :         if (fa)
      63           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
      64       78465 : }
      65             : 
      66             : static const struct xfs_buf_ops xfs_btree_mem_head_buf_ops = {
      67             :         .name                   = "xfs_btree_mem_head",
      68             :         .magic                  = { cpu_to_be32(XFS_BTREE_MEM_HEAD_MAGIC),
      69             :                                     cpu_to_be32(XFS_BTREE_MEM_HEAD_MAGIC) },
      70             :         .verify_read            = xfs_btree_mem_head_read_verify,
      71             :         .verify_write           = xfs_btree_mem_head_write_verify,
      72             :         .verify_struct          = xfs_btree_mem_head_verify,
      73             : };
      74             : 
      75             : /* Initialize the header block for an in-memory btree. */
      76             : static inline void
      77       78478 : xfs_btree_mem_head_init(
      78             :         struct xfs_buf                  *head_bp,
      79             :         unsigned long long              owner,
      80             :         xfileoff_t                      leaf_xfoff)
      81             : {
      82       78478 :         struct xfs_btree_mem_head       *mhead = head_bp->b_addr;
      83       78478 :         struct xfs_mount                *mp = head_bp->b_mount;
      84             : 
      85       78478 :         mhead->mh_magic = cpu_to_be32(XFS_BTREE_MEM_HEAD_MAGIC);
      86       78478 :         mhead->mh_nlevels = cpu_to_be32(1);
      87       78478 :         mhead->mh_owner = cpu_to_be64(owner);
      88       78478 :         mhead->mh_root = cpu_to_be64(leaf_xfoff);
      89       78478 :         uuid_copy(&mhead->mh_uuid, &mp->m_sb.sb_meta_uuid);
      90             : 
      91       78477 :         head_bp->b_ops = &xfs_btree_mem_head_buf_ops;
      92       78477 : }
      93             : 
      94             : /* Return tree height from the in-memory btree head. */
      95             : unsigned int
      96  1051761266 : xfs_btree_mem_head_nlevels(
      97             :         struct xfs_buf                  *head_bp)
      98             : {
      99  1051761266 :         struct xfs_btree_mem_head       *mhead = head_bp->b_addr;
     100             : 
     101  1051761266 :         return be32_to_cpu(mhead->mh_nlevels);
     102             : }
     103             : 
     104             : /* Extract the buftarg target for this xfile btree. */
     105             : struct xfs_buftarg *
     106  1099145543 : xfbtree_target(struct xfbtree *xfbtree)
     107             : {
     108  3816884439 :         return xfbtree->target;
     109             : }
     110             : 
     111             : /* Is this daddr (sector offset) contained within the buffer target? */
     112             : static inline bool
     113             : xfbtree_verify_buftarg_xfileoff(
     114             :         struct xfs_buftarg      *btp,
     115             :         xfileoff_t              xfoff)
     116             : {
     117    43887232 :         xfs_daddr_t             xfoff_daddr = xfo_to_daddr(xfoff);
     118             : 
     119  2761626128 :         return xfs_buftarg_verify_daddr(btp, xfoff_daddr);
     120             : }
     121             : 
     122             : /* Is this btree xfile offset contained within the xfile? */
     123             : bool
     124   414321085 : xfbtree_verify_xfileoff(
     125             :         struct xfs_btree_cur    *cur,
     126             :         unsigned long long      xfoff)
     127             : {
     128  2717738896 :         struct xfs_buftarg      *btp = xfbtree_target(cur->bc_mem.xfbtree);
     129             : 
     130   414321085 :         return xfbtree_verify_buftarg_xfileoff(btp, xfoff);
     131             : }
     132             : 
     133             : /* Check if a btree pointer is reasonable. */
     134             : int
     135  2303417811 : xfbtree_check_ptr(
     136             :         struct xfs_btree_cur            *cur,
     137             :         const union xfs_btree_ptr       *ptr,
     138             :         int                             index,
     139             :         int                             level)
     140             : {
     141  2303417811 :         xfileoff_t                      bt_xfoff;
     142  2303417811 :         xfs_failaddr_t                  fa = NULL;
     143             : 
     144  2303417811 :         ASSERT(cur->bc_flags & XFS_BTREE_IN_XFILE);
     145             : 
     146  2303417811 :         if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
     147  2125839197 :                 bt_xfoff = be64_to_cpu(ptr->l);
     148             :         else
     149   177578614 :                 bt_xfoff = be32_to_cpu(ptr->s);
     150             : 
     151  2303417811 :         if (!xfbtree_verify_xfileoff(cur, bt_xfoff)) {
     152           0 :                 fa = __this_address;
     153           0 :                 goto done;
     154             :         }
     155             : 
     156             :         /* Can't point to the head or anything before it */
     157  2303417612 :         if (bt_xfoff < XFBTREE_INIT_LEAF_BLOCK) {
     158           0 :                 fa = __this_address;
     159           0 :                 goto done;
     160             :         }
     161             : 
     162  2303417612 : done:
     163           0 :         if (fa) {
     164           0 :                 xfs_err(cur->bc_mp,
     165             : "In-memory: Corrupt btree %d flags 0x%x pointer at level %d index %d fa %pS.",
     166             :                                 cur->bc_btnum, cur->bc_flags, level, index,
     167             :                                 fa);
     168           0 :                 return -EFSCORRUPTED;
     169             :         }
     170             :         return 0;
     171             : }
     172             : 
     173             : /* Convert a btree pointer to a daddr */
     174             : xfs_daddr_t
     175  2254738134 : xfbtree_ptr_to_daddr(
     176             :         struct xfs_btree_cur            *cur,
     177             :         const union xfs_btree_ptr       *ptr)
     178             : {
     179  2254738134 :         xfileoff_t                      bt_xfoff;
     180             : 
     181  2254738134 :         if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
     182  2110538161 :                 bt_xfoff = be64_to_cpu(ptr->l);
     183             :         else
     184   144199973 :                 bt_xfoff = be32_to_cpu(ptr->s);
     185  2254738134 :         return xfo_to_daddr(bt_xfoff);
     186             : }
     187             : 
     188             : /* Set the pointer to point to this buffer. */
     189             : void
     190       11191 : xfbtree_buf_to_ptr(
     191             :         struct xfs_btree_cur    *cur,
     192             :         struct xfs_buf          *bp,
     193             :         union xfs_btree_ptr     *ptr)
     194             : {
     195       11191 :         xfileoff_t              xfoff = xfs_daddr_to_xfo(xfs_buf_daddr(bp));
     196             : 
     197       11191 :         if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
     198        2914 :                 ptr->l = cpu_to_be64(xfoff);
     199             :         else
     200        8277 :                 ptr->s = cpu_to_be32(xfoff);
     201       11191 : }
     202             : 
     203             : /* Return the in-memory btree block size, in units of 512 bytes. */
     204  1099145547 : unsigned int xfbtree_bbsize(void)
     205             : {
     206  1099145547 :         return xfo_to_daddr(1);
     207             : }
     208             : 
     209             : /* Set the root of an in-memory btree. */
     210             : void
     211        1707 : xfbtree_set_root(
     212             :         struct xfs_btree_cur            *cur,
     213             :         const union xfs_btree_ptr       *ptr,
     214             :         int                             inc)
     215             : {
     216        1707 :         struct xfs_buf                  *head_bp = cur->bc_mem.head_bp;
     217        1707 :         struct xfs_btree_mem_head       *mhead = head_bp->b_addr;
     218             : 
     219        1707 :         ASSERT(cur->bc_flags & XFS_BTREE_IN_XFILE);
     220             : 
     221        1707 :         if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
     222         192 :                 mhead->mh_root = ptr->l;
     223             :         } else {
     224        1515 :                 uint32_t                root = be32_to_cpu(ptr->s);
     225             : 
     226        1515 :                 mhead->mh_root = cpu_to_be64(root);
     227             :         }
     228        1707 :         be32_add_cpu(&mhead->mh_nlevels, inc);
     229        1707 :         xfs_trans_log_buf(cur->bc_tp, head_bp, 0, sizeof(*mhead) - 1);
     230        1707 : }
     231             : 
     232             : /* Initialize a pointer from the in-memory btree header. */
     233             : void
     234  1106417099 : xfbtree_init_ptr_from_cur(
     235             :         struct xfs_btree_cur            *cur,
     236             :         union xfs_btree_ptr             *ptr)
     237             : {
     238  1106417099 :         struct xfs_buf                  *head_bp = cur->bc_mem.head_bp;
     239  1106417099 :         struct xfs_btree_mem_head       *mhead = head_bp->b_addr;
     240             : 
     241  1106417099 :         ASSERT(cur->bc_flags & XFS_BTREE_IN_XFILE);
     242             : 
     243  1106417099 :         if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
     244  1047395269 :                 ptr->l = mhead->mh_root;
     245             :         } else {
     246    59021830 :                 uint64_t                root = be64_to_cpu(mhead->mh_root);
     247             : 
     248    59021830 :                 ptr->s = cpu_to_be32(root);
     249             :         }
     250  1106417099 : }
     251             : 
     252             : /* Duplicate an in-memory btree cursor. */
     253             : struct xfs_btree_cur *
     254     6660483 : xfbtree_dup_cursor(
     255             :         struct xfs_btree_cur            *cur)
     256             : {
     257     6660483 :         struct xfs_btree_cur            *ncur;
     258             : 
     259     6660483 :         ASSERT(cur->bc_flags & XFS_BTREE_IN_XFILE);
     260             : 
     261     6660483 :         ncur = xfs_btree_alloc_cursor(cur->bc_mp, cur->bc_tp, cur->bc_btnum,
     262             :                         cur->bc_ops, cur->bc_maxlevels, cur->bc_cache);
     263     6660483 :         ncur->bc_flags = cur->bc_flags;
     264     6660483 :         ncur->bc_nlevels = cur->bc_nlevels;
     265     6660483 :         ncur->bc_statoff = cur->bc_statoff;
     266             : 
     267    13320966 :         memcpy(&ncur->bc_mem, &cur->bc_mem, sizeof(cur->bc_mem));
     268             : 
     269     6660483 :         if (cur->bc_mem.pag)
     270     4309634 :                 ncur->bc_mem.pag = xfs_perag_hold(cur->bc_mem.pag);
     271     6660483 :         if (cur->bc_mem.rtg)
     272     2350849 :                 ncur->bc_mem.rtg = xfs_rtgroup_hold(cur->bc_mem.rtg);
     273             : 
     274     6660483 :         return ncur;
     275             : }
     276             : 
     277             : /* Check the owner of an in-memory btree block. */
     278             : xfs_failaddr_t
     279  1071397119 : xfbtree_check_block_owner(
     280             :         struct xfs_btree_cur    *cur,
     281             :         struct xfs_btree_block  *block)
     282             : {
     283  1071397119 :         struct xfbtree          *xfbt = cur->bc_mem.xfbtree;
     284             : 
     285  1071397119 :         if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
     286  1038284485 :                 if (be64_to_cpu(block->bb_u.l.bb_owner) != xfbt->owner)
     287           0 :                         return __this_address;
     288             : 
     289             :                 return NULL;
     290             :         }
     291             : 
     292    33112634 :         if (be32_to_cpu(block->bb_u.s.bb_owner) != xfbt->owner)
     293           0 :                 return __this_address;
     294             : 
     295             :         return NULL;
     296             : }
     297             : 
     298             : /* Return the owner of this in-memory btree. */
     299             : unsigned long long
     300       11191 : xfbtree_owner(
     301             :         struct xfs_btree_cur    *cur)
     302             : {
     303       11191 :         return cur->bc_mem.xfbtree->owner;
     304             : }
     305             : 
     306             : /* Return the xfile offset (in blocks) of a btree buffer. */
     307             : unsigned long long
     308  3093635335 : xfbtree_buf_to_xfoff(
     309             :         struct xfs_btree_cur    *cur,
     310             :         struct xfs_buf          *bp)
     311             : {
     312  3093635335 :         ASSERT(cur->bc_flags & XFS_BTREE_IN_XFILE);
     313             : 
     314  3093635335 :         return xfs_daddr_to_xfo(xfs_buf_daddr(bp));
     315             : }
     316             : 
     317             : /* Verify a long-format btree block. */
     318             : xfs_failaddr_t
     319   703240240 : xfbtree_lblock_verify(
     320             :         struct xfs_buf          *bp,
     321             :         unsigned int            max_recs)
     322             : {
     323   703240240 :         struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
     324   703240240 :         struct xfs_buftarg      *btp = bp->b_target;
     325             : 
     326             :         /* numrecs verification */
     327   703240240 :         if (be16_to_cpu(block->bb_numrecs) > max_recs)
     328           0 :                 return __this_address;
     329             : 
     330             :         /* sibling pointer verification */
     331   710920581 :         if (block->bb_u.l.bb_leftsib != cpu_to_be64(NULLFSBLOCK) &&
     332     7680343 :             !xfbtree_verify_buftarg_xfileoff(btp,
     333     7680343 :                                 be64_to_cpu(block->bb_u.l.bb_leftsib)))
     334           0 :                 return __this_address;
     335             : 
     336   710786679 :         if (block->bb_u.l.bb_rightsib != cpu_to_be64(NULLFSBLOCK) &&
     337     7546441 :             !xfbtree_verify_buftarg_xfileoff(btp,
     338     7546441 :                                 be64_to_cpu(block->bb_u.l.bb_rightsib)))
     339           0 :                 return __this_address;
     340             : 
     341             :         return NULL;
     342             : }
     343             : 
     344             : /* Verify a short-format btree block. */
     345             : xfs_failaddr_t
     346    28234856 : xfbtree_sblock_verify(
     347             :         struct xfs_buf          *bp,
     348             :         unsigned int            max_recs)
     349             : {
     350    28234856 :         struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
     351    28234856 :         struct xfs_buftarg      *btp = bp->b_target;
     352             : 
     353             :         /* numrecs verification */
     354    28234856 :         if (be16_to_cpu(block->bb_numrecs) > max_recs)
     355           0 :                 return __this_address;
     356             : 
     357             :         /* sibling pointer verification */
     358    43298818 :         if (block->bb_u.s.bb_leftsib != cpu_to_be32(NULLAGBLOCK) &&
     359    15063962 :             !xfbtree_verify_buftarg_xfileoff(btp,
     360    15063962 :                                 be32_to_cpu(block->bb_u.s.bb_leftsib)))
     361           0 :                 return __this_address;
     362             : 
     363    41831342 :         if (block->bb_u.s.bb_rightsib != cpu_to_be32(NULLAGBLOCK) &&
     364    13596486 :             !xfbtree_verify_buftarg_xfileoff(btp,
     365    13596486 :                                 be32_to_cpu(block->bb_u.s.bb_rightsib)))
     366           0 :                 return __this_address;
     367             : 
     368             :         return NULL;
     369             : }
     370             : 
     371             : /* Close the btree xfile and release all resources. */
     372             : void
     373       78472 : xfbtree_destroy(
     374             :         struct xfbtree          *xfbt)
     375             : {
     376       78472 :         xbitmap_destroy(xfbt->freespace);
     377       78471 :         kfree(xfbt->freespace);
     378       78474 :         xfs_buftarg_drain(xfbt->target);
     379       78479 :         kfree(xfbt);
     380       78478 : }
     381             : 
     382             : /* Compute the number of bytes available for records. */
     383             : static inline unsigned int
     384       78479 : xfbtree_rec_bytes(
     385             :         struct xfs_mount                *mp,
     386             :         const struct xfbtree_config     *cfg)
     387             : {
     388       78479 :         unsigned int                    blocklen = xfo_to_b(1);
     389             : 
     390       78479 :         if (cfg->btree_ops->geom_flags & XFS_BTREE_LONG_PTRS) {
     391       69218 :                 if (xfs_has_crc(mp))
     392             :                         return blocklen - XFS_BTREE_LBLOCK_CRC_LEN;
     393             : 
     394           0 :                 return blocklen - XFS_BTREE_LBLOCK_LEN;
     395             :         }
     396             : 
     397        9261 :         if (xfs_has_crc(mp))
     398        9261 :                 return blocklen - XFS_BTREE_SBLOCK_CRC_LEN;
     399             : 
     400             :         return blocklen - XFS_BTREE_SBLOCK_LEN;
     401             : }
     402             : 
     403             : /* Initialize an empty leaf block as the btree root. */
     404             : STATIC int
     405       78479 : xfbtree_init_leaf_block(
     406             :         struct xfs_mount                *mp,
     407             :         struct xfbtree                  *xfbt,
     408             :         const struct xfbtree_config     *cfg)
     409             : {
     410       78479 :         struct xfs_buf                  *bp;
     411       78479 :         xfs_daddr_t                     daddr;
     412       78479 :         int                             error;
     413             : 
     414       78479 :         daddr = xfo_to_daddr(XFBTREE_INIT_LEAF_BLOCK);
     415       78479 :         error = xfs_buf_get(xfbt->target, daddr, xfbtree_bbsize(), &bp);
     416       78470 :         if (error)
     417             :                 return error;
     418             : 
     419       78472 :         trace_xfbtree_create_root_buf(xfbt, bp);
     420             : 
     421       78470 :         xfs_btree_init_buf(mp, bp, cfg->btree_ops, 0, 0, cfg->owner);
     422       78466 :         error = xfs_bwrite(bp);
     423       78473 :         xfs_buf_relse(bp);
     424       78463 :         if (error)
     425             :                 return error;
     426             : 
     427       78463 :         xfbt->xf_used++;
     428       78463 :         return 0;
     429             : }
     430             : 
     431             : /* Initialize the in-memory btree header block. */
     432             : STATIC int
     433       78478 : xfbtree_init_head(
     434             :         struct xfbtree          *xfbt)
     435             : {
     436       78478 :         struct xfs_buf          *bp;
     437       78478 :         xfs_daddr_t             daddr;
     438       78478 :         int                     error;
     439             : 
     440       78478 :         daddr = xfo_to_daddr(XFBTREE_HEAD_BLOCK);
     441       78478 :         error = xfs_buf_get(xfbt->target, daddr, xfbtree_bbsize(), &bp);
     442       78478 :         if (error)
     443             :                 return error;
     444             : 
     445       78478 :         xfs_btree_mem_head_init(bp, xfbt->owner, XFBTREE_INIT_LEAF_BLOCK);
     446       78478 :         error = xfs_bwrite(bp);
     447       78478 :         xfs_buf_relse(bp);
     448       78478 :         if (error)
     449             :                 return error;
     450             : 
     451       78478 :         xfbt->xf_used++;
     452       78478 :         return 0;
     453             : }
     454             : 
     455             : /* Create an xfile btree backing thing that can be used for in-memory btrees. */
     456             : int
     457       78479 : xfbtree_create(
     458             :         struct xfs_mount                *mp,
     459             :         const struct xfbtree_config     *cfg,
     460             :         struct xfbtree                  **xfbtreep)
     461             : {
     462       78479 :         struct xfbtree                  *xfbt;
     463       78479 :         unsigned int                    blocklen = xfbtree_rec_bytes(mp, cfg);
     464       78479 :         unsigned int                    keyptr_len = cfg->btree_ops->key_len;
     465       78479 :         int                             error;
     466             : 
     467             :         /* Requires an xfile-backed buftarg. */
     468       78479 :         if (!(cfg->target->bt_flags & XFS_BUFTARG_XFILE)) {
     469           0 :                 ASSERT(cfg->target->bt_flags & XFS_BUFTARG_XFILE);
     470           0 :                 return -EINVAL;
     471             :         }
     472             : 
     473       78479 :         xfbt = kzalloc(sizeof(struct xfbtree), XCHK_GFP_FLAGS);
     474       78479 :         if (!xfbt)
     475             :                 return -ENOMEM;
     476             : 
     477             :         /* Assign our memory file and the free space bitmap. */
     478       78479 :         xfbt->target = cfg->target;
     479       78479 :         if (cfg->flags & XFBTREE_DIRECT_MAP)
     480       78479 :                 xfbt->target->bt_flags |= XFS_BUFTARG_DIRECT_MAP;
     481             : 
     482       78479 :         xfbt->freespace = kmalloc(sizeof(struct xbitmap), XCHK_GFP_FLAGS);
     483       78479 :         if (!xfbt->freespace) {
     484           0 :                 error = -ENOMEM;
     485           0 :                 goto err_buftarg;
     486             :         }
     487       78479 :         xbitmap_init(xfbt->freespace);
     488             : 
     489             :         /* Set up min/maxrecs for this btree. */
     490       78479 :         if (cfg->btree_ops->geom_flags & XFS_BTREE_LONG_PTRS)
     491       69218 :                 keyptr_len += sizeof(__be64);
     492             :         else
     493        9261 :                 keyptr_len += sizeof(__be32);
     494       78479 :         xfbt->maxrecs[0] = blocklen / cfg->btree_ops->rec_len;
     495       78479 :         xfbt->maxrecs[1] = blocklen / keyptr_len;
     496       78479 :         xfbt->minrecs[0] = xfbt->maxrecs[0] / 2;
     497       78479 :         xfbt->minrecs[1] = xfbt->maxrecs[1] / 2;
     498       78479 :         xfbt->owner = cfg->owner;
     499             : 
     500             :         /* Initialize the empty btree. */
     501       78479 :         error = xfbtree_init_leaf_block(mp, xfbt, cfg);
     502       78465 :         if (error)
     503           0 :                 goto err_freesp;
     504             : 
     505       78465 :         error = xfbtree_init_head(xfbt);
     506       78479 :         if (error)
     507           0 :                 goto err_freesp;
     508             : 
     509       78479 :         trace_xfbtree_create(mp, cfg, xfbt);
     510             : 
     511       78478 :         *xfbtreep = xfbt;
     512       78478 :         return 0;
     513             : 
     514           0 : err_freesp:
     515           0 :         xbitmap_destroy(xfbt->freespace);
     516           0 :         kfree(xfbt->freespace);
     517           0 : err_buftarg:
     518           0 :         xfs_buftarg_drain(xfbt->target);
     519           0 :         kfree(xfbt);
     520           0 :         return error;
     521             : }
     522             : 
     523             : /* Read the in-memory btree head. */
     524             : int
     525  1051760716 : xfbtree_head_read_buf(
     526             :         struct xfbtree          *xfbt,
     527             :         struct xfs_trans        *tp,
     528             :         struct xfs_buf          **bpp)
     529             : {
     530  1051760716 :         struct xfs_buftarg      *btp = xfbt->target;
     531  1051760716 :         struct xfs_mount        *mp = btp->bt_mount;
     532  1051760716 :         struct xfs_btree_mem_head *mhead;
     533  1051760716 :         struct xfs_buf          *bp;
     534  1051760716 :         xfs_daddr_t             daddr;
     535  1051760716 :         int                     error;
     536             : 
     537  1051760716 :         daddr = xfo_to_daddr(XFBTREE_HEAD_BLOCK);
     538  1051760716 :         error = xfs_trans_read_buf(mp, tp, btp, daddr, xfbtree_bbsize(), 0,
     539             :                         &bp, &xfs_btree_mem_head_buf_ops);
     540  1051761276 :         if (error)
     541             :                 return error;
     542             : 
     543  1051761276 :         mhead = bp->b_addr;
     544  1051761276 :         if (be64_to_cpu(mhead->mh_owner) != xfbt->owner) {
     545           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, __this_address);
     546           0 :                 xfs_trans_brelse(tp, bp);
     547           0 :                 return -EFSCORRUPTED;
     548             :         }
     549             : 
     550  1051761276 :         *bpp = bp;
     551  1051761276 :         return 0;
     552             : }
     553             : 
     554             : static inline struct xfile *xfbtree_xfile(struct xfbtree *xfbt)
     555             : {
     556       11191 :         return xfbt->target->bt_xfile;
     557             : }
     558             : 
     559             : /* Allocate a block to our in-memory btree. */
     560             : int
     561       11191 : xfbtree_alloc_block(
     562             :         struct xfs_btree_cur            *cur,
     563             :         const union xfs_btree_ptr       *start,
     564             :         union xfs_btree_ptr             *new,
     565             :         int                             *stat)
     566             : {
     567       11191 :         struct xfbtree                  *xfbt = cur->bc_mem.xfbtree;
     568       11191 :         xfileoff_t                      bt_xfoff;
     569       11191 :         loff_t                          pos;
     570       11191 :         int                             error;
     571             : 
     572       11191 :         ASSERT(cur->bc_flags & XFS_BTREE_IN_XFILE);
     573             : 
     574             :         /*
     575             :          * Find the first free block in the free space bitmap and take it.  If
     576             :          * none are found, seek to end of the file.
     577             :          */
     578       11191 :         error = xbitmap_take_first_set(xfbt->freespace, 0, -1ULL, &bt_xfoff);
     579       11191 :         if (error == -ENODATA) {
     580       11189 :                 bt_xfoff = xfbt->xf_used;
     581       11189 :                 xfbt->xf_used++;
     582           2 :         } else if (error) {
     583             :                 return error;
     584             :         }
     585             : 
     586       11191 :         trace_xfbtree_alloc_block(xfbt, cur, bt_xfoff);
     587             : 
     588             :         /* Fail if the block address exceeds the maximum for short pointers. */
     589       11191 :         if (!(cur->bc_flags & XFS_BTREE_LONG_PTRS) && bt_xfoff >= INT_MAX) {
     590           0 :                 *stat = 0;
     591           0 :                 return 0;
     592             :         }
     593             : 
     594             :         /* Make sure we actually can write to the block before we return it. */
     595       11191 :         pos = xfo_to_b(bt_xfoff);
     596       11191 :         error = xfile_prealloc(xfbtree_xfile(xfbt), pos, xfo_to_b(1));
     597       11191 :         if (error)
     598             :                 return error;
     599             : 
     600       11191 :         if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
     601        2914 :                 new->l = cpu_to_be64(bt_xfoff);
     602             :         else
     603        8277 :                 new->s = cpu_to_be32(bt_xfoff);
     604             : 
     605       11191 :         *stat = 1;
     606       11191 :         return 0;
     607             : }
     608             : 
     609             : /* Free a block from our in-memory btree. */
     610             : int
     611           2 : xfbtree_free_block(
     612             :         struct xfs_btree_cur    *cur,
     613             :         struct xfs_buf          *bp)
     614             : {
     615           2 :         struct xfbtree          *xfbt = cur->bc_mem.xfbtree;
     616           2 :         xfileoff_t              bt_xfoff, bt_xflen;
     617             : 
     618           2 :         ASSERT(cur->bc_flags & XFS_BTREE_IN_XFILE);
     619             : 
     620           2 :         bt_xfoff = xfs_daddr_to_xfot(xfs_buf_daddr(bp));
     621           2 :         bt_xflen = xfs_daddr_to_xfot(bp->b_length);
     622             : 
     623           2 :         trace_xfbtree_free_block(xfbt, cur, bt_xfoff);
     624             : 
     625           2 :         return xbitmap_set(xfbt->freespace, bt_xfoff, bt_xflen);
     626             : }
     627             : 
     628             : /* Return the minimum number of records for a btree block. */
     629             : int
     630      109295 : xfbtree_get_minrecs(
     631             :         struct xfs_btree_cur    *cur,
     632             :         int                     level)
     633             : {
     634      109295 :         struct xfbtree          *xfbt = cur->bc_mem.xfbtree;
     635             : 
     636      109295 :         return xfbt->minrecs[level != 0];
     637             : }
     638             : 
     639             : /* Return the maximum number of records for a btree block. */
     640             : int
     641  3626998184 : xfbtree_get_maxrecs(
     642             :         struct xfs_btree_cur    *cur,
     643             :         int                     level)
     644             : {
     645  3626998184 :         struct xfbtree          *xfbt = cur->bc_mem.xfbtree;
     646             : 
     647  3626998184 :         return xfbt->maxrecs[level != 0];
     648             : }
     649             : 
     650             : /* If this log item is a buffer item that came from the xfbtree, return it. */
     651             : static inline struct xfs_buf *
     652             : xfbtree_buf_match(
     653             :         struct xfbtree                  *xfbt,
     654             :         const struct xfs_log_item       *lip)
     655             : {
     656  4729525197 :         const struct xfs_buf_log_item   *bli;
     657  4729525197 :         struct xfs_buf                  *bp;
     658             : 
     659  4729525197 :         if (lip->li_type != XFS_LI_BUF)
     660             :                 return NULL;
     661             : 
     662  4729525195 :         bli = container_of(lip, struct xfs_buf_log_item, bli_item);
     663  4729525195 :         bp = bli->bli_buf;
     664  4729525195 :         if (bp->b_target != xfbt->target)
     665             :                 return NULL;
     666             : 
     667             :         return bp;
     668             : }
     669             : 
     670             : /*
     671             :  * Detach this (probably dirty) xfbtree buffer from the transaction by any
     672             :  * means necessary.  Returns true if the buffer needs to be written.
     673             :  */
     674             : STATIC bool
     675   758903551 : xfbtree_trans_bdetach(
     676             :         struct xfs_trans        *tp,
     677             :         struct xfs_buf          *bp)
     678             : {
     679   758903551 :         struct xfs_buf_log_item *bli = bp->b_log_item;
     680   758903551 :         bool                    dirty;
     681             : 
     682   758903551 :         ASSERT(bli != NULL);
     683             : 
     684   758903551 :         dirty = bli->bli_flags & (XFS_BLI_DIRTY | XFS_BLI_ORDERED);
     685             : 
     686   758903551 :         bli->bli_flags &= ~(XFS_BLI_DIRTY | XFS_BLI_ORDERED |
     687             :                             XFS_BLI_LOGGED | XFS_BLI_STALE);
     688   758903551 :         clear_bit(XFS_LI_DIRTY, &bli->bli_item.li_flags);
     689             : 
     690  1517807899 :         while (bp->b_log_item != NULL)
     691   758903858 :                 xfs_trans_bdetach(tp, bp);
     692             : 
     693   758904041 :         return dirty;
     694             : }
     695             : 
     696             : /*
     697             :  * Commit changes to the incore btree immediately by writing all dirty xfbtree
     698             :  * buffers to the backing xfile.  This detaches all xfbtree buffers from the
     699             :  * transaction, even on failure.  The buffer locks are dropped between the
     700             :  * delwri queue and submit, so the caller must synchronize btree access.
     701             :  *
     702             :  * Normally we'd let the buffers commit with the transaction and get written to
     703             :  * the xfile via the log, but online repair stages ephemeral btrees in memory
     704             :  * and uses the btree_staging functions to write new btrees to disk atomically.
     705             :  * The in-memory btree (and its backing store) are discarded at the end of the
     706             :  * repair phase, which means that xfbtree buffers cannot commit with the rest
     707             :  * of a transaction.
     708             :  *
     709             :  * In other words, online repair only needs the transaction to collect buffer
     710             :  * pointers and to avoid buffer deadlocks, not to guarantee consistency of
     711             :  * updates.
     712             :  */
     713             : int
     714   719890222 : xfbtree_trans_commit(
     715             :         struct xfbtree          *xfbt,
     716             :         struct xfs_trans        *tp)
     717             : {
     718   719890222 :         LIST_HEAD(buffer_list);
     719   719890222 :         struct xfs_log_item     *lip, *n;
     720   719890222 :         bool                    corrupt = false;
     721   719890222 :         bool                    tp_dirty = false;
     722             : 
     723             :         /*
     724             :          * For each xfbtree buffer attached to the transaction, write the dirty
     725             :          * buffers to the xfile and release them.
     726             :          */
     727  5449415529 :         list_for_each_entry_safe(lip, n, &tp->t_items, li_trans) {
     728  4729525197 :                 struct xfs_buf  *bp = xfbtree_buf_match(xfbt, lip);
     729   758903942 :                 bool            dirty;
     730             : 
     731   758903942 :                 if (!bp) {
     732  7941242510 :                         if (test_bit(XFS_LI_DIRTY, &lip->li_flags))
     733           0 :                                 tp_dirty |= true;
     734  3970621255 :                         continue;
     735             :                 }
     736             : 
     737   758903942 :                 trace_xfbtree_trans_commit_buf(xfbt, bp);
     738             : 
     739   758903900 :                 dirty = xfbtree_trans_bdetach(tp, bp);
     740   758904052 :                 if (dirty && !corrupt) {
     741   731398323 :                         xfs_failaddr_t  fa;
     742             : 
     743             :                         /*
     744             :                          * Because this btree is ephemeral, validate the buffer
     745             :                          * structure before delwri_submit so that we can return
     746             :                          * corruption errors to the caller without shutting
     747             :                          * down the filesystem.
     748             :                          *
     749             :                          * Buffers that are directly mapped to the xfile do not
     750             :                          * need to be queued for IO at all.  Check if the DRAM
     751             :                          * has been poisoned, however.
     752             :                          *
     753             :                          * If the buffer fails verification, log the failure
     754             :                          * but continue walking the transaction items so that
     755             :                          * we remove all ephemeral btree buffers.
     756             :                          */
     757   731398323 :                         if (xfs_buf_check_poisoned(bp)) {
     758           0 :                                 corrupt = true;
     759           0 :                                 xfs_verifier_error(bp, -EFSCORRUPTED,
     760           0 :                                                 __this_address);
     761           0 :                                 continue;
     762             :                         }
     763             : 
     764   731398342 :                         fa = bp->b_ops->verify_struct(bp);
     765   731398321 :                         if (fa) {
     766           0 :                                 corrupt = true;
     767           0 :                                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     768           0 :                                 continue;
     769             :                         }
     770             : 
     771   731398321 :                         if (!(bp->b_flags & _XBF_DIRECT_MAP))
     772           0 :                                 xfs_buf_delwri_queue_here(bp, &buffer_list);
     773             :                 }
     774             : 
     775   758904050 :                 xfs_buf_relse(bp);
     776             :         }
     777             : 
     778             :         /*
     779             :          * Reset the transaction's dirty flag to reflect the dirty state of the
     780             :          * log items that are still attached.
     781             :          */
     782  1439780664 :         tp->t_flags = (tp->t_flags & ~XFS_TRANS_DIRTY) |
     783   719890332 :                         (tp_dirty ? XFS_TRANS_DIRTY : 0);
     784             : 
     785   719890332 :         if (corrupt) {
     786           0 :                 xfs_buf_delwri_cancel(&buffer_list);
     787           0 :                 return -EFSCORRUPTED;
     788             :         }
     789             : 
     790   719890332 :         if (list_empty(&buffer_list))
     791             :                 return 0;
     792             : 
     793           0 :         return xfs_buf_delwri_submit(&buffer_list);
     794             : }
     795             : 
     796             : /*
     797             :  * Cancel changes to the incore btree by detaching all the xfbtree buffers.
     798             :  * Changes are not written to the backing store.  This is needed for online
     799             :  * repair btrees, which are by nature ephemeral.
     800             :  */
     801             : void
     802           0 : xfbtree_trans_cancel(
     803             :         struct xfbtree          *xfbt,
     804             :         struct xfs_trans        *tp)
     805             : {
     806           0 :         struct xfs_log_item     *lip, *n;
     807           0 :         bool                    tp_dirty = false;
     808             : 
     809           0 :         list_for_each_entry_safe(lip, n, &tp->t_items, li_trans) {
     810           0 :                 struct xfs_buf  *bp = xfbtree_buf_match(xfbt, lip);
     811             : 
     812           0 :                 if (!bp) {
     813           0 :                         if (test_bit(XFS_LI_DIRTY, &lip->li_flags))
     814           0 :                                 tp_dirty |= true;
     815           0 :                         continue;
     816             :                 }
     817             : 
     818           0 :                 trace_xfbtree_trans_cancel_buf(xfbt, bp);
     819             : 
     820           0 :                 xfbtree_trans_bdetach(tp, bp);
     821           0 :                 xfs_buf_relse(bp);
     822             :         }
     823             : 
     824             :         /*
     825             :          * Reset the transaction's dirty flag to reflect the dirty state of the
     826             :          * log items that are still attached.
     827             :          */
     828           0 :         tp->t_flags = (tp->t_flags & ~XFS_TRANS_DIRTY) |
     829           0 :                         (tp_dirty ? XFS_TRANS_DIRTY : 0);
     830           0 : }

Generated by: LCOV version 1.14