when cookie is domain=example.com, then we implicitely add
dot to the domain name, which made us reject the cookie as the
request domain "example.com" != ".example.com". fix by making
isdomainmatch() skip the implicit dot in pattern before string
comparsion.
when there where multiple syscalls returning out of order,
it would print blank lines between the exits. avoid this
by remembering if the last char written was a newline and
conditionally insert newline on out of order return.
sometimes, ratrace would return before all messages have
been printed. make the writer process the parent so ratrace
wont exit until all readers are finished avoiding the
problem.
we already export mntauth() and mntversion(), so why not stop
being sneaky and just export mntattach() so bindmount() and
devshr can just call it directly with proper arguments being
checked.
we can also avoid handling #M attach specially in namec()
by having the devmnt's attach function do error(Enoattach).
to avoid double caching, attachimage() and setswapchan() clear
the CCACHE flag on the channel but this keeps the read ahread
state of the cache arround (until the chan gets closed), so also
call cclunk() to detach the mcp and free the read ahead state.
avoid the call to cread() when CCACHE flag is clear.
use the actual iounit returned from Ropen/Rcreate to chunk reads and writes
instead of c->mux->msize-IOHDRSZ.
dont preallocate the rpc buffers to msize, most 9p requests are rather small
(except Twrite of course). so we allocate the buffer on demand in mountio()
with some rounding to avoid frequent reallocations.
avoid malloc()/free() while holding mntalloc lock.
this changes devmnt adding mntrahread() function and some helpers
for it to do pipelined sequential read ahead for the mount cache.
basically, cread() calls mntrahread() with Mntrah structure and it
figures out if we where reading sequentially and if thats the case
issues reads of c->iounit size in advance.
the read ahead state (Mntrah) is kept in the mount cache so we can
handle (read ahead) cache invalidation in the presence of writes.
Tflush handling was wrong, we cannot respond to the old
request if we have not actually removed the req from the
in progress block queue.
when reads are issued concurrently, we have to set b->len
before the block is inserted into the inprogress list.
otherwise findblock() is unable to find it and no requests
can be queued on the block. this caused the same offset
to be downloaded multiple times.
set the errstr in getrange() so in case of an error, we dont
get some random previous error string.
as the Fgrp can be shared with other processes, we have to
recheck the fd index after locking the Fgrp in fdclose()
to make sure not to read beyond the bounds of the fd array.
using the user buffer has a race where the user can modify
the buffer from another process before it is copied into the cache.
this allows poisoning the cache for every file where the user
has read access.
instead, we update the cache from kernel memory.
*after* writing, the directory tree gets alphabetically sorted for
path table. this causes data to not be in the same order as it was
written causing seeks when taring up the filesystem.
so instead write the files in alphabetical order as well to better
match the directory sorting.
data on the disk is layed out sequentially and directory information
is at the end of the disk. we want to keep data and metadata separated
so that reading large sequential files will not evict the directory
information from the cache causing long seeks.
for that, we tag the clusters (an 8th for metadata, and the rest
for data) and getbuf() will only evict clusters of the same tag.
doing tests taring up 9front.iso shows the following:
lowering the cluster size back to 128k avoids over half the
reads. 837888 sectors read for 512k vs. 347712 sectors with
128k cluster size.
foo.c includes bar/bar.h, which includes "baz.h"; it wants bar/baz.h
meanwhile, it also includes meh/quux.h, which includes "baz.h"; it wants meh/baz.h
Wnode gets two new counters: txcount and txerror
and actrate pointer that will be between minrate
and maxrate.
driver should use actrate instead of maxrate for
transmission when it can provide error feedback.
when a driver detects a transmission failed, it calls
wifitxfail() with the original packet. wifitxfail() then
reduces wn->actrate.
every 256th packet, we optimistically increase wn->actrate
before transmitting.
- reject files smaller or equal to two bytes, they are bogus
- fix out of bounds access in shargs() when n <= 2
- only copy the bytes read into line buffer
- use nil for pointers instead of 0
imagereclaim(), pagereclaim():
- move imagereclaim() and pagereclaim() declarations to portfns.h
- consistently use ulong type for page counts
- name number of pages to free "pages" instead of "min"
- check for pages == 0 on entry
freepages():
- move pagechaindone() call to wakeup newpage() consumers inside
palloc critical section.
putimage():
- use long type for refcount
- reduce delay for channel hop to 200ms
- use 1000ms timeout for auth response (dont hop channels while we wait)
- bunny hop sequence is mathematically prooven
addresses va's of 0 and -BY2PG cause trouble with some memmove()/memset()
implementations and possibly other code because of the nil pointer
and end pointers wrapping to zero.
unlock()/iunlock():
we need to place the coherence() *before* "l->key = 0", so that any
stores that where done while holding the lock become observable
*before* other processors see the lock released.
cas()/tas():
place memory barrier before successfull return to prevent reordering.
making sure to close the dot in every kproc appears repetitive,
so instead stop inheriting the dot in kproc() as this is usually
never what you wanted in the first place.
give kernel processes and local disk file servers (procs
having noswap flag set) a clear advantage for page allocation
under starved condition by giving them ther own wait queue so
they get readied as soon as pages become available.
check parent directory permission *after* we determined
that the new name does not exist in the parent, so that
when the new name is the same as old name then no write
permission is required in the parent directory.
instead of copying the whole packet, just save the
udp header and restore it aftwards. dont call redistrib()
when there are no forwards (this should be almost always
the case).
the code used P_Random()-P_Random() in some places which has
undefined evaluation order resulting in the wrong pseudo random
numbers being returned causing demo playback to desync.
this change adds P_Random2() function which returns the right
delta-random number and uses it in place of P_Random()-P_Random()
expression.
yoann padioleaus report on 9fans:
> I think I’ve found a bug in the network stack.
> in 9/ip/ip.h there is
> struct Ipht
> {
> Lock;
> Iphash *tab[Nipht];
> };
>
> where Night is 521,
>
> but then in 9/ip/ipaux.c there is
>
> ulong
> iphash(uchar *sa, ushort sp, uchar *da, ushort dp)
> {
> return ((sa[IPaddrlen-1]<<24) ^ (sp << 16) ^ (da[IPaddrlen-1]<<8) ^ dp ) % Nhash;
> }
>
> where Nhash is just 64,
prevent double sleep():
callers to sleep() need to be serialized as there can only
be one process sleeping at a time. plrlock and plwlock do
this.
wait for dma to complete in plwrite():
we have to wait for the dma to complete before touching
plbuf again.
maintain COPEN flag in archopen()/archclose():
when open fails because it was in use, clear the COPEN
flag, so archclose() wont screw stuff up.
try the handle buffer in reverse order looking for plan9.ini
to find plan9 partition (9fat). when that fails, we'll default
to the first handle which should be the esp.
there where two problems with blank (-b flag):
we did not update the backup header when there was already a valid
backup header in place. we always want to initialize a new backup header
in blank mode!
we now also check the backup header matches the primary (or the other
way arround depending on which header could be read), reporting any
mismatches and restoring the backup from the data of the primary.
the protective mbr needs to start at sector 1 not 0 (apparently, this
matters for ovmf).
efi systems may use traditional dos partition table
with an esp (efi system partition). otherwise, honor
the protective mbr partition (0xEE) and exit when we
encounter it.
- make sure disk file is an actual file and not a directory, log or empty file
- sanity check: file has to be at least one sector to be a disk
- simplify error handling using freedisk()
- make UU() shorter by using long long constant to encode node field
- store Flag as a mask, not as a shift count
- put the attributes before the name in cmdsum() as it is fixed length
often, documents specify charsets but are really utf-8 encoded.
we now try to decode as utf-8 and only if that fails assume
the charset specified in the document.
make digest_certinfo() return the digest length, otherwise
return -1 as an error and handle it in the callers.
pass expected digest length to verify_signature() and
check digest length from certificate! make sure we wont
run off the buffer.
fix newlines in error prints of X509dump().
this implements SHA2 (224, 256, 384, 512) signature algorithms and
uses sha256WithRSAEncryption for X509req() and X509gen() instead
of oid_md5WithRSAEncryption.
the compiler used to skip zero initialization when initializer
list was given not covering unspecified elements. now we zero
all non explicitely initialized elements. for example:
typedef struct F F;
struct F
{
int a;
int b;
int c;
};
void
main(void)
{
char a[16] = { 1, 2, 3 }; /* a[3..15] initialized to zero */
F f = { .b = 1 }; /* f.a, f.c initialized to zero */
}
the emited code that initializes local variables did not handle
unaligned data causing stack corruption, affecting code like:
void main(void)
{
char a[9] = {0};
}
this change will emit code that does byte stores for the unaligned
bytes and also handles small objects (<= 16 bytes) without branches.