xref: /plan9/sys/src/cmd/9nfs/9p.c (revision 453ee12c5ca2e4fdd97e94dd56f9cc72c0d42ba4)
1 #include "all.h"
2 
3 static char *tnames[] = {
4 	[Tversion]	"version",
5 	[Tauth]		"auth",
6 	[Tattach]	"attach",
7 	[Tflush]	"flush",
8 	[Twalk]		"walk",
9 	[Topen]		"open",
10 	[Tcreate]	"create",
11 	[Tread]		"read",
12 	[Twrite]	"write",
13 	[Tclunk]	"clunk",
14 	[Tremove]	"remove",
15 	[Tstat]		"stat",
16 	[Twstat]	"wstat",
17 };
18 
19 int	messagesize = IOHDRSZ+Maxfdata;
20 
21 int
xmesg(Session * s,int t)22 xmesg(Session *s, int t)
23 {
24 	int n;
25 
26 	if(chatty){
27 		if(0 <= t && t < nelem(tnames) && tnames[t])
28 			chat("T%s...", tnames[t]);
29 		else
30 			chat("T%d...", t);
31 	}
32 	s->f.type = t;
33 	s->f.tag = ++s->tag;
34 	if(p9debug)
35 		fprint(2, "xmseg\tsend %F\n", &s->f);
36 	n = convS2M(&s->f, s->data, messagesize);
37 	if(niwrite(s->fd, s->data, n) != n){
38 		clog("xmesg write error on %d: %r\n", s->fd);
39 		return -1;
40 	}
41 again:
42 	n = read9pmsg(s->fd, s->data, messagesize);
43 	if(n < 0){
44 		clog("xmesg read error: %r\n");
45 		return -1;
46 	}
47 	if(convM2S(s->data, n, &s->f) <= 0){
48 		clog("xmesg bad convM2S %d %.2x %.2x %.2x %.2x\n",
49 			n, ((uchar*)s->data)[0], ((uchar*)s->data)[1],
50 			((uchar*)s->data)[2], ((uchar*)s->data)[3]);
51 		return -1;
52 	}
53 	if(p9debug)
54 		fprint(2, "\trecv %F\n", &s->f);
55 	if(s->f.tag != s->tag){
56 		clog("xmesg tag %d for %d\n", s->f.tag, s->tag);
57 		goto again;
58 	}
59 	if(s->f.type == Rerror){
60 		if(t == Tclunk)
61 			clog("xmesg clunk: %s", s->f.ename);
62 		chat("xmesg %d error %s...", t, s->f.ename);
63 		return -1;
64 	}
65 	if(s->f.type != t+1){
66 		clog("xmesg type mismatch: %d, expected %d\n", s->f.type, t+1);
67 		return -1;
68 	}
69 	return 0;
70 }
71 
72 int
clunkfid(Session * s,Fid * f)73 clunkfid(Session *s, Fid *f)
74 {
75 	putfid(s, f);
76 	if(s == 0 || f == 0)
77 		return 0;
78 	s->f.fid = f - s->fids;
79 	return xmesg(s, Tclunk);
80 }
81 
82 #define	UNLINK(p)	((p)->prev->next = (p)->next, (p)->next->prev = (p)->prev)
83 
84 #define	LINK(h, p)	((p)->next = (h)->next, (p)->prev = (h), \
85 			 (h)->next->prev = (p), (h)->next = (p))
86 
87 #define	TOFRONT(h, p)	((h)->next != (p) ? (UNLINK(p), LINK(h,p)) : 0)
88 
89 Fid *
newfid(Session * s)90 newfid(Session *s)
91 {
92 	Fid *f, *fN;
93 
94 	chat("newfid..");
95 	if(s->list.prev == 0){
96 		chat("init..");
97 		s->list.prev = &s->list;
98 		s->list.next = &s->list;
99 		s->free = s->fids;
100 		if(0 && chatty)
101 			fN = &s->fids[25];
102 		else
103 			fN = &s->fids[nelem(s->fids)];
104 		for(f=s->fids; f<fN; f++){
105 			f->owner = 0;
106 			f->prev = 0;
107 			f->next = f+1;
108 		}
109 		(f-1)->next = 0;
110 	}
111 	if(s->free){
112 		f = s->free;
113 		s->free = f->next;
114 		LINK(&s->list, f);
115 	}else{
116 		for(f=s->list.prev; f!=&s->list; f=f->prev)
117 			if(f->owner)
118 				break;
119 		if(f == &s->list){
120 			clog("fid leak");
121 			return 0;
122 		}
123 		setfid(s, f);
124 		if(xmesg(s, Tclunk) < 0){
125 			clog("clunk failed, no fids?");
126 			/*return 0;*/
127 		}
128 		*(f->owner) = 0;
129 		f->owner = 0;
130 	}
131 	chat("%ld...", f - s->fids);
132 	f->tstale = nfstime + staletime;
133 	return f;
134 }
135 
136 void
setfid(Session * s,Fid * f)137 setfid(Session *s, Fid *f)
138 {
139 	/*
140 	 * TOFRONT(&s->list, f);
141 	 */
142 	if(s->list.next != f){
143 		UNLINK(f);
144 		LINK(&s->list, f);
145 	}
146 
147 	f->tstale = nfstime + staletime;
148 	s->f.fid = f - s->fids;
149 }
150 
151 void
putfid(Session * s,Fid * f)152 putfid(Session *s, Fid *f)
153 {
154 	chat("putfid %ld...", f-s->fids);
155 	if(s == 0 || f == 0){
156 		clog("putfid(0x%p, 0x%p) %s", s, f, (s ? s->service : "?"));
157 		return;
158 	}
159 	UNLINK(f);
160 	if(f->owner)
161 		*(f->owner) = 0;
162 	f->owner = 0;
163 	f->prev = 0;
164 	f->next = s->free;
165 	s->free = f;
166 }
167 
168 void
fidtimer(Session * s,long now)169 fidtimer(Session *s, long now)
170 {
171 	Fid *f, *t;
172 	int n;
173 
174 	f = s->list.next;
175 	n = 0;
176 	while(f != &s->list){
177 		t = f;
178 		f = f->next;
179 		if(t->owner && now >= t->tstale)
180 			++n, clunkfid(s, t);
181 	}
182 	if(n > 0)
183 		chat("fidtimer %s\n", s->service);
184 }
185