History

kern: update qio and devmnt, remove mount cache stub

cinap_lenrek committed 10 years ago

Commit 3b886fc1 parent 278bcb76 files · +475 −764Browse files

Unified · Split

6 files
  1. kern/Makefile +0 −1
  2. kern/allocb.c +21 −55
  3. kern/cache.c +0 −46
  4. kern/devmnt.c +207 −288
  5. kern/fns.h +2 −10
  6. kern/qio.c +245 −364
kern/Makefile+0−1
@@ -5,7 +5,6 @@ LIB=libkern.a · 4 unmodified lines
5OFILES=\5OFILES=\
6 alloc.$O\6 alloc.$O\
7 allocb.$O\7 allocb.$O\
8 cache.$O\
9 chan.$O\8 chan.$O\
10 data.$O\9 data.$O\
11 dev.$O\10 dev.$O\
kern/allocb.c+21−55
@@ -7,27 +7,23 @@ · 6 unmodified lines
7enum7enum
8{8{
9 Hdrspc = 64, /* leave room for high-level headers */9 Hdrspc = 64, /* leave room for high-level headers */
10 Tlrspc = 16, /* extra room at the end for pad/crc/mac */
10 Bdead = 0x51494F42, /* "QIOB" */11 Bdead = 0x51494F42, /* "QIOB" */
11};12};
12 13
13struct
14{
15 Lock lk;
16 ulong bytes;
17} ialloc;
18
19static Block*14static Block*
20_allocb(int size)15_allocb(int size)
21{16{
22 Block *b;17 Block *b;
23 uintptr addr;18 uintptr addr;
24 19
20 size += Tlrspc;
25 if((b = mallocz(sizeof(Block)+size+Hdrspc, 0)) == nil)21 if((b = mallocz(sizeof(Block)+size+Hdrspc, 0)) == nil)
26 return nil;22 return nil;
27 23
28 b->next = nil;24 b->next = nil;
29 b->list = nil;25 b->list = nil;
30 b->free = 0;26 b->free = nil;
31 b->flag = 0;27 b->flag = 0;
32 28
33 /* align start of data portion by rounding up */29 /* align start of data portion by rounding up */
@@ -36,9 +32,9 @@ _allocb(int size) · 2 unmodified lines
36 b->base = (uchar*)addr;32 b->base = (uchar*)addr;
37 33
38 /* align end of data portion by rounding down */34 /* align end of data portion by rounding down */
39 b->lim = ((uchar*)b) + sizeof(Block)+size+Hdrspc;35 b->lim = (uchar*)b + sizeof(Block)+size+Hdrspc;
40 addr = (uintptr)(b->lim);36 addr = (uintptr)b->lim;
41 addr = addr & ~(BLOCKALIGN-1);37 addr &= ~(BLOCKALIGN-1);
42 b->lim = (uchar*)addr;38 b->lim = (uchar*)addr;
43 39
44 /* leave sluff at beginning for added headers */40 /* leave sluff at beginning for added headers */
@@ -57,13 +53,11 @@ allocb(int size) · 12 unmodified lines
57 53
58 /*54 /*
59 * Check in a process and wait until successful.55 * Check in a process and wait until successful.
60 * Can still error out of here, though.
61 */56 */
62 if(up == nil)57 if(up == nil)
63 panic("allocb without up: %p\n", getcallerpc(&size));58 panic("allocb without up: %#p", getcallerpc(&size));
64 if((b = _allocb(size)) == nil){59 if((b = _allocb(size)) == nil)
65 panic("allocb: no memory for %d bytes\n", size);60 panic("allocb: no memory for %d bytes", size);
66 }
67 setmalloctag(b, getcallerpc(&size));61 setmalloctag(b, getcallerpc(&size));
68 62
69 return b;63 return b;
@@ -73,28 +67,12 @@ Block* · 3 unmodified lines
73iallocb(int size)67iallocb(int size)
74{68{
75 Block *b;69 Block *b;
76 static int m1, m2;
77 70
78 if(ialloc.bytes > conf.ialloc){71 if((b = _allocb(size)) == nil)
79 if((m1++%10000)==0)72 panic("iallocb: no memory for %d bytes", size);
80 print("iallocb: limited %lud/%lud\n",
81 ialloc.bytes, conf.ialloc);
82 return 0;
83 }
84
85 if((b = _allocb(size)) == nil){
86 if((m2++%10000)==0)
87 print("iallocb: no memory %lud/%lud\n",
88 ialloc.bytes, conf.ialloc);
89 return nil;
90 }
91 setmalloctag(b, getcallerpc(&size));73 setmalloctag(b, getcallerpc(&size));
92 b->flag = BINTR;74 b->flag = BINTR;
93 75
94 ilock(&ialloc.lk);
95 ialloc.bytes += b->lim - b->base;
96 iunlock(&ialloc.lk);
97
98 return b;76 return b;
99}77}
100 78
@@ -110,15 +88,10 @@ freeb(Block *b) · 9 unmodified lines
110 * drivers which perform non cache coherent DMA manage their own buffer88 * drivers which perform non cache coherent DMA manage their own buffer
111 * pool of uncached buffers and provide their own free routine.89 * pool of uncached buffers and provide their own free routine.
112 */90 */
113 if(b->free) {91 if(b->free != nil) {
114 b->free(b);92 b->free(b);
115 return;93 return;
116 }94 }
117 if(b->flag & BINTR) {
118 ilock(&ialloc.lk);
119 ialloc.bytes -= b->lim - b->base;
120 iunlock(&ialloc.lk);
121 }
122 95
123 /* poison the block in case someone is still holding onto it */96 /* poison the block in case someone is still holding onto it */
124 b->next = dead;97 b->next = dead;
@@ -136,30 +109,23 @@ checkb(Block *b, char *msg) · 11 unmodified lines
136 void *dead = (void*)Bdead;109 void *dead = (void*)Bdead;
137 110
138 if(b == dead)111 if(b == dead)
139 panic("checkb b %s %lux", msg, b);112 panic("checkb b %s %#p", msg, b);
140 if(b->base == dead || b->lim == dead || b->next == dead113 if(b->base == dead || b->lim == dead || b->next == dead
141 || b->rp == dead || b->wp == dead){114 || b->rp == dead || b->wp == dead){
142 print("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\n",115 print("checkb: base %#p lim %#p next %#p\n",
143 b->base, b->lim, b->next);116 b->base, b->lim, b->next);
144 print("checkb: rp 0x%8.8luX wp 0x%8.8luX\n", b->rp, b->wp);117 print("checkb: rp %#p wp %#p\n", b->rp, b->wp);
145 panic("checkb dead: %s\n", msg);118 panic("checkb dead: %s", msg);
146 }119 }
147 120
148 if(b->base > b->lim)121 if(b->base > b->lim)
149 panic("checkb 0 %s %lux %lux", msg, b->base, b->lim);122 panic("checkb 0 %s %#p %#p", msg, b->base, b->lim);
150 if(b->rp < b->base)123 if(b->rp < b->base)
151 panic("checkb 1 %s %lux %lux", msg, b->base, b->rp);124 panic("checkb 1 %s %#p %#p", msg, b->base, b->rp);
152 if(b->wp < b->base)125 if(b->wp < b->base)
153 panic("checkb 2 %s %lux %lux", msg, b->base, b->wp);126 panic("checkb 2 %s %#p %#p", msg, b->base, b->wp);
154 if(b->rp > b->lim)127 if(b->rp > b->lim)
155 panic("checkb 3 %s %lux %lux", msg, b->rp, b->lim);128 panic("checkb 3 %s %#p %#p", msg, b->rp, b->lim);
156 if(b->wp > b->lim)129 if(b->wp > b->lim)
157 panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim);130 panic("checkb 4 %s %#p %#p", msg, b->wp, b->lim);
158
159}
160
161void
162iallocsummary(void)
163{
164 print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc);
165}131}
kern/cache.c+0−46
@@ -1,46 +0,0 @@
1#include "u.h"
2#include "lib.h"
3#include "dat.h"
4#include "fns.h"
5#include "error.h"
6
7
8void
9cinit(void)
10{
11}
12
13void
14copen(Chan *c)
15{
16 USED(c);
17}
18
19int
20cread(Chan *c, uchar *buf, int len, vlong off)
21{
22 USED(c);
23 USED(buf);
24 USED(len);
25 USED(off);
26
27 return 0;
28}
29
30void
31cupdate(Chan *c, uchar *buf, int len, vlong off)
32{
33 USED(c);
34 USED(buf);
35 USED(len);
36 USED(off);
37}
38
39void
40cwrite(Chan* c, uchar *buf, int len, vlong off)
41{
42 USED(c);
43 USED(buf);
44 USED(len);
45 USED(off);
46}
kern/devmnt.c+207−288
@@ -24,15 +24,10 @@ struct Mntrpc · 23 unmodified lines
24 Fcall request; /* Outgoing file system protocol message */24 Fcall request; /* Outgoing file system protocol message */
25 Fcall reply; /* Incoming reply */25 Fcall reply; /* Incoming reply */
26 Mnt* m; /* Mount device during rpc */26 Mnt* m; /* Mount device during rpc */
27 Rendez r; /* Place to hang out */27 Rendez* z; /* Place to hang out */
28 uchar* rpc; /* I/O Data buffer */28 Block* b; /* reply blocks */
29 uint rpclen; /* len of buffer */
30 Block *b; /* reply blocks */
31 char done; /* Rpc completed */
32 uvlong stime; /* start time for mnt statistics */
33 ulong reqlen; /* request length for mnt statistics */
34 ulong replen; /* reply length for mnt statistics */
35 Mntrpc* flushed; /* message this one flushes */29 Mntrpc* flushed; /* message this one flushes */
30 char done; /* Rpc completed */
36};31};
37 32
38enum33enum
@@ -42,42 +37,38 @@ enum · 3 unmodified lines
42 NMASK = (64*1024)>>TAGSHIFT,37 NMASK = (64*1024)>>TAGSHIFT,
43};38};
44 39
45struct Mntalloc40static struct Mntalloc
46{41{
47 Lock lk;42 Lock lk;
48 Mnt* list; /* Mount devices in use */43 Mnt* list; /* Mount devices in use */
49 Mnt* mntfree; /* Free list */44 Mnt* mntfree; /* Free list */
50 Mntrpc* rpcfree;45 Mntrpc* rpcfree;
51 int nrpcfree;46 ulong nrpcfree;
52 int nrpcused;47 ulong nrpcused;
53 ulong id;48 ulong id;
54 ulong tagmask[NMASK];49 ulong tagmask[NMASK];
55}mntalloc;50} mntalloc;
56 51
57void mattach(Mnt*, Chan*, char*);52static Chan* mntchan(void);
58Mnt* mntchk(Chan*);53static Mnt* mntchk(Chan*);
59void mntdirfix(uchar*, Chan*);54static void mntdirfix(uchar*, Chan*);
60Mntrpc* mntflushalloc(Mntrpc*, ulong);55static Mntrpc* mntflushalloc(Mntrpc*);
61void mntflushfree(Mnt*, Mntrpc*);56static Mntrpc* mntflushfree(Mnt*, Mntrpc*);
62void mntfree(Mntrpc*);57static void mntfree(Mntrpc*);
63void mntgate(Mnt*);58static void mntgate(Mnt*);
64void mntpntfree(Mnt*);59static void mntqrm(Mnt*, Mntrpc*);
65void mntqrm(Mnt*, Mntrpc*);60static Mntrpc* mntralloc(Chan*);
66Mntrpc* mntralloc(Chan*, ulong);61static long mntrdwr(int, Chan*, void*, long, vlong);
67long mntrdwr(int, Chan*, void*, long, vlong);62static int mntrpcread(Mnt*, Mntrpc*);
68int mntrpcread(Mnt*, Mntrpc*);63static void mountio(Mnt*, Mntrpc*);
69void mountio(Mnt*, Mntrpc*);64static void mountmux(Mnt*, Mntrpc*);
70void mountmux(Mnt*, Mntrpc*);65static void mountrpc(Mnt*, Mntrpc*);
71void mountrpc(Mnt*, Mntrpc*);66static int rpcattn(void*);
72int rpcattn(void*);
73Chan* mntchan(void);
74 67
75char Esbadstat[] = "invalid directory entry received from server";68char Esbadstat[] = "invalid directory entry received from server";
76char Enoversion[] = "version not established for mount channel";69char Enoversion[] = "version not established for mount channel";
77 70
78 71
79void (*mntstats)(int, Chan*, uvlong, ulong);
80
81static void72static void
82mntreset(void)73mntreset(void)
83{74{
@@ -87,20 +78,19 @@ mntreset(void) · 3 unmodified lines
87 fmtinstall('F', fcallfmt);78 fmtinstall('F', fcallfmt);
88 fmtinstall('D', dirfmt);79 fmtinstall('D', dirfmt);
89/* We can't install %M since eipfmt does and is used in the kernel [sape] */80/* We can't install %M since eipfmt does and is used in the kernel [sape] */
90
91 cinit();
92}81}
93 82
94/*83/*
95 * Version is not multiplexed: message sent only once per connection.84 * Version is not multiplexed: message sent only once per connection.
96 */85 */
97long86int
98mntversion(Chan *c, char *version, int msize, int returnlen)87mntversion(Chan *c, char *version, int msize, int returnlen)
99{88{
100 Fcall f;89 Fcall f;
101 uchar *msg;90 uchar *msg;
102 Mnt *m;91 Mnt *m;
103 char *v;92 char *v;
93 Queue *q;
104 long k, l;94 long k, l;
105 uvlong oo;95 uvlong oo;
106 char buf[128];96 char buf[128];
@@ -167,7 +157,6 @@ mntversion(Chan *c, char *version, int msize, int returnlen) · 60 unmodified lines
167 unlock(&c->ref.lk);157 unlock(&c->ref.lk);
168 158
169 l = devtab[c->type]->write(c, msg, k, oo);159 l = devtab[c->type]->write(c, msg, k, oo);
170
171 if(l < k){160 if(l < k){
172 lock(&c->ref.lk);161 lock(&c->ref.lk);
173 c->offset -= k - l;162 c->offset -= k - l;
@@ -176,13 +165,14 @@ mntversion(Chan *c, char *version, int msize, int returnlen) · 2 unmodified lines
176 }165 }
177 166
178 /* message sent; receive and decode reply */167 /* message sent; receive and decode reply */
179 k = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset);168 for(k = 0; k < BIT32SZ || (k < GBIT32(msg) && k < 8192+IOHDRSZ); k += l){
180 if(k <= 0)169 l = devtab[c->type]->read(c, msg+k, 8192+IOHDRSZ-k, c->offset);
181 error("EOF receiving fversion reply");170 if(l <= 0)
182 171 error("EOF receiving fversion reply");
183 lock(&c->ref.lk);172 lock(&c->ref.lk);
184 c->offset += k;173 c->offset += l;
185 unlock(&c->ref.lk);174 unlock(&c->ref.lk);
175 }
186 176
187 l = convM2S(msg, k, &f);177 l = convM2S(msg, k, &f);
188 if(l != k)178 if(l != k)
@@ -199,40 +189,49 @@ mntversion(Chan *c, char *version, int msize, int returnlen) · 10 unmodified lines
199 k = strlen(f.version);189 k = strlen(f.version);
200 if(strncmp(f.version, v, k) != 0)190 if(strncmp(f.version, v, k) != 0)
201 error("bad 9P version returned from server");191 error("bad 9P version returned from server");
192 if(returnlen > 0 && returnlen < k)
193 error(Eshort);
194
195 v = nil;
196 kstrdup(&v, f.version);
197 q = qopen(10*MAXRPC, 0, nil, nil);
198 if(q == nil){
199 free(v);
200 exhausted("mount queues");
201 }
202 202
203 /* now build Mnt associated with this connection */203 /* now build Mnt associated with this connection */
204 lock(&mntalloc.lk);204 lock(&mntalloc.lk);
205 m = mntalloc.mntfree;205 m = mntalloc.mntfree;
206 if(m != 0)206 if(m != nil)
207 mntalloc.mntfree = m->list;207 mntalloc.mntfree = m->list;
208 else {208 else {
209 unlock(&mntalloc.lk);
209 m = malloc(sizeof(Mnt));210 m = malloc(sizeof(Mnt));
210 if(m == 0) {211 if(m == nil) {
211 unlock(&mntalloc.lk);212 qfree(q);
213 free(v);
212 exhausted("mount devices");214 exhausted("mount devices");
213 }215 }
216 lock(&mntalloc.lk);
214 }217 }
215 m->list = mntalloc.list;218 m->list = mntalloc.list;
216 mntalloc.list = m;219 mntalloc.list = m;
217 m->version = nil;220 m->version = v;
218 kstrdup(&m->version, f.version);
219 m->id = mntalloc.id++;221 m->id = mntalloc.id++;
220 m->q = qopen(10*MAXRPC, 0, 0, nil);222 m->q = q;
221 m->msize = f.msize;223 m->msize = f.msize;
222 unlock(&mntalloc.lk);224 unlock(&mntalloc.lk);
223 225
224 if(returnlen > 0){226 if(returnlen > 0)
225 if(returnlen < k)227 memmove(version, f.version, k); /* length was checked above */
226 error(Eshort);
227 memmove(version, f.version, k);
228 }
229 228
230 poperror(); /* msg */229 poperror(); /* msg */
231 free(msg);230 free(msg);
232 231
233 lock(&m->lk);232 lock(&m->lk);
234 m->queue = 0;233 m->queue = nil;
235 m->rip = 0;234 m->rip = nil;
236 235
237 c->flag |= CMSG;236 c->flag |= CMSG;
238 c->mux = m;237 c->mux = m;
@@ -252,9 +251,8 @@ mntauth(Chan *c, char *spec) · 13 unmodified lines
252 Mntrpc *r;251 Mntrpc *r;
253 252
254 m = c->mux;253 m = c->mux;
255
256 if(m == nil){254 if(m == nil){
257 mntversion(c, VERSION9P, MAXRPC, 0);255 mntversion(c, nil, 0, 0);
258 m = c->mux;256 m = c->mux;
259 if(m == nil)257 if(m == nil)
260 error(Enoversion);258 error(Enoversion);
@@ -269,8 +267,7 @@ mntauth(Chan *c, char *spec) · 8 unmodified lines
269 nexterror();267 nexterror();
270 }268 }
271 269
272 r = mntralloc(0, m->msize);270 r = mntralloc(c);
273
274 if(waserror()) {271 if(waserror()) {
275 mntfree(r);272 mntfree(r);
276 nexterror();273 nexterror();
@@ -287,6 +284,7 @@ mntauth(Chan *c, char *spec) · 10 unmodified lines
287 incref(&m->c->ref);284 incref(&m->c->ref);
288 c->mqid = c->qid;285 c->mqid = c->qid;
289 c->mode = ORDWR;286 c->mode = ORDWR;
287 c->iounit = m->msize-IOHDRSZ;
290 288
291 poperror(); /* r */289 poperror(); /* r */
292 mntfree(r);290 mntfree(r);
@@ -297,24 +295,13 @@ mntauth(Chan *c, char *spec) · 4 unmodified lines
297 295
298}296}
299 297
300static Chan*298Chan*
301mntattach(char *muxattach)299mntattach(Chan *c, Chan *ac, char *spec, int flags)
302{300{
303 Mnt *m;301 Mnt *m;
304 Chan *c;
305 Mntrpc *r;302 Mntrpc *r;
306 struct bogus{
307 Chan *chan;
308 Chan *authchan;
309 char *spec;
310 int flags;
311 }bogus;
312
313 bogus = *((struct bogus *)muxattach);
314 c = bogus.chan;
315 303
316 m = c->mux;304 m = c->mux;
317
318 if(m == nil){305 if(m == nil){
319 mntversion(c, nil, 0, 0);306 mntversion(c, nil, 0, 0);
320 m = c->mux;307 m = c->mux;
@@ -331,21 +318,19 @@ mntattach(char *muxattach) · 10 unmodified lines
331 nexterror();318 nexterror();
332 }319 }
333 320
334 r = mntralloc(0, m->msize);321 r = mntralloc(c);
335
336 if(waserror()) {322 if(waserror()) {
337 mntfree(r);323 mntfree(r);
338 nexterror();324 nexterror();
339 }325 }
340
341 r->request.type = Tattach;326 r->request.type = Tattach;
342 r->request.fid = c->fid;327 r->request.fid = c->fid;
343 if(bogus.authchan == nil)328 if(ac == nil)
344 r->request.afid = NOFID;329 r->request.afid = NOFID;
345 else330 else
346 r->request.afid = bogus.authchan->fid;331 r->request.afid = ac->fid;
347 r->request.uname = up->user;332 r->request.uname = up->user;
348 r->request.aname = bogus.spec;333 r->request.aname = spec;
349 mountrpc(m, r);334 mountrpc(m, r);
350 335
351 c->qid = r->reply.qid;336 c->qid = r->reply.qid;
@@ -358,12 +343,20 @@ mntattach(char *muxattach) · 6 unmodified lines
358 343
359 poperror(); /* c */344 poperror(); /* c */
360 345
361 if(bogus.flags&MCACHE)346 if(flags&MCACHE)
362 c->flag |= CCACHE;347 c->flag |= CCACHE;
363 return c;348 return c;
364}349}
365 350
366Chan*351static Chan*
352noattach(char *s)
353{
354 USED(s);
355 error(Enoattach);
356 return nil;
357}
358
359static Chan*
367mntchan(void)360mntchan(void)
368{361{
369 Chan *c;362 Chan *c;
@@ -373,7 +366,7 @@ mntchan(void) · 3 unmodified lines
373 c->dev = mntalloc.id++;366 c->dev = mntalloc.id++;
374 unlock(&mntalloc.lk);367 unlock(&mntalloc.lk);
375 368
376 if(c->mchan)369 if(c->mchan != nil)
377 panic("mntchan non-zero %p", c->mchan);370 panic("mntchan non-zero %p", c->mchan);
378 return c;371 return c;
379}372}
@@ -401,7 +394,7 @@ mntwalk(Chan *c, Chan *nc, char **name, int nname) · 21 unmodified lines
401 394
402 alloc = 0;395 alloc = 0;
403 m = mntchk(c);396 m = mntchk(c);
404 r = mntralloc(c, m->msize);397 r = mntralloc(c);
405 if(nc == nil){398 if(nc == nil){
406 nc = devclone(c);399 nc = devclone(c);
407 /*400 /*
@@ -409,6 +402,7 @@ mntwalk(Chan *c, Chan *nc, char **name, int nname) · 1 unmodified line
409 * Therefore set type to 0 for now; rootclose is known to be safe.402 * Therefore set type to 0 for now; rootclose is known to be safe.
410 */403 */
411 nc->type = 0;404 nc->type = 0;
405 nc->flag |= (c->flag & CCACHE);
412 alloc = 1;406 alloc = 1;
413 }407 }
414 wq->clone = nc;408 wq->clone = nc;
@@ -468,7 +462,7 @@ mntstat(Chan *c, uchar *dp, int n) · 53 unmodified lines
468 if(n < BIT16SZ)462 if(n < BIT16SZ)
469 error(Eshortstat);463 error(Eshortstat);
470 m = mntchk(c);464 m = mntchk(c);
471 r = mntralloc(c, m->msize);465 r = mntralloc(c);
472 if(waserror()) {466 if(waserror()) {
473 mntfree(r);467 mntfree(r);
474 nexterror();468 nexterror();
@@ -477,28 +471,9 @@ mntstat(Chan *c, uchar *dp, int n) · 2 unmodified lines
477 r->request.fid = c->fid;471 r->request.fid = c->fid;
478 mountrpc(m, r);472 mountrpc(m, r);
479 473
480/* r->reply.nstat is 16 bits
481 if(r->reply.nstat >= 1<<16)
482 error("returned stat buffer count too large");
483*/
484
485 if(r->reply.nstat > n){474 if(r->reply.nstat > n){
486 /*
487 * 12/31/2002 RSC
488 *
489 * This should be nstat-2, which is the first two
490 * bytes of the stat buffer. But dirstat and dirfstat
491 * depended on getting the full nstat (they didn't
492 * add BIT16SZ themselves). I fixed dirstat and dirfstat
493 * but am leaving this unchanged for now. After a
494 * few months, once enough of the relevant binaries
495 * have been recompiled for other reasons, we can
496 * change this to nstat-2. Devstat gets this right
497 * (via convD2M).
498 */
499 /* doesn't fit; just patch the count and return */
500 PBIT16((uchar*)dp, r->reply.nstat);
501 n = BIT16SZ;475 n = BIT16SZ;
476 PBIT16((uchar*)dp, r->reply.nstat-2);
502 }else{477 }else{
503 n = r->reply.nstat;478 n = r->reply.nstat;
504 memmove(dp, r->reply.stat, n);479 memmove(dp, r->reply.stat, n);
@@ -517,7 +492,7 @@ mntopencreate(int type, Chan *c, char *name, int omode, ulong perm) · 12 unmodified lines
517 Mntrpc *r;492 Mntrpc *r;
518 493
519 m = mntchk(c);494 m = mntchk(c);
520 r = mntralloc(c, m->msize);495 r = mntralloc(c);
521 if(waserror()) {496 if(waserror()) {
522 mntfree(r);497 mntfree(r);
523 nexterror();498 nexterror();
@@ -541,9 +516,6 @@ mntopencreate(int type, Chan *c, char *name, int omode, ulong perm) · 17 unmodified lines
541 poperror();516 poperror();
542 mntfree(r);517 mntfree(r);
543 518
544 if(c->flag & CCACHE)
545 copen(c);
546
547 return c;519 return c;
548}520}
549 521
@@ -566,12 +538,11 @@ mntclunk(Chan *c, int t) · 16 unmodified lines
566 Mntrpc *r;538 Mntrpc *r;
567 539
568 m = mntchk(c);540 m = mntchk(c);
569 r = mntralloc(c, m->msize);541 r = mntralloc(c);
570 if(waserror()){542 if(waserror()) {
571 mntfree(r);543 mntfree(r);
572 nexterror();544 nexterror();
573 }545 }
574
575 r->request.type = t;546 r->request.type = t;
576 r->request.fid = c->fid;547 r->request.fid = c->fid;
577 mountrpc(m, r);548 mountrpc(m, r);
@@ -582,27 +553,22 @@ mntclunk(Chan *c, int t) · 4 unmodified lines
582void553void
583muxclose(Mnt *m)554muxclose(Mnt *m)
584{555{
585 Mntrpc *q, *r;556 Mnt *f, **l;
557 Mntrpc *r;
586 558
587 for(q = m->queue; q; q = r) {559 while((r = m->queue) != nil){
588 r = q->list;560 m->queue = r->list;
589 mntfree(q);561 mntfree(r);
590 }562 }
591 m->id = 0;563 m->id = 0;
592 free(m->version);564 free(m->version);
593 m->version = nil;565 m->version = nil;
594 mntpntfree(m);566 qfree(m->q);
595}567 m->q = nil;
596
597void
598mntpntfree(Mnt *m)
599{
600 Mnt *f, **l;
601 Queue *q;
602 568
603 lock(&mntalloc.lk);569 lock(&mntalloc.lk);
604 l = &mntalloc.list;570 l = &mntalloc.list;
605 for(f = *l; f; f = f->list) {571 for(f = *l; f != nil; f = f->list) {
606 if(f == m) {572 if(f == m) {
607 *l = m->list;573 *l = m->list;
608 break;574 break;
@@ -611,10 +577,7 @@ mntpntfree(Mnt *m) · 2 unmodified lines
611 }577 }
612 m->list = mntalloc.mntfree;578 m->list = mntalloc.mntfree;
613 mntalloc.mntfree = m;579 mntalloc.mntfree = m;
614 q = m->q;
615 unlock(&mntalloc.lk);580 unlock(&mntalloc.lk);
616
617 qfree(q);
618}581}
619 582
620static void583static void
@@ -636,7 +599,7 @@ mntwstat(Chan *c, uchar *dp, int n) · 15 unmodified lines
636 Mntrpc *r;599 Mntrpc *r;
637 600
638 m = mntchk(c);601 m = mntchk(c);
639 r = mntralloc(c, m->msize);602 r = mntralloc(c);
640 if(waserror()) {603 if(waserror()) {
641 mntfree(r);604 mntfree(r);
642 nexterror();605 nexterror();
@@ -655,32 +618,11 @@ static long · 12 unmodified lines
655mntread(Chan *c, void *buf, long n, vlong off)618mntread(Chan *c, void *buf, long n, vlong off)
656{619{
657 uchar *p, *e;620 uchar *p, *e;
658 int nc, cache, isdir, dirlen;621 int dirlen;
659
660 isdir = 0;
661 cache = c->flag & CCACHE;
662 if(c->qid.type & QTDIR) {
663 cache = 0;
664 isdir = 1;
665 }
666 622
667 p = buf;623 p = buf;
668 if(cache) {624 n = mntrdwr(Tread, c, p, n, off);
669 nc = cread(c, buf, n, off);625 if(c->qid.type & QTDIR) {
670 if(nc > 0) {
671 n -= nc;
672 if(n == 0)
673 return nc;
674 p += nc;
675 off += nc;
676 }
677 n = mntrdwr(Tread, c, p, n, off);
678 cupdate(c, p, n, off);
679 return n + nc;
680 }
681
682 n = mntrdwr(Tread, c, buf, n, off);
683 if(isdir) {
684 for(e = &p[n]; p+BIT16SZ < e; p += dirlen){626 for(e = &p[n]; p+BIT16SZ < e; p += dirlen){
685 dirlen = BIT16SZ+GBIT16(p);627 dirlen = BIT16SZ+GBIT16(p);
686 if(p+dirlen > e)628 if(p+dirlen > e)
@@ -700,23 +642,24 @@ mntwrite(Chan *c, void *buf, long n, vlong off) · 13 unmodified lines
700 return mntrdwr(Twrite, c, buf, n, off);642 return mntrdwr(Twrite, c, buf, n, off);
701}643}
702 644
703long645static long
704mntrdwr(int type, Chan *c, void *buf, long n, vlong off)646mntrdwr(int type, Chan *c, void *buf, long n, vlong off)
705{647{
706 Mnt *m;648 Mnt *m;
707 Mntrpc *r;649 Mntrpc *r;
708 char *uba;650 char *uba;
709 int cache;
710 ulong cnt, nr, nreq;651 ulong cnt, nr, nreq;
711 652
712 m = mntchk(c);653 m = mntchk(c);
713 uba = buf;654 uba = buf;
714 cnt = 0;655 cnt = 0;
715 cache = c->flag & CCACHE;656
716 if(c->qid.type & QTDIR)
717 cache = 0;
718 for(;;) {657 for(;;) {
719 r = mntralloc(c, m->msize);658 nreq = n;
659 if(nreq > c->iounit)
660 nreq = c->iounit;
661
662 r = mntralloc(c);
720 if(waserror()) {663 if(waserror()) {
721 mntfree(r);664 mntfree(r);
722 nexterror();665 nexterror();
@@ -725,23 +668,16 @@ mntrdwr(int type, Chan *c, void *buf, long n, vlong off) · 2 unmodified lines
725 r->request.fid = c->fid;668 r->request.fid = c->fid;
726 r->request.offset = off;669 r->request.offset = off;
727 r->request.data = uba;670 r->request.data = uba;
728 nr = n;671 r->request.count = nreq;
729 if(nr > m->msize-IOHDRSZ)
730 nr = m->msize-IOHDRSZ;
731 r->request.count = nr;
732 mountrpc(m, r);672 mountrpc(m, r);
733 nreq = r->request.count;
734 nr = r->reply.count;673 nr = r->reply.count;
735 if(nr > nreq)674 if(nr > nreq)
736 nr = nreq;675 nr = nreq;
737
738 if(type == Tread)676 if(type == Tread)
739 r->b = bl2mem((uchar*)uba, r->b, nr);677 nr = readblist(r->b, (uchar*)uba, nr, 0);
740 else if(cache)
741 cwrite(c, (uchar*)uba, nr, off);
742
743 poperror();
744 mntfree(r);678 mntfree(r);
679 poperror();
680
745 off += nr;681 off += nr;
746 uba += nr;682 uba += nr;
747 cnt += nr;683 cnt += nr;
@@ -752,10 +688,9 @@ mntrdwr(int type, Chan *c, void *buf, long n, vlong off) · 4 unmodified lines
752 return cnt;688 return cnt;
753}689}
754 690
755void691static void
756mountrpc(Mnt *m, Mntrpc *r)692mountrpc(Mnt *m, Mntrpc *r)
757{693{
758 char *sn, *cn;
759 int t;694 int t;
760 695
761 r->reply.tag = 0;696 r->reply.tag = 0;
@@ -772,60 +707,70 @@ mountrpc(Mnt *m, Mntrpc *r) · 10 unmodified lines
772 default:707 default:
773 if(t == r->request.type+1)708 if(t == r->request.type+1)
774 break;709 break;
775 sn = "?";710 print("mnt: proc %s %lud: mismatch from %s %s rep %#p tag %d fid %d T%d R%d rp %d\n",
776 if(m->c->name != nil)711 up->text, up->pid, chanpath(m->c), chanpath(r->c),
777 sn = m->c->name->s;
778 cn = "?";
779 if(r->c != nil && r->c->name != nil)
780 cn = r->c->name->s;
781 print("mnt: proc %lud: mismatch from %s %s rep 0x%lux tag %d fid %d T%d R%d rp %d\n",
782 up->pid, sn, cn,
783 r, r->request.tag, r->request.fid, r->request.type,712 r, r->request.tag, r->request.fid, r->request.type,
784 r->reply.type, r->reply.tag);713 r->reply.type, r->reply.tag);
785 error(Emountrpc);714 error(Emountrpc);
786 }715 }
787}716}
788 717
789void718static void
790mountio(Mnt *m, Mntrpc *r)719mountio(Mnt *m, Mntrpc *r)
791{720{
721 Block *b;
792 int n;722 int n;
793 723
794 while(waserror()) {724 while(waserror()) {
795 if(m->rip == up)725 if(m->rip == up)
796 mntgate(m);726 mntgate(m);
797 if(strcmp(up->errstr, Eintr) != 0){727 if(strcmp(up->errstr, Eintr) != 0 || waserror()){
798 mntflushfree(m, r);728 r = mntflushfree(m, r);
729 switch(r->request.type){
730 case Tremove:
731 case Tclunk:
732 /* botch, abandon fid */
733 if(strcmp(up->errstr, Ehungup) != 0)
734 r->c->fid = 0;
735 }
799 nexterror();736 nexterror();
800 }737 }
801 r = mntflushalloc(r, m->msize);738 r = mntflushalloc(r);
739 poperror();
802 }740 }
803 741
804 lock(&m->lk);742 lock(&m->lk);
743 r->z = &up->sleep;
805 r->m = m;744 r->m = m;
806 r->list = m->queue;745 r->list = m->queue;
807 m->queue = r;746 m->queue = r;
808 unlock(&m->lk);747 unlock(&m->lk);
809 748
810 /* Transmit a file system rpc */749 /* Transmit a file system rpc */
811 if(m->msize == 0)750 n = sizeS2M(&r->request);
812 panic("msize");751 b = allocb(n);
813 n = convS2M(&r->request, r->rpc, m->msize);752 if(waserror()){
814 if(n < 0)753 freeb(b);
815 panic("bad message type in mountio");754 nexterror();
816 if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n)755 }
756 n = convS2M(&r->request, b->wp, n);
757 if(n <= 0 || n > m->msize) {
758 print("mountio: proc %s %lud: convS2M returned %d for tag %d fid %d T%d\n",
759 up->text, up->pid, n, r->request.tag, r->request.fid, r->request.type);
817 error(Emountrpc);760 error(Emountrpc);
818 r->stime = fastticks(nil);761 }
819 r->reqlen = n;762 b->wp += n;
763 poperror();
764 devtab[m->c->type]->bwrite(m->c, b, 0);
820 765
821 /* Gate readers onto the mount point one at a time */766 /* Gate readers onto the mount point one at a time */
822 for(;;) {767 for(;;) {
823 lock(&m->lk);768 lock(&m->lk);
824 if(m->rip == 0)769 if(m->rip == nil)
825 break;770 break;
826 unlock(&m->lk);771 unlock(&m->lk);
827 sleep(&r->r, rpcattn, r);772 sleep(r->z, rpcattn, r);
828 if(r->done){773 if(r->done) {
829 poperror();774 poperror();
830 mntflushfree(m, r);775 mntflushfree(m, r);
831 return;776 return;
@@ -850,18 +795,13 @@ doread(Mnt *m, int len) · 18 unmodified lines
850 795
851 while(qlen(m->q) < len){796 while(qlen(m->q) < len){
852 b = devtab[m->c->type]->bread(m->c, m->msize, 0);797 b = devtab[m->c->type]->bread(m->c, m->msize, 0);
853 if(b == nil)798 if(b == nil || qaddlist(m->q, b) == 0)
854 return -1;799 return -1;
855 if(BLEN(b) == 0){
856 freeblist(b);
857 return -1;
858 }
859 qaddlist(m->q, b);
860 }800 }
861 return 0;801 return 0;
862}802}
863 803
864int804static int
865mntrpcread(Mnt *m, Mntrpc *r)805mntrpcread(Mnt *m, Mntrpc *r)
866{806{
867 int i, t, len, hlen;807 int i, t, len, hlen;
@@ -875,7 +815,7 @@ mntrpcread(Mnt *m, Mntrpc *r) · 7 unmodified lines
875 return -1;815 return -1;
876 nb = pullupqueue(m->q, BIT32SZ+BIT8SZ+BIT16SZ);816 nb = pullupqueue(m->q, BIT32SZ+BIT8SZ+BIT16SZ);
877 817
878 /* read in the rest of the message, avoid rediculous (for now) message sizes */818 /* read in the rest of the message, avoid ridiculous (for now) message sizes */
879 len = GBIT32(nb->rp);819 len = GBIT32(nb->rp);
880 if(len > m->msize){820 if(len > m->msize){
881 qdiscard(m->q, qlen(m->q));821 qdiscard(m->q, qlen(m->q));
@@ -933,49 +873,50 @@ mntrpcread(Mnt *m, Mntrpc *r) · 51 unmodified lines
933 return 0;873 return 0;
934}874}
935 875
936void876static void
937mntgate(Mnt *m)877mntgate(Mnt *m)
938{878{
939 Mntrpc *q;879 Mntrpc *q;
940 880
941 lock(&m->lk);881 lock(&m->lk);
942 m->rip = 0;882 m->rip = nil;
943 for(q = m->queue; q; q = q->list) {883 for(q = m->queue; q != nil; q = q->list) {
944 if(q->done == 0)884 if(q->done == 0)
945 if(wakeup(&q->r))885 if(wakeup(q->z))
946 break;886 break;
947 }887 }
948 unlock(&m->lk);888 unlock(&m->lk);
949}889}
950 890
951void891static void
952mountmux(Mnt *m, Mntrpc *r)892mountmux(Mnt *m, Mntrpc *r)
953{893{
954 Mntrpc **l, *q;894 Mntrpc **l, *q;
895 Rendez *z;
955 896
956 lock(&m->lk);897 lock(&m->lk);
957 l = &m->queue;898 l = &m->queue;
958 for(q = *l; q; q = q->list) {899 for(q = *l; q != nil; q = q->list) {
959 /* look for a reply to a message */900 /* look for a reply to a message */
960 if(q->request.tag == r->reply.tag) {901 if(q->request.tag == r->reply.tag) {
961 *l = q->list;902 *l = q->list;
962 if(q != r) {903 if(q == r) {
963 /*904 q->done = 1;
964 * Completed someone else.905 unlock(&m->lk);
965 * Trade pointers to receive buffer.906 return;
966 */
967 q->reply = r->reply;
968 q->b = r->b;
969 r->b = nil;
970 }907 }
908 /*
909 * Completed someone else.
910 * Trade pointers to receive buffer.
911 */
912 q->reply = r->reply;
913 q->b = r->b;
914 r->b = nil;
915 z = q->z;
916 // coherence();
971 q->done = 1;917 q->done = 1;
918 wakeup(z);
972 unlock(&m->lk);919 unlock(&m->lk);
973 if(mntstats != 0)
974 (*mntstats)(q->request.type,
975 m->c, q->stime,
976 q->reqlen + r->replen);
977 if(q != r)
978 wakeup(&q->r);
979 return;920 return;
980 }921 }
981 l = &q->list;922 l = &q->list;
@@ -988,13 +929,12 @@ mountmux(Mnt *m, Mntrpc *r) · 6 unmodified lines
988 * Create a new flush request and chain the previous929 * Create a new flush request and chain the previous
989 * requests from it930 * requests from it
990 */931 */
991Mntrpc*932static Mntrpc*
992mntflushalloc(Mntrpc *r, ulong iounit)933mntflushalloc(Mntrpc *r)
993{934{
994 Mntrpc *fr;935 Mntrpc *fr;
995 936
996 fr = mntralloc(0, iounit);937 fr = mntralloc(r->c);
997
998 fr->request.type = Tflush;938 fr->request.type = Tflush;
999 if(r->request.type == Tflush)939 if(r->request.type == Tflush)
1000 fr->request.oldtag = r->request.oldtag;940 fr->request.oldtag = r->request.oldtag;
@@ -1010,26 +950,28 @@ mntflushalloc(Mntrpc *r, ulong iounit) · 9 unmodified lines
1010 * flush and the original message from the unanswered950 * flush and the original message from the unanswered
1011 * request queue. Mark the original message as done951 * request queue. Mark the original message as done
1012 * and if it hasn't been answered set the reply to to952 * and if it hasn't been answered set the reply to to
1013 * Rflush.953 * Rflush. Return the original rpc.
1014 */954 */
1015void955static Mntrpc*
1016mntflushfree(Mnt *m, Mntrpc *r)956mntflushfree(Mnt *m, Mntrpc *r)
1017{957{
1018 Mntrpc *fr;958 Mntrpc *fr;
1019 959
1020 while(r){960 while(r != nil){
1021 fr = r->flushed;961 fr = r->flushed;
1022 if(!r->done){962 if(!r->done){
1023 r->reply.type = Rflush;963 r->reply.type = Rflush;
1024 mntqrm(m, r);964 mntqrm(m, r);
1025 }965 }
1026 if(fr)966 if(fr == nil)
1027 mntfree(r);967 break;
968 mntfree(r);
1028 r = fr;969 r = fr;
1029 }970 }
971 return r;
1030}972}
1031 973
1032int974static int
1033alloctag(void)975alloctag(void)
1034{976{
1035 int i, j;977 int i, j;
@@ -1037,7 +979,7 @@ alloctag(void) · 1 unmodified line
1037 979
1038 for(i = 0; i < NMASK; i++){980 for(i = 0; i < NMASK; i++){
1039 v = mntalloc.tagmask[i];981 v = mntalloc.tagmask[i];
1040 if(v == ~0)982 if(v == ~0UL)
1041 continue;983 continue;
1042 for(j = 0; j < 1<<TAGSHIFT; j++)984 for(j = 0; j < 1<<TAGSHIFT; j++)
1043 if((v & (1<<j)) == 0){985 if((v & (1<<j)) == 0){
@@ -1049,52 +991,33 @@ alloctag(void) · 5 unmodified lines
1049 return NOTAG;991 return NOTAG;
1050}992}
1051 993
1052void994static void
1053freetag(int t)995freetag(int t)
1054{996{
1055 mntalloc.tagmask[t>>TAGSHIFT] &= ~(1<<(t&TAGMASK));997 mntalloc.tagmask[t>>TAGSHIFT] &= ~(1<<(t&TAGMASK));
1056}998}
1057 999
1058Mntrpc*1000static Mntrpc*
1059mntralloc(Chan *c, ulong msize)1001mntralloc(Chan *c)
1060{1002{
1061 Mntrpc *new;1003 Mntrpc *new;
1062 1004
1063 lock(&mntalloc.lk);1005 if(mntalloc.nrpcfree == 0) {
1064 new = mntalloc.rpcfree;1006 Alloc:
1065 if(new == nil){
1066 new = malloc(sizeof(Mntrpc));1007 new = malloc(sizeof(Mntrpc));
1067 if(new == nil) {1008 if(new == nil)
1068 unlock(&mntalloc.lk);
1069 exhausted("mount rpc header");1009 exhausted("mount rpc header");
1070 }1010 lock(&mntalloc.lk);
1071 /*1011 new->request.tag = alloctag();
1072 * The header is split from the data buffer as1012 } else {
1073 * mountmux may swap the buffer with another header.1013 lock(&mntalloc.lk);
1074 */1014 new = mntalloc.rpcfree;
1075 new->rpc = mallocz(msize, 0);1015 if(new == nil) {
1076 if(new->rpc == nil){
1077 free(new);
1078 unlock(&mntalloc.lk);1016 unlock(&mntalloc.lk);
1079 exhausted("mount rpc buffer");1017 goto Alloc;
1080 }1018 }
1081 new->rpclen = msize;
1082 new->request.tag = alloctag();
1083 }
1084 else {
1085 mntalloc.rpcfree = new->list;1019 mntalloc.rpcfree = new->list;
1086 mntalloc.nrpcfree--;1020 mntalloc.nrpcfree--;
1087 if(new->rpclen < msize){
1088 free(new->rpc);
1089 new->rpc = mallocz(msize, 0);
1090 if(new->rpc == nil){
1091 free(new);
1092 mntalloc.nrpcused--;
1093 unlock(&mntalloc.lk);
1094 exhausted("mount rpc buffer");
1095 }
1096 new->rpclen = msize;
1097 }
1098 }1021 }
1099 mntalloc.nrpcused++;1022 mntalloc.nrpcused++;
1100 unlock(&mntalloc.lk);1023 unlock(&mntalloc.lk);
@@ -1105,27 +1028,25 @@ mntralloc(Chan *c, ulong msize) · 4 unmodified lines
1105 return new;1028 return new;
1106}1029}
1107 1030
1108void1031static void
1109mntfree(Mntrpc *r)1032mntfree(Mntrpc *r)
1110{1033{
1111 if(r->b != nil)1034 freeblist(r->b);
1112 freeblist(r->b);
1113 lock(&mntalloc.lk);1035 lock(&mntalloc.lk);
1114 if(mntalloc.nrpcfree >= 10){1036 mntalloc.nrpcused--;
1115 free(r->rpc);1037 if(mntalloc.nrpcfree < 32) {
1116 free(r);
1117 freetag(r->request.tag);
1118 }
1119 else{
1120 r->list = mntalloc.rpcfree;1038 r->list = mntalloc.rpcfree;
1121 mntalloc.rpcfree = r;1039 mntalloc.rpcfree = r;
1122 mntalloc.nrpcfree++;1040 mntalloc.nrpcfree++;
1041 unlock(&mntalloc.lk);
1042 return;
1123 }1043 }
1124 mntalloc.nrpcused--;1044 freetag(r->request.tag);
1125 unlock(&mntalloc.lk);1045 unlock(&mntalloc.lk);
1046 free(r);
1126}1047}
1127 1048
1128void1049static void
1129mntqrm(Mnt *m, Mntrpc *r)1050mntqrm(Mnt *m, Mntrpc *r)
1130{1051{
1131 Mntrpc **l, *f;1052 Mntrpc **l, *f;
@@ -1134,7 +1055,7 @@ mntqrm(Mnt *m, Mntrpc *r) · 2 unmodified lines
1134 r->done = 1;1055 r->done = 1;
1135 1056
1136 l = &m->queue;1057 l = &m->queue;
1137 for(f = *l; f; f = f->list) {1058 for(f = *l; f != nil; f = f->list) {
1138 if(f == r) {1059 if(f == r) {
1139 *l = r->list;1060 *l = r->list;
1140 break;1061 break;
@@ -1144,23 +1065,21 @@ mntqrm(Mnt *m, Mntrpc *r) · 3 unmodified lines
1144 unlock(&m->lk);1065 unlock(&m->lk);
1145}1066}
1146 1067
1147Mnt*1068static Mnt*
1148mntchk(Chan *c)1069mntchk(Chan *c)
1149{1070{
1150 Mnt *m;1071 Mnt *m;
1151 1072
1152 /* This routine is mostly vestiges of prior lives; now it's just sanity checking */1073 /* This routine is mostly vestiges of prior lives; now it's just sanity checking */
1153
1154 if(c->mchan == nil)1074 if(c->mchan == nil)
1155 panic("mntchk 1: nil mchan c %s\n", chanpath(c));1075 panic("mntchk 1: nil mchan c %s", chanpath(c));
1156 1076
1157 m = c->mchan->mux;1077 m = c->mchan->mux;
1158
1159 if(m == nil)1078 if(m == nil)
1160 print("mntchk 2: nil mux c %s c->mchan %s \n", chanpath(c), chanpath(c->mchan));1079 print("mntchk 2: nil mux c %s c->mchan %s \n", chanpath(c), chanpath(c->mchan));
1161 1080
1162 /*1081 /*
1163 * Was it closed and reused (was error(Eshutdown); now, it can't happen)1082 * Was it closed and reused (was error(Eshutdown); now, it cannot happen)
1164 */1083 */
1165 if(m->id == 0 || m->id >= c->dev)1084 if(m->id == 0 || m->id >= c->dev)
1166 panic("mntchk 3: can't happen");1085 panic("mntchk 3: can't happen");
@@ -1173,7 +1092,7 @@ mntchk(Chan *c) · 6 unmodified lines
1173 * reflect local values. These entries are known to be1092 * reflect local values. These entries are known to be
1174 * the first two in the Dir encoding after the count.1093 * the first two in the Dir encoding after the count.
1175 */1094 */
1176void1095static void
1177mntdirfix(uchar *dirbuf, Chan *c)1096mntdirfix(uchar *dirbuf, Chan *c)
1178{1097{
1179 uint r;1098 uint r;
@@ -1185,13 +1104,13 @@ mntdirfix(uchar *dirbuf, Chan *c) · 5 unmodified lines
1185 PBIT32(dirbuf, c->dev);1104 PBIT32(dirbuf, c->dev);
1186}1105}
1187 1106
1188int1107static int
1189rpcattn(void *v)1108rpcattn(void *v)
1190{1109{
1191 Mntrpc *r;1110 Mntrpc *r;
1192 1111
1193 r = v;1112 r = v;
1194 return r->done || r->m->rip == 0;1113 return r->done || r->m->rip == nil;
1195}1114}
1196 1115
1197Dev mntdevtab = {1116Dev mntdevtab = {
@@ -1201,7 +1120,7 @@ Dev mntdevtab = { · 3 unmodified lines
1201 mntreset,1120 mntreset,
1202 devinit,1121 devinit,
1203 devshutdown,1122 devshutdown,
1204 mntattach,1123 noattach,
1205 mntwalk,1124 mntwalk,
1206 mntstat,1125 mntstat,
1207 mntopen,1126 mntopen,
kern/fns.h+2−10
@@ -10,7 +10,6 @@ Block* allocb(int); · 9 unmodified lines
10int anyhigher(void);10int anyhigher(void);
11int anyready(void);11int anyready(void);
12Page* auxpage(void);12Page* auxpage(void);
13Block* bl2mem(uchar*, Block*, int);
14int blocklen(Block*);13int blocklen(Block*);
15void callwithureg(void(*)(Ureg*));14void callwithureg(void(*)(Ureg*));
16char* chanpath(Chan*);15char* chanpath(Chan*);
@@ -27,7 +26,6 @@ void chanfree(Chan*); · 10 unmodified lines
27void chanrec(Mnt*);26void chanrec(Mnt*);
28void checkalarms(void);27void checkalarms(void);
29void checkb(Block*, char*);28void checkb(Block*, char*);
30void cinit(void);
31Chan* cclone(Chan*);29Chan* cclone(Chan*);
32void cclose(Chan*);30void cclose(Chan*);
33char* clipread(void);31char* clipread(void);
@@ -45,14 +43,10 @@ void confinit(void); · 11 unmodified lines
45void confinit1(int);43void confinit1(int);
46int consactive(void);44int consactive(void);
47extern void (*consdebug)(void);45extern void (*consdebug)(void);
48void copen(Chan*);
49Block* concatblock(Block*);46Block* concatblock(Block*);
50Block* copyblock(Block*, int);47Block* copyblock(Block*, int);
51void copypage(Page*, Page*);48void copypage(Page*, Page*);
52int cread(Chan*, uchar*, int, vlong);
53void cunmount(Chan*, Chan*);49void cunmount(Chan*, Chan*);
54void cupdate(Chan*, uchar*, int, vlong);
55void cwrite(Chan*, uchar*, int, vlong);
56ulong dbgpc(Proc*);50ulong dbgpc(Proc*);
57int decref(Ref*);51int decref(Ref*);
58int decrypt(void*, void*, int);52int decrypt(void*, void*, int);
@@ -119,7 +113,6 @@ long hostownerwrite(char*, int); · 60 unmodified lines
119void hzsched(void);113void hzsched(void);
120void iallocinit(void);114void iallocinit(void);
121Block* iallocb(int);115Block* iallocb(int);
122void iallocsummary(void);
123long ibrk(ulong, int);116long ibrk(ulong, int);
124void ilock(Lock*);117void ilock(Lock*);
125void iunlock(Lock*);118void iunlock(Lock*);
@@ -161,8 +154,6 @@ void machinit(void); · 35 unmodified lines
161void* mallocz(ulong, int);154void* mallocz(ulong, int);
162#define malloc kmalloc155#define malloc kmalloc
163void* malloc(ulong);156void* malloc(ulong);
164void mallocsummary(void);
165Block* mem2bl(uchar*, int);
166void mfreeseg(Segment*, ulong, int);157void mfreeseg(Segment*, ulong, int);
167void microdelay(int);158void microdelay(int);
168void mkqid(Qid*, vlong, ulong, int);159void mkqid(Qid*, vlong, ulong, int);
@@ -238,7 +229,8 @@ void putstrn(char*, int); · 69 unmodified lines
238void putswap(Page*);229void putswap(Page*);
239ulong pwait(Waitmsg*);230ulong pwait(Waitmsg*);
240Label* pwaserror(void);231Label* pwaserror(void);
241void qaddlist(Queue*, Block*);232long readblist(Block*, uchar *, long, long);
233int qaddlist(Queue*, Block*);
242Block* qbread(Queue*, int);234Block* qbread(Queue*, int);
243long qbwrite(Queue*, Block*);235long qbwrite(Queue*, Block*);
244Queue* qbypass(void (*)(void*, Block*), void*);236Queue* qbypass(void (*)(void*, Block*), void*);
kern/qio.c+245−364
@@ -10,18 +10,17 @@ static ulong pullupblockcnt; · 9 unmodified lines
10static ulong copyblockcnt;10static ulong copyblockcnt;
11static ulong consumecnt;11static ulong consumecnt;
12static ulong producecnt;12static ulong producecnt;
13static ulong qcopycnt;
14
15static int debugging;
16 13
17#define QDEBUG if(0)14#define QDEBUG if(0)
18 15
19/*16/*
20 * IO queues17 * IO queues
21 */18 */
19typedef struct Queue Queue;
20
22struct Queue21struct Queue
23{22{
24 Lock lk;23 Lock lk;
25 24
26 Block* bfirst; /* buffer */25 Block* bfirst; /* buffer */
27 Block* blast;26 Block* blast;
@@ -53,17 +52,6 @@ enum · 25 unmodified lines
53 52
54uint qiomaxatomic = Maxatomic;53uint qiomaxatomic = Maxatomic;
55 54
56void
57ixsummary(void)
58{
59 debugging ^= 1;
60 iallocsummary();
61 print("pad %lud, concat %lud, pullup %lud, copy %lud\n",
62 padblockcnt, concatblockcnt, pullupblockcnt, copyblockcnt);
63 print("consume %lud, produce %lud, qcopy %lud\n",
64 consumecnt, producecnt, qcopycnt);
65}
66
67/*55/*
68 * free a list of blocks56 * free a list of blocks
69 */57 */
@@ -72,9 +60,9 @@ freeblist(Block *b) · 2 unmodified lines
72{60{
73 Block *next;61 Block *next;
74 62
75 for(; b != 0; b = next){63 for(; b != nil; b = next){
76 next = b->next;64 next = b->next;
77 b->next = 0;65 b->next = nil;
78 freeb(b);66 freeb(b);
79 }67 }
80}68}
@@ -88,40 +76,31 @@ padblock(Block *bp, int size) · 7 unmodified lines
88 int n;76 int n;
89 Block *nbp;77 Block *nbp;
90 78
91 QDEBUG checkb(bp, "padblock 1");79 QDEBUG checkb(bp, "padblock 0");
92 if(size >= 0){80 if(size >= 0){
93 if(bp->rp - bp->base >= size){81 if(bp->rp - bp->base >= size){
94 bp->rp -= size;82 bp->rp -= size;
95 return bp;83 return bp;
96 }84 }
97
98 if(bp->next)
99 panic("padblock 0x%p", getcallerpc(&bp));
100 n = BLEN(bp);85 n = BLEN(bp);
101 padblockcnt++;
102 nbp = allocb(size+n);86 nbp = allocb(size+n);
103 nbp->rp += size;87 nbp->rp += size;
104 nbp->wp = nbp->rp;88 nbp->wp = nbp->rp;
105 memmove(nbp->wp, bp->rp, n);89 memmove(nbp->wp, bp->rp, n);
106 nbp->wp += n;90 nbp->wp += n;
107 freeb(bp);
108 nbp->rp -= size;91 nbp->rp -= size;
109 } else {92 } else {
110 size = -size;93 size = -size;
111
112 if(bp->next)
113 panic("padblock 0x%p", getcallerpc(&bp));
114
115 if(bp->lim - bp->wp >= size)94 if(bp->lim - bp->wp >= size)
116 return bp;95 return bp;
117
118 n = BLEN(bp);96 n = BLEN(bp);
119 padblockcnt++;97 nbp = allocb(n+size);
120 nbp = allocb(size+n);
121 memmove(nbp->wp, bp->rp, n);98 memmove(nbp->wp, bp->rp, n);
122 nbp->wp += n;99 nbp->wp += n;
123 freeb(bp);
124 }100 }
101 nbp->next = bp->next;
102 freeb(bp);
103 padblockcnt++;
125 QDEBUG checkb(nbp, "padblock 1");104 QDEBUG checkb(nbp, "padblock 1");
126 return nbp;105 return nbp;
127}106}
@@ -135,7 +114,7 @@ blocklen(Block *bp) · 7 unmodified lines
135 int len;114 int len;
136 115
137 len = 0;116 len = 0;
138 while(bp) {117 while(bp != nil) {
139 len += BLEN(bp);118 len += BLEN(bp);
140 bp = bp->next;119 bp = bp->next;
141 }120 }
@@ -151,7 +130,7 @@ blockalloclen(Block *bp) · 9 unmodified lines
151 int len;130 int len;
152 131
153 len = 0;132 len = 0;
154 while(bp) {133 while(bp != nil) {
155 len += BALLOC(bp);134 len += BALLOC(bp);
156 bp = bp->next;135 bp = bp->next;
157 }136 }
@@ -159,28 +138,19 @@ blockalloclen(Block *bp) · 1 unmodified line
159}138}
160 139
161/*140/*
162 * copy the string of blocks into141 * copy the string of blocks into
163 * a single block and free the string142 * a single block and free the string
164 */143 */
165Block*144Block*
166concatblock(Block *bp)145concatblock(Block *bp)
167{146{
168 int len;147 int len;
169 Block *nb, *f;
170 148
171 if(bp->next == 0)149 if(bp->next == nil)
172 return bp;150 return bp;
173 151 len = blocklen(bp);
174 nb = allocb(blocklen(bp));152 concatblockcnt += len;
175 for(f = bp; f; f = f->next) {153 return pullupblock(bp, len);
176 len = BLEN(f);
177 memmove(nb->wp, f->rp, len);
178 nb->wp += len;
179 }
180 concatblockcnt += BLEN(nb);
181 freeblist(bp);
182 QDEBUG checkb(nb, "concatblock 1");
183 return nb;
184}154}
185 155
186/*156/*
@@ -189,8 +159,8 @@ concatblock(Block *bp) · 2 unmodified lines
189Block*159Block*
190pullupblock(Block *bp, int n)160pullupblock(Block *bp, int n)
191{161{
192 int i;
193 Block *nbp;162 Block *nbp;
163 int i;
194 164
195 /*165 /*
196 * this should almost always be true, it's166 * this should almost always be true, it's
@@ -213,11 +183,11 @@ pullupblock(Block *bp, int n) · 16 unmodified lines
213 * copy bytes from the trailing blocks into the first183 * copy bytes from the trailing blocks into the first
214 */184 */
215 n -= BLEN(bp);185 n -= BLEN(bp);
216 while((nbp = bp->next)){186 while((nbp = bp->next) != nil){
187 pullupblockcnt++;
217 i = BLEN(nbp);188 i = BLEN(nbp);
218 if(i > n) {189 if(i > n) {
219 memmove(bp->wp, nbp->rp, n);190 memmove(bp->wp, nbp->rp, n);
220 pullupblockcnt++;
221 bp->wp += n;191 bp->wp += n;
222 nbp->rp += n;192 nbp->rp += n;
223 QDEBUG checkb(bp, "pullupblock 1");193 QDEBUG checkb(bp, "pullupblock 1");
@@ -225,14 +195,14 @@ pullupblock(Block *bp, int n) · 1 unmodified line
225 } else {195 } else {
226 /* shouldn't happen but why crash if it does */196 /* shouldn't happen but why crash if it does */
227 if(i < 0){197 if(i < 0){
228 print("pullup negative length packet\n");198 print("pullup negative length packet, called from %#p\n",
199 getcallerpc(&bp));
229 i = 0;200 i = 0;
230 }201 }
231 memmove(bp->wp, nbp->rp, i);202 memmove(bp->wp, nbp->rp, i);
232 pullupblockcnt++;
233 bp->wp += i;203 bp->wp += i;
234 bp->next = nbp->next;204 bp->next = nbp->next;
235 nbp->next = 0;205 nbp->next = nil;
236 freeb(nbp);206 freeb(nbp);
237 n -= i;207 n -= i;
238 if(n == 0){208 if(n == 0){
@@ -242,7 +212,7 @@ pullupblock(Block *bp, int n) · 3 unmodified lines
242 }212 }
243 }213 }
244 freeb(bp);214 freeb(bp);
245 return 0;215 return nil;
246}216}
247 217
248/*218/*
@@ -295,7 +265,7 @@ trimblock(Block *bp, int offset, int len) · 46 unmodified lines
295 265
296 bp->wp -= (BLEN(bp) - len);266 bp->wp -= (BLEN(bp) - len);
297 267
298 if(bp->next) {268 if(bp->next != nil) {
299 freeblist(bp->next);269 freeblist(bp->next);
300 bp->next = nil;270 bp->next = nil;
301 }271 }
@@ -314,7 +284,7 @@ copyblock(Block *bp, int count) · 12 unmodified lines
314 284
315 QDEBUG checkb(bp, "copyblock 0");285 QDEBUG checkb(bp, "copyblock 0");
316 nbp = allocb(count);286 nbp = allocb(count);
317 for(; count > 0 && bp != 0; bp = bp->next){287 for(; count > 0 && bp != nil; bp = bp->next){
318 l = BLEN(bp);288 l = BLEN(bp);
319 if(l > count)289 if(l > count)
320 l = count;290 l = count;
@@ -412,11 +382,11 @@ qget(Queue *q) · 91 unmodified lines
412 iunlock(&q->lk);382 iunlock(&q->lk);
413 return nil;383 return nil;
414 }384 }
385 QDEBUG checkb(b, "qget");
415 q->bfirst = b->next;386 q->bfirst = b->next;
416 b->next = 0;387 b->next = nil;
417 q->len -= BALLOC(b);388 q->len -= BALLOC(b);
418 q->dlen -= BLEN(b);389 q->dlen -= BLEN(b);
419 QDEBUG checkb(b, "qget");
420 390
421 /* if writer flow controlled, restart */391 /* if writer flow controlled, restart */
422 if((q->state & Qflow) && q->len < q->limit/2){392 if((q->state & Qflow) && q->len < q->limit/2){
@@ -439,7 +409,7 @@ qget(Queue *q) · 16 unmodified lines
439int409int
440qdiscard(Queue *q, int len)410qdiscard(Queue *q, int len)
441{411{
442 Block *b;412 Block *b, *tofree = nil;
443 int dowakeup, n, sofar;413 int dowakeup, n, sofar;
444 414
445 ilock(&q->lk);415 ilock(&q->lk);
@@ -451,10 +421,12 @@ qdiscard(Queue *q, int len) · 5 unmodified lines
451 n = BLEN(b);421 n = BLEN(b);
452 if(n <= len - sofar){422 if(n <= len - sofar){
453 q->bfirst = b->next;423 q->bfirst = b->next;
454 b->next = 0;
455 q->len -= BALLOC(b);424 q->len -= BALLOC(b);
456 q->dlen -= BLEN(b);425 q->dlen -= BLEN(b);
457 freeb(b);426
427 /* remember to free this */
428 b->next = tofree;
429 tofree = b;
458 } else {430 } else {
459 n = len - sofar;431 n = len - sofar;
460 b->rp += n;432 b->rp += n;
@@ -483,6 +455,9 @@ qdiscard(Queue *q, int len) · 22 unmodified lines
483 if(dowakeup)455 if(dowakeup)
484 wakeup(&q->wr);456 wakeup(&q->wr);
485 457
458 if(tofree != nil)
459 freeblist(tofree);
460
486 return sofar;461 return sofar;
487}462}
488 463
@@ -492,20 +467,19 @@ qdiscard(Queue *q, int len) · 3 unmodified lines
492int467int
493qconsume(Queue *q, void *vp, int len)468qconsume(Queue *q, void *vp, int len)
494{469{
495 Block *b;470 Block *b, *tofree = nil;
496 int n, dowakeup;471 int n, dowakeup;
497 uchar *p = vp;472 uchar *p = vp;
498 Block *tofree = nil;
499 473
500 /* sync with qwrite */474 /* sync with qwrite */
501 ilock(&q->lk);475 ilock(&q->lk);
502 476
503 for(;;) {477 for(;;) {
504 b = q->bfirst;478 b = q->bfirst;
505 if(b == 0){479 if(b == nil){
506 q->state |= Qstarve;480 q->state |= Qstarve;
507 iunlock(&q->lk);481 len = -1;
508 return -1;482 goto out;
509 }483 }
510 QDEBUG checkb(b, "qconsume 1");484 QDEBUG checkb(b, "qconsume 1");
511 485
@@ -520,17 +494,16 @@ qconsume(Queue *q, void *vp, int len) · 8 unmodified lines
520 tofree = b;494 tofree = b;
521 };495 };
522 496
497 consumecnt += n;
523 if(n < len)498 if(n < len)
524 len = n;499 len = n;
525 memmove(p, b->rp, len);500 memmove(p, b->rp, len);
526 consumecnt += n;
527 b->rp += len;501 b->rp += len;
528 q->dlen -= len;502 q->dlen -= len;
529 503
530 /* discard the block if we're done with it */504 /* discard the block if we're done with it */
531 if((q->state & Qmsg) || len == n){505 if((q->state & Qmsg) || len == n){
532 q->bfirst = b->next;506 q->bfirst = b->next;
533 b->next = 0;
534 q->len -= BALLOC(b);507 q->len -= BALLOC(b);
535 q->dlen -= BLEN(b);508 q->dlen -= BLEN(b);
536 509
@@ -539,6 +512,7 @@ qconsume(Queue *q, void *vp, int len) · 2 unmodified lines
539 tofree = b;512 tofree = b;
540 }513 }
541 514
515out:
542 /* if writer flow controlled, restart */516 /* if writer flow controlled, restart */
543 if((q->state & Qflow) && q->len < q->limit/2){517 if((q->state & Qflow) && q->len < q->limit/2){
544 q->state &= ~Qflow;518 q->state &= ~Qflow;
@@ -560,39 +534,23 @@ qconsume(Queue *q, void *vp, int len) · 15 unmodified lines
560int534int
561qpass(Queue *q, Block *b)535qpass(Queue *q, Block *b)
562{536{
563 int dlen, len, dowakeup;537 int len, dowakeup;
564 538
565 /* sync with qread */539 /* sync with qread */
566 dowakeup = 0;540 dowakeup = 0;
567 ilock(&q->lk);541 ilock(&q->lk);
568 if(q->len >= q->limit){542 if(q->len >= q->limit){
569 freeblist(b);
570 iunlock(&q->lk);543 iunlock(&q->lk);
544 freeblist(b);
571 return -1;545 return -1;
572 }546 }
573 if(q->state & Qclosed){547 if(q->state & Qclosed){
574 freeblist(b);
575 iunlock(&q->lk);548 iunlock(&q->lk);
576 return BALLOC(b);549 freeblist(b);
550 return 0;
577 }551 }
578 552
579 /* add buffer to queue */553 len = qaddlist(q, b);
580 if(q->bfirst)
581 q->blast->next = b;
582 else
583 q->bfirst = b;
584 len = BALLOC(b);
585 dlen = BLEN(b);
586 QDEBUG checkb(b, "qpass");
587 while(b->next){
588 b = b->next;
589 QDEBUG checkb(b, "qpass");
590 len += BALLOC(b);
591 dlen += BLEN(b);
592 }
593 q->blast = b;
594 q->len += len;
595 q->dlen += dlen;
596 554
597 if(q->len >= q->limit/2)555 if(q->len >= q->limit/2)
598 q->state |= Qflow;556 q->state |= Qflow;
@@ -612,35 +570,19 @@ qpass(Queue *q, Block *b) · 13 unmodified lines
612int570int
613qpassnolim(Queue *q, Block *b)571qpassnolim(Queue *q, Block *b)
614{572{
615 int dlen, len, dowakeup;573 int len, dowakeup;
616 574
617 /* sync with qread */575 /* sync with qread */
618 dowakeup = 0;576 dowakeup = 0;
619 ilock(&q->lk);577 ilock(&q->lk);
620 578
621 if(q->state & Qclosed){579 if(q->state & Qclosed){
622 freeblist(b);
623 iunlock(&q->lk);580 iunlock(&q->lk);
624 return BALLOC(b);581 freeblist(b);
582 return 0;
625 }583 }
626 584
627 /* add buffer to queue */585 len = qaddlist(q, b);
628 if(q->bfirst)
629 q->blast->next = b;
630 else
631 q->bfirst = b;
632 len = BALLOC(b);
633 dlen = BLEN(b);
634 QDEBUG checkb(b, "qpass");
635 while(b->next){
636 b = b->next;
637 QDEBUG checkb(b, "qpass");
638 len += BALLOC(b);
639 dlen += BLEN(b);
640 }
641 q->blast = b;
642 q->len += len;
643 q->dlen += dlen;
644 586
645 if(q->len >= q->limit/2)587 if(q->len >= q->limit/2)
646 q->state |= Qflow;588 q->state |= Qflow;
@@ -667,8 +609,7 @@ packblock(Block *bp) · 20 unmodified lines
667 Block **l, *nbp;609 Block **l, *nbp;
668 int n;610 int n;
669 611
670 for(l = &bp; *l; l = &(*l)->next){612 for(l = &bp; (nbp = *l) != nil; l = &(*l)->next){
671 nbp = *l;
672 n = BLEN(nbp);613 n = BLEN(nbp);
673 if((n<<2) < BALLOC(nbp)){614 if((n<<2) < BALLOC(nbp)){
674 *l = allocb(n);615 *l = allocb(n);
@@ -689,6 +630,10 @@ qproduce(Queue *q, void *vp, int len) · 14 unmodified lines
689 int dowakeup;630 int dowakeup;
690 uchar *p = vp;631 uchar *p = vp;
691 632
633 b = iallocb(len);
634 if(b == nil)
635 return 0;
636
692 /* sync with qread */637 /* sync with qread */
693 dowakeup = 0;638 dowakeup = 0;
694 ilock(&q->lk);639 ilock(&q->lk);
@@ -699,25 +644,12 @@ qproduce(Queue *q, void *vp, int len) · 4 unmodified lines
699 iunlock(&q->lk);644 iunlock(&q->lk);
700 return -1;645 return -1;
701 }646 }
647 producecnt += len;
702 648
703 /* save in buffer */649 /* save in buffer */
704 b = iallocb(len);
705 if(b == 0){
706 iunlock(&q->lk);
707 return 0;
708 }
709 memmove(b->wp, p, len);650 memmove(b->wp, p, len);
710 producecnt += len;
711 b->wp += len;651 b->wp += len;
712 if(q->bfirst)652 qaddlist(q, b);
713 q->blast->next = b;
714 else
715 q->bfirst = b;
716 q->blast = b;
717 /* b->next = 0; done by iallocb() */
718 q->len += BALLOC(b);
719 q->dlen += BLEN(b);
720 QDEBUG checkb(b, "qproduce");
721 653
722 if(q->state & Qstarve){654 if(q->state & Qstarve){
723 q->state &= ~Qstarve;655 q->state &= ~Qstarve;
@@ -740,49 +672,13 @@ qproduce(Queue *q, void *vp, int len) · 16 unmodified lines
740Block*672Block*
741qcopy(Queue *q, int len, ulong offset)673qcopy(Queue *q, int len, ulong offset)
742{674{
743 int sofar;675 Block *b;
744 int n;
745 Block *b, *nb;
746 uchar *p;
747
748 nb = allocb(len);
749 676
677 b = allocb(len);
750 ilock(&q->lk);678 ilock(&q->lk);
751 679 b->wp += readblist(q->bfirst, b->wp, len, offset);
752 /* go to offset */
753 b = q->bfirst;
754 for(sofar = 0; ; sofar += n){
755 if(b == nil){
756 iunlock(&q->lk);
757 return nb;
758 }
759 n = BLEN(b);
760 if(sofar + n > offset){
761 p = b->rp + offset - sofar;
762 n -= offset - sofar;
763 break;
764 }
765 QDEBUG checkb(b, "qcopy");
766 b = b->next;
767 }
768
769 /* copy bytes from there */
770 for(sofar = 0; sofar < len;){
771 if(n > len - sofar)
772 n = len - sofar;
773 memmove(nb->wp, p, n);
774 qcopycnt += n;
775 sofar += n;
776 nb->wp += n;
777 b = b->next;
778 if(b == nil)
779 break;
780 n = BLEN(b);
781 p = b->rp;
782 }
783 iunlock(&q->lk);680 iunlock(&q->lk);
784 681 return b;
785 return nb;
786}682}
787 683
788/*684/*
@@ -794,8 +690,8 @@ qopen(int limit, int msg, void (*kick)(void*), void *arg) · 5 unmodified lines
794 Queue *q;690 Queue *q;
795 691
796 q = malloc(sizeof(Queue));692 q = malloc(sizeof(Queue));
797 if(q == 0)693 if(q == nil)
798 return 0;694 return nil;
799 695
800 q->limit = q->inilim = limit;696 q->limit = q->inilim = limit;
801 q->kick = kick;697 q->kick = kick;
@@ -816,8 +712,8 @@ qbypass(void (*bypass)(void*, Block*), void *arg) · 14 unmodified lines
816 Queue *q;712 Queue *q;
817 713
818 q = malloc(sizeof(Queue));714 q = malloc(sizeof(Queue));
819 if(q == 0)715 if(q == nil)
820 return 0;716 return nil;
821 717
822 q->limit = 0;718 q->limit = 0;
823 q->arg = arg;719 q->arg = arg;
@@ -832,7 +728,7 @@ notempty(void *a) · 8 unmodified lines
832{728{
833 Queue *q = a;729 Queue *q = a;
834 730
835 return (q->state & Qclosed) || q->bfirst != 0;731 return (q->state & Qclosed) || q->bfirst != nil;
836}732}
837 733
838/*734/*
@@ -864,21 +760,34 @@ qwait(Queue *q) · 25 unmodified lines
864}760}
865 761
866/*762/*
867 * add a block list to a queue763 * add a block list to a queue, return bytes added
868 */764 */
869void765int
870qaddlist(Queue *q, Block *b)766qaddlist(Queue *q, Block *b)
871{767{
768 int len, dlen;
769
770 QDEBUG checkb(b, "qaddlist 1");
771
872 /* queue the block */772 /* queue the block */
873 if(q->bfirst)773 if(q->bfirst != nil)
874 q->blast->next = b;774 q->blast->next = b;
875 else775 else
876 q->bfirst = b;776 q->bfirst = b;
877 q->len += blockalloclen(b);777
878 q->dlen += blocklen(b);778 len = BALLOC(b);
879 while(b->next)779 dlen = BLEN(b);
780 while(b->next != nil){
880 b = b->next;781 b = b->next;
782 QDEBUG checkb(b, "qaddlist 2");
783
784 len += BALLOC(b);
785 dlen += BLEN(b);
786 }
881 q->blast = b;787 q->blast = b;
788 q->len += len;
789 q->dlen += dlen;
790 return dlen;
882}791}
883 792
884/*793/*
@@ -892,74 +801,42 @@ qremove(Queue *q) · 7 unmodified lines
892 b = q->bfirst;801 b = q->bfirst;
893 if(b == nil)802 if(b == nil)
894 return nil;803 return nil;
804 QDEBUG checkb(b, "qremove");
895 q->bfirst = b->next;805 q->bfirst = b->next;
896 b->next = nil;806 b->next = nil;
897 q->dlen -= BLEN(b);807 q->dlen -= BLEN(b);
898 q->len -= BALLOC(b);808 q->len -= BALLOC(b);
899 QDEBUG checkb(b, "qremove");
900 return b;809 return b;
901}810}
902 811
903/*812/*
904 * copy the contents of a string of blocks into813 * copy the contents of a string of blocks into
905 * memory. emptied blocks are freed. return814 * memory from an offset. blocklist kept unchanged.
906 * pointer to first unconsumed block.815 * return number of copied bytes.
907 */816 */
908Block*817long
909bl2mem(uchar *p, Block *b, int n)818readblist(Block *b, uchar *p, long n, long o)
910{819{
911 int i;820 long m, r;
912 Block *next;
913 821
914 for(; b != nil; b = next){822 r = 0;
915 i = BLEN(b);823 while(n > 0 && b != nil){
916 if(i > n){824 m = BLEN(b);
917 memmove(p, b->rp, n);825 if(o >= m)
918 b->rp += n;826 o -= m;
919 return b;827 else {
828 m -= o;
829 if(n < m)
830 m = n;
831 memmove(p, b->rp + o, m);
832 p += m;
833 r += m;
834 n -= m;
835 o = 0;
920 }836 }
921 memmove(p, b->rp, i);837 b = b->next;
922 n -= i;
923 p += i;
924 b->rp += i;
925 next = b->next;
926 freeb(b);
927 }
928 return nil;
929}
930
931/*
932 * copy the contents of memory into a string of blocks.
933 * return nil on error.
934 */
935Block*
936mem2bl(uchar *p, int len)
937{
938 int n;
939 Block *b, *first, **l;
940
941 first = nil;
942 l = &first;
943 if(waserror()){
944 freeblist(first);
945 nexterror();
946 }838 }
947 do {839 return r;
948 n = len;
949 if(n > Maxatomic)
950 n = Maxatomic;
951
952 *l = b = allocb(n);
953 /* setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]); */
954 memmove(b->wp, p, n);
955 b->wp += n;
956 p += n;
957 len -= n;
958 l = &b->next;
959 } while(len > 0);
960 poperror();
961
962 return first;
963}840}
964 841
965/*842/*
@@ -977,6 +854,35 @@ qputback(Queue *q, Block *b) · 11 unmodified lines
977 q->dlen += BLEN(b);854 q->dlen += BLEN(b);
978}855}
979 856
857/*
858 * cut off n bytes from the end of *h. return a new
859 * block with the tail and change *h to refer to the
860 * head.
861 */
862static Block*
863splitblock(Block **h, int n)
864{
865 Block *a, *b;
866 int m;
867
868 a = *h;
869 m = BLEN(a) - n;
870 if(m < n){
871 b = allocb(m);
872 memmove(b->wp, a->rp, m);
873 b->wp += m;
874 a->rp += m;
875 *h = b;
876 return a;
877 } else {
878 b = allocb(n);
879 a->wp -= n;
880 memmove(b->wp, a->wp, n);
881 b->wp += n;
882 return b;
883 }
884}
885
980/*886/*
981 * flow control, get producer going again887 * flow control, get producer going again
982 * called with q ilocked888 * called with q ilocked
@@ -996,7 +902,7 @@ qwakeup_iunlock(Queue *q) · 13 unmodified lines
996 902
997 /* wakeup flow controlled writers */903 /* wakeup flow controlled writers */
998 if(dowakeup){904 if(dowakeup){
999 if(q->kick)905 if(q->kick != nil)
1000 q->kick(q->arg);906 q->kick(q->arg);
1001 wakeup(&q->wr);907 wakeup(&q->wr);
1002 }908 }
@@ -1008,7 +914,7 @@ qwakeup_iunlock(Queue *q) · 5 unmodified lines
1008Block*914Block*
1009qbread(Queue *q, int len)915qbread(Queue *q, int len)
1010{916{
1011 Block *b, *nb;917 Block *b;
1012 int n;918 int n;
1013 919
1014 qlock(&q->rlock);920 qlock(&q->rlock);
@@ -1036,24 +942,21 @@ qbread(Queue *q, int len) · 21 unmodified lines
1036 n = BLEN(b);942 n = BLEN(b);
1037 943
1038 /* split block if it's too big and this is not a message queue */944 /* split block if it's too big and this is not a message queue */
1039 nb = b;
1040 if(n > len){945 if(n > len){
1041 if((q->state&Qmsg) == 0){946 n -= len;
1042 n -= len;947 if((q->state & Qmsg) == 0)
1043 b = allocb(n);948 qputback(q, splitblock(&b, n));
1044 memmove(b->wp, nb->rp+len, n);949 else
1045 b->wp += n;950 b->wp -= n;
1046 qputback(q, b);
1047 }
1048 nb->wp = nb->rp + len;
1049 }951 }
1050 952
1051 /* restart producer */953 /* restart producer */
1052 qwakeup_iunlock(q);954 qwakeup_iunlock(q);
1053 955
1054 poperror();
1055 qunlock(&q->rlock);956 qunlock(&q->rlock);
1056 return nb;957 poperror();
958
959 return b;
1057}960}
1058 961
1059/*962/*
@@ -1063,7 +966,7 @@ qbread(Queue *q, int len) · 3 unmodified lines
1063long966long
1064qread(Queue *q, void *vp, int len)967qread(Queue *q, void *vp, int len)
1065{968{
1066 Block *b, *first, **l;969 Block *b, *first, **last;
1067 int m, n;970 int m, n;
1068 971
1069 qlock(&q->rlock);972 qlock(&q->rlock);
@@ -1088,57 +991,53 @@ again: · 18 unmodified lines
1088 }991 }
1089 992
1090 /* if we get here, there's at least one block in the queue */993 /* if we get here, there's at least one block in the queue */
994 last = &first;
1091 if(q->state & Qcoalesce){995 if(q->state & Qcoalesce){
1092 /* when coalescing, 0 length blocks just go away */996 /* when coalescing, 0 length blocks just go away */
1093 b = q->bfirst;997 b = q->bfirst;
1094 if(BLEN(b) <= 0){998 m = BLEN(b);
999 if(m <= 0){
1095 freeb(qremove(q));1000 freeb(qremove(q));
1096 goto again;1001 goto again;
1097 }1002 }
1098 1003
1099 /* grab the first block plus as many1004 /* grab the first block plus as many
1100 * following blocks as will completely1005 * following blocks as will partially
1101 * fit in the read.1006 * fit in the read.
1102 */1007 */
1103 n = 0;1008 n = 0;
1104 l = &first;
1105 m = BLEN(b);
1106 for(;;) {1009 for(;;) {
1107 *l = qremove(q);1010 *last = qremove(q);
1108 l = &b->next;
1109 n += m;1011 n += m;
1110 1012 if(n >= len || q->bfirst == nil)
1111 b = q->bfirst;
1112 if(b == nil)
1113 break;1013 break;
1014 last = &b->next;
1015 b = q->bfirst;
1114 m = BLEN(b);1016 m = BLEN(b);
1115 if(n+m > len)
1116 break;
1117 }1017 }
1118 } else {1018 } else {
1119 first = qremove(q);1019 first = qremove(q);
1120 n = BLEN(first);1020 n = BLEN(first);
1121 }1021 }
1122 1022
1123 /* copy to user space outside of the ilock */1023 /* split last block if it's too big and this is not a message queue */
1124 iunlock(&q->lk);1024 if(n > len && (q->state & Qmsg) == 0)
1125 b = bl2mem(vp, first, len);1025 qputback(q, splitblock(last, n - len));
1126 ilock(&q->lk);
1127
1128 /* take care of any left over partial block */
1129 if(b != nil){
1130 n -= BLEN(b);
1131 if(q->state & Qmsg)
1132 freeb(b);
1133 else
1134 qputback(q, b);
1135 }
1136 1026
1137 /* restart producer */1027 /* restart producer */
1138 qwakeup_iunlock(q);1028 qwakeup_iunlock(q);
1139 1029
1140 poperror();
1141 qunlock(&q->rlock);1030 qunlock(&q->rlock);
1031 poperror();
1032
1033 if(waserror()){
1034 freeblist(first);
1035 nexterror();
1036 }
1037 n = readblist(first, vp, len, 0);
1038 freeblist(first);
1039 poperror();
1040
1142 return n;1041 return n;
1143}1042}
1144 1043
@@ -1150,7 +1049,30 @@ qnotfull(void *a) · 5 unmodified lines
1150 return q->len < q->limit || (q->state & Qclosed);1049 return q->len < q->limit || (q->state & Qclosed);
1151}1050}
1152 1051
1153ulong noblockcnt;1052/*
1053 * flow control, wait for queue to get below the limit
1054 */
1055static void
1056qflow(Queue *q)
1057{
1058 for(;;){
1059 if(q->noblock || qnotfull(q))
1060 break;
1061
1062 ilock(&q->lk);
1063 q->state |= Qflow;
1064 iunlock(&q->lk);
1065
1066 qlock(&q->wlock);
1067 if(waserror()){
1068 qunlock(&q->wlock);
1069 nexterror();
1070 }
1071 sleep(&q->wr, qnotfull, q);
1072 qunlock(&q->wlock);
1073 poperror();
1074 }
1075}
1154 1076
1155/*1077/*
1156 * add a block to a queue obeying flow control1078 * add a block to a queue obeying flow control
@@ -1158,24 +1080,19 @@ ulong noblockcnt; · 1 unmodified line
1158long1080long
1159qbwrite(Queue *q, Block *b)1081qbwrite(Queue *q, Block *b)
1160{1082{
1161 int n, dowakeup;1083 int len, dowakeup;
1162 1084
1163 n = BLEN(b);1085 if(q->bypass != nil){
1164 1086 len = blocklen(b);
1165 if(q->bypass){
1166 (*q->bypass)(q->arg, b);1087 (*q->bypass)(q->arg, b);
1167 return n;1088 return len;
1168 }1089 }
1169 1090
1170 dowakeup = 0;1091 dowakeup = 0;
1171 qlock(&q->wlock);
1172 if(waserror()){1092 if(waserror()){
1173 if(b != nil)1093 freeblist(b);
1174 freeb(b);
1175 qunlock(&q->wlock);
1176 nexterror();1094 nexterror();
1177 }1095 }
1178
1179 ilock(&q->lk);1096 ilock(&q->lk);
1180 1097
1181 /* give up if the queue is closed */1098 /* give up if the queue is closed */
@@ -1184,29 +1101,16 @@ qbwrite(Queue *q, Block *b) · 2 unmodified lines
1184 error(q->err);1101 error(q->err);
1185 }1102 }
1186 1103
1187 /* if nonblocking, don't queue over the limit */1104 /* don't queue over the limit */
1188 if(q->len >= q->limit){1105 if(q->len >= q->limit && q->noblock){
1189 if(q->noblock){1106 iunlock(&q->lk);
1190 iunlock(&q->lk);1107 poperror();
1191 freeb(b);1108 len = blocklen(b);
1192 noblockcnt += n;1109 freeblist(b);
1193 qunlock(&q->wlock);1110 return len;
1194 poperror();
1195 return n;
1196 }
1197 }1111 }
1198 1112
1199 /* queue the block */1113 len = qaddlist(q, b);
1200 if(q->bfirst)
1201 q->blast->next = b;
1202 else
1203 q->bfirst = b;
1204 q->blast = b;
1205 b->next = 0;
1206 q->len += BALLOC(b);
1207 q->dlen += n;
1208 QDEBUG checkb(b, "qbwrite");
1209 b = nil;
1210 1114
1211 /* make sure other end gets awakened */1115 /* make sure other end gets awakened */
1212 if(q->state & Qstarve){1116 if(q->state & Qstarve){
@@ -1214,49 +1118,26 @@ qbwrite(Queue *q, Block *b) · 1 unmodified line
1214 dowakeup = 1;1118 dowakeup = 1;
1215 }1119 }
1216 iunlock(&q->lk);1120 iunlock(&q->lk);
1121 poperror();
1217 1122
1218 /* get output going again */1123 /* get output going again */
1219 if(q->kick && (dowakeup || (q->state&Qkick)))1124 if(q->kick != nil && (dowakeup || (q->state&Qkick)))
1220 q->kick(q->arg);1125 q->kick(q->arg);
1221 1126
1222 /* wakeup anyone consuming at the other end */1127 /* wakeup anyone consuming at the other end */
1223 if(dowakeup){1128 if(dowakeup)
1224 wakeup(&q->rr);1129 wakeup(&q->rr);
1225 1130
1226 /* if we just wokeup a higher priority process, let it run */
1227 /*
1228 p = wakeup(&q->rr);
1229 if(p != nil && p->priority > up->priority)
1230 sched();
1231 */
1232 }
1233
1234 /*1131 /*
1235 * flow control, wait for queue to get below the limit1132 * flow control, before allowing the process to continue and
1236 * before allowing the process to continue and queue1133 * queue more. We do this here so that postnote can only
1237 * more. We do this here so that postnote can only1134 * interrupt us after the data has been queued. This means that
1238 * interrupt us after the data has been queued. This1135 * things like 9p flushes and ssl messages will not be disrupted
1239 * means that things like 9p flushes and ssl messages1136 * by software interrupts.
1240 * will not be disrupted by software interrupts.
1241 *
1242 * Note - this is moderately dangerous since a process
1243 * that keeps getting interrupted and rewriting will
1244 * queue infinite crud.
1245 */1137 */
1246 for(;;){1138 qflow(q);
1247 if(q->noblock || qnotfull(q))
1248 break;
1249 1139
1250 ilock(&q->lk);1140 return len;
1251 q->state |= Qflow;
1252 iunlock(&q->lk);
1253 sleep(&q->wr, qnotfull, q);
1254 }
1255 USED(b);
1256
1257 qunlock(&q->wlock);
1258 poperror();
1259 return n;
1260}1141}
1261 1142
1262/*1143/*
@@ -1270,7 +1151,15 @@ qwrite(Queue *q, void *vp, int len) · 7 unmodified lines
1270 uchar *p = vp;1151 uchar *p = vp;
1271 1152
1272 QDEBUG if(!islo())1153 QDEBUG if(!islo())
1273 print("qwrite hi %p\n", getcallerpc(&q));1154 print("qwrite hi %#p\n", getcallerpc(&q));
1155
1156 /* stop queue bloat before allocating blocks */
1157 if(q->len/2 >= q->limit && q->noblock == 0 && q->bypass == nil){
1158 while(waserror())
1159 ;
1160 qflow(q);
1161 poperror();
1162 }
1274 1163
1275 sofar = 0;1164 sofar = 0;
1276 do {1165 do {
@@ -1279,7 +1168,6 @@ qwrite(Queue *q, void *vp, int len) · 2 unmodified lines
1279 n = Maxatomic;1168 n = Maxatomic;
1280 1169
1281 b = allocb(n);1170 b = allocb(n);
1282 /* setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]); */
1283 if(waserror()){1171 if(waserror()){
1284 freeb(b);1172 freeb(b);
1285 nexterror();1173 nexterror();
@@ -1288,9 +1176,7 @@ qwrite(Queue *q, void *vp, int len) · 2 unmodified lines
1288 poperror();1176 poperror();
1289 b->wp += n;1177 b->wp += n;
1290 1178
1291 qbwrite(q, b);1179 sofar += qbwrite(q, b);
1292
1293 sofar += n;
1294 } while(sofar < len && (q->state & Qmsg) == 0);1180 } while(sofar < len && (q->state & Qmsg) == 0);
1295 1181
1296 return len;1182 return len;
@@ -1323,14 +1209,16 @@ qiwrite(Queue *q, void *vp, int len) · 26 unmodified lines
1323 1209
1324 ilock(&q->lk);1210 ilock(&q->lk);
1325 1211
1326 QDEBUG checkb(b, "qiwrite");1212 /* we use an artificially high limit for kernel prints since anything
1327 if(q->bfirst)1213 * over the limit gets dropped
1328 q->blast->next = b;1214 */
1329 else1215 if((q->state & Qclosed) != 0 || q->len/2 >= q->limit){
1330 q->bfirst = b;1216 iunlock(&q->lk);
1331 q->blast = b;1217 freeb(b);
1332 q->len += BALLOC(b);1218 break;
1333 q->dlen += n;1219 }
1220
1221 qaddlist(q, b);
1334 1222
1335 if(q->state & Qstarve){1223 if(q->state & Qstarve){
1336 q->state &= ~Qstarve;1224 q->state &= ~Qstarve;
@@ -1340,7 +1228,7 @@ qiwrite(Queue *q, void *vp, int len) · 3 unmodified lines
1340 iunlock(&q->lk);1228 iunlock(&q->lk);
1341 1229
1342 if(dowakeup){1230 if(dowakeup){
1343 if(q->kick)1231 if(q->kick != nil)
1344 q->kick(q->arg);1232 q->kick(q->arg);
1345 wakeup(&q->rr);1233 wakeup(&q->rr);
1346 }1234 }
@@ -1378,9 +1266,9 @@ qclose(Queue *q) · 31 unmodified lines
1378 ilock(&q->lk);1266 ilock(&q->lk);
1379 q->state |= Qclosed;1267 q->state |= Qclosed;
1380 q->state &= ~(Qflow|Qstarve);1268 q->state &= ~(Qflow|Qstarve);
1381 strcpy(q->err, Ehungup);1269 kstrcpy(q->err, Ehungup, ERRMAX);
1382 bfirst = q->bfirst;1270 bfirst = q->bfirst;
1383 q->bfirst = 0;1271 q->bfirst = nil;
1384 q->len = 0;1272 q->len = 0;
1385 q->dlen = 0;1273 q->dlen = 0;
1386 q->noblock = 0;1274 q->noblock = 0;
@@ -1404,10 +1292,9 @@ qhangup(Queue *q, char *msg) · 17 unmodified lines
1404 /* mark it */1292 /* mark it */
1405 ilock(&q->lk);1293 ilock(&q->lk);
1406 q->state |= Qclosed;1294 q->state |= Qclosed;
1407 if(msg == 0 || *msg == 0)1295 if(msg == nil || *msg == '\0')
1408 strcpy(q->err, Ehungup);1296 msg = Ehungup;
1409 else1297 kstrcpy(q->err, msg, ERRMAX);
1410 strncpy(q->err, msg, ERRMAX-1);
1411 iunlock(&q->lk);1298 iunlock(&q->lk);
1412 1299
1413 /* wake up readers/writers */1300 /* wake up readers/writers */
@@ -1467,7 +1354,7 @@ qwindow(Queue *q) · 53 unmodified lines
1467int1354int
1468qcanread(Queue *q)1355qcanread(Queue *q)
1469{1356{
1470 return q->bfirst!=0;1357 return q->bfirst != nil;
1471}1358}
1472 1359
1473/*1360/*
@@ -1499,7 +1386,7 @@ qflush(Queue *q) · 25 unmodified lines
1499 /* mark it */1386 /* mark it */
1500 ilock(&q->lk);1387 ilock(&q->lk);
1501 bfirst = q->bfirst;1388 bfirst = q->bfirst;
1502 q->bfirst = 0;1389 q->bfirst = nil;
1503 q->len = 0;1390 q->len = 0;
1504 q->dlen = 0;1391 q->dlen = 0;
1505 iunlock(&q->lk);1392 iunlock(&q->lk);
@@ -1507,7 +1394,7 @@ qflush(Queue *q) · 1 unmodified line
1507 /* free queued blocks */1394 /* free queued blocks */
1508 freeblist(bfirst);1395 freeblist(bfirst);
1509 1396
1510 /* wake up readers/writers */1397 /* wake up writers */
1511 wakeup(&q->wr);1398 wakeup(&q->wr);
1512}1399}
1513 1400
@@ -1516,9 +1403,3 @@ qfull(Queue *q) · 2 unmodified lines
1516{1403{
1517 return q->state & Qflow;1404 return q->state & Qflow;
1518}1405}
1519
1520int
1521qstate(Queue *q)
1522{
1523 return q->state;
1524}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t