1035e00acSDarrick J. Wong /* 2035e00acSDarrick J. Wong * Copyright (c) 2014 Red Hat, Inc. 3035e00acSDarrick J. Wong * All Rights Reserved. 4035e00acSDarrick J. Wong * 5035e00acSDarrick J. Wong * This program is free software; you can redistribute it and/or 6035e00acSDarrick J. Wong * modify it under the terms of the GNU General Public License as 7035e00acSDarrick J. Wong * published by the Free Software Foundation. 8035e00acSDarrick J. Wong * 9035e00acSDarrick J. Wong * This program is distributed in the hope that it would be useful, 10035e00acSDarrick J. Wong * but WITHOUT ANY WARRANTY; without even the implied warranty of 11035e00acSDarrick J. Wong * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12035e00acSDarrick J. Wong * GNU General Public License for more details. 13035e00acSDarrick J. Wong * 14035e00acSDarrick J. Wong * You should have received a copy of the GNU General Public License 15035e00acSDarrick J. Wong * along with this program; if not, write the Free Software Foundation, 16035e00acSDarrick J. Wong * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17035e00acSDarrick J. Wong */ 18035e00acSDarrick J. Wong #include "xfs.h" 19035e00acSDarrick J. Wong #include "xfs_fs.h" 20035e00acSDarrick J. Wong #include "xfs_shared.h" 21035e00acSDarrick J. Wong #include "xfs_format.h" 22035e00acSDarrick J. Wong #include "xfs_log_format.h" 23035e00acSDarrick J. Wong #include "xfs_trans_resv.h" 24035e00acSDarrick J. Wong #include "xfs_bit.h" 25035e00acSDarrick J. Wong #include "xfs_sb.h" 26035e00acSDarrick J. Wong #include "xfs_mount.h" 27035e00acSDarrick J. Wong #include "xfs_defer.h" 28035e00acSDarrick J. Wong #include "xfs_inode.h" 29035e00acSDarrick J. Wong #include "xfs_trans.h" 30035e00acSDarrick J. Wong #include "xfs_alloc.h" 31035e00acSDarrick J. Wong #include "xfs_btree.h" 32035e00acSDarrick J. Wong #include "xfs_rmap_btree.h" 33035e00acSDarrick J. Wong #include "xfs_trace.h" 34035e00acSDarrick J. Wong #include "xfs_cksum.h" 35035e00acSDarrick J. Wong #include "xfs_error.h" 36035e00acSDarrick J. Wong #include "xfs_extent_busy.h" 37035e00acSDarrick J. Wong 38035e00acSDarrick J. Wong static struct xfs_btree_cur * 39035e00acSDarrick J. Wong xfs_rmapbt_dup_cursor( 40035e00acSDarrick J. Wong struct xfs_btree_cur *cur) 41035e00acSDarrick J. Wong { 42035e00acSDarrick J. Wong return xfs_rmapbt_init_cursor(cur->bc_mp, cur->bc_tp, 43035e00acSDarrick J. Wong cur->bc_private.a.agbp, cur->bc_private.a.agno); 44035e00acSDarrick J. Wong } 45035e00acSDarrick J. Wong 46035e00acSDarrick J. Wong static bool 47035e00acSDarrick J. Wong xfs_rmapbt_verify( 48035e00acSDarrick J. Wong struct xfs_buf *bp) 49035e00acSDarrick J. Wong { 50035e00acSDarrick J. Wong struct xfs_mount *mp = bp->b_target->bt_mount; 51035e00acSDarrick J. Wong struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); 52035e00acSDarrick J. Wong struct xfs_perag *pag = bp->b_pag; 53035e00acSDarrick J. Wong unsigned int level; 54035e00acSDarrick J. Wong 55035e00acSDarrick J. Wong /* 56035e00acSDarrick J. Wong * magic number and level verification 57035e00acSDarrick J. Wong * 58035e00acSDarrick J. Wong * During growfs operations, we can't verify the exact level or owner as 59035e00acSDarrick J. Wong * the perag is not fully initialised and hence not attached to the 60035e00acSDarrick J. Wong * buffer. In this case, check against the maximum tree depth. 61035e00acSDarrick J. Wong * 62035e00acSDarrick J. Wong * Similarly, during log recovery we will have a perag structure 63035e00acSDarrick J. Wong * attached, but the agf information will not yet have been initialised 64035e00acSDarrick J. Wong * from the on disk AGF. Again, we can only check against maximum limits 65035e00acSDarrick J. Wong * in this case. 66035e00acSDarrick J. Wong */ 67035e00acSDarrick J. Wong if (block->bb_magic != cpu_to_be32(XFS_RMAP_CRC_MAGIC)) 68035e00acSDarrick J. Wong return false; 69035e00acSDarrick J. Wong 70035e00acSDarrick J. Wong if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) 71035e00acSDarrick J. Wong return false; 72035e00acSDarrick J. Wong if (!xfs_btree_sblock_v5hdr_verify(bp)) 73035e00acSDarrick J. Wong return false; 74035e00acSDarrick J. Wong 75035e00acSDarrick J. Wong level = be16_to_cpu(block->bb_level); 76035e00acSDarrick J. Wong if (pag && pag->pagf_init) { 77035e00acSDarrick J. Wong if (level >= pag->pagf_levels[XFS_BTNUM_RMAPi]) 78035e00acSDarrick J. Wong return false; 79035e00acSDarrick J. Wong } else if (level >= mp->m_rmap_maxlevels) 80035e00acSDarrick J. Wong return false; 81035e00acSDarrick J. Wong 82035e00acSDarrick J. Wong return xfs_btree_sblock_verify(bp, mp->m_rmap_mxr[level != 0]); 83035e00acSDarrick J. Wong } 84035e00acSDarrick J. Wong 85035e00acSDarrick J. Wong static void 86035e00acSDarrick J. Wong xfs_rmapbt_read_verify( 87035e00acSDarrick J. Wong struct xfs_buf *bp) 88035e00acSDarrick J. Wong { 89035e00acSDarrick J. Wong if (!xfs_btree_sblock_verify_crc(bp)) 90035e00acSDarrick J. Wong xfs_buf_ioerror(bp, -EFSBADCRC); 91035e00acSDarrick J. Wong else if (!xfs_rmapbt_verify(bp)) 92035e00acSDarrick J. Wong xfs_buf_ioerror(bp, -EFSCORRUPTED); 93035e00acSDarrick J. Wong 94035e00acSDarrick J. Wong if (bp->b_error) { 95035e00acSDarrick J. Wong trace_xfs_btree_corrupt(bp, _RET_IP_); 96035e00acSDarrick J. Wong xfs_verifier_error(bp); 97035e00acSDarrick J. Wong } 98035e00acSDarrick J. Wong } 99035e00acSDarrick J. Wong 100035e00acSDarrick J. Wong static void 101035e00acSDarrick J. Wong xfs_rmapbt_write_verify( 102035e00acSDarrick J. Wong struct xfs_buf *bp) 103035e00acSDarrick J. Wong { 104035e00acSDarrick J. Wong if (!xfs_rmapbt_verify(bp)) { 105035e00acSDarrick J. Wong trace_xfs_btree_corrupt(bp, _RET_IP_); 106035e00acSDarrick J. Wong xfs_buf_ioerror(bp, -EFSCORRUPTED); 107035e00acSDarrick J. Wong xfs_verifier_error(bp); 108035e00acSDarrick J. Wong return; 109035e00acSDarrick J. Wong } 110035e00acSDarrick J. Wong xfs_btree_sblock_calc_crc(bp); 111035e00acSDarrick J. Wong 112035e00acSDarrick J. Wong } 113035e00acSDarrick J. Wong 114035e00acSDarrick J. Wong const struct xfs_buf_ops xfs_rmapbt_buf_ops = { 115035e00acSDarrick J. Wong .name = "xfs_rmapbt", 116035e00acSDarrick J. Wong .verify_read = xfs_rmapbt_read_verify, 117035e00acSDarrick J. Wong .verify_write = xfs_rmapbt_write_verify, 118035e00acSDarrick J. Wong }; 119035e00acSDarrick J. Wong 120035e00acSDarrick J. Wong static const struct xfs_btree_ops xfs_rmapbt_ops = { 121035e00acSDarrick J. Wong .rec_len = sizeof(struct xfs_rmap_rec), 122035e00acSDarrick J. Wong .key_len = 2 * sizeof(struct xfs_rmap_key), 123035e00acSDarrick J. Wong 124035e00acSDarrick J. Wong .dup_cursor = xfs_rmapbt_dup_cursor, 125035e00acSDarrick J. Wong .buf_ops = &xfs_rmapbt_buf_ops, 126035e00acSDarrick J. Wong 127035e00acSDarrick J. Wong .get_leaf_keys = xfs_btree_get_leaf_keys_overlapped, 128035e00acSDarrick J. Wong .get_node_keys = xfs_btree_get_node_keys_overlapped, 129035e00acSDarrick J. Wong .update_keys = xfs_btree_update_keys_overlapped, 130035e00acSDarrick J. Wong }; 131035e00acSDarrick J. Wong 132035e00acSDarrick J. Wong /* 133035e00acSDarrick J. Wong * Allocate a new allocation btree cursor. 134035e00acSDarrick J. Wong */ 135035e00acSDarrick J. Wong struct xfs_btree_cur * 136035e00acSDarrick J. Wong xfs_rmapbt_init_cursor( 137035e00acSDarrick J. Wong struct xfs_mount *mp, 138035e00acSDarrick J. Wong struct xfs_trans *tp, 139035e00acSDarrick J. Wong struct xfs_buf *agbp, 140035e00acSDarrick J. Wong xfs_agnumber_t agno) 141035e00acSDarrick J. Wong { 142035e00acSDarrick J. Wong struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); 143035e00acSDarrick J. Wong struct xfs_btree_cur *cur; 144035e00acSDarrick J. Wong 145035e00acSDarrick J. Wong cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS); 146035e00acSDarrick J. Wong cur->bc_tp = tp; 147035e00acSDarrick J. Wong cur->bc_mp = mp; 148035e00acSDarrick J. Wong cur->bc_btnum = XFS_BTNUM_RMAP; 149035e00acSDarrick J. Wong cur->bc_flags = XFS_BTREE_CRC_BLOCKS; 150035e00acSDarrick J. Wong cur->bc_blocklog = mp->m_sb.sb_blocklog; 151035e00acSDarrick J. Wong cur->bc_ops = &xfs_rmapbt_ops; 152035e00acSDarrick J. Wong cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]); 153035e00acSDarrick J. Wong 154035e00acSDarrick J. Wong cur->bc_private.a.agbp = agbp; 155035e00acSDarrick J. Wong cur->bc_private.a.agno = agno; 156035e00acSDarrick J. Wong 157035e00acSDarrick J. Wong return cur; 158035e00acSDarrick J. Wong } 159035e00acSDarrick J. Wong 160035e00acSDarrick J. Wong /* 161035e00acSDarrick J. Wong * Calculate number of records in an rmap btree block. 162035e00acSDarrick J. Wong */ 163035e00acSDarrick J. Wong int 164035e00acSDarrick J. Wong xfs_rmapbt_maxrecs( 165035e00acSDarrick J. Wong struct xfs_mount *mp, 166035e00acSDarrick J. Wong int blocklen, 167035e00acSDarrick J. Wong int leaf) 168035e00acSDarrick J. Wong { 169035e00acSDarrick J. Wong blocklen -= XFS_RMAP_BLOCK_LEN; 170035e00acSDarrick J. Wong 171035e00acSDarrick J. Wong if (leaf) 172035e00acSDarrick J. Wong return blocklen / sizeof(struct xfs_rmap_rec); 173035e00acSDarrick J. Wong return blocklen / 174035e00acSDarrick J. Wong (sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t)); 175035e00acSDarrick J. Wong } 176035e00acSDarrick J. Wong 177035e00acSDarrick J. Wong /* Compute the maximum height of an rmap btree. */ 178035e00acSDarrick J. Wong void 179035e00acSDarrick J. Wong xfs_rmapbt_compute_maxlevels( 180035e00acSDarrick J. Wong struct xfs_mount *mp) 181035e00acSDarrick J. Wong { 182035e00acSDarrick J. Wong mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp, 183035e00acSDarrick J. Wong mp->m_rmap_mnr, mp->m_sb.sb_agblocks); 184035e00acSDarrick J. Wong } 185