[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 <michaelc@cs.wisc.edu> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
0fe2347957
commit
059af497c2
1 changed files with 9 additions and 4 deletions
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue