From 4d47b51dd493933e275bbc8da09321a136de367f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 15 Feb 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-02-15 --- port/devsdp.c | 48 ++++++++++++++++++++++++-------------- port/error.h | 1 + port/sysfile.c | 63 +++++++++++++++++++++++++++++++++----------------- 3 files changed, 74 insertions(+), 38 deletions(-) diff --git a/port/devsdp.c b/port/devsdp.c index 59bd2b2cb1aa262c7ba28728a5f34deac6aa337e..ecdb6c3be97ca833281547ea86103fb9b58362f3 100644 --- a/port/devsdp.c +++ b/port/devsdp.c @@ -188,6 +188,7 @@ enum { ConOpenAck, ConOpenAckAck, ConClose, + ConCloseAck, ConReset, }; @@ -442,7 +443,7 @@ sdpopen(Chan* ch, int omode) case Qstats: case Qrstats: c = sdp->conv[CONV(ch->qid)]; -print("open %d:%d: ref=%d\n", c->id, TYPE(ch->qid), c->ref); +print("open %d:%ld: ref=%d\n", c->id, TYPE(ch->qid), c->ref); qlock(c); if(waserror()) { qunlock(c); @@ -717,7 +718,7 @@ sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp) switch(TYPE(c->qid)){ case Qtopdir: case Qsdpdir: - snprint(buf, sizeof(buf), "#E%d", c->dev); + snprint(buf, sizeof(buf), "#E%ld", c->dev); devdir(c, (Qid){CHDIR|Qtopdir, 0}, buf, 0, eve, 0555, dp); break; case Qconvdir: @@ -1199,6 +1200,21 @@ conviput(Conv *c, Block *b, int control) return nil; } + switch(c->state) { + case CInit: + case CDial: + c->lstats.inBadOther++; + convoconnect(c, ConReset, c->dialid, c->acceptid); + convsetstate(c, CClosed); + break; + case CAccept: + case CRemoteClose: + case CLocalClose: + c->lstats.inBadOther++; + freeb(b); + return nil; + } + seq = (b->rp[0]<<16) + (b->rp[1]<<8) + b->rp[2]; b->rp += 3; @@ -1328,6 +1344,11 @@ conviconnect(Conv *c, int subtype, Block *b) print("conviconnect: %s: %d %uld %uld\n", convstatename[c->state], subtype, dialid, acceptid); + if(subtype == ConReset) { + convsetstate(c, CClosed); + return; + } + switch(c->state) { default: panic("unknown state: %d", c->state); @@ -1380,37 +1401,29 @@ print("conviconnect: %s: %d %uld %uld\n", convstatename[c->state], subtype, dial convsetstate(c, COpen); return; case COpen: + case CLocalClose: + case CRemoteClose: // duplicate that we ignore return; } break; case ConClose: - convoconnect(c, ConReset, dialid, acceptid); switch(c->state) { - case CInit: - case CDial: - case CAccept: - case CLocalClose: - convsetstate(c, CClosed); - return; case COpen: + convoconnect(c, ConCloseAck, dialid, acceptid); convsetstate(c, CRemoteClose); return; case CRemoteClose: + // duplicate ConClose + convoconnect(c, ConCloseAck, dialid, acceptid); return; } break; - case ConReset: + case ConCloseAck: switch(c->state) { - case CInit: - case CDial: - case CAccept: - case COpen: case CLocalClose: convsetstate(c, CClosed); return; - case CRemoteClose: - return; } break; } @@ -1418,6 +1431,7 @@ Reset: // invalid connection message - reset to sender print("invalid conviconnect - sending reset\n"); convoconnect(c, ConReset, dialid, acceptid); + convsetstate(c, CClosed); } static void @@ -1637,7 +1651,7 @@ readcontrol(Conv *c, int n) qlock(c); // this lock is not held during the sleep below for(;;) { - if(c->state == CInit || c->state == CClosed) { + if(c->chan == nil || c->state == CClosed) { qunlock(c); print("readcontrol: return error - state = %s\n", convstatename[c->state]); error("conversation closed"); diff --git a/port/error.h b/port/error.h index 0e69e1428146cc7b881a70ec68b340f917cc10e9..8badd47734f80e5d2a4e0dd553501a9eeb8bd758 100644 --- a/port/error.h +++ b/port/error.h @@ -39,6 +39,7 @@ extern char Eioload[]; /* i/o error in demand load */ extern char Enovmem[]; /* virtual memory allocation failed */ extern char Ebadld[]; /* illegal line discipline */ extern char Ebadfd[]; /* fd out of range or not open */ +extern char Enofd[]; /* no free file descriptors */ extern char Eisstream[]; /* seek on a stream */ extern char Ebadexec[]; /* exec header invalid */ extern char Etimedout[]; /* connection timed out */ diff --git a/port/sysfile.c b/port/sysfile.c index fcee5e7f2618f6e4580a7190e9eda31b399bfeb2..dd41c9c47ebb48a7603d900c3ab2c201db8c8f05 100644 --- a/port/sysfile.c +++ b/port/sysfile.c @@ -10,28 +10,22 @@ */ int -newfd(Chan *c) +growfd(Fgrp *f, int fd) /* fd is always >= 0 */ { - int i; - Fgrp *f = up->fgrp; Chan **newfd, **oldfd; - lock(f); - for(i=0; infd; i++) - if(f->fd[i] == 0){ - if(i > f->maxfd) - f->maxfd = i; - f->fd[i] = c; - unlock(f); - return i; - } + if(fd < f->nfd) + return 0; + if(fd >= f->nfd+DELTAFD) + return -1; /* out of range */ + if(fd % 100 == 0) + pprint("warning: process exceeds %d file descriptors\n", fd); /* * Unbounded allocation is unwise; besides, there are only 16 bits * of fid in 9P */ if(f->nfd >= 5000){ - Exhausted: - unlock(f); + Exhausted: exhausted("file descriptors"); return -1; } @@ -41,14 +35,33 @@ newfd(Chan *c) oldfd = f->fd; memmove(newfd, oldfd, f->nfd*sizeof(Chan*)); f->fd = newfd; + free(oldfd); f->nfd += DELTAFD; - f->maxfd = i; - f->fd[i] = c; + if(fd > f->maxfd) + f->maxfd = fd; + return 1; +} + +int +newfd(Chan *c) +{ + int fd; + Fgrp *f; + + f = up->fgrp; + lock(f); + for(fd=0; fdnfd; fd++) + if(f->fd[fd] == 0) + break; + if(fd >= f->nfd && growfd(f, fd) < 0){ + unlock(f); + return -1; + } + if(fd > f->maxfd) + f->maxfd = fd; + f->fd[fd] = c; unlock(f); - free(oldfd); - if(i%100 == 0) - pprint("warning: process exceeds %d file descriptors\n", i); - return i; + return fd; } Chan* @@ -155,6 +168,8 @@ syspipe(ulong *arg) c[1] = d->open(c[1], ORDWR); fd[0] = newfd(c[0]); fd[1] = newfd(c[1]); + if(fd[0] < 0 || fd[1] < 0) + error(Enofd); ((long*)arg[0])[0] = fd[0]; ((long*)arg[0])[1] = fd[1]; poperror(); @@ -175,7 +190,7 @@ sysdup(ulong *arg) fd = arg[1]; if(fd != -1){ lock(f); - if(fd<0 || f->nfd<=fd) { + if(fd<0 || growfd(f, fd)<0) { unlock(f); cclose(c); error(Ebadfd); @@ -194,6 +209,8 @@ sysdup(ulong *arg) nexterror(); } fd = newfd(c); + if(fd < 0) + error(Enofd); poperror(); } @@ -215,6 +232,8 @@ sysopen(ulong *arg) validaddr(arg[0], 1, 0); c = namec((char*)arg[0], Aopen, arg[1], 0); fd = newfd(c); + if(fd < 0) + error(Enofd); poperror(); return fd; } @@ -724,6 +743,8 @@ syscreate(ulong *arg) validaddr(arg[0], 1, 0); c = namec((char*)arg[0], Acreate, arg[1], arg[2]); fd = newfd(c); + if(fd < 0) + error(Enofd); poperror(); return fd; }