19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <fcall.h>
49a747e4fSDavid du Colombier #include <thread.h>
59a747e4fSDavid du Colombier #include <9p.h>
6*22a127bbSDavid du Colombier #include <auth.h>
7*22a127bbSDavid du Colombier
8*22a127bbSDavid du Colombier static void postproc(void*);
99a747e4fSDavid du Colombier
109a747e4fSDavid du Colombier void
_postmountsrv(Srv * s,char * name,char * mtpt,int flag)11*22a127bbSDavid du Colombier _postmountsrv(Srv *s, char *name, char *mtpt, int flag)
129a747e4fSDavid du Colombier {
13*22a127bbSDavid du Colombier int fd[2];
149a747e4fSDavid du Colombier
15*22a127bbSDavid du Colombier if(!s->nopipe){
16*22a127bbSDavid du Colombier if(pipe(fd) < 0)
17*22a127bbSDavid du Colombier sysfatal("pipe: %r");
18*22a127bbSDavid du Colombier s->infd = s->outfd = fd[1];
19*22a127bbSDavid du Colombier s->srvfd = fd[0];
209a747e4fSDavid du Colombier }
21*22a127bbSDavid du Colombier if(name)
22*22a127bbSDavid du Colombier if(postfd(name, s->srvfd) < 0)
23*22a127bbSDavid du Colombier sysfatal("postfd %s: %r", name);
24*22a127bbSDavid du Colombier
25*22a127bbSDavid du Colombier if(_forker == nil)
26*22a127bbSDavid du Colombier sysfatal("no forker");
27*22a127bbSDavid du Colombier _forker(postproc, s, RFNAMEG);
28*22a127bbSDavid du Colombier
29*22a127bbSDavid du Colombier /*
30*22a127bbSDavid du Colombier * Normally the server is posting as the last thing it does
31*22a127bbSDavid du Colombier * before exiting, so the correct thing to do is drop into
32*22a127bbSDavid du Colombier * a different fd space and close the 9P server half of the
33*22a127bbSDavid du Colombier * pipe before trying to mount the kernel half. This way,
34*22a127bbSDavid du Colombier * if the file server dies, we don't have a ref to the 9P server
35*22a127bbSDavid du Colombier * half of the pipe. Then killing the other procs will drop
36*22a127bbSDavid du Colombier * all the refs on the 9P server half, and the mount will fail.
37*22a127bbSDavid du Colombier * Otherwise the mount hangs forever.
38*22a127bbSDavid du Colombier *
39*22a127bbSDavid du Colombier * Libthread in general and acme win in particular make
40*22a127bbSDavid du Colombier * it hard to make this fd bookkeeping work out properly,
41*22a127bbSDavid du Colombier * so leaveinfdopen is a flag that win sets to opt out of this
42*22a127bbSDavid du Colombier * safety net.
43*22a127bbSDavid du Colombier */
44*22a127bbSDavid du Colombier if(!s->leavefdsopen){
45*22a127bbSDavid du Colombier rfork(RFFDG);
46*22a127bbSDavid du Colombier rendezvous(0, 0);
47*22a127bbSDavid du Colombier close(s->infd);
48*22a127bbSDavid du Colombier if(s->infd != s->outfd)
49*22a127bbSDavid du Colombier close(s->outfd);
509a747e4fSDavid du Colombier }
519a747e4fSDavid du Colombier
52*22a127bbSDavid du Colombier if(mtpt){
53*22a127bbSDavid du Colombier if(amount(s->srvfd, mtpt, flag, "") == -1)
54*22a127bbSDavid du Colombier sysfatal("mount %s: %r", mtpt);
55*22a127bbSDavid du Colombier }else
56*22a127bbSDavid du Colombier close(s->srvfd);
57*22a127bbSDavid du Colombier }
58*22a127bbSDavid du Colombier
59*22a127bbSDavid du Colombier static void
postproc(void * v)60*22a127bbSDavid du Colombier postproc(void *v)
61*22a127bbSDavid du Colombier {
62*22a127bbSDavid du Colombier Srv *s;
63*22a127bbSDavid du Colombier
64*22a127bbSDavid du Colombier s = v;
65*22a127bbSDavid du Colombier if(!s->leavefdsopen){
66*22a127bbSDavid du Colombier rfork(RFNOTEG);
67*22a127bbSDavid du Colombier rendezvous(0, 0);
68*22a127bbSDavid du Colombier close(s->srvfd);
69*22a127bbSDavid du Colombier }
70*22a127bbSDavid du Colombier srv(s);
71*22a127bbSDavid du Colombier }
72