diff --git a/block/blk-merge.c b/block/blk-merge.c index 4de085431fbf7b145a162a1c2b3125182d8426f0..e6f8367646fcc7f91b3189a1946ef41463e8de52 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -599,8 +599,8 @@ int blk_rq_map_sg_bidir(struct request_queue *q, struct request *rq, { int nsegs = 0; struct scatterlist *sglist[2] = {sglist_read, sglist_write}; - struct scatterlist *last_sg_write = NULL, *last_sg_read = NULL; - struct scatterlist **sglist_last[2] = {&last_sg_write, &last_sg_read}; + struct scatterlist *last_sg_read = NULL, *last_sg_write = NULL; + struct scatterlist **sglist_last[2] = {&last_sg_read, &last_sg_write}; if (rq->bio) nsegs = __blk_bios_map_sg_bidir(q, rq->bio, sglist, sglist_last); diff --git a/block/blk-mq.c b/block/blk-mq.c index 63df4b48768cbf3454f9746648ac83e5930093d3..d72b96d469b6ac1ed2990ead389762cf485cbb47 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -329,7 +329,8 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data, if ((set->flags & BLK_MQ_F_DYN_ALLOC) && (tag >= set->nr_static_rqs)) tags->static_rqs[tag] = kmalloc(sizeof(struct request) + - set->cmd_size, GFP_KERNEL | __GFP_ZERO); + set->cmd_size, + GFP_KERNEL | __GFP_ZERO | __GFP_NOFAIL); rq = tags->static_rqs[tag]; diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index ee7003eb35021fa767d0fa27329fc17f531599b4..295c6cf8f537eb3235b3e53613b6e267c0465ad0 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -1456,6 +1456,13 @@ static int init_vq_rpair(struct virtio_blk *vblk) if (err) goto out; + /* + * Publish num_vqs before the cq_req allocation loop so that the + * error path in virtblk_kfree_vqs_cq_reqs() can iterate over all + * already-allocated cq_req arrays when one of the allocations fails. + */ + vblk->num_vqs = num_vqs; + for (i = 0; i < num_vqs; i++) { vring_size = virtqueue_get_vring_size(vqs[i]); if ((i % VIRTBLK_RING_NUM) == VIRTBLK_RING_CQ) { @@ -1464,6 +1471,7 @@ static int init_vq_rpair(struct virtio_blk *vblk) GFP_KERNEL | __GFP_ZERO); if (!vblk->vqs[i].cq_req) { err = -ENOMEM; + vdev->config->del_vqs(vdev); goto out; } } else { @@ -1479,8 +1487,6 @@ static int init_vq_rpair(struct virtio_blk *vblk) if (err < 0) vdev->config->del_vqs(vdev); - vblk->num_vqs = num_vqs; - out: kfree(vqs); kfree(callbacks);