arm: mm: Add v7_clean_kern_cache_louis
[linux-3.10.git] / fs / compat.c
index 0b48d01..fc3b55d 100644 (file)
 #include <linux/nfs4_mount.h>
 #include <linux/syscalls.h>
 #include <linux/ctype.h>
-#include <linux/module.h>
 #include <linux/dirent.h>
 #include <linux/fsnotify.h>
 #include <linux/highuid.h>
-#include <linux/nfsd/syscall.h>
 #include <linux/personality.h>
 #include <linux/rwsem.h>
 #include <linux/tsacct_kern.h>
 #include <linux/signal.h>
 #include <linux/poll.h>
 #include <linux/mm.h>
-#include <linux/eventpoll.h>
 #include <linux/fs_struct.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
+#include <linux/aio.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -70,8 +68,6 @@ int compat_printk(const char *fmt, ...)
        return ret;
 }
 
-#include "read_write.h"
-
 /*
  * Not all architectures have sys_utime, so implement this in terms
  * of sys_utimes.
@@ -132,41 +128,35 @@ asmlinkage long compat_sys_utimes(const char __user *filename, struct compat_tim
 
 static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
 {
-       compat_ino_t ino = stat->ino;
-       typeof(ubuf->st_uid) uid = 0;
-       typeof(ubuf->st_gid) gid = 0;
-       int err;
+       struct compat_stat tmp;
 
-       SET_UID(uid, stat->uid);
-       SET_GID(gid, stat->gid);
+       if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
+               return -EOVERFLOW;
 
-       if ((u64) stat->size > MAX_NON_LFS ||
-           !old_valid_dev(stat->dev) ||
-           !old_valid_dev(stat->rdev))
+       memset(&tmp, 0, sizeof(tmp));
+       tmp.st_dev = old_encode_dev(stat->dev);
+       tmp.st_ino = stat->ino;
+       if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
                return -EOVERFLOW;
-       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
+       tmp.st_mode = stat->mode;
+       tmp.st_nlink = stat->nlink;
+       if (tmp.st_nlink != stat->nlink)
                return -EOVERFLOW;
-
-       if (clear_user(ubuf, sizeof(*ubuf)))
-               return -EFAULT;
-
-       err  = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev);
-       err |= __put_user(ino, &ubuf->st_ino);
-       err |= __put_user(stat->mode, &ubuf->st_mode);
-       err |= __put_user(stat->nlink, &ubuf->st_nlink);
-       err |= __put_user(uid, &ubuf->st_uid);
-       err |= __put_user(gid, &ubuf->st_gid);
-       err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev);
-       err |= __put_user(stat->size, &ubuf->st_size);
-       err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime);
-       err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec);
-       err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime);
-       err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec);
-       err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime);
-       err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec);
-       err |= __put_user(stat->blksize, &ubuf->st_blksize);
-       err |= __put_user(stat->blocks, &ubuf->st_blocks);
-       return err;
+       SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
+       SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
+       tmp.st_rdev = old_encode_dev(stat->rdev);
+       if ((u64) stat->size > MAX_NON_LFS)
+               return -EOVERFLOW;
+       tmp.st_size = stat->size;
+       tmp.st_atime = stat->atime.tv_sec;
+       tmp.st_atime_nsec = stat->atime.tv_nsec;
+       tmp.st_mtime = stat->mtime.tv_sec;
+       tmp.st_mtime_nsec = stat->mtime.tv_nsec;
+       tmp.st_ctime = stat->ctime.tv_sec;
+       tmp.st_ctime_nsec = stat->ctime.tv_nsec;
+       tmp.st_blocks = stat->blocks;
+       tmp.st_blksize = stat->blksize;
+       return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
 asmlinkage long compat_sys_newstat(const char __user * filename,
@@ -247,11 +237,8 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
            __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
            __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
            __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
-           __put_user(0, &ubuf->f_spare[0]) || 
-           __put_user(0, &ubuf->f_spare[1]) || 
-           __put_user(0, &ubuf->f_spare[2]) || 
-           __put_user(0, &ubuf->f_spare[3]) || 
-           __put_user(0, &ubuf->f_spare[4]))
+           __put_user(kbuf->f_flags, &ubuf->f_flags) ||
+           __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare)))
                return -EFAULT;
        return 0;
 }
@@ -346,16 +333,9 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c
  */
 asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u)
 {
-       struct super_block *sb;
        struct compat_ustat tmp;
        struct kstatfs sbuf;
-       int err;
-
-       sb = user_get_super(new_decode_dev(dev));
-       if (!sb)
-               return -EINVAL;
-       err = statfs_by_dentry(sb->s_root, &sbuf);
-       drop_super(sb);
+       int err = vfs_ustat(new_decode_dev(dev), &sbuf);
        if (err)
                return err;
 
@@ -576,6 +556,10 @@ ssize_t compat_rw_copy_check_uvector(int type,
        }
        *ret_pointer = iov;
 
+       ret = -EFAULT;
+       if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
+               goto out;
+
        /*
         * Single unix specification:
         * We should -EINVAL if an element length is not >= 0 and fitting an
@@ -597,7 +581,8 @@ ssize_t compat_rw_copy_check_uvector(int type,
                }
                if (len < 0)    /* size_t not fitting in compat_ssize_t .. */
                        goto out;
-               if (!access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
+               if (type >= 0 &&
+                   !access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
                        ret = -EFAULT;
                        goto out;
                }
@@ -793,16 +778,16 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
        char *kernel_type;
        unsigned long data_page;
        char *kernel_dev;
-       char *dir_page;
+       struct filename *dir;
        int retval;
 
        retval = copy_mount_string(type, &kernel_type);
        if (retval < 0)
                goto out;
 
-       dir_page = getname(dir_name);
-       retval = PTR_ERR(dir_page);
-       if (IS_ERR(dir_page))
+       dir = getname(dir_name);
+       retval = PTR_ERR(dir);
+       if (IS_ERR(dir))
                goto out1;
 
        retval = copy_mount_string(dev_name, &kernel_dev);
@@ -824,7 +809,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
                }
        }
 
