]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - libxfs/xfs_btree.c
xfs: remove unneeded parameter from XFS_TEST_ERROR
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_btree.c
index 5d48341a166b899bb3cac0b96ff62048d2216e29..1d39245086bbdd0ce8c1a2cfc7d307b19753ae28 100644 (file)
@@ -39,15 +39,25 @@ kmem_zone_t *xfs_btree_cur_zone;
 /*
  * Btree magic numbers.
  */
-static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = {
+static const uint32_t xfs_magics[2][XFS_BTNUM_MAX] = {
        { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, 0, XFS_BMAP_MAGIC, XFS_IBT_MAGIC,
          XFS_FIBT_MAGIC, 0 },
        { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, XFS_RMAP_CRC_MAGIC,
          XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC,
          XFS_REFC_CRC_MAGIC }
 };
-#define xfs_btree_magic(cur) \
-       xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum]
+
+uint32_t
+xfs_btree_magic(
+       int                     crc,
+       xfs_btnum_t             btnum)
+{
+       uint32_t                magic = xfs_magics[crc][btnum];
+
+       /* Ensure we asked for crc for crc-only magics. */
+       ASSERT(magic != 0);
+       return magic;
+}
 
 STATIC int                             /* error (0 or EFSCORRUPTED) */
 xfs_btree_check_lblock(
@@ -58,10 +68,13 @@ xfs_btree_check_lblock(
 {
        int                     lblock_ok = 1; /* block passes checks */
        struct xfs_mount        *mp;    /* file system mount point */
+       xfs_btnum_t             btnum = cur->bc_btnum;
+       int                     crc;
 
        mp = cur->bc_mp;
+       crc = xfs_sb_version_hascrc(&mp->m_sb);
 
-       if (xfs_sb_version_hascrc(&mp->m_sb)) {
+       if (crc) {
                lblock_ok = lblock_ok &&
                        uuid_equal(&block->bb_u.l.bb_uuid,
                                   &mp->m_sb.sb_meta_uuid) &&
@@ -70,7 +83,7 @@ xfs_btree_check_lblock(
        }
 
        lblock_ok = lblock_ok &&
-               be32_to_cpu(block->bb_magic) == xfs_btree_magic(cur) &&
+               be32_to_cpu(block->bb_magic) == xfs_btree_magic(crc, btnum) &&
                be16_to_cpu(block->bb_level) == level &&
                be16_to_cpu(block->bb_numrecs) <=
                        cur->bc_ops->get_maxrecs(cur, level) &&
@@ -84,8 +97,7 @@ xfs_btree_check_lblock(
                        be64_to_cpu(block->bb_u.l.bb_rightsib)));
 
        if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp,
-                       XFS_ERRTAG_BTREE_CHECK_LBLOCK,
-                       XFS_RANDOM_BTREE_CHECK_LBLOCK))) {
+                       XFS_ERRTAG_BTREE_CHECK_LBLOCK))) {
                if (bp)
                        trace_xfs_btree_corrupt(bp, _RET_IP_);
                XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
@@ -106,13 +118,16 @@ xfs_btree_check_sblock(
        struct xfs_agf          *agf;   /* ag. freespace structure */
        xfs_agblock_t           agflen; /* native ag. freespace length */
        int                     sblock_ok = 1; /* block passes checks */
+       xfs_btnum_t             btnum = cur->bc_btnum;
+       int                     crc;
 
        mp = cur->bc_mp;
+       crc = xfs_sb_version_hascrc(&mp->m_sb);
        agbp = cur->bc_private.a.agbp;
        agf = XFS_BUF_TO_AGF(agbp);
        agflen = be32_to_cpu(agf->agf_length);
 
-       if (xfs_sb_version_hascrc(&mp->m_sb)) {
+       if (crc) {
                sblock_ok = sblock_ok &&
                        uuid_equal(&block->bb_u.s.bb_uuid,
                                   &mp->m_sb.sb_meta_uuid) &&
@@ -121,7 +136,7 @@ xfs_btree_check_sblock(
        }
 
        sblock_ok = sblock_ok &&
-               be32_to_cpu(block->bb_magic) == xfs_btree_magic(cur) &&
+               be32_to_cpu(block->bb_magic) == xfs_btree_magic(crc, btnum) &&
                be16_to_cpu(block->bb_level) == level &&
                be16_to_cpu(block->bb_numrecs) <=
                        cur->bc_ops->get_maxrecs(cur, level) &&
@@ -133,8 +148,7 @@ xfs_btree_check_sblock(
                block->bb_u.s.bb_rightsib;
 
        if (unlikely(XFS_TEST_ERROR(!sblock_ok, mp,
-                       XFS_ERRTAG_BTREE_CHECK_SBLOCK,
-                       XFS_RANDOM_BTREE_CHECK_SBLOCK))) {
+                       XFS_ERRTAG_BTREE_CHECK_SBLOCK))) {
                if (bp)
                        trace_xfs_btree_corrupt(bp, _RET_IP_);
                XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
@@ -244,7 +258,7 @@ xfs_btree_lblock_verify_crc(
        struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
        struct xfs_mount        *mp = bp->b_target->bt_mount;
 
-       if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb)) {
+       if (xfs_sb_version_hascrc(&mp->m_sb)) {
                if (!xfs_log_check_lsn(mp, be64_to_cpu(block->bb_u.l.bb_lsn)))
                        return false;
                return xfs_buf_verify_cksum(bp, XFS_BTREE_LBLOCK_CRC_OFF);
@@ -282,7 +296,7 @@ xfs_btree_sblock_verify_crc(
        struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
        struct xfs_mount        *mp = bp->b_target->bt_mount;
 
-       if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb)) {
+       if (xfs_sb_version_hascrc(&mp->m_sb)) {
                if (!xfs_log_check_lsn(mp, be64_to_cpu(block->bb_u.s.bb_lsn)))
                        return false;
                return xfs_buf_verify_cksum(bp, XFS_BTREE_SBLOCK_CRC_OFF);
@@ -548,7 +562,7 @@ xfs_btree_ptr_offset(
 /*
  * Return a pointer to the n-th record in the btree block.
  */
-STATIC union xfs_btree_rec *
+union xfs_btree_rec *
 xfs_btree_rec_addr(
        struct xfs_btree_cur    *cur,
        int                     n,
@@ -561,7 +575,7 @@ xfs_btree_rec_addr(
 /*
  * Return a pointer to the n-th key in the btree block.
  */
-STATIC union xfs_btree_key *
+union xfs_btree_key *
 xfs_btree_key_addr(
        struct xfs_btree_cur    *cur,
        int                     n,
@@ -574,7 +588,7 @@ xfs_btree_key_addr(
 /*
  * Return a pointer to the n-th high key in the btree block.
  */
-STATIC union xfs_btree_key *
+union xfs_btree_key *
 xfs_btree_high_key_addr(
        struct xfs_btree_cur    *cur,
        int                     n,
@@ -587,7 +601,7 @@ xfs_btree_high_key_addr(
 /*
  * Return a pointer to the n-th block pointer in the btree block.
  */
-STATIC union xfs_btree_ptr *
+union xfs_btree_ptr *
 xfs_btree_ptr_addr(
        struct xfs_btree_cur    *cur,
        int                     n,
@@ -621,7 +635,7 @@ xfs_btree_get_iroot(
  * Retrieve the block pointer from the cursor at the given level.
  * This may be an inode btree root or from a buffer.
  */
-STATIC struct xfs_btree_block *                /* generic btree block pointer */
+struct xfs_btree_block *               /* generic btree block pointer */
 xfs_btree_get_block(
        struct xfs_btree_cur    *cur,   /* btree cursor */
        int                     level,  /* level in btree */
@@ -758,14 +772,14 @@ xfs_btree_lastrec(
  */
 void
 xfs_btree_offsets(
-       __int64_t       fields,         /* bitmask of fields */
+       int64_t         fields,         /* bitmask of fields */
        const short     *offsets,       /* table of field offsets */
        int             nbits,          /* number of bits to inspect */
        int             *first,         /* output: first byte offset */
        int             *last)          /* output: last byte offset */
 {
        int             i;              /* current bit number */
-       __int64_t       imask;          /* mask for current bit number */
+       int64_t         imask;          /* mask for current bit number */
 
        ASSERT(fields != 0);
        /*
@@ -806,7 +820,8 @@ xfs_btree_read_bufl(
        xfs_daddr_t             d;              /* real disk block address */
        int                     error;
 
-       ASSERT(fsbno != NULLFSBLOCK);
+       if (!XFS_FSB_SANITY_CHECK(mp, fsbno))
+               return -EFSCORRUPTED;
        d = XFS_FSB_TO_DADDR(mp, fsbno);
        error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
                                   mp->m_bsize, lock, &bp, ops);
@@ -1080,12 +1095,15 @@ xfs_btree_init_block_int(
        struct xfs_mount        *mp,
        struct xfs_btree_block  *buf,
        xfs_daddr_t             blkno,
-       __u32                   magic,
+       xfs_btnum_t             btnum,
        __u16                   level,
        __u16                   numrecs,
        __u64                   owner,
        unsigned int            flags)
 {
+       int                     crc = xfs_sb_version_hascrc(&mp->m_sb);
+       __u32                   magic = xfs_btree_magic(crc, btnum);
+
        buf->bb_magic = cpu_to_be32(magic);
        buf->bb_level = cpu_to_be16(level);
        buf->bb_numrecs = cpu_to_be16(numrecs);
@@ -1093,7 +1111,7 @@ xfs_btree_init_block_int(
        if (flags & XFS_BTREE_LONG_PTRS) {
                buf->bb_u.l.bb_leftsib = cpu_to_be64(NULLFSBLOCK);
                buf->bb_u.l.bb_rightsib = cpu_to_be64(NULLFSBLOCK);
-               if (flags & XFS_BTREE_CRC_BLOCKS) {
+               if (crc) {
                        buf->bb_u.l.bb_blkno = cpu_to_be64(blkno);
                        buf->bb_u.l.bb_owner = cpu_to_be64(owner);
                        uuid_copy(&buf->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid);
@@ -1106,7 +1124,7 @@ xfs_btree_init_block_int(
 
                buf->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
                buf->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
-               if (flags & XFS_BTREE_CRC_BLOCKS) {
+               if (crc) {
                        buf->bb_u.s.bb_blkno = cpu_to_be64(blkno);
                        buf->bb_u.s.bb_owner = cpu_to_be32(__owner);
                        uuid_copy(&buf->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid);
@@ -1119,14 +1137,14 @@ void
 xfs_btree_init_block(
        struct xfs_mount *mp,
        struct xfs_buf  *bp,
-       __u32           magic,
+       xfs_btnum_t     btnum,
        __u16           level,
        __u16           numrecs,
        __u64           owner,
        unsigned int    flags)
 {
        xfs_btree_init_block_int(mp, XFS_BUF_TO_BLOCK(bp), bp->b_bn,
-                                magic, level, numrecs, owner, flags);
+                                btnum, level, numrecs, owner, flags);
 }
 
 STATIC void
@@ -1136,7 +1154,7 @@ xfs_btree_init_block_cur(
        int                     level,
        int                     numrecs)
 {
-       __u64 owner;
+       __u64                   owner;
 
        /*
         * we can pull the owner from the cursor right now as the different
@@ -1150,7 +1168,7 @@ xfs_btree_init_block_cur(
                owner = cur->bc_private.a.agno;
 
        xfs_btree_init_block_int(cur->bc_mp, XFS_BUF_TO_BLOCK(bp), bp->b_bn,
-                                xfs_btree_magic(cur), level, numrecs,
+                                cur->bc_btnum, level, numrecs,
                                 owner, cur->bc_flags);
 }
 
@@ -1732,7 +1750,7 @@ error0:
        return error;
 }
 
-STATIC int
+int
 xfs_btree_lookup_get_block(
        struct xfs_btree_cur    *cur,   /* btree cursor */
        int                     level,  /* level in the btree */
@@ -1765,8 +1783,28 @@ xfs_btree_lookup_get_block(
        if (error)
                return error;
 
+       /* Check the inode owner since the verifiers don't. */
+       if (xfs_sb_version_hascrc(&cur->bc_mp->m_sb) &&
+           (cur->bc_flags & XFS_BTREE_LONG_PTRS) &&
+           be64_to_cpu((*blkp)->bb_u.l.bb_owner) !=
+                       cur->bc_private.b.ip->i_ino)
+               goto out_bad;
+
+       /* Did we get the level we were looking for? */
+       if (be16_to_cpu((*blkp)->bb_level) != level)
+               goto out_bad;
+
+       /* Check that internal nodes have at least one record. */
+       if (level != 0 && be16_to_cpu((*blkp)->bb_numrecs) == 0)
+               goto out_bad;
+
        xfs_btree_setbuf(cur, level, bp);
        return 0;
+
+out_bad:
+       *blkp = NULL;
+       xfs_trans_brelse(cur->bc_tp, bp);
+       return -EFSCORRUPTED;
 }
 
 /*
@@ -1802,7 +1840,7 @@ xfs_btree_lookup(
        int                     *stat)  /* success/failure */
 {
        struct xfs_btree_block  *block; /* current btree block */
-       __int64_t               diff;   /* difference for the current key */
+       int64_t                 diff;   /* difference for the current key */
        int                     error;  /* error return value */
        int                     keyno;  /* current key number */
        int                     level;  /* level in the btree */
@@ -2843,7 +2881,7 @@ xfs_btree_split_worker(
        struct xfs_btree_split_args     *args = container_of(work,
                                                struct xfs_btree_split_args, work);
        unsigned long           pflags;
-       unsigned long           new_pflags = PF_FSTRANS;
+       unsigned long           new_pflags = PF_MEMALLOC_NOFS;
 
        /*
         * we are in a transaction context here, but may also be doing work
@@ -4355,7 +4393,7 @@ xfs_btree_visit_blocks(
                        xfs_btree_readahead_ptr(cur, ptr, 1);
 
                        /* save for the next iteration of the loop */
-                       lptr = *ptr;
+                       xfs_btree_copy_ptrs(cur, &lptr, ptr, 1);
                }
 
                /* for each buffer in the level */
@@ -4395,7 +4433,7 @@ xfs_btree_visit_blocks(
  * recovery completion writes the changes to disk.
  */
 struct xfs_btree_block_change_owner_info {
-       __uint64_t              new_owner;
+       uint64_t                new_owner;
        struct list_head        *buffer_list;
 };
 
@@ -4441,7 +4479,7 @@ xfs_btree_block_change_owner(
 int
 xfs_btree_change_owner(
        struct xfs_btree_cur    *cur,
-       __uint64_t              new_owner,
+       uint64_t                new_owner,
        struct list_head        *buffer_list)
 {
        struct xfs_btree_block_change_owner_info        bbcoi;
@@ -4545,7 +4583,7 @@ xfs_btree_simple_query_range(
 {
        union xfs_btree_rec             *recp;
        union xfs_btree_key             rec_key;
-       __int64_t                       diff;
+       int64_t                         diff;
        int                             stat;
        bool                            firstrec = true;
        int                             error;
@@ -4642,8 +4680,8 @@ xfs_btree_overlapped_query_range(
        union xfs_btree_key             *hkp;
        union xfs_btree_rec             *recp;
        struct xfs_btree_block          *block;
-       __int64_t                       ldiff;
-       __int64_t                       hdiff;
+       int64_t                         ldiff;
+       int64_t                         hdiff;
        int                             level;
        struct xfs_buf                  *bp;
        int                             i;
@@ -4802,6 +4840,23 @@ xfs_btree_query_range(
                        fn, priv);
 }
 
+/* Query a btree for all records. */
+int
+xfs_btree_query_all(
+       struct xfs_btree_cur            *cur,
+       xfs_btree_query_range_fn        fn,
+       void                            *priv)
+{
+       union xfs_btree_key             low_key;
+       union xfs_btree_key             high_key;
+
+       memset(&cur->bc_rec, 0, sizeof(cur->bc_rec));
+       memset(&low_key, 0, sizeof(low_key));
+       memset(&high_key, 0xFF, sizeof(high_key));
+
+       return xfs_btree_simple_query_range(cur, &low_key, &high_key, fn, priv);
+}
+
 /*
  * Calculate the number of blocks needed to store a given number of records
  * in a short-format (per-AG metadata) btree.
@@ -4826,7 +4881,7 @@ xfs_btree_calc_size(
        return rval;
 }
 
-int
+static int
 xfs_btree_count_blocks_helper(
        struct xfs_btree_cur    *cur,
        int                     level,