Re: [PATCH RFC] vfs: make fstatat retry on ESTALE errors fromgetattr call

From: Jeff Layton
Date: Tue Apr 17 2012 - 10:22:23 EST

On Tue, 17 Apr 2012 16:03:06 +0200
Miklos Szeredi <miklos@xxxxxxxxxx> wrote:

> Jeff Layton <jlayton@xxxxxxxxxx> writes:
> >> The retry is needed when when we discover during ->getattr() that the
> >> cached lookup returned a stale file handle.
> >>
> >> If the lookup wasn't cached or if there was no lookup at all
> >> (stat(".") and friends) then retrying will not gain anything.
> >>
> >
> > That's not necessarily the case, at least not with NFS. It's easily
> > possible for you to do a full-fledged lookup over the wire, and then
> > for that inode to be removed prior to issuing a call against the FH that
> > you got back.
> >
> >> And that also means that retrying multiple times is pointless, since
> >> after the first retry we are sure to have up-to-date attributes.
> >>
> >
> > Again, it's not pointless. It's possible (though somewhat pathological)
> > for you to hit the race above more than once in the same operation.
> > Granted, it's an unlikely race but it is possible.
> ->lookup() should (and does AFAICS) leave a fully initialized inode with
> up-to-date atributes in there and at that moment there's not a lot of
> sense in fetching the attributes from the server *again*.
> How that lookup is implemented is another question, I can see in
> nfs3_proc_lookup() that it may or may not be atomic, and retrying (and
> looping) there might make sense. But it doesn't retry and doesn't loop,
> so the fact is, it will either return ESTALE (and the path lookup will
> retry once with LOOKUP_REVAL) or the inode *will* be up-to-date.
> So I think I'm still right that it's pointless to do retry after a
> non-cached lookup.

Ok, I'll grant that for stat() type calls, but I've just been focusing
on that as an example here. We'll need to do something similar for all
path based syscalls. What about things that require more than one round
trip -- e.g. chmod()?

> >> Unfortunately it's impossible for the filesystem to know whether a
> >> ->getattr (or other inode operation) was perfromed after a cached or a
> >> non-cached lookup.
> >>
> >> I'm not sure what the right interface for this would be. One would be
> >> to just pass the "cached-or-not" information as a flag. That works for
> >> getattr() but not for other operations.
> >>
> >> Another is to introduce atomic lookup+foo variants of these operations
> >> just like for open. E.g. the lookup+getattr is called if the cached
> >> lookup fails or if the cached lookup succeeds and the plain ->getattr
> >> call returns ESTALE.
> >>
> >
> > To do that would require protocol support that we simply don't have. We
> > don't have a way to (for instance) say via NFS "give me the attributes
> > for this filename". Well, at least not for NFSv3...
> >
> > With v4 you could theoretically construct a compound that does that,
> > but you'd have to assume that the server won't release the reference to
> > the inode midway through the compound. That's a reasonably safe
> > assumption.
> >
> > While it's nice to consider new atomic ops like this, it's not really
> > possible with earlier versions of NFS.
> It's just an interface question: where you put the retry logic for those
> non-atomic protocols. I think it's cleaner if the retry logic is in the
> filesystem and not in the VFS. Then NFS can do whatever it wants
> without having to impose policy in the generic filesystem layer.

So essentially you want to push all of the LOOKUP handling down into
the filesystems such that all ops are atomic_* or have an atomic_*
variant. That sounds like a very heavy-handed way to solve this.

Jeff Layton <jlayton@xxxxxxxxxx>
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at
Please read the FAQ at