lib9p: expose Srv.forker handler and srvforker(), threadsrvforker() and threadsrv() functions

To use srvrease()/srvaquire() we need to have a way to spawn
new processes to handle the service loop. This functionality
was provided by the internal _forker() function which was
eigther rfork or libthread based implementation depending on
if postmountsrv() or threadpostmountsrv() where called.

For servers who want to use srv() directly, _forker would not
be initialized so srvrelease() could not be used.

To untangle this, we get rid of the global _forker handler
and put the handler in the Srv structure. Which will get
initialized (when nil) to eigther srvforker() or threadsrvforker()
depending on if the thread or non-thread entry points where used.

For symmetry, we provde new threadsrv() and threadpostsrv()
functions which handle the default initialization of Srv.forker.

This also allows a user to provide his own forker function,
maybe to conserve stack space.

To avoid dead code, we put each of these function in their
own object file. Note, this also allows a user to define its
own srvforker() symbol.
This commit is contained in:
cinap_lenrek 2021-05-01 16:37:00 +02:00
parent 013b498314
commit f6509078ed
15 changed files with 201 additions and 125 deletions

View file

@ -235,23 +235,29 @@ struct Srv {
int spid; /* pid of srv() caller */ int spid; /* pid of srv() caller */
void (*forker)(void (*)(void*), void*, int);
void (*free)(Srv*); void (*free)(Srv*);
}; };
void srvforker(void (*)(void*), void*, int);
void threadsrvforker(void (*)(void*), void*, int);
void srv(Srv*); void srv(Srv*);
void postsrv(Srv*, char*);
void postmountsrv(Srv*, char*, char*, int); void postmountsrv(Srv*, char*, char*, int);
void _postmountsrv(Srv*, char*, char*, int);
void postsharesrv(Srv*, char*, char*, char*); void postsharesrv(Srv*, char*, char*, char*);
void _postsharesrv(Srv*, char*, char*, char*);
void listensrv(Srv*, char*); void listensrv(Srv*, char*);
void _listensrv(Srv*, char*);
int chatty9p; void threadsrv(Srv*);
void respond(Req*, char*); void threadpostsrv(Srv*, char*);
void responderror(Req*);
void threadpostmountsrv(Srv*, char*, char*, int); void threadpostmountsrv(Srv*, char*, char*, int);
void threadpostsharesrv(Srv*, char*, char*, char*); void threadpostsharesrv(Srv*, char*, char*, char*);
void threadlistensrv(Srv *s, char *addr); void threadlistensrv(Srv *s, char *addr);
int chatty9p;
void respond(Req*, char*);
void responderror(Req*);
/* /*
* Helper. Assumes user is same as group. * Helper. Assumes user is same as group.
*/ */
@ -276,8 +282,6 @@ void authwrite(Req*);
void authdestroy(Fid*); void authdestroy(Fid*);
int authattach(Req*); int authattach(Req*);
extern void (*_forker)(void (*)(void*), void*, int);
void srvacquire(Srv *); void srvacquire(Srv *);
void srvrelease(Srv *); void srvrelease(Srv *);

View file

