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-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html