All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2 for-4.19] nvmet: handle bio allocation failure
@ 2018-09-28  0:40 Sagi Grimberg
  2018-09-28 15:16 ` Christoph Hellwig
  0 siblings, 1 reply; 3+ messages in thread
From: Sagi Grimberg @ 2018-09-28  0:40 UTC (permalink / raw)


We cannot rely on bio_alloc to succeed, so we first allocate
the needed bios in a list, and only then submit all of them so
we can cleanup if something fails in the process of building
the chained bios.

Signed-off-by: Sagi Grimberg <sagi at grimberg.me>
---
 drivers/nvme/target/io-cmd-bdev.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c
index 7bc9f6240432..0664e2049fa4 100644
--- a/drivers/nvme/target/io-cmd-bdev.c
+++ b/drivers/nvme/target/io-cmd-bdev.c
@@ -59,9 +59,10 @@ static void nvmet_bdev_execute_rw(struct nvmet_req *req)
 {
 	int sg_cnt = req->sg_cnt;
 	struct bio *bio = &req->b.inline_bio;
+	struct bio_list list;
 	struct scatterlist *sg;
 	sector_t sector;
-	blk_qc_t cookie;
+	blk_qc_t cookie = BLK_QC_T_NONE;
 	int op, op_flags = 0, i;
 
 	if (!req->sg_cnt) {
@@ -88,27 +89,39 @@ static void nvmet_bdev_execute_rw(struct nvmet_req *req)
 	bio->bi_end_io = nvmet_bio_done;
 	bio_set_op_attrs(bio, op, op_flags);
 
+	bio_list_init(&list);
 	for_each_sg(req->sg, sg, req->sg_cnt, i) {
 		while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
 				!= sg->length) {
 			struct bio *prev = bio;
 
 			bio = bio_alloc(GFP_KERNEL, min(sg_cnt, BIO_MAX_PAGES));
+			if (unlikely(!bio))
+				goto err;
+
 			bio_set_dev(bio, req->ns->bdev);
 			bio->bi_iter.bi_sector = sector;
 			bio_set_op_attrs(bio, op, op_flags);
 
 			bio_chain(bio, prev);
-			submit_bio(prev);
+			bio_list_add(&list, bio);
 		}
 
 		sector += sg->length >> 9;
 		sg_cnt--;
 	}
 
-	cookie = submit_bio(bio);
+	bio_list_add(&list, bio);
+	while ((bio = bio_list_pop(&list)))
+		cookie = submit_bio(bio);
 
 	blk_poll(bdev_get_queue(req->ns->bdev), cookie);
+	return;
+err:
+	while ((bio = bio_list_pop(&list)))
+		if (bio != &req->b.inline_bio)
+			bio_put(bio);
+	nvmet_req_complete(req, NVME_SC_INTERNAL);
 }
 
 static void nvmet_bdev_execute_flush(struct nvmet_req *req)
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-09-28 22:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-09-28  0:40 [PATCH 1/2 for-4.19] nvmet: handle bio allocation failure Sagi Grimberg
2018-09-28 15:16 ` Christoph Hellwig
2018-09-28 22:41   ` Sagi Grimberg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.