From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1760930AbcAKWGy (ORCPT ); Mon, 11 Jan 2016 17:06:54 -0500 Received: from kanga.kvack.org ([205.233.56.17]:51544 "EHLO kanga.kvack.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1760754AbcAKWGv (ORCPT ); Mon, 11 Jan 2016 17:06:51 -0500 Date: Mon, 11 Jan 2016 17:06:50 -0500 From: Benjamin LaHaise To: linux-aio@kvack.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-mm@kvack.org Cc: Alexander Viro , Andrew Morton , Linus Torvalds Subject: [PATCH 03/13] aio: for async operations, make the iter argument persistent Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.4.2.2i Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When implementing async read/write operations, the complexity of having to duplicate the iter argument before passing to another thread leads to duplicate code. There is no reason async operations issued by the aio core need to be placed on the stack when an aio_kiocb is allocated for each operation, so put the iter and iovec into aio_kiocb instead of on the stack. Signed-off-by: Benjamin LaHaise Signed-off-by: Benjamin LaHaise --- fs/aio.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 2cd5071..fc453ca 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -187,6 +187,10 @@ struct aio_kiocb { * this is the underlying eventfd context to deliver events to. */ struct eventfd_ctx *ki_eventfd; + + struct iov_iter ki_iter; + struct iovec *ki_iovec; + struct iovec ki_inline_vecs[UIO_FASTIOV]; }; /*------ sysctl variables----*/ @@ -1026,6 +1030,7 @@ static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx) percpu_ref_get(&ctx->reqs); req->ki_ctx = ctx; + req->ki_iovec = req->ki_inline_vecs; return req; out_put: put_reqs_available(ctx, 1); @@ -1038,6 +1043,8 @@ static void kiocb_free(struct aio_kiocb *req) fput(req->common.ki_filp); if (req->ki_eventfd != NULL) eventfd_ctx_put(req->ki_eventfd); + if (req->ki_iovec != req->ki_inline_vecs) + kfree(req->ki_iovec); kmem_cache_free(kiocb_cachep, req); } @@ -1417,16 +1424,14 @@ static int aio_setup_vectored_rw(int rw, char __user *buf, size_t len, * aio_run_iocb: * Performs the initial checks and io submission. */ -static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, +static ssize_t aio_run_iocb(struct aio_kiocb *req, unsigned opcode, char __user *buf, size_t len, bool compat) { - struct file *file = req->ki_filp; + struct file *file = req->common.ki_filp; ssize_t ret; int rw; fmode_t mode; rw_iter_op *iter_op; - struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; - struct iov_iter iter; switch (opcode) { case IOCB_CMD_PREAD: @@ -1451,43 +1456,39 @@ rw_common: if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV) ret = aio_setup_vectored_rw(rw, buf, len, - &iovec, compat, &iter); + &req->ki_iovec, compat, + &req->ki_iter); else { - ret = import_single_range(rw, buf, len, iovec, &iter); - iovec = NULL; + ret = import_single_range(rw, buf, len, req->ki_iovec, + &req->ki_iter); } if (!ret) - ret = rw_verify_area(rw, file, &req->ki_pos, - iov_iter_count(&iter)); - if (ret < 0) { - kfree(iovec); + ret = rw_verify_area(rw, file, &req->common.ki_pos, + iov_iter_count(&req->ki_iter)); + if (ret < 0) return ret; - } - - len = ret; if (rw == WRITE) file_start_write(file); - ret = iter_op(req, &iter); + ret = iter_op(&req->common, &req->ki_iter); if (rw == WRITE) file_end_write(file); - kfree(iovec); break; case IOCB_CMD_FDSYNC: if (!file->f_op->aio_fsync) return -EINVAL; - ret = file->f_op->aio_fsync(req, 1); + ret = file->f_op->aio_fsync(&req->common, 1); break; case IOCB_CMD_FSYNC: if (!file->f_op->aio_fsync) return -EINVAL; - ret = file->f_op->aio_fsync(req, 0); + ret = file->f_op->aio_fsync(&req->common, 0); break; default: @@ -1504,7 +1505,7 @@ rw_common: ret == -ERESTARTNOHAND || ret == -ERESTART_RESTARTBLOCK)) ret = -EINTR; - aio_complete(req, ret, 0); + aio_complete(&req->common, ret, 0); } return 0; @@ -1571,7 +1572,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, req->ki_user_iocb = user_iocb; req->ki_user_data = iocb->aio_data; - ret = aio_run_iocb(&req->common, iocb->aio_lio_opcode, + ret = aio_run_iocb(req, iocb->aio_lio_opcode, (char __user *)(unsigned long)iocb->aio_buf, iocb->aio_nbytes, compat); -- 2.5.0 -- "Thought is the essence of where you are now." From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Mon, 11 Jan 2016 17:06:50 -0500 From: Benjamin LaHaise To: linux-aio@kvack.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-mm@kvack.org Cc: Alexander Viro , Andrew Morton , Linus Torvalds Subject: [PATCH 03/13] aio: for async operations, make the iter argument persistent Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: Sender: owner-linux-mm@kvack.org List-ID: When implementing async read/write operations, the complexity of having to duplicate the iter argument before passing to another thread leads to duplicate code. There is no reason async operations issued by the aio core need to be placed on the stack when an aio_kiocb is allocated for each operation, so put the iter and iovec into aio_kiocb instead of on the stack. Signed-off-by: Benjamin LaHaise Signed-off-by: Benjamin LaHaise --- fs/aio.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 2cd5071..fc453ca 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -187,6 +187,10 @@ struct aio_kiocb { * this is the underlying eventfd context to deliver events to. */ struct eventfd_ctx *ki_eventfd; + + struct iov_iter ki_iter; + struct iovec *ki_iovec; + struct iovec ki_inline_vecs[UIO_FASTIOV]; }; /*------ sysctl variables----*/ @@ -1026,6 +1030,7 @@ static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx) percpu_ref_get(&ctx->reqs); req->ki_ctx = ctx; + req->ki_iovec = req->ki_inline_vecs; return req; out_put: put_reqs_available(ctx, 1); @@ -1038,6 +1043,8 @@ static void kiocb_free(struct aio_kiocb *req) fput(req->common.ki_filp); if (req->ki_eventfd != NULL) eventfd_ctx_put(req->ki_eventfd); + if (req->ki_iovec != req->ki_inline_vecs) + kfree(req->ki_iovec); kmem_cache_free(kiocb_cachep, req); } @@ -1417,16 +1424,14 @@ static int aio_setup_vectored_rw(int rw, char __user *buf, size_t len, * aio_run_iocb: * Performs the initial checks and io submission. */ -static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, +static ssize_t aio_run_iocb(struct aio_kiocb *req, unsigned opcode, char __user *buf, size_t len, bool compat) { - struct file *file = req->ki_filp; + struct file *file = req->common.ki_filp; ssize_t ret; int rw; fmode_t mode; rw_iter_op *iter_op; - struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; - struct iov_iter iter; switch (opcode) { case IOCB_CMD_PREAD: @@ -1451,43 +1456,39 @@ rw_common: if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV) ret = aio_setup_vectored_rw(rw, buf, len, - &iovec, compat, &iter); + &req->ki_iovec, compat, + &req->ki_iter); else { - ret = import_single_range(rw, buf, len, iovec, &iter); - iovec = NULL; + ret = import_single_range(rw, buf, len, req->ki_iovec, + &req->ki_iter); } if (!ret) - ret = rw_verify_area(rw, file, &req->ki_pos, - iov_iter_count(&iter)); - if (ret < 0) { - kfree(iovec); + ret = rw_verify_area(rw, file, &req->common.ki_pos, + iov_iter_count(&req->ki_iter)); + if (ret < 0) return ret; - } - - len = ret; if (rw == WRITE) file_start_write(file); - ret = iter_op(req, &iter); + ret = iter_op(&req->common, &req->ki_iter); if (rw == WRITE) file_end_write(file); - kfree(iovec); break; case IOCB_CMD_FDSYNC: if (!file->f_op->aio_fsync) return -EINVAL; - ret = file->f_op->aio_fsync(req, 1); + ret = file->f_op->aio_fsync(&req->common, 1); break; case IOCB_CMD_FSYNC: if (!file->f_op->aio_fsync) return -EINVAL; - ret = file->f_op->aio_fsync(req, 0); + ret = file->f_op->aio_fsync(&req->common, 0); break; default: @@ -1504,7 +1505,7 @@ rw_common: ret == -ERESTARTNOHAND || ret == -ERESTART_RESTARTBLOCK)) ret = -EINTR; - aio_complete(req, ret, 0); + aio_complete(&req->common, ret, 0); } return 0; @@ -1571,7 +1572,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, req->ki_user_iocb = user_iocb; req->ki_user_data = iocb->aio_data; - ret = aio_run_iocb(&req->common, iocb->aio_lio_opcode, + ret = aio_run_iocb(req, iocb->aio_lio_opcode, (char __user *)(unsigned long)iocb->aio_buf, iocb->aio_nbytes, compat); -- 2.5.0 -- "Thought is the essence of where you are now." -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: email@kvack.org From mboxrd@z Thu Jan 1 00:00:00 1970 From: Benjamin LaHaise Subject: [PATCH 03/13] aio: for async operations, make the iter argument persistent Date: Mon, 11 Jan 2016 17:06:50 -0500 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Return-path: Content-Disposition: inline In-Reply-To: Sender: owner-linux-aio@kvack.org To: linux-aio@kvack.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-mm@kvack.org Cc: Alexander Viro , Andrew Morton , Linus Torvalds List-Id: linux-api@vger.kernel.org When implementing async read/write operations, the complexity of having to duplicate the iter argument before passing to another thread leads to duplicate code. There is no reason async operations issued by the aio core need to be placed on the stack when an aio_kiocb is allocated for each operation, so put the iter and iovec into aio_kiocb instead of on the stack. Signed-off-by: Benjamin LaHaise Signed-off-by: Benjamin LaHaise --- fs/aio.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 2cd5071..fc453ca 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -187,6 +187,10 @@ struct aio_kiocb { * this is the underlying eventfd context to deliver events to. */ struct eventfd_ctx *ki_eventfd; + + struct iov_iter ki_iter; + struct iovec *ki_iovec; + struct iovec ki_inline_vecs[UIO_FASTIOV]; }; /*------ sysctl variables----*/ @@ -1026,6 +1030,7 @@ static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx) percpu_ref_get(&ctx->reqs); req->ki_ctx = ctx; + req->ki_iovec = req->ki_inline_vecs; return req; out_put: put_reqs_available(ctx, 1); @@ -1038,6 +1043,8 @@ static void kiocb_free(struct aio_kiocb *req) fput(req->common.ki_filp); if (req->ki_eventfd != NULL) eventfd_ctx_put(req->ki_eventfd); + if (req->ki_iovec != req->ki_inline_vecs) + kfree(req->ki_iovec); kmem_cache_free(kiocb_cachep, req); } @@ -1417,16 +1424,14 @@ static int aio_setup_vectored_rw(int rw, char __user *buf, size_t len, * aio_run_iocb: * Performs the initial checks and io submission. */ -static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, +static ssize_t aio_run_iocb(struct aio_kiocb *req, unsigned opcode, char __user *buf, size_t len, bool compat) { - struct file *file = req->ki_filp; + struct file *file = req->common.ki_filp; ssize_t ret; int rw; fmode_t mode; rw_iter_op *iter_op; - struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; - struct iov_iter iter; switch (opcode) { case IOCB_CMD_PREAD: @@ -1451,43 +1456,39 @@ rw_common: if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV) ret = aio_setup_vectored_rw(rw, buf, len, - &iovec, compat, &iter); + &req->ki_iovec, compat, + &req->ki_iter); else { - ret = import_single_range(rw, buf, len, iovec, &iter); - iovec = NULL; + ret = import_single_range(rw, buf, len, req->ki_iovec, + &req->ki_iter); } if (!ret) - ret = rw_verify_area(rw, file, &req->ki_pos, - iov_iter_count(&iter)); - if (ret < 0) { - kfree(iovec); + ret = rw_verify_area(rw, file, &req->common.ki_pos, + iov_iter_count(&req->ki_iter)); + if (ret < 0) return ret; - } - - len = ret; if (rw == WRITE) file_start_write(file); - ret = iter_op(req, &iter); + ret = iter_op(&req->common, &req->ki_iter); if (rw == WRITE) file_end_write(file); - kfree(iovec); break; case IOCB_CMD_FDSYNC: if (!file->f_op->aio_fsync) return -EINVAL; - ret = file->f_op->aio_fsync(req, 1); + ret = file->f_op->aio_fsync(&req->common, 1); break; case IOCB_CMD_FSYNC: if (!file->f_op->aio_fsync) return -EINVAL; - ret = file->f_op->aio_fsync(req, 0); + ret = file->f_op->aio_fsync(&req->common, 0); break; default: @@ -1504,7 +1505,7 @@ rw_common: ret == -ERESTARTNOHAND || ret == -ERESTART_RESTARTBLOCK)) ret = -EINTR; - aio_complete(req, ret, 0); + aio_complete(&req->common, ret, 0); } return 0; @@ -1571,7 +1572,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, req->ki_user_iocb = user_iocb; req->ki_user_data = iocb->aio_data; - ret = aio_run_iocb(&req->common, iocb->aio_lio_opcode, + ret = aio_run_iocb(req, iocb->aio_lio_opcode, (char __user *)(unsigned long)iocb->aio_buf, iocb->aio_nbytes, compat); -- 2.5.0 -- "Thought is the essence of where you are now." -- To unsubscribe, send a message with 'unsubscribe linux-aio' in the body to majordomo@kvack.org. For more info on Linux AIO, see: http://www.kvack.org/aio/ Don't email: aart@kvack.org