in qbread, why does qbread only take full blocks for coalescing queues? (these are only used for the console, and for tcp) for example:
if(q->state & Qcoalesce){ /* when coalescing, 0 length blocks just go away */ b = q->bfirst; if(BLEN(b) <= 0){ freeb(qremove(q)); goto again; } /* grab the first block plus as many * following blocks as will completely * fit in the read. */ n = 0; l = &first; m = BLEN(b); for(;;) { *l = qremove(q); l = &b->next; n += m; b = q->bfirst; if(b == nil) break; m = BLEN(b); if(n+m > len) break; } } /* code to put extra bytes back on the queue below */ in the typical use with tcp, we're going to have a protocol like 9p or tls running on top of tcp, and if it does a read of n bytes, it really does need n bytes. so splitting reads rather than blocks would seem less efficient because copying a partial block <= mss should be much faster than a syscall. (nsec() with the fd open takes ~7-900ns, but a 1460-byte copy takes ~130ns @ a modest 10gb/s, much less if cache pressure doesn't dominate.) i noticed this because even with the tcp rx queue full (slow receiver) i was seeing twice as many reads as i would have expected. the following code works fine. if(q->state & Qcoalesce){ /* when coalescing, 0 length blocks just go away */ b = q->bfirst; if(BLEN(b) <= 0){ freeb(qremove(q)); goto again; } /* * grab the first block and as many following * blocks as will partially fit in the read */ n = 0; l = &first; m = BLEN(b); for(;;) { *l = qremove(q); l = &b->next; n += BLEN(b); if(n >= len || (b = q->bfirst) == nil) break; } } /* code to put extra bytes back on the queue below */ is there something or some consideration here that i'm missing? - erik