V_* meta-symbols and locking
James Gritton
jamie at gritton.org
Wed Jun 18 03:48:39 UTC 2008
Like everything I have to say about the V_* issue, perhaps this doesn't
apply to the vnet stuff. But to the two symbols I currently care about,
hostname and rootvnode, locking is a problem.
Current kernel code plays fast and loose with both these symbols. Check
out getcredhostname for example:
void
getcredhostname(struct ucred *cred, char *buf, size_t size)
{
struct prison *pr;
pr = cred->cr_prison;
if (pr != &prison0) {
mtx_lock(&pr->pr_mtx);
strlcpy(buf, (pr->pr_flags & PR_NOHOST)
? hostname : pr->pr_host, size);
mtx_unlock(&pr->pr_mtx);
} else
strlcpy(buf, hostname, size);
}
In the prison case, it nicely locks the prison record. But for the
global hostname, it just copies it. The hostname sysctl is no better
about setting it. And rootvnode is referred to all over the place
without any sort of lock - pretty safe since it's not expected to change
(though it theoretically can).
This same no-locking assumption seems to be going on with V_hostname.
But now this macro applies not only to the "real" hostname but to the
"virtual" one as well - no locking the vimage record. As I try to add a
similar macro to my new jail framework, I find I can't. Instead of a
mere variable redirection, I need to lock-copy-unlock much like
getcredhostname does. Luckily, much hostname access is already
jail-aware. But anything using the "real" hostname should have the same
locking on prison0. Perhaps not wholly necessary since it's just a
string that we know will always have a null byte at the end of the
buffer, but still good form and unknown prevention. And in the case of
actually virtual hostnames, it's essential since they'll be changing
from fixed arrays in struct prison into pointers that may be freed.
Rootvnode is a stickier problem. There's much more code that refers to
it, and it's a more essential part of the system. I don't relish
digging in everywhere and changing the whole rootvnode paradigm with
locking. So instead my solution is to make the jail "path" parameter
(and thus root vnode) set-once. So as long as the V_rootvnode is taken
from a context that will remain for the duration of its use (curthread
is a good bet), it will be safe to access it without locks. In
particular, the real rootvnode that lives at prison0 isn't going anywhere.
So in summary:
I won't use V_hostname (or G_hostname), opting for explicit locking.
I will V_rootvnode (and perhaps G_rootvnode).
All the other network-related V_stuff may deserve a look, but it out of
my purview.
- Jamie
More information about the freebsd-virtualization
mailing list