diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2012-09-19 07:01:52 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-02 21:35:55 -0400 |
commit | 8f9c0119d7ba94c3ad13876acc240d7f12b6d8e1 (patch) | |
tree | 44d618a21b60c5a268088bfae6c78c591f1e4334 /fs | |
parent | 8c0a85377048b64c880e76ec7368904fe46d0b94 (diff) |
compat: fs: Generic compat_sys_sendfile implementation
This function is used by sparc, powerpc and arm64 for compat support.
The patch adds a generic implementation which calls do_sendfile()
directly and avoids set_fs().
The sparc architecture has wrappers for the sign extensions while
powerpc relies on the compiler to do the this. The patch adds wrappers
for powerpc to handle the u32->int type conversion.
compat_sys_sendfile64() can be replaced by a sys_sendfile() call since
compat_loff_t has the same size as off_t on a 64-bit system.
On powerpc, the patch also changes the 64-bit sendfile call from
sys_sendile64 to sys_sendfile.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: David S. Miller <davem@davemloft.net>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/compat.c | 22 | ||||
-rw-r--r-- | fs/read_write.c | 4 | ||||
-rw-r--r-- | fs/read_write.h | 2 |
3 files changed, 26 insertions, 2 deletions
diff --git a/fs/compat.c b/fs/compat.c index d72d51e19025..b7a24d0ca30d 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1792,3 +1792,25 @@ compat_sys_open_by_handle_at(int mountdirfd, | |||
1792 | return do_handle_open(mountdirfd, handle, flags); | 1792 | return do_handle_open(mountdirfd, handle, flags); |
1793 | } | 1793 | } |
1794 | #endif | 1794 | #endif |
1795 | |||
1796 | #ifdef __ARCH_WANT_COMPAT_SYS_SENDFILE | ||
1797 | asmlinkage long compat_sys_sendfile(int out_fd, int in_fd, | ||
1798 | compat_off_t __user *offset, compat_size_t count) | ||
1799 | { | ||
1800 | loff_t pos; | ||
1801 | off_t off; | ||
1802 | ssize_t ret; | ||
1803 | |||
1804 | if (offset) { | ||
1805 | if (unlikely(get_user(off, offset))) | ||
1806 | return -EFAULT; | ||
1807 | pos = off; | ||
1808 | ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS); | ||
1809 | if (unlikely(put_user(pos, offset))) | ||
1810 | return -EFAULT; | ||
1811 | return ret; | ||
1812 | } | ||
1813 | |||
1814 | return do_sendfile(out_fd, in_fd, NULL, count, 0); | ||
1815 | } | ||
1816 | #endif /* __ARCH_WANT_COMPAT_SYS_SENDFILE */ | ||
diff --git a/fs/read_write.c b/fs/read_write.c index 28b38279a219..d06534857e9e 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -862,8 +862,8 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | |||
862 | return ret; | 862 | return ret; |
863 | } | 863 | } |
864 | 864 | ||
865 | static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | 865 | ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count, |
866 | size_t count, loff_t max) | 866 | loff_t max) |
867 | { | 867 | { |
868 | struct fd in, out; | 868 | struct fd in, out; |
869 | struct inode *in_inode, *out_inode; | 869 | struct inode *in_inode, *out_inode; |
diff --git a/fs/read_write.h b/fs/read_write.h index d07b954c6e0c..d3e00ef67420 100644 --- a/fs/read_write.h +++ b/fs/read_write.h | |||
@@ -12,3 +12,5 @@ ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov, | |||
12 | unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn); | 12 | unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn); |
13 | ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov, | 13 | ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov, |
14 | unsigned long nr_segs, loff_t *ppos, io_fn_t fn); | 14 | unsigned long nr_segs, loff_t *ppos, io_fn_t fn); |
15 | ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count, | ||
16 | loff_t max); | ||