Merge tag 'riscv-for-linus-4.16-merge_window' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-microblaze.git] / fs / xfs / libxfs / xfs_btree.c
index 5f33adf..79ee4a1 100644 (file)
@@ -273,7 +273,7 @@ xfs_btree_lblock_calc_crc(
        struct xfs_buf          *bp)
 {
        struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
-       struct xfs_buf_log_item *bip = bp->b_fspriv;
+       struct xfs_buf_log_item *bip = bp->b_log_item;
 
        if (!xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb))
                return;
@@ -311,7 +311,7 @@ xfs_btree_sblock_calc_crc(
        struct xfs_buf          *bp)
 {
        struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
-       struct xfs_buf_log_item *bip = bp->b_fspriv;
+       struct xfs_buf_log_item *bip = bp->b_log_item;
 
        if (!xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb))
                return;
@@ -329,7 +329,7 @@ xfs_btree_sblock_verify_crc(
 
        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 __this_address;
                return xfs_buf_verify_cksum(bp, XFS_BTREE_SBLOCK_CRC_OFF);
        }
 
@@ -853,7 +853,7 @@ xfs_btree_read_bufl(
        xfs_daddr_t             d;              /* real disk block address */
        int                     error;
 
-       if (!XFS_FSB_SANITY_CHECK(mp, fsbno))
+       if (!xfs_verify_fsbno(mp, fsbno))
                return -EFSCORRUPTED;
        d = XFS_FSB_TO_DADDR(mp, fsbno);
        error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
@@ -4529,6 +4529,51 @@ xfs_btree_change_owner(
                        &bbcoi);
 }
 
+/* Verify the v5 fields of a long-format btree block. */
+xfs_failaddr_t
+xfs_btree_lblock_v5hdr_verify(
+       struct xfs_buf          *bp,
+       uint64_t                owner)
+{
+       struct xfs_mount        *mp = bp->b_target->bt_mount;
+       struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
+
+       if (!xfs_sb_version_hascrc(&mp->m_sb))
+               return __this_address;
+       if (!uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid))
+               return __this_address;
+       if (block->bb_u.l.bb_blkno != cpu_to_be64(bp->b_bn))
+               return __this_address;
+       if (owner != XFS_RMAP_OWN_UNKNOWN &&
+           be64_to_cpu(block->bb_u.l.bb_owner) != owner)
+               return __this_address;
+       return NULL;
+}
+
+/* Verify a long-format btree block. */
+xfs_failaddr_t
+xfs_btree_lblock_verify(
+       struct xfs_buf          *bp,
+       unsigned int            max_recs)
+{
+       struct xfs_mount        *mp = bp->b_target->bt_mount;
+       struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
+
+       /* numrecs verification */
+       if (be16_to_cpu(block->bb_numrecs) > max_recs)
+               return __this_address;
+
+       /* sibling pointer verification */
+       if (block->bb_u.l.bb_leftsib != cpu_to_be64(NULLFSBLOCK) &&
+           !xfs_verify_fsbno(mp, be64_to_cpu(block->bb_u.l.bb_leftsib)))
+               return __this_address;
+       if (block->bb_u.l.bb_rightsib != cpu_to_be64(NULLFSBLOCK) &&
+           !xfs_verify_fsbno(mp, be64_to_cpu(block->bb_u.l.bb_rightsib)))
+               return __this_address;
+
+       return NULL;
+}
+
 /**
  * xfs_btree_sblock_v5hdr_verify() -- verify the v5 fields of a short-format
  *                                   btree block
@@ -4537,7 +4582,7 @@ xfs_btree_change_owner(
  * @max_recs: pointer to the m_*_mxr max records field in the xfs mount
  * @pag_max_level: pointer to the per-ag max level field
  */
-bool
+xfs_failaddr_t
 xfs_btree_sblock_v5hdr_verify(
        struct xfs_buf          *bp)
 {
@@ -4546,14 +4591,14 @@ xfs_btree_sblock_v5hdr_verify(
        struct xfs_perag        *pag = bp->b_pag;
 
        if (!xfs_sb_version_hascrc(&mp->m_sb))
-               return false;
+               return __this_address;
        if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid))
-               return false;
+               return __this_address;
        if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn))
-               return false;
+               return __this_address;
        if (pag && be32_to_cpu(block->bb_u.s.bb_owner) != pag->pag_agno)
-               return false;
-       return true;
+               return __this_address;
+       return NULL;
 }
 
 /**
@@ -4562,29 +4607,29 @@ xfs_btree_sblock_v5hdr_verify(
  * @bp: buffer containing the btree block
  * @max_recs: maximum records allowed in this btree node
  */
-bool
+xfs_failaddr_t
 xfs_btree_sblock_verify(
        struct xfs_buf          *bp,
        unsigned int            max_recs)
 {
        struct xfs_mount        *mp = bp->b_target->bt_mount;
        struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
+       xfs_agblock_t           agno;
 
        /* numrecs verification */
        if (be16_to_cpu(block->bb_numrecs) > max_recs)
-               return false;
+               return __this_address;
 
        /* sibling pointer verification */
-       if (!block->bb_u.s.bb_leftsib ||
-           (be32_to_cpu(block->bb_u.s.bb_leftsib) >= mp->m_sb.sb_agblocks &&
-            block->bb_u.s.bb_leftsib != cpu_to_be32(NULLAGBLOCK)))
-               return false;
-       if (!block->bb_u.s.bb_rightsib ||
-           (be32_to_cpu(block->bb_u.s.bb_rightsib) >= mp->m_sb.sb_agblocks &&
-            block->bb_u.s.bb_rightsib != cpu_to_be32(NULLAGBLOCK)))
-               return false;
+       agno = xfs_daddr_to_agno(mp, XFS_BUF_ADDR(bp));
+       if (block->bb_u.s.bb_leftsib != cpu_to_be32(NULLAGBLOCK) &&
+           !xfs_verify_agbno(mp, agno, be32_to_cpu(block->bb_u.s.bb_leftsib)))
+               return __this_address;
+       if (block->bb_u.s.bb_rightsib != cpu_to_be32(NULLAGBLOCK) &&
+           !xfs_verify_agbno(mp, agno, be32_to_cpu(block->bb_u.s.bb_rightsib)))
+               return __this_address;
 
-       return true;
+       return NULL;
 }
 
 /*
@@ -4953,3 +4998,33 @@ xfs_btree_diff_two_ptrs(
                return (int64_t)be64_to_cpu(a->l) - be64_to_cpu(b->l);
        return (int64_t)be32_to_cpu(a->s) - be32_to_cpu(b->s);
 }
+
+/* If there's an extent, we're done. */
+STATIC int
+xfs_btree_has_record_helper(
+       struct xfs_btree_cur            *cur,
+       union xfs_btree_rec             *rec,
+       void                            *priv)
+{
+       return XFS_BTREE_QUERY_RANGE_ABORT;
+}
+
+/* Is there a record covering a given range of keys? */
+int
+xfs_btree_has_record(
+       struct xfs_btree_cur    *cur,
+       union xfs_btree_irec    *low,
+       union xfs_btree_irec    *high,
+       bool                    *exists)
+{
+       int                     error;
+
+       error = xfs_btree_query_range(cur, low, high,
+                       &xfs_btree_has_record_helper, NULL);
+       if (error == XFS_BTREE_QUERY_RANGE_ABORT) {
+               *exists = true;
+               return 0;
+       }
+       *exists = false;
+       return error;
+}