fs: Provide function telling whether file_remove_privs() will do anything
[linux-block.git] / fs / open.c
index 6796f04d6032ab7e3009d3666bde640fdec37934..1dbc79358d591833efa7409b946b0c9945d1b289 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -231,8 +231,7 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
                return -EINVAL;
 
        /* Return error if mode is not supported */
-       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
-                    FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE))
+       if (mode & ~FALLOC_FL_SUPPORTED_MASK)
                return -EOPNOTSUPP;
 
        /* Punch hole and zero range are mutually exclusive */
@@ -250,6 +249,11 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
            (mode & ~FALLOC_FL_COLLAPSE_RANGE))
                return -EINVAL;
 
+       /* Insert range should only be used exclusively. */
+       if ((mode & FALLOC_FL_INSERT_RANGE) &&
+           (mode & ~FALLOC_FL_INSERT_RANGE))
+               return -EINVAL;
+
        if (!(file->f_mode & FMODE_WRITE))
                return -EBADF;
 
@@ -363,7 +367,7 @@ retry:
        if (res)
                goto out;
 
-       inode = path.dentry->d_inode;
+       inode = d_backing_inode(path.dentry);
 
        if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {
                /*
@@ -674,18 +678,18 @@ 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)
 {
        static const struct file_operations empty_fops = {};
-       struct inode *inode;
        int error;
 
        f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
                                FMODE_PREAD | FMODE_PWRITE;
 
        path_get(&f->f_path);
-       inode = f->f_inode = f->f_path.dentry->d_inode;
+       f->f_inode = inode;
        f->f_mapping = inode->i_mapping;
 
        if (unlikely(f->f_flags & O_PATH)) {
@@ -789,7 +793,8 @@ 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, open, current_cred());
+       error = do_dentry_open(file, d_backing_inode(dentry), open,
+                              current_cred());
        if (!error)
                *opened |= FILE_OPENED;
 
@@ -818,6 +823,34 @@ int finish_no_open(struct file *file, struct dentry *dentry)
 }
 EXPORT_SYMBOL(finish_no_open);
 
+char *file_path(struct file *filp, char *buf, int buflen)
+{
+       return d_path(&filp->f_path, buf, buflen);
+}
+EXPORT_SYMBOL(file_path);
+
+/**
+ * vfs_open - open the file at the given path
+ * @path: path to open
+ * @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)
+{
+       struct dentry *dentry = path->dentry;
+       struct inode *inode = dentry->d_inode;
+
+       file->f_path = *path;
+       if (dentry->d_flags & DCACHE_OP_SELECT_INODE) {
+               inode = dentry->d_op->d_select_inode(dentry, file->f_flags);
+               if (IS_ERR(inode))
+                       return PTR_ERR(inode);
+       }
+
+       return do_dentry_open(file, inode, NULL, cred);
+}
+
 struct file *dentry_open(const struct path *path, int flags,
                         const struct cred *cred)
 {
@@ -849,26 +882,6 @@ struct file *dentry_open(const struct path *path, int flags,
 }
 EXPORT_SYMBOL(dentry_open);
 
-/**
- * vfs_open - open the file at the given path
- * @path: path to open
- * @filp: newly allocated file with f_flag initialized
- * @cred: credentials to use
- */
-int vfs_open(const struct path *path, struct file *filp,
-            const struct cred *cred)
-{
-       struct inode *inode = path->dentry->d_inode;
-
-       if (inode->i_op->dentry_open)
-               return inode->i_op->dentry_open(path->dentry, filp, cred);
-       else {
-               filp->f_path = *path;
-               return do_dentry_open(filp, NULL, cred);
-       }
-}
-EXPORT_SYMBOL(vfs_open);
-
 static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
 {
        int lookup_flags = 0;