1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * include/linux/backing-dev.h 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * low-level device information and state which is propagated up through 61da177e4SLinus Torvalds * to high-level code. 71da177e4SLinus Torvalds */ 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds #ifndef _LINUX_BACKING_DEV_H 101da177e4SLinus Torvalds #define _LINUX_BACKING_DEV_H 111da177e4SLinus Torvalds 12cf0ca9feSPeter Zijlstra #include <linux/kernel.h> 13e4ad08feSMiklos Szeredi #include <linux/fs.h> 1403ba3782SJens Axboe #include <linux/sched.h> 15a212b105STejun Heo #include <linux/blkdev.h> 1603ba3782SJens Axboe #include <linux/writeback.h> 1752ebea74STejun Heo #include <linux/blk-cgroup.h> 1866114cadSTejun Heo #include <linux/backing-dev-defs.h> 19a13f35e8STejun Heo #include <linux/slab.h> 20de1414a6SChristoph Hellwig 21d03f6cdcSJan Kara static inline struct backing_dev_info *bdi_get(struct backing_dev_info *bdi) 22d03f6cdcSJan Kara { 23d03f6cdcSJan Kara kref_get(&bdi->refcnt); 24d03f6cdcSJan Kara return bdi; 25d03f6cdcSJan Kara } 26d03f6cdcSJan Kara 27d03f6cdcSJan Kara void bdi_put(struct backing_dev_info *bdi); 28b2e8fb6eSPeter Zijlstra 297c4cc300SJan Kara __printf(2, 3) 307c4cc300SJan Kara int bdi_register(struct backing_dev_info *bdi, const char *fmt, ...); 317c4cc300SJan Kara int bdi_register_va(struct backing_dev_info *bdi, const char *fmt, 327c4cc300SJan Kara va_list args); 33df08c32cSDan Williams int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner); 34b02176f3STejun Heo void bdi_unregister(struct backing_dev_info *bdi); 35b02176f3STejun Heo 36d03f6cdcSJan Kara struct backing_dev_info *bdi_alloc_node(gfp_t gfp_mask, int node_id); 37baf7a616SJan Kara static inline struct backing_dev_info *bdi_alloc(gfp_t gfp_mask) 38baf7a616SJan Kara { 39baf7a616SJan Kara return bdi_alloc_node(gfp_mask, NUMA_NO_NODE); 40baf7a616SJan Kara } 41b02176f3STejun Heo 429ecf4866STejun Heo void wb_start_background_writeback(struct bdi_writeback *wb); 43f0054bb1STejun Heo void wb_workfn(struct work_struct *work); 44f0054bb1STejun Heo void wb_wakeup_delayed(struct bdi_writeback *wb); 45cf0ca9feSPeter Zijlstra 4603ba3782SJens Axboe extern spinlock_t bdi_lock; 4766f3b8e2SJens Axboe extern struct list_head bdi_list; 4866f3b8e2SJens Axboe 49839a8e86STejun Heo extern struct workqueue_struct *bdi_wq; 50839a8e86STejun Heo 51d6c10f1fSTejun Heo static inline bool wb_has_dirty_io(struct bdi_writeback *wb) 5203ba3782SJens Axboe { 53d6c10f1fSTejun Heo return test_bit(WB_has_dirty_io, &wb->state); 5403ba3782SJens Axboe } 5503ba3782SJens Axboe 5695a46c65STejun Heo static inline bool bdi_has_dirty_io(struct backing_dev_info *bdi) 57e0bf68ddSPeter Zijlstra { 5895a46c65STejun Heo /* 5995a46c65STejun Heo * @bdi->tot_write_bandwidth is guaranteed to be > 0 if there are 6095a46c65STejun Heo * any dirty wbs. See wb_update_write_bandwidth(). 6195a46c65STejun Heo */ 6295a46c65STejun Heo return atomic_long_read(&bdi->tot_write_bandwidth); 63e0bf68ddSPeter Zijlstra } 64e0bf68ddSPeter Zijlstra 6593f78d88STejun Heo static inline void __add_wb_stat(struct bdi_writeback *wb, 6693f78d88STejun Heo enum wb_stat_item item, s64 amount) 67e0bf68ddSPeter Zijlstra { 68104b4e51SNikolay Borisov percpu_counter_add_batch(&wb->stat[item], amount, WB_STAT_BATCH); 69b2e8fb6eSPeter Zijlstra } 70b2e8fb6eSPeter Zijlstra 713e8f399dSNikolay Borisov static inline void inc_wb_stat(struct bdi_writeback *wb, enum wb_stat_item item) 72e0bf68ddSPeter Zijlstra { 7393f78d88STejun Heo __add_wb_stat(wb, item, 1); 74b2e8fb6eSPeter Zijlstra } 75b2e8fb6eSPeter Zijlstra 7693f78d88STejun Heo static inline void dec_wb_stat(struct bdi_writeback *wb, enum wb_stat_item item) 77b2e8fb6eSPeter Zijlstra { 783e8f399dSNikolay Borisov __add_wb_stat(wb, item, -1); 79b2e8fb6eSPeter Zijlstra } 80b2e8fb6eSPeter Zijlstra 8193f78d88STejun Heo static inline s64 wb_stat(struct bdi_writeback *wb, enum wb_stat_item item) 82b2e8fb6eSPeter Zijlstra { 8393f78d88STejun Heo return percpu_counter_read_positive(&wb->stat[item]); 84b2e8fb6eSPeter Zijlstra } 85b2e8fb6eSPeter Zijlstra 8693f78d88STejun Heo static inline s64 wb_stat_sum(struct bdi_writeback *wb, enum wb_stat_item item) 87b2e8fb6eSPeter Zijlstra { 88e3d3910aSNikolay Borisov return percpu_counter_sum_positive(&wb->stat[item]); 89b2e8fb6eSPeter Zijlstra } 90b2e8fb6eSPeter Zijlstra 9193f78d88STejun Heo extern void wb_writeout_inc(struct bdi_writeback *wb); 92dd5656e5SMiklos Szeredi 93b2e8fb6eSPeter Zijlstra /* 94b2e8fb6eSPeter Zijlstra * maximal error of a stat counter. 95b2e8fb6eSPeter Zijlstra */ 96*2bce774eSWang Long static inline unsigned long wb_stat_error(void) 97b2e8fb6eSPeter Zijlstra { 98b2e8fb6eSPeter Zijlstra #ifdef CONFIG_SMP 9993f78d88STejun Heo return nr_cpu_ids * WB_STAT_BATCH; 100b2e8fb6eSPeter Zijlstra #else 101b2e8fb6eSPeter Zijlstra return 1; 102b2e8fb6eSPeter Zijlstra #endif 103e0bf68ddSPeter Zijlstra } 1041da177e4SLinus Torvalds 105189d3c4aSPeter Zijlstra int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio); 106a42dde04SPeter Zijlstra int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio); 107189d3c4aSPeter Zijlstra 1081da177e4SLinus Torvalds /* 1091da177e4SLinus Torvalds * Flags in backing_dev_info::capability 110e4ad08feSMiklos Szeredi * 111e4ad08feSMiklos Szeredi * The first three flags control whether dirty pages will contribute to the 1121da177e4SLinus Torvalds * VM's accounting and whether writepages() should be called for dirty pages 1131da177e4SLinus Torvalds * (something that would not, for example, be appropriate for ramfs) 114e4ad08feSMiklos Szeredi * 115e4ad08feSMiklos Szeredi * WARNING: these flags are closely related and should not normally be 116e4ad08feSMiklos Szeredi * used separately. The BDI_CAP_NO_ACCT_AND_WRITEBACK combines these 117e4ad08feSMiklos Szeredi * three flags into a single convenience macro. 118e4ad08feSMiklos Szeredi * 119e4ad08feSMiklos Szeredi * BDI_CAP_NO_ACCT_DIRTY: Dirty pages shouldn't contribute to accounting 120e4ad08feSMiklos Szeredi * BDI_CAP_NO_WRITEBACK: Don't write pages back 121e4ad08feSMiklos Szeredi * BDI_CAP_NO_ACCT_WB: Don't automatically account writeback pages 1225a537485SMaxim Patlasov * BDI_CAP_STRICTLIMIT: Keep number of dirty pages below bdi threshold. 12389e9b9e0STejun Heo * 12489e9b9e0STejun Heo * BDI_CAP_CGROUP_WRITEBACK: Supports cgroup-aware writeback. 12523c47d2aSMinchan Kim * BDI_CAP_SYNCHRONOUS_IO: Device is so fast that asynchronous IO would be 12623c47d2aSMinchan Kim * inefficient. 1271da177e4SLinus Torvalds */ 128e4ad08feSMiklos Szeredi #define BDI_CAP_NO_ACCT_DIRTY 0x00000001 129e4ad08feSMiklos Szeredi #define BDI_CAP_NO_WRITEBACK 0x00000002 130b4caecd4SChristoph Hellwig #define BDI_CAP_NO_ACCT_WB 0x00000004 131b4caecd4SChristoph Hellwig #define BDI_CAP_STABLE_WRITES 0x00000008 132b4caecd4SChristoph Hellwig #define BDI_CAP_STRICTLIMIT 0x00000010 13389e9b9e0STejun Heo #define BDI_CAP_CGROUP_WRITEBACK 0x00000020 13423c47d2aSMinchan Kim #define BDI_CAP_SYNCHRONOUS_IO 0x00000040 1351da177e4SLinus Torvalds 136e4ad08feSMiklos Szeredi #define BDI_CAP_NO_ACCT_AND_WRITEBACK \ 137e4ad08feSMiklos Szeredi (BDI_CAP_NO_WRITEBACK | BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_ACCT_WB) 138e4ad08feSMiklos Szeredi 1395129a469SJörn Engel extern struct backing_dev_info noop_backing_dev_info; 1401da177e4SLinus Torvalds 141bc05873dSTejun Heo /** 142bc05873dSTejun Heo * writeback_in_progress - determine whether there is writeback in progress 143bc05873dSTejun Heo * @wb: bdi_writeback of interest 144bc05873dSTejun Heo * 145bc05873dSTejun Heo * Determine whether there is writeback waiting to be handled against a 146bc05873dSTejun Heo * bdi_writeback. 147bc05873dSTejun Heo */ 148bc05873dSTejun Heo static inline bool writeback_in_progress(struct bdi_writeback *wb) 1491da177e4SLinus Torvalds { 150bc05873dSTejun Heo return test_bit(WB_writeback_running, &wb->state); 151bc05873dSTejun Heo } 1521da177e4SLinus Torvalds 153a212b105STejun Heo static inline struct backing_dev_info *inode_to_bdi(struct inode *inode) 154a212b105STejun Heo { 155a212b105STejun Heo struct super_block *sb; 156a212b105STejun Heo 157a212b105STejun Heo if (!inode) 158a212b105STejun Heo return &noop_backing_dev_info; 159a212b105STejun Heo 160a212b105STejun Heo sb = inode->i_sb; 161a212b105STejun Heo #ifdef CONFIG_BLOCK 162a212b105STejun Heo if (sb_is_blkdev_sb(sb)) 163efa7c9f9SJan Kara return I_BDEV(inode)->bd_bdi; 164a212b105STejun Heo #endif 165a212b105STejun Heo return sb->s_bdi; 166a212b105STejun Heo } 167a212b105STejun Heo 168ec8a6f26STejun Heo static inline int wb_congested(struct bdi_writeback *wb, int cong_bits) 1691da177e4SLinus Torvalds { 170ec8a6f26STejun Heo struct backing_dev_info *bdi = wb->bdi; 171ec8a6f26STejun Heo 1721da177e4SLinus Torvalds if (bdi->congested_fn) 173ec8a6f26STejun Heo return bdi->congested_fn(bdi->congested_data, cong_bits); 174ec8a6f26STejun Heo return wb->congested->state & cong_bits; 1751da177e4SLinus Torvalds } 1761da177e4SLinus Torvalds 1778aa7e847SJens Axboe long congestion_wait(int sync, long timeout); 178599d0c95SMel Gorman long wait_iff_congested(struct pglist_data *pgdat, int sync, long timeout); 1791da177e4SLinus Torvalds 18023c47d2aSMinchan Kim static inline bool bdi_cap_synchronous_io(struct backing_dev_info *bdi) 18123c47d2aSMinchan Kim { 18223c47d2aSMinchan Kim return bdi->capabilities & BDI_CAP_SYNCHRONOUS_IO; 18323c47d2aSMinchan Kim } 18423c47d2aSMinchan Kim 1857d311cdaSDarrick J. Wong static inline bool bdi_cap_stable_pages_required(struct backing_dev_info *bdi) 1867d311cdaSDarrick J. Wong { 1877d311cdaSDarrick J. Wong return bdi->capabilities & BDI_CAP_STABLE_WRITES; 1887d311cdaSDarrick J. Wong } 1897d311cdaSDarrick J. Wong 190e4ad08feSMiklos Szeredi static inline bool bdi_cap_writeback_dirty(struct backing_dev_info *bdi) 191e4ad08feSMiklos Szeredi { 192e4ad08feSMiklos Szeredi return !(bdi->capabilities & BDI_CAP_NO_WRITEBACK); 193e4ad08feSMiklos Szeredi } 1941da177e4SLinus Torvalds 195e4ad08feSMiklos Szeredi static inline bool bdi_cap_account_dirty(struct backing_dev_info *bdi) 196e4ad08feSMiklos Szeredi { 197e4ad08feSMiklos Szeredi return !(bdi->capabilities & BDI_CAP_NO_ACCT_DIRTY); 198e4ad08feSMiklos Szeredi } 1991da177e4SLinus Torvalds 200e4ad08feSMiklos Szeredi static inline bool bdi_cap_account_writeback(struct backing_dev_info *bdi) 201e4ad08feSMiklos Szeredi { 202e4ad08feSMiklos Szeredi /* Paranoia: BDI_CAP_NO_WRITEBACK implies BDI_CAP_NO_ACCT_WB */ 203e4ad08feSMiklos Szeredi return !(bdi->capabilities & (BDI_CAP_NO_ACCT_WB | 204e4ad08feSMiklos Szeredi BDI_CAP_NO_WRITEBACK)); 205e4ad08feSMiklos Szeredi } 2061da177e4SLinus Torvalds 207e4ad08feSMiklos Szeredi static inline bool mapping_cap_writeback_dirty(struct address_space *mapping) 208e4ad08feSMiklos Szeredi { 209de1414a6SChristoph Hellwig return bdi_cap_writeback_dirty(inode_to_bdi(mapping->host)); 210e4ad08feSMiklos Szeredi } 211e4ad08feSMiklos Szeredi 212e4ad08feSMiklos Szeredi static inline bool mapping_cap_account_dirty(struct address_space *mapping) 213e4ad08feSMiklos Szeredi { 214de1414a6SChristoph Hellwig return bdi_cap_account_dirty(inode_to_bdi(mapping->host)); 215e4ad08feSMiklos Szeredi } 2161da177e4SLinus Torvalds 21703ba3782SJens Axboe static inline int bdi_sched_wait(void *word) 21803ba3782SJens Axboe { 21903ba3782SJens Axboe schedule(); 22003ba3782SJens Axboe return 0; 22103ba3782SJens Axboe } 22203ba3782SJens Axboe 22389e9b9e0STejun Heo #ifdef CONFIG_CGROUP_WRITEBACK 22489e9b9e0STejun Heo 22552ebea74STejun Heo struct bdi_writeback_congested * 22652ebea74STejun Heo wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp); 22752ebea74STejun Heo void wb_congested_put(struct bdi_writeback_congested *congested); 22852ebea74STejun Heo struct bdi_writeback *wb_get_create(struct backing_dev_info *bdi, 22952ebea74STejun Heo struct cgroup_subsys_state *memcg_css, 23052ebea74STejun Heo gfp_t gfp); 23152ebea74STejun Heo void wb_memcg_offline(struct mem_cgroup *memcg); 23252ebea74STejun Heo void wb_blkcg_offline(struct blkcg *blkcg); 233703c2708STejun Heo int inode_congested(struct inode *inode, int cong_bits); 23452ebea74STejun Heo 23589e9b9e0STejun Heo /** 23689e9b9e0STejun Heo * inode_cgwb_enabled - test whether cgroup writeback is enabled on an inode 23789e9b9e0STejun Heo * @inode: inode of interest 23889e9b9e0STejun Heo * 23989e9b9e0STejun Heo * cgroup writeback requires support from both the bdi and filesystem. 2409badce00STejun Heo * Also, both memcg and iocg have to be on the default hierarchy. Test 2419badce00STejun Heo * whether all conditions are met. 2429badce00STejun Heo * 2439badce00STejun Heo * Note that the test result may change dynamically on the same inode 2449badce00STejun Heo * depending on how memcg and iocg are configured. 24589e9b9e0STejun Heo */ 24689e9b9e0STejun Heo static inline bool inode_cgwb_enabled(struct inode *inode) 24789e9b9e0STejun Heo { 24889e9b9e0STejun Heo struct backing_dev_info *bdi = inode_to_bdi(inode); 24989e9b9e0STejun Heo 250c0522908STejun Heo return cgroup_subsys_on_dfl(memory_cgrp_subsys) && 251c0522908STejun Heo cgroup_subsys_on_dfl(io_cgrp_subsys) && 2529badce00STejun Heo bdi_cap_account_dirty(bdi) && 25389e9b9e0STejun Heo (bdi->capabilities & BDI_CAP_CGROUP_WRITEBACK) && 25446b15caaSTejun Heo (inode->i_sb->s_iflags & SB_I_CGROUPWB); 25589e9b9e0STejun Heo } 25689e9b9e0STejun Heo 25752ebea74STejun Heo /** 25852ebea74STejun Heo * wb_find_current - find wb for %current on a bdi 25952ebea74STejun Heo * @bdi: bdi of interest 26052ebea74STejun Heo * 26152ebea74STejun Heo * Find the wb of @bdi which matches both the memcg and blkcg of %current. 26252ebea74STejun Heo * Must be called under rcu_read_lock() which protects the returend wb. 26352ebea74STejun Heo * NULL if not found. 26452ebea74STejun Heo */ 26552ebea74STejun Heo static inline struct bdi_writeback *wb_find_current(struct backing_dev_info *bdi) 26652ebea74STejun Heo { 26752ebea74STejun Heo struct cgroup_subsys_state *memcg_css; 26852ebea74STejun Heo struct bdi_writeback *wb; 26952ebea74STejun Heo 27052ebea74STejun Heo memcg_css = task_css(current, memory_cgrp_id); 27152ebea74STejun Heo if (!memcg_css->parent) 27252ebea74STejun Heo return &bdi->wb; 27352ebea74STejun Heo 27452ebea74STejun Heo wb = radix_tree_lookup(&bdi->cgwb_tree, memcg_css->id); 27552ebea74STejun Heo 27652ebea74STejun Heo /* 27752ebea74STejun Heo * %current's blkcg equals the effective blkcg of its memcg. No 27852ebea74STejun Heo * need to use the relatively expensive cgroup_get_e_css(). 27952ebea74STejun Heo */ 280c165b3e3STejun Heo if (likely(wb && wb->blkcg_css == task_css(current, io_cgrp_id))) 28152ebea74STejun Heo return wb; 28252ebea74STejun Heo return NULL; 28352ebea74STejun Heo } 28452ebea74STejun Heo 28552ebea74STejun Heo /** 28652ebea74STejun Heo * wb_get_create_current - get or create wb for %current on a bdi 28752ebea74STejun Heo * @bdi: bdi of interest 28852ebea74STejun Heo * @gfp: allocation mask 28952ebea74STejun Heo * 29052ebea74STejun Heo * Equivalent to wb_get_create() on %current's memcg. This function is 29152ebea74STejun Heo * called from a relatively hot path and optimizes the common cases using 29252ebea74STejun Heo * wb_find_current(). 29352ebea74STejun Heo */ 29452ebea74STejun Heo static inline struct bdi_writeback * 29552ebea74STejun Heo wb_get_create_current(struct backing_dev_info *bdi, gfp_t gfp) 29652ebea74STejun Heo { 29752ebea74STejun Heo struct bdi_writeback *wb; 29852ebea74STejun Heo 29952ebea74STejun Heo rcu_read_lock(); 30052ebea74STejun Heo wb = wb_find_current(bdi); 30152ebea74STejun Heo if (wb && unlikely(!wb_tryget(wb))) 30252ebea74STejun Heo wb = NULL; 30352ebea74STejun Heo rcu_read_unlock(); 30452ebea74STejun Heo 30552ebea74STejun Heo if (unlikely(!wb)) { 30652ebea74STejun Heo struct cgroup_subsys_state *memcg_css; 30752ebea74STejun Heo 30852ebea74STejun Heo memcg_css = task_get_css(current, memory_cgrp_id); 30952ebea74STejun Heo wb = wb_get_create(bdi, memcg_css, gfp); 31052ebea74STejun Heo css_put(memcg_css); 31152ebea74STejun Heo } 31252ebea74STejun Heo return wb; 31352ebea74STejun Heo } 31452ebea74STejun Heo 31552ebea74STejun Heo /** 316aaa2cacfSTejun Heo * inode_to_wb_is_valid - test whether an inode has a wb associated 317aaa2cacfSTejun Heo * @inode: inode of interest 318aaa2cacfSTejun Heo * 319aaa2cacfSTejun Heo * Returns %true if @inode has a wb associated. May be called without any 320aaa2cacfSTejun Heo * locking. 321aaa2cacfSTejun Heo */ 322aaa2cacfSTejun Heo static inline bool inode_to_wb_is_valid(struct inode *inode) 323aaa2cacfSTejun Heo { 324aaa2cacfSTejun Heo return inode->i_wb; 325aaa2cacfSTejun Heo } 326aaa2cacfSTejun Heo 327aaa2cacfSTejun Heo /** 32852ebea74STejun Heo * inode_to_wb - determine the wb of an inode 32952ebea74STejun Heo * @inode: inode of interest 33052ebea74STejun Heo * 331aaa2cacfSTejun Heo * Returns the wb @inode is currently associated with. The caller must be 332aaa2cacfSTejun Heo * holding either @inode->i_lock, @inode->i_mapping->tree_lock, or the 333aaa2cacfSTejun Heo * associated wb's list_lock. 33452ebea74STejun Heo */ 33552ebea74STejun Heo static inline struct bdi_writeback *inode_to_wb(struct inode *inode) 33652ebea74STejun Heo { 337aaa2cacfSTejun Heo #ifdef CONFIG_LOCKDEP 338aaa2cacfSTejun Heo WARN_ON_ONCE(debug_locks && 339aaa2cacfSTejun Heo (!lockdep_is_held(&inode->i_lock) && 340aaa2cacfSTejun Heo !lockdep_is_held(&inode->i_mapping->tree_lock) && 341aaa2cacfSTejun Heo !lockdep_is_held(&inode->i_wb->list_lock))); 342aaa2cacfSTejun Heo #endif 34352ebea74STejun Heo return inode->i_wb; 34452ebea74STejun Heo } 34552ebea74STejun Heo 346682aa8e1STejun Heo /** 347682aa8e1STejun Heo * unlocked_inode_to_wb_begin - begin unlocked inode wb access transaction 348682aa8e1STejun Heo * @inode: target inode 349682aa8e1STejun Heo * @lockedp: temp bool output param, to be passed to the end function 350682aa8e1STejun Heo * 351682aa8e1STejun Heo * The caller wants to access the wb associated with @inode but isn't 352682aa8e1STejun Heo * holding inode->i_lock, mapping->tree_lock or wb->list_lock. This 353682aa8e1STejun Heo * function determines the wb associated with @inode and ensures that the 354682aa8e1STejun Heo * association doesn't change until the transaction is finished with 355682aa8e1STejun Heo * unlocked_inode_to_wb_end(). 356682aa8e1STejun Heo * 357682aa8e1STejun Heo * The caller must call unlocked_inode_to_wb_end() with *@lockdep 358682aa8e1STejun Heo * afterwards and can't sleep during transaction. IRQ may or may not be 359682aa8e1STejun Heo * disabled on return. 360682aa8e1STejun Heo */ 361682aa8e1STejun Heo static inline struct bdi_writeback * 362682aa8e1STejun Heo unlocked_inode_to_wb_begin(struct inode *inode, bool *lockedp) 363682aa8e1STejun Heo { 364682aa8e1STejun Heo rcu_read_lock(); 365682aa8e1STejun Heo 366682aa8e1STejun Heo /* 367682aa8e1STejun Heo * Paired with store_release in inode_switch_wb_work_fn() and 368682aa8e1STejun Heo * ensures that we see the new wb if we see cleared I_WB_SWITCH. 369682aa8e1STejun Heo */ 370682aa8e1STejun Heo *lockedp = smp_load_acquire(&inode->i_state) & I_WB_SWITCH; 371682aa8e1STejun Heo 372682aa8e1STejun Heo if (unlikely(*lockedp)) 373682aa8e1STejun Heo spin_lock_irq(&inode->i_mapping->tree_lock); 374aaa2cacfSTejun Heo 375aaa2cacfSTejun Heo /* 376aaa2cacfSTejun Heo * Protected by either !I_WB_SWITCH + rcu_read_lock() or tree_lock. 377aaa2cacfSTejun Heo * inode_to_wb() will bark. Deref directly. 378aaa2cacfSTejun Heo */ 379aaa2cacfSTejun Heo return inode->i_wb; 380682aa8e1STejun Heo } 381682aa8e1STejun Heo 382682aa8e1STejun Heo /** 383682aa8e1STejun Heo * unlocked_inode_to_wb_end - end inode wb access transaction 384682aa8e1STejun Heo * @inode: target inode 385682aa8e1STejun Heo * @locked: *@lockedp from unlocked_inode_to_wb_begin() 386682aa8e1STejun Heo */ 387682aa8e1STejun Heo static inline void unlocked_inode_to_wb_end(struct inode *inode, bool locked) 388682aa8e1STejun Heo { 389682aa8e1STejun Heo if (unlikely(locked)) 390682aa8e1STejun Heo spin_unlock_irq(&inode->i_mapping->tree_lock); 391682aa8e1STejun Heo 392682aa8e1STejun Heo rcu_read_unlock(); 393682aa8e1STejun Heo } 394682aa8e1STejun Heo 39589e9b9e0STejun Heo #else /* CONFIG_CGROUP_WRITEBACK */ 39689e9b9e0STejun Heo 39789e9b9e0STejun Heo static inline bool inode_cgwb_enabled(struct inode *inode) 39889e9b9e0STejun Heo { 39989e9b9e0STejun Heo return false; 40089e9b9e0STejun Heo } 40189e9b9e0STejun Heo 40252ebea74STejun Heo static inline struct bdi_writeback_congested * 40352ebea74STejun Heo wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp) 40452ebea74STejun Heo { 405a13f35e8STejun Heo atomic_inc(&bdi->wb_congested->refcnt); 406a13f35e8STejun Heo return bdi->wb_congested; 40752ebea74STejun Heo } 40852ebea74STejun Heo 40952ebea74STejun Heo static inline void wb_congested_put(struct bdi_writeback_congested *congested) 41052ebea74STejun Heo { 411a13f35e8STejun Heo if (atomic_dec_and_test(&congested->refcnt)) 412a13f35e8STejun Heo kfree(congested); 41352ebea74STejun Heo } 41452ebea74STejun Heo 41552ebea74STejun Heo static inline struct bdi_writeback *wb_find_current(struct backing_dev_info *bdi) 41652ebea74STejun Heo { 41752ebea74STejun Heo return &bdi->wb; 41852ebea74STejun Heo } 41952ebea74STejun Heo 42052ebea74STejun Heo static inline struct bdi_writeback * 42152ebea74STejun Heo wb_get_create_current(struct backing_dev_info *bdi, gfp_t gfp) 42252ebea74STejun Heo { 42352ebea74STejun Heo return &bdi->wb; 42452ebea74STejun Heo } 42552ebea74STejun Heo 426aaa2cacfSTejun Heo static inline bool inode_to_wb_is_valid(struct inode *inode) 427aaa2cacfSTejun Heo { 428aaa2cacfSTejun Heo return true; 429aaa2cacfSTejun Heo } 430aaa2cacfSTejun Heo 43152ebea74STejun Heo static inline struct bdi_writeback *inode_to_wb(struct inode *inode) 43252ebea74STejun Heo { 43352ebea74STejun Heo return &inode_to_bdi(inode)->wb; 43452ebea74STejun Heo } 43552ebea74STejun Heo 436682aa8e1STejun Heo static inline struct bdi_writeback * 437682aa8e1STejun Heo unlocked_inode_to_wb_begin(struct inode *inode, bool *lockedp) 438682aa8e1STejun Heo { 439682aa8e1STejun Heo return inode_to_wb(inode); 440682aa8e1STejun Heo } 441682aa8e1STejun Heo 442682aa8e1STejun Heo static inline void unlocked_inode_to_wb_end(struct inode *inode, bool locked) 443682aa8e1STejun Heo { 444682aa8e1STejun Heo } 445682aa8e1STejun Heo 44652ebea74STejun Heo static inline void wb_memcg_offline(struct mem_cgroup *memcg) 44752ebea74STejun Heo { 44852ebea74STejun Heo } 44952ebea74STejun Heo 45052ebea74STejun Heo static inline void wb_blkcg_offline(struct blkcg *blkcg) 45152ebea74STejun Heo { 45252ebea74STejun Heo } 45352ebea74STejun Heo 454703c2708STejun Heo static inline int inode_congested(struct inode *inode, int cong_bits) 455703c2708STejun Heo { 456703c2708STejun Heo return wb_congested(&inode_to_bdi(inode)->wb, cong_bits); 457703c2708STejun Heo } 458703c2708STejun Heo 45989e9b9e0STejun Heo #endif /* CONFIG_CGROUP_WRITEBACK */ 46089e9b9e0STejun Heo 461703c2708STejun Heo static inline int inode_read_congested(struct inode *inode) 462703c2708STejun Heo { 463703c2708STejun Heo return inode_congested(inode, 1 << WB_sync_congested); 464703c2708STejun Heo } 465703c2708STejun Heo 466703c2708STejun Heo static inline int inode_write_congested(struct inode *inode) 467703c2708STejun Heo { 468703c2708STejun Heo return inode_congested(inode, 1 << WB_async_congested); 469703c2708STejun Heo } 470703c2708STejun Heo 471703c2708STejun Heo static inline int inode_rw_congested(struct inode *inode) 472703c2708STejun Heo { 473703c2708STejun Heo return inode_congested(inode, (1 << WB_sync_congested) | 474703c2708STejun Heo (1 << WB_async_congested)); 475703c2708STejun Heo } 476703c2708STejun Heo 477ec8a6f26STejun Heo static inline int bdi_congested(struct backing_dev_info *bdi, int cong_bits) 478ec8a6f26STejun Heo { 479ec8a6f26STejun Heo return wb_congested(&bdi->wb, cong_bits); 480ec8a6f26STejun Heo } 481ec8a6f26STejun Heo 482ec8a6f26STejun Heo static inline int bdi_read_congested(struct backing_dev_info *bdi) 483ec8a6f26STejun Heo { 484ec8a6f26STejun Heo return bdi_congested(bdi, 1 << WB_sync_congested); 485ec8a6f26STejun Heo } 486ec8a6f26STejun Heo 487ec8a6f26STejun Heo static inline int bdi_write_congested(struct backing_dev_info *bdi) 488ec8a6f26STejun Heo { 489ec8a6f26STejun Heo return bdi_congested(bdi, 1 << WB_async_congested); 490ec8a6f26STejun Heo } 491ec8a6f26STejun Heo 492ec8a6f26STejun Heo static inline int bdi_rw_congested(struct backing_dev_info *bdi) 493ec8a6f26STejun Heo { 494ec8a6f26STejun Heo return bdi_congested(bdi, (1 << WB_sync_congested) | 495ec8a6f26STejun Heo (1 << WB_async_congested)); 496ec8a6f26STejun Heo } 497ec8a6f26STejun Heo 4981da177e4SLinus Torvalds #endif /* _LINUX_BACKING_DEV_H */ 499