Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / fs / open.c
index 3cac0bd..5720854 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -446,78 +446,56 @@ out:
        return error;
 }
 
-SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
+static int chmod_common(struct path *path, umode_t mode)
 {
-       struct inode * inode;
-       struct dentry * dentry;
-       struct file * file;
-       int err = -EBADF;
+       struct inode *inode = path->dentry->d_inode;
        struct iattr newattrs;
+       int error;
 
-       file = fget(fd);
-       if (!file)
-               goto out;
-
-       dentry = file->f_path.dentry;
-       inode = dentry->d_inode;
-
-       audit_inode(NULL, dentry);
-
-       err = mnt_want_write_file(file);
-       if (err)
-               goto out_putf;
+       error = mnt_want_write(path->mnt);
+       if (error)
+               return error;
        mutex_lock(&inode->i_mutex);
-       err = security_path_chmod(dentry, file->f_vfsmnt, mode);
-       if (err)
+       error = security_path_chmod(path, mode);
+       if (error)
                goto out_unlock;
-       if (mode == (mode_t) -1)
-               mode = inode->i_mode;
        newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-       err = notify_change(dentry, &newattrs);
+       error = notify_change(path->dentry, &newattrs);
 out_unlock:
        mutex_unlock(&inode->i_mutex);
-       mnt_drop_write(file->f_path.mnt);
-out_putf:
-       fput(file);
-out:
+       mnt_drop_write(path->mnt);
+       return error;
+}
+
+SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
+{
+       struct file * file;
+       int err = -EBADF;
+
+       file = fget(fd);
+       if (file) {
+               audit_inode(NULL, file->f_path.dentry);
+               err = chmod_common(&file->f_path, mode);
+               fput(file);
+       }
        return err;
 }
 
-SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode)
+SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode)
 {
        struct path path;
-       struct inode *inode;
        int error;
-       struct iattr newattrs;
 
        error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
-       if (error)
-               goto out;
-       inode = path.dentry->d_inode;
-
-       error = mnt_want_write(path.mnt);
-       if (error)
-               goto dput_and_out;
-       mutex_lock(&inode->i_mutex);
-       error = security_path_chmod(path.dentry, path.mnt, mode);
-       if (error)
-               goto out_unlock;
-       if (mode == (mode_t) -1)
-               mode = inode->i_mode;
-       newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
-       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-       error = notify_change(path.dentry, &newattrs);
-out_unlock:
-       mutex_unlock(&inode->i_mutex);
-       mnt_drop_write(path.mnt);
-dput_and_out:
-       path_put(&path);
-out:
+       if (!error) {
+               error = chmod_common(&path, mode);
+               path_put(&path);
+       }
        return error;
 }
 
-SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode)
+SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
 {
        return sys_fchmodat(AT_FDCWD, filename, mode);
 }
@@ -630,7 +608,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
        dentry = file->f_path.dentry;
        audit_inode(NULL, dentry);
        error = chown_common(&file->f_path, user, group);
-       mnt_drop_write(file->f_path.mnt);
+       mnt_drop_write_file(file);
 out_fput:
        fput(file);
 out:
@@ -707,6 +685,10 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
        if (error)
                goto cleanup_all;
 
+       error = break_lease(inode, f->f_flags);
+       if (error)
+               goto cleanup_all;
+
        if (!open && f->f_op)
                open = f->f_op->open;
        if (open) {
@@ -714,7 +696,8 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
                if (error)
                        goto cleanup_all;
        }
-       ima_counts_get(f);
+       if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+               i_readcount_inc(inode);
 
        f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 
@@ -792,7 +775,7 @@ out:
        return nd->intent.open.file;
 out_err:
        release_open_intent(nd);
-       nd->intent.open.file = (struct file *)dentry;
+       nd->intent.open.file = ERR_CAST(dentry);
        goto out;
 }
 EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
@@ -834,17 +817,8 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
 
        validate_creds(cred);
 
-       /*
-        * We must always pass in a valid mount pointer.   Historically
-        * callers got away with not passing it, but we must enforce this at
-        * the earliest possible point now to avoid strange problems deep in the
-        * filesystem stack.
-        */
-       if (!mnt) {
-               printk(KERN_WARNING "%s called with NULL vfsmount\n", __func__);
-               dump_stack();
-               return ERR_PTR(-EINVAL);
-       }
+       /* We must always pass in a valid mount pointer. */
+       BUG_ON(!mnt);
 
        error = -ENFILE;
        f = get_empty_filp();
@@ -862,7 +836,7 @@ EXPORT_SYMBOL(dentry_open);
 static void __put_unused_fd(struct files_struct *files, unsigned int fd)
 {
        struct fdtable *fdt = files_fdtable(files);
-       __FD_CLR(fd, fdt->open_fds);
+       __clear_open_fd(fd, fdt);
        if (fd < files->next_fd)
                files->next_fd = fd;
 }
@@ -903,7 +877,7 @@ void fd_install(unsigned int fd, struct file *file)
 
 EXPORT_SYMBOL(fd_install);
 
-static inline int build_open_flags(int flags, int mode, struct open_flags *op)
+static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
 {
        int lookup_flags = 0;
        int acc_mode;
@@ -974,7 +948,7 @@ static inline int build_open_flags(int flags, int mode, struct open_flags *op)
  * have to.  But in generally you should not do this, so please move
  * along, nothing to see here..
  */
-struct file *filp_open(const char *filename, int flags, int mode)
+struct file *filp_open(const char *filename, int flags, umode_t mode)
 {
        struct open_flags op;
        int lookup = build_open_flags(flags, mode, &op);
@@ -996,7 +970,7 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
 }
 EXPORT_SYMBOL(file_open_root);
 
-long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
+long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
 {
        struct open_flags op;
        int lookup = build_open_flags(flags, mode, &op);
@@ -1020,7 +994,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
        return fd;
 }
 
-SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)
+SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
 {
        long ret;
 
@@ -1034,7 +1008,7 @@ SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)
 }
 
 SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags,
-               int, mode)
+               umode_t, mode)
 {
        long ret;
 
@@ -1053,7 +1027,7 @@ SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags,
  * For backward compatibility?  Maybe this should be moved
  * into arch/i386 instead?
  */
-SYSCALL_DEFINE2(creat, const char __user *, pathname, int, mode)
+SYSCALL_DEFINE2(creat, const char __user *, pathname, umode_t, mode)
 {
        return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
 }
@@ -1106,7 +1080,7 @@ SYSCALL_DEFINE1(close, unsigned int, fd)
        if (!filp)
                goto out_unlock;
        rcu_assign_pointer(fdt->fd[fd], NULL);
-       FD_CLR(fd, fdt->close_on_exec);
+       __clear_close_on_exec(fd, fdt);
        __put_unused_fd(files, fd);
        spin_unlock(&files->file_lock);
        retval = filp_close(filp, files);