-       retval = do_mount(kernel_dev, dir_page, kernel_type,
+       retval = do_mount(kernel_dev, dir->name, kernel_type,
                        flags, (void*)data_page);
 
  out4:
@@ -832,7 +817,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
  out3:
        kfree(kernel_dev);
  out2:
-       putname(dir_page);
+       putname(dir);
  out1:
        kfree(kernel_type);
  out:
@@ -887,23 +872,20 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
        struct compat_old_linux_dirent __user *dirent, unsigned int count)
 {
        int error;
-       struct file *file;
+       struct fd f = fdget(fd);
        struct compat_readdir_callback buf;
 
-       error = -EBADF;
-       file = fget(fd);
-       if (!file)
-               goto out;
+       if (!f.file)
+               return -EBADF;
 
        buf.result = 0;
        buf.dirent = dirent;
 
-       error = vfs_readdir(file, compat_fillonedir, &buf);
+       error = vfs_readdir(f.file, compat_fillonedir, &buf);
        if (buf.result)
                error = buf.result;
 
-       fput(file);
-out:
+       fdput(f);
        return error;
 }
 
@@ -967,37 +949,34 @@ efault:
 asmlinkage long compat_sys_getdents(unsigned int fd,
                struct compat_linux_dirent __user *dirent, unsigned int count)
 {
-       struct file * file;
+       struct fd f;
        struct compat_linux_dirent __user * lastdirent;
        struct compat_getdents_callback buf;
        int error;
 
-       error = -EFAULT;
        if (!access_ok(VERIFY_WRITE, dirent, count))
-               goto out;
+               return -EFAULT;
 
-       error = -EBADF;
-       file = fget(fd);
-       if (!file)
-               goto out;
+       f = fdget(fd);
+       if (!f.file)
+               return -EBADF;
 
        buf.current_dir = dirent;
        buf.previous = NULL;
        buf.count = count;
        buf.error = 0;
 
-       error = vfs_readdir(file, compat_filldir, &buf);
+       error = vfs_readdir(f.file, compat_filldir, &buf);
        if (error >= 0)
                error = buf.error;
        lastdirent = buf.previous;
        if (lastdirent) {
-               if (put_user(file->f_pos, &lastdirent->d_off))
+               if (put_user(f.file->f_pos, &lastdirent->d_off))
                        error = -EFAULT;
                else
                        error = count - buf.count;
        }
-       fput(file);
-out:
+       fdput(f);
        return error;
 }
 
