a take at cache coherency

Matthew Dillon dillon at apollo.backplane.com
Wed Jan 25 10:51:57 PST 2006

:(When I say "I do foo like this" I refer to this updated version, not the
:first one which was posted.)


:>     (2) For renames and other namespace operations, it should be sufficient
:> 	to simply INVALIDATE the upper layers rather then attempt to 
:> 	actually adjust them to perfection.
:> 	This could be particularly important for something like rename if
:> 	an upper layer needs to do some sort of filename translation.
:> 	When an invalid entry is encountered by a normal operation, like
:> 	a rename or open or something like that, it will be resolved.  So
:> 	the work of resynchronizing the entries would be done by the
:> 	resolver.
:That's how I treat renames, although a simple invalidation (in the sense
:of cache_inval) seems to be unsufficent for getting renaming right: shadowing
:relations must be torn down and get recalculated too.
:But if you want to follow this scheme in general, current code will make
:that shipwreck, because there are cases when a positive action is done
:without asking the vfs.
:Eg., there are cache_setvp() calls popping up here and there. Now say
:nullnode shadows foonode, and nullnode is unresolved. The plan is that
:nullnode will sync itself up to foonode in null_nresolve (which will be 
:resolved at that point, if for nothing else, because the null_nresolve
:itself forwards the resolution request to foonode).
:Now some function is invoked which has a cache_setvp() call in it, and
:cache_setvp() happens to hit nullnode. It gets then resolved
:mercilessly. foonode also gets resolved independently. They are now out
:of sync despite the efforts of the null layer, because null_nresolve was
:left out of the game.
:So, to achieve "shadowability", either cache_setvp() calls should be
:purged out from general vfs code or cache_setvp() itself has to propagate
:its effect through the shadow chain.
:There are issues with the shadowability of other things like fsmid, too.

    Yes, I agree to a point.  When the chain is invalidated for the rename
    case, the shadow association(s) must be disconnected.  I think that will
    'just work' since re-resolving any entity will cause the shadow chain
    to be regenerated from that entity downwards.  For the simple deletion
    case I don't think we have to disconnect the shadow association(s), but
    to make the code generic we probably should anyway.  Any invalidation.

    The fact that we would have a single common lock on entry to the 
    invalidation code makes things easier because it means the shadowing
    topology will also be locked, allowing it to be manipulated (i.e. 
    disconnected) as part of the invalidation.

    I do feel that we should not attempt to combine fields, in particular
    nc_vp, within the common shadow structure.  Only the lock should
    be 'shared' per-say.  I say this even knowing that most of the time
    the nc_vp will be the same between the layers.  There are several
    reasons why I want to keep nc_vp per-namecache.  One is that I feel
    it is important to keep the namecache's current topology abstraction
    intact in order to greatly reduce the amount of code pollution 
    introduced by the shadowing.  Another is that nc_vp is accessed all
    over the place and I see no reason to add an extra unnecessary
    indirection for it.  A third is that I believe there may be cases
    where we may want to do a partial invalidation and still possibly
    maintain the shadow linkages.  A shared nc_vp ties our hands.

:> 	(in the parent layers) means that some namecache records will be
:> 	marked unresolved while other deeper layers will be marked
:> 	resolved.  Currently a combination of nc_vp and nc_flags is used
:> 	to determine this state.  It is very, very fragile and I don't
:> 	want to change that code at all.
:My idea was that the basic relation of cache coherency is "x shadows y",
:in the sense that x wants all its resolution related data kept in sync
:with y.
:Now you say that the coherency layer doesn't even know of such things,
:it's just concerned about locking; and that the exact way and extent of
:shadowing should reside in vfs scope.
:However, the namecache struct doesn't have fs specific private data
:field (I suppose by design). How could then the fs associate shadowing
:related info with a namecache node? If there is no strict "x shadows y"
:relation but an overlay aspires to translate data, then having just a
:nc_shadowed field is pretty pointless... (unless if it's of type "void
:*", which we might not allow). Eg., unionfs might want then its
:namecache nodes to shadow two lower nodes in some sense.

    We don't want the shadowing info as fs-specific private data.  It
    would be explicit in the namecache structure.  The mount structure
    (which the namecache structure references) can be used to hold
    topological information to aid the resolution code.  The primary
    method of creating a shadow association will be done by the 
    per-VFS resolution code since it will have access to the namecache
    record, the mount point, and any fs-specific information.  So
    the resolution code would be the one that calls cache_shadow() (or

:>     forwards until one wraps to the highest layer, and continue iterating
:>     invalidating namecache records until the original entry is encountered
:>     again.
:What does "highest layer" mean? How do we have a hierarchy if we only
:know of sharing the lock?

    The namecache code would know about the shadow hierarchy but really
    only for nodes that have been resolved.  That should be sufficient if
    we make it a rule that unresolved nodes be disconnected from any
    shadowing hierarchy.

					Matthew Dillon 
					<dillon at xxxxxxxxxxxxx>

More information about the Kernel mailing list