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-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 38 41 92.7 %
Date: 2023-07-31 20:08:12 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             : 
      84             : #ifdef CONFIG_XFS_ONLINE_REPAIR
      85             :         /*
      86             :          * Alternate btree heights so that online repair won't trip the write
      87             :          * verifiers while rebuilding the AG btrees.
      88             :          */
      89             :         uint8_t         pagf_alt_levels[XFS_BTNUM_AGF];
      90             :         uint8_t         pagf_alt_refcount_level;
      91             : #endif
      92             : 
      93             :         spinlock_t      pag_state_lock;
      94             : 
      95             :         spinlock_t      pagb_lock;      /* lock for pagb_tree */
      96             :         struct rb_root  pagb_tree;      /* ordered tree of busy extents */
      97             :         unsigned int    pagb_gen;       /* generation count for pagb_tree */
      98             :         wait_queue_head_t pagb_wait;    /* woken when pagb_gen changes */
      99             : 
     100             :         atomic_t        pagf_fstrms;    /* # of filestreams active in this AG */
     101             : 
     102             :         spinlock_t      pag_ici_lock;   /* incore inode cache lock */
     103             :         struct radix_tree_root pag_ici_root;    /* incore inode cache root */
     104             :         int             pag_ici_reclaimable;    /* reclaimable inodes */
     105             :         unsigned long   pag_ici_reclaim_cursor; /* reclaim restart point */
     106             : 
     107             :         struct xfs_buf_cache    pag_bcache;
     108             : 
     109             :         /* background prealloc block trimming */
     110             :         struct delayed_work     pag_blockgc_work;
     111             : 
     112             :         /*
     113             :          * We use xfs_drain to track the number of deferred log intent items
     114             :          * that have been queued (but not yet processed) so that waiters (e.g.
     115             :          * scrub) will not lock resources when other threads are in the middle
     116             :          * of processing a chain of intent items only to find momentary
     117             :          * inconsistencies.
     118             :          */
     119             :         struct xfs_defer_drain  pag_intents_drain;
     120             : 
     121             :         /* Hook to feed rmapbt updates to an active online repair. */
     122             :         struct xfs_hooks        pag_rmap_update_hooks;
     123             : #endif /* __KERNEL__ */
     124             : };
     125             : 
     126             : /*
     127             :  * Per-AG operational state. These are atomic flag bits.
     128             :  */
     129             : #define XFS_AGSTATE_AGF_INIT            0
     130             : #define XFS_AGSTATE_AGI_INIT            1
     131             : #define XFS_AGSTATE_PREFERS_METADATA    2
     132             : #define XFS_AGSTATE_ALLOWS_INODES       3
     133             : #define XFS_AGSTATE_AGFL_NEEDS_RESET    4
     134             : 
     135             : #define __XFS_AG_OPSTATE(name, NAME) \
     136             : static inline bool xfs_perag_ ## name (struct xfs_perag *pag) \
     137             : { \
     138             :         return test_bit(XFS_AGSTATE_ ## NAME, &pag->pag_opstate); \
     139             : }
     140             : 
     141  2418803306 : __XFS_AG_OPSTATE(initialised_agf, AGF_INIT)
     142  2691366478 : __XFS_AG_OPSTATE(initialised_agi, AGI_INIT)
     143   781421981 : __XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA)
     144   232156355 : __XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES)
     145   593438455 : __XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)
     146             : 
     147             : int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount,
     148             :                         xfs_rfsblock_t dcount, xfs_agnumber_t *maxagi);
     149             : int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
     150             : void xfs_free_perag(struct xfs_mount *mp);
     151             : 
     152             : /* Passive AG references */
     153             : struct xfs_perag *xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno);
     154             : struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno,
     155             :                 unsigned int tag);
     156             : struct xfs_perag *xfs_perag_hold(struct xfs_perag *pag);
     157             : void xfs_perag_put(struct xfs_perag *pag);
     158             : 
     159             : /* Active AG references */
     160             : struct xfs_perag *xfs_perag_grab(struct xfs_mount *, xfs_agnumber_t);
     161             : struct xfs_perag *xfs_perag_grab_tag(struct xfs_mount *, xfs_agnumber_t,
     162             :                                    int tag);
     163             : void xfs_perag_rele(struct xfs_perag *pag);
     164             : 
     165             : /*
     166             :  * Per-ag geometry infomation and validation
     167             :  */
     168             : xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
     169             : void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
     170             :                 xfs_agino_t *first, xfs_agino_t *last);
     171             : 
     172             : static inline bool
     173             : xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno)
     174             : {
     175 >59203*10^7 :         if (agbno >= pag->block_count)
     176             :                 return false;
     177 >61186*10^7 :         if (agbno <= pag->min_block)
     178           0 :                 return false;
     179             :         return true;
     180             : }
     181             : 
     182             : static inline bool
     183 99101619565 : xfs_verify_agbext(
     184             :         struct xfs_perag        *pag,
     185             :         xfs_agblock_t           agbno,
     186             :         xfs_agblock_t           len)
     187             : {
     188 99101619565 :         if (agbno + len <= agbno)
     189             :                 return false;
     190             : 
     191 99101619565 :         if (!xfs_verify_agbno(pag, agbno))
     192             :                 return false;
     193             : 
     194 99101619555 :         return xfs_verify_agbno(pag, agbno + len - 1);
     195             : }
     196             : 
     197             : /*
     198             :  * Verify that an AG inode number pointer neither points outside the AG
     199             :  * nor points at static metadata.
     200             :  */
     201             : static inline bool
     202             : xfs_verify_agino(struct xfs_perag *pag, xfs_agino_t agino)
     203             : {
     204 64682591074 :         if (agino < pag->agino_min)
     205             :                 return false;
     206 64813950549 :         if (agino > pag->agino_max)
     207           0 :                 return false;
     208             :         return true;
     209             : }
     210             : 
     211             : /*
     212             :  * Verify that an AG inode number pointer neither points outside the AG
     213             :  * nor points at static metadata, or is NULLAGINO.
     214             :  */
     215             : static inline bool
     216             : xfs_verify_agino_or_null(struct xfs_perag *pag, xfs_agino_t agino)
     217             : {
     218  2317784408 :         if (agino == NULLAGINO)
     219             :                 return true;
     220   225638478 :         return xfs_verify_agino(pag, agino);
     221             : }
     222             : 
     223             : static inline bool
     224     2914003 : xfs_ag_contains_log(struct xfs_mount *mp, xfs_agnumber_t agno)
     225             : {
     226     2914003 :         return mp->m_sb.sb_logstart > 0 &&
     227     2524707 :                agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
     228             : }
     229             : 
     230             : /*
     231             :  * Perag iteration APIs
     232             :  */
     233             : static inline struct xfs_perag *
     234    32558098 : xfs_perag_next(
     235             :         struct xfs_perag        *pag,
     236             :         xfs_agnumber_t          *agno,
     237             :         xfs_agnumber_t          end_agno)
     238             : {
     239    32558098 :         struct xfs_mount        *mp = pag->pag_mount;
     240             : 
     241    32558098 :         *agno = pag->pag_agno + 1;
     242    32558098 :         xfs_perag_rele(pag);
     243    32558098 :         while (*agno <= end_agno) {
     244    24528435 :                 pag = xfs_perag_grab(mp, *agno);
     245    24528009 :                 if (pag)
     246    24528009 :                         return pag;
     247           0 :                 (*agno)++;
     248             :         }
     249             :         return NULL;
     250             : }
     251             : 
     252             : #define for_each_perag_range(mp, agno, end_agno, pag) \
     253             :         for ((pag) = xfs_perag_grab((mp), (agno)); \
     254             :                 (pag) != NULL; \
     255             :                 (pag) = xfs_perag_next((pag), &(agno), (end_agno)))
     256             : 
     257             : #define for_each_perag_from(mp, agno, pag) \
     258             :         for_each_perag_range((mp), (agno), (mp)->m_sb.sb_agcount - 1, (pag))
     259             : 
     260             : #define for_each_perag(mp, agno, pag) \
     261             :         (agno) = 0; \
     262             :         for_each_perag_from((mp), (agno), (pag))
     263             : 
     264             : #define for_each_perag_tag(mp, agno, pag, tag) \
     265             :         for ((agno) = 0, (pag) = xfs_perag_grab_tag((mp), 0, (tag)); \
     266             :                 (pag) != NULL; \
     267             :                 (agno) = (pag)->pag_agno + 1, \
     268             :                 xfs_perag_rele(pag), \
     269             :                 (pag) = xfs_perag_grab_tag((mp), (agno), (tag)))
     270             : 
     271             : static inline struct xfs_perag *
     272   295408851 : xfs_perag_next_wrap(
     273             :         struct xfs_perag        *pag,
     274             :         xfs_agnumber_t          *agno,
     275             :         xfs_agnumber_t          stop_agno,
     276             :         xfs_agnumber_t          restart_agno,
     277             :         xfs_agnumber_t          wrap_agno)
     278             : {
     279   295408851 :         struct xfs_mount        *mp = pag->pag_mount;
     280             : 
     281   295408851 :         *agno = pag->pag_agno + 1;
     282   295408851 :         xfs_perag_rele(pag);
     283   296008689 :         while (*agno != stop_agno) {
     284   295915718 :                 if (*agno >= wrap_agno) {
     285    17394854 :                         if (restart_agno >= stop_agno)
     286             :                                 break;
     287     1903519 :                         *agno = restart_agno;
     288             :                 }
     289             : 
     290   280424383 :                 pag = xfs_perag_grab(mp, *agno);
     291   280698033 :                 if (pag)
     292   280098195 :                         return pag;
     293      599839 :                 (*agno)++;
     294             :         }
     295             :         return NULL;
     296             : }
     297             : 
     298             : /*
     299             :  * Iterate all AGs from start_agno through wrap_agno, then restart_agno through
     300             :  * (start_agno - 1).
     301             :  */
     302             : #define for_each_perag_wrap_range(mp, start_agno, restart_agno, wrap_agno, agno, pag) \
     303             :         for ((agno) = (start_agno), (pag) = xfs_perag_grab((mp), (agno)); \
     304             :                 (pag) != NULL; \
     305             :                 (pag) = xfs_perag_next_wrap((pag), &(agno), (start_agno), \
     306             :                                 (restart_agno), (wrap_agno)))
     307             : /*
     308             :  * Iterate all AGs from start_agno through wrap_agno, then 0 through
     309             :  * (start_agno - 1).
     310             :  */
     311             : #define for_each_perag_wrap_at(mp, start_agno, wrap_agno, agno, pag) \
     312             :         for_each_perag_wrap_range((mp), (start_agno), 0, (wrap_agno), (agno), (pag))
     313             : 
     314             : /*
     315             :  * Iterate all AGs from start_agno through to the end of the filesystem, then 0
     316             :  * through (start_agno - 1).
     317             :  */
     318             : #define for_each_perag_wrap(mp, start_agno, agno, pag) \
     319             :         for_each_perag_wrap_at((mp), (start_agno), (mp)->m_sb.sb_agcount, \
     320             :                                 (agno), (pag))
     321             : 
     322             : 
     323             : struct aghdr_init_data {
     324             :         /* per ag data */
     325             :         xfs_agblock_t           agno;           /* ag to init */
     326             :         xfs_extlen_t            agsize;         /* new AG size */
     327             :         struct list_head        buffer_list;    /* buffer writeback list */
     328             :         xfs_rfsblock_t          nfree;          /* cumulative new free space */
     329             : 
     330             :         /* per header data */
     331             :         xfs_daddr_t             daddr;          /* header location */
     332             :         size_t                  numblks;        /* size of header */
     333             :         const struct xfs_btree_ops *bc_ops;     /* btree ops */
     334             : };
     335             : 
     336             : int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id);
     337             : int xfs_ag_shrink_space(struct xfs_perag *pag, struct xfs_trans **tpp,
     338             :                         xfs_extlen_t delta);
     339             : int xfs_ag_extend_space(struct xfs_perag *pag, struct xfs_trans *tp,
     340             :                         xfs_extlen_t len);
     341             : int xfs_ag_get_geometry(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);
     342             : 
     343             : #endif /* __LIBXFS_AG_H */

Generated by: LCOV version 1.14