From: Miklos Szeredi <mszeredi@redhat.com>
To: linux-fsdevel@vger.kernel.org
Cc: Al Viro <viro@ZenIV.linux.org.uk>,
Amir Goldstein <amir73il@gmail.com>,
David Howells <dhowells@redhat.com>,
Yu-li Lin <yulilin@google.com>,
Chirantan Ekbote <chirantan@chromium.org>
Subject: [PATCH 6/8] vfs: move open right after ->tmpfile()
Date: Fri, 16 Sep 2022 21:44:14 +0200 [thread overview]
Message-ID: <20220916194416.1657716-6-mszeredi@redhat.com> (raw)
In-Reply-To: <20220916194416.1657716-1-mszeredi@redhat.com>
Create a helper finish_tmpfile() that opens a file after the tmpfile
creation is done. Call this helper right after ->tmpfile() is called.
Next patch will change the tmpfile API and move this call into tmpfile
instances.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
fs/namei.c | 65 ++++++++++++++++++++--------------------------
fs/open.c | 11 ++++++++
include/linux/fs.h | 1 +
3 files changed, 40 insertions(+), 37 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index eacaf9ccbaa6..22353853651b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3583,11 +3583,12 @@ static int do_open(struct nameidata *nd,
* On non-idmapped mounts or if permission checking is to be performed on the
* raw inode simply passs init_user_ns.
*/
-static struct dentry *vfs_tmpfile(struct user_namespace *mnt_userns,
- struct dentry *dentry, umode_t mode, int open_flag)
+static int vfs_tmpfile(struct user_namespace *mnt_userns,
+ const struct path *parentpath,
+ struct file *file, umode_t mode)
{
- struct dentry *child = NULL;
- struct inode *dir = dentry->d_inode;
+ struct dentry *child;
+ struct inode *dir = d_inode(parentpath->dentry);
struct inode *inode;
int error;
@@ -3599,28 +3600,34 @@ static struct dentry *vfs_tmpfile(struct user_namespace *mnt_userns,
if (!dir->i_op->tmpfile)
goto out_err;
error = -ENOMEM;
- child = d_alloc(dentry, &slash_name);
+ child = d_alloc(parentpath->dentry, &slash_name);
if (unlikely(!child))
goto out_err;
+ file->f_path.mnt = parentpath->mnt;
+ file->f_path.dentry = child;
mode = vfs_prepare_mode(mnt_userns, dir, mode, mode, mode);
error = dir->i_op->tmpfile(mnt_userns, dir, child, mode);
+ error = finish_tmpfile(file, error);
+ dput(child);
+ if (error)
+ goto out_err;
+ error = may_open(mnt_userns, &file->f_path, 0, file->f_flags);
if (error)
goto out_err;
error = -ENOENT;
inode = child->d_inode;
if (unlikely(!inode))
goto out_err;
- if (!(open_flag & O_EXCL)) {
+ if (!(file->f_flags & O_EXCL)) {
spin_lock(&inode->i_lock);
inode->i_state |= I_LINKABLE;
spin_unlock(&inode->i_lock);
}
ima_post_create_tmpfile(mnt_userns, inode);
- return child;
+ return 0;
out_err:
- dput(child);
- return ERR_PTR(error);
+ return error;
}
@@ -3642,25 +3649,15 @@ struct file *tmpfile_open(struct user_namespace *mnt_userns,
{
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);
+ file = alloc_empty_file_noaccount(open_flag, cred);
+ if (!IS_ERR(file)) {
+ error = vfs_tmpfile(mnt_userns, parentpath, file, mode);
+ if (error) {
+ fput(file);
+ file = ERR_PTR(error);
+ }
+ }
return file;
}
EXPORT_SYMBOL(tmpfile_open);
@@ -3671,26 +3668,20 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
struct file *file)
{
struct user_namespace *mnt_userns;
- struct dentry *child;
struct path path;
int error = path_lookupat(nd, flags | LOOKUP_DIRECTORY, &path);
+
if (unlikely(error))
return error;
error = mnt_want_write(path.mnt);
if (unlikely(error))
goto out;
mnt_userns = mnt_user_ns(path.mnt);
- child = vfs_tmpfile(mnt_userns, path.dentry, op->mode, op->open_flag);
- error = PTR_ERR(child);
- if (IS_ERR(child))
+ error = vfs_tmpfile(mnt_userns, &path, file, op->mode);
+ if (error)
goto out2;
- dput(path.dentry);
- path.dentry = child;
- audit_inode(nd->name, child, 0);
+ audit_inode(nd->name, file->f_path.dentry, 0);
/* Don't check for other permissions, the inode was just created */
- error = may_open(mnt_userns, &path, 0, op->open_flag);
- if (!error)
- error = vfs_open(&path, file);
out2:
mnt_drop_write(path.mnt);
out:
diff --git a/fs/open.c b/fs/open.c
index 8a813fa5ca56..90ff9d4c0d81 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -975,6 +975,17 @@ int finish_open(struct file *file, struct dentry *dentry,
}
EXPORT_SYMBOL(finish_open);
+int finish_tmpfile(struct file *file, int error)
+{
+ WARN_ON(file->f_mode & FMODE_OPENED);
+
+ if (error)
+ return error;
+
+ return do_dentry_open(file, d_inode(file->f_path.dentry), NULL);
+}
+EXPORT_SYMBOL(finish_tmpfile);
+
/**
* finish_no_open - finish ->atomic_open() without opening the file
*
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a445da4842e0..8d0e11ba930c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2778,6 +2778,7 @@ extern void putname(struct filename *name);
extern int finish_open(struct file *file, struct dentry *dentry,
int (*open)(struct inode *, struct file *));
+extern int finish_tmpfile(struct file *file, int error);
extern int finish_no_open(struct file *file, struct dentry *dentry);
/* fs/dcache.c */
--
2.37.3
next prev parent reply other threads:[~2022-09-16 19:44 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-16 19:44 [PATCH 1/8] cachefiles: tmpfile error handling cleanup Miklos Szeredi
2022-09-16 19:44 ` [PATCH 2/8] vfs: add tmpfile_open() helper Miklos Szeredi
2022-09-16 19:44 ` [PATCH 3/8] cachefiles: use " Miklos Szeredi
2022-09-16 19:44 ` [PATCH 4/8] ovl: " Miklos Szeredi
2022-09-16 19:44 ` [PATCH 5/8] vfs: make vfs_tmpfile() static Miklos Szeredi
2022-09-16 19:44 ` Miklos Szeredi [this message]
2022-09-16 19:44 ` [PATCH 7/8] vfs: open inside ->tmpfile() Miklos Szeredi
2022-09-16 22:04 ` kernel test robot
2022-09-17 1:28 ` kernel test robot
2022-09-17 1:49 ` kernel test robot
2022-09-16 19:44 ` [PATCH 8/8] fuse: implement ->tmpfile() Miklos Szeredi
2022-09-16 21:52 ` Bernd Schubert
2022-09-19 6:30 ` Miklos Szeredi
2022-09-19 7:16 ` Bernd Schubert
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220916194416.1657716-6-mszeredi@redhat.com \
--to=mszeredi@redhat.com \
--cc=amir73il@gmail.com \
--cc=chirantan@chromium.org \
--cc=dhowells@redhat.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=viro@ZenIV.linux.org.uk \
--cc=yulilin@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.