xref: /linux/fs/xfs/libxfs/xfs_ag.h (revision 497560b9ef42a4ab22ada7f1ea975a89cd3c5dfa)
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 #include "xfs_group.h"
11 
12 struct xfs_mount;
13 struct xfs_trans;
14 struct xfs_perag;
15 
16 /*
17  * Per-ag infrastructure
18  */
19 
20 /* per-AG block reservation data structures*/
21 struct xfs_ag_resv {
22 	/* number of blocks originally reserved here */
23 	xfs_extlen_t			ar_orig_reserved;
24 	/* number of blocks reserved here */
25 	xfs_extlen_t			ar_reserved;
26 	/* number of blocks originally asked for */
27 	xfs_extlen_t			ar_asked;
28 };
29 
30 /*
31  * Per-ag incore structure, copies of information in agf and agi, to improve the
32  * performance of allocation group selection.
33  */
34 struct xfs_perag {
35 	struct xfs_group pag_group;
36 	unsigned long	pag_opstate;
37 	uint8_t		pagf_bno_level;	/* # of levels in bno btree */
38 	uint8_t		pagf_cnt_level;	/* # of levels in cnt btree */
39 	uint8_t		pagf_rmap_level;/* # of levels in rmap btree */
40 	uint32_t	pagf_flcount;	/* count of blocks in freelist */
41 	xfs_extlen_t	pagf_freeblks;	/* total free blocks */
42 	xfs_extlen_t	pagf_longest;	/* longest free space */
43 	uint32_t	pagf_btreeblks;	/* # of blocks held in AGF btrees */
44 	xfs_agino_t	pagi_freecount;	/* number of free inodes */
45 	xfs_agino_t	pagi_count;	/* number of allocated inodes */
46 
47 	/*
48 	 * Inode allocation search lookup optimisation.
49 	 * If the pagino matches, the search for new inodes
50 	 * doesn't need to search the near ones again straight away
51 	 */
52 	xfs_agino_t	pagl_pagino;
53 	xfs_agino_t	pagl_leftrec;
54 	xfs_agino_t	pagl_rightrec;
55 
56 	uint8_t		pagf_refcount_level; /* recount btree height */
57 
58 	/* Blocks reserved for all kinds of metadata. */
59 	struct xfs_ag_resv	pag_meta_resv;
60 	/* Blocks reserved for the reverse mapping btree. */
61 	struct xfs_ag_resv	pag_rmapbt_resv;
62 
63 	/* Precalculated geometry info */
64 	xfs_agino_t		agino_min;
65 	xfs_agino_t		agino_max;
66 
67 #ifdef __KERNEL__
68 	/* -- kernel only structures below this line -- */
69 
70 #ifdef CONFIG_XFS_ONLINE_REPAIR
71 	/*
72 	 * Alternate btree heights so that online repair won't trip the write
73 	 * verifiers while rebuilding the AG btrees.
74 	 */
75 	uint8_t		pagf_repair_bno_level;
76 	uint8_t		pagf_repair_cnt_level;
77 	uint8_t		pagf_repair_refcount_level;
78 	uint8_t		pagf_repair_rmap_level;
79 #endif
80 
81 	atomic_t        pagf_fstrms;    /* # of filestreams active in this AG */
82 
83 	spinlock_t	pag_ici_lock;	/* incore inode cache lock */
84 	struct radix_tree_root pag_ici_root;	/* incore inode cache root */
85 	int		pag_ici_reclaimable;	/* reclaimable inodes */
86 	unsigned long	pag_ici_reclaim_cursor;	/* reclaim restart point */
87 
88 	/* background prealloc block trimming */
89 	struct delayed_work	pag_blockgc_work;
90 #endif /* __KERNEL__ */
91 };
92 
93 static inline struct xfs_perag *to_perag(struct xfs_group *xg)
94 {
95 	return container_of(xg, struct xfs_perag, pag_group);
96 }
97 
98 static inline struct xfs_group *pag_group(struct xfs_perag *pag)
99 {
100 	return &pag->pag_group;
101 }
102 
103 static inline struct xfs_mount *pag_mount(const struct xfs_perag *pag)
104 {
105 	return pag->pag_group.xg_mount;
106 }
107 
108 static inline xfs_agnumber_t pag_agno(const struct xfs_perag *pag)
109 {
110 	return pag->pag_group.xg_gno;
111 }
112 
113 /*
114  * Per-AG operational state. These are atomic flag bits.
115  */
116 #define XFS_AGSTATE_AGF_INIT		0
117 #define XFS_AGSTATE_AGI_INIT		1
118 #define XFS_AGSTATE_PREFERS_METADATA	2
119 #define XFS_AGSTATE_ALLOWS_INODES	3
120 #define XFS_AGSTATE_AGFL_NEEDS_RESET	4
121 
122 #define __XFS_AG_OPSTATE(name, NAME) \
123 static inline bool xfs_perag_ ## name (struct xfs_perag *pag) \
124 { \
125 	return test_bit(XFS_AGSTATE_ ## NAME, &pag->pag_opstate); \
126 }
127 
128 __XFS_AG_OPSTATE(initialised_agf, AGF_INIT)
129 __XFS_AG_OPSTATE(initialised_agi, AGI_INIT)
130 __XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA)
131 __XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES)
132 __XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)
133 
134 int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t orig_agcount,
135 		xfs_agnumber_t new_agcount, xfs_rfsblock_t dcount,
136 		xfs_agnumber_t *maxagi);
137 void xfs_free_perag_range(struct xfs_mount *mp, xfs_agnumber_t first_agno,
138 		xfs_agnumber_t end_agno);
139 int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
140 int xfs_update_last_ag_size(struct xfs_mount *mp, xfs_agnumber_t prev_agcount);
141 
142 /* Passive AG references */
143 static inline struct xfs_perag *
144 xfs_perag_get(
145 	struct xfs_mount	*mp,
146 	xfs_agnumber_t		agno)
147 {
148 	return to_perag(xfs_group_get(mp, agno, XG_TYPE_AG));
149 }
150 
151 static inline struct xfs_perag *
152 xfs_perag_hold(
153 	struct xfs_perag	*pag)
154 {
155 	return to_perag(xfs_group_hold(pag_group(pag)));
156 }
157 
158 static inline void
159 xfs_perag_put(
160 	struct xfs_perag	*pag)
161 {
162 	xfs_group_put(pag_group(pag));
163 }
164 
165 /* Active AG references */
166 static inline struct xfs_perag *
167 xfs_perag_grab(
168 	struct xfs_mount	*mp,
169 	xfs_agnumber_t		agno)
170 {
171 	return to_perag(xfs_group_grab(mp, agno, XG_TYPE_AG));
172 }
173 
174 static inline void
175 xfs_perag_rele(
176 	struct xfs_perag	*pag)
177 {
178 	xfs_group_rele(pag_group(pag));
179 }
180 
181 static inline struct xfs_perag *
182 xfs_perag_next_range(
183 	struct xfs_mount	*mp,
184 	struct xfs_perag	*pag,
185 	xfs_agnumber_t		start_agno,
186 	xfs_agnumber_t		end_agno)
187 {
188 	return to_perag(xfs_group_next_range(mp, pag ? pag_group(pag) : NULL,
189 			start_agno, end_agno, XG_TYPE_AG));
190 }
191 
192 static inline struct xfs_perag *
193 xfs_perag_next_from(
194 	struct xfs_mount	*mp,
195 	struct xfs_perag	*pag,
196 	xfs_agnumber_t		start_agno)
197 {
198 	return xfs_perag_next_range(mp, pag, start_agno, mp->m_sb.sb_agcount - 1);
199 }
200 
201 static inline struct xfs_perag *
202 xfs_perag_next(
203 	struct xfs_mount	*mp,
204 	struct xfs_perag	*pag)
205 {
206 	return xfs_perag_next_from(mp, pag, 0);
207 }
208 
209 /*
210  * Per-ag geometry infomation and validation
211  */
212 xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
213 void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
214 		xfs_agino_t *first, xfs_agino_t *last);
215 
216 static inline bool
217 xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno)
218 {
219 	return xfs_verify_gbno(pag_group(pag), agbno);
220 }
221 
222 static inline bool
223 xfs_verify_agbext(
224 	struct xfs_perag	*pag,
225 	xfs_agblock_t		agbno,
226 	xfs_agblock_t		len)
227 {
228 	return xfs_verify_gbext(pag_group(pag), agbno, len);
229 }
230 
231 /*
232  * Verify that an AG inode number pointer neither points outside the AG
233  * nor points at static metadata.
234  */
235 static inline bool
236 xfs_verify_agino(struct xfs_perag *pag, xfs_agino_t agino)
237 {
238 	if (agino < pag->agino_min)
239 		return false;
240 	if (agino > pag->agino_max)
241 		return false;
242 	return true;
243 }
244 
245 /*
246  * Verify that an AG inode number pointer neither points outside the AG
247  * nor points at static metadata, or is NULLAGINO.
248  */
249 static inline bool
250 xfs_verify_agino_or_null(struct xfs_perag *pag, xfs_agino_t agino)
251 {
252 	if (agino == NULLAGINO)
253 		return true;
254 	return xfs_verify_agino(pag, agino);
255 }
256 
257 static inline bool
258 xfs_ag_contains_log(struct xfs_mount *mp, xfs_agnumber_t agno)
259 {
260 	return mp->m_sb.sb_logstart > 0 &&
261 	       agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
262 }
263 
264 static inline struct xfs_perag *
265 xfs_perag_next_wrap(
266 	struct xfs_perag	*pag,
267 	xfs_agnumber_t		*agno,
268 	xfs_agnumber_t		stop_agno,
269 	xfs_agnumber_t		restart_agno,
270 	xfs_agnumber_t		wrap_agno)
271 {
272 	struct xfs_mount	*mp = pag_mount(pag);
273 
274 	*agno = pag_agno(pag) + 1;
275 	xfs_perag_rele(pag);
276 	while (*agno != stop_agno) {
277 		if (*agno >= wrap_agno) {
278 			if (restart_agno >= stop_agno)
279 				break;
280 			*agno = restart_agno;
281 		}
282 
283 		pag = xfs_perag_grab(mp, *agno);
284 		if (pag)
285 			return pag;
286 		(*agno)++;
287 	}
288 	return NULL;
289 }
290 
291 /*
292  * Iterate all AGs from start_agno through wrap_agno, then restart_agno through
293  * (start_agno - 1).
294  */
295 #define for_each_perag_wrap_range(mp, start_agno, restart_agno, wrap_agno, agno, pag) \
296 	for ((agno) = (start_agno), (pag) = xfs_perag_grab((mp), (agno)); \
297 		(pag) != NULL; \
298 		(pag) = xfs_perag_next_wrap((pag), &(agno), (start_agno), \
299 				(restart_agno), (wrap_agno)))
300 /*
301  * Iterate all AGs from start_agno through wrap_agno, then 0 through
302  * (start_agno - 1).
303  */
304 #define for_each_perag_wrap_at(mp, start_agno, wrap_agno, agno, pag) \
305 	for_each_perag_wrap_range((mp), (start_agno), 0, (wrap_agno), (agno), (pag))
306 
307 /*
308  * Iterate all AGs from start_agno through to the end of the filesystem, then 0
309  * through (start_agno - 1).
310  */
311 #define for_each_perag_wrap(mp, start_agno, agno, pag) \
312 	for_each_perag_wrap_at((mp), (start_agno), (mp)->m_sb.sb_agcount, \
313 				(agno), (pag))
314 
315 
316 struct aghdr_init_data {
317 	/* per ag data */
318 	xfs_agblock_t		agno;		/* ag to init */
319 	xfs_extlen_t		agsize;		/* new AG size */
320 	struct list_head	buffer_list;	/* buffer writeback list */
321 	xfs_rfsblock_t		nfree;		/* cumulative new free space */
322 
323 	/* per header data */
324 	xfs_daddr_t		daddr;		/* header location */
325 	size_t			numblks;	/* size of header */
326 	const struct xfs_btree_ops *bc_ops;	/* btree ops */
327 };
328 
329 int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id);
330 int xfs_ag_shrink_space(struct xfs_perag *pag, struct xfs_trans **tpp,
331 			xfs_extlen_t delta);
332 void
333 xfs_growfs_compute_deltas(struct xfs_mount *mp, xfs_rfsblock_t nb,
334 			int64_t *deltap, xfs_agnumber_t *nagcountp);
335 int xfs_ag_extend_space(struct xfs_perag *pag, struct xfs_trans *tp,
336 			xfs_extlen_t len);
337 int xfs_ag_get_geometry(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);
338 
339 static inline xfs_fsblock_t
340 xfs_agbno_to_fsb(
341 	struct xfs_perag	*pag,
342 	xfs_agblock_t		agbno)
343 {
344 	return XFS_AGB_TO_FSB(pag_mount(pag), pag_agno(pag), agbno);
345 }
346 
347 static inline xfs_daddr_t
348 xfs_agbno_to_daddr(
349 	struct xfs_perag	*pag,
350 	xfs_agblock_t		agbno)
351 {
352 	return XFS_AGB_TO_DADDR(pag_mount(pag), pag_agno(pag), agbno);
353 }
354 
355 static inline xfs_ino_t
356 xfs_agino_to_ino(
357 	struct xfs_perag	*pag,
358 	xfs_agino_t		agino)
359 {
360 	return XFS_AGINO_TO_INO(pag_mount(pag), pag_agno(pag), agino);
361 }
362 
363 #endif /* __LIBXFS_AG_H */
364