tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

semantics of TRYEMULROOT



Has anyone ever sat down and clearly worked out the desired semantics
for TRYEMULROOT? I've noted inconsistencies in the past, and because
in a number of ways it's a special case of onionfs I'm somewhat
concerned that there may be cases where the proper or desired behavior
is unclear or ambiguous.

Right now most path lookups set TRYEMULROOT. This is fine for ordinary
cases (e.g. stat) -- if the object is present under the emulation
root, it's found and returned; if not, the real root is tried instead.
However, for operations that look up a parent directory and then
operate on it (e.g. mkdir) it becomes less clear: one approach is to
go strictly by whether the parent dir exists in the emulation root; if
it does, the operation is performed on that dir and if it doesn't work
there it fails. Another approach is to allow some or all errors in the
directory operation to cause retrying with the real root, that is,
getting a new parent dir using the real root and then retrying the
operation on it. A third alternative is to always look up both parent
dirs and use them or their contents to deduce the right action to
take, which might be different for different operations.

I think it's safe to consider only two such operations: the create
operations are all basically the same as mkdir, and the remove
operations are all basically the same as rmdir. (Rename is one of each
rolled together.)

I think I favor the first alternative, which is to get a parent dir
and only ever retry that. Not only is it (much) simpler, but it gives
a clear and systematic behavior in all cases.

Otherwise you end up with possibly weird situations like mkdir("/a/b")
when /emul/foo/a exists, /emul/foo/a/b does not, and /a/b does; or
rmdir("/a/b") when both /emul/foo/a/b and /a/b exist. Or mkdir("/a/b")
when /emul/foo/a and /a both exist but /emul/foo is mounted read-only,
or NFS mounted with rootsquash or whatever else. Experience with
onionfs suggests that there's a nearly unlimited supply of such
possibilities and failure to account for them all in advance leads to
a nearly unlimited supply of crashing bugs.

The behavior we currently have is not quite the same as this; it
retries on all errors that occur underneath a particular point in the
namei/lookup spaghetti, regardless of what the error is or what
operation is in progress. If I'm reading the code correctly, for
example, if you do mkdir("/a/b/c") and /emul/foo/a/b is a symbolic
link that contains a component longer than NAME_MAX, it'll retry and
possibly create /a/b/c. But if /emul/foo/a/b is a symbolic link that
points to itself, you'll get ELOOP and it'll never look in the real
root. This doesn't really make much sense.

Thoughts?

Does anyone know of specific cases that have to be handled in a
particular way (e.g. to make applications happy), such that searching
only for the parent directory to operate in won't work?

-- 
David A. Holland
dholland%netbsd.org@localhost


Home | Main Index | Thread Index | Old Index