[PATCH 34/45] writeback: sync livelock - kick background writeback

From: Wu Fengguang
Date: Wed Oct 07 2009 - 04:05:57 EST


The periodic/background writeback can run forever. So when any
sync work is enqueued, increase bdi->sync_works to notify the
active non-sync works to exit. Non-sync works queued after all sync
works won't be affected.

Signed-off-by: Wu Fengguang <fengguang.wu@xxxxxxxxx>
---
fs/fs-writeback.c | 11 +++++++++++
include/linux/backing-dev.h | 5 +++++
mm/backing-dev.c | 1 +
3 files changed, 17 insertions(+)

--- linux.orig/fs/fs-writeback.c 2009-10-06 23:39:33.000000000 +0800
+++ linux/fs/fs-writeback.c 2009-10-06 23:39:33.000000000 +0800
@@ -139,6 +139,8 @@ static void wb_clear_pending(struct bdi_
list_del_rcu(&work->list);
if (work->args.for_background)
clear_bit(WB_FLAG_BACKGROUND_WORK, &bdi->wb_mask);
+ if (work->args.for_sync)
+ bdi->sync_works--;
spin_unlock(&bdi->wb_lock);

wb_work_complete(work);
@@ -159,6 +161,8 @@ static void bdi_queue_work(struct backin
*/
spin_lock(&bdi->wb_lock);
list_add_tail_rcu(&work->list, &bdi->work_list);
+ if (work->args.for_sync)
+ bdi->sync_works++;
spin_unlock(&bdi->wb_lock);

/*
@@ -811,6 +815,13 @@ static long wb_writeback(struct bdi_writ
break;

/*
+ * background/periodic works can run forever, need to abort
+ * on seeing any pending sync work, to prevent livelock it.
+ */
+ if (!args->for_sync && wb->bdi->sync_works > 0)
+ break;
+
+ /*
* For background writeout, stop when we are below the
* background dirty threshold
*/
--- linux.orig/include/linux/backing-dev.h 2009-10-06 23:39:33.000000000 +0800
+++ linux/include/linux/backing-dev.h 2009-10-06 23:39:33.000000000 +0800
@@ -84,6 +84,11 @@ struct backing_dev_info {
struct list_head wb_list; /* the flusher threads hanging off this bdi */
unsigned long wb_mask; /* bitmask of registered tasks */
unsigned int wb_cnt; /* number of registered tasks */
+ /*
+ * sync works queued, background works shall abort on seeing this,
+ * to prevent livelocking the sync works
+ */
+ unsigned int sync_works;

struct list_head work_list;

--- linux.orig/mm/backing-dev.c 2009-10-06 23:38:52.000000000 +0800
+++ linux/mm/backing-dev.c 2009-10-06 23:39:33.000000000 +0800
@@ -647,6 +647,7 @@ int bdi_init(struct backing_dev_info *bd
*/
bdi->wb_mask = 1;
bdi->wb_cnt = 1;
+ bdi->sync_works = 0;

bdi->write_bandwidth = MAX_WRITEBACK_PAGES;



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/