@@ -1055,243 +1034,44 @@ efault:
 asmlinkage long compat_sys_getdents64(unsigned int fd,
                struct linux_dirent64 __user * dirent, unsigned int count)
 {
-       struct file * file;
+       struct fd f;
        struct linux_dirent64 __user * lastdirent;
        struct compat_getdents_callback64 buf;
        int error;
 
-       error = -EFAULT;
        if (!access_ok(VERIFY_WRITE, dirent, count))
-               goto out;
+               return -EFAULT;
 
-       error = -EBADF;
-       file = fget(fd);
-       if (!file)
-               goto out;
+       f = fdget(fd);
+       if (!f.file)
+               return -EBADF;
 
        buf.current_dir = dirent;
        buf.previous = NULL;
        buf.count = count;
        buf.error = 0;
 
-       error = vfs_readdir(file, compat_filldir64, &buf);
+       error = vfs_readdir(f.file, compat_filldir64, &buf);
        if (error >= 0)
                error = buf.error;
        lastdirent = buf.previous;
        if (lastdirent) {
-               typeof(lastdirent->d_off) d_off = file->f_pos;
+               typeof(lastdirent->d_off) d_off = f.file->f_pos;
                if (__put_user_unaligned(d_off, &lastdirent->d_off))
                        error = -EFAULT;
                else
                        error = count - buf.count;
        }
-       fput(file);
-out:
+       fdput(f);
        return error;
 }
 #endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */
 
-static ssize_t compat_do_readv_writev(int type, struct file *file,
-                              const struct compat_iovec __user *uvector,
-                              unsigned long nr_segs, loff_t *pos)
-{
-       compat_ssize_t tot_len;
-       struct iovec iovstack[UIO_FASTIOV];
-       struct iovec *iov = iovstack;
-       ssize_t ret;
-       io_fn_t fn;
-       iov_fn_t fnv;
-
-       ret = -EINVAL;
-       if (!file->f_op)
-               goto out;
-
-       ret = -EFAULT;
-       if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
-               goto out;
-
-       tot_len = compat_rw_copy_check_uvector(type, uvector, nr_segs,
-                                              UIO_FASTIOV, iovstack, &iov);
-       if (tot_len == 0) {
-               ret = 0;
-               goto out;
-       }
-
-       ret = rw_verify_area(type, file, pos, tot_len);
-       if (ret < 0)
-               goto out;
-
-       fnv = NULL;
-       if (type == READ) {
-               fn = file->f_op->read;
-               fnv = file->f_op->aio_read;
-       } else {
-               fn = (io_fn_t)file->f_op->write;
-               fnv = file->f_op->aio_write;
-       }
-
-       if (fnv)
-               ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
-                                               pos, fnv);
-       else
-               ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
-
-out:
-       if (iov != iovstack)
-               kfree(iov);
-       if ((ret + (type == READ)) > 0) {
-               if (type == READ)
-                       fsnotify_access(file);
-               else
-                       fsnotify_modify(file);
-       }
-       return ret;
-}
-
-static size_t compat_readv(struct file *file,
-                          const struct compat_iovec __user *vec,
-                          unsigned long vlen, loff_t *pos)
-{
-       ssize_t ret = -EBADF;
-
-       if (!(file->f_mode & FMODE_READ))
-               goto out;
-
-       ret = -EINVAL;
-       if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
-               goto out;
-
-       ret = compat_do_readv_writev(READ, file, vec, vlen, pos);
-
-out:
-       if (ret > 0)
-               add_rchar(current, ret);
-       inc_syscr(current);
-       return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
-                unsigned long vlen)
-{
-       struct file *file;
-       int fput_needed;
-       ssize_t ret;
-
-       file = fget_light(fd, &fput_needed);
-       if (!file)
-               return -EBADF;
-       ret = compat_readv(file, vec, vlen, &file->f_pos);
-       fput_light(file, fput_needed);
-       return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec,
-                 unsigned long vlen, u32 pos_low, u32 pos_high)
-{
-       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
-       struct file *file;
-       int fput_needed;
-       ssize_t ret;
-
-       if (pos < 0)
-               return -EINVAL;
-       file = fget_light(fd, &fput_needed);
-       if (!file)
-               return -EBADF;
-       ret = -ESPIPE;
-       if (file->f_mode & FMODE_PREAD)
-               ret = compat_readv(file, vec, vlen, &pos);
-       fput_light(file, fput_needed);
-       return ret;
-}
-
-static size_t compat_writev(struct file *file,
-                           const struct compat_iovec __user *vec,
-                           unsigned long vlen, loff_t *pos)
-{
-       ssize_t ret = -EBADF;
-
-       if (!(file->f_mode & FMODE_WRITE))
-               goto out;
-
-       ret = -EINVAL;
-       if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
-               goto out;
-
-       ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos);
-
-out:
-       if (ret > 0)
-               add_wchar(current, ret);
-       inc_syscw(current);
-       return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec,
-                 unsigned long vlen)
-{
-       struct file *file;
-       int fput_needed;
-       ssize_t ret;
-
-       file = fget_light(fd, &fput_needed);
-       if (!file)
-               return -EBADF;
-       ret = compat_writev(file, vec, vlen, &file->f_pos);
-       fput_light(file, fput_needed);
-       return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec,
-                  unsigned long vlen, u32 pos_low, u32 pos_high)
-{
-       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
-       struct file *file;
-       int fput_needed;
-       ssize_t ret;
-
-       if (pos < 0)
-               return -EINVAL;
-       file = fget_light(fd, &fput_needed);
-       if (!file)
-               return -EBADF;
-       ret = -ESPIPE;
-       if (file->f_mode & FMODE_PWRITE)
-               ret = compat_writev(file, vec, vlen, &pos);
-       fput_light(file, fput_needed);
-       return ret;
-}
-
-asmlinkage long
-compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32,
-                   unsigned int nr_segs, unsigned int flags)
-{
-       unsigned i;
-       struct iovec __user *iov;
-       if (nr_segs > UIO_MAXIOV)
-               return -EINVAL;
-       iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
-       for (i = 0; i < nr_segs; i++) {
-               struct compat_iovec v;
-               if (get_user(v.iov_base, &iov32[i].iov_base) ||
-                   get_user(v.iov_len, &iov32[i].iov_len) ||
-                   put_user(compat_ptr(v.iov_base), &iov[i].iov_base) ||
-                   put_user(v.iov_len, &iov[i].iov_len))
-                       return -EFAULT;
-       }
-       return sys_vmsplice(fd, iov, nr_segs, flags);
-}
-
 /*
  * Exactly like fs/open.c:sys_open(), except that it doesn't set the
  * O_LARGEFILE flag.
  */
