xfs_types.c (6122B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. 4 * Copyright (C) 2017 Oracle. 5 * All Rights Reserved. 6 */ 7#include "xfs.h" 8#include "xfs_fs.h" 9#include "xfs_format.h" 10#include "xfs_shared.h" 11#include "xfs_trans_resv.h" 12#include "xfs_bit.h" 13#include "xfs_mount.h" 14#include "xfs_ag.h" 15 16/* Find the size of the AG, in blocks. */ 17inline xfs_agblock_t 18xfs_ag_block_count( 19 struct xfs_mount *mp, 20 xfs_agnumber_t agno) 21{ 22 ASSERT(agno < mp->m_sb.sb_agcount); 23 24 if (agno < mp->m_sb.sb_agcount - 1) 25 return mp->m_sb.sb_agblocks; 26 return mp->m_sb.sb_dblocks - (agno * mp->m_sb.sb_agblocks); 27} 28 29/* 30 * Verify that an AG block number pointer neither points outside the AG 31 * nor points at static metadata. 32 */ 33inline bool 34xfs_verify_agbno( 35 struct xfs_mount *mp, 36 xfs_agnumber_t agno, 37 xfs_agblock_t agbno) 38{ 39 xfs_agblock_t eoag; 40 41 eoag = xfs_ag_block_count(mp, agno); 42 if (agbno >= eoag) 43 return false; 44 if (agbno <= XFS_AGFL_BLOCK(mp)) 45 return false; 46 return true; 47} 48 49/* 50 * Verify that an FS block number pointer neither points outside the 51 * filesystem nor points at static AG metadata. 52 */ 53inline bool 54xfs_verify_fsbno( 55 struct xfs_mount *mp, 56 xfs_fsblock_t fsbno) 57{ 58 xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, fsbno); 59 60 if (agno >= mp->m_sb.sb_agcount) 61 return false; 62 return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno)); 63} 64 65/* 66 * Verify that a data device extent is fully contained inside the filesystem, 67 * does not cross an AG boundary, and does not point at static metadata. 68 */ 69bool 70xfs_verify_fsbext( 71 struct xfs_mount *mp, 72 xfs_fsblock_t fsbno, 73 xfs_fsblock_t len) 74{ 75 if (fsbno + len <= fsbno) 76 return false; 77 78 if (!xfs_verify_fsbno(mp, fsbno)) 79 return false; 80 81 if (!xfs_verify_fsbno(mp, fsbno + len - 1)) 82 return false; 83 84 return XFS_FSB_TO_AGNO(mp, fsbno) == 85 XFS_FSB_TO_AGNO(mp, fsbno + len - 1); 86} 87 88/* Calculate the first and last possible inode number in an AG. */ 89inline void 90xfs_agino_range( 91 struct xfs_mount *mp, 92 xfs_agnumber_t agno, 93 xfs_agino_t *first, 94 xfs_agino_t *last) 95{ 96 xfs_agblock_t bno; 97 xfs_agblock_t eoag; 98 99 eoag = xfs_ag_block_count(mp, agno); 100 101 /* 102 * Calculate the first inode, which will be in the first 103 * cluster-aligned block after the AGFL. 104 */ 105 bno = round_up(XFS_AGFL_BLOCK(mp) + 1, M_IGEO(mp)->cluster_align); 106 *first = XFS_AGB_TO_AGINO(mp, bno); 107 108 /* 109 * Calculate the last inode, which will be at the end of the 110 * last (aligned) cluster that can be allocated in the AG. 111 */ 112 bno = round_down(eoag, M_IGEO(mp)->cluster_align); 113 *last = XFS_AGB_TO_AGINO(mp, bno) - 1; 114} 115 116/* 117 * Verify that an AG inode number pointer neither points outside the AG 118 * nor points at static metadata. 119 */ 120inline bool 121xfs_verify_agino( 122 struct xfs_mount *mp, 123 xfs_agnumber_t agno, 124 xfs_agino_t agino) 125{ 126 xfs_agino_t first; 127 xfs_agino_t last; 128 129 xfs_agino_range(mp, agno, &first, &last); 130 return agino >= first && agino <= last; 131} 132 133/* 134 * Verify that an AG inode number pointer neither points outside the AG 135 * nor points at static metadata, or is NULLAGINO. 136 */ 137bool 138xfs_verify_agino_or_null( 139 struct xfs_mount *mp, 140 xfs_agnumber_t agno, 141 xfs_agino_t agino) 142{ 143 return agino == NULLAGINO || xfs_verify_agino(mp, agno, agino); 144} 145 146/* 147 * Verify that an FS inode number pointer neither points outside the 148 * filesystem nor points at static AG metadata. 149 */ 150inline bool 151xfs_verify_ino( 152 struct xfs_mount *mp, 153 xfs_ino_t ino) 154{ 155 xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ino); 156 xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino); 157 158 if (agno >= mp->m_sb.sb_agcount) 159 return false; 160 if (XFS_AGINO_TO_INO(mp, agno, agino) != ino) 161 return false; 162 return xfs_verify_agino(mp, agno, agino); 163} 164 165/* Is this an internal inode number? */ 166inline bool 167xfs_internal_inum( 168 struct xfs_mount *mp, 169 xfs_ino_t ino) 170{ 171 return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino || 172 (xfs_has_quota(mp) && 173 xfs_is_quota_inode(&mp->m_sb, ino)); 174} 175 176/* 177 * Verify that a directory entry's inode number doesn't point at an internal 178 * inode, empty space, or static AG metadata. 179 */ 180bool 181xfs_verify_dir_ino( 182 struct xfs_mount *mp, 183 xfs_ino_t ino) 184{ 185 if (xfs_internal_inum(mp, ino)) 186 return false; 187 return xfs_verify_ino(mp, ino); 188} 189 190/* 191 * Verify that an realtime block number pointer doesn't point off the 192 * end of the realtime device. 193 */ 194inline bool 195xfs_verify_rtbno( 196 struct xfs_mount *mp, 197 xfs_rtblock_t rtbno) 198{ 199 return rtbno < mp->m_sb.sb_rblocks; 200} 201 202/* Verify that a realtime device extent is fully contained inside the volume. */ 203bool 204xfs_verify_rtext( 205 struct xfs_mount *mp, 206 xfs_rtblock_t rtbno, 207 xfs_rtblock_t len) 208{ 209 if (rtbno + len <= rtbno) 210 return false; 211 212 if (!xfs_verify_rtbno(mp, rtbno)) 213 return false; 214 215 return xfs_verify_rtbno(mp, rtbno + len - 1); 216} 217 218/* Calculate the range of valid icount values. */ 219inline void 220xfs_icount_range( 221 struct xfs_mount *mp, 222 unsigned long long *min, 223 unsigned long long *max) 224{ 225 unsigned long long nr_inos = 0; 226 struct xfs_perag *pag; 227 xfs_agnumber_t agno; 228 229 /* root, rtbitmap, rtsum all live in the first chunk */ 230 *min = XFS_INODES_PER_CHUNK; 231 232 for_each_perag(mp, agno, pag) { 233 xfs_agino_t first, last; 234 235 xfs_agino_range(mp, agno, &first, &last); 236 nr_inos += last - first + 1; 237 } 238 *max = nr_inos; 239} 240 241/* Sanity-checking of inode counts. */ 242bool 243xfs_verify_icount( 244 struct xfs_mount *mp, 245 unsigned long long icount) 246{ 247 unsigned long long min, max; 248 249 xfs_icount_range(mp, &min, &max); 250 return icount >= min && icount <= max; 251} 252 253/* Sanity-checking of dir/attr block offsets. */ 254bool 255xfs_verify_dablk( 256 struct xfs_mount *mp, 257 xfs_fileoff_t dabno) 258{ 259 xfs_dablk_t max_dablk = -1U; 260 261 return dabno <= max_dablk; 262} 263 264/* Check that a file block offset does not exceed the maximum. */ 265bool 266xfs_verify_fileoff( 267 struct xfs_mount *mp, 268 xfs_fileoff_t off) 269{ 270 return off <= XFS_MAX_FILEOFF; 271} 272 273/* Check that a range of file block offsets do not exceed the maximum. */ 274bool 275xfs_verify_fileext( 276 struct xfs_mount *mp, 277 xfs_fileoff_t off, 278 xfs_fileoff_t len) 279{ 280 if (off + len <= off) 281 return false; 282 283 if (!xfs_verify_fileoff(mp, off)) 284 return false; 285 286 return xfs_verify_fileoff(mp, off + len - 1); 287}