3110 lines · 93.1 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* * mm/page-writeback.c * * Copyright (C) 2002, Linus Torvalds. * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra * * Contains functions related to writing back dirty pages at the * address_space level. * * 10Apr2002	Andrew Morton *		Initial version */ #include <linux/kernel.h>#include <linux/math64.h>#include <linux/export.h>#include <linux/spinlock.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/swap.h>#include <linux/slab.h>#include <linux/pagemap.h>#include <linux/writeback.h>#include <linux/init.h>#include <linux/backing-dev.h>#include <linux/task_io_accounting_ops.h>#include <linux/mpage.h>#include <linux/rmap.h>#include <linux/percpu.h>#include <linux/smp.h>#include <linux/sysctl.h>#include <linux/cpu.h>#include <linux/syscalls.h>#include <linux/folio_batch.h>#include <linux/timer.h>#include <linux/sched/rt.h>#include <linux/sched/signal.h>#include <linux/mm_inline.h>#include <linux/shmem_fs.h>#include <trace/events/writeback.h> #include "internal.h" /* * Sleep at most 200ms at a time in balance_dirty_pages(). */#define MAX_PAUSE		max(HZ/5, 1) /* * Try to keep balance_dirty_pages() call intervals higher than this many pages * by raising pause time to max_pause when falls below it. */#define DIRTY_POLL_THRESH	(128 >> (PAGE_SHIFT - 10)) /* * Estimate write bandwidth or update dirty limit at 200ms intervals. */#define BANDWIDTH_INTERVAL	max(HZ/5, 1) #define RATELIMIT_CALC_SHIFT	10 /* * After a CPU has dirtied this many pages, balance_dirty_pages_ratelimited * will look to see if it needs to force writeback or throttling. */static long ratelimit_pages = 32; /* The following parameters are exported via /proc/sys/vm */ /* * Start background writeback (via writeback threads) at this percentage */static int dirty_background_ratio = 10; /* * dirty_background_bytes starts at 0 (disabled) so that it is a function of * dirty_background_ratio * the amount of dirtyable memory */static unsigned long dirty_background_bytes; /* * free highmem will not be subtracted from the total free memory * for calculating free ratios if vm_highmem_is_dirtyable is true */static int vm_highmem_is_dirtyable; /* * The generator of dirty data starts writeback at this percentage */static int vm_dirty_ratio = 20; /* * vm_dirty_bytes starts at 0 (disabled) so that it is a function of * vm_dirty_ratio * the amount of dirtyable memory */static unsigned long vm_dirty_bytes; /* * The interval between `kupdate'-style writebacks */unsigned int dirty_writeback_interval = 5 * 100; /* centiseconds */ EXPORT_SYMBOL_GPL(dirty_writeback_interval); /* * The longest time for which data is allowed to remain dirty */unsigned int dirty_expire_interval = 30 * 100; /* centiseconds */ /* End of sysctl-exported parameters */ struct wb_domain global_wb_domain; /* * Length of period for aging writeout fractions of bdis. This is an * arbitrarily chosen number. The longer the period, the slower fractions will * reflect changes in current writeout rate. */#define VM_COMPLETIONS_PERIOD_LEN (3*HZ) #ifdef CONFIG_CGROUP_WRITEBACK #define GDTC_INIT(__wb)		.wb = (__wb),				\				.dom = &global_wb_domain,		\				.wb_completions = &(__wb)->completions #define GDTC_INIT_NO_WB		.dom = &global_wb_domain #define MDTC_INIT(__wb, __gdtc)	.wb = (__wb),				\				.dom = mem_cgroup_wb_domain(__wb),	\				.wb_completions = &(__wb)->memcg_completions, \				.gdtc = __gdtc static bool mdtc_valid(struct dirty_throttle_control *dtc){	return dtc->dom;} static struct wb_domain *dtc_dom(struct dirty_throttle_control *dtc){	return dtc->dom;} static struct dirty_throttle_control *mdtc_gdtc(struct dirty_throttle_control *mdtc){	return mdtc->gdtc;} static struct fprop_local_percpu *wb_memcg_completions(struct bdi_writeback *wb){	return &wb->memcg_completions;} static void wb_min_max_ratio(struct bdi_writeback *wb,			     unsigned long *minp, unsigned long *maxp){	unsigned long this_bw = READ_ONCE(wb->avg_write_bandwidth);	unsigned long tot_bw = atomic_long_read(&wb->bdi->tot_write_bandwidth);	unsigned long long min = wb->bdi->min_ratio;	unsigned long long max = wb->bdi->max_ratio; 	/*	 * @wb may already be clean by the time control reaches here and	 * the total may not include its bw.	 */	if (this_bw < tot_bw) {		if (min) {			min *= this_bw;			min = div64_ul(min, tot_bw);		}		if (max < 100 * BDI_RATIO_SCALE) {			max *= this_bw;			max = div64_ul(max, tot_bw);		}	} 	*minp = min;	*maxp = max;} #else	/* CONFIG_CGROUP_WRITEBACK */ #define GDTC_INIT(__wb)		.wb = (__wb),                           \				.wb_completions = &(__wb)->completions#define GDTC_INIT_NO_WB#define MDTC_INIT(__wb, __gdtc) static bool mdtc_valid(struct dirty_throttle_control *dtc){	return false;} static struct wb_domain *dtc_dom(struct dirty_throttle_control *dtc){	return &global_wb_domain;} static struct dirty_throttle_control *mdtc_gdtc(struct dirty_throttle_control *mdtc){	return NULL;} static struct fprop_local_percpu *wb_memcg_completions(struct bdi_writeback *wb){	return NULL;} static void wb_min_max_ratio(struct bdi_writeback *wb,			     unsigned long *minp, unsigned long *maxp){	*minp = wb->bdi->min_ratio;	*maxp = wb->bdi->max_ratio;} #endif	/* CONFIG_CGROUP_WRITEBACK */ /* * In a memory zone, there is a certain amount of pages we consider * available for the page cache, which is essentially the number of * free and reclaimable pages, minus some zone reserves to protect * lowmem and the ability to uphold the zone's watermarks without * requiring writeback. * * This number of dirtyable pages is the base value of which the * user-configurable dirty ratio is the effective number of pages that * are allowed to be actually dirtied.  Per individual zone, or * globally by using the sum of dirtyable pages over all zones. * * Because the user is allowed to specify the dirty limit globally as * absolute number of bytes, calculating the per-zone dirty limit can * require translating the configured limit into a percentage of * global dirtyable memory first. */ /** * node_dirtyable_memory - number of dirtyable pages in a node * @pgdat: the node * * Return: the node's number of pages potentially available for dirty * page cache.  This is the base value for the per-node dirty limits. */static unsigned long node_dirtyable_memory(struct pglist_data *pgdat){	unsigned long nr_pages = 0;	int z; 	for (z = 0; z < MAX_NR_ZONES; z++) {		struct zone *zone = pgdat->node_zones + z; 		if (!populated_zone(zone))			continue; 		nr_pages += zone_page_state(zone, NR_FREE_PAGES);	} 	/*	 * Pages reserved for the kernel should not be considered	 * dirtyable, to prevent a situation where reclaim has to	 * clean pages in order to balance the zones.	 */	nr_pages -= min(nr_pages, pgdat->totalreserve_pages); 	nr_pages += node_page_state(pgdat, NR_INACTIVE_FILE);	nr_pages += node_page_state(pgdat, NR_ACTIVE_FILE); 	return nr_pages;} static unsigned long highmem_dirtyable_memory(unsigned long total){#ifdef CONFIG_HIGHMEM	int node;	unsigned long x = 0;	int i; 	for_each_node_state(node, N_HIGH_MEMORY) {		for (i = ZONE_NORMAL + 1; i < MAX_NR_ZONES; i++) {			struct zone *z;			unsigned long nr_pages; 			if (!is_highmem_idx(i))				continue; 			z = &NODE_DATA(node)->node_zones[i];			if (!populated_zone(z))				continue; 			nr_pages = zone_page_state(z, NR_FREE_PAGES);			/* watch for underflows */			nr_pages -= min(nr_pages, high_wmark_pages(z));			nr_pages += zone_page_state(z, NR_ZONE_INACTIVE_FILE);			nr_pages += zone_page_state(z, NR_ZONE_ACTIVE_FILE);			x += nr_pages;		}	} 	/*	 * Make sure that the number of highmem pages is never larger	 * than the number of the total dirtyable memory. This can only	 * occur in very strange VM situations but we want to make sure	 * that this does not occur.	 */	return min(x, total);#else	return 0;#endif} /** * global_dirtyable_memory - number of globally dirtyable pages * * Return: the global number of pages potentially available for dirty * page cache.  This is the base value for the global dirty limits. */static unsigned long global_dirtyable_memory(void){	unsigned long x; 	x = global_zone_page_state(NR_FREE_PAGES);	/*	 * Pages reserved for the kernel should not be considered	 * dirtyable, to prevent a situation where reclaim has to	 * clean pages in order to balance the zones.	 */	x -= min(x, totalreserve_pages); 	x += global_node_page_state(NR_INACTIVE_FILE);	x += global_node_page_state(NR_ACTIVE_FILE); 	if (!vm_highmem_is_dirtyable)		x -= highmem_dirtyable_memory(x); 	return x + 1;	/* Ensure that we never return 0 */} /** * domain_dirty_limits - calculate thresh and bg_thresh for a wb_domain * @dtc: dirty_throttle_control of interest * * Calculate @dtc->thresh and ->bg_thresh considering * vm_dirty_{bytes|ratio} and dirty_background_{bytes|ratio}.  The caller * must ensure that @dtc->avail is set before calling this function.  The * dirty limits will be lifted by 1/4 for real-time tasks. */static void domain_dirty_limits(struct dirty_throttle_control *dtc){	const unsigned long available_memory = dtc->avail;	struct dirty_throttle_control *gdtc = mdtc_gdtc(dtc);	unsigned long bytes = vm_dirty_bytes;	unsigned long bg_bytes = dirty_background_bytes;	/* convert ratios to per-PAGE_SIZE for higher precision */	unsigned long ratio = (vm_dirty_ratio * PAGE_SIZE) / 100;	unsigned long bg_ratio = (dirty_background_ratio * PAGE_SIZE) / 100;	unsigned long thresh;	unsigned long bg_thresh;	struct task_struct *tsk; 	/* gdtc is !NULL iff @dtc is for memcg domain */	if (gdtc) {		unsigned long global_avail = gdtc->avail; 		/*		 * The byte settings can't be applied directly to memcg		 * domains.  Convert them to ratios by scaling against		 * globally available memory.  As the ratios are in		 * per-PAGE_SIZE, they can be obtained by dividing bytes by		 * number of pages.		 */		if (bytes)			ratio = min(DIV_ROUND_UP(bytes, global_avail),				    PAGE_SIZE);		if (bg_bytes)			bg_ratio = min(DIV_ROUND_UP(bg_bytes, global_avail),				       PAGE_SIZE);		bytes = bg_bytes = 0;	} 	if (bytes)		thresh = DIV_ROUND_UP(bytes, PAGE_SIZE);	else		thresh = (ratio * available_memory) / PAGE_SIZE; 	if (bg_bytes)		bg_thresh = DIV_ROUND_UP(bg_bytes, PAGE_SIZE);	else		bg_thresh = (bg_ratio * available_memory) / PAGE_SIZE; 	tsk = current;	if (rt_or_dl_task(tsk)) {		bg_thresh += bg_thresh / 4 + global_wb_domain.dirty_limit / 32;		thresh += thresh / 4 + global_wb_domain.dirty_limit / 32;	}	/*	 * Dirty throttling logic assumes the limits in page units fit into	 * 32-bits. This gives 16TB dirty limits max which is hopefully enough.	 */	if (thresh > UINT_MAX)		thresh = UINT_MAX;	/* This makes sure bg_thresh is within 32-bits as well */	if (bg_thresh >= thresh)		bg_thresh = thresh / 2;	dtc->thresh = thresh;	dtc->bg_thresh = bg_thresh; 	/* we should eventually report the domain in the TP */	if (!gdtc)		trace_global_dirty_state(bg_thresh, thresh);} /** * global_dirty_limits - background-writeback and dirty-throttling thresholds * @pbackground: out parameter for bg_thresh * @pdirty: out parameter for thresh * * Calculate bg_thresh and thresh for global_wb_domain.  See * domain_dirty_limits() for details. */void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty){	struct dirty_throttle_control gdtc = { GDTC_INIT_NO_WB }; 	gdtc.avail = global_dirtyable_memory();	domain_dirty_limits(&gdtc); 	*pbackground = gdtc.bg_thresh;	*pdirty = gdtc.thresh;} /** * node_dirty_limit - maximum number of dirty pages allowed in a node * @pgdat: the node * * Return: the maximum number of dirty pages allowed in a node, based * on the node's dirtyable memory. */static unsigned long node_dirty_limit(struct pglist_data *pgdat){	unsigned long node_memory = node_dirtyable_memory(pgdat);	struct task_struct *tsk = current;	unsigned long dirty; 	if (vm_dirty_bytes)		dirty = DIV_ROUND_UP(vm_dirty_bytes, PAGE_SIZE) *			node_memory / global_dirtyable_memory();	else		dirty = vm_dirty_ratio * node_memory / 100; 	if (rt_or_dl_task(tsk))		dirty += dirty / 4; 	/*	 * Dirty throttling logic assumes the limits in page units fit into	 * 32-bits. This gives 16TB dirty limits max which is hopefully enough.	 */	return min_t(unsigned long, dirty, UINT_MAX);} /** * node_dirty_ok - tells whether a node is within its dirty limits * @pgdat: the node to check * * Return: %true when the dirty pages in @pgdat are within the node's * dirty limit, %false if the limit is exceeded. */bool node_dirty_ok(struct pglist_data *pgdat){	unsigned long limit = node_dirty_limit(pgdat);	unsigned long nr_pages = 0; 	nr_pages += node_page_state(pgdat, NR_FILE_DIRTY);	nr_pages += node_page_state(pgdat, NR_WRITEBACK); 	return nr_pages <= limit;} #ifdef CONFIG_SYSCTLstatic int dirty_background_ratio_handler(const struct ctl_table *table, int write,		void *buffer, size_t *lenp, loff_t *ppos){	int ret; 	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);	if (ret == 0 && write)		dirty_background_bytes = 0;	return ret;} static int dirty_background_bytes_handler(const struct ctl_table *table, int write,		void *buffer, size_t *lenp, loff_t *ppos){	int ret;	unsigned long old_bytes = dirty_background_bytes; 	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);	if (ret == 0 && write) {		if (DIV_ROUND_UP(dirty_background_bytes, PAGE_SIZE) >								UINT_MAX) {			dirty_background_bytes = old_bytes;			return -ERANGE;

Lines 1–500 of 3110.