diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-11 12:17:05 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-11 12:17:05 -0400 |
| commit | a12e4d304ce701844c639541d90df86e165d03f9 (patch) | |
| tree | 6ad7314b63a3303d9aa36f1c7eeb68abf64d3592 /include | |
| parent | 89af571ca633ada14d17746519a179553a732d31 (diff) | |
| parent | 500b067c5e6ceea49cf280a02597b1169320e08c (diff) | |
Merge branch 'writeback' of git://git.kernel.dk/linux-2.6-block
* 'writeback' of git://git.kernel.dk/linux-2.6-block:
writeback: check for registered bdi in flusher add and inode dirty
writeback: add name to backing_dev_info
writeback: add some debug inode list counters to bdi stats
writeback: get rid of pdflush completely
writeback: switch to per-bdi threads for flushing data
writeback: move dirty inodes from super_block to backing_dev_info
writeback: get rid of generic_sync_sb_inodes() export
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/backing-dev.h | 55 | ||||
| -rw-r--r-- | include/linux/fs.h | 9 | ||||
| -rw-r--r-- | include/linux/writeback.h | 23 |
3 files changed, 64 insertions, 23 deletions
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 1d52425a6118..f169bcb90b58 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h | |||
| @@ -13,6 +13,8 @@ | |||
| 13 | #include <linux/proportions.h> | 13 | #include <linux/proportions.h> |
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/fs.h> | 15 | #include <linux/fs.h> |
| 16 | #include <linux/sched.h> | ||
| 17 | #include <linux/writeback.h> | ||
| 16 | #include <asm/atomic.h> | 18 | #include <asm/atomic.h> |
| 17 | 19 | ||
| 18 | struct page; | 20 | struct page; |
| @@ -23,9 +25,11 @@ struct dentry; | |||
| 23 | * Bits in backing_dev_info.state | 25 | * Bits in backing_dev_info.state |
| 24 | */ | 26 | */ |
| 25 | enum bdi_state { | 27 | enum bdi_state { |
| 26 | BDI_pdflush, /* A pdflush thread is working this device */ | 28 | BDI_pending, /* On its way to being activated */ |
| 29 | BDI_wb_alloc, /* Default embedded wb allocated */ | ||
| 27 | BDI_async_congested, /* The async (write) queue is getting full */ | 30 | BDI_async_congested, /* The async (write) queue is getting full */ |
| 28 | BDI_sync_congested, /* The sync queue is getting full */ | 31 | BDI_sync_congested, /* The sync queue is getting full */ |
| 32 | BDI_registered, /* bdi_register() was done */ | ||
| 29 | BDI_unused, /* Available bits start here */ | 33 | BDI_unused, /* Available bits start here */ |
| 30 | }; | 34 | }; |
| 31 | 35 | ||
| @@ -39,7 +43,22 @@ enum bdi_stat_item { | |||
| 39 | 43 | ||
| 40 | #define BDI_STAT_BATCH (8*(1+ilog2(nr_cpu_ids))) | 44 | #define BDI_STAT_BATCH (8*(1+ilog2(nr_cpu_ids))) |
| 41 | 45 | ||
| 46 | struct bdi_writeback { | ||
| 47 | struct list_head list; /* hangs off the bdi */ | ||
| 48 | |||
| 49 | struct backing_dev_info *bdi; /* our parent bdi */ | ||
| 50 | unsigned int nr; | ||
| 51 | |||
| 52 | unsigned long last_old_flush; /* last old data flush */ | ||
| 53 | |||
| 54 | struct task_struct *task; /* writeback task */ | ||
| 55 | struct list_head b_dirty; /* dirty inodes */ | ||
| 56 | struct list_head b_io; /* parked for writeback */ | ||
| 57 | struct list_head b_more_io; /* parked for more writeback */ | ||
| 58 | }; | ||
| 59 | |||
| 42 | struct backing_dev_info { | 60 | struct backing_dev_info { |
| 61 | struct list_head bdi_list; | ||
| 43 | unsigned long ra_pages; /* max readahead in PAGE_CACHE_SIZE units */ | 62 | unsigned long ra_pages; /* max readahead in PAGE_CACHE_SIZE units */ |
| 44 | unsigned long state; /* Always use atomic bitops on this */ | 63 | unsigned long state; /* Always use atomic bitops on this */ |
| 45 | unsigned int capabilities; /* Device capabilities */ | 64 | unsigned int capabilities; /* Device capabilities */ |
| @@ -48,6 +67,8 @@ struct backing_dev_info { | |||
| 48 | void (*unplug_io_fn)(struct backing_dev_info *, struct page *); | 67 | void (*unplug_io_fn)(struct backing_dev_info *, struct page *); |
| 49 | void *unplug_io_data; | 68 | void *unplug_io_data; |
| 50 | 69 | ||
| 70 | char *name; | ||
| 71 | |||
| 51 | struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS]; | 72 | struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS]; |
| 52 | 73 | ||
| 53 | struct prop_local_percpu completions; | 74 | struct prop_local_percpu completions; |
| @@ -56,6 +77,14 @@ struct backing_dev_info { | |||
| 56 | unsigned int min_ratio; | 77 | unsigned int min_ratio; |
| 57 | unsigned int max_ratio, max_prop_frac; | 78 | unsigned int max_ratio, max_prop_frac; |
| 58 | 79 | ||
| 80 | struct bdi_writeback wb; /* default writeback info for this bdi */ | ||
| 81 | spinlock_t wb_lock; /* protects update side of wb_list */ | ||
| 82 | struct list_head wb_list; /* the flusher threads hanging off this bdi */ | ||
| 83 | unsigned long wb_mask; /* bitmask of registered tasks */ | ||
| 84 | unsigned int wb_cnt; /* number of registered tasks */ | ||
| 85 | |||
| 86 | struct list_head work_list; | ||
| 87 | |||
| 59 | struct device *dev; | 88 | struct device *dev; |
| 60 | 89 | ||
| 61 | #ifdef CONFIG_DEBUG_FS | 90 | #ifdef CONFIG_DEBUG_FS |
| @@ -71,6 +100,19 @@ int bdi_register(struct backing_dev_info *bdi, struct device *parent, | |||
| 71 | const char *fmt, ...); | 100 | const char *fmt, ...); |
| 72 | int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev); | 101 | int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev); |
| 73 | void bdi_unregister(struct backing_dev_info *bdi); | 102 | void bdi_unregister(struct backing_dev_info *bdi); |
| 103 | void bdi_start_writeback(struct writeback_control *wbc); | ||
| 104 | int bdi_writeback_task(struct bdi_writeback *wb); | ||
| 105 | int bdi_has_dirty_io(struct backing_dev_info *bdi); | ||
| 106 | |||
| 107 | extern spinlock_t bdi_lock; | ||
| 108 | extern struct list_head bdi_list; | ||
| 109 | |||
| 110 | static inline int wb_has_dirty_io(struct bdi_writeback *wb) | ||
| 111 | { | ||
| 112 | return !list_empty(&wb->b_dirty) || | ||
| 113 | !list_empty(&wb->b_io) || | ||
| 114 | !list_empty(&wb->b_more_io); | ||
| 115 | } | ||
| 74 | 116 | ||
| 75 | static inline void __add_bdi_stat(struct backing_dev_info *bdi, | 117 | static inline void __add_bdi_stat(struct backing_dev_info *bdi, |
| 76 | enum bdi_stat_item item, s64 amount) | 118 | enum bdi_stat_item item, s64 amount) |
| @@ -261,6 +303,11 @@ static inline bool bdi_cap_swap_backed(struct backing_dev_info *bdi) | |||
| 261 | return bdi->capabilities & BDI_CAP_SWAP_BACKED; | 303 | return bdi->capabilities & BDI_CAP_SWAP_BACKED; |
| 262 | } | 304 | } |
| 263 | 305 | ||
| 306 | static inline bool bdi_cap_flush_forker(struct backing_dev_info *bdi) | ||
| 307 | { | ||
| 308 | return bdi == &default_backing_dev_info; | ||
| 309 | } | ||
| 310 | |||
| 264 | static inline bool mapping_cap_writeback_dirty(struct address_space *mapping) | 311 | static inline bool mapping_cap_writeback_dirty(struct address_space *mapping) |
| 265 | { | 312 | { |
| 266 | return bdi_cap_writeback_dirty(mapping->backing_dev_info); | 313 | return bdi_cap_writeback_dirty(mapping->backing_dev_info); |
| @@ -276,4 +323,10 @@ static inline bool mapping_cap_swap_backed(struct address_space *mapping) | |||
| 276 | return bdi_cap_swap_backed(mapping->backing_dev_info); | 323 | return bdi_cap_swap_backed(mapping->backing_dev_info); |
| 277 | } | 324 | } |
| 278 | 325 | ||
| 326 | static inline int bdi_sched_wait(void *word) | ||
| 327 | { | ||
| 328 | schedule(); | ||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | |||
| 279 | #endif /* _LINUX_BACKING_DEV_H */ | 332 | #endif /* _LINUX_BACKING_DEV_H */ |
diff --git a/include/linux/fs.h b/include/linux/fs.h index c1f993515f51..26da98f61116 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -715,7 +715,7 @@ struct posix_acl; | |||
| 715 | 715 | ||
| 716 | struct inode { | 716 | struct inode { |
| 717 | struct hlist_node i_hash; | 717 | struct hlist_node i_hash; |
| 718 | struct list_head i_list; | 718 | struct list_head i_list; /* backing dev IO list */ |
| 719 | struct list_head i_sb_list; | 719 | struct list_head i_sb_list; |
| 720 | struct list_head i_dentry; | 720 | struct list_head i_dentry; |
| 721 | unsigned long i_ino; | 721 | unsigned long i_ino; |
| @@ -1336,9 +1336,6 @@ struct super_block { | |||
| 1336 | struct xattr_handler **s_xattr; | 1336 | struct xattr_handler **s_xattr; |
| 1337 | 1337 | ||
| 1338 | struct list_head s_inodes; /* all inodes */ | 1338 | struct list_head s_inodes; /* all inodes */ |
| 1339 | struct list_head s_dirty; /* dirty inodes */ | ||
| 1340 | struct list_head s_io; /* parked for writeback */ | ||
| 1341 | struct list_head s_more_io; /* parked for more writeback */ | ||
| 1342 | struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */ | 1339 | struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */ |
| 1343 | struct list_head s_files; | 1340 | struct list_head s_files; |
| 1344 | /* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */ | 1341 | /* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */ |
| @@ -1789,6 +1786,7 @@ extern int get_sb_pseudo(struct file_system_type *, char *, | |||
| 1789 | struct vfsmount *mnt); | 1786 | struct vfsmount *mnt); |
| 1790 | extern void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb); | 1787 | extern void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb); |
| 1791 | int __put_super_and_need_restart(struct super_block *sb); | 1788 | int __put_super_and_need_restart(struct super_block *sb); |
| 1789 | void put_super(struct super_block *sb); | ||
| 1792 | 1790 | ||
| 1793 | /* Alas, no aliases. Too much hassle with bringing module.h everywhere */ | 1791 | /* Alas, no aliases. Too much hassle with bringing module.h everywhere */ |
| 1794 | #define fops_get(fops) \ | 1792 | #define fops_get(fops) \ |
| @@ -2071,8 +2069,6 @@ static inline void invalidate_remote_inode(struct inode *inode) | |||
| 2071 | extern int invalidate_inode_pages2(struct address_space *mapping); | 2069 | extern int invalidate_inode_pages2(struct address_space *mapping); |
| 2072 | extern int invalidate_inode_pages2_range(struct address_space *mapping, | 2070 | extern int invalidate_inode_pages2_range(struct address_space *mapping, |
| 2073 | pgoff_t start, pgoff_t end); | 2071 | pgoff_t start, pgoff_t end); |
| 2074 | extern void generic_sync_sb_inodes(struct super_block *sb, | ||
| 2075 | struct writeback_control *wbc); | ||
| 2076 | extern int write_inode_now(struct inode *, int); | 2072 | extern int write_inode_now(struct inode *, int); |
| 2077 | extern int filemap_fdatawrite(struct address_space *); | 2073 | extern int filemap_fdatawrite(struct address_space *); |
| 2078 | extern int filemap_flush(struct address_space *); | 2074 | extern int filemap_flush(struct address_space *); |
| @@ -2187,7 +2183,6 @@ extern int bdev_read_only(struct block_device *); | |||
| 2187 | extern int set_blocksize(struct block_device *, int); | 2183 | extern int set_blocksize(struct block_device *, int); |
| 2188 | extern int sb_set_blocksize(struct super_block *, int); | 2184 | extern int sb_set_blocksize(struct super_block *, int); |
| 2189 | extern int sb_min_blocksize(struct super_block *, int); | 2185 | extern int sb_min_blocksize(struct super_block *, int); |
| 2190 | extern int sb_has_dirty_inodes(struct super_block *); | ||
| 2191 | 2186 | ||
| 2192 | extern int generic_file_mmap(struct file *, struct vm_area_struct *); | 2187 | extern int generic_file_mmap(struct file *, struct vm_area_struct *); |
| 2193 | extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); | 2188 | extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 3224820c8514..78b1e4684cc9 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
| @@ -14,17 +14,6 @@ extern struct list_head inode_in_use; | |||
| 14 | extern struct list_head inode_unused; | 14 | extern struct list_head inode_unused; |
| 15 | 15 | ||
| 16 | /* | 16 | /* |
| 17 | * Yes, writeback.h requires sched.h | ||
| 18 | * No, sched.h is not included from here. | ||
| 19 | */ | ||
| 20 | static inline int task_is_pdflush(struct task_struct *task) | ||
| 21 | { | ||
| 22 | return task->flags & PF_FLUSHER; | ||
| 23 | } | ||
| 24 | |||
| 25 | #define current_is_pdflush() task_is_pdflush(current) | ||
| 26 | |||
| 27 | /* | ||
| 28 | * fs/fs-writeback.c | 17 | * fs/fs-writeback.c |
| 29 | */ | 18 | */ |
| 30 | enum writeback_sync_modes { | 19 | enum writeback_sync_modes { |
| @@ -40,6 +29,8 @@ enum writeback_sync_modes { | |||
| 40 | struct writeback_control { | 29 | struct writeback_control { |
| 41 | struct backing_dev_info *bdi; /* If !NULL, only write back this | 30 | struct backing_dev_info *bdi; /* If !NULL, only write back this |
| 42 | queue */ | 31 | queue */ |
| 32 | struct super_block *sb; /* if !NULL, only write inodes from | ||
| 33 | this super_block */ | ||
| 43 | enum writeback_sync_modes sync_mode; | 34 | enum writeback_sync_modes sync_mode; |
| 44 | unsigned long *older_than_this; /* If !NULL, only write back inodes | 35 | unsigned long *older_than_this; /* If !NULL, only write back inodes |
| 45 | older than this */ | 36 | older than this */ |
| @@ -76,9 +67,13 @@ struct writeback_control { | |||
| 76 | /* | 67 | /* |
| 77 | * fs/fs-writeback.c | 68 | * fs/fs-writeback.c |
| 78 | */ | 69 | */ |
| 79 | void writeback_inodes(struct writeback_control *wbc); | 70 | struct bdi_writeback; |
| 80 | int inode_wait(void *); | 71 | int inode_wait(void *); |
| 81 | void sync_inodes_sb(struct super_block *, int wait); | 72 | long writeback_inodes_sb(struct super_block *); |
| 73 | long sync_inodes_sb(struct super_block *); | ||
| 74 | void writeback_inodes_wbc(struct writeback_control *wbc); | ||
| 75 | long wb_do_writeback(struct bdi_writeback *wb, int force_wait); | ||
| 76 | void wakeup_flusher_threads(long nr_pages); | ||
| 82 | 77 | ||
| 83 | /* writeback.h requires fs.h; it, too, is not included from here. */ | 78 | /* writeback.h requires fs.h; it, too, is not included from here. */ |
| 84 | static inline void wait_on_inode(struct inode *inode) | 79 | static inline void wait_on_inode(struct inode *inode) |
| @@ -98,7 +93,6 @@ static inline void inode_sync_wait(struct inode *inode) | |||
| 98 | /* | 93 | /* |
| 99 | * mm/page-writeback.c | 94 | * mm/page-writeback.c |
| 100 | */ | 95 | */ |
| 101 | int wakeup_pdflush(long nr_pages); | ||
| 102 | void laptop_io_completion(void); | 96 | void laptop_io_completion(void); |
| 103 | void laptop_sync_completion(void); | 97 | void laptop_sync_completion(void); |
| 104 | void throttle_vm_writeout(gfp_t gfp_mask); | 98 | void throttle_vm_writeout(gfp_t gfp_mask); |
| @@ -150,7 +144,6 @@ balance_dirty_pages_ratelimited(struct address_space *mapping) | |||
| 150 | typedef int (*writepage_t)(struct page *page, struct writeback_control *wbc, | 144 | typedef int (*writepage_t)(struct page *page, struct writeback_control *wbc, |
| 151 | void *data); | 145 | void *data); |
| 152 | 146 | ||
| 153 | int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0); | ||
| 154 | int generic_writepages(struct address_space *mapping, | 147 | int generic_writepages(struct address_space *mapping, |
| 155 | struct writeback_control *wbc); | 148 | struct writeback_control *wbc); |
| 156 | int write_cache_pages(struct address_space *mapping, | 149 | int write_cache_pages(struct address_space *mapping, |
