xref: /plan9/sys/src/cmd/9nfs/9p.c (revision 453ee12c5ca2e4fdd97e94dd56f9cc72c0d42ba4)
19a747e4fSDavid du Colombier #include "all.h"
29a747e4fSDavid du Colombier 
39a747e4fSDavid du Colombier static char *tnames[] = {
49a747e4fSDavid du Colombier 	[Tversion]	"version",
59a747e4fSDavid du Colombier 	[Tauth]		"auth",
69a747e4fSDavid du Colombier 	[Tattach]	"attach",
79a747e4fSDavid du Colombier 	[Tflush]	"flush",
89a747e4fSDavid du Colombier 	[Twalk]		"walk",
99a747e4fSDavid du Colombier 	[Topen]		"open",
109a747e4fSDavid du Colombier 	[Tcreate]	"create",
119a747e4fSDavid du Colombier 	[Tread]		"read",
129a747e4fSDavid du Colombier 	[Twrite]	"write",
139a747e4fSDavid du Colombier 	[Tclunk]	"clunk",
149a747e4fSDavid du Colombier 	[Tremove]	"remove",
159a747e4fSDavid du Colombier 	[Tstat]		"stat",
169a747e4fSDavid du Colombier 	[Twstat]	"wstat",
179a747e4fSDavid du Colombier };
189a747e4fSDavid du Colombier 
199a747e4fSDavid du Colombier int	messagesize = IOHDRSZ+Maxfdata;
209a747e4fSDavid du Colombier 
219a747e4fSDavid du Colombier int
xmesg(Session * s,int t)229a747e4fSDavid du Colombier xmesg(Session *s, int t)
239a747e4fSDavid du Colombier {
249a747e4fSDavid du Colombier 	int n;
259a747e4fSDavid du Colombier 
269a747e4fSDavid du Colombier 	if(chatty){
279a747e4fSDavid du Colombier 		if(0 <= t && t < nelem(tnames) && tnames[t])
289a747e4fSDavid du Colombier 			chat("T%s...", tnames[t]);
299a747e4fSDavid du Colombier 		else
309a747e4fSDavid du Colombier 			chat("T%d...", t);
319a747e4fSDavid du Colombier 	}
329a747e4fSDavid du Colombier 	s->f.type = t;
339a747e4fSDavid du Colombier 	s->f.tag = ++s->tag;
349a747e4fSDavid du Colombier 	if(p9debug)
359a747e4fSDavid du Colombier 		fprint(2, "xmseg\tsend %F\n", &s->f);
369a747e4fSDavid du Colombier 	n = convS2M(&s->f, s->data, messagesize);
379a747e4fSDavid du Colombier 	if(niwrite(s->fd, s->data, n) != n){
389a747e4fSDavid du Colombier 		clog("xmesg write error on %d: %r\n", s->fd);
399a747e4fSDavid du Colombier 		return -1;
409a747e4fSDavid du Colombier 	}
419a747e4fSDavid du Colombier again:
429a747e4fSDavid du Colombier 	n = read9pmsg(s->fd, s->data, messagesize);
439a747e4fSDavid du Colombier 	if(n < 0){
449a747e4fSDavid du Colombier 		clog("xmesg read error: %r\n");
459a747e4fSDavid du Colombier 		return -1;
469a747e4fSDavid du Colombier 	}
479a747e4fSDavid du Colombier 	if(convM2S(s->data, n, &s->f) <= 0){
489a747e4fSDavid du Colombier 		clog("xmesg bad convM2S %d %.2x %.2x %.2x %.2x\n",
499a747e4fSDavid du Colombier 			n, ((uchar*)s->data)[0], ((uchar*)s->data)[1],
509a747e4fSDavid du Colombier 			((uchar*)s->data)[2], ((uchar*)s->data)[3]);
519a747e4fSDavid du Colombier 		return -1;
529a747e4fSDavid du Colombier 	}
539a747e4fSDavid du Colombier 	if(p9debug)
549a747e4fSDavid du Colombier 		fprint(2, "\trecv %F\n", &s->f);
559a747e4fSDavid du Colombier 	if(s->f.tag != s->tag){
569a747e4fSDavid du Colombier 		clog("xmesg tag %d for %d\n", s->f.tag, s->tag);
579a747e4fSDavid du Colombier 		goto again;
589a747e4fSDavid du Colombier 	}
599a747e4fSDavid du Colombier 	if(s->f.type == Rerror){
609a747e4fSDavid du Colombier 		if(t == Tclunk)
619a747e4fSDavid du Colombier 			clog("xmesg clunk: %s", s->f.ename);
629a747e4fSDavid du Colombier 		chat("xmesg %d error %s...", t, s->f.ename);
639a747e4fSDavid du Colombier 		return -1;
649a747e4fSDavid du Colombier 	}
659a747e4fSDavid du Colombier 	if(s->f.type != t+1){
669a747e4fSDavid du Colombier 		clog("xmesg type mismatch: %d, expected %d\n", s->f.type, t+1);
679a747e4fSDavid du Colombier 		return -1;
689a747e4fSDavid du Colombier 	}
699a747e4fSDavid du Colombier 	return 0;
709a747e4fSDavid du Colombier }
719a747e4fSDavid du Colombier 
729a747e4fSDavid du Colombier int
clunkfid(Session * s,Fid * f)739a747e4fSDavid du Colombier clunkfid(Session *s, Fid *f)
749a747e4fSDavid du Colombier {
759a747e4fSDavid du Colombier 	putfid(s, f);
769a747e4fSDavid du Colombier 	if(s == 0 || f == 0)
779a747e4fSDavid du Colombier 		return 0;
789a747e4fSDavid du Colombier 	s->f.fid = f - s->fids;
799a747e4fSDavid du Colombier 	return xmesg(s, Tclunk);
809a747e4fSDavid du Colombier }
819a747e4fSDavid du Colombier 
829a747e4fSDavid du Colombier #define	UNLINK(p)	((p)->prev->next = (p)->next, (p)->next->prev = (p)->prev)
839a747e4fSDavid du Colombier 
849a747e4fSDavid du Colombier #define	LINK(h, p)	((p)->next = (h)->next, (p)->prev = (h), \
859a747e4fSDavid du Colombier 			 (h)->next->prev = (p), (h)->next = (p))
869a747e4fSDavid du Colombier 
879a747e4fSDavid du Colombier #define	TOFRONT(h, p)	((h)->next != (p) ? (UNLINK(p), LINK(h,p)) : 0)
889a747e4fSDavid du Colombier 
899a747e4fSDavid du Colombier Fid *
newfid(Session * s)909a747e4fSDavid du Colombier newfid(Session *s)
919a747e4fSDavid du Colombier {
929a747e4fSDavid du Colombier 	Fid *f, *fN;
939a747e4fSDavid du Colombier 
949a747e4fSDavid du Colombier 	chat("newfid..");
959a747e4fSDavid du Colombier 	if(s->list.prev == 0){
969a747e4fSDavid du Colombier 		chat("init..");
979a747e4fSDavid du Colombier 		s->list.prev = &s->list;
989a747e4fSDavid du Colombier 		s->list.next = &s->list;
999a747e4fSDavid du Colombier 		s->free = s->fids;
1009a747e4fSDavid du Colombier 		if(0 && chatty)
1019a747e4fSDavid du Colombier 			fN = &s->fids[25];
1029a747e4fSDavid du Colombier 		else
1039a747e4fSDavid du Colombier 			fN = &s->fids[nelem(s->fids)];
1049a747e4fSDavid du Colombier 		for(f=s->fids; f<fN; f++){
1059a747e4fSDavid du Colombier 			f->owner = 0;
1069a747e4fSDavid du Colombier 			f->prev = 0;
1079a747e4fSDavid du Colombier 			f->next = f+1;
1089a747e4fSDavid du Colombier 		}
1099a747e4fSDavid du Colombier 		(f-1)->next = 0;
1109a747e4fSDavid du Colombier 	}
1119a747e4fSDavid du Colombier 	if(s->free){
1129a747e4fSDavid du Colombier 		f = s->free;
1139a747e4fSDavid du Colombier 		s->free = f->next;
1149a747e4fSDavid du Colombier 		LINK(&s->list, f);
1159a747e4fSDavid du Colombier 	}else{
1169a747e4fSDavid du Colombier 		for(f=s->list.prev; f!=&s->list; f=f->prev)
1179a747e4fSDavid du Colombier 			if(f->owner)
1189a747e4fSDavid du Colombier 				break;
1199a747e4fSDavid du Colombier 		if(f == &s->list){
1209a747e4fSDavid du Colombier 			clog("fid leak");
1219a747e4fSDavid du Colombier 			return 0;
1229a747e4fSDavid du Colombier 		}
1239a747e4fSDavid du Colombier 		setfid(s, f);
1249a747e4fSDavid du Colombier 		if(xmesg(s, Tclunk) < 0){
1259a747e4fSDavid du Colombier 			clog("clunk failed, no fids?");
1269a747e4fSDavid du Colombier 			/*return 0;*/
1279a747e4fSDavid du Colombier 		}
1289a747e4fSDavid du Colombier 		*(f->owner) = 0;
1299a747e4fSDavid du Colombier 		f->owner = 0;
1309a747e4fSDavid du Colombier 	}
1319a747e4fSDavid du Colombier 	chat("%ld...", f - s->fids);
1329a747e4fSDavid du Colombier 	f->tstale = nfstime + staletime;
1339a747e4fSDavid du Colombier 	return f;
1349a747e4fSDavid du Colombier }
1359a747e4fSDavid du Colombier 
1369a747e4fSDavid du Colombier void
setfid(Session * s,Fid * f)1379a747e4fSDavid du Colombier setfid(Session *s, Fid *f)
1389a747e4fSDavid du Colombier {
139*453ee12cSDavid du Colombier 	/*
140*453ee12cSDavid du Colombier 	 * TOFRONT(&s->list, f);
141*453ee12cSDavid du Colombier 	 */
142*453ee12cSDavid du Colombier 	if(s->list.next != f){
143*453ee12cSDavid du Colombier 		UNLINK(f);
144*453ee12cSDavid du Colombier 		LINK(&s->list, f);
145*453ee12cSDavid du Colombier 	}
146*453ee12cSDavid du Colombier 
1479a747e4fSDavid du Colombier 	f->tstale = nfstime + staletime;
1489a747e4fSDavid du Colombier 	s->f.fid = f - s->fids;
1499a747e4fSDavid du Colombier }
1509a747e4fSDavid du Colombier 
1519a747e4fSDavid du Colombier void
putfid(Session * s,Fid * f)1529a747e4fSDavid du Colombier putfid(Session *s, Fid *f)
1539a747e4fSDavid du Colombier {
1549a747e4fSDavid du Colombier 	chat("putfid %ld...", f-s->fids);
1559a747e4fSDavid du Colombier 	if(s == 0 || f == 0){
1569a747e4fSDavid du Colombier 		clog("putfid(0x%p, 0x%p) %s", s, f, (s ? s->service : "?"));
1579a747e4fSDavid du Colombier 		return;
1589a747e4fSDavid du Colombier 	}
1599a747e4fSDavid du Colombier 	UNLINK(f);
1609a747e4fSDavid du Colombier 	if(f->owner)
1619a747e4fSDavid du Colombier 		*(f->owner) = 0;
1629a747e4fSDavid du Colombier 	f->owner = 0;
1639a747e4fSDavid du Colombier 	f->prev = 0;
1649a747e4fSDavid du Colombier 	f->next = s->free;
1659a747e4fSDavid du Colombier 	s->free = f;
1669a747e4fSDavid du Colombier }
1679a747e4fSDavid du Colombier 
1689a747e4fSDavid du Colombier void
fidtimer(Session * s,long now)1699a747e4fSDavid du Colombier fidtimer(Session *s, long now)
1709a747e4fSDavid du Colombier {
1719a747e4fSDavid du Colombier 	Fid *f, *t;
1729a747e4fSDavid du Colombier 	int n;
1739a747e4fSDavid du Colombier 
1749a747e4fSDavid du Colombier 	f = s->list.next;
1759a747e4fSDavid du Colombier 	n = 0;
1769a747e4fSDavid du Colombier 	while(f != &s->list){
1779a747e4fSDavid du Colombier 		t = f;
1789a747e4fSDavid du Colombier 		f = f->next;
1799a747e4fSDavid du Colombier 		if(t->owner && now >= t->tstale)
1809a747e4fSDavid du Colombier 			++n, clunkfid(s, t);
1819a747e4fSDavid du Colombier 	}
1829a747e4fSDavid du Colombier 	if(n > 0)
1839a747e4fSDavid du Colombier 		chat("fidtimer %s\n", s->service);
1849a747e4fSDavid du Colombier }
185