ocfs2: Read from an unwritten extent returns zeros
[powerpc.git] / fs / compat.c
index a7e3f16..040a8be 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/highmem.h>
 #include <linux/poll.h>
 #include <linux/mm.h>
+#include <linux/eventpoll.h>
 
 #include <net/sock.h>          /* siocdevprivate_ioctl */
 
@@ -232,7 +233,7 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user
        file = fget(fd);
        if (!file)
                goto out;
-       error = vfs_statfs(file->f_dentry, &tmp);
+       error = vfs_statfs(file->f_path.dentry, &tmp);
        if (!error)
                error = put_compat_statfs(buf, &tmp);
        fput(file);
@@ -303,7 +304,7 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c
        file = fget(fd);
        if (!file)
                goto out;
-       error = vfs_statfs(file->f_dentry, &tmp);
+       error = vfs_statfs(file->f_path.dentry, &tmp);
        if (!error)
                error = put_compat_statfs64(buf, &tmp);
        fput(file);
@@ -365,7 +366,7 @@ static void compat_ioctl_error(struct file *filp, unsigned int fd,
        /* find the name of the device. */
        path = (char *)__get_free_page(GFP_KERNEL);
        if (path) {
-               fn = d_path(filp->f_dentry, filp->f_vfsmnt, path, PAGE_SIZE);
+               fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE);
                if (IS_ERR(fn))
                        fn = "?";
        }
@@ -416,7 +417,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
        case FIBMAP:
        case FIGETBSZ:
        case FIONREAD:
-               if (S_ISREG(filp->f_dentry->d_inode->i_mode))
+               if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
                        break;
                /*FALL THROUGH*/
 
@@ -438,7 +439,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
                        goto found_handler;
        }
 
-       if (S_ISSOCK(filp->f_dentry->d_inode->i_mode) &&
+       if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) &&
            cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
                error = siocdevprivate_ioctl(fd, cmd, arg);
        } else {
@@ -1259,7 +1260,7 @@ out:
        if (iov != iovstack)
                kfree(iov);
        if ((ret + (type == READ)) > 0) {
-               struct dentry *dentry = file->f_dentry;
+               struct dentry *dentry = file->f_path.dentry;
                if (type == READ)
                        fsnotify_access(dentry);
                else
@@ -1679,19 +1680,19 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
 {
        fd_set_bits fds;
        char *bits;
-       int size, max_fdset, ret = -EINVAL;
+       int size, max_fds, ret = -EINVAL;
        struct fdtable *fdt;
 
        if (n < 0)
                goto out_nofds;
 
-       /* max_fdset can increase, so grab it once to avoid race */
+       /* max_fds can increase, so grab it once to avoid race */
        rcu_read_lock();
        fdt = files_fdtable(current->files);
-       max_fdset = fdt->max_fdset;
+       max_fds = fdt->max_fds;
        rcu_read_unlock();
-       if (n > max_fdset)
-               n = max_fdset;
+       if (n > max_fds)
+               n = max_fds;
 
        /*
         * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
@@ -2235,3 +2236,102 @@ long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2)
        return sys_ni_syscall();
 }
 #endif
+
+#ifdef CONFIG_EPOLL
+
+#ifdef CONFIG_HAS_COMPAT_EPOLL_EVENT
+asmlinkage long compat_sys_epoll_ctl(int epfd, int op, int fd,
+                       struct compat_epoll_event __user *event)
+{
+       long err = 0;
+       struct compat_epoll_event user;
+       struct epoll_event __user *kernel = NULL;
+
+       if (event) {
+               if (copy_from_user(&user, event, sizeof(user)))
+                       return -EFAULT;
+               kernel = compat_alloc_user_space(sizeof(struct epoll_event));
+               err |= __put_user(user.events, &kernel->events);
+               err |= __put_user(user.data, &kernel->data);
+       }
+
+       return err ? err : sys_epoll_ctl(epfd, op, fd, kernel);
+}
+
+
+asmlinkage long compat_sys_epoll_wait(int epfd,
+                       struct compat_epoll_event __user *events,
+                       int maxevents, int timeout)
+{
+       long i, ret, err = 0;
+       struct epoll_event __user *kbuf;
+       struct epoll_event ev;
+
+       if ((maxevents <= 0) ||
+                       (maxevents > (INT_MAX / sizeof(struct epoll_event))))
+               return -EINVAL;
+       kbuf = compat_alloc_user_space(sizeof(struct epoll_event) * maxevents);
+       ret = sys_epoll_wait(epfd, kbuf, maxevents, timeout);
+       for (i = 0; i < ret; i++) {
+               err |= __get_user(ev.events, &kbuf[i].events);
+               err |= __get_user(ev.data, &kbuf[i].data);
+               err |= __put_user(ev.events, &events->events);
+               err |= __put_user_unaligned(ev.data, &events->data);
+               events++;
+       }
+
+       return err ? -EFAULT: ret;
+}
+#endif /* CONFIG_HAS_COMPAT_EPOLL_EVENT */
+
+#ifdef TIF_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);
+       }
+
+#ifdef CONFIG_HAS_COMPAT_EPOLL_EVENT
+       err = compat_sys_epoll_wait(epfd, events, maxevents, timeout);
+#else
+       err = sys_epoll_wait(epfd, events, maxevents, timeout);
+#endif
+
+       /*
+        * 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_thread_flag(TIF_RESTORE_SIGMASK);
+               } else
+                       sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+       }
+
+       return err;
+}
+#endif /* TIF_RESTORE_SIGMASK */
+
+#endif /* CONFIG_EPOLL */