On Sat, 2023-04-08 at 19:42 +0300, Amir Goldstein wrote: > In preparation for moving lowerstack into ovl_inode. > > Note that in ovl_lookup() the temp stack dentry refs are now cloned > into the final ovl_lowerstack instead of being transfered, so cleanup > always needs to call ovl_stack_free(stack). > > Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> Reviewed-by: Alexander Larsson <alexl@xxxxxxxxxx> > --- > fs/overlayfs/namei.c | 13 +++++-------- > fs/overlayfs/overlayfs.h | 5 +++++ > fs/overlayfs/ovl_entry.h | 2 -- > fs/overlayfs/super.c | 14 ++------------ > fs/overlayfs/util.c | 34 ++++++++++++++++++++++++++++++++++ > 5 files changed, 46 insertions(+), 22 deletions(-) > > diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c > index 31f889d27083..c237c8dbff09 100644 > --- a/fs/overlayfs/namei.c > +++ b/fs/overlayfs/namei.c > @@ -907,8 +907,7 @@ struct dentry *ovl_lookup(struct inode *dir, > struct dentry *dentry, > > if (!d.stop && ovl_numlower(poe)) { > err = -ENOMEM; > - stack = kcalloc(ofs->numlayer - 1, sizeof(struct > ovl_path), > - GFP_KERNEL); > + stack = ovl_stack_alloc(ofs->numlayer - 1); I realize this is not really related to your patch, but why is this using ofs->numlayer - 1, rather than ovl_numlower(poe)? The later is what we iterate over below, and is potentially smaller than numlayers. > if (!stack) > goto out_put_upper; > } > @@ -1073,7 +1072,7 @@ struct dentry *ovl_lookup(struct inode *dir, > struct dentry *dentry, > if (!oe) > goto out_put; > > - memcpy(ovl_lowerstack(oe), stack, sizeof(struct ovl_path) * > ctr); > + ovl_stack_cpy(ovl_lowerstack(oe), stack, ctr); > dentry->d_fsdata = oe; > > if (upperopaque) > @@ -1131,18 +1130,16 @@ struct dentry *ovl_lookup(struct inode *dir, > struct dentry *dentry, > kfree(origin_path); > } > dput(index); > - kfree(stack); > + ovl_stack_free(stack, ctr); > kfree(d.redirect); > return d_splice_alias(inode, dentry); > > out_free_oe: > dentry->d_fsdata = NULL; > - kfree(oe); > + ovl_free_entry(oe); > out_put: > dput(index); > - for (i = 0; i < ctr; i++) > - dput(stack[i].dentry); > - kfree(stack); > + ovl_stack_free(stack, ctr); > out_put_upper: > if (origin_path) { > dput(origin_path->dentry); > diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h > index e100c55bb924..6a50296fef8f 100644 > --- a/fs/overlayfs/overlayfs.h > +++ b/fs/overlayfs/overlayfs.h > @@ -373,7 +373,12 @@ int ovl_can_decode_fh(struct super_block *sb); > struct dentry *ovl_indexdir(struct super_block *sb); > bool ovl_index_all(struct super_block *sb); > bool ovl_verify_lower(struct super_block *sb); > +struct ovl_path *ovl_stack_alloc(unsigned int n); > +void ovl_stack_cpy(struct ovl_path *dst, struct ovl_path *src, > unsigned int n); > +void ovl_stack_put(struct ovl_path *stack, unsigned int n); > +void ovl_stack_free(struct ovl_path *stack, unsigned int n); > struct ovl_entry *ovl_alloc_entry(unsigned int numlower); > +void ovl_free_entry(struct ovl_entry *oe); > bool ovl_dentry_remote(struct dentry *dentry); > void ovl_dentry_update_reval(struct dentry *dentry, struct dentry > *realdentry); > void ovl_dentry_init_reval(struct dentry *dentry, struct dentry > *upperdentry); > diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h > index f456a99d6017..754f8ae4ce62 100644 > --- a/fs/overlayfs/ovl_entry.h > +++ b/fs/overlayfs/ovl_entry.h > @@ -127,8 +127,6 @@ static inline struct ovl_path > *ovl_lowerstack(struct ovl_entry *oe) > return oe ? oe->__lowerstack : NULL; > } > > -struct ovl_entry *ovl_alloc_entry(unsigned int numlower); > - > static inline struct ovl_entry *OVL_E(struct dentry *dentry) > { > return (struct ovl_entry *) dentry->d_fsdata; > diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c > index 89e9843bd2de..d8fe857bd7e1 100644 > --- a/fs/overlayfs/super.c > +++ b/fs/overlayfs/super.c > @@ -54,15 +54,6 @@ module_param_named(xino_auto, ovl_xino_auto_def, > bool, 0644); > MODULE_PARM_DESC(xino_auto, > "Auto enable xino feature"); > > -static void ovl_entry_stack_free(struct ovl_entry *oe) > -{ > - struct ovl_path *lowerstack = ovl_lowerstack(oe); > - unsigned int i; > - > - for (i = 0; i < ovl_numlower(oe); i++) > - dput(lowerstack[i].dentry); > -} > - > static bool ovl_metacopy_def = > IS_ENABLED(CONFIG_OVERLAY_FS_METACOPY); > module_param_named(metacopy, ovl_metacopy_def, bool, 0644); > MODULE_PARM_DESC(metacopy, > @@ -73,7 +64,7 @@ static void ovl_dentry_release(struct dentry > *dentry) > struct ovl_entry *oe = dentry->d_fsdata; > > if (oe) { > - ovl_entry_stack_free(oe); > + ovl_stack_put(ovl_lowerstack(oe), ovl_numlower(oe)); > kfree_rcu(oe, rcu); > } > } > @@ -2078,8 +2069,7 @@ static int ovl_fill_super(struct super_block > *sb, void *data, int silent) > return 0; > > out_free_oe: > - ovl_entry_stack_free(oe); > - kfree(oe); > + ovl_free_entry(oe); > out_err: > kfree(splitlower); > path_put(&upperpath); > diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c > index a139eb581093..1ba6dbea808c 100644 > --- a/fs/overlayfs/util.c > +++ b/fs/overlayfs/util.c > @@ -83,6 +83,34 @@ bool ovl_verify_lower(struct super_block *sb) > return ofs->config.nfs_export && ofs->config.index; > } > > +struct ovl_path *ovl_stack_alloc(unsigned int n) > +{ > + return kcalloc(n, sizeof(struct ovl_path), GFP_KERNEL); > +} > + > +void ovl_stack_cpy(struct ovl_path *dst, struct ovl_path *src, > unsigned int n) > +{ > + unsigned int i; > + > + memcpy(dst, src, sizeof(struct ovl_path) * n); > + for (i = 0; i < n; i++) > + dget(src[i].dentry); > +} > + > +void ovl_stack_put(struct ovl_path *stack, unsigned int n) > +{ > + unsigned int i; > + > + for (i = 0; stack && i < n; i++) > + dput(stack[i].dentry); > +} > + > +void ovl_stack_free(struct ovl_path *stack, unsigned int n) > +{ > + ovl_stack_put(stack, n); > + kfree(stack); > +} > + > struct ovl_entry *ovl_alloc_entry(unsigned int numlower) > { > size_t size = offsetof(struct ovl_entry, > __lowerstack[numlower]); > @@ -94,6 +122,12 @@ struct ovl_entry *ovl_alloc_entry(unsigned int > numlower) > return oe; > } > > +void ovl_free_entry(struct ovl_entry *oe) > +{ > + ovl_stack_put(ovl_lowerstack(oe), ovl_numlower(oe)); > + kfree(oe); > +} > + > #define OVL_D_REVALIDATE (DCACHE_OP_REVALIDATE | > DCACHE_OP_WEAK_REVALIDATE) > > bool ovl_dentry_remote(struct dentry *dentry) -- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- =-=-= Alexander Larsson Red Hat, Inc alexl@xxxxxxxxxx alexander.larsson@xxxxxxxxx He's an oversexed devious romance novelist who hangs with the wrong crowd. She's a radical red-headed doctor prone to fits of savage, blood-crazed rage. They fight crime!