On Wed, 15 Oct 2014 00:24:21 -0400
Anders Kaseorg via RT <openafs-bugs@openafs.org> wrote:
> On 10/13/2014 10:14 AM, Andrew Deason via RT wrote:
> > Hmm, once guess is that 'vcp' is a directory and 'tvc' is a mountpoint
> > object, and to fix it we just need to evaludate the tvc mntpt and it
> > will become vcp. Are you running with any kind of fakestat?
>
> Yes, -fakestat-all.
So, I can reproduce _a_ way of getting this to happen, which I'll
describe below. I don't know if it's what is actually happening in your
situation, so if you would like to know what was actually happening (and
I would, at least), it would still be helpful to get some more
information from some additional log messages. Specifically, the fids
for tvc and vcp, as well as their mvstat, when tvc && tvc != vcp.
The attached patch adds some logging to provide that information, as
well as effectively reverting gerrit 11358 (so you can run with this
without having things break again). Or implement this however you want;
I'm just attaching this to clearly illustrate what I'm after and what
you can do to get it.
Anyway, the motivation for my suspicions above is that the code in our
d_revalidate routine "sometimes" converts vcp from a mtpt object to a
dir. And when we perform the afs_lookup later on, that code also
"sometimes" converts its returned vcache from a mtpt to a dir. This was
concerning because of the duplication in logic and the specifics of the
"sometimes". After looking at it more closely I cannot actually think of
any situation where we consistently get different outcomes, but those
decisions are made in different points in time, which opens up the
possibility of a race.
Specifically, we are looking at if the mtpt has the CMValid flag set. In
order to trigger this race, we either need to clear or set the CMValid
flag after the check in our d_revalidate occurs, but before the check
near the end of afs_lookup. Getting CMValid to be cleared seems easier
than getting it set, since I think getting it set cannot be done while
we are running d_revalidate (but I haven't tried looking into this
much).
The way I have managed to see this happen works like this:
- Someone has /afs/cell/user/adeason as their pwd. The dir and mtpt and
everything is fully cached and has CMValid set.
- Either /afs/cell/user changes, or some relevant callbacks expire;
regardless, something happens such that we need to call afs_lookup in
our d_revalidate.
- Something triggers a lookup for /afs/cell/user/adeason, causing a
d_revalidate to occur. Since CMValid is set, we convert 'adeason' the
mtpt to 'adeason' the dir. Later on we call afs_lookup.
- While afs_lookup is running, something causes CMValid to be cleared.
This can be caused by a volume release, callbacks expiring, or vldb
cache entries expiring. It can also occur by running 'fs checkv',
which is convenient for artificially reproducing the issue.
- The afs_lookup from above sees that CMValid is cleared, and so
returns 'adeason' the mtpt to our d_revalidate. The d_revalidate code
sees that the vcaches do not match, so we d_drop.
- The process with /afs/cell/user/adeason as their pwd now sees ENOENT
when looking up their working directory.
I'm not sure how plausible this is for your situation. I can reproduce
this reliably by adding artificial sleeps and such, but without those
hitting that race window seems pretty coincidental. But iirc, this issue
doesn't happen immediately/constantly; it does take a bit of time...?
This is maybe explainable in that if something is accessing
/afs/cell/user/adeason pretty frequently, as soon as some callbacks
expire we require the afs_lookup and clear CMValid, so every time that
expiration happens maybe we'd have a decent chance at triggering the
race.
But I'm not really sure, so that's why I'd like to get more information.
A real fix for this would probably involve ust converting tvc or vcp
from a mtpt to a dir, if their mvstats mismatch. Ideally we could just
work with mtpt objects and not deal with converting them or something,
but I expect doing that would be more involved.
Oh, and of course, all of this goes away without fakestat. This stuff
with converting mtpts and CMValid and such is only applicable when we
are encountering a mountpoint where fakestat applies. (So, all mtpts
with -fakestat-all, and cellular mountpoints with -fakestat.)
[Note: sorry if I skipped over anything or appear brief; my laptop lost
power during the initial draft and I had to write it all again.]
--
Andrew Deason
adeason@sinenomine.net