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 */
void (*forker)(void (*)(void*), void*, int);
void (*free)(Srv*);
};
void srvforker(void (*)(void*), void*, int);
void threadsrvforker(void (*)(void*), void*, int);
void srv(Srv*);
void postsrv(Srv*, char*);
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 listensrv(Srv*, char*);
void _listensrv(Srv*, char*);
int chatty9p;
void respond(Req*, char*);
void responderror(Req*);
void threadsrv(Srv*);
void threadpostsrv(Srv*, char*);
void threadpostmountsrv(Srv*, char*, char*, int);
void threadpostsharesrv(Srv*, char*, char*, char*);
void threadlistensrv(Srv *s, char *addr);
int chatty9p;
void respond(Req*, char*);
void responderror(Req*);
/*
* Helper. Assumes user is same as group.
*/
@ -276,8 +282,6 @@ void authwrite(Req*);
void authdestroy(Fid*);
int authattach(Req*);
extern void (*_forker)(void (*)(void*), void*, int);
void srvacquire(Srv *);
void srvrelease(Srv *);

View file

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

View file

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

View file

@ -7,17 +7,24 @@ OFILES=\
fid.$O\
file.$O\
intmap.$O\
listen.$O\
mem.$O\
req.$O\
parse.$O\
post.$O\
queue.$O\
rfork.$O\
srv.$O\
thread.$O\
uid.$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

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
postproc(void *v)
{
Srv *s;
s = v;
Srv *s = v;
rendezvous(0, 0);
close(s->srvfd);
srv(s);
}
static void
void
postsrv(Srv *s, char *name)
{
char buf[80];
@ -37,9 +35,9 @@ postsrv(Srv *s, char *name)
} else
cfd = -1;
if(_forker == nil)
sysfatal("no forker");
_forker(postproc, s, RFNAMEG|RFNOTEG);
if(s->forker == nil)
s->forker = srvforker;
(*s->forker)(postproc, s, RFNAMEG|RFNOTEG);
rfork(RFFDG);
rendezvous(0, 0);
@ -51,43 +49,3 @@ postsrv(Srv *s, char *name)
if(cfd >= 0)
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 <9p.h>
static void
rforker(void (*fn)(void*), void *arg, int flag)
void
srvforker(void (*fn)(void*), void *arg, int flag)
{
switch(rfork(RFPROC|RFMEM|RFNOWAIT|flag)){
case -1:
@ -17,24 +17,3 @@ rforker(void (*fn)(void*), void *arg, int flag)
_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 <9p.h>
void (*_forker)(void(*)(void*), void*, int);
static char Ebadattach[] = "unknown specifier in attach";
static char Ebadoffset[] = "bad offset";
static char Ebadcount[] = "bad count";
@ -813,7 +811,7 @@ srvrelease(Srv *srv)
{
if(decref(&srv->sref) == 0){
incref(&srv->sref);
_forker(srvwork, srv, 0);
(*srv->forker)(srvwork, srv, 0);
}
qunlock(&srv->slock);
}
@ -843,6 +841,9 @@ srv(Srv *srv)
if(srv->start)
srv->start(srv);
if(srv->forker == nil)
srv->forker = srvforker;
incref(&srv->sref);
srvwork(srv);
}

View file

@ -4,29 +4,8 @@
#include <thread.h>
#include <9p.h>
static void
tforker(void (*fn)(void*), void *arg, int rflag)
void
threadsrvforker(void (*fn)(void*), void *arg, int 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);
}