diff --git a/sys/include/9p.h b/sys/include/9p.h index eac9745e3..377ebc437 100644 --- a/sys/include/9p.h +++ b/sys/include/9p.h @@ -216,9 +216,12 @@ struct Srv { void srv(Srv*); void postmountsrv(Srv*, char*, char*, int); void _postmountsrv(Srv*, char*, char*, int); +void postsharesrv(Srv*, char*, char*, char*, char*); +void _postsharesrv(Srv*, char*, char*, char*, char*); void listensrv(Srv*, char*); void _listensrv(Srv*, char*); int postfd(char*, int); +int sharefd(char*, char*, char*, int); int chatty9p; void respond(Req*, char*); void responderror(Req*); diff --git a/sys/src/lib9p/post.c b/sys/src/lib9p/post.c index b42c7b32c..37dcfd5dc 100644 --- a/sys/src/lib9p/post.c +++ b/sys/src/lib9p/post.c @@ -56,6 +56,56 @@ _postmountsrv(Srv *s, char *name, char *mtpt, int flag) close(s->srvfd); } +void +_postsharesrv(Srv *s, char *name, char *mtpt, char *desc, char *flag) +{ + int fd[2]; + + if(!s->nopipe){ + if(pipe(fd) < 0) + sysfatal("pipe: %r"); + s->infd = s->outfd = fd[1]; + s->srvfd = fd[0]; + } + if(name) + if(postfd(name, s->srvfd) < 0) + sysfatal("postfd %s: %r", name); + + if(_forker == nil) + sysfatal("no forker"); + _forker(postproc, s, RFNAMEG); + + /* + * Normally the server is posting as the last thing it does + * before exiting, so the correct thing to do is drop into + * a different fd space and close the 9P server half of the + * pipe before trying to mount the kernel half. This way, + * if the file server dies, we don't have a ref to the 9P server + * half of the pipe. Then killing the other procs will drop + * all the refs on the 9P server half, and the mount will fail. + * Otherwise the mount hangs forever. + * + * Libthread in general and acme win in particular make + * it hard to make this fd bookkeeping work out properly, + * so leaveinfdopen is a flag that win sets to opt out of this + * safety net. + */ + if(!s->leavefdsopen){ + rfork(RFFDG); + rendezvous(0, 0); + close(s->infd); + if(s->infd != s->outfd) + close(s->outfd); + } + + if(mtpt){ + if(sharefd(mtpt, desc, flag, s->srvfd) < 0) + sysfatal("sharefd %s: %r", mtpt); + }else + close(s->srvfd); +} + + static void postproc(void *v) { diff --git a/sys/src/lib9p/rfork.c b/sys/src/lib9p/rfork.c index e279cc9e9..37cf6448b 100644 --- a/sys/src/lib9p/rfork.c +++ b/sys/src/lib9p/rfork.c @@ -32,3 +32,9 @@ postmountsrv(Srv *s, char *name, char *mtpt, int flag) _postmountsrv(s, name, mtpt, flag); } +void +postsharesrv(Srv *s, char *name, char *mtpt, char *desc, char *flag) +{ + _forker = rforker; + _postsharesrv(s, name, mtpt, desc, flag); +} diff --git a/sys/src/lib9p/srv.c b/sys/src/lib9p/srv.c index 82e2240b4..bbe025b46 100644 --- a/sys/src/lib9p/srv.c +++ b/sys/src/lib9p/srv.c @@ -851,3 +851,29 @@ postfd(char *name, int pfd) return 0; } +int +sharefd(char *name, char *desc, char *flags, int pfd) +{ + int fd; + char buf[80]; + + snprint(buf, sizeof buf, "#σc/%s", name); + if(chatty9p) + fprint(2, "sharefd %s\n", buf); + fd = create(buf, OWRITE, 0600); + if(fd < 0){ + if(chatty9p) + fprint(2, "create fails: %r\n"); + return -1; + } + if(fprint(fd, "%s %d %s\n", flags, pfd, desc) < 0){ + if(chatty9p) + fprint(2, "write fails: %r\n"); + close(fd); + return -1; + } + close(fd); + if(chatty9p) + fprint(2, "sharefd successful\n"); + return 0; +}