[PATCH-v2 16/16] target/iblock: Convert to inline bio/bvec + blk_poll

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>

This patch converts IBLOCK to use inline_bio and inline_bvec
as part of target_iostate, and converts iblock_execute_rw()
and iblock_execute_write_same() accordingly.

Also, it follows nvme-target/io-cmd code and uses blk_poll()
for both cases with submit_bio() cookie.

Cc: Jens Axboe <axboe@xxxxxx>
Cc: Christoph Hellwig <hch@xxxxxx>
Cc: Martin Petersen <martin.petersen@xxxxxxxxxx>
Cc: Sagi Grimberg <sagi@xxxxxxxxxxx>
Cc: Hannes Reinecke <hare@xxxxxxx>
Cc: Mike Christie <michaelc@xxxxxxxxxxx>
Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
---
 drivers/target/target_core_iblock.c | 118 +++++++++++++-----------------------
 include/target/target_core_base.h   |   4 ++
 2 files changed, 47 insertions(+), 75 deletions(-)

diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index b898dd7..f84c151 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -304,32 +304,21 @@ static void iblock_bio_done(struct bio *bio)
 		smp_mb__after_atomic();
 	}
 
-	bio_put(bio);
+	if (bio != &ios->inline_bio)
+		bio_put(bio);
 
 	iblock_complete_cmd(ios);
 }
 
-
-
 static struct bio *
-iblock_get_bio(struct target_iostate *ios, sector_t lba, u32 sg_num)
+iblock_get_bio(struct target_iostate *ios, sector_t lba)
 {
 	struct iblock_dev *ib_dev = IBLOCK_DEV(ios->se_dev);
-	struct bio *bio;
-
-	/*
-	 * Only allocate as many vector entries as the bio code allows us to,
-	 * we'll loop later on until we have handled the whole request.
-	 */
-	if (sg_num > BIO_MAX_PAGES)
-		sg_num = BIO_MAX_PAGES;
-
-	bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set);
-	if (!bio) {
-		pr_err("Unable to allocate memory for bio\n");
-		return NULL;
-	}
+	struct bio *bio = &ios->inline_bio;
 
+	bio_init(bio);
+	bio->bi_max_vecs = IOS_MAX_INLINE_BIOVEC;
+	bio->bi_io_vec = ios->inline_bvec;
 	bio->bi_bdev = ib_dev->ibd_bd;
 	bio->bi_private = ios;
 	bio->bi_end_io = &iblock_bio_done;
@@ -338,17 +327,6 @@ iblock_get_bio(struct target_iostate *ios, sector_t lba, u32 sg_num)
 	return bio;
 }
 
