LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_ag.h (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 38 41 92.7 %
Date: 2023-07-31 20:08:17 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 */
       2             : /*
       3             :  * Copyright (c) 2018 Red Hat, Inc.
       4             :  * All rights reserved.
       5             :  */
       6             : 
       7             : #ifndef __LIBXFS_AG_H
       8             : #define __LIBXFS_AG_H 1
       9             : 
      10             : struct xfs_mount;
      11             : struct xfs_trans;
      12             : struct xfs_perag;
      13             : 
      14             : /*
      15             :  * Per-ag infrastructure
      16             :  */
      17             : 
      18             : /* per-AG block reservation data structures*/
      19             : struct xfs_ag_resv {
      20             :         /* number of blocks originally reserved here */
      21             :         xfs_extlen_t                    ar_orig_reserved;
      22             :         /* number of blocks reserved here */
      23             :         xfs_extlen_t                    ar_reserved;
      24             :         /* number of blocks originally asked for */
      25             :         xfs_extlen_t                    ar_asked;
      26             : };
      27             : 
      28             : /*
      29             :  * Per-ag incore structure, copies of information in agf and agi, to improve the
      30             :  * performance of allocation group selection.
      31             :  */
      32             : struct xfs_perag {
      33             :         struct xfs_mount *pag_mount;    /* owner filesystem */
      34             :         xfs_agnumber_t  pag_agno;       /* AG this structure belongs to */
      35             :         atomic_t        pag_ref;        /* passive reference count */
      36             :         atomic_t        pag_active_ref; /* active reference count */
      37             :         wait_queue_head_t pag_active_wq;/* woken active_ref falls to zero */
      38             :         unsigned long   pag_opstate;
      39             :         uint8_t         pagf_levels[XFS_BTNUM_AGF];
      40             :                                         /* # of levels in bno & cnt btree */
      41             :         uint32_t        pagf_flcount;   /* count of blocks in freelist */
      42             :         xfs_extlen_t    pagf_freeblks;  /* total free blocks */
      43             :         xfs_extlen_t    pagf_longest;   /* longest free space */
      44             :         uint32_t        pagf_btreeblks; /* # of blocks held in AGF btrees */
      45             :         xfs_agino_t     pagi_freecount; /* number of free inodes */
      46             :         xfs_agino_t     pagi_count;     /* number of allocated inodes */
      47             : 
      48             :         /*
      49             :          * Inode allocation search lookup optimisation.
      50             :          * If the pagino matches, the search for new inodes
      51             :          * doesn't need to search the near ones again straight away
      52             :          */
      53             :         xfs_agino_t     pagl_pagino;
      54             :         xfs_agino_t     pagl_leftrec;
      55             :         xfs_agino_t     pagl_rightrec;
      56             : 
      57             :         int             pagb_count;     /* pagb slots in use */
      58             :         uint8_t         pagf_refcount_level; /* recount btree height */
      59             : 
      60             :         /* Blocks reserved for all kinds of metadata. */
      61             :         struct xfs_ag_resv      pag_meta_resv;
      62             :         /* Blocks reserved for the reverse mapping btree. */
      63             :         struct xfs_ag_resv      pag_rmapbt_resv;
      64             : 
      65             :         /* for rcu-safe freeing */
      66             :         struct rcu_head rcu_head;
      67             : 
      68             :         /* Precalculated geometry info */
      69             :         xfs_agblock_t           block_count;
      70             :         xfs_agblock_t           min_block;
      71             :         xfs_agino_t             agino_min;
      72             :         xfs_agino_t             agino_max;
      73             : 
      74             : #ifdef __KERNEL__
      75             :         /* -- kernel only structures below this line -- */
      76             : 
      77             :         /*
      78             :          * Bitsets of per-ag metadata that have been checked and/or are sick.
      79             :          * Callers should hold pag_state_lock before accessing this field.
      80             :          */
      81             :         uint16_t        pag_checked;
      82             :         uint16_t        pag_sick;
      83             :         spinlock_t      pag_state_lock;
      84             : 
      85             :         spinlock_t      pagb_lock;      /* lock for pagb_tree */
      86             :         struct rb_root  pagb_tree;      /* ordered tree of busy extents */
      87             :         unsigned int    pagb_gen;       /* generation count for pagb_tree */
      88             :         wait_queue_head_t pagb_wait;    /* woken when pagb_gen changes */
      89             : 
      90             :         atomic_t        pagf_fstrms;    /* # of filestreams active in this AG */
      91             : 
      92             :         spinlock_t      pag_ici_lock;   /* incore inode cache lock */
      93             :         struct radix_tree_root pag_ici_root;    /* incore inode cache root */
      94             :         int             pag_ici_reclaimable;    /* reclaimable inodes */
      95             :         unsigned long   pag_ici_reclaim_cursor; /* reclaim restart point */
      96             : 
      97             :         /* buffer cache index */
      98             :         spinlock_t      pag_buf_lock;   /* lock for pag_buf_hash */
      99             :         struct rhashtable pag_buf_hash;
     100             : 
     101             :         /* background prealloc block trimming */
     102             :         struct delayed_work     pag_blockgc_work;
     103             : 
     104             :         /*
     105             :          * We use xfs_drain to track the number of deferred log intent items
     106             :          * that have been queued (but not yet processed) so that waiters (e.g.
     107             :          * scrub) will not lock resources when other threads are in the middle
     108             :          * of processing a chain of intent items only to find momentary
     109             :          * inconsistencies.
     110             :          */
     111             :         struct xfs_defer_drain  pag_intents_drain;
     112             : #endif /* __KERNEL__ */
     113             : };
     114             : 
     115             : /*
     116             :  * Per-AG operational state. These are atomic flag bits.
     117             :  */
     118             : #define XFS_AGSTATE_AGF_INIT            0
     119             : #define XFS_AGSTATE_AGI_INIT            1
     120             : #define XFS_AGSTATE_PREFERS_METADATA    2
     121             : #define XFS_AGSTATE_ALLOWS_INODES       3
     122             : #define XFS_AGSTATE_AGFL_NEEDS_RESET    4
     123             : 
     124             : #define __XFS_AG_OPSTATE(name, NAME) \
     125             : static inline bool xfs_perag_ ## name (struct xfs_perag *pag) \
     126             : { \
     127             :         return test_bit(XFS_AGSTATE_ ## NAME, &pag->pag_opstate); \
     128             : }
     129             : 
     130  1546090776 : __XFS_AG_OPSTATE(initialised_agf, AGF_INIT)
     131  1447414641 : __XFS_AG_OPSTATE(initialised_agi, AGI_INIT)
     132   311320787 : __XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA)
     133    48973831 : __XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES)
     134   275565935 : __XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)
     135             : 
     136             : int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount,
     137             :                         xfs_rfsblock_t dcount, xfs_agnumber_t *maxagi);
     138             : int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
     139             : void xfs_free_perag(struct xfs_mount *mp);
     140             : 
     141             : /* Passive AG references */
     142             : struct xfs_perag *xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno);
     143             : struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno,
     144             :                 unsigned int tag);
     145             : struct xfs_perag *xfs_perag_hold(struct xfs_perag *pag);
     146             : void xfs_perag_put(struct xfs_perag *pag);
     147             : 
     148             : /* Active AG references */
     149             : struct xfs_perag *xfs_perag_grab(struct xfs_mount *, xfs_agnumber_t);
     150             : struct xfs_perag *xfs_perag_grab_tag(struct xfs_mount *, xfs_agnumber_t,
     151             :                                    int tag);
     152             : void xfs_perag_rele(struct xfs_perag *pag);
     153             : 
     154             : /*
     155             :  * Per-ag geometry infomation and validation
     156             :  */
     157             : xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
     158             : void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
     159             :                 xfs_agino_t *first, xfs_agino_t *last);
     160             : 
     161             : static inline bool
     162             : xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno)
     163             : {
     164 >34564*10^7 :         if (agbno >= pag->block_count)
     165             :                 return false;
     166 >35618*10^7 :         if (agbno <= pag->min_block)
     167           0 :                 return false;
     168             :         return true;
     169             : }
     170             : 
     171             : static inline bool
     172 59710798291 : xfs_verify_agbext(
     173             :         struct xfs_perag        *pag,
     174             :         xfs_agblock_t           agbno,
     175             :         xfs_agblock_t           len)
     176             : {
     177 59710798291 :         if (agbno + len <= agbno)
     178             :                 return false;
     179             : 
     180 59710798291 :         if (!xfs_verify_agbno(pag, agbno))
     181             :                 return false;
     182             : 
     183 59710798287 :         return xfs_verify_agbno(pag, agbno + len - 1);
     184             : }
     185             : 
     186             : /*
     187             :  * Verify that an AG inode number pointer neither points outside the AG
     188             :  * nor points at static metadata.
     189             :  */
     190             : static inline bool
     191             : xfs_verify_agino(struct xfs_perag *pag, xfs_agino_t agino)
     192             : {
     193 28758049890 :         if (agino < pag->agino_min)
     194             :                 return false;
     195 28805505638 :         if (agino > pag->agino_max)
     196           0 :                 return false;
     197             :         return true;
     198             : }
     199             : 
     200             : /*
     201             :  * Verify that an AG inode number pointer neither points outside the AG
     202             :  * nor points at static metadata, or is NULLAGINO.
     203             :  */
     204             : static inline bool
     205             : xfs_verify_agino_or_null(struct xfs_perag *pag, xfs_agino_t agino)
     206             : {
     207  1343284111 :         if (agino == NULLAGINO)
     208             :                 return true;
     209    76606865 :         return xfs_verify_agino(pag, agino);
     210             : }
     211             : 
     212             : static inline bool
     213     1222020 : xfs_ag_contains_log(struct xfs_mount *mp, xfs_agnumber_t agno)
     214             : {
     215     1222020 :         return mp->m_sb.sb_logstart > 0 &&
     216     1221976 :                agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
     217             : }
     218             : 
     219             : /*
     220             :  * Perag iteration APIs
     221             :  */
     222             : static inline struct xfs_perag *
     223    13545004 : xfs_perag_next(
     224             :         struct xfs_perag        *pag,
     225             :         xfs_agnumber_t          *agno,
     226             :         xfs_agnumber_t          end_agno)
     227             : {
     228    13545004 :         struct xfs_mount        *mp = pag->pag_mount;
     229             : 
     230    13545004 :         *agno = pag->pag_agno + 1;
     231    13545004 :         xfs_perag_rele(pag);
     232    13545004 :         while (*agno <= end_agno) {
     233     9189179 :                 pag = xfs_perag_grab(mp, *agno);
     234     9189179 :                 if (pag)
     235     9189179 :                         return pag;
     236           0 :                 (*agno)++;
     237             :         }
     238             :         return NULL;
     239             : }
     240             : 
     241             : #define for_each_perag_range(mp, agno, end_agno, pag) \
     242             :         for ((pag) = xfs_perag_grab((mp), (agno)); \
     243             :                 (pag) != NULL; \
     244             :                 (pag) = xfs_perag_next((pag), &(agno), (end_agno)))
     245             : 
     246             : #define for_each_perag_from(mp, agno, pag) \
     247             :         for_each_perag_range((mp), (agno), (mp)->m_sb.sb_agcount - 1, (pag))
     248             : 
     249             : #define for_each_perag(mp, agno, pag) \
     250             :         (agno) = 0; \
     251             :         for_each_perag_from((mp), (agno), (pag))
     252             : 
     253             : #define for_each_perag_tag(mp, agno, pag, tag) \
     254             :         for ((agno) = 0, (pag) = xfs_perag_grab_tag((mp), 0, (tag)); \
     255             :                 (pag) != NULL; \
     256             :                 (agno) = (pag)->pag_agno + 1, \
     257             :                 xfs_perag_rele(pag), \
     258             :                 (pag) = xfs_perag_grab_tag((mp), (agno), (tag)))
     259             : 
     260             : static inline struct xfs_perag *
     261    38144266 : xfs_perag_next_wrap(
     262             :         struct xfs_perag        *pag,
     263             :         xfs_agnumber_t          *agno,
     264             :         xfs_agnumber_t          stop_agno,
     265             :         xfs_agnumber_t          restart_agno,
     266             :         xfs_agnumber_t          wrap_agno)
     267             : {
     268    38144266 :         struct xfs_mount        *mp = pag->pag_mount;
     269             : 
     270    38144266 :         *agno = pag->pag_agno + 1;
     271    38144266 :         xfs_perag_rele(pag);
     272    38146609 :         while (*agno != stop_agno) {
     273    37873371 :                 if (*agno >= wrap_agno) {
     274      892420 :                         if (restart_agno >= stop_agno)
     275             :                                 break;
     276      777903 :                         *agno = restart_agno;
     277             :                 }
     278             : 
     279    37758854 :                 pag = xfs_perag_grab(mp, *agno);
     280    37758987 :                 if (pag)
     281    37756644 :                         return pag;
     282        2343 :                 (*agno)++;
     283             :         }
     284             :         return NULL;
     285             : }
     286             : 
     287             : /*
     288             :  * Iterate all AGs from start_agno through wrap_agno, then restart_agno through
     289             :  * (start_agno - 1).
     290             :  */
     291             : #define for_each_perag_wrap_range(mp, start_agno, restart_agno, wrap_agno, agno, pag) \
     292             :         for ((agno) = (start_agno), (pag) = xfs_perag_grab((mp), (agno)); \
     293             :                 (pag) != NULL; \
     294             :                 (pag) = xfs_perag_next_wrap((pag), &(agno), (start_agno), \
     295             :                                 (restart_agno), (wrap_agno)))
     296             : /*
     297             :  * Iterate all AGs from start_agno through wrap_agno, then 0 through
     298             :  * (start_agno - 1).
     299             :  */
     300             : #define for_each_perag_wrap_at(mp, start_agno, wrap_agno, agno, pag) \
     301             :         for_each_perag_wrap_range((mp), (start_agno), 0, (wrap_agno), (agno), (pag))
     302             : 
     303             : /*
     304             :  * Iterate all AGs from start_agno through to the end of the filesystem, then 0
     305             :  * through (start_agno - 1).
     306             :  */
     307             : #define for_each_perag_wrap(mp, start_agno, agno, pag) \
     308             :         for_each_perag_wrap_at((mp), (start_agno), (mp)->m_sb.sb_agcount, \
     309             :                                 (agno), (pag))
     310             : 
     311             : 
     312             : struct aghdr_init_data {
     313             :         /* per ag data */
     314             :         xfs_agblock_t           agno;           /* ag to init */
     315             :         xfs_extlen_t            agsize;         /* new AG size */
     316             :         struct list_head        buffer_list;    /* buffer writeback list */
     317             :         xfs_rfsblock_t          nfree;          /* cumulative new free space */
     318             : 
     319             :         /* per header data */
     320             :         xfs_daddr_t             daddr;          /* header location */
     321             :         size_t                  numblks;        /* size of header */
     322             :         xfs_btnum_t             type;           /* type of btree root block */
     323             : };
     324             : 
     325             : int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id);
     326             : int xfs_ag_shrink_space(struct xfs_perag *pag, struct xfs_trans **tpp,
     327             :                         xfs_extlen_t delta);
     328             : int xfs_ag_extend_space(struct xfs_perag *pag, struct xfs_trans *tp,
     329             :                         xfs_extlen_t len);
     330             : int xfs_ag_get_geometry(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);
     331             : 
     332             : #endif /* __LIBXFS_AG_H */

Generated by: LCOV version 1.14