11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * include/linux/backing-dev.h 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * low-level device information and state which is propagated up through 51da177e4SLinus Torvalds * to high-level code. 61da177e4SLinus Torvalds */ 71da177e4SLinus Torvalds 81da177e4SLinus Torvalds #ifndef _LINUX_BACKING_DEV_H 91da177e4SLinus Torvalds #define _LINUX_BACKING_DEV_H 101da177e4SLinus Torvalds 11cf0ca9feSPeter Zijlstra #include <linux/kernel.h> 12e4ad08feSMiklos Szeredi #include <linux/fs.h> 1303ba3782SJens Axboe #include <linux/sched.h> 14a212b105STejun Heo #include <linux/blkdev.h> 1503ba3782SJens Axboe #include <linux/writeback.h> 1652ebea74STejun Heo #include <linux/blk-cgroup.h> 1766114cadSTejun Heo #include <linux/backing-dev-defs.h> 18a13f35e8STejun Heo #include <linux/slab.h> 19de1414a6SChristoph Hellwig 208077c0d9SMikulas Patocka int __must_check bdi_init(struct backing_dev_info *bdi); 21b02176f3STejun Heo void bdi_exit(struct backing_dev_info *bdi); 22b2e8fb6eSPeter Zijlstra 23d2cc4ddeSJoe Perches __printf(3, 4) 24cf0ca9feSPeter Zijlstra int bdi_register(struct backing_dev_info *bdi, struct device *parent, 25cf0ca9feSPeter Zijlstra const char *fmt, ...); 26cf0ca9feSPeter Zijlstra int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev); 27b02176f3STejun Heo void bdi_unregister(struct backing_dev_info *bdi); 28b02176f3STejun Heo 29b4caecd4SChristoph Hellwig int __must_check bdi_setup_and_register(struct backing_dev_info *, char *); 30b02176f3STejun Heo void bdi_destroy(struct backing_dev_info *bdi); 31b02176f3STejun Heo 32c00ddad3STejun Heo void wb_start_writeback(struct bdi_writeback *wb, long nr_pages, 33c00ddad3STejun Heo bool range_cyclic, enum wb_reason reason); 349ecf4866STejun Heo void wb_start_background_writeback(struct bdi_writeback *wb); 35f0054bb1STejun Heo void wb_workfn(struct work_struct *work); 36f0054bb1STejun Heo void wb_wakeup_delayed(struct bdi_writeback *wb); 37cf0ca9feSPeter Zijlstra 3803ba3782SJens Axboe extern spinlock_t bdi_lock; 3966f3b8e2SJens Axboe extern struct list_head bdi_list; 4066f3b8e2SJens Axboe 41839a8e86STejun Heo extern struct workqueue_struct *bdi_wq; 42839a8e86STejun Heo 43d6c10f1fSTejun Heo static inline bool wb_has_dirty_io(struct bdi_writeback *wb) 4403ba3782SJens Axboe { 45d6c10f1fSTejun Heo return test_bit(WB_has_dirty_io, &wb->state); 4603ba3782SJens Axboe } 4703ba3782SJens Axboe 4895a46c65STejun Heo static inline bool bdi_has_dirty_io(struct backing_dev_info *bdi) 49e0bf68ddSPeter Zijlstra { 5095a46c65STejun Heo /* 5195a46c65STejun Heo * @bdi->tot_write_bandwidth is guaranteed to be > 0 if there are 5295a46c65STejun Heo * any dirty wbs. See wb_update_write_bandwidth(). 5395a46c65STejun Heo */ 5495a46c65STejun Heo return atomic_long_read(&bdi->tot_write_bandwidth); 55e0bf68ddSPeter Zijlstra } 56e0bf68ddSPeter Zijlstra 5793f78d88STejun Heo static inline void __add_wb_stat(struct bdi_writeback *wb, 5893f78d88STejun Heo enum wb_stat_item item, s64 amount) 59e0bf68ddSPeter Zijlstra { 6093f78d88STejun Heo __percpu_counter_add(&wb->stat[item], amount, WB_STAT_BATCH); 61b2e8fb6eSPeter Zijlstra } 62b2e8fb6eSPeter Zijlstra 6393f78d88STejun Heo static inline void __inc_wb_stat(struct bdi_writeback *wb, 6493f78d88STejun Heo enum wb_stat_item item) 65e0bf68ddSPeter Zijlstra { 6693f78d88STejun Heo __add_wb_stat(wb, item, 1); 67b2e8fb6eSPeter Zijlstra } 68b2e8fb6eSPeter Zijlstra 6993f78d88STejun Heo static inline void inc_wb_stat(struct bdi_writeback *wb, enum wb_stat_item item) 70b2e8fb6eSPeter Zijlstra { 71b2e8fb6eSPeter Zijlstra unsigned long flags; 72b2e8fb6eSPeter Zijlstra 73b2e8fb6eSPeter Zijlstra local_irq_save(flags); 7493f78d88STejun Heo __inc_wb_stat(wb, item); 75b2e8fb6eSPeter Zijlstra local_irq_restore(flags); 76b2e8fb6eSPeter Zijlstra } 77b2e8fb6eSPeter Zijlstra 7893f78d88STejun Heo static inline void __dec_wb_stat(struct bdi_writeback *wb, 7993f78d88STejun Heo enum wb_stat_item item) 80b2e8fb6eSPeter Zijlstra { 8193f78d88STejun Heo __add_wb_stat(wb, item, -1); 82b2e8fb6eSPeter Zijlstra } 83b2e8fb6eSPeter Zijlstra 8493f78d88STejun Heo static inline void dec_wb_stat(struct bdi_writeback *wb, enum wb_stat_item item) 85b2e8fb6eSPeter Zijlstra { 86b2e8fb6eSPeter Zijlstra unsigned long flags; 87b2e8fb6eSPeter Zijlstra 88b2e8fb6eSPeter Zijlstra local_irq_save(flags); 8993f78d88STejun Heo __dec_wb_stat(wb, item); 90b2e8fb6eSPeter Zijlstra local_irq_restore(flags); 91b2e8fb6eSPeter Zijlstra } 92b2e8fb6eSPeter Zijlstra 9393f78d88STejun Heo static inline s64 wb_stat(struct bdi_writeback *wb, enum wb_stat_item item) 94b2e8fb6eSPeter Zijlstra { 9593f78d88STejun Heo return percpu_counter_read_positive(&wb->stat[item]); 96b2e8fb6eSPeter Zijlstra } 97b2e8fb6eSPeter Zijlstra 9893f78d88STejun Heo static inline s64 __wb_stat_sum(struct bdi_writeback *wb, 9993f78d88STejun Heo enum wb_stat_item item) 100b2e8fb6eSPeter Zijlstra { 10193f78d88STejun Heo return percpu_counter_sum_positive(&wb->stat[item]); 102b2e8fb6eSPeter Zijlstra } 103b2e8fb6eSPeter Zijlstra 10493f78d88STejun Heo static inline s64 wb_stat_sum(struct bdi_writeback *wb, enum wb_stat_item item) 105b2e8fb6eSPeter Zijlstra { 106b2e8fb6eSPeter Zijlstra s64 sum; 107b2e8fb6eSPeter Zijlstra unsigned long flags; 108b2e8fb6eSPeter Zijlstra 109b2e8fb6eSPeter Zijlstra local_irq_save(flags); 11093f78d88STejun Heo sum = __wb_stat_sum(wb, item); 111b2e8fb6eSPeter Zijlstra local_irq_restore(flags); 112b2e8fb6eSPeter Zijlstra 113b2e8fb6eSPeter Zijlstra return sum; 114b2e8fb6eSPeter Zijlstra } 115b2e8fb6eSPeter Zijlstra 11693f78d88STejun Heo extern void wb_writeout_inc(struct bdi_writeback *wb); 117dd5656e5SMiklos Szeredi 118b2e8fb6eSPeter Zijlstra /* 119b2e8fb6eSPeter Zijlstra * maximal error of a stat counter. 120b2e8fb6eSPeter Zijlstra */ 12193f78d88STejun Heo static inline unsigned long wb_stat_error(struct bdi_writeback *wb) 122b2e8fb6eSPeter Zijlstra { 123b2e8fb6eSPeter Zijlstra #ifdef CONFIG_SMP 12493f78d88STejun Heo return nr_cpu_ids * WB_STAT_BATCH; 125b2e8fb6eSPeter Zijlstra #else 126b2e8fb6eSPeter Zijlstra return 1; 127b2e8fb6eSPeter Zijlstra #endif 128e0bf68ddSPeter Zijlstra } 1291da177e4SLinus Torvalds 130189d3c4aSPeter Zijlstra int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio); 131a42dde04SPeter Zijlstra int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio); 132189d3c4aSPeter Zijlstra 1331da177e4SLinus Torvalds /* 1341da177e4SLinus Torvalds * Flags in backing_dev_info::capability 135e4ad08feSMiklos Szeredi * 136e4ad08feSMiklos Szeredi * The first three flags control whether dirty pages will contribute to the 1371da177e4SLinus Torvalds * VM's accounting and whether writepages() should be called for dirty pages 1381da177e4SLinus Torvalds * (something that would not, for example, be appropriate for ramfs) 139e4ad08feSMiklos Szeredi * 140e4ad08feSMiklos Szeredi * WARNING: these flags are closely related and should not normally be 141e4ad08feSMiklos Szeredi * used separately. The BDI_CAP_NO_ACCT_AND_WRITEBACK combines these 142e4ad08feSMiklos Szeredi * three flags into a single convenience macro. 143e4ad08feSMiklos Szeredi * 144e4ad08feSMiklos Szeredi * BDI_CAP_NO_ACCT_DIRTY: Dirty pages shouldn't contribute to accounting 145e4ad08feSMiklos Szeredi * BDI_CAP_NO_WRITEBACK: Don't write pages back 146e4ad08feSMiklos Szeredi * BDI_CAP_NO_ACCT_WB: Don't automatically account writeback pages 1475a537485SMaxim Patlasov * BDI_CAP_STRICTLIMIT: Keep number of dirty pages below bdi threshold. 14889e9b9e0STejun Heo * 14989e9b9e0STejun Heo * BDI_CAP_CGROUP_WRITEBACK: Supports cgroup-aware writeback. 1501da177e4SLinus Torvalds */ 151e4ad08feSMiklos Szeredi #define BDI_CAP_NO_ACCT_DIRTY 0x00000001 152e4ad08feSMiklos Szeredi #define BDI_CAP_NO_WRITEBACK 0x00000002 153b4caecd4SChristoph Hellwig #define BDI_CAP_NO_ACCT_WB 0x00000004 154b4caecd4SChristoph Hellwig #define BDI_CAP_STABLE_WRITES 0x00000008 155b4caecd4SChristoph Hellwig #define BDI_CAP_STRICTLIMIT 0x00000010 15689e9b9e0STejun Heo #define BDI_CAP_CGROUP_WRITEBACK 0x00000020 1571da177e4SLinus Torvalds 158e4ad08feSMiklos Szeredi #define BDI_CAP_NO_ACCT_AND_WRITEBACK \ 159e4ad08feSMiklos Szeredi (BDI_CAP_NO_WRITEBACK | BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_ACCT_WB) 160e4ad08feSMiklos Szeredi 1615129a469SJörn Engel extern struct backing_dev_info noop_backing_dev_info; 1621da177e4SLinus Torvalds 163bc05873dSTejun Heo /** 164bc05873dSTejun Heo * writeback_in_progress - determine whether there is writeback in progress 165bc05873dSTejun Heo * @wb: bdi_writeback of interest 166bc05873dSTejun Heo * 167bc05873dSTejun Heo * Determine whether there is writeback waiting to be handled against a 168bc05873dSTejun Heo * bdi_writeback. 169bc05873dSTejun Heo */ 170bc05873dSTejun Heo static inline bool writeback_in_progress(struct bdi_writeback *wb) 1711da177e4SLinus Torvalds { 172bc05873dSTejun Heo return test_bit(WB_writeback_running, &wb->state); 173bc05873dSTejun Heo } 1741da177e4SLinus Torvalds 175a212b105STejun Heo static inline struct backing_dev_info *inode_to_bdi(struct inode *inode) 176a212b105STejun Heo { 177a212b105STejun Heo struct super_block *sb; 178a212b105STejun Heo 179a212b105STejun Heo if (!inode) 180a212b105STejun Heo return &noop_backing_dev_info; 181a212b105STejun Heo 182a212b105STejun Heo sb = inode->i_sb; 183a212b105STejun Heo #ifdef CONFIG_BLOCK 184a212b105STejun Heo if (sb_is_blkdev_sb(sb)) 185a212b105STejun Heo return blk_get_backing_dev_info(I_BDEV(inode)); 186a212b105STejun Heo #endif 187a212b105STejun Heo return sb->s_bdi; 188a212b105STejun Heo } 189a212b105STejun Heo 190ec8a6f26STejun Heo static inline int wb_congested(struct bdi_writeback *wb, int cong_bits) 1911da177e4SLinus Torvalds { 192ec8a6f26STejun Heo struct backing_dev_info *bdi = wb->bdi; 193ec8a6f26STejun Heo 1941da177e4SLinus Torvalds if (bdi->congested_fn) 195ec8a6f26STejun Heo return bdi->congested_fn(bdi->congested_data, cong_bits); 196ec8a6f26STejun Heo return wb->congested->state & cong_bits; 1971da177e4SLinus Torvalds } 1981da177e4SLinus Torvalds 1998aa7e847SJens Axboe long congestion_wait(int sync, long timeout); 200*599d0c95SMel Gorman long wait_iff_congested(struct pglist_data *pgdat, int sync, long timeout); 2013965c9aeSWanpeng Li int pdflush_proc_obsolete(struct ctl_table *table, int write, 2023965c9aeSWanpeng Li void __user *buffer, size_t *lenp, loff_t *ppos); 2031da177e4SLinus Torvalds 2047d311cdaSDarrick J. Wong static inline bool bdi_cap_stable_pages_required(struct backing_dev_info *bdi) 2057d311cdaSDarrick J. Wong { 2067d311cdaSDarrick J. Wong return bdi->capabilities & BDI_CAP_STABLE_WRITES; 2077d311cdaSDarrick J. Wong } 2087d311cdaSDarrick J. Wong 209e4ad08feSMiklos Szeredi static inline bool bdi_cap_writeback_dirty(struct backing_dev_info *bdi) 210e4ad08feSMiklos Szeredi { 211e4ad08feSMiklos Szeredi return !(bdi->capabilities & BDI_CAP_NO_WRITEBACK); 212e4ad08feSMiklos Szeredi } 2131da177e4SLinus Torvalds 214e4ad08feSMiklos Szeredi static inline bool bdi_cap_account_dirty(struct backing_dev_info *bdi) 215e4ad08feSMiklos Szeredi { 216e4ad08feSMiklos Szeredi return !(bdi->capabilities & BDI_CAP_NO_ACCT_DIRTY); 217e4ad08feSMiklos Szeredi } 2181da177e4SLinus Torvalds 219e4ad08feSMiklos Szeredi static inline bool bdi_cap_account_writeback(struct backing_dev_info *bdi) 220e4ad08feSMiklos Szeredi { 221e4ad08feSMiklos Szeredi /* Paranoia: BDI_CAP_NO_WRITEBACK implies BDI_CAP_NO_ACCT_WB */ 222e4ad08feSMiklos Szeredi return !(bdi->capabilities & (BDI_CAP_NO_ACCT_WB | 223e4ad08feSMiklos Szeredi BDI_CAP_NO_WRITEBACK)); 224e4ad08feSMiklos Szeredi } 2251da177e4SLinus Torvalds 226e4ad08feSMiklos Szeredi static inline bool mapping_cap_writeback_dirty(struct address_space *mapping) 227e4ad08feSMiklos Szeredi { 228de1414a6SChristoph Hellwig return bdi_cap_writeback_dirty(inode_to_bdi(mapping->host)); 229e4ad08feSMiklos Szeredi } 230e4ad08feSMiklos Szeredi 231e4ad08feSMiklos Szeredi static inline bool mapping_cap_account_dirty(struct address_space *mapping) 232e4ad08feSMiklos Szeredi { 233de1414a6SChristoph Hellwig return bdi_cap_account_dirty(inode_to_bdi(mapping->host)); 234e4ad08feSMiklos Szeredi } 2351da177e4SLinus Torvalds 23603ba3782SJens Axboe static inline int bdi_sched_wait(void *word) 23703ba3782SJens Axboe { 23803ba3782SJens Axboe schedule(); 23903ba3782SJens Axboe return 0; 24003ba3782SJens Axboe } 24103ba3782SJens Axboe 24289e9b9e0STejun Heo #ifdef CONFIG_CGROUP_WRITEBACK 24389e9b9e0STejun Heo 24452ebea74STejun Heo struct bdi_writeback_congested * 24552ebea74STejun Heo wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp); 24652ebea74STejun Heo void wb_congested_put(struct bdi_writeback_congested *congested); 24752ebea74STejun Heo struct bdi_writeback *wb_get_create(struct backing_dev_info *bdi, 24852ebea74STejun Heo struct cgroup_subsys_state *memcg_css, 24952ebea74STejun Heo gfp_t gfp); 25052ebea74STejun Heo void wb_memcg_offline(struct mem_cgroup *memcg); 25152ebea74STejun Heo void wb_blkcg_offline(struct blkcg *blkcg); 252703c2708STejun Heo int inode_congested(struct inode *inode, int cong_bits); 25352ebea74STejun Heo 25489e9b9e0STejun Heo /** 25589e9b9e0STejun Heo * inode_cgwb_enabled - test whether cgroup writeback is enabled on an inode 25689e9b9e0STejun Heo * @inode: inode of interest 25789e9b9e0STejun Heo * 25889e9b9e0STejun Heo * cgroup writeback requires support from both the bdi and filesystem. 2599badce00STejun Heo * Also, both memcg and iocg have to be on the default hierarchy. Test 2609badce00STejun Heo * whether all conditions are met. 2619badce00STejun Heo * 2629badce00STejun Heo * Note that the test result may change dynamically on the same inode 2639badce00STejun Heo * depending on how memcg and iocg are configured. 26489e9b9e0STejun Heo */ 26589e9b9e0STejun Heo static inline bool inode_cgwb_enabled(struct inode *inode) 26689e9b9e0STejun Heo { 26789e9b9e0STejun Heo struct backing_dev_info *bdi = inode_to_bdi(inode); 26889e9b9e0STejun Heo 269c0522908STejun Heo return cgroup_subsys_on_dfl(memory_cgrp_subsys) && 270c0522908STejun Heo cgroup_subsys_on_dfl(io_cgrp_subsys) && 2719badce00STejun Heo bdi_cap_account_dirty(bdi) && 27289e9b9e0STejun Heo (bdi->capabilities & BDI_CAP_CGROUP_WRITEBACK) && 27346b15caaSTejun Heo (inode->i_sb->s_iflags & SB_I_CGROUPWB); 27489e9b9e0STejun Heo } 27589e9b9e0STejun Heo 27652ebea74STejun Heo /** 27752ebea74STejun Heo * wb_find_current - find wb for %current on a bdi 27852ebea74STejun Heo * @bdi: bdi of interest 27952ebea74STejun Heo * 28052ebea74STejun Heo * Find the wb of @bdi which matches both the memcg and blkcg of %current. 28152ebea74STejun Heo * Must be called under rcu_read_lock() which protects the returend wb. 28252ebea74STejun Heo * NULL if not found. 28352ebea74STejun Heo */ 28452ebea74STejun Heo static inline struct bdi_writeback *wb_find_current(struct backing_dev_info *bdi) 28552ebea74STejun Heo { 28652ebea74STejun Heo struct cgroup_subsys_state *memcg_css; 28752ebea74STejun Heo struct bdi_writeback *wb; 28852ebea74STejun Heo 28952ebea74STejun Heo memcg_css = task_css(current, memory_cgrp_id); 29052ebea74STejun Heo if (!memcg_css->parent) 29152ebea74STejun Heo return &bdi->wb; 29252ebea74STejun Heo 29352ebea74STejun Heo wb = radix_tree_lookup(&bdi->cgwb_tree, memcg_css->id); 29452ebea74STejun Heo 29552ebea74STejun Heo /* 29652ebea74STejun Heo * %current's blkcg equals the effective blkcg of its memcg. No 29752ebea74STejun Heo * need to use the relatively expensive cgroup_get_e_css(). 29852ebea74STejun Heo */ 299c165b3e3STejun Heo if (likely(wb && wb->blkcg_css == task_css(current, io_cgrp_id))) 30052ebea74STejun Heo return wb; 30152ebea74STejun Heo return NULL; 30252ebea74STejun Heo } 30352ebea74STejun Heo 30452ebea74STejun Heo /** 30552ebea74STejun Heo * wb_get_create_current - get or create wb for %current on a bdi 30652ebea74STejun Heo * @bdi: bdi of interest 30752ebea74STejun Heo * @gfp: allocation mask 30852ebea74STejun Heo * 30952ebea74STejun Heo * Equivalent to wb_get_create() on %current's memcg. This function is 31052ebea74STejun Heo * called from a relatively hot path and optimizes the common cases using 31152ebea74STejun Heo * wb_find_current(). 31252ebea74STejun Heo */ 31352ebea74STejun Heo static inline struct bdi_writeback * 31452ebea74STejun Heo wb_get_create_current(struct backing_dev_info *bdi, gfp_t gfp) 31552ebea74STejun Heo { 31652ebea74STejun Heo struct bdi_writeback *wb; 31752ebea74STejun Heo 31852ebea74STejun Heo rcu_read_lock(); 31952ebea74STejun Heo wb = wb_find_current(bdi); 32052ebea74STejun Heo if (wb && unlikely(!wb_tryget(wb))) 32152ebea74STejun Heo wb = NULL; 32252ebea74STejun Heo rcu_read_unlock(); 32352ebea74STejun Heo 32452ebea74STejun Heo if (unlikely(!wb)) { 32552ebea74STejun Heo struct cgroup_subsys_state *memcg_css; 32652ebea74STejun Heo 32752ebea74STejun Heo memcg_css = task_get_css(current, memory_cgrp_id); 32852ebea74STejun Heo wb = wb_get_create(bdi, memcg_css, gfp); 32952ebea74STejun Heo css_put(memcg_css); 33052ebea74STejun Heo } 33152ebea74STejun Heo return wb; 33252ebea74STejun Heo } 33352ebea74STejun Heo 33452ebea74STejun Heo /** 335aaa2cacfSTejun Heo * inode_to_wb_is_valid - test whether an inode has a wb associated 336aaa2cacfSTejun Heo * @inode: inode of interest 337aaa2cacfSTejun Heo * 338aaa2cacfSTejun Heo * Returns %true if @inode has a wb associated. May be called without any 339aaa2cacfSTejun Heo * locking. 340aaa2cacfSTejun Heo */ 341aaa2cacfSTejun Heo static inline bool inode_to_wb_is_valid(struct inode *inode) 342aaa2cacfSTejun Heo { 343aaa2cacfSTejun Heo return inode->i_wb; 344aaa2cacfSTejun Heo } 345aaa2cacfSTejun Heo 346aaa2cacfSTejun Heo /** 34752ebea74STejun Heo * inode_to_wb - determine the wb of an inode 34852ebea74STejun Heo * @inode: inode of interest 34952ebea74STejun Heo * 350aaa2cacfSTejun Heo * Returns the wb @inode is currently associated with. The caller must be 351aaa2cacfSTejun Heo * holding either @inode->i_lock, @inode->i_mapping->tree_lock, or the 352aaa2cacfSTejun Heo * associated wb's list_lock. 35352ebea74STejun Heo */ 35452ebea74STejun Heo static inline struct bdi_writeback *inode_to_wb(struct inode *inode) 35552ebea74STejun Heo { 356aaa2cacfSTejun Heo #ifdef CONFIG_LOCKDEP 357aaa2cacfSTejun Heo WARN_ON_ONCE(debug_locks && 358aaa2cacfSTejun Heo (!lockdep_is_held(&inode->i_lock) && 359aaa2cacfSTejun Heo !lockdep_is_held(&inode->i_mapping->tree_lock) && 360aaa2cacfSTejun Heo !lockdep_is_held(&inode->i_wb->list_lock))); 361aaa2cacfSTejun Heo #endif 36252ebea74STejun Heo return inode->i_wb; 36352ebea74STejun Heo } 36452ebea74STejun Heo 365682aa8e1STejun Heo /** 366682aa8e1STejun Heo * unlocked_inode_to_wb_begin - begin unlocked inode wb access transaction 367682aa8e1STejun Heo * @inode: target inode 368682aa8e1STejun Heo * @lockedp: temp bool output param, to be passed to the end function 369682aa8e1STejun Heo * 370682aa8e1STejun Heo * The caller wants to access the wb associated with @inode but isn't 371682aa8e1STejun Heo * holding inode->i_lock, mapping->tree_lock or wb->list_lock. This 372682aa8e1STejun Heo * function determines the wb associated with @inode and ensures that the 373682aa8e1STejun Heo * association doesn't change until the transaction is finished with 374682aa8e1STejun Heo * unlocked_inode_to_wb_end(). 375682aa8e1STejun Heo * 376682aa8e1STejun Heo * The caller must call unlocked_inode_to_wb_end() with *@lockdep 377682aa8e1STejun Heo * afterwards and can't sleep during transaction. IRQ may or may not be 378682aa8e1STejun Heo * disabled on return. 379682aa8e1STejun Heo */ 380682aa8e1STejun Heo static inline struct bdi_writeback * 381682aa8e1STejun Heo unlocked_inode_to_wb_begin(struct inode *inode, bool *lockedp) 382682aa8e1STejun Heo { 383682aa8e1STejun Heo rcu_read_lock(); 384682aa8e1STejun Heo 385682aa8e1STejun Heo /* 386682aa8e1STejun Heo * Paired with store_release in inode_switch_wb_work_fn() and 387682aa8e1STejun Heo * ensures that we see the new wb if we see cleared I_WB_SWITCH. 388682aa8e1STejun Heo */ 389682aa8e1STejun Heo *lockedp = smp_load_acquire(&inode->i_state) & I_WB_SWITCH; 390682aa8e1STejun Heo 391682aa8e1STejun Heo if (unlikely(*lockedp)) 392682aa8e1STejun Heo spin_lock_irq(&inode->i_mapping->tree_lock); 393aaa2cacfSTejun Heo 394aaa2cacfSTejun Heo /* 395aaa2cacfSTejun Heo * Protected by either !I_WB_SWITCH + rcu_read_lock() or tree_lock. 396aaa2cacfSTejun Heo * inode_to_wb() will bark. Deref directly. 397aaa2cacfSTejun Heo */ 398aaa2cacfSTejun Heo return inode->i_wb; 399682aa8e1STejun Heo } 400682aa8e1STejun Heo 401682aa8e1STejun Heo /** 402682aa8e1STejun Heo * unlocked_inode_to_wb_end - end inode wb access transaction 403682aa8e1STejun Heo * @inode: target inode 404682aa8e1STejun Heo * @locked: *@lockedp from unlocked_inode_to_wb_begin() 405682aa8e1STejun Heo */ 406682aa8e1STejun Heo static inline void unlocked_inode_to_wb_end(struct inode *inode, bool locked) 407682aa8e1STejun Heo { 408682aa8e1STejun Heo if (unlikely(locked)) 409682aa8e1STejun Heo spin_unlock_irq(&inode->i_mapping->tree_lock); 410682aa8e1STejun Heo 411682aa8e1STejun Heo rcu_read_unlock(); 412682aa8e1STejun Heo } 413682aa8e1STejun Heo 41489e9b9e0STejun Heo #else /* CONFIG_CGROUP_WRITEBACK */ 41589e9b9e0STejun Heo 41689e9b9e0STejun Heo static inline bool inode_cgwb_enabled(struct inode *inode) 41789e9b9e0STejun Heo { 41889e9b9e0STejun Heo return false; 41989e9b9e0STejun Heo } 42089e9b9e0STejun Heo 42152ebea74STejun Heo static inline struct bdi_writeback_congested * 42252ebea74STejun Heo wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp) 42352ebea74STejun Heo { 424a13f35e8STejun Heo atomic_inc(&bdi->wb_congested->refcnt); 425a13f35e8STejun Heo return bdi->wb_congested; 42652ebea74STejun Heo } 42752ebea74STejun Heo 42852ebea74STejun Heo static inline void wb_congested_put(struct bdi_writeback_congested *congested) 42952ebea74STejun Heo { 430a13f35e8STejun Heo if (atomic_dec_and_test(&congested->refcnt)) 431a13f35e8STejun Heo kfree(congested); 43252ebea74STejun Heo } 43352ebea74STejun Heo 43452ebea74STejun Heo static inline struct bdi_writeback *wb_find_current(struct backing_dev_info *bdi) 43552ebea74STejun Heo { 43652ebea74STejun Heo return &bdi->wb; 43752ebea74STejun Heo } 43852ebea74STejun Heo 43952ebea74STejun Heo static inline struct bdi_writeback * 44052ebea74STejun Heo wb_get_create_current(struct backing_dev_info *bdi, gfp_t gfp) 44152ebea74STejun Heo { 44252ebea74STejun Heo return &bdi->wb; 44352ebea74STejun Heo } 44452ebea74STejun Heo 445aaa2cacfSTejun Heo static inline bool inode_to_wb_is_valid(struct inode *inode) 446aaa2cacfSTejun Heo { 447aaa2cacfSTejun Heo return true; 448aaa2cacfSTejun Heo } 449aaa2cacfSTejun Heo 45052ebea74STejun Heo static inline struct bdi_writeback *inode_to_wb(struct inode *inode) 45152ebea74STejun Heo { 45252ebea74STejun Heo return &inode_to_bdi(inode)->wb; 45352ebea74STejun Heo } 45452ebea74STejun Heo 455682aa8e1STejun Heo static inline struct bdi_writeback * 456682aa8e1STejun Heo unlocked_inode_to_wb_begin(struct inode *inode, bool *lockedp) 457682aa8e1STejun Heo { 458682aa8e1STejun Heo return inode_to_wb(inode); 459682aa8e1STejun Heo } 460682aa8e1STejun Heo 461682aa8e1STejun Heo static inline void unlocked_inode_to_wb_end(struct inode *inode, bool locked) 462682aa8e1STejun Heo { 463682aa8e1STejun Heo } 464682aa8e1STejun Heo 46552ebea74STejun Heo static inline void wb_memcg_offline(struct mem_cgroup *memcg) 46652ebea74STejun Heo { 46752ebea74STejun Heo } 46852ebea74STejun Heo 46952ebea74STejun Heo static inline void wb_blkcg_offline(struct blkcg *blkcg) 47052ebea74STejun Heo { 47152ebea74STejun Heo } 47252ebea74STejun Heo 473703c2708STejun Heo static inline int inode_congested(struct inode *inode, int cong_bits) 474703c2708STejun Heo { 475703c2708STejun Heo return wb_congested(&inode_to_bdi(inode)->wb, cong_bits); 476703c2708STejun Heo } 477703c2708STejun Heo 47889e9b9e0STejun Heo #endif /* CONFIG_CGROUP_WRITEBACK */ 47989e9b9e0STejun Heo 480703c2708STejun Heo static inline int inode_read_congested(struct inode *inode) 481703c2708STejun Heo { 482703c2708STejun Heo return inode_congested(inode, 1 << WB_sync_congested); 483703c2708STejun Heo } 484703c2708STejun Heo 485703c2708STejun Heo static inline int inode_write_congested(struct inode *inode) 486703c2708STejun Heo { 487703c2708STejun Heo return inode_congested(inode, 1 << WB_async_congested); 488703c2708STejun Heo } 489703c2708STejun Heo 490703c2708STejun Heo static inline int inode_rw_congested(struct inode *inode) 491703c2708STejun Heo { 492703c2708STejun Heo return inode_congested(inode, (1 << WB_sync_congested) | 493703c2708STejun Heo (1 << WB_async_congested)); 494703c2708STejun Heo } 495703c2708STejun Heo 496ec8a6f26STejun Heo static inline int bdi_congested(struct backing_dev_info *bdi, int cong_bits) 497ec8a6f26STejun Heo { 498ec8a6f26STejun Heo return wb_congested(&bdi->wb, cong_bits); 499ec8a6f26STejun Heo } 500ec8a6f26STejun Heo 501ec8a6f26STejun Heo static inline int bdi_read_congested(struct backing_dev_info *bdi) 502ec8a6f26STejun Heo { 503ec8a6f26STejun Heo return bdi_congested(bdi, 1 << WB_sync_congested); 504ec8a6f26STejun Heo } 505ec8a6f26STejun Heo 506ec8a6f26STejun Heo static inline int bdi_write_congested(struct backing_dev_info *bdi) 507ec8a6f26STejun Heo { 508ec8a6f26STejun Heo return bdi_congested(bdi, 1 << WB_async_congested); 509ec8a6f26STejun Heo } 510ec8a6f26STejun Heo 511ec8a6f26STejun Heo static inline int bdi_rw_congested(struct backing_dev_info *bdi) 512ec8a6f26STejun Heo { 513ec8a6f26STejun Heo return bdi_congested(bdi, (1 << WB_sync_congested) | 514ec8a6f26STejun Heo (1 << WB_async_congested)); 515ec8a6f26STejun Heo } 516ec8a6f26STejun Heo 5171da177e4SLinus Torvalds #endif /* _LINUX_BACKING_DEV_H */ 518