Fcall reply; /* Incoming reply */
Mnt* m; /* Mount device during rpc */
Rendez* z; /* Place to hang out */
- uchar* rpc; /* I/O Data buffer */
- uint rpclen; /* len of buffer */
+ Block* w; /* copy of write rpc for cache */
Block* b; /* reply blocks */
- uvlong stime; /* start time for mnt statistics */
- ulong reqlen; /* request length for mnt statistics */
- ulong replen; /* reply length for mnt statistics */
Mntrpc* flushed; /* message this one flushes */
char done; /* Rpc completed */
};
enum
{
- TAGSHIFT = 5, /* ulong has to be 32 bits */
+ TAGSHIFT = 5,
TAGMASK = (1<<TAGSHIFT)-1,
NMASK = (64*1024)>>TAGSHIFT,
};
-struct Mntalloc
+static struct Mntalloc
{
Lock;
Mnt* list; /* Mount devices in use */
Mnt* mntfree; /* Free list */
Mntrpc* rpcfree;
- int nrpcfree;
- int nrpcused;
+ ulong nrpcfree;
+ ulong nrpcused;
ulong id;
- ulong tagmask[NMASK];
-}mntalloc;
-
-Mnt* mntchk(Chan*);
-void mntdirfix(uchar*, Chan*);
-Mntrpc* mntflushalloc(Mntrpc*, ulong);
-void mntflushfree(Mnt*, Mntrpc*);
-void mntfree(Mntrpc*);
-void mntgate(Mnt*);
-void mntqrm(Mnt*, Mntrpc*);
-Mntrpc* mntralloc(Chan*, ulong);
-long mntrdwr(int, Chan*, void*, long, vlong);
-int mntrpcread(Mnt*, Mntrpc*);
-void mountio(Mnt*, Mntrpc*);
-void mountmux(Mnt*, Mntrpc*);
-void mountrpc(Mnt*, Mntrpc*);
-int rpcattn(void*);
-Chan* mntchan(void);
+ u32int tagmask[NMASK];
+} mntalloc;
+
+static Chan* mntchan(void);
+static Mnt* mntchk(Chan*);
+static void mntdirfix(uchar*, Chan*);
+static Mntrpc* mntflushalloc(Mntrpc*);
+static Mntrpc* mntflushfree(Mnt*, Mntrpc*);
+static void mntfree(Mntrpc*);
+static void mntgate(Mnt*);
+static void mntqrm(Mnt*, Mntrpc*);
+static Mntrpc* mntralloc(Chan*);
+static long mntrdwr(int, Chan*, void*, long, vlong);
+static int mntrpcread(Mnt*, Mntrpc*);
+static void mountio(Mnt*, Mntrpc*);
+static void mountmux(Mnt*, Mntrpc*);
+static void mountrpc(Mnt*, Mntrpc*);
+static int rpcattn(void*);
+
+#define cachedchan(c) (((c)->flag & CCACHE) != 0 && (c)->mcp != nil)
char Esbadstat[] = "invalid directory entry received from server";
char Enoversion[] = "version not established for mount channel";
-void (*mntstats)(int, Chan*, uvlong, ulong);
-
static void
mntreset(void)
{
mntalloc.id = 1;
mntalloc.tagmask[0] = 1; /* don't allow 0 as a tag */
- mntalloc.tagmask[NMASK-1] = 0x80000000UL; /* don't allow NOTAG */
+ mntalloc.tagmask[NMASK-1] = 0x80000000; /* don't allow NOTAG */
fmtinstall('F', fcallfmt);
fmtinstall('D', dirfmt);
/* We can't install %M since eipfmt does and is used in the kernel [sape] */
/*
* Version is not multiplexed: message sent only once per connection.
*/
-long
+int
mntversion(Chan *c, char *version, int msize, int returnlen)
{
Fcall f;
unlock(c);
l = devtab[c->type]->write(c, msg, k, oo);
-
if(l < k){
lock(c);
c->offset -= k - l;
}
/* message sent; receive and decode reply */
- k = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset);
- if(k <= 0)
- error("EOF receiving fversion reply");
-
- lock(c);
- c->offset += k;
- unlock(c);
+ for(k = 0; k < BIT32SZ || (k < GBIT32(msg) && k < 8192+IOHDRSZ); k += l){
+ l = devtab[c->type]->read(c, msg+k, 8192+IOHDRSZ-k, c->offset);
+ if(l <= 0)
+ error("EOF receiving fversion reply");
+ lock(c);
+ c->offset += l;
+ unlock(c);
+ }
l = convM2S(msg, k, &f);
if(l != k)
/* now build Mnt associated with this connection */
lock(&mntalloc);
m = mntalloc.mntfree;
- if(m != 0)
+ if(m != nil)
mntalloc.mntfree = m->list;
else {
+ unlock(&mntalloc);
m = malloc(sizeof(Mnt));
- if(m == 0) {
+ if(m == nil) {
qfree(q);
free(v);
- unlock(&mntalloc);
exhausted("mount devices");
}
+ lock(&mntalloc);
}
m->list = mntalloc.list;
mntalloc.list = m;
free(msg);
lock(m);
- m->queue = 0;
- m->rip = 0;
+ m->queue = nil;
+ m->rip = nil;
c->flag |= CMSG;
c->mux = m;
Mntrpc *r;
m = c->mux;
-
if(m == nil){
- mntversion(c, VERSION9P, MAXRPC, 0);
+ mntversion(c, nil, 0, 0);
m = c->mux;
if(m == nil)
error(Enoversion);
nexterror();
}
- r = mntralloc(0, m->msize);
-
+ r = mntralloc(c);
if(waserror()) {
mntfree(r);
nexterror();
incref(m->c);
c->mqid = c->qid;
c->mode = ORDWR;
+ c->iounit = m->msize-IOHDRSZ;
poperror(); /* r */
mntfree(r);
}
-static Chan*
-mntattach(char *muxattach)
+Chan*
+mntattach(Chan *c, Chan *ac, char *spec, int flags)
{
Mnt *m;
- Chan *c;
Mntrpc *r;
- struct bogus{
- Chan *chan;
- Chan *authchan;
- char *spec;
- int flags;
- }bogus;
- bogus = *((struct bogus *)muxattach);
- c = bogus.chan;
+ if(ac != nil && ac->mchan != c)
+ error(Ebadusefd);
m = c->mux;
-
if(m == nil){
mntversion(c, nil, 0, 0);
m = c->mux;
nexterror();
}
- r = mntralloc(0, m->msize);
-
+ r = mntralloc(c);
if(waserror()) {
mntfree(r);
nexterror();
}
-
r->request.type = Tattach;
r->request.fid = c->fid;
- if(bogus.authchan == nil)
+ if(ac == nil)
r->request.afid = NOFID;
else
- r->request.afid = bogus.authchan->fid;
+ r->request.afid = ac->fid;
r->request.uname = up->user;
- r->request.aname = bogus.spec;
+ r->request.aname = spec;
mountrpc(m, r);
c->qid = r->reply.qid;
poperror(); /* c */
- if(bogus.flags&MCACHE)
+ if(flags&MCACHE)
c->flag |= CCACHE;
return c;
}
-Chan*
+static Chan*
+noattach(char *)
+{
+ error(Enoattach);
+ return nil;
+}
+
+static Chan*
mntchan(void)
{
Chan *c;
c->dev = mntalloc.id++;
unlock(&mntalloc);
- if(c->mchan)
+ if(c->mchan != nil)
panic("mntchan non-zero %p", c->mchan);
return c;
}
alloc = 0;
m = mntchk(c);
- r = mntralloc(c, m->msize);
+ r = mntralloc(c);
if(nc == nil){
nc = devclone(c);
/*
if(n < BIT16SZ)
error(Eshortstat);
m = mntchk(c);
- r = mntralloc(c, m->msize);
+ r = mntralloc(c);
if(waserror()) {
mntfree(r);
nexterror();
Mntrpc *r;
m = mntchk(c);
- r = mntralloc(c, m->msize);
+ r = mntralloc(c);
if(waserror()) {
mntfree(r);
nexterror();
poperror();
mntfree(r);
- if(c->flag & CCACHE)
- copen(c);
+ if(c->flag & CCACHE){
+ if(copen(c))
+ if(type == Tcreate || (omode&OTRUNC) != 0)
+ ctrunc(c);
+ }
return c;
}
Mnt *m;
Mntrpc *r;
+ cclunk(c);
m = mntchk(c);
- r = mntralloc(c, m->msize);
- if(waserror()){
+ r = mntralloc(c);
+ if(waserror()) {
mntfree(r);
nexterror();
}
-
r->request.type = t;
r->request.fid = c->fid;
mountrpc(m, r);
lock(&mntalloc);
l = &mntalloc.list;
- for(f = *l; f; f = f->list) {
+ for(f = *l; f != nil; f = f->list) {
if(f == m) {
*l = m->list;
break;
Mntrpc *r;
m = mntchk(c);
- r = mntralloc(c, m->msize);
+ r = mntralloc(c);
if(waserror()) {
mntfree(r);
nexterror();
mountrpc(m, r);
poperror();
mntfree(r);
+
+ if(c->flag & CCACHE)
+ if(GBIT64(&dp[STATFIXLEN-4*BIT16SZ-BIT64SZ]) != ~0ULL)
+ ctrunc(c);
+
return n;
}
mntread(Chan *c, void *buf, long n, vlong off)
{
uchar *p, *e;
- int nc, cache, isdir, dirlen;
-
- isdir = 0;
- cache = c->flag & CCACHE;
- if(c->qid.type & QTDIR) {
- cache = 0;
- isdir = 1;
- }
+ int dirlen;
p = buf;
- if(cache) {
- nc = cread(c, buf, n, off);
- if(nc > 0) {
- n -= nc;
- if(n == 0)
- return nc;
- p += nc;
- off += nc;
- }
- n = mntrdwr(Tread, c, p, n, off);
- cupdate(c, p, n, off);
- return n + nc;
- }
-
- n = mntrdwr(Tread, c, buf, n, off);
- if(isdir) {
+ n = mntrdwr(Tread, c, p, n, off);
+ if(c->qid.type & QTDIR) {
for(e = &p[n]; p+BIT16SZ < e; p += dirlen){
dirlen = BIT16SZ+GBIT16(p);
if(p+dirlen > e)
return mntrdwr(Twrite, c, buf, n, off);
}
-long
+static void
+mntcache(Mntrpc *r)
+{
+ ulong n, m;
+ vlong off;
+ Block *b;
+ Chan *c;
+
+ c = r->c;
+ if(!cachedchan(c))
+ return;
+ off = r->request.offset;
+ switch(r->reply.type){
+ case Rread:
+ m = r->reply.count;
+ if(m > r->request.count)
+ m = r->request.count;
+ for(b = r->b; m > 0 && b != nil; m -= n, b = b->next) {
+ n = BLEN(b);
+ if(m < n)
+ n = m;
+ cupdate(c, b->rp, n, off);
+ off += n;
+ }
+ break;
+ case Rwrite:
+ b = r->w;
+ if(convM2S(b->rp, BLEN(b), &r->request) == 0)
+ panic("convM2S");
+ m = r->reply.count;
+ if(m > r->request.count)
+ m = r->request.count;
+ cwrite(c, (uchar*)r->request.data, m, off);
+ break;
+ }
+}
+
+static long
mntrdwr(int type, Chan *c, void *buf, long n, vlong off)
{
Mnt *m;
Mntrpc *r;
char *uba;
- int cache;
ulong cnt, nr, nreq;
m = mntchk(c);
uba = buf;
cnt = 0;
- cache = c->flag & CCACHE;
- if(c->qid.type & QTDIR)
- cache = 0;
+
for(;;) {
- r = mntralloc(c, m->msize);
+ nreq = n;
+ if(nreq > c->iounit)
+ nreq = c->iounit;
+
+ if(type == Tread && cachedchan(c)) {
+ nr = cread(c, (uchar*)uba, nreq, off);
+ if(nr > 0) {
+ nreq = nr;
+ goto Next;
+ }
+ }
+
+ r = mntralloc(c);
if(waserror()) {
mntfree(r);
nexterror();
r->request.fid = c->fid;
r->request.offset = off;
r->request.data = uba;
- nr = n;
- if(nr > m->msize-IOHDRSZ)
- nr = m->msize-IOHDRSZ;
- r->request.count = nr;
+ r->request.count = nreq;
mountrpc(m, r);
- nreq = r->request.count;
+ mntcache(r);
nr = r->reply.count;
if(nr > nreq)
nr = nreq;
-
if(type == Tread)
- r->b = bl2mem((uchar*)uba, r->b, nr);
- else if(cache)
- cwrite(c, (uchar*)uba, nr, off);
-
- poperror();
+ nr = readblist(r->b, (uchar*)uba, nr, 0);
mntfree(r);
+ poperror();
+
+ Next:
off += nr;
uba += nr;
cnt += nr;
return cnt;
}
+static int
+mntprocwork(void *a)
+{
+ Mntproc *p = a;
+ return p->f != nil;
+}
+
+static void
+mntproc(void *a)
+{
+ Mntproc *p = a;
+ Chan *c;
+ Mnt *m;
+
+ while(waserror())
+ ;
+
+ m = p->m;
+ for(;;){
+ tsleep(p, mntprocwork, p, 500);
+
+ lock(m);
+ if(p->f == nil){
+ p->m = nil;
+ unlock(m);
+ pexit("no work", 1);
+ }
+ c = p->r->c;
+ unlock(m);
+
+ (*p->f)(p->r, p->a);
+
+ lock(m);
+ p->r = nil;
+ p->a = nil;
+ p->f = nil;
+ unlock(m);
+
+ cclose(c);
+ }
+}
+
+static int
+mntdefer(void (*f)(Mntrpc*, void*), Mntrpc *r, void *a)
+{
+ Mntproc *p;
+ Mnt *m;
+ int i;
+
+ m = mntchk(r->c);
+ lock(m);
+ for(i = 0; i < nelem(m->defered); i++){
+ p = &m->defered[i];
+ if(p->f != nil)
+ continue;
+
+ incref(r->c);
+ r->m = m;
+ p->r = r;
+ p->a = a;
+ p->f = f;
+
+ if(p->m == nil){
+ p->m = m;
+ unlock(m);
+ kproc("mntproc", mntproc, p);
+ } else {
+ unlock(m);
+ wakeup(p);
+ }
+ return 1;
+ }
+ unlock(m);
+ return 0;
+}
+
+static void
+rahproc(Mntrpc *r, void *a)
+{
+ Mntrah *rah = a;
+
+ if(!waserror()){
+ mountrpc(r->m, r);
+ poperror();
+ }
+ r->done = 2;
+ wakeup(rah);
+}
+
+static int
+rahdone(void *v)
+{
+ Mntrpc *r = v;
+ return r->done == 2;
+}
+
+static Mntrpc*
+rahfindrpc(Mntrah *rah, vlong off)
+{
+ Mntrpc *r;
+ int i, n;
+ vlong o;
+
+ for(i=0; i<nelem(rah->r); i++){
+ if((r = rah->r[i]) == nil)
+ continue;
+ n = r->request.count;
+ o = r->request.offset;
+ if(off >= o && off < o+n)
+ return r;
+ }
+ return nil;
+}
+
void
+mntrahinit(Mntrah *rah)
+{
+ Mntrpc *r;
+ int i;
+
+ while(waserror())
+ ;
+
+ for(i=0; i<nelem(rah->r); i++){
+ if((r = rah->r[i]) != nil){
+ while(!rahdone(r))
+ sleep(rah, rahdone, r);
+ rah->r[i] = nil;
+ mntfree(r);
+ }
+ }
+ rah->i = 0;
+
+ rah->off = 0;
+ rah->seq = 0;
+
+ poperror();
+}
+
+long
+mntrahread(Mntrah *rah, Chan *c, uchar *buf, long len, vlong off)
+{
+ Mntrpc *r, **rr;
+ vlong o, w, e;
+ long n, tot;
+
+ if(len <= 0)
+ return 0;
+ if(off != rah->off){
+ rah->off = off;
+ if(rahfindrpc(rah, off) == nil)
+ rah->seq = 0;
+ }
+ rah->off += len;
+ rah->seq += len;
+ if(rah->seq >= 2*c->iounit){
+ w = (off / c->iounit) * c->iounit;
+ e = w + rah->seq;
+ for(o = w; o < e; o += c->iounit){
+ if(rahfindrpc(rah, o) != nil)
+ continue;
+
+ rr = &rah->r[rah->i % nelem(rah->r)];
+ if((r = *rr) != nil){
+ if(!rahdone(r) || (r->request.offset >= w && r->request.offset < e))
+ break;
+ *rr = nil;
+ mntfree(r);
+ }
+
+ r = mntralloc(c);
+ r->request.type = Tread;
+ r->request.fid = c->fid;
+ r->request.offset = o;
+ r->request.count = c->iounit;
+ if(!mntdefer(rahproc, r, rah)){
+ mntfree(r);
+ break;
+ }
+ *rr = r;
+ rah->i++;
+ }
+ }
+
+ tot = 0;
+ while(len > 0 && (r = rahfindrpc(rah, off)) != nil){
+ while(!rahdone(r))
+ sleep(rah, rahdone, r);
+
+ switch(r->reply.type){
+ default:
+ error(Emountrpc);
+ case Rflush:
+ error(Eintr);
+ case Rerror:
+ error(r->reply.ename);
+ case Rread:
+ break;
+ }
+ mntcache(r);
+ n = r->request.count;
+ o = r->request.offset;
+ if(r->reply.count < n)
+ n = r->reply.count;
+ n -= (off - o);
+ if(n <= 0)
+ break;
+ if(len < n)
+ n = len;
+ n = readblist(r->b, buf, n, off - o);
+ buf += n;
+ off += n;
+ tot += n;
+ len -= n;
+ }
+ if(tot > 0){
+ rah->off -= len;
+ rah->seq -= len;
+ }
+
+ return tot;
+}
+
+static void
mountrpc(Mnt *m, Mntrpc *r)
{
- char *sn, *cn;
int t;
r->reply.tag = 0;
default:
if(t == r->request.type+1)
break;
- sn = "?";
- if(m->c->path != nil)
- sn = m->c->path->s;
- cn = "?";
- if(r->c != nil && r->c->path != nil)
- cn = r->c->path->s;
print("mnt: proc %s %lud: mismatch from %s %s rep %#p tag %d fid %d T%d R%d rp %d\n",
- up->text, up->pid, sn, cn,
+ up->text, up->pid, chanpath(m->c), chanpath(r->c),
r, r->request.tag, r->request.fid, r->request.type,
r->reply.type, r->reply.tag);
error(Emountrpc);
}
}
-void
+static void
mountio(Mnt *m, Mntrpc *r)
{
+ Block *b;
int n;
while(waserror()) {
if(m->rip == up)
mntgate(m);
- if(strcmp(up->errstr, Eintr) != 0){
+ if(strcmp(up->errstr, Eintr) != 0 || waserror()){
+ r = mntflushfree(m, r);
switch(r->request.type){
case Tremove:
case Tclunk:
if(strcmp(up->errstr, Ehungup) != 0)
r->c->fid = 0;
}
- mntflushfree(m, r);
nexterror();
}
- r = mntflushalloc(r, m->msize);
+ r = mntflushalloc(r);
+ poperror();
}
lock(m);
unlock(m);
/* Transmit a file system rpc */
- if(m->msize == 0)
- panic("msize");
- n = convS2M(&r->request, r->rpc, m->msize);
- if(n <= 0){
+ n = sizeS2M(&r->request);
+ b = allocb(n);
+ if(waserror()){
+ freeb(b);
+ nexterror();
+ }
+ n = convS2M(&r->request, b->wp, n);
+ if(n <= 0 || n > m->msize) {
print("mountio: proc %s %lud: convS2M returned %d for tag %d fid %d T%d\n",
up->text, up->pid, n, r->request.tag, r->request.fid, r->request.type);
error(Emountrpc);
}
-
- if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n)
- error(Emountrpc);
- r->stime = fastticks(nil);
- r->reqlen = n;
+ b->wp += n;
+ if(r->request.type == Twrite && cachedchan(r->c))
+ r->w = copyblock(b, n);
+ poperror();
+ devtab[m->c->type]->bwrite(m->c, b, 0);
/* Gate readers onto the mount point one at a time */
for(;;) {
lock(m);
- if(m->rip == 0)
+ if(m->rip == nil)
break;
unlock(m);
sleep(r->z, rpcattn, r);
- if(r->done){
+ if(r->done) {
poperror();
mntflushfree(m, r);
return;
while(qlen(m->q) < len){
b = devtab[m->c->type]->bread(m->c, m->msize, 0);
- if(b == nil)
- return -1;
- if(blocklen(b) == 0){
- freeblist(b);
+ if(b == nil || qaddlist(m->q, b) == 0)
return -1;
- }
- qaddlist(m->q, b);
}
return 0;
}
-int
+static int
mntrpcread(Mnt *m, Mntrpc *r)
{
int i, t, len, hlen;
return 0;
}
-void
+static void
mntgate(Mnt *m)
{
Mntrpc *q;
lock(m);
- m->rip = 0;
- for(q = m->queue; q; q = q->list) {
+ m->rip = nil;
+ for(q = m->queue; q != nil; q = q->list) {
if(q->done == 0)
if(wakeup(q->z))
break;
unlock(m);
}
-void
+static void
mountmux(Mnt *m, Mntrpc *r)
{
Mntrpc **l, *q;
lock(m);
l = &m->queue;
- for(q = *l; q; q = q->list) {
+ for(q = *l; q != nil; q = q->list) {
/* look for a reply to a message */
if(q->request.tag == r->reply.tag) {
*l = q->list;
- if(mntstats != nil)
- (*mntstats)(q->request.type,
- m->c, q->stime,
- q->reqlen + r->replen);
- if(q != r) {
- /*
- * Completed someone else.
- * Trade pointers to receive buffer.
- */
- q->reply = r->reply;
- q->b = r->b;
- r->b = nil;
- z = q->z;
- } else
- z = nil;
- q->done = 1; /* hands off */
- if(z != nil)
- wakeup(z);
+ if(q == r) {
+ q->done = 1;
+ unlock(m);
+ return;
+ }
+ /*
+ * Completed someone else.
+ * Trade pointers to receive buffer.
+ */
+ q->reply = r->reply;
+ q->b = r->b;
+ r->b = nil;
+ z = q->z;
+ coherence();
+ q->done = 1;
+ wakeup(z);
unlock(m);
return;
}
l = &q->list;
}
unlock(m);
- print("unexpected reply tag %ud; type %d\n", r->reply.tag, r->reply.type);
+ print("mnt: unexpected reply from %s tag %ud; type %d\n",
+ chanpath(m->c), r->reply.tag, r->reply.type);
}
/*
* Create a new flush request and chain the previous
* requests from it
*/
-Mntrpc*
-mntflushalloc(Mntrpc *r, ulong iounit)
+static Mntrpc*
+mntflushalloc(Mntrpc *r)
{
Mntrpc *fr;
- fr = mntralloc(0, iounit);
-
+ fr = mntralloc(r->c);
fr->request.type = Tflush;
if(r->request.type == Tflush)
fr->request.oldtag = r->request.oldtag;
* flush and the original message from the unanswered
* request queue. Mark the original message as done
* and if it hasn't been answered set the reply to to
- * Rflush.
+ * Rflush. Return the original rpc.
*/
-void
+static Mntrpc*
mntflushfree(Mnt *m, Mntrpc *r)
{
Mntrpc *fr;
- while(r){
+ while(r != nil){
fr = r->flushed;
if(!r->done){
r->reply.type = Rflush;
mntqrm(m, r);
}
- if(fr)
- mntfree(r);
+ if(fr == nil)
+ break;
+ mntfree(r);
r = fr;
}
+ return r;
}
-int
+static int
alloctag(void)
{
int i, j;
- ulong v;
+ u32int v;
for(i = 0; i < NMASK; i++){
v = mntalloc.tagmask[i];
- if(v == ~0UL)
+ if(v == -1)
continue;
- for(j = 0; j < 1<<TAGSHIFT; j++)
- if((v & (1<<j)) == 0){
- mntalloc.tagmask[i] |= 1<<j;
- return (i<<TAGSHIFT) + j;
- }
+ for(j = 0; (v & 1) != 0; j++)
+ v >>= 1;
+ mntalloc.tagmask[i] |= 1<<j;
+ return i<<TAGSHIFT | j;
}
panic("no friggin tags left");
return NOTAG;
}
-void
+static void
freetag(int t)
{
mntalloc.tagmask[t>>TAGSHIFT] &= ~(1<<(t&TAGMASK));
}
-Mntrpc*
-mntralloc(Chan *c, ulong msize)
+static Mntrpc*
+mntralloc(Chan *c)
{
Mntrpc *new;
- lock(&mntalloc);
- new = mntalloc.rpcfree;
- if(new == nil){
+ if(mntalloc.nrpcfree == 0) {
+ Alloc:
new = malloc(sizeof(Mntrpc));
- if(new == nil) {
- unlock(&mntalloc);
+ if(new == nil)
exhausted("mount rpc header");
- }
- /*
- * The header is split from the data buffer as
- * mountmux may swap the buffer with another header.
- */
- new->rpc = mallocz(msize, 0);
- if(new->rpc == nil){
- free(new);
+ lock(&mntalloc);
+ new->request.tag = alloctag();
+ } else {
+ lock(&mntalloc);
+ new = mntalloc.rpcfree;
+ if(new == nil) {
unlock(&mntalloc);
- exhausted("mount rpc buffer");
+ goto Alloc;
}
- new->rpclen = msize;
- new->request.tag = alloctag();
- }
- else {
mntalloc.rpcfree = new->list;
mntalloc.nrpcfree--;
- if(new->rpclen < msize){
- free(new->rpc);
- new->rpc = mallocz(msize, 0);
- if(new->rpc == nil){
- free(new);
- mntalloc.nrpcused--;
- unlock(&mntalloc);
- exhausted("mount rpc buffer");
- }
- new->rpclen = msize;
- }
}
mntalloc.nrpcused++;
unlock(&mntalloc);
new->done = 0;
new->flushed = nil;
new->b = nil;
+ new->w = nil;
return new;
}
-void
+static void
mntfree(Mntrpc *r)
{
- if(r->b != nil)
- freeblist(r->b);
+ freeb(r->w);
+ freeblist(r->b);
lock(&mntalloc);
- if(mntalloc.nrpcfree >= 10){
- free(r->rpc);
- freetag(r->request.tag);
- free(r);
- }
- else{
+ mntalloc.nrpcused--;
+ if(mntalloc.nrpcfree < 32) {
r->list = mntalloc.rpcfree;
mntalloc.rpcfree = r;
mntalloc.nrpcfree++;
+ unlock(&mntalloc);
+ return;
}
- mntalloc.nrpcused--;
+ freetag(r->request.tag);
unlock(&mntalloc);
+ free(r);
}
-void
+static void
mntqrm(Mnt *m, Mntrpc *r)
{
Mntrpc **l, *f;
r->done = 1;
l = &m->queue;
- for(f = *l; f; f = f->list) {
+ for(f = *l; f != nil; f = f->list) {
if(f == r) {
*l = r->list;
break;
unlock(m);
}
-Mnt*
+static Mnt*
mntchk(Chan *c)
{
Mnt *m;
/* This routine is mostly vestiges of prior lives; now it's just sanity checking */
-
if(c->mchan == nil)
panic("mntchk 1: nil mchan c %s", chanpath(c));
m = c->mchan->mux;
-
if(m == nil)
print("mntchk 2: nil mux c %s c->mchan %s \n", chanpath(c), chanpath(c->mchan));
* reflect local values. These entries are known to be
* the first two in the Dir encoding after the count.
*/
-void
+static void
mntdirfix(uchar *dirbuf, Chan *c)
{
uint r;
PBIT32(dirbuf, c->dev);
}
-int
+static int
rpcattn(void *v)
{
Mntrpc *r;
r = v;
- return r->done || r->m->rip == 0;
+ return r->done || r->m->rip == nil;
}
Dev mntdevtab = {
mntreset,
devinit,
devshutdown,
- mntattach,
+ noattach,
mntwalk,
mntstat,
mntopen,