-asmlinkage long
-compat_sys_open(const char __user *filename, int flags, int mode)
+COMPAT_SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
 {
        return do_sys_open(AT_FDCWD, filename, flags, mode);
 }
@@ -1300,8 +1080,7 @@ compat_sys_open(const char __user *filename, int flags, int mode)
  * Exactly like fs/open.c:sys_openat(), except that it doesn't set the
  * O_LARGEFILE flag.
  */
-asmlinkage long
-compat_sys_openat(unsigned int dfd, const char __user *filename, int flags, int mode)
+COMPAT_SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, umode_t, mode)
 {
        return do_sys_open(dfd, filename, flags, mode);
 }
@@ -1550,7 +1329,6 @@ asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg)
                                 compat_ptr(a.exp), compat_ptr(a.tvp));
 }
 
-#ifdef HAVE_SET_RESTORE_SIGMASK
 static long do_compat_pselect(int n, compat_ulong_t __user *inp,
        compat_ulong_t __user *outp, compat_ulong_t __user *exp,
        struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
@@ -1673,142 +1451,14 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
 
        return ret;
 }
-#endif /* HAVE_SET_RESTORE_SIGMASK */
-
-long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2)
-{
-       return sys_ni_syscall();
-}
-
-#ifdef CONFIG_EPOLL
-
-#ifdef HAVE_SET_RESTORE_SIGMASK
-asmlinkage long compat_sys_epoll_pwait(int epfd,
-                       struct compat_epoll_event __user *events,
-                       int maxevents, int timeout,
-                       const compat_sigset_t __user *sigmask,
-                       compat_size_t sigsetsize)
-{
-       long err;
-       compat_sigset_t csigmask;
-       sigset_t ksigmask, sigsaved;
-
-       /*
-        * If the caller wants a certain signal mask to be set during the wait,
-        * we apply it here.
-        */
-       if (sigmask) {
-               if (sigsetsize != sizeof(compat_sigset_t))
-                       return -EINVAL;
-               if (copy_from_user(&csigmask, sigmask, sizeof(csigmask)))
-                       return -EFAULT;
-               sigset_from_compat(&ksigmask, &csigmask);
-               sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
-               sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
-       }
-
-       err = sys_epoll_wait(epfd, events, maxevents, timeout);
-
-       /*
-        * If we changed the signal mask, we need to restore the original one.
-        * In case we've got a signal while waiting, we do not restore the
-        * signal mask yet, and we allow do_signal() to deliver the signal on
-        * the way back to userspace, before the signal mask is restored.
-        */
-       if (sigmask) {
-               if (err == -EINTR) {
-                       memcpy(&current->saved_sigmask, &sigsaved,
-                              sizeof(sigsaved));
-                       set_restore_sigmask();
-               } else
-                       sigprocmask(SIG_SETMASK, &sigsaved, NULL);
-       }
-
-       return err;
-}
-#endif /* HAVE_SET_RESTORE_SIGMASK */
-
-#endif /* CONFIG_EPOLL */
-
-#ifdef CONFIG_SIGNALFD
-
-asmlinkage long compat_sys_signalfd4(int ufd,
-                                    const compat_sigset_t __user *sigmask,
-                                    compat_size_t sigsetsize, int flags)
-{
-       compat_sigset_t ss32;
-       sigset_t tmp;
-       sigset_t __user *ksigmask;
-
-       if (sigsetsize != sizeof(compat_sigset_t))
-               return -EINVAL;
-       if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
-               return -EFAULT;
-       sigset_from_compat(&tmp, &ss32);
-       ksigmask = compat_alloc_user_space(sizeof(sigset_t));
-       if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
-               return -EFAULT;
-
-       return sys_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags);
-}
-
-asmlinkage long compat_sys_signalfd(int ufd,
-                                   const compat_sigset_t __user *sigmask,
-                                   compat_size_t sigsetsize)
-{
-       return compat_sys_signalfd4(ufd, sigmask, sigsetsize, 0);
-}
-#endif /* CONFIG_SIGNALFD */
-
-#ifdef CONFIG_TIMERFD
-
-asmlinkage long compat_sys_timerfd_settime(int ufd, int flags,
-                                  const struct compat_itimerspec __user *utmr,
-                                  struct compat_itimerspec __user *otmr)
-{
-       int error;
-       struct itimerspec t;
-       struct itimerspec __user *ut;
-
-       if (get_compat_itimerspec(&t, utmr))
-               return -EFAULT;
-       ut = compat_alloc_user_space(2 * sizeof(struct itimerspec));
-       if (copy_to_user(&ut[0], &t, sizeof(t)))
-               return -EFAULT;
-       error = sys_timerfd_settime(ufd, flags, &ut[0], &ut[1]);
-       if (!error && otmr)
-               error = (copy_from_user(&t, &ut[1], sizeof(struct itimerspec)) ||
-                        put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0;
-
-       return error;
-}
-
-asmlinkage long compat_sys_timerfd_gettime(int ufd,
-                                  struct compat_itimerspec __user *otmr)
-{
-       int error;
-       struct itimerspec t;
-       struct itimerspec __user *ut;
-
-       ut = compat_alloc_user_space(sizeof(struct itimerspec));
-       error = sys_timerfd_gettime(ufd, ut);
-       if (!error)
-               error = (copy_from_user(&t, ut, sizeof(struct itimerspec)) ||
-                        put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0;
-
-       return error;
-}
-
-#endif /* CONFIG_TIMERFD */
 
 #ifdef CONFIG_FHANDLE
 /*
  * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
  * doesn't set the O_LARGEFILE flag.
  */
-asmlinkage long
-compat_sys_open_by_handle_at(int mountdirfd,
-                            struct file_handle __user *handle, int flags)
+COMPAT_SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
+                            struct file_handle __user *, handle, int, flags)
 {
        return do_handle_open(mountdirfd, handle, flags);
 }