1b16817b6SDave Chinner /* SPDX-License-Identifier: GPL-2.0 */
2b16817b6SDave Chinner /*
3b16817b6SDave Chinner * Copyright (c) 2018 Red Hat, Inc.
4b16817b6SDave Chinner * All rights reserved.
5b16817b6SDave Chinner */
6b16817b6SDave Chinner
7b16817b6SDave Chinner #ifndef __LIBXFS_AG_H
8b16817b6SDave Chinner #define __LIBXFS_AG_H 1
9b16817b6SDave Chinner
1049dd56f2SDave Chinner struct xfs_mount;
1149dd56f2SDave Chinner struct xfs_trans;
129bbafc71SDave Chinner struct xfs_perag;
139bbafc71SDave Chinner
149bbafc71SDave Chinner /*
1507b6403aSDave Chinner * Per-ag infrastructure
169bbafc71SDave Chinner */
1707b6403aSDave Chinner
1807b6403aSDave Chinner /* per-AG block reservation data structures*/
1907b6403aSDave Chinner struct xfs_ag_resv {
2007b6403aSDave Chinner /* number of blocks originally reserved here */
2107b6403aSDave Chinner xfs_extlen_t ar_orig_reserved;
2207b6403aSDave Chinner /* number of blocks reserved here */
2307b6403aSDave Chinner xfs_extlen_t ar_reserved;
2407b6403aSDave Chinner /* number of blocks originally asked for */
2507b6403aSDave Chinner xfs_extlen_t ar_asked;
2607b6403aSDave Chinner };
2707b6403aSDave Chinner
2807b6403aSDave Chinner /*
2907b6403aSDave Chinner * Per-ag incore structure, copies of information in agf and agi, to improve the
3007b6403aSDave Chinner * performance of allocation group selection.
3107b6403aSDave Chinner */
3250920116SDave Chinner struct xfs_perag {
3307b6403aSDave Chinner struct xfs_mount *pag_mount; /* owner filesystem */
3407b6403aSDave Chinner xfs_agnumber_t pag_agno; /* AG this structure belongs to */
35c4d5660aSDave Chinner atomic_t pag_ref; /* passive reference count */
36c4d5660aSDave Chinner atomic_t pag_active_ref; /* active reference count */
37c4d5660aSDave Chinner wait_queue_head_t pag_active_wq;/* woken active_ref falls to zero */
387ac2ff8bSDave Chinner unsigned long pag_opstate;
3907b6403aSDave Chinner uint8_t pagf_levels[XFS_BTNUM_AGF];
4007b6403aSDave Chinner /* # of levels in bno & cnt btree */
4107b6403aSDave Chinner uint32_t pagf_flcount; /* count of blocks in freelist */
4207b6403aSDave Chinner xfs_extlen_t pagf_freeblks; /* total free blocks */
4307b6403aSDave Chinner xfs_extlen_t pagf_longest; /* longest free space */
4407b6403aSDave Chinner uint32_t pagf_btreeblks; /* # of blocks held in AGF btrees */
4507b6403aSDave Chinner xfs_agino_t pagi_freecount; /* number of free inodes */
4607b6403aSDave Chinner xfs_agino_t pagi_count; /* number of allocated inodes */
4707b6403aSDave Chinner
4807b6403aSDave Chinner /*
4907b6403aSDave Chinner * Inode allocation search lookup optimisation.
5007b6403aSDave Chinner * If the pagino matches, the search for new inodes
5107b6403aSDave Chinner * doesn't need to search the near ones again straight away
5207b6403aSDave Chinner */
5307b6403aSDave Chinner xfs_agino_t pagl_pagino;
5407b6403aSDave Chinner xfs_agino_t pagl_leftrec;
5507b6403aSDave Chinner xfs_agino_t pagl_rightrec;
5607b6403aSDave Chinner
5707b6403aSDave Chinner int pagb_count; /* pagb slots in use */
5807b6403aSDave Chinner uint8_t pagf_refcount_level; /* recount btree height */
5907b6403aSDave Chinner
6007b6403aSDave Chinner /* Blocks reserved for all kinds of metadata. */
6107b6403aSDave Chinner struct xfs_ag_resv pag_meta_resv;
6207b6403aSDave Chinner /* Blocks reserved for the reverse mapping btree. */
6307b6403aSDave Chinner struct xfs_ag_resv pag_rmapbt_resv;
6407b6403aSDave Chinner
6529f11fceSEric Sandeen /* for rcu-safe freeing */
6629f11fceSEric Sandeen struct rcu_head rcu_head;
6729f11fceSEric Sandeen
680800169eSDave Chinner /* Precalculated geometry info */
690800169eSDave Chinner xfs_agblock_t block_count;
700800169eSDave Chinner xfs_agblock_t min_block;
712d6ca832SDave Chinner xfs_agino_t agino_min;
722d6ca832SDave Chinner xfs_agino_t agino_max;
730800169eSDave Chinner
7429f11fceSEric Sandeen #ifdef __KERNEL__
7507b6403aSDave Chinner /* -- kernel only structures below this line -- */
7607b6403aSDave Chinner
7707b6403aSDave Chinner /*
7807b6403aSDave Chinner * Bitsets of per-ag metadata that have been checked and/or are sick.
7907b6403aSDave Chinner * Callers should hold pag_state_lock before accessing this field.
8007b6403aSDave Chinner */
8107b6403aSDave Chinner uint16_t pag_checked;
8207b6403aSDave Chinner uint16_t pag_sick;
8307b6403aSDave Chinner spinlock_t pag_state_lock;
8407b6403aSDave Chinner
8507b6403aSDave Chinner spinlock_t pagb_lock; /* lock for pagb_tree */
8607b6403aSDave Chinner struct rb_root pagb_tree; /* ordered tree of busy extents */
8707b6403aSDave Chinner unsigned int pagb_gen; /* generation count for pagb_tree */
8807b6403aSDave Chinner wait_queue_head_t pagb_wait; /* woken when pagb_gen changes */
8907b6403aSDave Chinner
9007b6403aSDave Chinner atomic_t pagf_fstrms; /* # of filestreams active in this AG */
9107b6403aSDave Chinner
9207b6403aSDave Chinner spinlock_t pag_ici_lock; /* incore inode cache lock */
9307b6403aSDave Chinner struct radix_tree_root pag_ici_root; /* incore inode cache root */
9407b6403aSDave Chinner int pag_ici_reclaimable; /* reclaimable inodes */
9507b6403aSDave Chinner unsigned long pag_ici_reclaim_cursor; /* reclaim restart point */
9607b6403aSDave Chinner
9707b6403aSDave Chinner /* buffer cache index */
9807b6403aSDave Chinner spinlock_t pag_buf_lock; /* lock for pag_buf_hash */
9907b6403aSDave Chinner struct rhashtable pag_buf_hash;
10007b6403aSDave Chinner
10107b6403aSDave Chinner /* background prealloc block trimming */
10207b6403aSDave Chinner struct delayed_work pag_blockgc_work;
10307b6403aSDave Chinner
104d5c88131SDarrick J. Wong /*
105d5c88131SDarrick J. Wong * We use xfs_drain to track the number of deferred log intent items
106d5c88131SDarrick J. Wong * that have been queued (but not yet processed) so that waiters (e.g.
107d5c88131SDarrick J. Wong * scrub) will not lock resources when other threads are in the middle
108d5c88131SDarrick J. Wong * of processing a chain of intent items only to find momentary
109d5c88131SDarrick J. Wong * inconsistencies.
110d5c88131SDarrick J. Wong */
111d5c88131SDarrick J. Wong struct xfs_defer_drain pag_intents_drain;
11229f11fceSEric Sandeen #endif /* __KERNEL__ */
11350920116SDave Chinner };
11407b6403aSDave Chinner
1157ac2ff8bSDave Chinner /*
1167ac2ff8bSDave Chinner * Per-AG operational state. These are atomic flag bits.
1177ac2ff8bSDave Chinner */
1187ac2ff8bSDave Chinner #define XFS_AGSTATE_AGF_INIT 0
1197ac2ff8bSDave Chinner #define XFS_AGSTATE_AGI_INIT 1
1207ac2ff8bSDave Chinner #define XFS_AGSTATE_PREFERS_METADATA 2
1217ac2ff8bSDave Chinner #define XFS_AGSTATE_ALLOWS_INODES 3
1227ac2ff8bSDave Chinner #define XFS_AGSTATE_AGFL_NEEDS_RESET 4
1237ac2ff8bSDave Chinner
1247ac2ff8bSDave Chinner #define __XFS_AG_OPSTATE(name, NAME) \
1257ac2ff8bSDave Chinner static inline bool xfs_perag_ ## name (struct xfs_perag *pag) \
1267ac2ff8bSDave Chinner { \
1277ac2ff8bSDave Chinner return test_bit(XFS_AGSTATE_ ## NAME, &pag->pag_opstate); \
1287ac2ff8bSDave Chinner }
1297ac2ff8bSDave Chinner
1307ac2ff8bSDave Chinner __XFS_AG_OPSTATE(initialised_agf, AGF_INIT)
1317ac2ff8bSDave Chinner __XFS_AG_OPSTATE(initialised_agi, AGI_INIT)
1327ac2ff8bSDave Chinner __XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA)
1337ac2ff8bSDave Chinner __XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES)
1347ac2ff8bSDave Chinner __XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)
1357ac2ff8bSDave Chinner
1368a456679SLong Li void xfs_free_unused_perag_range(struct xfs_mount *mp, xfs_agnumber_t agstart,
1378a456679SLong Li xfs_agnumber_t agend);
138bb305f88SChristoph Hellwig int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t old_agcount,
139bb305f88SChristoph Hellwig xfs_agnumber_t agcount, xfs_rfsblock_t dcount,
140bb305f88SChristoph Hellwig xfs_agnumber_t *maxagi);
141ffc18582SDarrick J. Wong int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
14207b6403aSDave Chinner void xfs_free_perag(struct xfs_mount *mp);
143*c904df65SChristoph Hellwig int xfs_update_last_ag_size(struct xfs_mount *mp, xfs_agnumber_t prev_agcount);
14407b6403aSDave Chinner
145c4d5660aSDave Chinner /* Passive AG references */
146ffc18582SDarrick J. Wong struct xfs_perag *xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno);
147ffc18582SDarrick J. Wong struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno,
148ffc18582SDarrick J. Wong unsigned int tag);
1499b2e5a23SDarrick J. Wong struct xfs_perag *xfs_perag_hold(struct xfs_perag *pag);
1509bbafc71SDave Chinner void xfs_perag_put(struct xfs_perag *pag);
15149dd56f2SDave Chinner
152c4d5660aSDave Chinner /* Active AG references */
153c4d5660aSDave Chinner struct xfs_perag *xfs_perag_grab(struct xfs_mount *, xfs_agnumber_t);
154c4d5660aSDave Chinner struct xfs_perag *xfs_perag_grab_tag(struct xfs_mount *, xfs_agnumber_t,
155c4d5660aSDave Chinner int tag);
156c4d5660aSDave Chinner void xfs_perag_rele(struct xfs_perag *pag);
157c4d5660aSDave Chinner
158f250eedcSDave Chinner /*
1590800169eSDave Chinner * Per-ag geometry infomation and validation
1600800169eSDave Chinner */
1610800169eSDave Chinner xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
1622d6ca832SDave Chinner void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
1632d6ca832SDave Chinner xfs_agino_t *first, xfs_agino_t *last);
1640800169eSDave Chinner
1650800169eSDave Chinner static inline bool
xfs_verify_agbno(struct xfs_perag * pag,xfs_agblock_t agbno)1660800169eSDave Chinner xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno)
1670800169eSDave Chinner {
1680800169eSDave Chinner if (agbno >= pag->block_count)
1690800169eSDave Chinner return false;
1700800169eSDave Chinner if (agbno <= pag->min_block)
1710800169eSDave Chinner return false;
1720800169eSDave Chinner return true;
1730800169eSDave Chinner }
1740800169eSDave Chinner
175b65e08f8SDarrick J. Wong static inline bool
xfs_verify_agbext(struct xfs_perag * pag,xfs_agblock_t agbno,xfs_agblock_t len)176b65e08f8SDarrick J. Wong xfs_verify_agbext(
177b65e08f8SDarrick J. Wong struct xfs_perag *pag,
178b65e08f8SDarrick J. Wong xfs_agblock_t agbno,
179b65e08f8SDarrick J. Wong xfs_agblock_t len)
180b65e08f8SDarrick J. Wong {
181b65e08f8SDarrick J. Wong if (agbno + len <= agbno)
182b65e08f8SDarrick J. Wong return false;
183b65e08f8SDarrick J. Wong
184b65e08f8SDarrick J. Wong if (!xfs_verify_agbno(pag, agbno))
185b65e08f8SDarrick J. Wong return false;
186b65e08f8SDarrick J. Wong
187b65e08f8SDarrick J. Wong return xfs_verify_agbno(pag, agbno + len - 1);
188b65e08f8SDarrick J. Wong }
189b65e08f8SDarrick J. Wong
1900800169eSDave Chinner /*
1912d6ca832SDave Chinner * Verify that an AG inode number pointer neither points outside the AG
1922d6ca832SDave Chinner * nor points at static metadata.
1932d6ca832SDave Chinner */
1942d6ca832SDave Chinner static inline bool
xfs_verify_agino(struct xfs_perag * pag,xfs_agino_t agino)1952d6ca832SDave Chinner xfs_verify_agino(struct xfs_perag *pag, xfs_agino_t agino)
1962d6ca832SDave Chinner {
1972d6ca832SDave Chinner if (agino < pag->agino_min)
1982d6ca832SDave Chinner return false;
1992d6ca832SDave Chinner if (agino > pag->agino_max)
2002d6ca832SDave Chinner return false;
2012d6ca832SDave Chinner return true;
2022d6ca832SDave Chinner }
2032d6ca832SDave Chinner
2042d6ca832SDave Chinner /*
2052d6ca832SDave Chinner * Verify that an AG inode number pointer neither points outside the AG
2062d6ca832SDave Chinner * nor points at static metadata, or is NULLAGINO.
2072d6ca832SDave Chinner */
2082d6ca832SDave Chinner static inline bool
xfs_verify_agino_or_null(struct xfs_perag * pag,xfs_agino_t agino)2092d6ca832SDave Chinner xfs_verify_agino_or_null(struct xfs_perag *pag, xfs_agino_t agino)
2102d6ca832SDave Chinner {
2112d6ca832SDave Chinner if (agino == NULLAGINO)
2122d6ca832SDave Chinner return true;
2132d6ca832SDave Chinner return xfs_verify_agino(pag, agino);
2142d6ca832SDave Chinner }
2152d6ca832SDave Chinner
21636029deeSDave Chinner static inline bool
xfs_ag_contains_log(struct xfs_mount * mp,xfs_agnumber_t agno)21736029deeSDave Chinner xfs_ag_contains_log(struct xfs_mount *mp, xfs_agnumber_t agno)
21836029deeSDave Chinner {
21936029deeSDave Chinner return mp->m_sb.sb_logstart > 0 &&
22036029deeSDave Chinner agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
22136029deeSDave Chinner }
22236029deeSDave Chinner
2232d6ca832SDave Chinner /*
224f250eedcSDave Chinner * Perag iteration APIs
225f250eedcSDave Chinner */
226bf2307b1SBrian Foster static inline struct xfs_perag *
xfs_perag_next(struct xfs_perag * pag,xfs_agnumber_t * agno,xfs_agnumber_t end_agno)227bf2307b1SBrian Foster xfs_perag_next(
228bf2307b1SBrian Foster struct xfs_perag *pag,
229892a666fSBrian Foster xfs_agnumber_t *agno,
230892a666fSBrian Foster xfs_agnumber_t end_agno)
231bf2307b1SBrian Foster {
232bf2307b1SBrian Foster struct xfs_mount *mp = pag->pag_mount;
233bf2307b1SBrian Foster
234f1788b5eSBrian Foster *agno = pag->pag_agno + 1;
235c4d5660aSDave Chinner xfs_perag_rele(pag);
236c4d5660aSDave Chinner while (*agno <= end_agno) {
237c4d5660aSDave Chinner pag = xfs_perag_grab(mp, *agno);
238c4d5660aSDave Chinner if (pag)
239c4d5660aSDave Chinner return pag;
240c4d5660aSDave Chinner (*agno)++;
241c4d5660aSDave Chinner }
242892a666fSBrian Foster return NULL;
243bf2307b1SBrian Foster }
244bf2307b1SBrian Foster
245f1788b5eSBrian Foster #define for_each_perag_range(mp, agno, end_agno, pag) \
246c4d5660aSDave Chinner for ((pag) = xfs_perag_grab((mp), (agno)); \
247892a666fSBrian Foster (pag) != NULL; \
248892a666fSBrian Foster (pag) = xfs_perag_next((pag), &(agno), (end_agno)))
249f250eedcSDave Chinner
250f1788b5eSBrian Foster #define for_each_perag_from(mp, agno, pag) \
2518ed004ebSBrian Foster for_each_perag_range((mp), (agno), (mp)->m_sb.sb_agcount - 1, (pag))
25258d43a7eSDave Chinner
2536f4118fcSDave Chinner #define for_each_perag(mp, agno, pag) \
2546f4118fcSDave Chinner (agno) = 0; \
2556f4118fcSDave Chinner for_each_perag_from((mp), (agno), (pag))
2566f4118fcSDave Chinner
2576f4118fcSDave Chinner #define for_each_perag_tag(mp, agno, pag, tag) \
258c4d5660aSDave Chinner for ((agno) = 0, (pag) = xfs_perag_grab_tag((mp), 0, (tag)); \
259f250eedcSDave Chinner (pag) != NULL; \
2606f4118fcSDave Chinner (agno) = (pag)->pag_agno + 1, \
261c4d5660aSDave Chinner xfs_perag_rele(pag), \
262c4d5660aSDave Chinner (pag) = xfs_perag_grab_tag((mp), (agno), (tag)))
263f250eedcSDave Chinner
26476257a15SDave Chinner static inline struct xfs_perag *
xfs_perag_next_wrap(struct xfs_perag * pag,xfs_agnumber_t * agno,xfs_agnumber_t stop_agno,xfs_agnumber_t restart_agno,xfs_agnumber_t wrap_agno)26576257a15SDave Chinner xfs_perag_next_wrap(
26676257a15SDave Chinner struct xfs_perag *pag,
26776257a15SDave Chinner xfs_agnumber_t *agno,
26876257a15SDave Chinner xfs_agnumber_t stop_agno,
2693432ef61SDave Chinner xfs_agnumber_t restart_agno,
27076257a15SDave Chinner xfs_agnumber_t wrap_agno)
27176257a15SDave Chinner {
27276257a15SDave Chinner struct xfs_mount *mp = pag->pag_mount;
27376257a15SDave Chinner
27476257a15SDave Chinner *agno = pag->pag_agno + 1;
27576257a15SDave Chinner xfs_perag_rele(pag);
27676257a15SDave Chinner while (*agno != stop_agno) {
2773432ef61SDave Chinner if (*agno >= wrap_agno) {
2783432ef61SDave Chinner if (restart_agno >= stop_agno)
27976257a15SDave Chinner break;
2803432ef61SDave Chinner *agno = restart_agno;
2813432ef61SDave Chinner }
28276257a15SDave Chinner
28376257a15SDave Chinner pag = xfs_perag_grab(mp, *agno);
28476257a15SDave Chinner if (pag)
28576257a15SDave Chinner return pag;
28676257a15SDave Chinner (*agno)++;
28776257a15SDave Chinner }
28876257a15SDave Chinner return NULL;
28976257a15SDave Chinner }
29076257a15SDave Chinner
29176257a15SDave Chinner /*
2923432ef61SDave Chinner * Iterate all AGs from start_agno through wrap_agno, then restart_agno through
2933432ef61SDave Chinner * (start_agno - 1).
2943432ef61SDave Chinner */
2953432ef61SDave Chinner #define for_each_perag_wrap_range(mp, start_agno, restart_agno, wrap_agno, agno, pag) \
2963432ef61SDave Chinner for ((agno) = (start_agno), (pag) = xfs_perag_grab((mp), (agno)); \
2973432ef61SDave Chinner (pag) != NULL; \
2983432ef61SDave Chinner (pag) = xfs_perag_next_wrap((pag), &(agno), (start_agno), \
2993432ef61SDave Chinner (restart_agno), (wrap_agno)))
3003432ef61SDave Chinner /*
30176257a15SDave Chinner * Iterate all AGs from start_agno through wrap_agno, then 0 through
30276257a15SDave Chinner * (start_agno - 1).
30376257a15SDave Chinner */
30476257a15SDave Chinner #define for_each_perag_wrap_at(mp, start_agno, wrap_agno, agno, pag) \
3053432ef61SDave Chinner for_each_perag_wrap_range((mp), (start_agno), 0, (wrap_agno), (agno), (pag))
30676257a15SDave Chinner
30776257a15SDave Chinner /*
30876257a15SDave Chinner * Iterate all AGs from start_agno through to the end of the filesystem, then 0
30976257a15SDave Chinner * through (start_agno - 1).
31076257a15SDave Chinner */
31176257a15SDave Chinner #define for_each_perag_wrap(mp, start_agno, agno, pag) \
31276257a15SDave Chinner for_each_perag_wrap_at((mp), (start_agno), (mp)->m_sb.sb_agcount, \
31376257a15SDave Chinner (agno), (pag))
31476257a15SDave Chinner
31576257a15SDave Chinner
316b16817b6SDave Chinner struct aghdr_init_data {
317b16817b6SDave Chinner /* per ag data */
318b16817b6SDave Chinner xfs_agblock_t agno; /* ag to init */
319b16817b6SDave Chinner xfs_extlen_t agsize; /* new AG size */
320b16817b6SDave Chinner struct list_head buffer_list; /* buffer writeback list */
321b16817b6SDave Chinner xfs_rfsblock_t nfree; /* cumulative new free space */
322b16817b6SDave Chinner
323b16817b6SDave Chinner /* per header data */
324b16817b6SDave Chinner xfs_daddr_t daddr; /* header location */
325b16817b6SDave Chinner size_t numblks; /* size of header */
326b16817b6SDave Chinner xfs_btnum_t type; /* type of btree root block */
327b16817b6SDave Chinner };
328b16817b6SDave Chinner
329b16817b6SDave Chinner int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id);
330c6aee248SDave Chinner int xfs_ag_shrink_space(struct xfs_perag *pag, struct xfs_trans **tpp,
331c6aee248SDave Chinner xfs_extlen_t delta);
332c6aee248SDave Chinner int xfs_ag_extend_space(struct xfs_perag *pag, struct xfs_trans *tp,
333c6aee248SDave Chinner xfs_extlen_t len);
334c6aee248SDave Chinner int xfs_ag_get_geometry(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);
335b16817b6SDave Chinner
336b16817b6SDave Chinner #endif /* __LIBXFS_AG_H */
337