forked from Minki/linux
c4dc4beed2
These patches aim to improve balance_dirty_pages() and directly address three issues: 1) inter device starvation 2) stacked device deadlocks 3) inter process starvation 1 and 2 are a direct result from removing the global dirty limit and using per device dirty limits. By giving each device its own dirty limit is will no longer starve another device, and the cyclic dependancy on the dirty limit is broken. In order to efficiently distribute the dirty limit across the independant devices a floating proportion is used, this will allocate a share of the total limit proportional to the device's recent activity. 3 is done by also scaling the dirty limit proportional to the current task's recent dirty rate. This patch: nfs: remove congestion_end(). It's redundant, clear_bdi_congested() already wakes the waiters. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Trond Myklebust <trond.myklebust@fys.uio.no> Cc: "J. Bruce Fields" <bfields@fieldses.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
57 lines
1.4 KiB
C
57 lines
1.4 KiB
C
|
|
#include <linux/wait.h>
|
|
#include <linux/backing-dev.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/module.h>
|
|
|
|
static wait_queue_head_t congestion_wqh[2] = {
|
|
__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]),
|
|
__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1])
|
|
};
|
|
|
|
|
|
void clear_bdi_congested(struct backing_dev_info *bdi, int rw)
|
|
{
|
|
enum bdi_state bit;
|
|
wait_queue_head_t *wqh = &congestion_wqh[rw];
|
|
|
|
bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested;
|
|
clear_bit(bit, &bdi->state);
|
|
smp_mb__after_clear_bit();
|
|
if (waitqueue_active(wqh))
|
|
wake_up(wqh);
|
|
}
|
|
EXPORT_SYMBOL(clear_bdi_congested);
|
|
|
|
void set_bdi_congested(struct backing_dev_info *bdi, int rw)
|
|
{
|
|
enum bdi_state bit;
|
|
|
|
bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested;
|
|
set_bit(bit, &bdi->state);
|
|
}
|
|
EXPORT_SYMBOL(set_bdi_congested);
|
|
|
|
/**
|
|
* congestion_wait - wait for a backing_dev to become uncongested
|
|
* @rw: READ or WRITE
|
|
* @timeout: timeout in jiffies
|
|
*
|
|
* Waits for up to @timeout jiffies for a backing_dev (any backing_dev) to exit
|
|
* write congestion. If no backing_devs are congested then just wait for the
|
|
* next write to be completed.
|
|
*/
|
|
long congestion_wait(int rw, long timeout)
|
|
{
|
|
long ret;
|
|
DEFINE_WAIT(wait);
|
|
wait_queue_head_t *wqh = &congestion_wqh[rw];
|
|
|
|
prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
|
|
ret = io_schedule_timeout(timeout);
|
|
finish_wait(wqh, &wait);
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(congestion_wait);
|