Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752097AbaKYHUc (ORCPT ); Tue, 25 Nov 2014 02:20:32 -0500 Received: from mail-wg0-f51.google.com ([74.125.82.51]:59796 "EHLO mail-wg0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750770AbaKYHUW (ORCPT ); Tue, 25 Nov 2014 02:20:22 -0500 From: Pieter Smith To: pieter@boesman.nl Cc: Josh Triplett , Alexander Duyck , Alexander Viro , Alexei Starovoitov , Andrew Morton , Bertrand Jacquin , Catalina Mocanu , Daniel Borkmann , "David S. Miller" , Eric Dumazet , "Eric W. Biederman" , Fabian Frederick , fuse-devel@lists.sourceforge.net (open list:FUSE: FILESYSTEM...), Geert Uytterhoeven , Hugh Dickins , Iulia Manda , Jan Beulich , "J. Bruce Fields" , Jeff Layton , linux-api@vger.kernel.org (open list:ABI/API), linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org (open list), linux-nfs@vger.kernel.org (open list:KERNEL NFSD, SUNR...), "Luis R. Rodriguez" , Matt Turner , Mel Gorman , "Michael S. Tsirkin" , Miklos Szeredi , netdev@vger.kernel.org (open list:NETWORKING [GENERAL]), Oleg Nesterov , Paul Durrant , "Paul E. McKenney" , Peter Foley , Thomas Graf , Tom Herbert , Trond Myklebust , Willem de Bruijn , Xiao Guangrong , =?UTF-8?q?=E8=94=A1=E6=AD=A3=E9=BE=99?= Subject: [PATCH v5 1/7] fs: move sendfile syscall into fs/splice Date: Tue, 25 Nov 2014 08:19:36 +0100 Message-Id: <1416899996-21315-2-git-send-email-pieter@boesman.nl> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1416899996-21315-1-git-send-email-pieter@boesman.nl> References: <1416899996-21315-1-git-send-email-pieter@boesman.nl> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org sendfile functionally forms part of the splice group of syscalls (splice, vmsplice and tee). Grouping sendfile with splice paves the way to compiling out the splice group of syscalls for embedded systems that do not need these. add/remove: 0/0 grow/shrink: 7/2 up/down: 86/-61 (25) function old new delta file_start_write 34 68 +34 file_end_write 29 58 +29 sys_pwritev 115 122 +7 sys_preadv 115 122 +7 fdput_pos 29 36 +7 sys_pwrite64 115 116 +1 sys_pread64 115 116 +1 sys_tee 497 491 -6 sys_splice 1075 1020 -55 Signed-off-by: Pieter Smith --- fs/read_write.c | 175 ------------------------------------------------------- fs/splice.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 175 deletions(-) diff --git a/fs/read_write.c b/fs/read_write.c index 7d9318c..d9451ba 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1191,178 +1191,3 @@ COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd, } #endif -static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, - size_t count, loff_t max) -{ - struct fd in, out; - struct inode *in_inode, *out_inode; - loff_t pos; - loff_t out_pos; - ssize_t retval; - int fl; - - /* - * Get input file, and verify that it is ok.. - */ - retval = -EBADF; - in = fdget(in_fd); - if (!in.file) - goto out; - if (!(in.file->f_mode & FMODE_READ)) - goto fput_in; - retval = -ESPIPE; - if (!ppos) { - pos = in.file->f_pos; - } else { - pos = *ppos; - if (!(in.file->f_mode & FMODE_PREAD)) - goto fput_in; - } - retval = rw_verify_area(READ, in.file, &pos, count); - if (retval < 0) - goto fput_in; - count = retval; - - /* - * Get output file, and verify that it is ok.. - */ - retval = -EBADF; - out = fdget(out_fd); - if (!out.file) - goto fput_in; - if (!(out.file->f_mode & FMODE_WRITE)) - goto fput_out; - retval = -EINVAL; - in_inode = file_inode(in.file); - out_inode = file_inode(out.file); - out_pos = out.file->f_pos; - retval = rw_verify_area(WRITE, out.file, &out_pos, count); - if (retval < 0) - goto fput_out; - count = retval; - - if (!max) - max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); - - if (unlikely(pos + count > max)) { - retval = -EOVERFLOW; - if (pos >= max) - goto fput_out; - count = max - pos; - } - - fl = 0; -#if 0 - /* - * We need to debate whether we can enable this or not. The - * man page documents EAGAIN return for the output at least, - * and the application is arguably buggy if it doesn't expect - * EAGAIN on a non-blocking file descriptor. - */ - if (in.file->f_flags & O_NONBLOCK) - fl = SPLICE_F_NONBLOCK; -#endif - file_start_write(out.file); - retval = do_splice_direct(in.file, &pos, out.file, &out_pos, count, fl); - file_end_write(out.file); - - if (retval > 0) { - add_rchar(current, retval); - add_wchar(current, retval); - fsnotify_access(in.file); - fsnotify_modify(out.file); - out.file->f_pos = out_pos; - if (ppos) - *ppos = pos; - else - in.file->f_pos = pos; - } - - inc_syscr(current); - inc_syscw(current); - if (pos > max) - retval = -EOVERFLOW; - -fput_out: - fdput(out); -fput_in: - fdput(in); -out: - return retval; -} - -SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd, off_t __user *, offset, size_t, count) -{ - loff_t pos; - off_t off; - ssize_t ret; - - if (offset) { - if (unlikely(get_user(off, offset))) - return -EFAULT; - pos = off; - ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS); - if (unlikely(put_user(pos, offset))) - return -EFAULT; - return ret; - } - - return do_sendfile(out_fd, in_fd, NULL, count, 0); -} - -SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd, loff_t __user *, offset, size_t, count) -{ - loff_t pos; - ssize_t ret; - - if (offset) { - if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t)))) - return -EFAULT; - ret = do_sendfile(out_fd, in_fd, &pos, count, 0); - if (unlikely(put_user(pos, offset))) - return -EFAULT; - return ret; - } - - return do_sendfile(out_fd, in_fd, NULL, count, 0); -} - -#ifdef CONFIG_COMPAT -COMPAT_SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd, - compat_off_t __user *, offset, compat_size_t, count) -{ - loff_t pos; - off_t off; - ssize_t ret; - - if (offset) { - if (unlikely(get_user(off, offset))) - return -EFAULT; - pos = off; - ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS); - if (unlikely(put_user(pos, offset))) - return -EFAULT; - return ret; - } - - return do_sendfile(out_fd, in_fd, NULL, count, 0); -} - -COMPAT_SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd, - compat_loff_t __user *, offset, compat_size_t, count) -{ - loff_t pos; - ssize_t ret; - - if (offset) { - if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t)))) - return -EFAULT; - ret = do_sendfile(out_fd, in_fd, &pos, count, 0); - if (unlikely(put_user(pos, offset))) - return -EFAULT; - return ret; - } - - return do_sendfile(out_fd, in_fd, NULL, count, 0); -} -#endif diff --git a/fs/splice.c b/fs/splice.c index f5cb9ba..c1a2861 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -2039,3 +2040,180 @@ SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags) return error; } + +static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, + size_t count, loff_t max) +{ + struct fd in, out; + struct inode *in_inode, *out_inode; + loff_t pos; + loff_t out_pos; + ssize_t retval; + int fl; + + /* + * Get input file, and verify that it is ok.. + */ + retval = -EBADF; + in = fdget(in_fd); + if (!in.file) + goto out; + if (!(in.file->f_mode & FMODE_READ)) + goto fput_in; + retval = -ESPIPE; + if (!ppos) { + pos = in.file->f_pos; + } else { + pos = *ppos; + if (!(in.file->f_mode & FMODE_PREAD)) + goto fput_in; + } + retval = rw_verify_area(READ, in.file, &pos, count); + if (retval < 0) + goto fput_in; + count = retval; + + /* + * Get output file, and verify that it is ok.. + */ + retval = -EBADF; + out = fdget(out_fd); + if (!out.file) + goto fput_in; + if (!(out.file->f_mode & FMODE_WRITE)) + goto fput_out; + retval = -EINVAL; + in_inode = file_inode(in.file); + out_inode = file_inode(out.file); + out_pos = out.file->f_pos; + retval = rw_verify_area(WRITE, out.file, &out_pos, count); + if (retval < 0) + goto fput_out; + count = retval; + + if (!max) + max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); + + if (unlikely(pos + count > max)) { + retval = -EOVERFLOW; + if (pos >= max) + goto fput_out; + count = max - pos; + } + + fl = 0; +#if 0 + /* + * We need to debate whether we can enable this or not. The + * man page documents EAGAIN return for the output at least, + * and the application is arguably buggy if it doesn't expect + * EAGAIN on a non-blocking file descriptor. + */ + if (in.file->f_flags & O_NONBLOCK) + fl = SPLICE_F_NONBLOCK; +#endif + file_start_write(out.file); + retval = do_splice_direct(in.file, &pos, out.file, &out_pos, count, fl); + file_end_write(out.file); + + if (retval > 0) { + add_rchar(current, retval); + add_wchar(current, retval); + fsnotify_access(in.file); + fsnotify_modify(out.file); + out.file->f_pos = out_pos; + if (ppos) + *ppos = pos; + else + in.file->f_pos = pos; + } + + inc_syscr(current); + inc_syscw(current); + if (pos > max) + retval = -EOVERFLOW; + +fput_out: + fdput(out); +fput_in: + fdput(in); +out: + return retval; +} + +SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd, off_t __user *, offset, size_t, count) +{ + loff_t pos; + off_t off; + ssize_t ret; + + if (offset) { + if (unlikely(get_user(off, offset))) + return -EFAULT; + pos = off; + ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS); + if (unlikely(put_user(pos, offset))) + return -EFAULT; + return ret; + } + + return do_sendfile(out_fd, in_fd, NULL, count, 0); +} + +SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd, loff_t __user *, offset, size_t, count) +{ + loff_t pos; + ssize_t ret; + + if (offset) { + if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t)))) + return -EFAULT; + ret = do_sendfile(out_fd, in_fd, &pos, count, 0); + if (unlikely(put_user(pos, offset))) + return -EFAULT; + return ret; + } + + return do_sendfile(out_fd, in_fd, NULL, count, 0); +} + +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd, + compat_off_t __user *, offset, compat_size_t, count) +{ + loff_t pos; + off_t off; + ssize_t ret; + + if (offset) { + if (unlikely(get_user(off, offset))) + return -EFAULT; + pos = off; + ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS); + if (unlikely(put_user(pos, offset))) + return -EFAULT; + return ret; + } + + return do_sendfile(out_fd, in_fd, NULL, count, 0); +} + +COMPAT_SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd, + compat_loff_t __user *, offset, compat_size_t, count) +{ + loff_t pos; + ssize_t ret; + + if (offset) { + if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t)))) + return -EFAULT; + ret = do_sendfile(out_fd, in_fd, &pos, count, 0); + if (unlikely(put_user(pos, offset))) + return -EFAULT; + return ret; + } + + return do_sendfile(out_fd, in_fd, NULL, count, 0); +} +#endif + -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/