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

Generated by: LCOV version 1.14