-static void iblock_submit_bios(struct bio_list *list, int rw)
-{
-	struct blk_plug plug;
-	struct bio *bio;
-
-	blk_start_plug(&plug);
-	while ((bio = bio_list_pop(list)))
-		submit_bio(rw, bio);
-	blk_finish_plug(&plug);
-}
-
 static void iblock_end_io_flush(struct bio *bio)
 {
 	struct target_iostate *ios = bio->bi_private;
@@ -450,13 +428,14 @@ iblock_execute_write_same(struct target_iostate *ios,
 {
 	struct target_iomem *iomem = ios->iomem;
 	struct block_device *bdev = IBLOCK_DEV(ios->se_dev)->ibd_bd;
+	struct request_queue *q = bdev_get_queue(bdev);
 	struct scatterlist *sg;
 	struct bio *bio;
-	struct bio_list list;
 	struct se_device *dev = ios->se_dev;
 	sector_t block_lba = target_to_linux_sector(dev, ios->t_task_lba);
 	sector_t num_blocks = get_sectors(ios);
 	sector_t sectors = target_to_linux_sector(dev, num_blocks);
+	blk_qc_t cookie;
 
 	if (ios->prot_op) {
 		pr_err("WRITE_SAME: Protection information with IBLOCK"
@@ -477,25 +456,23 @@ iblock_execute_write_same(struct target_iostate *ios,
 		return iblock_execute_write_same_direct(bdev, ios, iomem,
 							num_blocks);
 
-	bio = iblock_get_bio(ios, block_lba, 1);
+	bio = iblock_get_bio(ios, block_lba);
 	if (!bio)
 		goto fail;
 
-	bio_list_init(&list);
-	bio_list_add(&list, bio);
-
 	atomic_set(&ios->backend_pending, 1);
 
 	while (sectors) {
 		while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
 				!= sg->length) {
+			struct bio *prev = bio;
 
-			bio = iblock_get_bio(ios, block_lba, 1);
-			if (!bio)
-				goto fail_put_bios;
+			bio = bio_alloc(GFP_KERNEL, 1);
+			bio->bi_bdev = bdev;
+			bio->bi_iter.bi_sector = block_lba;
 
-			atomic_inc(&ios->backend_pending);
-			bio_list_add(&list, bio);
+			bio_chain(bio, prev);
+			cookie = submit_bio(WRITE, prev);
 		}
 
 		/* Always in 512 byte units for Linux/Block */
@@ -503,12 +480,11 @@ iblock_execute_write_same(struct target_iostate *ios,
 		sectors -= 1;
 	}
 
-	iblock_submit_bios(&list, WRITE);
+	cookie = submit_bio(WRITE, bio);
+	blk_poll(q, cookie);
+
 	return 0;
 
-fail_put_bios:
-	while ((bio = bio_list_pop(&list)))
-		bio_put(bio);
 fail:
 	return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 }
@@ -669,18 +645,15 @@ iblock_execute_rw(struct target_iostate *ios, struct scatterlist *sgl, u32 sgl_n
 		  void (*t_comp_func)(struct target_iostate *ios, u16))
 {
 	struct se_device *dev = ios->se_dev;
+	struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
+	struct request_queue *q = bdev_get_queue(ib_dev->ibd_bd);
 	sector_t block_lba = target_to_linux_sector(dev, ios->t_task_lba);
-	struct bio *bio, *bio_start;
-	struct bio_list list;
+	struct bio *bio;
 	struct scatterlist *sg;
-	u32 sg_num = sgl_nents;
-	unsigned bio_cnt;
-	int rw = 0;
-	int i;
+	blk_qc_t cookie;
+	int sg_num = sgl_nents, rw = 0, i;
 
 	if (data_direction == DMA_TO_DEVICE) {
-		struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
-		struct request_queue *q = bdev_get_queue(ib_dev->ibd_bd);
 		/*
 		 * Force writethrough using WRITE_FUA if a volatile write cache
 		 * is not enabled, or if initiator set the Force Unit Access bit.
@@ -705,16 +678,17 @@ iblock_execute_rw(struct target_iostate *ios, struct scatterlist *sgl, u32 sgl_n
 		return 0;
 	}
 
-	bio = iblock_get_bio(ios, block_lba, sgl_nents);
+	bio = iblock_get_bio(ios, block_lba);
 	if (!bio)
 		goto fail;
 
-	bio_start = bio;
-	bio_list_init(&list);
-	bio_list_add(&list, bio);
-
 	atomic_set(&ios->backend_pending, 2);
-	bio_cnt = 1;
+
+	if (ios->prot_type && dev->dev_attrib.pi_prot_type) {
+		int rc = iblock_alloc_bip(ios, ios->iomem, bio);
+		if (rc)
+			goto fail_put_bios;
+	}
 
 	for_each_sg(sgl, sg, sgl_nents, i) {
 		/*
@@ -724,18 +698,14 @@ iblock_execute_rw(struct target_iostate *ios, struct scatterlist *sgl, u32 sgl_n
 		 */
 		while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
 				!= sg->length) {
-			if (bio_cnt >= IBLOCK_MAX_BIO_PER_TASK) {
-				iblock_submit_bios(&list, rw);
-				bio_cnt = 0;
-			}
+			struct bio *prev = bio;
 
-			bio = iblock_get_bio(ios, block_lba, sg_num);
-			if (!bio)
-				goto fail_put_bios;
+			bio = bio_alloc(GFP_KERNEL, min(sg_num, BIO_MAX_PAGES));
+			bio->bi_bdev = ib_dev->ibd_bd;
+			bio->bi_iter.bi_sector = block_lba;
 
-			atomic_inc(&ios->backend_pending);
-			bio_list_add(&list, bio);
-			bio_cnt++;
+			bio_chain(bio, prev);
+			cookie = submit_bio(rw, prev);
 		}
 
 		/* Always in 512 byte units for Linux/Block */
@@ -743,19 +713,17 @@ iblock_execute_rw(struct target_iostate *ios, struct scatterlist *sgl, u32 sgl_n
 		sg_num--;
 	}
 
-	if (ios->prot_type && dev->dev_attrib.pi_prot_type) {
-		int rc = iblock_alloc_bip(ios, ios->iomem, bio_start);
-		if (rc)
-			goto fail_put_bios;
-	}
+	cookie = submit_bio(rw, bio);
+	blk_poll(q, cookie);
 
-	iblock_submit_bios(&list, rw);
 	iblock_complete_cmd(ios);
 	return 0;
 
 fail_put_bios:
-	while ((bio = bio_list_pop(&list)))
-		bio_put(bio);
+	bio->bi_error = -EIO;
+	bio_endio(bio);
+	iblock_complete_cmd(ios);
+	return 0;
 fail:
 	return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 }
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 60a180f..2083340 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -449,6 +449,8 @@ struct target_iomem {
 	unsigned int		t_prot_nents;
 };
 
+#define IOS_MAX_INLINE_BIOVEC		8
+
 struct target_iostate {
 	unsigned long long	t_task_lba;
 	unsigned int		t_task_nolb;
@@ -473,6 +475,8 @@ struct target_iostate {
 	/* Used by IBLOCK for BIO submission + completion */
 	atomic_t		backend_pending;
 	atomic_t		backend_err_cnt;
+	struct bio		inline_bio;
+	struct bio_vec		inline_bvec[IOS_MAX_INLINE_BIOVEC];
 };
 
 struct se_cmd {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux