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
  15/* Find the size of the AG, in blocks. */
  16xfs_agblock_t
  17xfs_ag_block_count(
  18        struct xfs_mount        *mp,
  19        xfs_agnumber_t          agno)
  20{
  21        ASSERT(agno < mp->m_sb.sb_agcount);
  22
  23        if (agno < mp->m_sb.sb_agcount - 1)
  24                return mp->m_sb.sb_agblocks;
  25        return mp->m_sb.sb_dblocks - (agno * mp->m_sb.sb_agblocks);
  26}
  27
  28/*
  29 * Verify that an AG block number pointer neither points outside the AG
  30 * nor points at static metadata.
  31 */
  32bool
  33xfs_verify_agbno(
  34        struct xfs_mount        *mp,
  35        xfs_agnumber_t          agno,
  36        xfs_agblock_t           agbno)
  37{
  38        xfs_agblock_t           eoag;
  39
  40        eoag = xfs_ag_block_count(mp, agno);
  41        if (agbno >= eoag)
  42                return false;
  43        if (agbno <= XFS_AGFL_BLOCK(mp))
  44                return false;
  45        return true;
  46}
  47
  48/*
  49 * Verify that an FS block number pointer neither points outside the
  50 * filesystem nor points at static AG metadata.
  51 */
  52bool
  53xfs_verify_fsbno(
  54        struct xfs_mount        *mp,
  55        xfs_fsblock_t           fsbno)
  56{
  57        xfs_agnumber_t          agno = XFS_FSB_TO_AGNO(mp, fsbno);
  58
  59        if (agno >= mp->m_sb.sb_agcount)
  60                return false;
  61        return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno));
  62}
  63
  64/* Calculate the first and last possible inode number in an AG. */
  65void
  66xfs_agino_range(
  67        struct xfs_mount        *mp,
  68        xfs_agnumber_t          agno,
  69        xfs_agino_t             *first,
  70        xfs_agino_t             *last)
  71{
  72        xfs_agblock_t           bno;
  73        xfs_agblock_t           eoag;
  74
  75        eoag = xfs_ag_block_count(mp, agno);
  76
  77        /*
  78         * Calculate the first inode, which will be in the first
  79         * cluster-aligned block after the AGFL.
  80         */
  81        bno = round_up(XFS_AGFL_BLOCK(mp) + 1, M_IGEO(mp)->cluster_align);
  82        *first = XFS_AGB_TO_AGINO(mp, bno);
  83
  84        /*
  85         * Calculate the last inode, which will be at the end of the
  86         * last (aligned) cluster that can be allocated in the AG.
  87         */
  88        bno = round_down(eoag, M_IGEO(mp)->cluster_align);
  89        *last = XFS_AGB_TO_AGINO(mp, bno) - 1;
  90}
  91
  92/*
  93 * Verify that an AG inode number pointer neither points outside the AG
  94 * nor points at static metadata.
  95 */
  96bool
  97xfs_verify_agino(
  98        struct xfs_mount        *mp,
  99        xfs_agnumber_t          agno,
 100        xfs_agino_t             agino)
 101{
 102        xfs_agino_t             first;
 103        xfs_agino_t             last;
 104
 105        xfs_agino_range(mp, agno, &first, &last);
 106        return agino >= first && agino <= last;
 107}
 108
 109/*
 110 * Verify that an AG inode number pointer neither points outside the AG
 111 * nor points at static metadata, or is NULLAGINO.
 112 */
 113bool
 114xfs_verify_agino_or_null(
 115        struct xfs_mount        *mp,
 116        xfs_agnumber_t          agno,
 117        xfs_agino_t             agino)
 118{
 119        return agino == NULLAGINO || xfs_verify_agino(mp, agno, agino);
 120}
 121
 122/*
 123 * Verify that an FS inode number pointer neither points outside the
 124 * filesystem nor points at static AG metadata.
 125 */
 126bool
 127xfs_verify_ino(
 128        struct xfs_mount        *mp,
 129        xfs_ino_t               ino)
 130{
 131        xfs_agnumber_t          agno = XFS_INO_TO_AGNO(mp, ino);
 132        xfs_agino_t             agino = XFS_INO_TO_AGINO(mp, ino);
 133
 134        if (agno >= mp->m_sb.sb_agcount)
 135                return false;
 136        if (XFS_AGINO_TO_INO(mp, agno, agino) != ino)
 137                return false;
 138        return xfs_verify_agino(mp, agno, agino);
 139}
 140
 141/* Is this an internal inode number? */
 142bool
 143xfs_internal_inum(
 144        struct xfs_mount        *mp,
 145        xfs_ino_t               ino)
 146{
 147        return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
 148                (xfs_sb_version_hasquota(&mp->m_sb) &&
 149                 xfs_is_quota_inode(&mp->m_sb, ino));
 150}
 151
 152/*
 153 * Verify that a directory entry's inode number doesn't point at an internal
 154 * inode, empty space, or static AG metadata.
 155 */
 156bool
 157xfs_verify_dir_ino(
 158        struct xfs_mount        *mp,
 159        xfs_ino_t               ino)
 160{
 161        if (xfs_internal_inum(mp, ino))
 162                return false;
 163        return xfs_verify_ino(mp, ino);
 164}
 165
 166/*
 167 * Verify that an realtime block number pointer doesn't point off the
 168 * end of the realtime device.
 169 */
 170bool
 171xfs_verify_rtbno(
 172        struct xfs_mount        *mp,
 173        xfs_rtblock_t           rtbno)
 174{
 175        return rtbno < mp->m_sb.sb_rblocks;
 176}
 177
 178/* Calculate the range of valid icount values. */
 179void
 180xfs_icount_range(
 181        struct xfs_mount        *mp,
 182        unsigned long long      *min,
 183        unsigned long long      *max)
 184{
 185        unsigned long long      nr_inos = 0;
 186        xfs_agnumber_t          agno;
 187
 188        /* root, rtbitmap, rtsum all live in the first chunk */
 189        *min = XFS_INODES_PER_CHUNK;
 190
 191        for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
 192                xfs_agino_t     first, last;
 193
 194                xfs_agino_range(mp, agno, &first, &last);
 195                nr_inos += last - first + 1;
 196        }
 197        *max = nr_inos;
 198}
 199
 200/* Sanity-checking of inode counts. */
 201bool
 202xfs_verify_icount(
 203        struct xfs_mount        *mp,
 204        unsigned long long      icount)
 205{
 206        unsigned long long      min, max;
 207
 208        xfs_icount_range(mp, &min, &max);
 209        return icount >= min && icount <= max;
 210}
 211
 212/* Sanity-checking of dir/attr block offsets. */
 213bool
 214xfs_verify_dablk(
 215        struct xfs_mount        *mp,
 216        xfs_fileoff_t           dabno)
 217{
 218        xfs_dablk_t             max_dablk = -1U;
 219
 220        return dabno <= max_dablk;
 221}
 222