linux/fs/xfs/libxfs/xfs_types.c
<<
>>
Prefs
   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}
 288