From 8c29dd356bdd6bc1ae74cd1d9b84ed7e7ac21891 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Tue, 2 Aug 2011 12:32:08 +0100 Subject: [PATCH] --- yaml --- r: 262214 b: refs/heads/master c: ed8b752bccf2560e305e25125721d2f0ac759e88 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/md/dm-table.c | 43 +++++++++++++++++++++++++++++++++++++ trunk/drivers/md/dm.c | 1 - 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 19acbcb77633..2386246e6780 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 772ae5f54d69c38a5e3c4352c5fdbdaff141af21 +refs/heads/master: ed8b752bccf2560e305e25125721d2f0ac759e88 diff --git a/trunk/drivers/md/dm-table.c b/trunk/drivers/md/dm-table.c index 259ce99302fc..986b8754bb08 100644 --- a/trunk/drivers/md/dm-table.c +++ b/trunk/drivers/md/dm-table.c @@ -1248,9 +1248,45 @@ static void dm_table_set_integrity(struct dm_table *t) blk_get_integrity(template_disk)); } +static int device_flush_capable(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) +{ + unsigned flush = (*(unsigned *)data); + struct request_queue *q = bdev_get_queue(dev->bdev); + + return q && (q->flush_flags & flush); +} + +static bool dm_table_supports_flush(struct dm_table *t, unsigned flush) +{ + struct dm_target *ti; + unsigned i = 0; + + /* + * Require at least one underlying device to support flushes. + * t->devices includes internal dm devices such as mirror logs + * so we need to use iterate_devices here, which targets + * supporting flushes must provide. + */ + while (i < dm_table_get_num_targets(t)) { + ti = dm_table_get_target(t, i++); + + if (!ti->num_flush_requests) + continue; + + if (ti->type->iterate_devices && + ti->type->iterate_devices(ti, device_flush_capable, &flush)) + return 1; + } + + return 0; +} + void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, struct queue_limits *limits) { + unsigned flush = 0; + /* * Copy table's limits to the DM device's request_queue */ @@ -1261,6 +1297,13 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, else queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); + if (dm_table_supports_flush(t, REQ_FLUSH)) { + flush |= REQ_FLUSH; + if (dm_table_supports_flush(t, REQ_FUA)) + flush |= REQ_FUA; + } + blk_queue_flush(q, flush); + dm_table_set_integrity(t); /* diff --git a/trunk/drivers/md/dm.c b/trunk/drivers/md/dm.c index 1000eaf984ef..52b39f335bb3 100644 --- a/trunk/drivers/md/dm.c +++ b/trunk/drivers/md/dm.c @@ -1808,7 +1808,6 @@ static void dm_init_md_queue(struct mapped_device *md) blk_queue_make_request(md->queue, dm_request); blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); blk_queue_merge_bvec(md->queue, dm_merge_bvec); - blk_queue_flush(md->queue, REQ_FLUSH | REQ_FUA); } /*