@ -9,16 +9,21 @@ estrdup9p,
listensrv, listensrv,
postmountsrv, postmountsrv,
postsharesrv, postsharesrv,
postsrv,
readbuf, readbuf,
readstr, readstr,
respond, respond,
responderror, responderror,
srv
srvacquire, srvacquire,
srvforker,
srvrelease, srvrelease,
threadlistensrv, threadlistensrv,
threadpostmountsrv, threadpostmountsrv,
threadpostsharesrv, threadpostsharesrv,
srv \- 9P file service threadpostsrv,
threadsrv,
threadsrvforker - 9P file service
.SH SYNOPSIS .SH SYNOPSIS
.ft L .ft L
.nf .nf
@ -59,6 +64,8 @@ typedef struct Srv {
int infd; int infd;
int outfd; int outfd;
int srvfd; int srvfd;
void (*forker)(void (*fn)(void*), void *arg, int flags);
} Srv; } Srv;
.fi .fi
.PP .PP
@ -66,12 +73,17 @@ typedef struct Srv {
.ft L .ft L
.ta \w'\fLvoid* 'u .ta \w'\fLvoid* 'u
void srv(Srv *s) void srv(Srv *s)
void postsrv(Srv *s, char *name);
void postmountsrv(Srv *s, char *name, char *mtpt, int flag) void postmountsrv(Srv *s, char *name, char *mtpt, int flag)
void postsharesrv(Srv *s, char *name, char *mtpt, char *desc) void postsharesrv(Srv *s, char *name, char *mtpt, char *desc)
void listensrv(Srv *s, char *addr)
void threadsrv(Srv *s)
void threadpostsrv(Srv *s, char *name);
void threadpostmountsrv(Srv *s, char *name, char *mtpt, int flag) void threadpostmountsrv(Srv *s, char *name, char *mtpt, int flag)
void threadpostsharesrv(Srv *s, char *name, char *mtpt, char *desc) void threadpostsharesrv(Srv *s, char *name, char *mtpt, char *desc)
void listensrv(Srv *s, char *addr)
void threadlistensrv(Srv *s, char *addr) void threadlistensrv(Srv *s, char *addr)
void srvforker(void (*fn)(void*), void *arg, int flags)
void threadsrvforker(void (*fn)(void*), void *arg, int flags)
void respond(Req *r, char *error) void respond(Req *r, char *error)
void responderror(Req*) void responderror(Req*)
void readstr(Req *r, char *src) void readstr(Req *r, char *src)
@ -106,7 +118,9 @@ extern int chatty9p;
.SH DESCRIPTION .SH DESCRIPTION
The function The function
.I srv .I srv
serves a 9P session by reading requests from and
.I threadsrv
serve a 9P session by reading requests from
.BR s->infd , .BR s->infd ,
dispatching them to the function pointers kept in dispatching them to the function pointers kept in
.BR Srv , .BR Srv ,
@ -166,6 +180,19 @@ but abort the program if they run out of memory.
If alternate behavior is desired, clients can link against If alternate behavior is desired, clients can link against
alternate implementations of these functions. alternate implementations of these functions.
.PP .PP
The functions
.I srvforker
and
.I threadsrvforker
handle the creation of new processes on a connection which use
.I rfork
(see
.IR fork (2))
or
.I procrfork
(see
.IR thread (2)).
.PP
.I Postmountsrv .I Postmountsrv
and and
.I threadpostmountsrv .I threadpostmountsrv
@ -174,6 +201,14 @@ are wrappers that create a separate process in which to run
They do the following: They do the following:
.IP .IP
Initialize Initialize
.IB s -> forker
to eigther
.I srvforker
or
.I threadsrvforker
unless already initialized to a non-nil value.
.IP
Initialize
.IB s -> infd .IB s -> infd
and and
.IB s -> outfd .IB s -> outfd
@ -187,16 +222,12 @@ If
is non-nil, post the file descriptor is non-nil, post the file descriptor
.IB s -> srvfd .IB s -> srvfd
under the name under the name
.BI /srv/ name . .BI /srv/ name
using a call to
.IR postsrv .
.IP .IP
Fork a child process via Fork a child process via
.I rfork .IB s -> forker
(see
.IR fork (2))
or
.I procrfork
(see
.IR thread (2)),
using the using the
.BR RFPROC , .BR RFPROC ,
.BR RFNOWAIT , .BR RFNOWAIT ,

View file

@ -11,7 +11,7 @@ static void srvfree(Srv *);
static char *getremotesys(char*); static char *getremotesys(char*);
void void
_listensrv(Srv *os, char *addr) listensrv(Srv *os, char *addr)
{ {
Srv *s; Srv *s;
@ -33,9 +33,9 @@ _listensrv(Srv *os, char *addr)
s->spid = 0; s->spid = 0;
s->free = nil; s->free = nil;
if(_forker == nil) if(s->forker == nil)
sysfatal("no forker"); s->forker = srvforker;
_forker(listenproc, s, 0); (*s->forker)(listenproc, s, 0);
} }
static void static void
@ -72,7 +72,7 @@ listenproc(void *v)
s->addr = getremotesys(ndir); s->addr = getremotesys(ndir);
s->infd = s->outfd = data; s->infd = s->outfd = data;
s->free = srvfree; s->free = srvfree;
_forker(srvproc, s, 0); (*s->forker)(srvproc, s, 0);
} }
free(os->addr); free(os->addr);
free(os); free(os);

View file

