summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/namei.c41
-rw-r--r--include/linux/fs.h4
2 files changed, 45 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 53b4bc094db2..81c388a813d3 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3624,6 +3624,47 @@ out_err:
}
EXPORT_SYMBOL(vfs_tmpfile);
+/**
+ * vfs_tmpfile_open - open a tmpfile for kernel internal use
+ * @mnt_userns: user namespace of the mount the inode was found from
+ * @parentpath: path of the base directory
+ * @mode: mode of the new tmpfile
+ * @open_flag: flags
+ * @cred: credentials for open
+ *
+ * Create and open a temporary file. The file is not accounted in nr_files,
+ * hence this is only for kernel internal use, and must not be installed into
+ * file tables or such.
+ */
+struct file *vfs_tmpfile_open(struct user_namespace *mnt_userns,
+ const struct path *parentpath,
+ umode_t mode, int open_flag, const struct cred *cred)
+{
+ struct file *file;
+ int error;
+ struct path path = { .mnt = parentpath->mnt };
+
+ path.dentry = vfs_tmpfile(mnt_userns, parentpath->dentry, mode, open_flag);
+ if (IS_ERR(path.dentry))
+ return ERR_CAST(path.dentry);
+
+ error = may_open(mnt_userns, &path, 0, open_flag);
+ file = ERR_PTR(error);
+ if (error)
+ goto out_dput;
+
+ /*
+ * This relies on the "noaccount" property of fake open, otherwise
+ * equivalent to dentry_open().
+ */
+ file = open_with_fake_path(&path, open_flag, d_inode(path.dentry), cred);
+out_dput:
+ dput(path.dentry);
+
+ return file;
+}
+EXPORT_SYMBOL(vfs_tmpfile_open);
+
static int do_tmpfile(struct nameidata *nd, unsigned flags,
const struct open_flags *op,
struct file *file)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9eced4cc286e..15fafda95dd3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2007,6 +2007,10 @@ static inline int vfs_whiteout(struct user_namespace *mnt_userns,
struct dentry *vfs_tmpfile(struct user_namespace *mnt_userns,
struct dentry *dentry, umode_t mode, int open_flag);
+struct file *vfs_tmpfile_open(struct user_namespace *mnt_userns,
+ const struct path *parentpath,
+ umode_t mode, int open_flag, const struct cred *cred);
+
int vfs_mkobj(struct dentry *, umode_t,
int (*f)(struct dentry *, umode_t, void *),
void *);