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>
This commit is contained in:
Catalin Marinas
2012-09-19 12:01:52 +01:00
committed by Al Viro
parent 8c0a853770
commit 8f9c0119d7
10 changed files with 41 additions and 89 deletions

View File

@@ -143,48 +143,17 @@ long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t pt
* proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
* and the register representation of a signed int (msr in 64-bit mode) is performed.
*/
asmlinkage long compat_sys_sendfile(u32 out_fd, u32 in_fd, compat_off_t __user * offset, u32 count)
asmlinkage long compat_sys_sendfile_wrapper(u32 out_fd, u32 in_fd,
compat_off_t __user *offset, u32 count)
{
mm_segment_t old_fs = get_fs();
int ret;
off_t of;
off_t __user *up;
if (offset && get_user(of, offset))
return -EFAULT;
/* The __user pointer cast is valid because of the set_fs() */
set_fs(KERNEL_DS);
up = offset ? (off_t __user *) &of : NULL;
ret = sys_sendfile((int)out_fd, (int)in_fd, up, count);
set_fs(old_fs);
if (offset && put_user(of, offset))
return -EFAULT;
return ret;
return compat_sys_sendfile((int)out_fd, (int)in_fd, offset, count);
}
asmlinkage int compat_sys_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
asmlinkage long compat_sys_sendfile64_wrapper(u32 out_fd, u32 in_fd,
compat_loff_t __user *offset, u32 count)
{
mm_segment_t old_fs = get_fs();
int ret;
loff_t lof;
loff_t __user *up;
if (offset && get_user(lof, offset))
return -EFAULT;
/* The __user pointer cast is valid because of the set_fs() */
set_fs(KERNEL_DS);
up = offset ? (loff_t __user *) &lof : NULL;
ret = sys_sendfile64(out_fd, in_fd, up, count);
set_fs(old_fs);
if (offset && put_user(lof, offset))
return -EFAULT;
return ret;
return sys_sendfile((int)out_fd, (int)in_fd,
(off_t __user *)offset, count);
}
long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,