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