ref: c3d2d3f2ab7e0ad244661511ed328510bc1aeab1
parent: 01ed94c60df156518ce434401dfd471dd620ae4e
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Feb 22 15:52:48 EST 2025
gefs: cleanly reject too many connections before this commit, gefs would allow many attempts to attach, but would blow up when we ran out of epoch ids; now, we should log an error and reject the connection.
--- a/sys/src/cmd/gefs/blk.c
+++ b/sys/src/cmd/gefs/blk.c
@@ -849,6 +849,7 @@
{
ulong ge;
+ assert(tid >= 0);
ge = agetl(&fs->epoch);
asetl(&fs->lepoch[tid], ge | Eactive);
}
@@ -858,6 +859,7 @@
{
ulong le;
+ assert(tid >= 0);
le = agetl(&fs->lepoch[tid]);
asetl(&fs->lepoch[tid], le &~ Eactive);
}
--- a/sys/src/cmd/gefs/dat.h
+++ b/sys/src/cmd/gefs/dat.h
@@ -84,6 +84,7 @@
Leafspc = Blksz - Leafhdsz,
Msgmax = 1 + (Kvmax > Kpmax ? Kvmax : Kpmax),
Estacksz = 64,
+ Maxprocs = 128,
};
enum {
@@ -516,6 +517,7 @@
long syncing;
long nsyncers;
long nreaders;
+ long nprocs;
QLock synclk;
Rendez syncrz;
--- a/sys/src/cmd/gefs/fns.h
+++ b/sys/src/cmd/gefs/fns.h
@@ -64,7 +64,6 @@
void freeblk(Tree*, Blk*);
void freebp(Tree*, Bptr);
int logbarrier(Arena *, vlong);
-void dlappend(Dlist *dl, Bptr);
void killblk(Tree*, Bptr);
ushort blkfill(Blk*);
uvlong blkhash(Blk*);
--- a/sys/src/cmd/gefs/main.c
+++ b/sys/src/cmd/gefs/main.c
@@ -189,26 +189,39 @@
}
}
-static void
-launch(void (*f)(int, void *), void *arg, char *text)
+static int
+launch(void (*f)(int, void *), void *arg, long id, char *text)
{
- long pid, id;
+ long pid;
- assert(fs->nworker < nelem(fs->lepoch));
+ assert(id == -1 || id < nelem(fs->lepoch));
+ if(aincl(&fs->nprocs, 1) >= Maxprocs){
+ werrstr("too many worker procs\n");
+ return -1;
+ }
pid = rfork(RFPROC|RFMEM|RFNOWAIT);
if (pid < 0)
- sysfatal("can't fork: %r");
+ werrstr("fork: %r");
if (pid == 0) {
- id = aincl(&fs->nworker, 1);
if((*errctx = mallocz(sizeof(Errctx), 1)) == nil)
sysfatal("malloc: %r");
(*errctx)->tid = id;
procsetname("%s.%ld", text, id);
(*f)(id, arg);
+ aincl(&fs->nprocs, -1);
exits("child returned");
}
+ return pid;
}
+/* launches a proc that must start, kills the file system if it fails */
+static void
+xlaunch(void (*f)(int, void*), void *arg, long id, char *text)
+{
+ if(launch(f, arg, id, text) == -1)
+ sysfatal("setting up initial proc set failed: %r");
+}
+
static int
postfd(char *name, char *suff, int mode)
{
@@ -255,7 +268,10 @@
close(fd);
continue;
}
- launch(runfs, c, "netio");
+ if(launch(runfs, c, -1, "netio") == -1){
+ fprint(2, "listener failed: %r");
+ putconn(c);
+ }
}
close(actl);
}
@@ -411,25 +427,25 @@
fs->arenas[i].sync = &fs->syncq[i%fs->nsyncers];
srvfd = postfd(srvname, "", 0666);
ctlfd = postfd(srvname, ".cmd", 0600);
- launch(runcons, (void*)ctlfd, "ctl");
- launch(runmutate, nil, "mutate");
- launch(runsweep, nil, "sweep");
- launch(runtasks, nil, "tasks");
+ xlaunch(runcons, (void*)ctlfd, aincl(&fs->nworker, 1), "ctl");
+ xlaunch(runmutate, nil, aincl(&fs->nworker, 1), "mutate");
+ xlaunch(runsweep, nil, aincl(&fs->nworker, 1), "sweep");
+ xlaunch(runtasks, nil, aincl(&fs->nworker, 1), "tasks");
for(i = 0; i < fs->nreaders; i++)
- launch(runread, fs->rdchan[i], "readio");
+ xlaunch(runread, fs->rdchan[i], aincl(&fs->nworker, 1), "readio");
for(i = 0; i < fs->nsyncers; i++)
- launch(runsync, &fs->syncq[i], "syncio");
+ xlaunch(runsync, &fs->syncq[i], aincl(&fs->nworker, 1), "syncio");
for(i = 0; i < nann; i++)
- launch(runannounce, ann[i], "announce");
+ xlaunch(runannounce, ann[i], -1, "announce");
if(srvfd != -1){
if((c = newconn(srvfd, srvfd, -1)) == nil)
sysfatal("%r");
- launch(runfs, c, "srvio");
+ xlaunch(runfs, c, -1, "srvio");
}
if(stdio){
if((c = newconn(0, 1, -1)) == nil)
sysfatal("%r");
- launch(runfs, c, "stdio");
+ xlaunch(runfs, c, -1, "stdio");
}
exits(nil);
}
--
⑨