The functions lo_write_transfer() and lo_read_transfer() allocte and free the page everytime it is called from the do_req_filebacked(). Add a member to the loop_cmd structure and use that page in read/write transfer functions. This is *compile only* RFC, if this is accepted I'll send tested version. Signed-off-by: Chaitanya Kulkarni <chaitanya.kulkarni@xxxxxxx> --- drivers/block/loop.c | 22 ++++++++-------------- drivers/block/loop.h | 1 + 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 578fc034db3f..08bd17afbdff 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -318,14 +318,13 @@ static int lo_write_simple(struct loop_device *lo, struct request *rq, * access to the destination pages of the backing file. */ static int lo_write_transfer(struct loop_device *lo, struct request *rq, - loff_t pos) + struct loop_cmd *cmd, loff_t pos) { - struct bio_vec bvec, b; + struct page *page = &cmd->page; struct req_iterator iter; - struct page *page; + struct bio_vec bvec, b; int ret = 0; - page = alloc_page(GFP_NOIO); if (unlikely(!page)) return -ENOMEM; @@ -343,7 +342,6 @@ static int lo_write_transfer(struct loop_device *lo, struct request *rq, break; } - __free_page(page); return ret; } @@ -377,19 +375,15 @@ static int lo_read_simple(struct loop_device *lo, struct request *rq, } static int lo_read_transfer(struct loop_device *lo, struct request *rq, - loff_t pos) + struct loop_cmd *cmd, loff_t pos) { - struct bio_vec bvec, b; + struct page *page = &cmd->page; struct req_iterator iter; + struct bio_vec bvec, b; struct iov_iter i; - struct page *page; ssize_t len; int ret = 0; - page = alloc_page(GFP_NOIO); - if (unlikely(!page)) - return -ENOMEM; - rq_for_each_segment(bvec, rq, iter) { loff_t offset = pos; @@ -622,14 +616,14 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq) return lo_fallocate(lo, rq, pos, FALLOC_FL_PUNCH_HOLE); case REQ_OP_WRITE: if (lo->transfer) - return lo_write_transfer(lo, rq, pos); + return lo_write_transfer(lo, rq, cmd, pos); else if (cmd->use_aio) return lo_rw_aio(lo, cmd, pos, WRITE); else return lo_write_simple(lo, rq, pos); case REQ_OP_READ: if (lo->transfer) - return lo_read_transfer(lo, rq, pos); + return lo_read_transfer(lo, rq, cmd, pos); else if (cmd->use_aio) return lo_rw_aio(lo, cmd, pos, READ); else diff --git a/drivers/block/loop.h b/drivers/block/loop.h index a3c04f310672..dd949b22e9c9 100644 --- a/drivers/block/loop.h +++ b/drivers/block/loop.h @@ -71,6 +71,7 @@ struct loop_cmd { atomic_t ref; /* only for aio */ long ret; struct kiocb iocb; + struct page page; struct bio_vec *bvec; struct cgroup_subsys_state *css; }; -- 2.22.1