remove bl2mem(), it is broken. a fault while copying to memory
yields a partially freed block list. it can be simply replaced
by readblist() and freeblist(), which we also use for qcopy()
now.
remove mem2bl(), and handle putting back remainer from a short
read internally (splitblock()) avoiding the releasing and re-
acquiering of the ilock.
always attempt to free blocks outside of the ilock.
have qaddlist() return the number of bytes enqueued, which
avoids walking the block list twice.
remove unneeded waserror() block, loopoput is alled from
loopbackbwrite only so we will always get called with a
*single* block, so the concatblock() is not needed.
the convention for Dev.bwrite() is that it accepts a *single* block,
and not a block chain. so we never have concatblock here.
to keep stuff consistent, we also guarantee thet Medium.bwrite()
will get a *single* block passed as well, as the callers are
few in number.
to avoid copying in padblock() when adding cryptographics macs to a block
in devtls/devssl/esp we reserve 16 extra bytes to the allocation.
remove qio ixsummary() function and add acid function qiostats() to
/sys/lib/acid/kernel
simplify iallocb(), remove iallocsummary() statitics.
given that devmnt will almost always write into a pipe
or a network connection, which supports te bwrite routine,
we can avoid the memory copy that would have been done by
devbwrite(). this also means the i/o buffer for writes
will get freed sooner without having to wait for the 9p
rpc to get a response, saving memory.
theres one case where we have to keep the rpc arround and
that is when we write to a cached file, as we want to update
the cache with the data that was written, but the user buffer
cannot be trusted to stay the same during the rpc.
sugen() calls cgen64() speculatively so that when cgen64() returns
zero, it will fall back and compile 64-bit copy.
the bug was that cgen64() compiled the left hand side and then recursively
called cgen64() again, which didnt handle the memory copy so it returned
zero and sugen() would compile the left hand side again resulting in two
function calls being emited.
some code that reproduced the issue:
#include <u.h>
#include <libc.h>
typedef struct
{
char x[10];
vlong a;
} X;
X a;
X *f(void) { return &a; }
void
main(int argc, char *argv[])
{
f()->a = a.a;
}
producing:
TEXT f+0(SB),0,$0
MOVL $a+0(SB),AX
RET ,
RET ,
TEXT main+0(SB),0,$0
CALL ,f+0(SB)
CALL ,f+0(SB) <- bug
MOVL AX,CX
LEAL a+12(SB),DX
MOVL (DX),AX
MOVL AX,12(CX)
MOVL 4(DX),AX
MOVL AX,16(CX)
RET ,
GLOBL a+0(SB),$20
END ,