Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
0004  * Copyright (C) 2017 Oracle.
0005  * All Rights Reserved.
0006  */
0007 #include "xfs.h"
0008 #include "xfs_fs.h"
0009 #include "xfs_format.h"
0010 #include "xfs_shared.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_bit.h"
0013 #include "xfs_mount.h"
0014 #include "xfs_ag.h"
0015 
0016 
0017 /*
0018  * Verify that an AG block number pointer neither points outside the AG
0019  * nor points at static metadata.
0020  */
0021 static inline bool
0022 xfs_verify_agno_agbno(
0023     struct xfs_mount    *mp,
0024     xfs_agnumber_t      agno,
0025     xfs_agblock_t       agbno)
0026 {
0027     xfs_agblock_t       eoag;
0028 
0029     eoag = xfs_ag_block_count(mp, agno);
0030     if (agbno >= eoag)
0031         return false;
0032     if (agbno <= XFS_AGFL_BLOCK(mp))
0033         return false;
0034     return true;
0035 }
0036 
0037 /*
0038  * Verify that an FS block number pointer neither points outside the
0039  * filesystem nor points at static AG metadata.
0040  */
0041 inline bool
0042 xfs_verify_fsbno(
0043     struct xfs_mount    *mp,
0044     xfs_fsblock_t       fsbno)
0045 {
0046     xfs_agnumber_t      agno = XFS_FSB_TO_AGNO(mp, fsbno);
0047 
0048     if (agno >= mp->m_sb.sb_agcount)
0049         return false;
0050     return xfs_verify_agno_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno));
0051 }
0052 
0053 /*
0054  * Verify that a data device extent is fully contained inside the filesystem,
0055  * does not cross an AG boundary, and does not point at static metadata.
0056  */
0057 bool
0058 xfs_verify_fsbext(
0059     struct xfs_mount    *mp,
0060     xfs_fsblock_t       fsbno,
0061     xfs_fsblock_t       len)
0062 {
0063     if (fsbno + len <= fsbno)
0064         return false;
0065 
0066     if (!xfs_verify_fsbno(mp, fsbno))
0067         return false;
0068 
0069     if (!xfs_verify_fsbno(mp, fsbno + len - 1))
0070         return false;
0071 
0072     return  XFS_FSB_TO_AGNO(mp, fsbno) ==
0073         XFS_FSB_TO_AGNO(mp, fsbno + len - 1);
0074 }
0075 
0076 /*
0077  * Verify that an AG inode number pointer neither points outside the AG
0078  * nor points at static metadata.
0079  */
0080 static inline bool
0081 xfs_verify_agno_agino(
0082     struct xfs_mount    *mp,
0083     xfs_agnumber_t      agno,
0084     xfs_agino_t     agino)
0085 {
0086     xfs_agino_t     first;
0087     xfs_agino_t     last;
0088 
0089     xfs_agino_range(mp, agno, &first, &last);
0090     return agino >= first && agino <= last;
0091 }
0092 
0093 /*
0094  * Verify that an FS inode number pointer neither points outside the
0095  * filesystem nor points at static AG metadata.
0096  */
0097 inline bool
0098 xfs_verify_ino(
0099     struct xfs_mount    *mp,
0100     xfs_ino_t       ino)
0101 {
0102     xfs_agnumber_t      agno = XFS_INO_TO_AGNO(mp, ino);
0103     xfs_agino_t     agino = XFS_INO_TO_AGINO(mp, ino);
0104 
0105     if (agno >= mp->m_sb.sb_agcount)
0106         return false;
0107     if (XFS_AGINO_TO_INO(mp, agno, agino) != ino)
0108         return false;
0109     return xfs_verify_agno_agino(mp, agno, agino);
0110 }
0111 
0112 /* Is this an internal inode number? */
0113 inline bool
0114 xfs_internal_inum(
0115     struct xfs_mount    *mp,
0116     xfs_ino_t       ino)
0117 {
0118     return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
0119         (xfs_has_quota(mp) &&
0120          xfs_is_quota_inode(&mp->m_sb, ino));
0121 }
0122 
0123 /*
0124  * Verify that a directory entry's inode number doesn't point at an internal
0125  * inode, empty space, or static AG metadata.
0126  */
0127 bool
0128 xfs_verify_dir_ino(
0129     struct xfs_mount    *mp,
0130     xfs_ino_t       ino)
0131 {
0132     if (xfs_internal_inum(mp, ino))
0133         return false;
0134     return xfs_verify_ino(mp, ino);
0135 }
0136 
0137 /*
0138  * Verify that an realtime block number pointer doesn't point off the
0139  * end of the realtime device.
0140  */
0141 inline bool
0142 xfs_verify_rtbno(
0143     struct xfs_mount    *mp,
0144     xfs_rtblock_t       rtbno)
0145 {
0146     return rtbno < mp->m_sb.sb_rblocks;
0147 }
0148 
0149 /* Verify that a realtime device extent is fully contained inside the volume. */
0150 bool
0151 xfs_verify_rtext(
0152     struct xfs_mount    *mp,
0153     xfs_rtblock_t       rtbno,
0154     xfs_rtblock_t       len)
0155 {
0156     if (rtbno + len <= rtbno)
0157         return false;
0158 
0159     if (!xfs_verify_rtbno(mp, rtbno))
0160         return false;
0161 
0162     return xfs_verify_rtbno(mp, rtbno + len - 1);
0163 }
0164 
0165 /* Calculate the range of valid icount values. */
0166 inline void
0167 xfs_icount_range(
0168     struct xfs_mount    *mp,
0169     unsigned long long  *min,
0170     unsigned long long  *max)
0171 {
0172     unsigned long long  nr_inos = 0;
0173     struct xfs_perag    *pag;
0174     xfs_agnumber_t      agno;
0175 
0176     /* root, rtbitmap, rtsum all live in the first chunk */
0177     *min = XFS_INODES_PER_CHUNK;
0178 
0179     for_each_perag(mp, agno, pag)
0180         nr_inos += pag->agino_max - pag->agino_min + 1;
0181     *max = nr_inos;
0182 }
0183 
0184 /* Sanity-checking of inode counts. */
0185 bool
0186 xfs_verify_icount(
0187     struct xfs_mount    *mp,
0188     unsigned long long  icount)
0189 {
0190     unsigned long long  min, max;
0191 
0192     xfs_icount_range(mp, &min, &max);
0193     return icount >= min && icount <= max;
0194 }
0195 
0196 /* Sanity-checking of dir/attr block offsets. */
0197 bool
0198 xfs_verify_dablk(
0199     struct xfs_mount    *mp,
0200     xfs_fileoff_t       dabno)
0201 {
0202     xfs_dablk_t     max_dablk = -1U;
0203 
0204     return dabno <= max_dablk;
0205 }
0206 
0207 /* Check that a file block offset does not exceed the maximum. */
0208 bool
0209 xfs_verify_fileoff(
0210     struct xfs_mount    *mp,
0211     xfs_fileoff_t       off)
0212 {
0213     return off <= XFS_MAX_FILEOFF;
0214 }
0215 
0216 /* Check that a range of file block offsets do not exceed the maximum. */
0217 bool
0218 xfs_verify_fileext(
0219     struct xfs_mount    *mp,
0220     xfs_fileoff_t       off,
0221     xfs_fileoff_t       len)
0222 {
0223     if (off + len <= off)
0224         return false;
0225 
0226     if (!xfs_verify_fileoff(mp, off))
0227         return false;
0228 
0229     return xfs_verify_fileoff(mp, off + len - 1);
0230 }