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 11*b2e8fb6eSPeter Zijlstra #include <linux/percpu_counter.h> 12*b2e8fb6eSPeter Zijlstra #include <linux/log2.h> 131da177e4SLinus Torvalds #include <asm/atomic.h> 141da177e4SLinus Torvalds 153fcfab16SAndrew Morton struct page; 163fcfab16SAndrew Morton 171da177e4SLinus Torvalds /* 181da177e4SLinus Torvalds * Bits in backing_dev_info.state 191da177e4SLinus Torvalds */ 201da177e4SLinus Torvalds enum bdi_state { 211da177e4SLinus Torvalds BDI_pdflush, /* A pdflush thread is working this device */ 221da177e4SLinus Torvalds BDI_write_congested, /* The write queue is getting full */ 231da177e4SLinus Torvalds BDI_read_congested, /* The read queue is getting full */ 241da177e4SLinus Torvalds BDI_unused, /* Available bits start here */ 251da177e4SLinus Torvalds }; 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds typedef int (congested_fn)(void *, int); 281da177e4SLinus Torvalds 29*b2e8fb6eSPeter Zijlstra enum bdi_stat_item { 30*b2e8fb6eSPeter Zijlstra NR_BDI_STAT_ITEMS 31*b2e8fb6eSPeter Zijlstra }; 32*b2e8fb6eSPeter Zijlstra 33*b2e8fb6eSPeter Zijlstra #define BDI_STAT_BATCH (8*(1+ilog2(nr_cpu_ids))) 34*b2e8fb6eSPeter Zijlstra 351da177e4SLinus Torvalds struct backing_dev_info { 361da177e4SLinus Torvalds unsigned long ra_pages; /* max readahead in PAGE_CACHE_SIZE units */ 371da177e4SLinus Torvalds unsigned long state; /* Always use atomic bitops on this */ 381da177e4SLinus Torvalds unsigned int capabilities; /* Device capabilities */ 391da177e4SLinus Torvalds congested_fn *congested_fn; /* Function pointer if device is md/dm */ 401da177e4SLinus Torvalds void *congested_data; /* Pointer to aux data for congested func */ 411da177e4SLinus Torvalds void (*unplug_io_fn)(struct backing_dev_info *, struct page *); 421da177e4SLinus Torvalds void *unplug_io_data; 43*b2e8fb6eSPeter Zijlstra 44*b2e8fb6eSPeter Zijlstra struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS]; 451da177e4SLinus Torvalds }; 461da177e4SLinus Torvalds 47*b2e8fb6eSPeter Zijlstra int bdi_init(struct backing_dev_info *bdi); 48*b2e8fb6eSPeter Zijlstra void bdi_destroy(struct backing_dev_info *bdi); 49*b2e8fb6eSPeter Zijlstra 50*b2e8fb6eSPeter Zijlstra static inline void __add_bdi_stat(struct backing_dev_info *bdi, 51*b2e8fb6eSPeter Zijlstra enum bdi_stat_item item, s64 amount) 52e0bf68ddSPeter Zijlstra { 53*b2e8fb6eSPeter Zijlstra __percpu_counter_add(&bdi->bdi_stat[item], amount, BDI_STAT_BATCH); 54e0bf68ddSPeter Zijlstra } 55e0bf68ddSPeter Zijlstra 56*b2e8fb6eSPeter Zijlstra static inline void __inc_bdi_stat(struct backing_dev_info *bdi, 57*b2e8fb6eSPeter Zijlstra enum bdi_stat_item item) 58e0bf68ddSPeter Zijlstra { 59*b2e8fb6eSPeter Zijlstra __add_bdi_stat(bdi, item, 1); 60*b2e8fb6eSPeter Zijlstra } 61*b2e8fb6eSPeter Zijlstra 62*b2e8fb6eSPeter Zijlstra static inline void inc_bdi_stat(struct backing_dev_info *bdi, 63*b2e8fb6eSPeter Zijlstra enum bdi_stat_item item) 64*b2e8fb6eSPeter Zijlstra { 65*b2e8fb6eSPeter Zijlstra unsigned long flags; 66*b2e8fb6eSPeter Zijlstra 67*b2e8fb6eSPeter Zijlstra local_irq_save(flags); 68*b2e8fb6eSPeter Zijlstra __inc_bdi_stat(bdi, item); 69*b2e8fb6eSPeter Zijlstra local_irq_restore(flags); 70*b2e8fb6eSPeter Zijlstra } 71*b2e8fb6eSPeter Zijlstra 72*b2e8fb6eSPeter Zijlstra static inline void __dec_bdi_stat(struct backing_dev_info *bdi, 73*b2e8fb6eSPeter Zijlstra enum bdi_stat_item item) 74*b2e8fb6eSPeter Zijlstra { 75*b2e8fb6eSPeter Zijlstra __add_bdi_stat(bdi, item, -1); 76*b2e8fb6eSPeter Zijlstra } 77*b2e8fb6eSPeter Zijlstra 78*b2e8fb6eSPeter Zijlstra static inline void dec_bdi_stat(struct backing_dev_info *bdi, 79*b2e8fb6eSPeter Zijlstra enum bdi_stat_item item) 80*b2e8fb6eSPeter Zijlstra { 81*b2e8fb6eSPeter Zijlstra unsigned long flags; 82*b2e8fb6eSPeter Zijlstra 83*b2e8fb6eSPeter Zijlstra local_irq_save(flags); 84*b2e8fb6eSPeter Zijlstra __dec_bdi_stat(bdi, item); 85*b2e8fb6eSPeter Zijlstra local_irq_restore(flags); 86*b2e8fb6eSPeter Zijlstra } 87*b2e8fb6eSPeter Zijlstra 88*b2e8fb6eSPeter Zijlstra static inline s64 bdi_stat(struct backing_dev_info *bdi, 89*b2e8fb6eSPeter Zijlstra enum bdi_stat_item item) 90*b2e8fb6eSPeter Zijlstra { 91*b2e8fb6eSPeter Zijlstra return percpu_counter_read_positive(&bdi->bdi_stat[item]); 92*b2e8fb6eSPeter Zijlstra } 93*b2e8fb6eSPeter Zijlstra 94*b2e8fb6eSPeter Zijlstra static inline s64 __bdi_stat_sum(struct backing_dev_info *bdi, 95*b2e8fb6eSPeter Zijlstra enum bdi_stat_item item) 96*b2e8fb6eSPeter Zijlstra { 97*b2e8fb6eSPeter Zijlstra return percpu_counter_sum_positive(&bdi->bdi_stat[item]); 98*b2e8fb6eSPeter Zijlstra } 99*b2e8fb6eSPeter Zijlstra 100*b2e8fb6eSPeter Zijlstra static inline s64 bdi_stat_sum(struct backing_dev_info *bdi, 101*b2e8fb6eSPeter Zijlstra enum bdi_stat_item item) 102*b2e8fb6eSPeter Zijlstra { 103*b2e8fb6eSPeter Zijlstra s64 sum; 104*b2e8fb6eSPeter Zijlstra unsigned long flags; 105*b2e8fb6eSPeter Zijlstra 106*b2e8fb6eSPeter Zijlstra local_irq_save(flags); 107*b2e8fb6eSPeter Zijlstra sum = __bdi_stat_sum(bdi, item); 108*b2e8fb6eSPeter Zijlstra local_irq_restore(flags); 109*b2e8fb6eSPeter Zijlstra 110*b2e8fb6eSPeter Zijlstra return sum; 111*b2e8fb6eSPeter Zijlstra } 112*b2e8fb6eSPeter Zijlstra 113*b2e8fb6eSPeter Zijlstra /* 114*b2e8fb6eSPeter Zijlstra * maximal error of a stat counter. 115*b2e8fb6eSPeter Zijlstra */ 116*b2e8fb6eSPeter Zijlstra static inline unsigned long bdi_stat_error(struct backing_dev_info *bdi) 117*b2e8fb6eSPeter Zijlstra { 118*b2e8fb6eSPeter Zijlstra #ifdef CONFIG_SMP 119*b2e8fb6eSPeter Zijlstra return nr_cpu_ids * BDI_STAT_BATCH; 120*b2e8fb6eSPeter Zijlstra #else 121*b2e8fb6eSPeter Zijlstra return 1; 122*b2e8fb6eSPeter Zijlstra #endif 123e0bf68ddSPeter Zijlstra } 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds /* 1261da177e4SLinus Torvalds * Flags in backing_dev_info::capability 1271da177e4SLinus Torvalds * - The first two flags control whether dirty pages will contribute to the 1281da177e4SLinus Torvalds * VM's accounting and whether writepages() should be called for dirty pages 1291da177e4SLinus Torvalds * (something that would not, for example, be appropriate for ramfs) 1301da177e4SLinus Torvalds * - These flags let !MMU mmap() govern direct device mapping vs immediate 1311da177e4SLinus Torvalds * copying more easily for MAP_PRIVATE, especially for ROM filesystems 1321da177e4SLinus Torvalds */ 1331da177e4SLinus Torvalds #define BDI_CAP_NO_ACCT_DIRTY 0x00000001 /* Dirty pages shouldn't contribute to accounting */ 1341da177e4SLinus Torvalds #define BDI_CAP_NO_WRITEBACK 0x00000002 /* Don't write pages back */ 1351da177e4SLinus Torvalds #define BDI_CAP_MAP_COPY 0x00000004 /* Copy can be mapped (MAP_PRIVATE) */ 1361da177e4SLinus Torvalds #define BDI_CAP_MAP_DIRECT 0x00000008 /* Can be mapped directly (MAP_SHARED) */ 1371da177e4SLinus Torvalds #define BDI_CAP_READ_MAP 0x00000010 /* Can be mapped for reading */ 1381da177e4SLinus Torvalds #define BDI_CAP_WRITE_MAP 0x00000020 /* Can be mapped for writing */ 1391da177e4SLinus Torvalds #define BDI_CAP_EXEC_MAP 0x00000040 /* Can be mapped for execution */ 1401da177e4SLinus Torvalds #define BDI_CAP_VMFLAGS \ 1411da177e4SLinus Torvalds (BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP) 1421da177e4SLinus Torvalds 1431da177e4SLinus Torvalds #if defined(VM_MAYREAD) && \ 1441da177e4SLinus Torvalds (BDI_CAP_READ_MAP != VM_MAYREAD || \ 1451da177e4SLinus Torvalds BDI_CAP_WRITE_MAP != VM_MAYWRITE || \ 1461da177e4SLinus Torvalds BDI_CAP_EXEC_MAP != VM_MAYEXEC) 1471da177e4SLinus Torvalds #error please change backing_dev_info::capabilities flags 1481da177e4SLinus Torvalds #endif 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds extern struct backing_dev_info default_backing_dev_info; 1511da177e4SLinus Torvalds void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page); 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds int writeback_acquire(struct backing_dev_info *bdi); 1541da177e4SLinus Torvalds int writeback_in_progress(struct backing_dev_info *bdi); 1551da177e4SLinus Torvalds void writeback_release(struct backing_dev_info *bdi); 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds static inline int bdi_congested(struct backing_dev_info *bdi, int bdi_bits) 1581da177e4SLinus Torvalds { 1591da177e4SLinus Torvalds if (bdi->congested_fn) 1601da177e4SLinus Torvalds return bdi->congested_fn(bdi->congested_data, bdi_bits); 1611da177e4SLinus Torvalds return (bdi->state & bdi_bits); 1621da177e4SLinus Torvalds } 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds static inline int bdi_read_congested(struct backing_dev_info *bdi) 1651da177e4SLinus Torvalds { 1661da177e4SLinus Torvalds return bdi_congested(bdi, 1 << BDI_read_congested); 1671da177e4SLinus Torvalds } 1681da177e4SLinus Torvalds 1691da177e4SLinus Torvalds static inline int bdi_write_congested(struct backing_dev_info *bdi) 1701da177e4SLinus Torvalds { 1711da177e4SLinus Torvalds return bdi_congested(bdi, 1 << BDI_write_congested); 1721da177e4SLinus Torvalds } 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds static inline int bdi_rw_congested(struct backing_dev_info *bdi) 1751da177e4SLinus Torvalds { 1761da177e4SLinus Torvalds return bdi_congested(bdi, (1 << BDI_read_congested)| 1771da177e4SLinus Torvalds (1 << BDI_write_congested)); 1781da177e4SLinus Torvalds } 1791da177e4SLinus Torvalds 1803fcfab16SAndrew Morton void clear_bdi_congested(struct backing_dev_info *bdi, int rw); 1813fcfab16SAndrew Morton void set_bdi_congested(struct backing_dev_info *bdi, int rw); 1823fcfab16SAndrew Morton long congestion_wait(int rw, long timeout); 1833fcfab16SAndrew Morton 1841da177e4SLinus Torvalds #define bdi_cap_writeback_dirty(bdi) \ 1851da177e4SLinus Torvalds (!((bdi)->capabilities & BDI_CAP_NO_WRITEBACK)) 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds #define bdi_cap_account_dirty(bdi) \ 1881da177e4SLinus Torvalds (!((bdi)->capabilities & BDI_CAP_NO_ACCT_DIRTY)) 1891da177e4SLinus Torvalds 1901da177e4SLinus Torvalds #define mapping_cap_writeback_dirty(mapping) \ 1911da177e4SLinus Torvalds bdi_cap_writeback_dirty((mapping)->backing_dev_info) 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds #define mapping_cap_account_dirty(mapping) \ 1941da177e4SLinus Torvalds bdi_cap_account_dirty((mapping)->backing_dev_info) 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds #endif /* _LINUX_BACKING_DEV_H */ 198