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