plan9fox/sys/src/cmd/9nfs/9p.c
cinap_lenrek a0d4c5e208 make error handling in 9p service loops consistent
when we get eof, stop the loop immidiately and do not
rely on the read to eventually return an error.

when convM2S() fails to decode the message, error out
and stop the loop. there is no point in continuing.
2016-07-24 02:21:32 +02:00

187 lines
3.3 KiB
C

#include "all.h"
static char *tnames[] = {
[Tversion] "version",
[Tauth] "auth",
[Tattach] "attach",
[Tflush] "flush",
[Twalk] "walk",
[Topen] "open",
[Tcreate] "create",
[Tread] "read",
[Twrite] "write",
[Tclunk] "clunk",
[Tremove] "remove",
[Tstat] "stat",
[Twstat] "wstat",
};
int messagesize = IOHDRSZ+Maxfdata;
int
xmesg(Session *s, int t)
{
int n;
if(chatty){
if(0 <= t && t < nelem(tnames) && tnames[t])
chat("T%s...", tnames[t]);
else
chat("T%d...", t);
}
s->f.type = t;
s->f.tag = ++s->tag;
if(p9debug)
fprint(2, "xmseg\tsend %F\n", &s->f);
n = convS2M(&s->f, s->data, messagesize);
if(niwrite(s->fd, s->data, n) != n){
clog("xmesg write error on %d: %r\n", s->fd);
return -1;
}
again:
n = read9pmsg(s->fd, s->data, messagesize);
if(n == 0)
return -1;
if(n < 0){
clog("xmesg read error: %r\n");
return -1;
}
if(convM2S(s->data, n, &s->f) != n){
clog("xmesg bad convM2S %d %.2x %.2x %.2x %.2x\n",
n, ((uchar*)s->data)[0], ((uchar*)s->data)[1],
((uchar*)s->data)[2], ((uchar*)s->data)[3]);
return -1;
}
if(p9debug)
fprint(2, "\trecv %F\n", &s->f);
if(s->f.tag != s->tag){
clog("xmesg tag %d for %d\n", s->f.tag, s->tag);
goto again;
}
if(s->f.type == Rerror){
if(t == Tclunk)
clog("xmesg clunk: %s", s->f.ename);
chat("xmesg %d error %s...", t, s->f.ename);
return -1;
}
if(s->f.type != t+1){
clog("xmesg type mismatch: %d, expected %d\n", s->f.type, t+1);
return -1;
}
return 0;
}
int
clunkfid(Session *s, Fid *f)
{
putfid(s, f);
if(s == 0 || f == 0)
return 0;
s->f.fid = f - s->fids;
return xmesg(s, Tclunk);
}
#define UNLINK(p) ((p)->prev->next = (p)->next, (p)->next->prev = (p)->prev)
#define LINK(h, p) ((p)->next = (h)->next, (p)->prev = (h), \
(h)->next->prev = (p), (h)->next = (p))
#define TOFRONT(h, p) ((h)->next != (p) ? (UNLINK(p), LINK(h,p)) : 0)
Fid *
newfid(Session *s)
{
Fid *f, *fN;
chat("newfid..");
if(s->list.prev == 0){
chat("init..");
s->list.prev = &s->list;
s->list.next = &s->list;
s->free = s->fids;
if(0 && chatty)
fN = &s->fids[25];
else
fN = &s->fids[nelem(s->fids)];
for(f=s->fids; f<fN; f++){
f->owner = 0;
f->prev = 0;
f->next = f+1;
}
(f-1)->next = 0;
}
if(s->free){
f = s->free;
s->free = f->next;
LINK(&s->list, f);
}else{
for(f=s->list.prev; f!=&s->list; f=f->prev)
if(f->owner)
break;
if(f == &s->list){
clog("fid leak");
return 0;
}
setfid(s, f);
if(xmesg(s, Tclunk) < 0){
clog("clunk failed, no fids?");
/*return 0;*/
}
*(f->owner) = 0;
f->owner = 0;
}
chat("%zd...", f - s->fids);
f->tstale = nfstime + staletime;
return f;
}
void
setfid(Session *s, Fid *f)
{
/*
* TOFRONT(&s->list, f);
*/
if(s->list.next != f){
UNLINK(f);
LINK(&s->list, f);
}
f->tstale = nfstime + staletime;
s->f.fid = f - s->fids;
}
void
putfid(Session *s, Fid *f)
{
chat("putfid %zd...", f-s->fids);
if(s == 0 || f == 0){
clog("putfid(0x%p, 0x%p) %s", s, f, (s ? s->service : "?"));
return;
}
UNLINK(f);
if(f->owner)
*(f->owner) = 0;
f->owner = 0;
f->prev = 0;
f->next = s->free;
s->free = f;
}
void
fidtimer(Session *s, long now)
{
Fid *f, *t;
int n;
f = s->list.next;
n = 0;
while(f != &s->list){
t = f;
f = f->next;
if(t->owner && now >= t->tstale)
++n, clunkfid(s, t);
}
if(n > 0)
chat("fidtimer %s\n", s->service);
}