@ -7,17 +7,24 @@ OFILES=\
fid.$O\ fid.$O\
file.$O\ file.$O\
intmap.$O\ intmap.$O\
listen.$O\
mem.$O\ mem.$O\
req.$O\ req.$O\
parse.$O\ parse.$O\
post.$O\
queue.$O\ queue.$O\
rfork.$O\
srv.$O\
thread.$O\
uid.$O\ uid.$O\
util.$O\ util.$O\
srv.$O\
post.$O\
mount.$O\
share.$O\
listen.$O\
rfork.$O\
thread.$O\
threadsrv.$O\
threadpostsrv.$O\
threadpostmountsrv.$O\
threadpostsharesrv.$O\
threadlistensrv.$O\
HFILES=/sys/include/9p.h HFILES=/sys/include/9p.h

19
sys/src/lib9p/mount.c Normal file
View file

@ -0,0 +1,19 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include <auth.h>
void
postmountsrv(Srv *s, char *name, char *mtpt, int flag)
{
postsrv(s, name);
if(mtpt != nil){
if(amount(s->srvfd, mtpt, flag, "") == -1)
sysfatal("mount %s: %r", mtpt);
/* mount closed s->srvfd */
} else
close(s->srvfd);
}

View file

@ -8,15 +8,13 @@
static void static void
postproc(void *v) postproc(void *v)
{ {
Srv *s; Srv *s = v;
s = v;
rendezvous(0, 0); rendezvous(0, 0);
close(s->srvfd); close(s->srvfd);
srv(s); srv(s);
} }
static void void
postsrv(Srv *s, char *name) postsrv(Srv *s, char *name)
{ {
char buf[80]; char buf[80];
@ -37,9 +35,9 @@ postsrv(Srv *s, char *name)
} else } else
cfd = -1; cfd = -1;
if(_forker == nil) if(s->forker == nil)
sysfatal("no forker"); s->forker = srvforker;
_forker(postproc, s, RFNAMEG|RFNOTEG); (*s->forker)(postproc, s, RFNAMEG|RFNOTEG);
rfork(RFFDG); rfork(RFFDG);
rendezvous(0, 0); rendezvous(0, 0);
@ -51,43 +49,3 @@ postsrv(Srv *s, char *name)
if(cfd >= 0) if(cfd >= 0)
close(cfd); close(cfd);
} }
void
_postmountsrv(Srv *s, char *name, char *mtpt, int flag)
{
postsrv(s, name);
if(mtpt != nil){
if(amount(s->srvfd, mtpt, flag, "") == -1)
sysfatal("mount %s: %r", mtpt);
/* mount closed s->srvfd */
} else
close(s->srvfd);
}
void
_postsharesrv(Srv *s, char *name, char *mtpt, char *desc)
{
char buf[80];
int cfd;
if(mtpt != nil && desc != nil){
snprint(buf, sizeof buf, "#σc/%s", mtpt);
if((cfd = create(buf, OREAD, DMDIR|0700)) >= 0)
close(cfd);
snprint(buf, sizeof buf, "#σc/%s/%s", mtpt, desc);
if((cfd = create(buf, OWRITE|ORCLOSE|OCEXEC, 0600)) < 0)
sysfatal("create %s: %r", buf);
} else
cfd = -1;
postsrv(s, name);
if(cfd >= 0){
if(fprint(cfd, "%d\n", s->srvfd) < 0)
sysfatal("write %s: %r", buf);
close(cfd);
}
close(s->srvfd);
}

View file

@ -4,8 +4,8 @@
#include <thread.h> #include <thread.h>
#include <9p.h> #include <9p.h>
static void void
rforker(void (*fn)(void*), void *arg, int flag) srvforker(void (*fn)(void*), void *arg, int flag)
{ {
switch(rfork(RFPROC|RFMEM|RFNOWAIT|flag)){ switch(rfork(RFPROC|RFMEM|RFNOWAIT|flag)){
case -1: case -1:
@ -17,24 +17,3 @@ rforker(void (*fn)(void*), void *arg, int flag)
_exits(0); _exits(0);
} }
} }
void
listensrv(Srv *s, char *addr)
{
_forker = rforker;
_listensrv(s, addr);
}
void
postmountsrv(Srv *s, char *name, char *mtpt, int flag)
{
_forker = rforker;
_postmountsrv(s, name, mtpt, flag);
}
void
postsharesrv(Srv *s, char *name, char *mtpt, char *desc)
{
_forker = rforker;
_postsharesrv(s, name, mtpt, desc);
}

