brintos

brintos / linux-shallow public Read only

0
0
Text · 9.5 KiB · 9edfe0e Raw
336 lines · c
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_H8#define __LIBXFS_AG_H 19 10struct xfs_mount;11struct xfs_trans;12struct xfs_perag;13 14/*15 * Per-ag infrastructure16 */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 the30 * 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_bno_level;	/* # of levels in bno btree */40	uint8_t		pagf_cnt_level;	/* # of levels in cnt btree */41	uint8_t		pagf_rmap_level;/* # of levels in rmap btree */42	uint32_t	pagf_flcount;	/* count of blocks in freelist */43	xfs_extlen_t	pagf_freeblks;	/* total free blocks */44	xfs_extlen_t	pagf_longest;	/* longest free space */45	uint32_t	pagf_btreeblks;	/* # of blocks held in AGF btrees */46	xfs_agino_t	pagi_freecount;	/* number of free inodes */47	xfs_agino_t	pagi_count;	/* number of allocated inodes */48 49	/*50	 * Inode allocation search lookup optimisation.51	 * If the pagino matches, the search for new inodes52	 * doesn't need to search the near ones again straight away53	 */54	xfs_agino_t	pagl_pagino;55	xfs_agino_t	pagl_leftrec;56	xfs_agino_t	pagl_rightrec;57 58	int		pagb_count;	/* pagb slots in use */59	uint8_t		pagf_refcount_level; /* recount btree height */60 61	/* Blocks reserved for all kinds of metadata. */62	struct xfs_ag_resv	pag_meta_resv;63	/* Blocks reserved for the reverse mapping btree. */64	struct xfs_ag_resv	pag_rmapbt_resv;65 66	/* Precalculated geometry info */67	xfs_agblock_t		block_count;68	xfs_agblock_t		min_block;69	xfs_agino_t		agino_min;70	xfs_agino_t		agino_max;71 72#ifdef __KERNEL__73	/* -- kernel only structures below this line -- */74 75	/*76	 * Bitsets of per-ag metadata that have been checked and/or are sick.77	 * Callers should hold pag_state_lock before accessing this field.78	 */79	uint16_t	pag_checked;80	uint16_t	pag_sick;81 82#ifdef CONFIG_XFS_ONLINE_REPAIR83	/*84	 * Alternate btree heights so that online repair won't trip the write85	 * verifiers while rebuilding the AG btrees.86	 */87	uint8_t		pagf_repair_bno_level;88	uint8_t		pagf_repair_cnt_level;89	uint8_t		pagf_repair_refcount_level;90	uint8_t		pagf_repair_rmap_level;91#endif92 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 items114	 * 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 middle116	 * of processing a chain of intent items only to find momentary117	 * 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		0130#define XFS_AGSTATE_AGI_INIT		1131#define XFS_AGSTATE_PREFERS_METADATA	2132#define XFS_AGSTATE_ALLOWS_INODES	3133#define XFS_AGSTATE_AGFL_NEEDS_RESET	4134 135#define __XFS_AG_OPSTATE(name, NAME) \136static inline bool xfs_perag_ ## name (struct xfs_perag *pag) \137{ \138	return test_bit(XFS_AGSTATE_ ## NAME, &pag->pag_opstate); \139}140 141__XFS_AG_OPSTATE(initialised_agf, AGF_INIT)142__XFS_AG_OPSTATE(initialised_agi, AGI_INIT)143__XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA)144__XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES)145__XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)146 147int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t old_agcount,148		xfs_agnumber_t agcount, xfs_rfsblock_t dcount,149		xfs_agnumber_t *maxagi);150void xfs_free_perag_range(struct xfs_mount *mp, xfs_agnumber_t first_agno,151		xfs_agnumber_t end_agno);152int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);153int xfs_update_last_ag_size(struct xfs_mount *mp, xfs_agnumber_t prev_agcount);154 155/* Passive AG references */156struct xfs_perag *xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno);157struct xfs_perag *xfs_perag_hold(struct xfs_perag *pag);158void xfs_perag_put(struct xfs_perag *pag);159 160/* Active AG references */161struct xfs_perag *xfs_perag_grab(struct xfs_mount *, xfs_agnumber_t);162void xfs_perag_rele(struct xfs_perag *pag);163 164/*165 * Per-ag geometry infomation and validation166 */167xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);168void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,169		xfs_agino_t *first, xfs_agino_t *last);170 171static inline bool172xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno)173{174	if (agbno >= pag->block_count)175		return false;176	if (agbno <= pag->min_block)177		return false;178	return true;179}180 181static inline bool182xfs_verify_agbext(183	struct xfs_perag	*pag,184	xfs_agblock_t		agbno,185	xfs_agblock_t		len)186{187	if (agbno + len <= agbno)188		return false;189 190	if (!xfs_verify_agbno(pag, agbno))191		return false;192 193	return xfs_verify_agbno(pag, agbno + len - 1);194}195 196/*197 * Verify that an AG inode number pointer neither points outside the AG198 * nor points at static metadata.199 */200static inline bool201xfs_verify_agino(struct xfs_perag *pag, xfs_agino_t agino)202{203	if (agino < pag->agino_min)204		return false;205	if (agino > pag->agino_max)206		return false;207	return true;208}209 210/*211 * Verify that an AG inode number pointer neither points outside the AG212 * nor points at static metadata, or is NULLAGINO.213 */214static inline bool215xfs_verify_agino_or_null(struct xfs_perag *pag, xfs_agino_t agino)216{217	if (agino == NULLAGINO)218		return true;219	return xfs_verify_agino(pag, agino);220}221 222static inline bool223xfs_ag_contains_log(struct xfs_mount *mp, xfs_agnumber_t agno)224{225	return mp->m_sb.sb_logstart > 0 &&226	       agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);227}228 229/*230 * Perag iteration APIs231 */232static inline struct xfs_perag *233xfs_perag_next(234	struct xfs_perag	*pag,235	xfs_agnumber_t		*agno,236	xfs_agnumber_t		end_agno)237{238	struct xfs_mount	*mp = pag->pag_mount;239 240	*agno = pag->pag_agno + 1;241	xfs_perag_rele(pag);242	while (*agno <= end_agno) {243		pag = xfs_perag_grab(mp, *agno);244		if (pag)245			return pag;246		(*agno)++;247	}248	return NULL;249}250 251#define for_each_perag_range(mp, agno, end_agno, pag) \252	for ((pag) = xfs_perag_grab((mp), (agno)); \253		(pag) != NULL; \254		(pag) = xfs_perag_next((pag), &(agno), (end_agno)))255 256#define for_each_perag_from(mp, agno, pag) \257	for_each_perag_range((mp), (agno), (mp)->m_sb.sb_agcount - 1, (pag))258 259#define for_each_perag(mp, agno, pag) \260	(agno) = 0; \261	for_each_perag_from((mp), (agno), (pag))262 263static inline struct xfs_perag *264xfs_perag_next_wrap(265	struct xfs_perag	*pag,266	xfs_agnumber_t		*agno,267	xfs_agnumber_t		stop_agno,268	xfs_agnumber_t		restart_agno,269	xfs_agnumber_t		wrap_agno)270{271	struct xfs_mount	*mp = pag->pag_mount;272 273	*agno = pag->pag_agno + 1;274	xfs_perag_rele(pag);275	while (*agno != stop_agno) {276		if (*agno >= wrap_agno) {277			if (restart_agno >= stop_agno)278				break;279			*agno = restart_agno;280		}281 282		pag = xfs_perag_grab(mp, *agno);283		if (pag)284			return pag;285		(*agno)++;286	}287	return NULL;288}289 290/*291 * Iterate all AGs from start_agno through wrap_agno, then restart_agno through292 * (start_agno - 1).293 */294#define for_each_perag_wrap_range(mp, start_agno, restart_agno, wrap_agno, agno, pag) \295	for ((agno) = (start_agno), (pag) = xfs_perag_grab((mp), (agno)); \296		(pag) != NULL; \297		(pag) = xfs_perag_next_wrap((pag), &(agno), (start_agno), \298				(restart_agno), (wrap_agno)))299/*300 * Iterate all AGs from start_agno through wrap_agno, then 0 through301 * (start_agno - 1).302 */303#define for_each_perag_wrap_at(mp, start_agno, wrap_agno, agno, pag) \304	for_each_perag_wrap_range((mp), (start_agno), 0, (wrap_agno), (agno), (pag))305 306/*307 * Iterate all AGs from start_agno through to the end of the filesystem, then 0308 * through (start_agno - 1).309 */310#define for_each_perag_wrap(mp, start_agno, agno, pag) \311	for_each_perag_wrap_at((mp), (start_agno), (mp)->m_sb.sb_agcount, \312				(agno), (pag))313 314 315struct aghdr_init_data {316	/* per ag data */317	xfs_agblock_t		agno;		/* ag to init */318	xfs_extlen_t		agsize;		/* new AG size */319	struct list_head	buffer_list;	/* buffer writeback list */320	xfs_rfsblock_t		nfree;		/* cumulative new free space */321 322	/* per header data */323	xfs_daddr_t		daddr;		/* header location */324	size_t			numblks;	/* size of header */325	const struct xfs_btree_ops *bc_ops;	/* btree ops */326};327 328int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id);329int xfs_ag_shrink_space(struct xfs_perag *pag, struct xfs_trans **tpp,330			xfs_extlen_t delta);331int xfs_ag_extend_space(struct xfs_perag *pag, struct xfs_trans *tp,332			xfs_extlen_t len);333int xfs_ag_get_geometry(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);334 335#endif /* __LIBXFS_AG_H */336