Subject: Re: CVS commit: syssrc/sys/miscfs/nullfs
To: enami tsugutomo <enami@sm.sony.co.jp>
From: Bill Studenmund <wrstuden@netbsd.org>
List: tech-kern
Date: 03/18/2002 18:31:50
On 19 Mar 2002, enami tsugutomo wrote:

> Bill Studenmund <wrstuden@wasabisystems.com> writes:
>
> > True. I think that trying to ensure that things are reused in the exact
> > order they were last used gets messy with layered file systems. So my vote
> > is (now) to just release the lower vnode when the upper one dies, and let
> > the lower one die as it dies.
>
> `dies' measn when layer fs vnode is inactivated?

No, when it is reclaimed (VOP_RECLAIM).

> > > As we (or only me?) saw, rest of kernel expects node is released when
> > > it is no longer used.
> >
> > Ok. What does that have to do with the upper vnode keeping a reference to
> > the lower one? Yes, there is a problem from how we don't propogate
> > information up when the lower vnode has been fully unlinked. But we can
> > fix that without unreferencing the lower vnode when we inactivate the
> > upper one.
>
> The problem is that if layer fs cache holds reference to lower vnodes
> after layer fs node is inactivated (released), any action supposed to
> be done by vop_inactive of lower vnode is delayed until the layer fs
> vnode is reclaimed.
>
> One of such action is to reclaim on disk storage.

That's the whole point of what we were talking about for VOP_UPCALL().
When the lower layer notices the file is fully unlinked, it calls a
routine (v_upcall for now) and passes a command (like an ioctl). v_upcall
vgets() each upper node, calls the node's VOP_UPCALL() routine, and steps.
When each layer gets a VOP_UPCALL() that says the lower vnode has been
released, it takes steps so that when the layer (upper) vnode is
inactivated, it instead gets vrecycle()d.

There are some issues I'm not sure of about exact details, but this very
issue is why I/we came up with the idea. :-)

> > Hmm.. I just thought of a strong reason why we NEED the upper vnode to
> > reference the lower one. The lock for the upper one is the same as the
> > lower one - they use the same struct lock, which is located in the lower
> > vnode. As long as that is the case, the upper really needs to hang onto
> > the lower one.
>
> Even when the upper vnode isn't used?

Depends on how we do inactivation and reactivation. It either uses the
lower vnode's lock, or we have to swap locks around. And we will likely
get in a case where we have two locked locks and we have to merge them.
That sounds like a real mess to me.

> > Also, I think you've made an implicit assumption in what you describe, and
> > that it will (well can) get us into trouble. You've suggested (as I
> > understand it) when we put the upper vnode on the free list, we release
> > its reference on the lower vnode. Then in layer_node_find, if we find the
> > upper vnode doesn't have its reference to the lower one, we make sure it's
> > still the same lower vnode (v_id) and if so readd the reference.
> >
> > The assumption is that the only way that vnode can come back into use
> > involves layer_node_find(). While that may be the only way in practice,
> > strictly speaking, anything can vget the upper vnode off of the free list
> > and start using it. And there's no call to the file system when that
> > happens. So something can vget the layered vnode off of the free list and
> > start using it when it holds no reference to the lower vnode. That would
> > be bad.
>
> Of course, in upper vnode's vget(), it should vget() the cached lower
> vnode.

vget() doesn't call the vnode's file system.

Take care,

Bill