162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *   Copyright (C) International Business Machines Corp., 2000-2002
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#ifndef	_H_JFS_DMAP
662306a36Sopenharmony_ci#define _H_JFS_DMAP
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "jfs_txnmgr.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#define BMAPVERSION	1	/* version number */
1162306a36Sopenharmony_ci#define	TREESIZE	(256+64+16+4+1)	/* size of a dmap tree */
1262306a36Sopenharmony_ci#define	LEAFIND		(64+16+4+1)	/* index of 1st leaf of a dmap tree */
1362306a36Sopenharmony_ci#define LPERDMAP	256	/* num leaves per dmap tree */
1462306a36Sopenharmony_ci#define L2LPERDMAP	8	/* l2 number of leaves per dmap tree */
1562306a36Sopenharmony_ci#define	DBWORD		32	/* # of blks covered by a map word */
1662306a36Sopenharmony_ci#define	L2DBWORD	5	/* l2 # of blks covered by a mword */
1762306a36Sopenharmony_ci#define BUDMIN		L2DBWORD	/* max free string in a map word */
1862306a36Sopenharmony_ci#define BPERDMAP	(LPERDMAP * DBWORD)	/* num of blks per dmap */
1962306a36Sopenharmony_ci#define L2BPERDMAP	13	/* l2 num of blks per dmap */
2062306a36Sopenharmony_ci#define CTLTREESIZE	(1024+256+64+16+4+1)	/* size of a dmapctl tree */
2162306a36Sopenharmony_ci#define CTLLEAFIND	(256+64+16+4+1)	/* idx of 1st leaf of a dmapctl tree */
2262306a36Sopenharmony_ci#define LPERCTL		1024	/* num of leaves per dmapctl tree */
2362306a36Sopenharmony_ci#define L2LPERCTL	10	/* l2 num of leaves per dmapctl tree */
2462306a36Sopenharmony_ci#define	ROOT		0	/* index of the root of a tree */
2562306a36Sopenharmony_ci#define	NOFREE		((s8) -1)	/* no blocks free */
2662306a36Sopenharmony_ci#define	MAXAG		128	/* max number of allocation groups */
2762306a36Sopenharmony_ci#define L2MAXAG		7	/* l2 max num of AG */
2862306a36Sopenharmony_ci#define L2MINAGSZ	25	/* l2 of minimum AG size in bytes */
2962306a36Sopenharmony_ci#define	BMAPBLKNO	0	/* lblkno of bmap within the map */
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci/*
3262306a36Sopenharmony_ci * maximum l2 number of disk blocks at the various dmapctl levels.
3362306a36Sopenharmony_ci */
3462306a36Sopenharmony_ci#define	L2MAXL0SIZE	(L2BPERDMAP + 1 * L2LPERCTL)
3562306a36Sopenharmony_ci#define	L2MAXL1SIZE	(L2BPERDMAP + 2 * L2LPERCTL)
3662306a36Sopenharmony_ci#define	L2MAXL2SIZE	(L2BPERDMAP + 3 * L2LPERCTL)
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/*
3962306a36Sopenharmony_ci * maximum number of disk blocks at the various dmapctl levels.
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_ci#define	MAXL0SIZE	((s64)1 << L2MAXL0SIZE)
4262306a36Sopenharmony_ci#define	MAXL1SIZE	((s64)1 << L2MAXL1SIZE)
4362306a36Sopenharmony_ci#define	MAXL2SIZE	((s64)1 << L2MAXL2SIZE)
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define	MAXMAPSIZE	MAXL2SIZE	/* maximum aggregate map size */
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/*
4862306a36Sopenharmony_ci * determine the maximum free string for four (lower level) nodes
4962306a36Sopenharmony_ci * of the tree.
5062306a36Sopenharmony_ci */
5162306a36Sopenharmony_cistatic inline signed char TREEMAX(signed char *cp)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	signed char tmp1, tmp2;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	tmp1 = max(*(cp+2), *(cp+3));
5662306a36Sopenharmony_ci	tmp2 = max(*(cp), *(cp+1));
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	return max(tmp1, tmp2);
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci/*
6262306a36Sopenharmony_ci * convert disk block number to the logical block number of the dmap
6362306a36Sopenharmony_ci * describing the disk block.  s is the log2(number of logical blocks per page)
6462306a36Sopenharmony_ci *
6562306a36Sopenharmony_ci * The calculation figures out how many logical pages are in front of the dmap.
6662306a36Sopenharmony_ci *	- the number of dmaps preceding it
6762306a36Sopenharmony_ci *	- the number of L0 pages preceding its L0 page
6862306a36Sopenharmony_ci *	- the number of L1 pages preceding its L1 page
6962306a36Sopenharmony_ci *	- 3 is added to account for the L2, L1, and L0 page for this dmap
7062306a36Sopenharmony_ci *	- 1 is added to account for the control page of the map.
7162306a36Sopenharmony_ci */
7262306a36Sopenharmony_ci#define BLKTODMAP(b,s)    \
7362306a36Sopenharmony_ci	((((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1) << (s))
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci/*
7662306a36Sopenharmony_ci * convert disk block number to the logical block number of the LEVEL 0
7762306a36Sopenharmony_ci * dmapctl describing the disk block.  s is the log2(number of logical blocks
7862306a36Sopenharmony_ci * per page)
7962306a36Sopenharmony_ci *
8062306a36Sopenharmony_ci * The calculation figures out how many logical pages are in front of the L0.
8162306a36Sopenharmony_ci *	- the number of dmap pages preceding it
8262306a36Sopenharmony_ci *	- the number of L0 pages preceding it
8362306a36Sopenharmony_ci *	- the number of L1 pages preceding its L1 page
8462306a36Sopenharmony_ci *	- 2 is added to account for the L2, and L1 page for this L0
8562306a36Sopenharmony_ci *	- 1 is added to account for the control page of the map.
8662306a36Sopenharmony_ci */
8762306a36Sopenharmony_ci#define BLKTOL0(b,s)      \
8862306a36Sopenharmony_ci	(((((b) >> 23) << 10) + ((b) >> 23) + ((b) >> 33) + 2 + 1) << (s))
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/*
9162306a36Sopenharmony_ci * convert disk block number to the logical block number of the LEVEL 1
9262306a36Sopenharmony_ci * dmapctl describing the disk block.  s is the log2(number of logical blocks
9362306a36Sopenharmony_ci * per page)
9462306a36Sopenharmony_ci *
9562306a36Sopenharmony_ci * The calculation figures out how many logical pages are in front of the L1.
9662306a36Sopenharmony_ci *	- the number of dmap pages preceding it
9762306a36Sopenharmony_ci *	- the number of L0 pages preceding it
9862306a36Sopenharmony_ci *	- the number of L1 pages preceding it
9962306a36Sopenharmony_ci *	- 1 is added to account for the L2 page
10062306a36Sopenharmony_ci *	- 1 is added to account for the control page of the map.
10162306a36Sopenharmony_ci */
10262306a36Sopenharmony_ci#define BLKTOL1(b,s)      \
10362306a36Sopenharmony_ci     (((((b) >> 33) << 20) + (((b) >> 33) << 10) + ((b) >> 33) + 1 + 1) << (s))
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/*
10662306a36Sopenharmony_ci * convert disk block number to the logical block number of the dmapctl
10762306a36Sopenharmony_ci * at the specified level which describes the disk block.
10862306a36Sopenharmony_ci */
10962306a36Sopenharmony_ci#define BLKTOCTL(b,s,l)   \
11062306a36Sopenharmony_ci	(((l) == 2) ? 1 : ((l) == 1) ? BLKTOL1((b),(s)) : BLKTOL0((b),(s)))
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/*
11362306a36Sopenharmony_ci * convert aggregate map size to the zero origin dmapctl level of the
11462306a36Sopenharmony_ci * top dmapctl.
11562306a36Sopenharmony_ci */
11662306a36Sopenharmony_ci#define	BMAPSZTOLEV(size)	\
11762306a36Sopenharmony_ci	(((size) <= MAXL0SIZE) ? 0 : ((size) <= MAXL1SIZE) ? 1 : 2)
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci/* convert disk block number to allocation group number.
12062306a36Sopenharmony_ci */
12162306a36Sopenharmony_ci#define BLKTOAG(b,sbi)	((b) >> ((sbi)->bmap->db_agl2size))
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci/* convert allocation group number to starting disk block
12462306a36Sopenharmony_ci * number.
12562306a36Sopenharmony_ci */
12662306a36Sopenharmony_ci#define AGTOBLK(a,ip)	\
12762306a36Sopenharmony_ci	((s64)(a) << (JFS_SBI((ip)->i_sb)->bmap->db_agl2size))
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci/*
13062306a36Sopenharmony_ci *	dmap summary tree
13162306a36Sopenharmony_ci *
13262306a36Sopenharmony_ci * dmaptree must be consistent with dmapctl.
13362306a36Sopenharmony_ci */
13462306a36Sopenharmony_cistruct dmaptree {
13562306a36Sopenharmony_ci	__le32 nleafs;		/* 4: number of tree leafs	*/
13662306a36Sopenharmony_ci	__le32 l2nleafs;	/* 4: l2 number of tree leafs	*/
13762306a36Sopenharmony_ci	__le32 leafidx;		/* 4: index of first tree leaf	*/
13862306a36Sopenharmony_ci	__le32 height;		/* 4: height of the tree	*/
13962306a36Sopenharmony_ci	s8 budmin;		/* 1: min l2 tree leaf value to combine */
14062306a36Sopenharmony_ci	s8 stree[TREESIZE];	/* TREESIZE: tree		*/
14162306a36Sopenharmony_ci	u8 pad[2];		/* 2: pad to word boundary	*/
14262306a36Sopenharmony_ci};				/* - 360 -			*/
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci/*
14562306a36Sopenharmony_ci *	dmap page per 8K blocks bitmap
14662306a36Sopenharmony_ci */
14762306a36Sopenharmony_cistruct dmap {
14862306a36Sopenharmony_ci	__le32 nblocks;		/* 4: num blks covered by this dmap	*/
14962306a36Sopenharmony_ci	__le32 nfree;		/* 4: num of free blks in this dmap	*/
15062306a36Sopenharmony_ci	__le64 start;		/* 8: starting blkno for this dmap	*/
15162306a36Sopenharmony_ci	struct dmaptree tree;	/* 360: dmap tree			*/
15262306a36Sopenharmony_ci	u8 pad[1672];		/* 1672: pad to 2048 bytes		*/
15362306a36Sopenharmony_ci	__le32 wmap[LPERDMAP];	/* 1024: bits of the working map	*/
15462306a36Sopenharmony_ci	__le32 pmap[LPERDMAP];	/* 1024: bits of the persistent map	*/
15562306a36Sopenharmony_ci};				/* - 4096 -				*/
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci/*
15862306a36Sopenharmony_ci *	disk map control page per level.
15962306a36Sopenharmony_ci *
16062306a36Sopenharmony_ci * dmapctl must be consistent with dmaptree.
16162306a36Sopenharmony_ci */
16262306a36Sopenharmony_cistruct dmapctl {
16362306a36Sopenharmony_ci	__le32 nleafs;		/* 4: number of tree leafs	*/
16462306a36Sopenharmony_ci	__le32 l2nleafs;	/* 4: l2 number of tree leafs	*/
16562306a36Sopenharmony_ci	__le32 leafidx;		/* 4: index of the first tree leaf	*/
16662306a36Sopenharmony_ci	__le32 height;		/* 4: height of tree		*/
16762306a36Sopenharmony_ci	s8 budmin;		/* 1: minimum l2 tree leaf value	*/
16862306a36Sopenharmony_ci	s8 stree[CTLTREESIZE];	/* CTLTREESIZE: dmapctl tree	*/
16962306a36Sopenharmony_ci	u8 pad[2714];		/* 2714: pad to 4096		*/
17062306a36Sopenharmony_ci};				/* - 4096 -			*/
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci/*
17362306a36Sopenharmony_ci *	common definition for dmaptree within dmap and dmapctl
17462306a36Sopenharmony_ci */
17562306a36Sopenharmony_citypedef union dmtree {
17662306a36Sopenharmony_ci	struct dmaptree t1;
17762306a36Sopenharmony_ci	struct dmapctl t2;
17862306a36Sopenharmony_ci} dmtree_t;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci/* macros for accessing fields within dmtree */
18162306a36Sopenharmony_ci#define	dmt_nleafs	t1.nleafs
18262306a36Sopenharmony_ci#define	dmt_l2nleafs	t1.l2nleafs
18362306a36Sopenharmony_ci#define	dmt_leafidx	t1.leafidx
18462306a36Sopenharmony_ci#define	dmt_height	t1.height
18562306a36Sopenharmony_ci#define	dmt_budmin	t1.budmin
18662306a36Sopenharmony_ci#define	dmt_stree	t2.stree
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci/*
18962306a36Sopenharmony_ci *	on-disk aggregate disk allocation map descriptor.
19062306a36Sopenharmony_ci */
19162306a36Sopenharmony_cistruct dbmap_disk {
19262306a36Sopenharmony_ci	__le64 dn_mapsize;	/* 8: number of blocks in aggregate	*/
19362306a36Sopenharmony_ci	__le64 dn_nfree;	/* 8: num free blks in aggregate map	*/
19462306a36Sopenharmony_ci	__le32 dn_l2nbperpage;	/* 4: number of blks per page		*/
19562306a36Sopenharmony_ci	__le32 dn_numag;	/* 4: total number of ags		*/
19662306a36Sopenharmony_ci	__le32 dn_maxlevel;	/* 4: number of active ags		*/
19762306a36Sopenharmony_ci	__le32 dn_maxag;	/* 4: max active alloc group number	*/
19862306a36Sopenharmony_ci	__le32 dn_agpref;	/* 4: preferred alloc group (hint)	*/
19962306a36Sopenharmony_ci	__le32 dn_aglevel;	/* 4: dmapctl level holding the AG	*/
20062306a36Sopenharmony_ci	__le32 dn_agheight;	/* 4: height in dmapctl of the AG	*/
20162306a36Sopenharmony_ci	__le32 dn_agwidth;	/* 4: width in dmapctl of the AG	*/
20262306a36Sopenharmony_ci	__le32 dn_agstart;	/* 4: start tree index at AG height	*/
20362306a36Sopenharmony_ci	__le32 dn_agl2size;	/* 4: l2 num of blks per alloc group	*/
20462306a36Sopenharmony_ci	__le64 dn_agfree[MAXAG];/* 8*MAXAG: per AG free count		*/
20562306a36Sopenharmony_ci	__le64 dn_agsize;	/* 8: num of blks per alloc group	*/
20662306a36Sopenharmony_ci	s8 dn_maxfreebud;	/* 1: max free buddy system		*/
20762306a36Sopenharmony_ci	u8 pad[3007];		/* 3007: pad to 4096			*/
20862306a36Sopenharmony_ci};				/* - 4096 -				*/
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_cistruct dbmap {
21162306a36Sopenharmony_ci	s64 dn_mapsize;		/* number of blocks in aggregate	*/
21262306a36Sopenharmony_ci	s64 dn_nfree;		/* num free blks in aggregate map	*/
21362306a36Sopenharmony_ci	int dn_l2nbperpage;	/* number of blks per page		*/
21462306a36Sopenharmony_ci	int dn_numag;		/* total number of ags			*/
21562306a36Sopenharmony_ci	int dn_maxlevel;	/* number of active ags			*/
21662306a36Sopenharmony_ci	int dn_maxag;		/* max active alloc group number	*/
21762306a36Sopenharmony_ci	int dn_agpref;		/* preferred alloc group (hint)		*/
21862306a36Sopenharmony_ci	int dn_aglevel;		/* dmapctl level holding the AG		*/
21962306a36Sopenharmony_ci	int dn_agheight;	/* height in dmapctl of the AG		*/
22062306a36Sopenharmony_ci	int dn_agwidth;		/* width in dmapctl of the AG		*/
22162306a36Sopenharmony_ci	int dn_agstart;		/* start tree index at AG height	*/
22262306a36Sopenharmony_ci	int dn_agl2size;	/* l2 num of blks per alloc group	*/
22362306a36Sopenharmony_ci	s64 dn_agfree[MAXAG];	/* per AG free count			*/
22462306a36Sopenharmony_ci	s64 dn_agsize;		/* num of blks per alloc group		*/
22562306a36Sopenharmony_ci	signed char dn_maxfreebud;	/* max free buddy system	*/
22662306a36Sopenharmony_ci};				/* - 4096 -				*/
22762306a36Sopenharmony_ci/*
22862306a36Sopenharmony_ci *	in-memory aggregate disk allocation map descriptor.
22962306a36Sopenharmony_ci */
23062306a36Sopenharmony_cistruct bmap {
23162306a36Sopenharmony_ci	struct dbmap db_bmap;		/* on-disk aggregate map descriptor */
23262306a36Sopenharmony_ci	struct inode *db_ipbmap;	/* ptr to aggregate map incore inode */
23362306a36Sopenharmony_ci	struct mutex db_bmaplock;	/* aggregate map lock */
23462306a36Sopenharmony_ci	atomic_t db_active[MAXAG];	/* count of active, open files in AG */
23562306a36Sopenharmony_ci	u32 *db_DBmap;
23662306a36Sopenharmony_ci};
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci/* macros for accessing fields within in-memory aggregate map descriptor */
23962306a36Sopenharmony_ci#define	db_mapsize	db_bmap.dn_mapsize
24062306a36Sopenharmony_ci#define	db_nfree	db_bmap.dn_nfree
24162306a36Sopenharmony_ci#define	db_agfree	db_bmap.dn_agfree
24262306a36Sopenharmony_ci#define	db_agsize	db_bmap.dn_agsize
24362306a36Sopenharmony_ci#define	db_agl2size	db_bmap.dn_agl2size
24462306a36Sopenharmony_ci#define	db_agwidth	db_bmap.dn_agwidth
24562306a36Sopenharmony_ci#define	db_agheight	db_bmap.dn_agheight
24662306a36Sopenharmony_ci#define	db_agstart	db_bmap.dn_agstart
24762306a36Sopenharmony_ci#define	db_numag	db_bmap.dn_numag
24862306a36Sopenharmony_ci#define	db_maxlevel	db_bmap.dn_maxlevel
24962306a36Sopenharmony_ci#define	db_aglevel	db_bmap.dn_aglevel
25062306a36Sopenharmony_ci#define	db_agpref	db_bmap.dn_agpref
25162306a36Sopenharmony_ci#define	db_maxag	db_bmap.dn_maxag
25262306a36Sopenharmony_ci#define	db_maxfreebud	db_bmap.dn_maxfreebud
25362306a36Sopenharmony_ci#define	db_l2nbperpage	db_bmap.dn_l2nbperpage
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci/*
25662306a36Sopenharmony_ci * macros for various conversions needed by the allocators.
25762306a36Sopenharmony_ci * blkstol2(), cntlz(), and cnttz() are operating system dependent functions.
25862306a36Sopenharmony_ci */
25962306a36Sopenharmony_ci/* convert number of blocks to log2 number of blocks, rounding up to
26062306a36Sopenharmony_ci * the next log2 value if blocks is not a l2 multiple.
26162306a36Sopenharmony_ci */
26262306a36Sopenharmony_ci#define	BLKSTOL2(d)		(blkstol2(d))
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci/* convert number of leafs to log2 leaf value */
26562306a36Sopenharmony_ci#define	NLSTOL2BSZ(n)		(31 - cntlz((n)) + BUDMIN)
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci/* convert leaf index to log2 leaf value */
26862306a36Sopenharmony_ci#define	LITOL2BSZ(n,m,b)	((((n) == 0) ? (m) : cnttz((n))) + (b))
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci/* convert a block number to a dmap control leaf index */
27162306a36Sopenharmony_ci#define BLKTOCTLLEAF(b,m)	\
27262306a36Sopenharmony_ci	(((b) & (((s64)1 << ((m) + L2LPERCTL)) - 1)) >> (m))
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci/* convert log2 leaf value to buddy size */
27562306a36Sopenharmony_ci#define	BUDSIZE(s,m)		(1 << ((s) - (m)))
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci/*
27862306a36Sopenharmony_ci *	external references.
27962306a36Sopenharmony_ci */
28062306a36Sopenharmony_ciextern int dbMount(struct inode *ipbmap);
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ciextern int dbUnmount(struct inode *ipbmap, int mounterror);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ciextern int dbFree(struct inode *ipbmap, s64 blkno, s64 nblocks);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ciextern int dbUpdatePMap(struct inode *ipbmap,
28762306a36Sopenharmony_ci			int free, s64 blkno, s64 nblocks, struct tblock * tblk);
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ciextern int dbNextAG(struct inode *ipbmap);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ciextern int dbAlloc(struct inode *ipbmap, s64 hint, s64 nblocks, s64 * results);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ciextern int dbReAlloc(struct inode *ipbmap,
29462306a36Sopenharmony_ci		     s64 blkno, s64 nblocks, s64 addnblocks, s64 * results);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ciextern int dbSync(struct inode *ipbmap);
29762306a36Sopenharmony_ciextern int dbAllocBottomUp(struct inode *ip, s64 blkno, s64 nblocks);
29862306a36Sopenharmony_ciextern int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks);
29962306a36Sopenharmony_ciextern void dbFinalizeBmap(struct inode *ipbmap);
30062306a36Sopenharmony_ciextern s64 dbMapFileSizeToMapSize(struct inode *ipbmap);
30162306a36Sopenharmony_ciextern s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci#endif				/* _H_JFS_DMAP */
304