introduce FMODE_OPENED
[linux-block.git] / fs / open.c
index d0e955b558ad84ce2d6f98f6ccb490185bc36cc2..f3c6cb6a57b9c140d5ef8ab6c2f1d43916160012 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -736,15 +736,11 @@ int open_check_o_direct(struct file *f)
 
 static int do_dentry_open(struct file *f,
                          struct inode *inode,
-                         int (*open)(struct inode *, struct file *),
-                         const struct cred *cred)
+                         int (*open)(struct inode *, struct file *))
 {
        static const struct file_operations empty_fops = {};
        int error;
 
-       f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
-                               FMODE_PREAD | FMODE_PWRITE;
-
        path_get(&f->f_path);
        f->f_inode = inode;
        f->f_mapping = inode->i_mapping;
@@ -753,7 +749,7 @@ static int do_dentry_open(struct file *f,
        f->f_wb_err = filemap_sample_wb_err(f->f_mapping);
 
        if (unlikely(f->f_flags & O_PATH)) {
-               f->f_mode = FMODE_PATH;
+               f->f_mode = FMODE_PATH | FMODE_OPENED;
                f->f_op = &empty_fops;
                return 0;
        }
@@ -780,7 +776,7 @@ static int do_dentry_open(struct file *f,
                goto cleanup_all;
        }
 
-       error = security_file_open(f, cred);
+       error = security_file_open(f);
        if (error)
                goto cleanup_all;
 
@@ -788,6 +784,8 @@ static int do_dentry_open(struct file *f,
        if (error)
                goto cleanup_all;
 
+       /* normally all 3 are set; ->open() can clear them if needed */
+       f->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
        if (!open)
                open = f->f_op->open;
        if (open) {
@@ -795,6 +793,7 @@ static int do_dentry_open(struct file *f,
                if (error)
                        goto cleanup_all;
        }
+       f->f_mode |= FMODE_OPENED;
        if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
                i_readcount_inc(inode);
        if ((f->f_mode & FMODE_READ) &&
@@ -812,6 +811,8 @@ static int do_dentry_open(struct file *f,
        return 0;
 
 cleanup_all:
+       if (WARN_ON_ONCE(error > 0))
+               error = -EINVAL;
        fops_put(f->f_op);
        if (f->f_mode & FMODE_WRITER) {
                put_write_access(inode);
@@ -854,8 +855,7 @@ int finish_open(struct file *file, struct dentry *dentry,
        BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
 
        file->f_path.dentry = dentry;
-       error = do_dentry_open(file, d_backing_inode(dentry), open,
-                              current_cred());
+       error = do_dentry_open(file, d_backing_inode(dentry), open);
        if (!error)
                *opened |= FILE_OPENED;
 
@@ -896,8 +896,7 @@ EXPORT_SYMBOL(file_path);
  * @file: newly allocated file with f_flag initialized
  * @cred: credentials to use
  */
-int vfs_open(const struct path *path, struct file *file,
-            const struct cred *cred)
+int vfs_open(const struct path *path, struct file *file)
 {
        struct dentry *dentry = d_real(path->dentry, NULL, file->f_flags, 0);
 
@@ -905,7 +904,7 @@ int vfs_open(const struct path *path, struct file *file,
                return PTR_ERR(dentry);
 
        file->f_path = *path;
-       return do_dentry_open(file, d_backing_inode(dentry), NULL, cred);
+       return do_dentry_open(file, d_backing_inode(dentry), NULL);
 }
 
 struct file *dentry_open(const struct path *path, int flags,
@@ -919,10 +918,9 @@ struct file *dentry_open(const struct path *path, int flags,
        /* We must always pass in a valid mount pointer. */
        BUG_ON(!path->mnt);
 
-       f = get_empty_filp();
+       f = alloc_empty_file(flags, cred);
        if (!IS_ERR(f)) {
-               f->f_flags = flags;
-               error = vfs_open(path, f, cred);
+               error = vfs_open(path, f);
                if (!error) {
                        /* from now on we need fput() to dispose of f */
                        error = open_check_o_direct(f);
@@ -1063,26 +1061,6 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
 }
 EXPORT_SYMBOL(file_open_root);
 
-struct file *filp_clone_open(struct file *oldfile)
-{
-       struct file *file;
-       int retval;
-
-       file = get_empty_filp();
-       if (IS_ERR(file))
-               return file;
-
-       file->f_flags = oldfile->f_flags;
-       retval = vfs_open(&oldfile->f_path, file, oldfile->f_cred);
-       if (retval) {
-               put_filp(file);
-               return ERR_PTR(retval);
-       }
-
-       return file;
-}
-EXPORT_SYMBOL(filp_clone_open);
-
 long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
 {
        struct open_flags op;