162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2018 Red Hat, Inc.
462306a36Sopenharmony_ci * All rights reserved.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __LIBXFS_AG_H
862306a36Sopenharmony_ci#define __LIBXFS_AG_H 1
962306a36Sopenharmony_ci
1062306a36Sopenharmony_cistruct xfs_mount;
1162306a36Sopenharmony_cistruct xfs_trans;
1262306a36Sopenharmony_cistruct xfs_perag;
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/*
1562306a36Sopenharmony_ci * Per-ag infrastructure
1662306a36Sopenharmony_ci */
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* per-AG block reservation data structures*/
1962306a36Sopenharmony_cistruct xfs_ag_resv {
2062306a36Sopenharmony_ci	/* number of blocks originally reserved here */
2162306a36Sopenharmony_ci	xfs_extlen_t			ar_orig_reserved;
2262306a36Sopenharmony_ci	/* number of blocks reserved here */
2362306a36Sopenharmony_ci	xfs_extlen_t			ar_reserved;
2462306a36Sopenharmony_ci	/* number of blocks originally asked for */
2562306a36Sopenharmony_ci	xfs_extlen_t			ar_asked;
2662306a36Sopenharmony_ci};
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * Per-ag incore structure, copies of information in agf and agi, to improve the
3062306a36Sopenharmony_ci * performance of allocation group selection.
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_cistruct xfs_perag {
3362306a36Sopenharmony_ci	struct xfs_mount *pag_mount;	/* owner filesystem */
3462306a36Sopenharmony_ci	xfs_agnumber_t	pag_agno;	/* AG this structure belongs to */
3562306a36Sopenharmony_ci	atomic_t	pag_ref;	/* passive reference count */
3662306a36Sopenharmony_ci	atomic_t	pag_active_ref;	/* active reference count */
3762306a36Sopenharmony_ci	wait_queue_head_t pag_active_wq;/* woken active_ref falls to zero */
3862306a36Sopenharmony_ci	unsigned long	pag_opstate;
3962306a36Sopenharmony_ci	uint8_t		pagf_levels[XFS_BTNUM_AGF];
4062306a36Sopenharmony_ci					/* # of levels in bno & cnt btree */
4162306a36Sopenharmony_ci	uint32_t	pagf_flcount;	/* count of blocks in freelist */
4262306a36Sopenharmony_ci	xfs_extlen_t	pagf_freeblks;	/* total free blocks */
4362306a36Sopenharmony_ci	xfs_extlen_t	pagf_longest;	/* longest free space */
4462306a36Sopenharmony_ci	uint32_t	pagf_btreeblks;	/* # of blocks held in AGF btrees */
4562306a36Sopenharmony_ci	xfs_agino_t	pagi_freecount;	/* number of free inodes */
4662306a36Sopenharmony_ci	xfs_agino_t	pagi_count;	/* number of allocated inodes */
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	/*
4962306a36Sopenharmony_ci	 * Inode allocation search lookup optimisation.
5062306a36Sopenharmony_ci	 * If the pagino matches, the search for new inodes
5162306a36Sopenharmony_ci	 * doesn't need to search the near ones again straight away
5262306a36Sopenharmony_ci	 */
5362306a36Sopenharmony_ci	xfs_agino_t	pagl_pagino;
5462306a36Sopenharmony_ci	xfs_agino_t	pagl_leftrec;
5562306a36Sopenharmony_ci	xfs_agino_t	pagl_rightrec;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	int		pagb_count;	/* pagb slots in use */
5862306a36Sopenharmony_ci	uint8_t		pagf_refcount_level; /* recount btree height */
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	/* Blocks reserved for all kinds of metadata. */
6162306a36Sopenharmony_ci	struct xfs_ag_resv	pag_meta_resv;
6262306a36Sopenharmony_ci	/* Blocks reserved for the reverse mapping btree. */
6362306a36Sopenharmony_ci	struct xfs_ag_resv	pag_rmapbt_resv;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	/* for rcu-safe freeing */
6662306a36Sopenharmony_ci	struct rcu_head	rcu_head;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	/* Precalculated geometry info */
6962306a36Sopenharmony_ci	xfs_agblock_t		block_count;
7062306a36Sopenharmony_ci	xfs_agblock_t		min_block;
7162306a36Sopenharmony_ci	xfs_agino_t		agino_min;
7262306a36Sopenharmony_ci	xfs_agino_t		agino_max;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci#ifdef __KERNEL__
7562306a36Sopenharmony_ci	/* -- kernel only structures below this line -- */
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	/*
7862306a36Sopenharmony_ci	 * Bitsets of per-ag metadata that have been checked and/or are sick.
7962306a36Sopenharmony_ci	 * Callers should hold pag_state_lock before accessing this field.
8062306a36Sopenharmony_ci	 */
8162306a36Sopenharmony_ci	uint16_t	pag_checked;
8262306a36Sopenharmony_ci	uint16_t	pag_sick;
8362306a36Sopenharmony_ci	spinlock_t	pag_state_lock;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	spinlock_t	pagb_lock;	/* lock for pagb_tree */
8662306a36Sopenharmony_ci	struct rb_root	pagb_tree;	/* ordered tree of busy extents */
8762306a36Sopenharmony_ci	unsigned int	pagb_gen;	/* generation count for pagb_tree */
8862306a36Sopenharmony_ci	wait_queue_head_t pagb_wait;	/* woken when pagb_gen changes */
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	atomic_t        pagf_fstrms;    /* # of filestreams active in this AG */
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	spinlock_t	pag_ici_lock;	/* incore inode cache lock */
9362306a36Sopenharmony_ci	struct radix_tree_root pag_ici_root;	/* incore inode cache root */
9462306a36Sopenharmony_ci	int		pag_ici_reclaimable;	/* reclaimable inodes */
9562306a36Sopenharmony_ci	unsigned long	pag_ici_reclaim_cursor;	/* reclaim restart point */
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	/* buffer cache index */
9862306a36Sopenharmony_ci	spinlock_t	pag_buf_lock;	/* lock for pag_buf_hash */
9962306a36Sopenharmony_ci	struct rhashtable pag_buf_hash;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	/* background prealloc block trimming */
10262306a36Sopenharmony_ci	struct delayed_work	pag_blockgc_work;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	/*
10562306a36Sopenharmony_ci	 * We use xfs_drain to track the number of deferred log intent items
10662306a36Sopenharmony_ci	 * that have been queued (but not yet processed) so that waiters (e.g.
10762306a36Sopenharmony_ci	 * scrub) will not lock resources when other threads are in the middle
10862306a36Sopenharmony_ci	 * of processing a chain of intent items only to find momentary
10962306a36Sopenharmony_ci	 * inconsistencies.
11062306a36Sopenharmony_ci	 */
11162306a36Sopenharmony_ci	struct xfs_defer_drain	pag_intents_drain;
11262306a36Sopenharmony_ci#endif /* __KERNEL__ */
11362306a36Sopenharmony_ci};
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci/*
11662306a36Sopenharmony_ci * Per-AG operational state. These are atomic flag bits.
11762306a36Sopenharmony_ci */
11862306a36Sopenharmony_ci#define XFS_AGSTATE_AGF_INIT		0
11962306a36Sopenharmony_ci#define XFS_AGSTATE_AGI_INIT		1
12062306a36Sopenharmony_ci#define XFS_AGSTATE_PREFERS_METADATA	2
12162306a36Sopenharmony_ci#define XFS_AGSTATE_ALLOWS_INODES	3
12262306a36Sopenharmony_ci#define XFS_AGSTATE_AGFL_NEEDS_RESET	4
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci#define __XFS_AG_OPSTATE(name, NAME) \
12562306a36Sopenharmony_cistatic inline bool xfs_perag_ ## name (struct xfs_perag *pag) \
12662306a36Sopenharmony_ci{ \
12762306a36Sopenharmony_ci	return test_bit(XFS_AGSTATE_ ## NAME, &pag->pag_opstate); \
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci__XFS_AG_OPSTATE(initialised_agf, AGF_INIT)
13162306a36Sopenharmony_ci__XFS_AG_OPSTATE(initialised_agi, AGI_INIT)
13262306a36Sopenharmony_ci__XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA)
13362306a36Sopenharmony_ci__XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES)
13462306a36Sopenharmony_ci__XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ciint xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount,
13762306a36Sopenharmony_ci			xfs_rfsblock_t dcount, xfs_agnumber_t *maxagi);
13862306a36Sopenharmony_ciint xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
13962306a36Sopenharmony_civoid xfs_free_perag(struct xfs_mount *mp);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci/* Passive AG references */
14262306a36Sopenharmony_cistruct xfs_perag *xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno);
14362306a36Sopenharmony_cistruct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno,
14462306a36Sopenharmony_ci		unsigned int tag);
14562306a36Sopenharmony_cistruct xfs_perag *xfs_perag_hold(struct xfs_perag *pag);
14662306a36Sopenharmony_civoid xfs_perag_put(struct xfs_perag *pag);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci/* Active AG references */
14962306a36Sopenharmony_cistruct xfs_perag *xfs_perag_grab(struct xfs_mount *, xfs_agnumber_t);
15062306a36Sopenharmony_cistruct xfs_perag *xfs_perag_grab_tag(struct xfs_mount *, xfs_agnumber_t,
15162306a36Sopenharmony_ci				   int tag);
15262306a36Sopenharmony_civoid xfs_perag_rele(struct xfs_perag *pag);
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci/*
15562306a36Sopenharmony_ci * Per-ag geometry infomation and validation
15662306a36Sopenharmony_ci */
15762306a36Sopenharmony_cixfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
15862306a36Sopenharmony_civoid xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
15962306a36Sopenharmony_ci		xfs_agino_t *first, xfs_agino_t *last);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic inline bool
16262306a36Sopenharmony_cixfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	if (agbno >= pag->block_count)
16562306a36Sopenharmony_ci		return false;
16662306a36Sopenharmony_ci	if (agbno <= pag->min_block)
16762306a36Sopenharmony_ci		return false;
16862306a36Sopenharmony_ci	return true;
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_cistatic inline bool
17262306a36Sopenharmony_cixfs_verify_agbext(
17362306a36Sopenharmony_ci	struct xfs_perag	*pag,
17462306a36Sopenharmony_ci	xfs_agblock_t		agbno,
17562306a36Sopenharmony_ci	xfs_agblock_t		len)
17662306a36Sopenharmony_ci{
17762306a36Sopenharmony_ci	if (agbno + len <= agbno)
17862306a36Sopenharmony_ci		return false;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	if (!xfs_verify_agbno(pag, agbno))
18162306a36Sopenharmony_ci		return false;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	return xfs_verify_agbno(pag, agbno + len - 1);
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci/*
18762306a36Sopenharmony_ci * Verify that an AG inode number pointer neither points outside the AG
18862306a36Sopenharmony_ci * nor points at static metadata.
18962306a36Sopenharmony_ci */
19062306a36Sopenharmony_cistatic inline bool
19162306a36Sopenharmony_cixfs_verify_agino(struct xfs_perag *pag, xfs_agino_t agino)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	if (agino < pag->agino_min)
19462306a36Sopenharmony_ci		return false;
19562306a36Sopenharmony_ci	if (agino > pag->agino_max)
19662306a36Sopenharmony_ci		return false;
19762306a36Sopenharmony_ci	return true;
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci/*
20162306a36Sopenharmony_ci * Verify that an AG inode number pointer neither points outside the AG
20262306a36Sopenharmony_ci * nor points at static metadata, or is NULLAGINO.
20362306a36Sopenharmony_ci */
20462306a36Sopenharmony_cistatic inline bool
20562306a36Sopenharmony_cixfs_verify_agino_or_null(struct xfs_perag *pag, xfs_agino_t agino)
20662306a36Sopenharmony_ci{
20762306a36Sopenharmony_ci	if (agino == NULLAGINO)
20862306a36Sopenharmony_ci		return true;
20962306a36Sopenharmony_ci	return xfs_verify_agino(pag, agino);
21062306a36Sopenharmony_ci}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistatic inline bool
21362306a36Sopenharmony_cixfs_ag_contains_log(struct xfs_mount *mp, xfs_agnumber_t agno)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	return mp->m_sb.sb_logstart > 0 &&
21662306a36Sopenharmony_ci	       agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
21762306a36Sopenharmony_ci}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci/*
22062306a36Sopenharmony_ci * Perag iteration APIs
22162306a36Sopenharmony_ci */
22262306a36Sopenharmony_cistatic inline struct xfs_perag *
22362306a36Sopenharmony_cixfs_perag_next(
22462306a36Sopenharmony_ci	struct xfs_perag	*pag,
22562306a36Sopenharmony_ci	xfs_agnumber_t		*agno,
22662306a36Sopenharmony_ci	xfs_agnumber_t		end_agno)
22762306a36Sopenharmony_ci{
22862306a36Sopenharmony_ci	struct xfs_mount	*mp = pag->pag_mount;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	*agno = pag->pag_agno + 1;
23162306a36Sopenharmony_ci	xfs_perag_rele(pag);
23262306a36Sopenharmony_ci	while (*agno <= end_agno) {
23362306a36Sopenharmony_ci		pag = xfs_perag_grab(mp, *agno);
23462306a36Sopenharmony_ci		if (pag)
23562306a36Sopenharmony_ci			return pag;
23662306a36Sopenharmony_ci		(*agno)++;
23762306a36Sopenharmony_ci	}
23862306a36Sopenharmony_ci	return NULL;
23962306a36Sopenharmony_ci}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci#define for_each_perag_range(mp, agno, end_agno, pag) \
24262306a36Sopenharmony_ci	for ((pag) = xfs_perag_grab((mp), (agno)); \
24362306a36Sopenharmony_ci		(pag) != NULL; \
24462306a36Sopenharmony_ci		(pag) = xfs_perag_next((pag), &(agno), (end_agno)))
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci#define for_each_perag_from(mp, agno, pag) \
24762306a36Sopenharmony_ci	for_each_perag_range((mp), (agno), (mp)->m_sb.sb_agcount - 1, (pag))
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci#define for_each_perag(mp, agno, pag) \
25062306a36Sopenharmony_ci	(agno) = 0; \
25162306a36Sopenharmony_ci	for_each_perag_from((mp), (agno), (pag))
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci#define for_each_perag_tag(mp, agno, pag, tag) \
25462306a36Sopenharmony_ci	for ((agno) = 0, (pag) = xfs_perag_grab_tag((mp), 0, (tag)); \
25562306a36Sopenharmony_ci		(pag) != NULL; \
25662306a36Sopenharmony_ci		(agno) = (pag)->pag_agno + 1, \
25762306a36Sopenharmony_ci		xfs_perag_rele(pag), \
25862306a36Sopenharmony_ci		(pag) = xfs_perag_grab_tag((mp), (agno), (tag)))
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistatic inline struct xfs_perag *
26162306a36Sopenharmony_cixfs_perag_next_wrap(
26262306a36Sopenharmony_ci	struct xfs_perag	*pag,
26362306a36Sopenharmony_ci	xfs_agnumber_t		*agno,
26462306a36Sopenharmony_ci	xfs_agnumber_t		stop_agno,
26562306a36Sopenharmony_ci	xfs_agnumber_t		restart_agno,
26662306a36Sopenharmony_ci	xfs_agnumber_t		wrap_agno)
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	struct xfs_mount	*mp = pag->pag_mount;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	*agno = pag->pag_agno + 1;
27162306a36Sopenharmony_ci	xfs_perag_rele(pag);
27262306a36Sopenharmony_ci	while (*agno != stop_agno) {
27362306a36Sopenharmony_ci		if (*agno >= wrap_agno) {
27462306a36Sopenharmony_ci			if (restart_agno >= stop_agno)
27562306a36Sopenharmony_ci				break;
27662306a36Sopenharmony_ci			*agno = restart_agno;
27762306a36Sopenharmony_ci		}
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci		pag = xfs_perag_grab(mp, *agno);
28062306a36Sopenharmony_ci		if (pag)
28162306a36Sopenharmony_ci			return pag;
28262306a36Sopenharmony_ci		(*agno)++;
28362306a36Sopenharmony_ci	}
28462306a36Sopenharmony_ci	return NULL;
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci/*
28862306a36Sopenharmony_ci * Iterate all AGs from start_agno through wrap_agno, then restart_agno through
28962306a36Sopenharmony_ci * (start_agno - 1).
29062306a36Sopenharmony_ci */
29162306a36Sopenharmony_ci#define for_each_perag_wrap_range(mp, start_agno, restart_agno, wrap_agno, agno, pag) \
29262306a36Sopenharmony_ci	for ((agno) = (start_agno), (pag) = xfs_perag_grab((mp), (agno)); \
29362306a36Sopenharmony_ci		(pag) != NULL; \
29462306a36Sopenharmony_ci		(pag) = xfs_perag_next_wrap((pag), &(agno), (start_agno), \
29562306a36Sopenharmony_ci				(restart_agno), (wrap_agno)))
29662306a36Sopenharmony_ci/*
29762306a36Sopenharmony_ci * Iterate all AGs from start_agno through wrap_agno, then 0 through
29862306a36Sopenharmony_ci * (start_agno - 1).
29962306a36Sopenharmony_ci */
30062306a36Sopenharmony_ci#define for_each_perag_wrap_at(mp, start_agno, wrap_agno, agno, pag) \
30162306a36Sopenharmony_ci	for_each_perag_wrap_range((mp), (start_agno), 0, (wrap_agno), (agno), (pag))
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci/*
30462306a36Sopenharmony_ci * Iterate all AGs from start_agno through to the end of the filesystem, then 0
30562306a36Sopenharmony_ci * through (start_agno - 1).
30662306a36Sopenharmony_ci */
30762306a36Sopenharmony_ci#define for_each_perag_wrap(mp, start_agno, agno, pag) \
30862306a36Sopenharmony_ci	for_each_perag_wrap_at((mp), (start_agno), (mp)->m_sb.sb_agcount, \
30962306a36Sopenharmony_ci				(agno), (pag))
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_cistruct aghdr_init_data {
31362306a36Sopenharmony_ci	/* per ag data */
31462306a36Sopenharmony_ci	xfs_agblock_t		agno;		/* ag to init */
31562306a36Sopenharmony_ci	xfs_extlen_t		agsize;		/* new AG size */
31662306a36Sopenharmony_ci	struct list_head	buffer_list;	/* buffer writeback list */
31762306a36Sopenharmony_ci	xfs_rfsblock_t		nfree;		/* cumulative new free space */
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	/* per header data */
32062306a36Sopenharmony_ci	xfs_daddr_t		daddr;		/* header location */
32162306a36Sopenharmony_ci	size_t			numblks;	/* size of header */
32262306a36Sopenharmony_ci	xfs_btnum_t		type;		/* type of btree root block */
32362306a36Sopenharmony_ci};
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ciint xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id);
32662306a36Sopenharmony_ciint xfs_ag_shrink_space(struct xfs_perag *pag, struct xfs_trans **tpp,
32762306a36Sopenharmony_ci			xfs_extlen_t delta);
32862306a36Sopenharmony_ciint xfs_ag_extend_space(struct xfs_perag *pag, struct xfs_trans *tp,
32962306a36Sopenharmony_ci			xfs_extlen_t len);
33062306a36Sopenharmony_ciint xfs_ag_get_geometry(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci#endif /* __LIBXFS_AG_H */
333