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-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 39 42 92.9 %
Date: 2023-07-31 20:08:34 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             : #define XFS_AGSTATE_NOALLOC             5
     135             : 
     136             : #define __XFS_AG_OPSTATE(name, NAME) \
     137             : static inline bool xfs_perag_ ## name (struct xfs_perag *pag) \
     138             : { \
     139             :         return test_bit(XFS_AGSTATE_ ## NAME, &pag->pag_opstate); \
     140             : }
     141             : 
     142  3376873444 : __XFS_AG_OPSTATE(initialised_agf, AGF_INIT)
     143  3356753130 : __XFS_AG_OPSTATE(initialised_agi, AGI_INIT)
     144   840635637 : __XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA)
     145   229565154 : __XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES)
     146   651392650 : __XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)
     147  1064864778 : __XFS_AG_OPSTATE(prohibits_alloc, NOALLOC)
     148             : 
     149             : int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount,
     150             :                         xfs_rfsblock_t dcount, xfs_agnumber_t *maxagi);
     151             : int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
     152             : void xfs_free_perag(struct xfs_mount *mp);
     153             : 
     154             : /* Passive AG references */
     155             : struct xfs_perag *xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno);
     156             : struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno,
     157             :                 unsigned int tag);
     158             : struct xfs_perag *xfs_perag_hold(struct xfs_perag *pag);
     159             : void xfs_perag_put(struct xfs_perag *pag);
     160             : 
     161             : 
     162             : /* Active AG references */
     163             : struct xfs_perag *xfs_perag_grab(struct xfs_mount *, xfs_agnumber_t);
     164             : struct xfs_perag *xfs_perag_grab_tag(struct xfs_mount *, xfs_agnumber_t,
     165             :                                    int tag);
     166             : void xfs_perag_rele(struct xfs_perag *pag);
     167             : 
     168             : /* Enable or disable allocation from an AG */
     169             : xfs_extlen_t xfs_ag_fdblocks(struct xfs_perag *pag);
     170             : int xfs_ag_set_noalloc(struct xfs_perag *pag);
     171             : void xfs_ag_clear_noalloc(struct xfs_perag *pag);
     172             : 
     173             : /*
     174             :  * Per-ag geometry infomation and validation
     175             :  */
     176             : xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
     177             : void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
     178             :                 xfs_agino_t *first, xfs_agino_t *last);
     179             : 
     180             : static inline bool
     181             : xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno)
     182             : {
     183 >66120*10^7 :         if (agbno >= pag->block_count)
     184             :                 return false;
     185 >68138*10^7 :         if (agbno <= pag->min_block)
     186           0 :                 return false;
     187             :         return true;
     188             : }
     189             : 
     190             : static inline bool
     191 >10988*10^7 : xfs_verify_agbext(
     192             :         struct xfs_perag        *pag,
     193             :         xfs_agblock_t           agbno,
     194             :         xfs_agblock_t           len)
     195             : {
     196 >10988*10^7 :         if (agbno + len <= agbno)
     197             :                 return false;
     198             : 
     199 >10988*10^7 :         if (!xfs_verify_agbno(pag, agbno))
     200             :                 return false;
     201             : 
     202 >10988*10^7 :         return xfs_verify_agbno(pag, agbno + len - 1);
     203             : }
     204             : 
     205             : /*
     206             :  * Verify that an AG inode number pointer neither points outside the AG
     207             :  * nor points at static metadata.
     208             :  */
     209             : static inline bool
     210             : xfs_verify_agino(struct xfs_perag *pag, xfs_agino_t agino)
     211             : {
     212 61483078051 :         if (agino < pag->agino_min)
     213             :                 return false;
     214 61595542714 :         if (agino > pag->agino_max)
     215           0 :                 return false;
     216             :         return true;
     217             : }
     218             : 
     219             : /*
     220             :  * Verify that an AG inode number pointer neither points outside the AG
     221             :  * nor points at static metadata, or is NULLAGINO.
     222             :  */
     223             : static inline bool
     224             : xfs_verify_agino_or_null(struct xfs_perag *pag, xfs_agino_t agino)
     225             : {
     226  2780668587 :         if (agino == NULLAGINO)
     227             :                 return true;
     228   193011833 :         return xfs_verify_agino(pag, agino);
     229             : }
     230             : 
     231             : static inline bool
     232     4190566 : xfs_ag_contains_log(struct xfs_mount *mp, xfs_agnumber_t agno)
     233             : {
     234     4190566 :         return mp->m_sb.sb_logstart > 0 &&
     235     2810202 :                agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
     236             : }
     237             : 
     238             : /*
     239             :  * Perag iteration APIs
     240             :  */
     241             : static inline struct xfs_perag *
     242    46343331 : xfs_perag_next(
     243             :         struct xfs_perag        *pag,
     244             :         xfs_agnumber_t          *agno,
     245             :         xfs_agnumber_t          end_agno)
     246             : {
     247    46343331 :         struct xfs_mount        *mp = pag->pag_mount;
     248             : 
     249    46343331 :         *agno = pag->pag_agno + 1;
     250    46343331 :         xfs_perag_rele(pag);
     251    46343331 :         while (*agno <= end_agno) {
     252    36409021 :                 pag = xfs_perag_grab(mp, *agno);
     253    36409326 :                 if (pag)
     254    36409326 :                         return pag;
     255           0 :                 (*agno)++;
     256             :         }
     257             :         return NULL;
     258             : }
     259             : 
     260             : #define for_each_perag_range(mp, agno, end_agno, pag) \
     261             :         for ((pag) = xfs_perag_grab((mp), (agno)); \
     262             :                 (pag) != NULL; \
     263             :                 (pag) = xfs_perag_next((pag), &(agno), (end_agno)))
     264             : 
     265             : #define for_each_perag_from(mp, agno, pag) \
     266             :         for_each_perag_range((mp), (agno), (mp)->m_sb.sb_agcount - 1, (pag))
     267             : 
     268             : #define for_each_perag(mp, agno, pag) \
     269             :         (agno) = 0; \
     270             :         for_each_perag_from((mp), (agno), (pag))
     271             : 
     272             : #define for_each_perag_tag(mp, agno, pag, tag) \
     273             :         for ((agno) = 0, (pag) = xfs_perag_grab_tag((mp), 0, (tag)); \
     274             :                 (pag) != NULL; \
     275             :                 (agno) = (pag)->pag_agno + 1, \
     276             :                 xfs_perag_rele(pag), \
     277             :                 (pag) = xfs_perag_grab_tag((mp), (agno), (tag)))
     278             : 
     279             : static inline struct xfs_perag *
     280   298348987 : xfs_perag_next_wrap(
     281             :         struct xfs_perag        *pag,
     282             :         xfs_agnumber_t          *agno,
     283             :         xfs_agnumber_t          stop_agno,
     284             :         xfs_agnumber_t          restart_agno,
     285             :         xfs_agnumber_t          wrap_agno)
     286             : {
     287   298348987 :         struct xfs_mount        *mp = pag->pag_mount;
     288             : 
     289   298348987 :         *agno = pag->pag_agno + 1;
     290   298348987 :         xfs_perag_rele(pag);
     291   298775151 :         while (*agno != stop_agno) {
     292   298474176 :                 if (*agno >= wrap_agno) {
     293    17892297 :                         if (restart_agno >= stop_agno)
     294             :                                 break;
     295     2334308 :                         *agno = restart_agno;
     296             :                 }
     297             : 
     298   282916187 :                 pag = xfs_perag_grab(mp, *agno);
     299   282919558 :                 if (pag)
     300   282493394 :                         return pag;
     301      426164 :                 (*agno)++;
     302             :         }
     303             :         return NULL;
     304             : }
     305             : 
     306             : /*
     307             :  * Iterate all AGs from start_agno through wrap_agno, then restart_agno through
     308             :  * (start_agno - 1).
     309             :  */
     310             : #define for_each_perag_wrap_range(mp, start_agno, restart_agno, wrap_agno, agno, pag) \
     311             :         for ((agno) = (start_agno), (pag) = xfs_perag_grab((mp), (agno)); \
     312             :                 (pag) != NULL; \
     313             :                 (pag) = xfs_perag_next_wrap((pag), &(agno), (start_agno), \
     314             :                                 (restart_agno), (wrap_agno)))
     315             : /*
     316             :  * Iterate all AGs from start_agno through wrap_agno, then 0 through
     317             :  * (start_agno - 1).
     318             :  */
     319             : #define for_each_perag_wrap_at(mp, start_agno, wrap_agno, agno, pag) \
     320             :         for_each_perag_wrap_range((mp), (start_agno), 0, (wrap_agno), (agno), (pag))
     321             : 
     322             : /*
     323             :  * Iterate all AGs from start_agno through to the end of the filesystem, then 0
     324             :  * through (start_agno - 1).
     325             :  */
     326             : #define for_each_perag_wrap(mp, start_agno, agno, pag) \
     327             :         for_each_perag_wrap_at((mp), (start_agno), (mp)->m_sb.sb_agcount, \
     328             :                                 (agno), (pag))
     329             : 
     330             : 
     331             : struct aghdr_init_data {
     332             :         /* per ag data */
     333             :         xfs_agblock_t           agno;           /* ag to init */
     334             :         xfs_extlen_t            agsize;         /* new AG size */
     335             :         struct list_head        buffer_list;    /* buffer writeback list */
     336             :         xfs_rfsblock_t          nfree;          /* cumulative new free space */
     337             : 
     338             :         /* per header data */
     339             :         xfs_daddr_t             daddr;          /* header location */
     340             :         size_t                  numblks;        /* size of header */
     341             :         const struct xfs_btree_ops *bc_ops;     /* btree ops */
     342             : };
     343             : 
     344             : int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id);
     345             : int xfs_ag_shrink_space(struct xfs_perag *pag, struct xfs_trans **tpp,
     346             :                         xfs_extlen_t delta);
     347             : int xfs_ag_extend_space(struct xfs_perag *pag, struct xfs_trans *tp,
     348             :                         xfs_extlen_t len);
     349             : int xfs_ag_get_geometry(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);
     350             : 
     351             : #endif /* __LIBXFS_AG_H */

Generated by: LCOV version 1.14