xref: /kernel/linux/linux-6.6/fs/xfs/libxfs/xfs_ag.h (revision 62306a36)
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
10struct xfs_mount;
11struct xfs_trans;
12struct xfs_perag;
13
14/*
15 * Per-ag infrastructure
16 */
17
18/* per-AG block reservation data structures*/
19struct 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 */
32struct 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) \
125static inline bool xfs_perag_ ## name (struct xfs_perag *pag) \
126{ \
127	return test_bit(XFS_AGSTATE_ ## NAME, &pag->pag_opstate); \
128}
129
130__XFS_AG_OPSTATE(initialised_agf, AGF_INIT)
131__XFS_AG_OPSTATE(initialised_agi, AGI_INIT)
132__XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA)
133__XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES)
134__XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)
135
136int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount,
137			xfs_rfsblock_t dcount, xfs_agnumber_t *maxagi);
138int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
139void xfs_free_perag(struct xfs_mount *mp);
140
141/* Passive AG references */
142struct xfs_perag *xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno);
143struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno,
144		unsigned int tag);
145struct xfs_perag *xfs_perag_hold(struct xfs_perag *pag);
146void xfs_perag_put(struct xfs_perag *pag);
147
148/* Active AG references */
149struct xfs_perag *xfs_perag_grab(struct xfs_mount *, xfs_agnumber_t);
150struct xfs_perag *xfs_perag_grab_tag(struct xfs_mount *, xfs_agnumber_t,
151				   int tag);
152void xfs_perag_rele(struct xfs_perag *pag);
153
154/*
155 * Per-ag geometry infomation and validation
156 */
157xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
158void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
159		xfs_agino_t *first, xfs_agino_t *last);
160
161static inline bool
162xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno)
163{
164	if (agbno >= pag->block_count)
165		return false;
166	if (agbno <= pag->min_block)
167		return false;
168	return true;
169}
170
171static inline bool
172xfs_verify_agbext(
173	struct xfs_perag	*pag,
174	xfs_agblock_t		agbno,
175	xfs_agblock_t		len)
176{
177	if (agbno + len <= agbno)
178		return false;
179
180	if (!xfs_verify_agbno(pag, agbno))
181		return false;
182
183	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 */
190static inline bool
191xfs_verify_agino(struct xfs_perag *pag, xfs_agino_t agino)
192{
193	if (agino < pag->agino_min)
194		return false;
195	if (agino > pag->agino_max)
196		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 */
204static inline bool
205xfs_verify_agino_or_null(struct xfs_perag *pag, xfs_agino_t agino)
206{
207	if (agino == NULLAGINO)
208		return true;
209	return xfs_verify_agino(pag, agino);
210}
211
212static inline bool
213xfs_ag_contains_log(struct xfs_mount *mp, xfs_agnumber_t agno)
214{
215	return mp->m_sb.sb_logstart > 0 &&
216	       agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
217}
218
219/*
220 * Perag iteration APIs
221 */
222static inline struct xfs_perag *
223xfs_perag_next(
224	struct xfs_perag	*pag,
225	xfs_agnumber_t		*agno,
226	xfs_agnumber_t		end_agno)
227{
228	struct xfs_mount	*mp = pag->pag_mount;
229
230	*agno = pag->pag_agno + 1;
231	xfs_perag_rele(pag);
232	while (*agno <= end_agno) {
233		pag = xfs_perag_grab(mp, *agno);
234		if (pag)
235			return pag;
236		(*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
260static inline struct xfs_perag *
261xfs_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	struct xfs_mount	*mp = pag->pag_mount;
269
270	*agno = pag->pag_agno + 1;
271	xfs_perag_rele(pag);
272	while (*agno != stop_agno) {
273		if (*agno >= wrap_agno) {
274			if (restart_agno >= stop_agno)
275				break;
276			*agno = restart_agno;
277		}
278
279		pag = xfs_perag_grab(mp, *agno);
280		if (pag)
281			return pag;
282		(*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
312struct 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
325int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id);
326int xfs_ag_shrink_space(struct xfs_perag *pag, struct xfs_trans **tpp,
327			xfs_extlen_t delta);
328int xfs_ag_extend_space(struct xfs_perag *pag, struct xfs_trans *tp,
329			xfs_extlen_t len);
330int xfs_ag_get_geometry(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);
331
332#endif /* __LIBXFS_AG_H */
333