33
sys/src/lib9p/share.c Normal file
View file

@ -0,0 +1,33 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include <auth.h>
void
postsharesrv(Srv *s, char *name, char *mtpt, char *desc)
{
char buf[80];
int cfd;
if(mtpt != nil && desc != nil){
snprint(buf, sizeof buf, "#σc/%s", mtpt);
if((cfd = create(buf, OREAD, DMDIR|0700)) >= 0)
close(cfd);
snprint(buf, sizeof buf, "#σc/%s/%s", mtpt, desc);
if((cfd = create(buf, OWRITE|ORCLOSE|OCEXEC, 0600)) < 0)
sysfatal("create %s: %r", buf);
} else
cfd = -1;
postsrv(s, name);
if(cfd >= 0){
if(fprint(cfd, "%d\n", s->srvfd) < 0)
sysfatal("write %s: %r", buf);
close(cfd);
}
close(s->srvfd);
}

View file

@ -5,8 +5,6 @@
#include <thread.h> #include <thread.h>
#include <9p.h> #include <9p.h>
void (*_forker)(void(*)(void*), void*, int);
static char Ebadattach[] = "unknown specifier in attach"; static char Ebadattach[] = "unknown specifier in attach";
static char Ebadoffset[] = "bad offset"; static char Ebadoffset[] = "bad offset";
static char Ebadcount[] = "bad count"; static char Ebadcount[] = "bad count";
@ -813,7 +811,7 @@ srvrelease(Srv *srv)
{ {
if(decref(&srv->sref) == 0){ if(decref(&srv->sref) == 0){
incref(&srv->sref); incref(&srv->sref);
_forker(srvwork, srv, 0); (*srv->forker)(srvwork, srv, 0);
} }
qunlock(&srv->slock); qunlock(&srv->slock);
} }
@ -843,6 +841,9 @@ srv(Srv *srv)
if(srv->start) if(srv->start)
srv->start(srv); srv->start(srv);
if(srv->forker == nil)
srv->forker = srvforker;
incref(&srv->sref); incref(&srv->sref);
srvwork(srv); srvwork(srv);
} }

View file

@ -4,29 +4,8 @@
#include <thread.h> #include <thread.h>
#include <9p.h> #include <9p.h>
static void void
tforker(void (*fn)(void*), void *arg, int rflag) threadsrvforker(void (*fn)(void*), void *arg, int rflag)
{ {
procrfork(fn, arg, 32*1024, rflag); procrfork(fn, arg, 32*1024, rflag);
} }
void
threadlistensrv(Srv *s, char *addr)
{
_forker = tforker;
_listensrv(s, addr);
}
void
threadpostmountsrv(Srv *s, char *name, char *mtpt, int flag)
{
_forker = tforker;
_postmountsrv(s, name, mtpt, flag);
}
void
threadpostsharesrv(Srv *s, char *name, char *mtpt, char *desc)
{
_forker = tforker;
_postsharesrv(s, name, mtpt, desc);
}

View file

@ -0,0 +1,13 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
void
threadlistensrv(Srv *s, char *addr)
{
if(s->forker == nil)
s->forker = threadsrvforker;
listensrv(s, addr);
}

View file

@ -0,0 +1,13 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
void
threadpostmountsrv(Srv *s, char *name, char *mtpt, int flag)
{
if(s->forker == nil)
s->forker = threadsrvforker;
postmountsrv(s, name, mtpt, flag);
}

View file

@ -0,0 +1,13 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
void
threadpostsharesrv(Srv *s, char *name, char *mtpt, char *desc)
{
if(s->forker == nil)
s->forker = threadsrvforker;
postsharesrv(s, name, mtpt, desc);
}

View file

@ -0,0 +1,13 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
void
threadpostsrv(Srv *s, char *name)
{
if(s->forker == nil)
s->forker = threadsrvforker;
postsrv(s, name);
}

13
sys/src/lib9p/threadsrv.c Normal file
View file

@ -0,0 +1,13 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
void
threadsrv(Srv *s)
{
if(s->forker == nil)
s->forker = threadsrvforker;
srv(s);
}