xref: /openbmc/linux/fs/ext4/mballoc.h (revision f5166768)
1f5166768STheodore Ts'o // SPDX-License-Identifier: GPL-2.0
28f6e39a7SMingming Cao /*
38f6e39a7SMingming Cao  *  fs/ext4/mballoc.h
48f6e39a7SMingming Cao  *
58f6e39a7SMingming Cao  *  Written by: Alex Tomas <alex@clusterfs.com>
68f6e39a7SMingming Cao  *
78f6e39a7SMingming Cao  */
88f6e39a7SMingming Cao #ifndef _EXT4_MBALLOC_H
98f6e39a7SMingming Cao #define _EXT4_MBALLOC_H
108f6e39a7SMingming Cao 
118f6e39a7SMingming Cao #include <linux/time.h>
128f6e39a7SMingming Cao #include <linux/fs.h>
138f6e39a7SMingming Cao #include <linux/namei.h>
148f6e39a7SMingming Cao #include <linux/quotaops.h>
158f6e39a7SMingming Cao #include <linux/buffer_head.h>
168f6e39a7SMingming Cao #include <linux/module.h>
178f6e39a7SMingming Cao #include <linux/swap.h>
188f6e39a7SMingming Cao #include <linux/proc_fs.h>
198f6e39a7SMingming Cao #include <linux/pagemap.h>
208f6e39a7SMingming Cao #include <linux/seq_file.h>
218a0aba73STheodore Ts'o #include <linux/blkdev.h>
22920313a7SAneesh Kumar K.V #include <linux/mutex.h>
238f6e39a7SMingming Cao #include "ext4_jbd2.h"
248f6e39a7SMingming Cao #include "ext4.h"
258f6e39a7SMingming Cao 
268f6e39a7SMingming Cao /*
278f6e39a7SMingming Cao  */
286ba495e9STheodore Ts'o #ifdef CONFIG_EXT4_DEBUG
29a0b30c12STheodore Ts'o extern ushort ext4_mballoc_debug;
306ba495e9STheodore Ts'o 
31d74f3d25SJoe Perches #define mb_debug(n, fmt, ...)	                                        \
326ba495e9STheodore Ts'o do {									\
33a0b30c12STheodore Ts'o 	if ((n) <= ext4_mballoc_debug) {				\
34d74f3d25SJoe Perches 		printk(KERN_DEBUG "(%s, %d): %s: " fmt,			\
35d74f3d25SJoe Perches 		       __FILE__, __LINE__, __func__, ##__VA_ARGS__);	\
366ba495e9STheodore Ts'o 	}								\
376ba495e9STheodore Ts'o } while (0)
388f6e39a7SMingming Cao #else
39d74f3d25SJoe Perches #define mb_debug(n, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
408f6e39a7SMingming Cao #endif
418f6e39a7SMingming Cao 
428f6e39a7SMingming Cao #define EXT4_MB_HISTORY_ALLOC		1	/* allocation */
438f6e39a7SMingming Cao #define EXT4_MB_HISTORY_PREALLOC	2	/* preallocated blocks used */
448f6e39a7SMingming Cao 
458f6e39a7SMingming Cao /*
468f6e39a7SMingming Cao  * How long mballoc can look for a best extent (in found extents)
478f6e39a7SMingming Cao  */
488f6e39a7SMingming Cao #define MB_DEFAULT_MAX_TO_SCAN		200
498f6e39a7SMingming Cao 
508f6e39a7SMingming Cao /*
518f6e39a7SMingming Cao  * How long mballoc must look for a best extent
528f6e39a7SMingming Cao  */
538f6e39a7SMingming Cao #define MB_DEFAULT_MIN_TO_SCAN		10
548f6e39a7SMingming Cao 
558f6e39a7SMingming Cao /*
568f6e39a7SMingming Cao  * with 'ext4_mb_stats' allocator will collect stats that will be
578f6e39a7SMingming Cao  * shown at umount. The collecting costs though!
588f6e39a7SMingming Cao  */
5990576c0bSTheodore Ts'o #define MB_DEFAULT_STATS		0
608f6e39a7SMingming Cao 
618f6e39a7SMingming Cao /*
628f6e39a7SMingming Cao  * files smaller than MB_DEFAULT_STREAM_THRESHOLD are served
638f6e39a7SMingming Cao  * by the stream allocator, which purpose is to pack requests
648f6e39a7SMingming Cao  * as close each to other as possible to produce smooth I/O traffic
658f6e39a7SMingming Cao  * We use locality group prealloc space for stream request.
668f6e39a7SMingming Cao  * We can tune the same via /proc/fs/ext4/<parition>/stream_req
678f6e39a7SMingming Cao  */
688f6e39a7SMingming Cao #define MB_DEFAULT_STREAM_THRESHOLD	16	/* 64K */
698f6e39a7SMingming Cao 
708f6e39a7SMingming Cao /*
718f6e39a7SMingming Cao  * for which requests use 2^N search using buddies
728f6e39a7SMingming Cao  */
738f6e39a7SMingming Cao #define MB_DEFAULT_ORDER2_REQS		2
748f6e39a7SMingming Cao 
758f6e39a7SMingming Cao /*
768f6e39a7SMingming Cao  * default group prealloc size 512 blocks
778f6e39a7SMingming Cao  */
788f6e39a7SMingming Cao #define MB_DEFAULT_GROUP_PREALLOC	512
798f6e39a7SMingming Cao 
808f6e39a7SMingming Cao 
81c894058dSAneesh Kumar K.V struct ext4_free_data {
82a0154344SDaeho Jeong 	/* this links the free block information from sb_info */
83a0154344SDaeho Jeong 	struct list_head		efd_list;
8418aadd47SBobi Jam 
8518aadd47SBobi Jam 	/* this links the free block information from group_info */
8618aadd47SBobi Jam 	struct rb_node			efd_node;
87c894058dSAneesh Kumar K.V 
88c894058dSAneesh Kumar K.V 	/* group which free block extent belongs */
8918aadd47SBobi Jam 	ext4_group_t			efd_group;
90c894058dSAneesh Kumar K.V 
91c894058dSAneesh Kumar K.V 	/* free block extent */
9218aadd47SBobi Jam 	ext4_grpblk_t			efd_start_cluster;
9318aadd47SBobi Jam 	ext4_grpblk_t			efd_count;
94c894058dSAneesh Kumar K.V 
95c894058dSAneesh Kumar K.V 	/* transaction which freed this extent */
9618aadd47SBobi Jam 	tid_t				efd_tid;
978f6e39a7SMingming Cao };
988f6e39a7SMingming Cao 
998f6e39a7SMingming Cao struct ext4_prealloc_space {
1008f6e39a7SMingming Cao 	struct list_head	pa_inode_list;
1018f6e39a7SMingming Cao 	struct list_head	pa_group_list;
1028f6e39a7SMingming Cao 	union {
1038f6e39a7SMingming Cao 		struct list_head pa_tmp_list;
1048f6e39a7SMingming Cao 		struct rcu_head	pa_rcu;
1058f6e39a7SMingming Cao 	} u;
1068f6e39a7SMingming Cao 	spinlock_t		pa_lock;
1078f6e39a7SMingming Cao 	atomic_t		pa_count;
1088f6e39a7SMingming Cao 	unsigned		pa_deleted;
1098f6e39a7SMingming Cao 	ext4_fsblk_t		pa_pstart;	/* phys. block */
1108f6e39a7SMingming Cao 	ext4_lblk_t		pa_lstart;	/* log. block */
111a36b4498SEric Sandeen 	ext4_grpblk_t		pa_len;		/* len of preallocated chunk */
112a36b4498SEric Sandeen 	ext4_grpblk_t		pa_free;	/* how many blocks are free */
113cc0fb9adSAneesh Kumar K.V 	unsigned short		pa_type;	/* pa type. inode or group */
1148f6e39a7SMingming Cao 	spinlock_t		*pa_obj_lock;
1158f6e39a7SMingming Cao 	struct inode		*pa_inode;	/* hack, for history only */
1168f6e39a7SMingming Cao };
1178f6e39a7SMingming Cao 
118cc0fb9adSAneesh Kumar K.V enum {
119cc0fb9adSAneesh Kumar K.V 	MB_INODE_PA = 0,
120cc0fb9adSAneesh Kumar K.V 	MB_GROUP_PA = 1
121cc0fb9adSAneesh Kumar K.V };
1228f6e39a7SMingming Cao 
1238f6e39a7SMingming Cao struct ext4_free_extent {
1248f6e39a7SMingming Cao 	ext4_lblk_t fe_logical;
12553accfa9STheodore Ts'o 	ext4_grpblk_t fe_start;	/* In cluster units */
1268f6e39a7SMingming Cao 	ext4_group_t fe_group;
12753accfa9STheodore Ts'o 	ext4_grpblk_t fe_len;	/* In cluster units */
1288f6e39a7SMingming Cao };
1298f6e39a7SMingming Cao 
1308f6e39a7SMingming Cao /*
1318f6e39a7SMingming Cao  * Locality group:
1328f6e39a7SMingming Cao  *   we try to group all related changes together
1338f6e39a7SMingming Cao  *   so that writeback can flush/allocate them together as well
1346be2ded1SAneesh Kumar K.V  *   Size of lg_prealloc_list hash is determined by MB_DEFAULT_GROUP_PREALLOC
1356be2ded1SAneesh Kumar K.V  *   (512). We store prealloc space into the hash based on the pa_free blocks
1366be2ded1SAneesh Kumar K.V  *   order value.ie, fls(pa_free)-1;
1378f6e39a7SMingming Cao  */
1386be2ded1SAneesh Kumar K.V #define PREALLOC_TB_SIZE 10
1398f6e39a7SMingming Cao struct ext4_locality_group {
1408f6e39a7SMingming Cao 	/* for allocator */
1416be2ded1SAneesh Kumar K.V 	/* to serialize allocates */
1426be2ded1SAneesh Kumar K.V 	struct mutex		lg_mutex;
1436be2ded1SAneesh Kumar K.V 	/* list of preallocations */
1446be2ded1SAneesh Kumar K.V 	struct list_head	lg_prealloc_list[PREALLOC_TB_SIZE];
1458f6e39a7SMingming Cao 	spinlock_t		lg_prealloc_lock;
1468f6e39a7SMingming Cao };
1478f6e39a7SMingming Cao 
1488f6e39a7SMingming Cao struct ext4_allocation_context {
1498f6e39a7SMingming Cao 	struct inode *ac_inode;
1508f6e39a7SMingming Cao 	struct super_block *ac_sb;
1518f6e39a7SMingming Cao 
1528f6e39a7SMingming Cao 	/* original request */
1538f6e39a7SMingming Cao 	struct ext4_free_extent ac_o_ex;
1548f6e39a7SMingming Cao 
15558696f3aSColy Li 	/* goal request (normalized ac_o_ex) */
1568f6e39a7SMingming Cao 	struct ext4_free_extent ac_g_ex;
1578f6e39a7SMingming Cao 
1588f6e39a7SMingming Cao 	/* the best found extent */
1598f6e39a7SMingming Cao 	struct ext4_free_extent ac_b_ex;
1608f6e39a7SMingming Cao 
161ff3fc173SRobin Dong 	/* copy of the best found extent taken before preallocation efforts */
1628f6e39a7SMingming Cao 	struct ext4_free_extent ac_f_ex;
1638f6e39a7SMingming Cao 
1648f6e39a7SMingming Cao 	__u16 ac_groups_scanned;
1658f6e39a7SMingming Cao 	__u16 ac_found;
1668f6e39a7SMingming Cao 	__u16 ac_tail;
1678f6e39a7SMingming Cao 	__u16 ac_buddy;
1688f6e39a7SMingming Cao 	__u16 ac_flags;		/* allocation hints */
1698f6e39a7SMingming Cao 	__u8 ac_status;
1708f6e39a7SMingming Cao 	__u8 ac_criteria;
1718f6e39a7SMingming Cao 	__u8 ac_2order;		/* if request is to allocate 2^N blocks and
1728f6e39a7SMingming Cao 				 * N > 0, the field stores N, otherwise 0 */
1738f6e39a7SMingming Cao 	__u8 ac_op;		/* operation, for history only */
1748f6e39a7SMingming Cao 	struct page *ac_bitmap_page;
1758f6e39a7SMingming Cao 	struct page *ac_buddy_page;
1768f6e39a7SMingming Cao 	struct ext4_prealloc_space *ac_pa;
1778f6e39a7SMingming Cao 	struct ext4_locality_group *ac_lg;
1788f6e39a7SMingming Cao };
1798f6e39a7SMingming Cao 
1808f6e39a7SMingming Cao #define AC_STATUS_CONTINUE	1
1818f6e39a7SMingming Cao #define AC_STATUS_FOUND		2
1828f6e39a7SMingming Cao #define AC_STATUS_BREAK		3
1838f6e39a7SMingming Cao 
1848f6e39a7SMingming Cao struct ext4_buddy {
1858f6e39a7SMingming Cao 	struct page *bd_buddy_page;
1868f6e39a7SMingming Cao 	void *bd_buddy;
1878f6e39a7SMingming Cao 	struct page *bd_bitmap_page;
1888f6e39a7SMingming Cao 	void *bd_bitmap;
1898f6e39a7SMingming Cao 	struct ext4_group_info *bd_info;
1908f6e39a7SMingming Cao 	struct super_block *bd_sb;
1918f6e39a7SMingming Cao 	__u16 bd_blkbits;
1928f6e39a7SMingming Cao 	ext4_group_t bd_group;
1938f6e39a7SMingming Cao };
1948f6e39a7SMingming Cao 
195c3a326a6SAneesh Kumar K.V static inline ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
1968f6e39a7SMingming Cao 					struct ext4_free_extent *fex)
1978f6e39a7SMingming Cao {
1983212a80aSTheodore Ts'o 	return ext4_group_first_block_no(sb, fex->fe_group) +
1993212a80aSTheodore Ts'o 		(fex->fe_start << EXT4_SB(sb)->s_cluster_bits);
2008f6e39a7SMingming Cao }
2010c9ec4beSDarrick J. Wong 
2020c9ec4beSDarrick J. Wong typedef int (*ext4_mballoc_query_range_fn)(
2030c9ec4beSDarrick J. Wong 	struct super_block		*sb,
2040c9ec4beSDarrick J. Wong 	ext4_group_t			agno,
2050c9ec4beSDarrick J. Wong 	ext4_grpblk_t			start,
2060c9ec4beSDarrick J. Wong 	ext4_grpblk_t			len,
2070c9ec4beSDarrick J. Wong 	void				*priv);
2080c9ec4beSDarrick J. Wong 
2090c9ec4beSDarrick J. Wong int
2100c9ec4beSDarrick J. Wong ext4_mballoc_query_range(
2110c9ec4beSDarrick J. Wong 	struct super_block		*sb,
2120c9ec4beSDarrick J. Wong 	ext4_group_t			agno,
2130c9ec4beSDarrick J. Wong 	ext4_grpblk_t			start,
2140c9ec4beSDarrick J. Wong 	ext4_grpblk_t			end,
2150c9ec4beSDarrick J. Wong 	ext4_mballoc_query_range_fn	formatter,
2160c9ec4beSDarrick J. Wong 	void				*priv);
2170c9ec4beSDarrick J. Wong 
2188f6e39a7SMingming Cao #endif
219