From 407ee6c87e477434e3cb8be96885ed27b5539b6f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 22 Sep 2002 08:17:02 -0700 Subject: [PATCH] low-latency page reclaim Convert the VM to not wait on other people's dirty data. - If we find a dirty page and its queue is not congested, do some writeback. - If we find a dirty page and its queue _is_ congested then just refile the page. - If we find a PageWriteback page then just refile the page. - There is additional throttling for write(2) callers. Within generic_file_write(), record their backing queue in ->current. Within page reclaim, if this tasks encounters a page which is dirty or under writeback onthis queue, block on it. This gives some more writer throttling and reduces the page refiling frequency. It's somewhat CPU expensive - under really heavy load we only get a 50% reclaim rate in pages coming off the tail of the LRU. This can be fixed by splitting the inactive list into reclaimable and non-reclaimable lists. But the CPU load isn't too bad, and latency is much, much more important in these situations. Example: with `mem=512m', running 4 instances of `dbench 100', 2.5.34 took 35 minutes to compile a kernel. With this patch, it took three minutes, 45 seconds. I haven't done swapcache or MAP_SHARED pages yet. If there's tons of dirty swapcache or mmap data around we still stall heavily in page reclaim. That's less important. This patch also has a tweak for swapless machines: don't even bother bringing anon pages onto the inactive list if there is no swap online. --- include/linux/buffer_head.h | 1 - include/linux/sched.h | 2 ++ include/linux/writeback.h | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index c3535486d525..dd8f1bfb150e 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -163,7 +163,6 @@ struct buffer_head * __getblk(struct block_device *, sector_t, int); void __brelse(struct buffer_head *); void __bforget(struct buffer_head *); struct buffer_head *__bread(struct block_device *, sector_t block, int size); -void wakeup_bdflush(void); struct buffer_head *alloc_buffer_head(void); void free_buffer_head(struct buffer_head * bh); void FASTCALL(unlock_buffer(struct buffer_head *bh)); diff --git a/include/linux/sched.h b/include/linux/sched.h index 18dbb67449a4..e985f7c8fd5d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -273,6 +273,7 @@ extern struct user_struct root_user; #define INIT_USER (&root_user) typedef struct prio_array prio_array_t; +struct backing_dev_info; struct task_struct { volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ @@ -398,6 +399,7 @@ struct task_struct { /* journalling filesystem info */ void *journal_info; struct dentry *proc_dentry; + struct backing_dev_info *backing_dev_info; }; extern void __put_task_struct(struct task_struct *tsk); diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 850afbbeb70a..b71468f8f072 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -63,6 +63,8 @@ static inline void wait_on_inode(struct inode *inode) /* * mm/page-writeback.c */ +int wakeup_bdflush(long nr_pages); + /* These 5 are exported to sysctl. */ extern int dirty_background_ratio; extern int dirty_async_ratio; -- cgit v1.2.3