[PATCH 4/8] loop: cover simple read/write via lo_rw_aio()

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

 



lo_rw_aio() is capable of doing simple buffered read/write, not
necessary to use lo_simple_read()/lo_simple_write() for that.

Add cmd->use_dio for real loop dio, then cmd->use_aio is only used
in case that lo_rw_aio() is used for submitting IO against backing file.

Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx>
---
 drivers/block/loop.c | 83 +++++++++-----------------------------------
 drivers/block/loop.h |  1 +
 2 files changed, 18 insertions(+), 66 deletions(-)

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 769cf84c6899..d1784f825b6b 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -339,23 +339,6 @@ static int lo_write_bvec(struct file *file, struct bio_vec *bvec, loff_t *ppos)
 	return bw;
 }
 
-static int lo_write_simple(struct loop_device *lo, struct request *rq,
-		loff_t pos)
-{
-	struct bio_vec bvec;
-	struct req_iterator iter;
-	int ret = 0;
-
-	rq_for_each_segment(bvec, rq, iter) {
-		ret = lo_write_bvec(lo->lo_backing_file, &bvec, &pos);
-		if (ret < 0)
-			break;
-		cond_resched();
-	}
-
-	return ret;
-}
-
 /*
  * This is the slow, transforming version that needs to double buffer the
  * data as it cannot do the transformations in place without having direct
@@ -391,33 +374,6 @@ static int lo_write_transfer(struct loop_device *lo, struct request *rq,
 	return ret;
 }
 
-static int lo_read_simple(struct loop_device *lo, struct request *rq,
-		loff_t pos)
-{
-	struct bio_vec bvec;
-	struct req_iterator iter;
-	struct iov_iter i;
-	ssize_t len;
-
-	rq_for_each_segment(bvec, rq, iter) {
-		iov_iter_bvec(&i, READ, &bvec, 1, bvec.bv_len);
-		len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0);
-		if (len < 0)
-			return len;
-
-		if (len != bvec.bv_len) {
-			struct bio *bio;
-
-			__rq_for_each_bio(bio, rq)
-				zero_fill_bio(bio);
-			break;
-		}
-		cond_resched();
-	}
-
-	return 0;
-}
-
 static int lo_read_transfer(struct loop_device *lo, struct request *rq,
 		loff_t pos)
 {
@@ -520,10 +476,10 @@ static void lo_complete_rq(struct request *rq)
 	blk_status_t ret = BLK_STS_OK;
 
 	/* Kernel wrote to our pages, call flush_dcache_page */
-	if (req_op(rq) == REQ_OP_READ && !cmd->use_aio && cmd->ret >= 0)
+	if (req_op(rq) == REQ_OP_READ && !cmd->use_dio && cmd->ret >= 0)
 		lo_flush_dcache_for_read(rq);
 
-	if (!cmd->use_aio || cmd->ret < 0 || cmd->ret == blk_rq_bytes(rq) ||
+	if (!cmd->use_dio || cmd->ret < 0 || cmd->ret == blk_rq_bytes(rq) ||
 	    req_op(rq) != REQ_OP_READ) {
 		if (cmd->ret < 0)
 			ret = errno_to_blk_status(cmd->ret);
@@ -625,17 +581,24 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
 		offset = bio->bi_iter.bi_bvec_done;
 		bvec = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter);
 	}
-	atomic_set(&cmd->ref, 2);
-
 	iov_iter_bvec(&iter, rw, bvec, nr_bvec, blk_rq_bytes(rq));
 	iter.iov_offset = offset;
 
 	cmd->iocb.ki_pos = pos;
 	cmd->iocb.ki_filp = file;
-	cmd->iocb.ki_complete = lo_rw_aio_complete;
-	cmd->iocb.ki_flags = IOCB_DIRECT;
+
 	cmd->iocb.ki_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0);
+	if (!cmd->use_dio) {
+		atomic_set(&cmd->ref, 1);
+		cmd->iocb.ki_flags = 0;
+		cmd->ret = lo_call_backing_rw_iter(file, &cmd->iocb, &iter, rw);
+		lo_rw_aio_do_completion(cmd);
+		return 0;
+	}
 
+	atomic_set(&cmd->ref, 2);
+	cmd->iocb.ki_complete = lo_rw_aio_complete;
+	cmd->iocb.ki_flags = IOCB_DIRECT;
 	ret = lo_call_backing_rw_iter(file, &cmd->iocb, &iter, rw);
 
 	lo_rw_aio_do_completion(cmd);
@@ -650,15 +613,6 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq)
 	struct loop_cmd *cmd = blk_mq_rq_to_pdu(rq);
 	loff_t pos = ((loff_t) blk_rq_pos(rq) << 9) + lo->lo_offset;
 
-	/*
-	 * lo_write_simple and lo_read_simple should have been covered
-	 * by io submit style function like lo_rw_aio(), one blocker
-	 * is that lo_read_simple() need to call flush_dcache_page after
-	 * the page is written from kernel, and it isn't easy to handle
-	 * this in io submit style function which submits all segments
-	 * of the req at one time. And direct read IO doesn't need to
-	 * run flush_dcache_page().
-	 */
 	switch (req_op(rq)) {
 	case REQ_OP_FLUSH:
 		return lo_req_flush(lo, rq);
@@ -676,17 +630,13 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq)
 	case REQ_OP_WRITE:
 		if (lo->transfer)
 			return lo_write_transfer(lo, rq, pos);
-		else if (cmd->use_aio)
-			return lo_rw_aio(lo, cmd, pos, WRITE);
 		else
-			return lo_write_simple(lo, rq, pos);
+			return lo_rw_aio(lo, cmd, pos, WRITE);
 	case REQ_OP_READ:
 		if (lo->transfer)
 			return lo_read_transfer(lo, rq, pos);
-		else if (cmd->use_aio)
-			return lo_rw_aio(lo, cmd, pos, READ);
 		else
-			return lo_read_simple(lo, rq, pos);
+			return lo_rw_aio(lo, cmd, pos, READ);
 	default:
 		WARN_ON_ONCE(1);
 		return -EIO;
@@ -2171,7 +2121,8 @@ static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx,
 		cmd->use_aio = false;
 		break;
 	default:
-		cmd->use_aio = lo->use_dio;
+		cmd->use_aio = !lo->transfer;
+		cmd->use_dio = lo->use_dio && cmd->use_aio;
 		break;
 	}
 
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
index 04c88dd6eabd..b7d611e4f517 100644
--- a/drivers/block/loop.h
+++ b/drivers/block/loop.h
@@ -74,6 +74,7 @@ struct loop_device {
 struct loop_cmd {
 	struct list_head list_entry;
 	bool use_aio; /* use AIO interface to handle I/O */
+	bool use_dio;
 	atomic_t ref; /* only for aio */
 	long ret;
 	struct kiocb iocb;
-- 
2.31.1




[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux