Re: [PATCH 32/53f] ext4: move dcache modifying code out of __ext4_link()

From: NeilBrown

Date: Tue Mar 17 2026 - 16:29:01 EST



(cc trimmed...)

On Tue, 17 Mar 2026, Jan Kara wrote:
> On Fri 13-03-26 08:12:19, NeilBrown wrote:
> ...
> > diff --git a/fs/dcache.c b/fs/dcache.c
> > index a1219b446b74..c48337d95f9a 100644
> > --- a/fs/dcache.c
> > +++ b/fs/dcache.c
> > @@ -358,7 +358,7 @@ static inline int dname_external(const struct dentry *dentry)
> > return dentry->d_name.name != dentry->d_shortname.string;
> > }
> >
> > -void take_dentry_name_snapshot(struct name_snapshot *name, struct dentry *dentry)
> > +void take_dentry_name_snapshot(struct name_snapshot *name, const struct dentry *dentry)
> > {
> > unsigned seq;
> > const unsigned char *s;
>
> The constification of take_dentry_name_snapshot() should probably be a
> separate patch? Also I'd note that this constification (and the
> constification of __ext4_fc_track_link()) isn't really needed here because
> ext4_fc_track_link() will immediately bail through ext4_fc_disabled() when
> fast commit replay is happening so __ext4_fc_track_link() never gets called
> in that case - more about that below.

I thought I might have overdone the constantification, but I didn't want
to under-do it, at least for my compile tests.


>
> > @@ -1471,7 +1471,15 @@ static int ext4_fc_replay_link_internal(struct super_block *sb,
> > goto out;
> > }
> >
> > + ihold(inode);
> > + inc_nlink(inode);
> > ret = __ext4_link(dir, inode, dentry_inode);
> > + if (ret) {
> > + drop_nlink(inode);
> > + iput(inode);
> > + } else {
> > + d_instantiate(dentry_inode, inode);
> > + }
> > /*
> > * It's possible that link already existed since data blocks
> > * for the dir in question got persisted before we crashed OR
> ...
> > @@ -3460,8 +3460,6 @@ int __ext4_link(struct inode *dir, struct inode *inode, struct dentry *dentry)
> > ext4_handle_sync(handle);
> >
> > inode_set_ctime_current(inode);
> > - ext4_inc_count(inode);
> > - ihold(inode);
> >
> > err = ext4_add_entry(handle, dentry, inode);
> > if (!err) {
> > @@ -3471,11 +3469,7 @@ int __ext4_link(struct inode *dir, struct inode *inode, struct dentry *dentry)
> > */
> > if (inode->i_nlink == 1)
> > ext4_orphan_del(handle, inode);
> > - d_instantiate(dentry, inode);
> > - ext4_fc_track_link(handle, dentry);
> > - } else {
> > - drop_nlink(inode);
> > - iput(inode);
> > + __ext4_fc_track_link(handle, inode, dentry);
>
> This looks wrong. If fastcommit replay is running, we must skip calling
> __ext4_fc_track_link(). Similarly if the filesystem is currently
> inelligible for fastcommit (due to some complex unsupported operations
> running in parallel). Why did you change ext4_fc_track_link() to
> __ext4_fc_track_link()?

I changed to __ext4_fc_track_link() because I needed something that
accepted the inode separately from the dentry. As you point out, that
means we lose some important code which makes the decision misguided.

I'm wondering about taking a different approach - not using a dentry at
all and not constifying anything.
I could split __ext4_add_entry() out of ext4_add_entry() and instead of
passing the dentry-to-add I could pass the dir inode qstr name, and
d_flags.

Then ext4_link could be passed the same plus a "do fast commit" flag.

The result would be more verbose, but also hopefully more clear.

>
> > @@ -3504,7 +3498,16 @@ static int ext4_link(struct dentry *old_dentry,
> > err = dquot_initialize(dir);
> > if (err)
> > return err;
> > - return __ext4_link(dir, inode, dentry);
> > + ihold(inode);
> > + ext4_inc_count(inode);
>
> I'd put inc_nlink() here instead. We are guaranteed to have a regular file
> anyway and it matches what we do in ext4_fc_replay_link_internal().
> Alternatively we could consistently use ext4_inc_count() &
> ext4_dec_count() in these functions.

Current __ext4_link() has ext4_inc_count().
But it is only usable in namei.c. So I didn't use it in
ext4_fc_replay_link_internal() as that is in a different file.

I'll revise and resend these patches just to the ext4 team.

Thanks,
NeilBrown


>
> > + err = __ext4_link(dir, inode, dentry);
> > + if (err) {
> > + drop_nlink(inode);
> > + iput(inode);
> > + } else {
> > + d_instantiate(dentry, inode);
> > + }
> > + return err;
> > }
>
> Honza
> --
> Jan Kara <jack@xxxxxxxx>
> SUSE Labs, CR
>