162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __LINUX_BACKING_DEV_DEFS_H
362306a36Sopenharmony_ci#define __LINUX_BACKING_DEV_DEFS_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/list.h>
662306a36Sopenharmony_ci#include <linux/radix-tree.h>
762306a36Sopenharmony_ci#include <linux/rbtree.h>
862306a36Sopenharmony_ci#include <linux/spinlock.h>
962306a36Sopenharmony_ci#include <linux/percpu_counter.h>
1062306a36Sopenharmony_ci#include <linux/percpu-refcount.h>
1162306a36Sopenharmony_ci#include <linux/flex_proportions.h>
1262306a36Sopenharmony_ci#include <linux/timer.h>
1362306a36Sopenharmony_ci#include <linux/workqueue.h>
1462306a36Sopenharmony_ci#include <linux/kref.h>
1562306a36Sopenharmony_ci#include <linux/refcount.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistruct page;
1862306a36Sopenharmony_cistruct device;
1962306a36Sopenharmony_cistruct dentry;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/*
2262306a36Sopenharmony_ci * Bits in bdi_writeback.state
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_cienum wb_state {
2562306a36Sopenharmony_ci	WB_registered,		/* bdi_register() was done */
2662306a36Sopenharmony_ci	WB_writeback_running,	/* Writeback is in progress */
2762306a36Sopenharmony_ci	WB_has_dirty_io,	/* Dirty inodes on ->b_{dirty|io|more_io} */
2862306a36Sopenharmony_ci	WB_start_all,		/* nr_pages == 0 (all) work pending */
2962306a36Sopenharmony_ci};
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cienum wb_stat_item {
3262306a36Sopenharmony_ci	WB_RECLAIMABLE,
3362306a36Sopenharmony_ci	WB_WRITEBACK,
3462306a36Sopenharmony_ci	WB_DIRTIED,
3562306a36Sopenharmony_ci	WB_WRITTEN,
3662306a36Sopenharmony_ci	NR_WB_STAT_ITEMS
3762306a36Sopenharmony_ci};
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define WB_STAT_BATCH (8*(1+ilog2(nr_cpu_ids)))
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/*
4262306a36Sopenharmony_ci * why some writeback work was initiated
4362306a36Sopenharmony_ci */
4462306a36Sopenharmony_cienum wb_reason {
4562306a36Sopenharmony_ci	WB_REASON_BACKGROUND,
4662306a36Sopenharmony_ci	WB_REASON_VMSCAN,
4762306a36Sopenharmony_ci	WB_REASON_SYNC,
4862306a36Sopenharmony_ci	WB_REASON_PERIODIC,
4962306a36Sopenharmony_ci	WB_REASON_LAPTOP_TIMER,
5062306a36Sopenharmony_ci	WB_REASON_FS_FREE_SPACE,
5162306a36Sopenharmony_ci	/*
5262306a36Sopenharmony_ci	 * There is no bdi forker thread any more and works are done
5362306a36Sopenharmony_ci	 * by emergency worker, however, this is TPs userland visible
5462306a36Sopenharmony_ci	 * and we'll be exposing exactly the same information,
5562306a36Sopenharmony_ci	 * so it has a mismatch name.
5662306a36Sopenharmony_ci	 */
5762306a36Sopenharmony_ci	WB_REASON_FORKER_THREAD,
5862306a36Sopenharmony_ci	WB_REASON_FOREIGN_FLUSH,
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	WB_REASON_MAX,
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct wb_completion {
6462306a36Sopenharmony_ci	atomic_t		cnt;
6562306a36Sopenharmony_ci	wait_queue_head_t	*waitq;
6662306a36Sopenharmony_ci};
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci#define __WB_COMPLETION_INIT(_waitq)	\
6962306a36Sopenharmony_ci	(struct wb_completion){ .cnt = ATOMIC_INIT(1), .waitq = (_waitq) }
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/*
7262306a36Sopenharmony_ci * If one wants to wait for one or more wb_writeback_works, each work's
7362306a36Sopenharmony_ci * ->done should be set to a wb_completion defined using the following
7462306a36Sopenharmony_ci * macro.  Once all work items are issued with wb_queue_work(), the caller
7562306a36Sopenharmony_ci * can wait for the completion of all using wb_wait_for_completion().  Work
7662306a36Sopenharmony_ci * items which are waited upon aren't freed automatically on completion.
7762306a36Sopenharmony_ci */
7862306a36Sopenharmony_ci#define WB_COMPLETION_INIT(bdi)		__WB_COMPLETION_INIT(&(bdi)->wb_waitq)
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#define DEFINE_WB_COMPLETION(cmpl, bdi)	\
8162306a36Sopenharmony_ci	struct wb_completion cmpl = WB_COMPLETION_INIT(bdi)
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/*
8462306a36Sopenharmony_ci * Each wb (bdi_writeback) can perform writeback operations, is measured
8562306a36Sopenharmony_ci * and throttled, independently.  Without cgroup writeback, each bdi
8662306a36Sopenharmony_ci * (bdi_writeback) is served by its embedded bdi->wb.
8762306a36Sopenharmony_ci *
8862306a36Sopenharmony_ci * On the default hierarchy, blkcg implicitly enables memcg.  This allows
8962306a36Sopenharmony_ci * using memcg's page ownership for attributing writeback IOs, and every
9062306a36Sopenharmony_ci * memcg - blkcg combination can be served by its own wb by assigning a
9162306a36Sopenharmony_ci * dedicated wb to each memcg, which enables isolation across different
9262306a36Sopenharmony_ci * cgroups and propagation of IO back pressure down from the IO layer upto
9362306a36Sopenharmony_ci * the tasks which are generating the dirty pages to be written back.
9462306a36Sopenharmony_ci *
9562306a36Sopenharmony_ci * A cgroup wb is indexed on its bdi by the ID of the associated memcg,
9662306a36Sopenharmony_ci * refcounted with the number of inodes attached to it, and pins the memcg
9762306a36Sopenharmony_ci * and the corresponding blkcg.  As the corresponding blkcg for a memcg may
9862306a36Sopenharmony_ci * change as blkcg is disabled and enabled higher up in the hierarchy, a wb
9962306a36Sopenharmony_ci * is tested for blkcg after lookup and removed from index on mismatch so
10062306a36Sopenharmony_ci * that a new wb for the combination can be created.
10162306a36Sopenharmony_ci *
10262306a36Sopenharmony_ci * Each bdi_writeback that is not embedded into the backing_dev_info must hold
10362306a36Sopenharmony_ci * a reference to the parent backing_dev_info.  See cgwb_create() for details.
10462306a36Sopenharmony_ci */
10562306a36Sopenharmony_cistruct bdi_writeback {
10662306a36Sopenharmony_ci	struct backing_dev_info *bdi;	/* our parent bdi */
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	unsigned long state;		/* Always use atomic bitops on this */
10962306a36Sopenharmony_ci	unsigned long last_old_flush;	/* last old data flush */
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	struct list_head b_dirty;	/* dirty inodes */
11262306a36Sopenharmony_ci	struct list_head b_io;		/* parked for writeback */
11362306a36Sopenharmony_ci	struct list_head b_more_io;	/* parked for more writeback */
11462306a36Sopenharmony_ci	struct list_head b_dirty_time;	/* time stamps are dirty */
11562306a36Sopenharmony_ci	spinlock_t list_lock;		/* protects the b_* lists */
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	atomic_t writeback_inodes;	/* number of inodes under writeback */
11862306a36Sopenharmony_ci	struct percpu_counter stat[NR_WB_STAT_ITEMS];
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	unsigned long bw_time_stamp;	/* last time write bw is updated */
12162306a36Sopenharmony_ci	unsigned long dirtied_stamp;
12262306a36Sopenharmony_ci	unsigned long written_stamp;	/* pages written at bw_time_stamp */
12362306a36Sopenharmony_ci	unsigned long write_bandwidth;	/* the estimated write bandwidth */
12462306a36Sopenharmony_ci	unsigned long avg_write_bandwidth; /* further smoothed write bw, > 0 */
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	/*
12762306a36Sopenharmony_ci	 * The base dirty throttle rate, re-calculated on every 200ms.
12862306a36Sopenharmony_ci	 * All the bdi tasks' dirty rate will be curbed under it.
12962306a36Sopenharmony_ci	 * @dirty_ratelimit tracks the estimated @balanced_dirty_ratelimit
13062306a36Sopenharmony_ci	 * in small steps and is much more smooth/stable than the latter.
13162306a36Sopenharmony_ci	 */
13262306a36Sopenharmony_ci	unsigned long dirty_ratelimit;
13362306a36Sopenharmony_ci	unsigned long balanced_dirty_ratelimit;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	struct fprop_local_percpu completions;
13662306a36Sopenharmony_ci	int dirty_exceeded;
13762306a36Sopenharmony_ci	enum wb_reason start_all_reason;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	spinlock_t work_lock;		/* protects work_list & dwork scheduling */
14062306a36Sopenharmony_ci	struct list_head work_list;
14162306a36Sopenharmony_ci	struct delayed_work dwork;	/* work item used for writeback */
14262306a36Sopenharmony_ci	struct delayed_work bw_dwork;	/* work item used for bandwidth estimate */
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	struct list_head bdi_node;	/* anchored at bdi->wb_list */
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci#ifdef CONFIG_CGROUP_WRITEBACK
14762306a36Sopenharmony_ci	struct percpu_ref refcnt;	/* used only for !root wb's */
14862306a36Sopenharmony_ci	struct fprop_local_percpu memcg_completions;
14962306a36Sopenharmony_ci	struct cgroup_subsys_state *memcg_css; /* the associated memcg */
15062306a36Sopenharmony_ci	struct cgroup_subsys_state *blkcg_css; /* and blkcg */
15162306a36Sopenharmony_ci	struct list_head memcg_node;	/* anchored at memcg->cgwb_list */
15262306a36Sopenharmony_ci	struct list_head blkcg_node;	/* anchored at blkcg->cgwb_list */
15362306a36Sopenharmony_ci	struct list_head b_attached;	/* attached inodes, protected by list_lock */
15462306a36Sopenharmony_ci	struct list_head offline_node;	/* anchored at offline_cgwbs */
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	union {
15762306a36Sopenharmony_ci		struct work_struct release_work;
15862306a36Sopenharmony_ci		struct rcu_head rcu;
15962306a36Sopenharmony_ci	};
16062306a36Sopenharmony_ci#endif
16162306a36Sopenharmony_ci};
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_cistruct backing_dev_info {
16462306a36Sopenharmony_ci	u64 id;
16562306a36Sopenharmony_ci	struct rb_node rb_node; /* keyed by ->id */
16662306a36Sopenharmony_ci	struct list_head bdi_list;
16762306a36Sopenharmony_ci	unsigned long ra_pages;	/* max readahead in PAGE_SIZE units */
16862306a36Sopenharmony_ci	unsigned long io_pages;	/* max allowed IO size */
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	struct kref refcnt;	/* Reference counter for the structure */
17162306a36Sopenharmony_ci	unsigned int capabilities; /* Device capabilities */
17262306a36Sopenharmony_ci	unsigned int min_ratio;
17362306a36Sopenharmony_ci	unsigned int max_ratio, max_prop_frac;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	/*
17662306a36Sopenharmony_ci	 * Sum of avg_write_bw of wbs with dirty inodes.  > 0 if there are
17762306a36Sopenharmony_ci	 * any dirty wbs, which is depended upon by bdi_has_dirty().
17862306a36Sopenharmony_ci	 */
17962306a36Sopenharmony_ci	atomic_long_t tot_write_bandwidth;
18062306a36Sopenharmony_ci	/*
18162306a36Sopenharmony_ci	 * Jiffies when last process was dirty throttled on this bdi. Used by
18262306a36Sopenharmony_ci	 * blk-wbt.
18362306a36Sopenharmony_ci	 */
18462306a36Sopenharmony_ci	unsigned long last_bdp_sleep;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	struct bdi_writeback wb;  /* the root writeback info for this bdi */
18762306a36Sopenharmony_ci	struct list_head wb_list; /* list of all wbs */
18862306a36Sopenharmony_ci#ifdef CONFIG_CGROUP_WRITEBACK
18962306a36Sopenharmony_ci	struct radix_tree_root cgwb_tree; /* radix tree of active cgroup wbs */
19062306a36Sopenharmony_ci	struct mutex cgwb_release_mutex;  /* protect shutdown of wb structs */
19162306a36Sopenharmony_ci	struct rw_semaphore wb_switch_rwsem; /* no cgwb switch while syncing */
19262306a36Sopenharmony_ci#endif
19362306a36Sopenharmony_ci	wait_queue_head_t wb_waitq;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	struct device *dev;
19662306a36Sopenharmony_ci	char dev_name[64];
19762306a36Sopenharmony_ci	struct device *owner;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	struct timer_list laptop_mode_wb_timer;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
20262306a36Sopenharmony_ci	struct dentry *debug_dir;
20362306a36Sopenharmony_ci#endif
20462306a36Sopenharmony_ci};
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistruct wb_lock_cookie {
20762306a36Sopenharmony_ci	bool locked;
20862306a36Sopenharmony_ci	unsigned long flags;
20962306a36Sopenharmony_ci};
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci#ifdef CONFIG_CGROUP_WRITEBACK
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci/**
21462306a36Sopenharmony_ci * wb_tryget - try to increment a wb's refcount
21562306a36Sopenharmony_ci * @wb: bdi_writeback to get
21662306a36Sopenharmony_ci */
21762306a36Sopenharmony_cistatic inline bool wb_tryget(struct bdi_writeback *wb)
21862306a36Sopenharmony_ci{
21962306a36Sopenharmony_ci	if (wb != &wb->bdi->wb)
22062306a36Sopenharmony_ci		return percpu_ref_tryget(&wb->refcnt);
22162306a36Sopenharmony_ci	return true;
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci/**
22562306a36Sopenharmony_ci * wb_get - increment a wb's refcount
22662306a36Sopenharmony_ci * @wb: bdi_writeback to get
22762306a36Sopenharmony_ci */
22862306a36Sopenharmony_cistatic inline void wb_get(struct bdi_writeback *wb)
22962306a36Sopenharmony_ci{
23062306a36Sopenharmony_ci	if (wb != &wb->bdi->wb)
23162306a36Sopenharmony_ci		percpu_ref_get(&wb->refcnt);
23262306a36Sopenharmony_ci}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci/**
23562306a36Sopenharmony_ci * wb_put - decrement a wb's refcount
23662306a36Sopenharmony_ci * @wb: bdi_writeback to put
23762306a36Sopenharmony_ci * @nr: number of references to put
23862306a36Sopenharmony_ci */
23962306a36Sopenharmony_cistatic inline void wb_put_many(struct bdi_writeback *wb, unsigned long nr)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	if (WARN_ON_ONCE(!wb->bdi)) {
24262306a36Sopenharmony_ci		/*
24362306a36Sopenharmony_ci		 * A driver bug might cause a file to be removed before bdi was
24462306a36Sopenharmony_ci		 * initialized.
24562306a36Sopenharmony_ci		 */
24662306a36Sopenharmony_ci		return;
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	if (wb != &wb->bdi->wb)
25062306a36Sopenharmony_ci		percpu_ref_put_many(&wb->refcnt, nr);
25162306a36Sopenharmony_ci}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci/**
25462306a36Sopenharmony_ci * wb_put - decrement a wb's refcount
25562306a36Sopenharmony_ci * @wb: bdi_writeback to put
25662306a36Sopenharmony_ci */
25762306a36Sopenharmony_cistatic inline void wb_put(struct bdi_writeback *wb)
25862306a36Sopenharmony_ci{
25962306a36Sopenharmony_ci	wb_put_many(wb, 1);
26062306a36Sopenharmony_ci}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci/**
26362306a36Sopenharmony_ci * wb_dying - is a wb dying?
26462306a36Sopenharmony_ci * @wb: bdi_writeback of interest
26562306a36Sopenharmony_ci *
26662306a36Sopenharmony_ci * Returns whether @wb is unlinked and being drained.
26762306a36Sopenharmony_ci */
26862306a36Sopenharmony_cistatic inline bool wb_dying(struct bdi_writeback *wb)
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	return percpu_ref_is_dying(&wb->refcnt);
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci#else	/* CONFIG_CGROUP_WRITEBACK */
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistatic inline bool wb_tryget(struct bdi_writeback *wb)
27662306a36Sopenharmony_ci{
27762306a36Sopenharmony_ci	return true;
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic inline void wb_get(struct bdi_writeback *wb)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_cistatic inline void wb_put(struct bdi_writeback *wb)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_cistatic inline void wb_put_many(struct bdi_writeback *wb, unsigned long nr)
28962306a36Sopenharmony_ci{
29062306a36Sopenharmony_ci}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_cistatic inline bool wb_dying(struct bdi_writeback *wb)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	return false;
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci#endif	/* CONFIG_CGROUP_WRITEBACK */
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci#endif	/* __LINUX_BACKING_DEV_DEFS_H */
300