OSDN Git Service

powerpc/pseries: Allow not having ibm, hypertas-functions::hcall-multi-tce for DDW
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / fs / open.c
index b6f1e96..5ba3fca 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -363,6 +363,25 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
                                override_cred->cap_permitted;
        }
 
+       /*
+        * The new set of credentials can *only* be used in
+        * task-synchronous circumstances, and does not need
+        * RCU freeing, unless somebody then takes a separate
+        * reference to it.
+        *
+        * NOTE! This is _only_ true because this credential
+        * is used purely for override_creds() that installs
+        * it as the subjective cred. Other threads will be
+        * accessing ->real_cred, not the subjective cred.
+        *
+        * If somebody _does_ make a copy of this (using the
+        * 'get_current_cred()' function), that will clear the
+        * non_rcu field, because now that other user may be
+        * expecting RCU freeing. But normal thread-synchronous
+        * cred accesses will keep things non-RCY.
+        */
+       override_cred->non_rcu = 1;
+
        old_cred = override_creds(override_cred);
 retry:
        res = user_path_at(dfd, filename, lookup_flags, &path);
@@ -840,16 +859,12 @@ EXPORT_SYMBOL(file_path);
 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;
+       struct inode *inode = vfs_select_inode(path->dentry, file->f_flags);
 
-       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);
-       }
+       if (IS_ERR(inode))
+               return PTR_ERR(inode);
 
+       file->f_path = *path;
        return do_dentry_open(file, inode, NULL, cred);
 }
 
@@ -889,6 +904,12 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
        int lookup_flags = 0;
        int acc_mode;
 
+       /*
+        * Clear out all open flags we don't know about so that we don't report
+        * them in fcntl(F_GETFD) or similar interfaces.
+        */
+       flags &= VALID_OPEN_FLAGS;
+
        if (flags & (O_CREAT | __O_TMPFILE))
                op->mode = (mode & S_IALLUGO) | S_IFREG;
        else
@@ -995,14 +1016,12 @@ struct file *filp_open(const char *filename, int flags, umode_t mode)
 EXPORT_SYMBOL(filp_open);
 
 struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
-                           const char *filename, int flags)
+                           const char *filename, int flags, umode_t mode)
 {
        struct open_flags op;
-       int err = build_open_flags(flags, 0, &op);
+       int err = build_open_flags(flags, mode, &op);
        if (err)
                return ERR_PTR(err);
-       if (flags & O_CREAT)
-               return ERR_PTR(-EINVAL);
        return do_file_open_root(dentry, mnt, filename, &op);
 }
 EXPORT_SYMBOL(file_open_root);
@@ -1152,3 +1171,21 @@ int nonseekable_open(struct inode *inode, struct file *filp)
 }
 
 EXPORT_SYMBOL(nonseekable_open);
+
+/*
+ * stream_open is used by subsystems that want stream-like file descriptors.
+ * Such file descriptors are not seekable and don't have notion of position
+ * (file.f_pos is always 0). Contrary to file descriptors of other regular
+ * files, .read() and .write() can run simultaneously.
+ *
+ * stream_open never fails and is marked to return int so that it could be
+ * directly used as file_operations.open .
+ */
+int stream_open(struct inode *inode, struct file *filp)
+{
+       filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE | FMODE_ATOMIC_POS);
+       filp->f_mode |= FMODE_STREAM;
+       return 0;
+}
+
+EXPORT_SYMBOL(stream_open);