--- drivers/md/dm-thin.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) Index: linux-3.1-rc9/drivers/md/dm-thin.c =================================================================== --- linux-3.1-rc9.orig/drivers/md/dm-thin.c +++ linux-3.1-rc9/drivers/md/dm-thin.c @@ -490,7 +490,7 @@ struct pool { spinlock_t lock; struct bio_list deferred_bios; - struct bio_list awaiting_commit; + struct bio_list deferred_flush_bios; struct list_head prepared_mappings; struct bio_list retry_on_resume_list; @@ -618,9 +618,13 @@ static void remap_and_issue(struct thin_ remap(tc, bio, block); + /* + * Batch together any FUA/FLUSH bios we find and then issue + * a single commit for them in process_deferred_bios(). + */ if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) { spin_lock_irqsave(&pool->lock, flags); - bio_list_add(&pool->awaiting_commit, bio); + bio_list_add(&pool->deferred_flush_bios, bio); spin_unlock_irqrestore(&pool->lock, flags); } else generic_make_request(bio); @@ -1215,6 +1219,7 @@ static void process_deferred_bios(struct unsigned long flags; struct bio *bio; struct bio_list bios; + int r; bio_list_init(&bios); @@ -1240,25 +1245,30 @@ static void process_deferred_bios(struct process_bio(tc, bio); } + /* + * If there are any deferred flush bios, we must commit + * the metadata before issuing them. + */ bio_list_init(&bios); spin_lock_irqsave(&pool->lock, flags); - bio_list_merge(&bios, &pool->awaiting_commit); - bio_list_init(&pool->awaiting_commit); + bio_list_merge(&bios, &pool->deferred_flush_bios); + bio_list_init(&pool->deferred_flush_bios); spin_unlock_irqrestore(&pool->lock, flags); - if (!bio_list_empty(&bios)) { - int r = dm_pool_commit_metadata(pool->pmd); - if (r) { - DMERR("%s: dm_pool_commit_metadata() failed, error = %d", - __func__, r); - while ((bio = bio_list_pop(&bios))) - bio_io_error(bio); - return; - } + if (bio_list_empty(&bios)) + return; + r = dm_pool_commit_metadata(pool->pmd); + if (r) { + DMERR("%s: dm_pool_commit_metadata() failed, error = %d", + __func__, r); while ((bio = bio_list_pop(&bios))) - generic_make_request(bio); + bio_io_error(bio); + return; } + + while ((bio = bio_list_pop(&bios))) + generic_make_request(bio); } static void do_worker(struct work_struct *ws) @@ -1477,7 +1487,7 @@ static struct pool *pool_create(struct m INIT_WORK(&pool->worker, do_worker); spin_lock_init(&pool->lock); bio_list_init(&pool->deferred_bios); - bio_list_init(&pool->awaiting_commit); + bio_list_init(&pool->deferred_flush_bios); INIT_LIST_HEAD(&pool->prepared_mappings); pool->low_water_triggered = 0; pool->no_free_space = 0;