diff options
author | Robert Elliott <elliott@hp.com> | 2014-09-02 18:38:44 +0200 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2014-09-03 18:44:15 +0200 |
commit | 5676e7b6db02b80eafc2e3ad316d5f2fee817ecb (patch) | |
tree | 540c780f1bb691971d55bffdbecec972ffa5e5eb /block | |
parent | blk-mq: pass along blk_mq_alloc_tag_set return values (diff) | |
download | linux-5676e7b6db02b80eafc2e3ad316d5f2fee817ecb.tar.xz linux-5676e7b6db02b80eafc2e3ad316d5f2fee817ecb.zip |
blk-mq: cleanup after blk_mq_init_rq_map failures
In blk-mq.c blk_mq_alloc_tag_set, if:
set->tags = kmalloc_node()
succeeds, but one of the blk_mq_init_rq_map() calls fails,
goto out_unwind;
needs to free set->tags so the caller is not obligated
to do so. None of the current callers (null_blk,
virtio_blk, virtio_blk, or the forthcoming scsi-mq)
do so.
set->tags needs to be set to NULL after doing so,
so other tag cleanup logic doesn't try to free
a stale pointer later. Also set it to NULL
in blk_mq_free_tag_set.
Tested with error injection on the forthcoming
scsi-mq + hpsa combination.
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-mq.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c index 4aac82615a46..f9b85e83d9ba 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1982,6 +1982,8 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) out_unwind: while (--i >= 0) blk_mq_free_rq_map(set, set->tags[i], i); + kfree(set->tags); + set->tags = NULL; out: return -ENOMEM; } @@ -1997,6 +1999,7 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set) } kfree(set->tags); + set->tags = NULL; } EXPORT_SYMBOL(blk_mq_free_tag_set); |