On Wed, Jun 14, 2023 at 10:49:06AM +0300, Amir Goldstein wrote: > 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 backing_file for those internal files, that > is used to hold the "fake" ovl path along with the real path. > > Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> > --- > fs/cachefiles/namei.c | 4 +-- > fs/file_table.c | 74 +++++++++++++++++++++++++++++++++++++------ > fs/internal.h | 5 +-- > fs/open.c | 30 +++++++++++------- > fs/overlayfs/file.c | 4 +-- > include/linux/fs.h | 24 +++++++++++--- > 6 files changed, 109 insertions(+), 32 deletions(-) > > diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c > index 82219a8f6084..283534c6bc8d 100644 > --- a/fs/cachefiles/namei.c > +++ b/fs/cachefiles/namei.c > @@ -560,8 +560,8 @@ 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); > + file = open_backing_file(&path, O_RDWR | O_LARGEFILE | O_DIRECT, > + &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..138d5d405df7 100644 > --- a/fs/file_table.c > +++ b/fs/file_table.c > @@ -44,18 +44,40 @@ static struct kmem_cache *filp_cachep __read_mostly; > > static struct percpu_counter nr_files __cacheline_aligned_in_smp; > > +/* Container for backing file with optional real path */ > +struct backing_file { > + struct file file; > + struct path real_path; > +}; > + > +static inline struct backing_file *backing_file(struct file *f) > +{ > + return container_of(f, struct backing_file, file); > +} > + > +struct path *backing_file_real_path(struct file *f) > +{ > + return &backing_file(f)->real_path; > +} > +EXPORT_SYMBOL_GPL(backing_file_real_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 (unlikely(f->f_mode & FMODE_BACKING)) > + kfree(backing_file(f)); > + else > + kmem_cache_free(filp_cachep, f); > } > > static inline void file_free(struct file *f) > { > security_file_free(f); > - if (!(f->f_mode & FMODE_NOACCOUNT)) > + if (unlikely(f->f_mode & FMODE_BACKING)) > + path_put(backing_file_real_path(f)); > + else > percpu_counter_dec(&nr_files); I think this needs to be: if (unlikely(f->f_mode & FMODE_BACKING)) path_put(backing_file_real_path(f)); if (likely(!(f->f_mode & FMODE_NOACCOUNT))) percpu_counter_dec(&nr_files); as we do have FMODE_NOACCOUNT without FMODE_BACKING. No need to resend though.