Subject: Re: curproc removal (NFS, ...)
To: YAMAMOTO Takashi <firstname.lastname@example.org>
From: Jonathan Stone <email@example.com>
Date: 05/25/2004 12:27:22
In message <firstname.lastname@example.org>YAMAMOTO Takashi write
>i understand why you want to eliminate curproc.
>but i don't understand why you want to eliminate (struct proc *)NULL
>and (ab)use uio_procp.
Ah. OK, now I see what you mean. Thank you (again) for clarifying.
I had acutally suggested passing an explicit struct proc * to
soreceive. Matt Thomas pointed out that one could just use the
uio->uio_procp, and argued that was ``cleaner''. I may misremember
Matt's opinion, but what I recall was along the lines of: the
uio->uio_procp is already there, and (implicitly) if we pass another
struct proc *, they might end up both non-NULL, and different. Yuck.
I thought the only places I did that are where the caller already
passes a non-NULL sruct mbuf **mp to soreceive, in which case the
comment in soreceive() applies:
* The caller may receive the data as a single mbuf chain by supplying
* an mbuf **mp0 for use in returning the chain. The uio is then used
* only for the count in uio_resid.
But now the comment is out of date; the code also usese uio->uio_procp. Why?
The real motivation for abusing that (or to pass an explicit struct
proc *) is that soreceive() can call the per-domain dom_externalize
method. For Unix-domain sockets, that's unp_externalize(), which used
to grab curproc (which we agree is bad), but now gets the struct proc
* passed to soreceive() via uio->uio_procp. (I could easily have
passed in an explicit struct proc * instead; but see above).
The bottom line is that if you want to do arbitrary operations on
Unix-domain sockets, you basically *have* to keep track of some struct
proc * ``associated'' with that Unix-domain socket, wtih approrpriate
permissions to frob the filesystem state associated with the socket;
and you must pass that into sosend() or (implicitly) into soreceive().
Remember the whole idea of calling sosend() and soreceive() outside of
the ``top half'' is currently not well-defined. And if you are calling
from the `top half', the process to pass down is obviously the current
process, and not arbitrary.
I know what *I* would mandate, if I could. I'd prefer to allow a NULL
struct proc * for sosend() or soreceive() for data-only transfer on
connected sockets. Unfortunately, the p->p_stats->p_ru.ru_msgrcv
acounting and the p->p_rlimit[RLIMIT_SBSIZE make what I have done in
the past, and what I'd prefer to mandate ... tricky.
I could at least write a manpage about what I *want* to permit.
But what should it be called?
>> So you can't really tell, at the socket layer, what might or might not be
>> done with the struct proc * argument.
>do you mean, because proc pointer isn't used at all or is used in the
>very protocol specific manner, a pointer to an arbitrary proc is good enough?
I suspect we're talking at cross-purposes with that word `arbitrary'.
The struct proc * being passed must be NULL (if that works) or the
`owner', in some sense, of the request being passed. (Resource
accounting gets charged to that process; any VFS operations for
PF_UNIX sockets will [or should] use it; and so on).
Time to write that manpage, I guess.