cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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}