From: Jens Axboe Date: Thu, 21 Sep 2006 18:37:22 +0000 (+0200) Subject: [PATCH] blk_queue_start_tag() shared map race fix X-Git-Tag: v2.6.19-rc1~640^2 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=059af497c23492cb1ddcbba11c09dad385960bc0;p=linux-2.6 [PATCH] blk_queue_start_tag() shared map race fix If we share the tag map between two or more queues, then we cannot use __set_bit() to set the bit. In fact we need to make sure we atomically acquire this tag, so loop using test_and_set_bit() to protect from that. Noticed by Mike Christie Signed-off-by: Jens Axboe --- diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index f757ed4132..83425fb3c8 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1171,11 +1171,16 @@ int blk_queue_start_tag(request_queue_t *q, struct request *rq) BUG(); } - tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth); - if (tag >= bqt->max_depth) - return 1; + /* + * Protect against shared tag maps, as we may not have exclusive + * access to the tag map. + */ + do { + tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth); + if (tag >= bqt->max_depth) + return 1; - __set_bit(tag, bqt->tag_map); + } while (test_and_set_bit(tag, bqt->tag_map)); rq->cmd_flags |= REQ_QUEUED; rq->tag = tag;