aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Elliott <elliott@hp.com>2014-09-02 12:38:44 -0400
committerJens Axboe <axboe@fb.com>2014-09-03 12:44:15 -0400
commit5676e7b6db02b80eafc2e3ad316d5f2fee817ecb (patch)
tree540c780f1bb691971d55bffdbecec972ffa5e5eb
parentdc501dc0d9dc9cbabc18b920f91a26c207e9476c (diff)
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>
-rw-r--r--block/blk-mq.c3
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)
1982out_unwind: 1982out_unwind:
1983 while (--i >= 0) 1983 while (--i >= 0)
1984 blk_mq_free_rq_map(set, set->tags[i], i); 1984 blk_mq_free_rq_map(set, set->tags[i], i);
1985 kfree(set->tags);
1986 set->tags = NULL;
1985out: 1987out:
1986 return -ENOMEM; 1988 return -ENOMEM;
1987} 1989}
@@ -1997,6 +1999,7 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set)
1997 } 1999 }
1998 2000
1999 kfree(set->tags); 2001 kfree(set->tags);
2002 set->tags = NULL;
2000} 2003}
2001EXPORT_SYMBOL(blk_mq_free_tag_set); 2004EXPORT_SYMBOL(blk_mq_free_tag_set);
2002 2005