We cannot use lock() from screenputs() because lock calls
lockloop(), which would try to print() which on very slow
output (such as qemu) can cause kernel stack overflow.
It got triggered by noam with his rube-goldberg qemu setup:
lock 0xffffffff8058bbe0 loop key 0xdeaddead pc 0xffffffff80111114 held by pc 0xffffffff80111114 proc 339
panic: kenter: -40 stack bytes left, up 0xffffffff80bdfd00 ureg 0xffffffff80bddcd8 at pc 0xffffffff80231597
dumpstack
ktrace /kernel/path 0xffffffff80117679 0xffffffff80bddae0 <<EOF
We might want move this locking logic outside of screenputs()
in the future. It is very similar to what iprint() does.
git/save gets a list of paths (added or removed)
passed to it, and we have to ALWAYS stat the
file in the working directory to determine the
effective file-type.
There was a bug in the "skip children paths"
loop that would compare the next path element
instead of the full path prefix including
the next element.
reproducer:
git/init
touch a
git/add a
git/commit -m 'add a' a
rm a
mkdir a
touch a/b
git/add a/b
git/commit -m 'switch to folder' a a/b
For handling route invalidations, we have to allow
short bursts of traffic. Therefore we keep track
of the number of ra's received in the ra interal
and only start dropping packets when reaching 100
packets.
No idea who committed this in 2022 as its "glenda@9front.local",
but as qid.vers is incremented for each write and we definitely
should not use it as the cache tag.
Also, the initial code was stolen from du.c as the comment says,
and that one does the right thing.
We want to run test before we do the installation
into the system.
So do a temporary install into test/$cputype.git/
direcotry and bind it on /bin/git, that way,
all the scripts run the local source version.
When skipping objects, we need to process the full queue,
because some of the objects in the queue may have already
been painted with keep. This can cost a small amount of time,
but should not need to advance the frontier by more than
one object, so the additional time should be proportional
to the spread of the graph.
the previous bug wasn't a missing clamp, but a
mishandling of the 1-based closed intervals that
we were genrating internally, and some asserts
that assumed open intervals.
Before we would refuse to recurse, but would still give
a response with hints back. Some nefarious clients will interpret the
lack of a Refused response code as us being an open resolver.
When clunking a Fid while the file-system is read
only, dont just free the Amsg, but also drop the
references to dent and mnt.
Make clunkfid() nil fid->rclose, so no reuse
after free is possible.
Make clunkfid() always set the return pointer,
avoid missing prior initialization.
Do not abuse fidtab lock for serializing
clunking.
The clunk should serialize on Fid.Lock
instead, so add a canlock check here.
The lock order is strictly:
Fid.Lock > Conn.fidtab[x].Lock
The AuthRpc was attached to the Fid, but this doesnt
work as it does not handle dupfid() properly.
Instead attach the AuthRpc to the directory entry,
which is refcounted.
The dupfid() function retuns the new Fid* struct with
an extra reference. If we don't use it, we have to
putfid() it.
Use ainc()/adec() consistently and dont mix it with
agetl().
Before, we would just leak all the "Conn"
structures.
fshangup() could cause problems as it just
forcefully closes the file descriptors,
not considering someone else going to
write them afterwards.
Instead, we add a "hangup" flag to Conn,
which readers and writers check before
attempting i/o.
And we only close the file-descriptors
when the last reader/writer drops the
connection. (Make it ref-counted).
For faster teardown, also preserve the
"ctl" file descriptor from listen()
amd use it to kill the connection quickly
when fshangup() is called.
When at the task of decomposing a rune into its
"button" and "rune", also consider the keyboard
map table with the escaped scancodes.
This fixes Shift + left/right combinations in
drawterm.
For each connection, remember if authentication
protocol ran successfully and only then, allow
attach as 'none' user.
This prevents anonymous remote mounts of none.
The 'none' user also shouldnt attach to the dump
file system.
The Tauth for "none" should always fail,
but Tattach should only succeed when
the channel ran a successfull authentication
before.
Also, prevent "none" from attaching "dump".
We want to implement "none" attaches for hjfs,
but only if the 9p-"channel" ran a successfull
authentication before, to prevent anonymous
remote mounts as "none".
Add a flag to the Srv struct for this.
Before this it was possible to Tauth and Tattach with one
user name and then authenticate with factotum using a different
user name. To fix this we now ensure that the uname matches the returned
cuid from AuthInfo.
This security bug is still pending a cute mascot and theme song.
when appending to a directory, the copy of the offset in the dent was
set to the offset that the write was supposed to happen at -- however,
for DMAPPEND files the offset is always at the end of the file. Until
the file was closed, stat would show the wrong directory info.
Implement a hangup ctl command that flushes the
queues, but keeps the filter around.
This can be usefull for low-overhead traffic blocking,
as only the file-descriptor needs to be kept around
and the queues can be flushed.
No user-space process is needed to consume packets
and no buffers are wasted.
example:
aux/dial -e -o hangup 'ipmux!ver=4;src=8.8.8.8' rc -c 'echo 0 > /srv/blocked'
rm /srv/blocked
It seems some protocols are unprepared to
deal with ipoput*() raising an error
(thrown from ifc->m->bwrite()).
so catch it and return -1 (no route) instead.
We were accidentally searching the key for '&', instead of the value.
Inferno received this exact fix at some point, but it never made it back to Plan 9.
the installed version of git has a bug; removing
this file will trigger some spurious removals of
test files, so hold off deleting it until people
have time to install a fixed git
directories need to sort as though they end with a '/',
when running through them for comparison, otherwise we
flag files as added and removed spuriously, leading to
them incorrectly getting deleted when merging commits.
Instead of Proc { Mach *mp; Mach *wired; },
track affinity by an integer representing
the mach number instead.
This simplifies the code as it avoids needing
to compare with MACHP(m->machno).
Wiering a process to a processor is now done
by just assigning affinity and then set a flag
that it should not change.
Call procpriority() when we want to change
priority of a process instead of managing
the fields directly.
The idea is:
When we call sched() with interrupts disabled,
it must not return with them re-enabled.
The code becomes easier to reason about if
we make sched() preserve interrupt status,
which lets us call sched() from an interrupt
handler (with interrupts disabled) without
risking preemption by another interrupt once
sched() returns which can pump-up the stack.
This allows removing Proc.preempted flag as
it is now impossible for interrupts to
preempt each other in preempted().
Extra cleanups:
make interrupted() _Noreturn void
and remove unused Proc.yield flag.
the symptom is that ping is apparently skipping
transmits which recover with the next send,
resulting in exactly send-period spikes in
the ping rtt.
It appears that the core seems to reorder writes
to uncached memory, which can result in the doorbell
being written before the descriptor status bits
are written.
put a coherence() barrier before writing doorbell
fixes it.
thanks sigrid for reporting the issue!
On a multiprocessor, the scheduler can run into
a very unfair distribution of processes to cpus
when there are more long-running processes than cpus.
Say we have a 4 cpu machine and we run 4 long-running
proesses, each cpu will pick up a single process
and each process will get 100% of its fair share.
Everything is good so far.
If we start more long-running processes, all these
processes are going to be picked up by the cpu core
that runs most sporanic / bursty work loads as it
is calling sched() more often.
This results in all the extra long-running prcoesses
to cluster around the same core resulting in very
unfair sharing of load.
The problem is that once a process runs on a cpu,
it stays on that cpu as processor affinity
is never reset.
Process migration only happens when a cpu cannot
find any process to run, given the affinity
constrains, but this can never happen when
the system is under full load and each cpu
always has a low-priority long running
process to run.
How do we fix this?
The idea of this hack is to reset processor
affinity in ready() when its priority changes or,
when it appears to be a long-running process.
That way, we give every cpu a chance to pick
it up and share the load.
This is not a ideal solution of course. Long term,
we should probably have separate runqueues per cpu
and do the balancing explicitely.
In the sched() function, the call to reprioritize()
must be done before we set up, as reprioritize()
calls updatecpu(), which determines if the process
was running or not based on p == up. So move
the call to runproc() itself.
while rehashing the same files over and over will work
just fine, it can be slow with a large number of large
files; this makes 'git/comit .' perform much better in
repos with a large number of large binary blobs.
compress when the log doubles in size, rather than
using a fixed size heuristic; this means that we
don't start compressing frequently as the log gets
big and the file system gets fragmented.
this happens in libframe:
/sys/src/libframe/frutil.c:80: x -= (x-f->r.min.x)%f->maxtab;
but there's no way to control when the user changes the
maxtab value, so it's samterm's responsibility to
sanitize it.
we were copying the owner and group of the parent dir into the fid
on create, but we forgot the mode; fix that, so that we don't check
perms against the wrong dir.
The Italian keyboard layout is ISO, and unlike the ANSI layout,
it has an extra key between Shift and Z, and the key above Enter,
which becomes vertical, is moved to the bottom left of it.
- the key between Shift and Z is mapped to `<`, and shift+`<` is mapped to `>`
- the old `>` (at the bottom left of Enter) is mapped to `ù`
- shift+`ù` is mapped to `§`
- the old shift+`"` is mapped to `°`
- altgr+`'` is mapped to backtick
- altgr+`ì` is mapped to `~`
- altgr+`e` is mapped to `€`
- shiftaltgr+`[` is mapped to `{`
- shiftaltgr+`]` is mapped to `}`
This seems to have been around but not compiled since the third edition.
Remove it and the accompanying SMBus machinery that is only used
for this driver.
When modifying a sparse file, it's possible to get
clobbers and clears to item s that don't exist; in
this case, we try to apply to an empty kvp, and
assert -- we should just not apply.
void
main(void)
{
uchar a[3];
float f = a[2] | a[1] | (a[0]/1.2);
USED(f);
}
the code above used to generate impossible
code in the linker like:
main: doasm: notfound from=34 to=35 (872) ORL X0,X1
main: doasm: notfound from=34 to=35 (872) ORL X0,X1
main: doasm: notfound from=34 to=35 (872) ORL X0,X1
with the change, the compiler correctly rejects it:
incompatible types: "UINT" and "DOUBLE" for op "OR"
i assume the BNUMBER in the type matrix must have been
a oversight.
do not add default route when address is
deprecated (preflt == 0).
delete previous default route on router change.
implement rfc4862 section 5.5.3 processing rules
in regard to remaining valid lifetime.
In addition to removing expired default routes,
ask devip to clean out expired addresses as well.
In the future, devip might do something more
sophisticated than just checking the valid life time
like also considering if the address is still begin
used by active connections.
we shouldn't need to defer reclamation for procs that
don't actually interact with the tree directly, especially
since if they send on a channel they can stall for a while.
This change covers three improvements:
- inline the limbo entry into the objects
being freed, meaning we don't need to
allocate, and thus can't fail to free
an object when we're out of memory
- Preallocate Bfree objects, for the same
reason above.
the build process could be cleaned up a lot more. the default.*.h headers are
basically only used in cross-compilation, but every usable arch has its default
header already, so all the mkfile effectively does is copy it to $objtype.h. it
would perhaps make more sense to just run mk on any new arch and copy to a new
default.$objtype.h and get rid of a lot of this stuff. but then it's not really
worth messing with this further, so leaving it as is.
We were inserting very oversized deletion messages when
removing a file, instead of inserting the right size
message. This also batches the insertions, reducing the
number of upserts.
37e65b331b
Was to adjust the compiler to better match the ISA w.r.t.
subtraction, but was overzelous and rewrote all additions instead of
just those with constants.
5390130426
Intended to restrict compiler generated immediate operations to only
those of which can be encodable by the ISA. However the check for
signed constants was incorrect and resulted in constants that do not
properly encode.
0c6fd079ce
Attempted to classify address literals to save on instruction
encoding, but this is actually not possible. We have to walk the
program first to derive some of the constants (INITDAT depends on
etext) so we can not classify them here. Instead we should just limit
address literals to 32 bits (with sign extension) as a worst case. It
would be possible in the future to do a pass over to program later and
find address literals that only need one instruction instead of two
but this works for now.
The peeophole optimizer was removing MOVL R0, A0
instructions before BSR (A0) because copyu()
decided all registers are being written (because
function calls clobber the registers).
For indirect calls, the register operand must
be correctly reported as being used (and then
clobbered).
Filesystems should ensure that the mount
spec (aname) is valid before handing out
an auth fid.
This avoids pointless authenticaiton
protocols being run just for the
mount later to fail.
This happens with our current /lib/namespace
file for the opportunistic line:
mount /srv/boot /n/other other
i got rid of redundant code, and added routines
to get the xform matrix out of an rframe, so it
can be stored and used separately or as part of
a composition of xforms.
also replaced the big example in the man page for
more concise, useful ones.
with a global dent cache, directory entries from different
trees can be cached. This almost works, but QID state can
change as the files get modified -- ownership, permissions,
and similar can get changed.
A global mount cache means that changes to a qid may leak
across mount boundaries. Don't do that.
when writing back data blocks, we didn't
read the data back from disk, and instead
just enqueued the block pointer; This means
that we don't have the Blk struct to set
the freed flag on, so we would commit every
IO operation to a data block.
This change opportunistically reaches into
the cache and flags the data block as dead,
so we can skip writeback.
we only need to enforce ordering or syncedness to disk when
writing out the blocks during sync, we don't need to prevent
mutation on the tree once the arenas and superblock are
serialized.
When churning through data blocks and writing out of order, we would
copy blocks and release them often, leading to gaps at the back of
the file. Retrying an allocation could also lead to allocating a block
in the same arena as the metadata.
This would leave gaps in the allocated files, which would cause seeks
when accessing the data later.
This set of changes allocates blocks that are expected to be accessed
sequentially from the start of the arena, and blocks that are expected
to be accessed out of order at the end of the arena.
For full data blocks (ie, where the write is at the end of the block),
we assume that the accesses will be sequential. For partial data blocks,
when the write offset is not at the end of the data block, we assume
that future appends are inbound, and we allocate the block in the non
sequential part of the arena. As a result, when we eventuall fill the
block, we will allocate the sequential block.
This doesn't help us too much if we have writes to files interleaved,
or we overwrite the same section of a file over and over, but it's
better than nothing.
len is ulong, hence &l[-len] makes no sense.
&l[-(uintptr)len] and l - len are correct.
igfx uses a fixed segment to extend its memory when stolen memory is
insufficient for the requested mode. this caused segment allocation
to always fail since no page in the loop would fall within the range.
modesetting then fails but the bottom of the screen stays garbled.
This is a kernel for the NXP LX2160A, specifically the SolidRun
Honeycomb board which is available for sale on the SolidRun
website.
It currently boots on U-Boot. UEFI support is planned. Build or
download the U-Boot firmware from the SolidRun site and then write
it to the on-board SD card. Then, plug in a USB with the honeycomb
image and proceed to install as normal. Only NVMe or USB storage
is supported (SATA is planned).
This kernel supports PCIe and USB. On-board ethernet and SFP are
not supported (yet). It uses 2GB of memory by default, but that
can be increased using *maxmem depending on how much RAM you have
in the system. As well, SMP is currently disabled until an
uncommon deadlock issue is fixed (could be a hardware issue, unknown
at this point).
we copied and pasted the structure of this from
cwfs, but they lay out the bits differently. We
fixed this for the other cases, but forgot this
one, which lead to exec being permitted when it
shouldn't have been.
in out of memory situations, clunkfid could run
out of memory and error; preallocating moves the
error to fscreate/fsopen, which are prepared to
handle them.
vertical scrolling now works in a line-wise manner,
just like in rio(1), sam(1) and friends. horizontal
scrolling showed problems with some line widths
where they got cut before showing the last
characters.
finally, pressing LMB or RMB and swiping while going
through any of the blocks caused a storm of plumbs
and visibility toggling (when over the expander line).
this doesn't happen anymore.
Currently we use millisecond ticks for time spent in each function.
This is not good enough for modern machines where fast functions could
be completed in a handful of nanoseconds. Instead let us just use the
raw ticks and store the cyclecfreq in the output prof data. This
requires that we enlargen the time section in the data to 8 bytes,
which broke the assumptions for struct allignment and required a
slight refactor of the code used to read it in prof(1). Since this is
a breaking change, we've devised a small format to communicate the
version for future revision of this format and this patch includes a
modification to file(1) for recognizing this format. Additionally
some minor improvements were made across the board.