From: Amir Goldstein <amir73il@gmail.com>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: Christian Brauner <brauner@kernel.org>,
Al Viro <viro@zeniv.linux.org.uk>, Jan Kara <jack@suse.cz>,
Paul Moore <paul@paul-moore.com>,
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>,
linux-fsdevel@vger.kernel.org, linux-unionfs@vger.kernel.org
Subject: [PATCH 1/3] fs: use fake_file container for internal files with fake f_path
Date: Fri, 9 Jun 2023 10:32:37 +0300 [thread overview]
Message-ID: <20230609073239.957184-2-amir73il@gmail.com> (raw)
In-Reply-To: <20230609073239.957184-1-amir73il@gmail.com>
Overlayfs and cachefiles use open_with_fake_path() to allocate internal
files, where overlayfs also puts a "fake" path in f_path - a path which
is not on the same fs as f_inode.
Allocate a container struct file_fake for those internal files, that
will be used to hold the fake path qlong with the real path.
This commit does not populate the extra fake_path field and leaves the
overlayfs internal file's f_path fake.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
fs/cachefiles/namei.c | 2 +-
fs/file_table.c | 85 +++++++++++++++++++++++++++++++++++--------
fs/internal.h | 5 ++-
fs/namei.c | 2 +-
fs/open.c | 11 +++---
fs/overlayfs/file.c | 2 +-
include/linux/fs.h | 13 ++++---
7 files changed, 90 insertions(+), 30 deletions(-)
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 82219a8f6084..a71bdf2d03ba 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -561,7 +561,7 @@ static bool cachefiles_open_file(struct cachefiles_object *object,
path.mnt = cache->mnt;
path.dentry = dentry;
file = open_with_fake_path(&path, O_RDWR | O_LARGEFILE | O_DIRECT,
- d_backing_inode(dentry), cache->cache_cred);
+ &path, cache->cache_cred);
if (IS_ERR(file)) {
trace_cachefiles_vfs_error(object, d_backing_inode(dentry),
PTR_ERR(file),
diff --git a/fs/file_table.c b/fs/file_table.c
index 372653b92617..adc2a92faa52 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -44,18 +44,48 @@ static struct kmem_cache *filp_cachep __read_mostly;
static struct percpu_counter nr_files __cacheline_aligned_in_smp;
+/* Container for file with optional fake path to display in /proc files */
+struct file_fake {
+ struct file file;
+ struct path fake_path;
+};
+
+static inline struct file_fake *file_fake(struct file *f)
+{
+ return container_of(f, struct file_fake, file);
+}
+
+/* Returns fake_path if one exists, f_path otherwise */
+const struct path *file_fake_path(struct file *f)
+{
+ struct file_fake *ff = file_fake(f);
+
+ if (!(f->f_mode & FMODE_FAKE_PATH) || !ff->fake_path.dentry)
+ return &f->f_path;
+
+ return &ff->fake_path;
+}
+EXPORT_SYMBOL(file_fake_path);
+
static void file_free_rcu(struct rcu_head *head)
{
struct file *f = container_of(head, struct file, f_rcuhead);
put_cred(f->f_cred);
- kmem_cache_free(filp_cachep, f);
+ if (f->f_mode & FMODE_FAKE_PATH)
+ kfree(file_fake(f));
+ else
+ kmem_cache_free(filp_cachep, f);
}
static inline void file_free(struct file *f)
{
+ struct file_fake *ff = file_fake(f);
+
security_file_free(f);
- if (!(f->f_mode & FMODE_NOACCOUNT))
+ if (f->f_mode & FMODE_FAKE_PATH)
+ path_put(&ff->fake_path);
+ else
percpu_counter_dec(&nr_files);
call_rcu(&f->f_rcuhead, file_free_rcu);
}
@@ -131,20 +161,15 @@ static int __init init_fs_stat_sysctls(void)
fs_initcall(init_fs_stat_sysctls);
#endif
-static struct file *__alloc_file(int flags, const struct cred *cred)
+static int init_file(struct file *f, int flags, const struct cred *cred)
{
- struct file *f;
int error;
- f = kmem_cache_zalloc(filp_cachep, GFP_KERNEL);
- if (unlikely(!f))
- return ERR_PTR(-ENOMEM);
-
f->f_cred = get_cred(cred);
error = security_file_alloc(f);
if (unlikely(error)) {
file_free_rcu(&f->f_rcuhead);
- return ERR_PTR(error);
+ return error;
}
atomic_long_set(&f->f_count, 1);
@@ -155,6 +180,22 @@ static struct file *__alloc_file(int flags, const struct cred *cred)
f->f_mode = OPEN_FMODE(flags);
/* f->f_version: 0 */
+ return 0;
+}
+
+static struct file *__alloc_file(int flags, const struct cred *cred)
+{
+ struct file *f;
+ int error;
+
+ f = kmem_cache_zalloc(filp_cachep, GFP_KERNEL);
+ if (unlikely(!f))
+ return ERR_PTR(-ENOMEM);
+
+ error = init_file(f, flags, cred);
+ if (unlikely(error))
+ return ERR_PTR(error);
+
return f;
}
@@ -201,18 +242,32 @@ struct file *alloc_empty_file(int flags, const struct cred *cred)
}
/*
- * Variant of alloc_empty_file() that doesn't check and modify nr_files.
+ * Variant of alloc_empty_file() that allocates a file_fake container
+ * and doesn't check and modify nr_files.
*
* Should not be used unless there's a very good reason to do so.
*/
-struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred)
+struct file *alloc_empty_file_fake(const struct path *fake_path, int flags,
+ const struct cred *cred)
{
- struct file *f = __alloc_file(flags, cred);
+ struct file_fake *ff;
+ int error;
- if (!IS_ERR(f))
- f->f_mode |= FMODE_NOACCOUNT;
+ ff = kzalloc(sizeof(struct file_fake), GFP_KERNEL);
+ if (unlikely(!ff))
+ return ERR_PTR(-ENOMEM);
- return f;
+ error = init_file(&ff->file, flags, cred);
+ if (unlikely(error))
+ return ERR_PTR(error);
+
+ ff->file.f_mode |= FMODE_FAKE_PATH;
+ if (fake_path) {
+ path_get(fake_path);
+ ff->fake_path = *fake_path;
+ }
+
+ return &ff->file;
}
/**
diff --git a/fs/internal.h b/fs/internal.h
index bd3b2810a36b..8890c694745b 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -97,8 +97,9 @@ extern void chroot_fs_refs(const struct path *, const struct path *);
/*
* file_table.c
*/
-extern struct file *alloc_empty_file(int, const struct cred *);
-extern struct file *alloc_empty_file_noaccount(int, const struct cred *);
+extern struct file *alloc_empty_file(int flags, const struct cred *cred);
+extern struct file *alloc_empty_file_fake(const struct path *fake_path,
+ int flags, const struct cred *cred);
static inline void put_file_access(struct file *file)
{
diff --git a/fs/namei.c b/fs/namei.c
index e4fe0879ae55..5e6de1f29f4e 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3721,7 +3721,7 @@ struct file *vfs_tmpfile_open(struct mnt_idmap *idmap,
struct file *file;
int error;
- file = alloc_empty_file_noaccount(open_flag, cred);
+ file = alloc_empty_file_fake(NULL, open_flag, cred);
if (!IS_ERR(file)) {
error = vfs_tmpfile(idmap, parentpath, file, mode);
if (error) {
diff --git a/fs/open.c b/fs/open.c
index 4478adcc4f3a..c9e2300a037d 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1116,15 +1116,16 @@ struct file *dentry_create(const struct path *path, int flags, umode_t mode,
}
EXPORT_SYMBOL(dentry_create);
-struct file *open_with_fake_path(const struct path *path, int flags,
- struct inode *inode, const struct cred *cred)
+struct file *open_with_fake_path(const struct path *fake_path, int flags,
+ const struct path *path,
+ const struct cred *cred)
{
- struct file *f = alloc_empty_file_noaccount(flags, cred);
+ struct file *f = alloc_empty_file_fake(NULL, flags, cred);
if (!IS_ERR(f)) {
int error;
- f->f_path = *path;
- error = do_dentry_open(f, inode, NULL);
+ f->f_path = *fake_path;
+ error = do_dentry_open(f, d_inode(path->dentry), NULL);
if (error) {
fput(f);
f = ERR_PTR(error);
diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
index 7c04f033aadd..f5987377e9eb 100644
--- a/fs/overlayfs/file.c
+++ b/fs/overlayfs/file.c
@@ -61,7 +61,7 @@ static struct file *ovl_open_realfile(const struct file *file,
if (!inode_owner_or_capable(real_idmap, realinode))
flags &= ~O_NOATIME;
- realfile = open_with_fake_path(&file->f_path, flags, realinode,
+ realfile = open_with_fake_path(&file->f_path, flags, realpath,
current_cred());
}
revert_creds(old_cred);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 21a981680856..b112a3c9b499 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -180,8 +180,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
/* File represents mount that needs unmounting */
#define FMODE_NEED_UNMOUNT ((__force fmode_t)0x10000000)
-/* File does not contribute to nr_files count */
-#define FMODE_NOACCOUNT ((__force fmode_t)0x20000000)
+/* File is embedded in file_fake and doesn't contribute to nr_files */
+#define FMODE_FAKE_PATH ((__force fmode_t)0x20000000)
/* File supports async buffered reads */
#define FMODE_BUF_RASYNC ((__force fmode_t)0x40000000)
@@ -2349,11 +2349,14 @@ static inline struct file *file_open_root_mnt(struct vfsmount *mnt,
return file_open_root(&(struct path){.mnt = mnt, .dentry = mnt->mnt_root},
name, flags, mode);
}
-extern struct file * dentry_open(const struct path *, int, const struct cred *);
+extern struct file *dentry_open(const struct path *path, int flags,
+ const struct cred *creds);
extern struct file *dentry_create(const struct path *path, int flags,
umode_t mode, const struct cred *cred);
-extern struct file * open_with_fake_path(const struct path *, int,
- struct inode*, const struct cred *);
+extern struct file *open_with_fake_path(const struct path *fake_path, int flags,
+ const struct path *path,
+ const struct cred *cred);
+extern const struct path *file_fake_path(struct file *file);
static inline struct file *file_clone_open(struct file *file)
{
return dentry_open(&file->f_path, file->f_flags, file->f_cred);
--
2.34.1
next prev parent reply other threads:[~2023-06-09 7:34 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-09 7:32 [PATCH 0/3] Reduce impact of overlayfs fake path files Amir Goldstein
2023-06-09 7:32 ` Amir Goldstein [this message]
2023-06-09 11:32 ` [PATCH 1/3] fs: use fake_file container for internal files with fake f_path Christian Brauner
2023-06-09 11:57 ` Amir Goldstein
2023-06-09 12:12 ` Christian Brauner
2023-06-09 12:20 ` Amir Goldstein
2023-06-09 12:54 ` Christian Brauner
2023-06-09 13:00 ` Christian Brauner
2023-06-09 13:09 ` Amir Goldstein
2023-06-11 19:11 ` Amir Goldstein
2023-06-12 7:55 ` Christian Brauner
2023-06-09 7:32 ` [PATCH 2/3] fs: use file_fake_path() to get path of mapped files for display Amir Goldstein
2023-06-09 8:19 ` Miklos Szeredi
2023-06-09 7:32 ` [PATCH 3/3] fs: store fake path in file_fake along with real path Amir Goldstein
2023-06-09 11:12 ` Christian Brauner
2023-06-09 11:30 ` Amir Goldstein
2023-06-09 13:15 ` [PATCH 0/3] Reduce impact of overlayfs fake path files Miklos Szeredi
2023-06-09 14:28 ` Amir Goldstein
2023-06-09 14:42 ` Amir Goldstein
2023-06-09 15:00 ` Miklos Szeredi
2023-06-09 19:17 ` Amir Goldstein
2023-06-12 7:57 ` Christian Brauner
2023-10-02 15:32 ` Amir Goldstein
2023-10-04 15:29 ` Amir Goldstein
2023-06-09 15:27 ` Mimi Zohar
2023-06-09 13:15 ` Tetsuo Handa
2023-06-09 13:54 ` Amir Goldstein
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=20230609073239.957184-2-amir73il@gmail.com \
--to=amir73il@gmail.com \
--cc=brauner@kernel.org \
--cc=jack@suse.cz \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-unionfs@vger.kernel.org \
--cc=miklos@szeredi.hu \
--cc=paul@paul-moore.com \
--cc=penguin-kernel@I-love.SAKURA.ne.jp \
--cc=viro@zeniv.linux.org.uk \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).