2 years agoAdd a macro to count the number of args to a macro
Barret Rhoden [Fri, 20 Jul 2018 00:06:43 +0000 (20:06 -0400)]
Add a macro to count the number of args to a macro

assert(MACRO_NR_ARGS() == 0);
#define foo(...) printk("Got %d\n", MACRO_NR_ARGS(__VA_ARGS__))

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agorcu: Panic if a call_rcu() CB blocks
Barret Rhoden [Thu, 19 Jul 2018 21:14:54 +0000 (17:14 -0400)]
rcu: Panic if a call_rcu() CB blocks

RCU callbacks are not allowed to block.  Here's what Linux has to say:

... the callback function must be written to be called from softirq
context.  In particular, it cannot block.

Same goes for us.  If a CB blocks, then all further CBs will be blocked
too, and the code that will wake up the first CB could also be blocked on a
later CB.

Note the distinction between RCU callbacks and RCU threads.  The threads
are critical parts of implementing RCU; they are never allowed to block on
RCU primitives.  Yes, any RCU callback will be run by an RCU thread, but
the problem is slightly different.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agorendez: Make sure we can block before sleeping
Barret Rhoden [Thu, 19 Jul 2018 21:02:02 +0000 (17:02 -0400)]
rendez: Make sure we can block before sleeping

A lot of rendezvouses don't block, but any of them could.  By checking in
advance, instead of deep in sem_down(), we'll catch those cases where we
could have blocked but rarely do.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoSerialize console prints with the print_lock
Barret Rhoden [Thu, 19 Jul 2018 20:06:23 +0000 (16:06 -0400)]
Serialize console prints with the print_lock

When userspace writes to the console, it bypasses printk and could
interleave with the rest of the kernel prints.  Now it won't, and we can
remove yet another lock.

Note that we still will have single printk lines intermixed with userspace
characters, since userspace could be writing one byte at a time, without a
\n.  However, these writes won't interfere with multi-line printks within
the kernel.  The first line could have junk in front of it, and if that
becomes a problem, we can start putting printk("\n") in front of larger
prints (such as trapframes), like we do for panic and warnings.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoSerialize multiline printks
Barret Rhoden [Thu, 19 Jul 2018 19:59:48 +0000 (15:59 -0400)]
Serialize multiline printks

A lot of times the kernel will do a series of printks as part of a larger
call.  Backtraces, tabs for formatting, ASCII giraffes, you name it.

To prevent these prints from interleaving with other (atomic) printks, we
can use the print_lock().  There were at least two cases where the
print_lock() replaced an already-existing spinlock that served a similar

Additionally, there were a few places that just lacked a \n, which would be
hard to read.  Those usually needed to be warn() anyway.  And of course
there was a printk("YOU SHOULD PANIC (stuff)"), which is now a panic.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agox86: Don't turn off lock tracing in the console
Barret Rhoden [Thu, 19 Jul 2018 19:03:13 +0000 (15:03 -0400)]
x86: Don't turn off lock tracing in the console

It is unnecessary.  All callers already have the tracing disabled.  And if
we do want to turn it off further, the way to do that is to turn off the
pcpui variable.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoSupport atomic printks
Barret Rhoden [Thu, 19 Jul 2018 18:54:09 +0000 (14:54 -0400)]
Support atomic printks

printk() was atomic at the granularity of a line - most of the time.  It
wasn't for kernel faults, which leads to inscrutable bug reports.  At the
time, I avoided the lock to avoid deadlocking.  Instead, we can use a
recursive lock, which I'm not normally a fan of.

Additionally, other callers can use print_lock() to atomically print
multiple lines.  The classic example is panic() and warn().  panic() has a
few issues of its own, so we have print_unlock_force().

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoFix tracking of lock call sites
Barret Rhoden [Thu, 19 Jul 2018 18:49:00 +0000 (14:49 -0400)]
Fix tracking of lock call sites

If we don't inline post_lock(), the call site for a lock is just
spin_lock(), which is not what we want.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoAdd panic_hwtf() for kernel faults
Barret Rhoden [Wed, 18 Jul 2018 02:12:00 +0000 (22:12 -0400)]
Add panic_hwtf() for kernel faults

When the kernel faults, we would print the HWTF and maybe a backtrace,
and then panic.  These prints were not serialized like other panic
prints.  The new panic() would also print a backtrace of whoever called
panic, which isn't useful for faults (the stack frame was just the

panic_hwtf() will take a trapframe and print + backtrace that hw_tf
instead of backtracing the calling context.  This output will be
serialized, so the debug output from concurrent faults across multiple
cores won't be interleaved.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Fix concurrent TF removal bug
Barret Rhoden [Tue, 17 Jul 2018 17:03:06 +0000 (13:03 -0400)]
9ns: Fix concurrent TF removal bug

If you had two threads removing a child from a parent at the same time,
get_locked_and_kreffed_parent() would return a TF that was not the
parent of the child.  I think the check for child->parent was from before I
deferred clearning ->parent until __tf_free().

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agogtfs: Remove the EOF optimization
Barret Rhoden [Mon, 16 Jul 2018 23:47:34 +0000 (19:47 -0400)]
gtfs: Remove the EOF optimization

Turns out this is wrong for directories (and often device files).  The
ufs server reports a directory size of 4096, which is what Linux tells
it.  We'd read 4096 bytes worth of records, and then stop.

The 9p man page says:

 The length records the number of bytes in the file. Directories
 and most files representing devices have a conventional length
 of 0.

Instead of mucking around, we'll just issue the RPC for whatever offset
we're asked for.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agox86: Use a KERNBASE address for the bootstack
Barret Rhoden [Sat, 14 Jul 2018 03:02:28 +0000 (23:02 -0400)]
x86: Use a KERNBASE address for the bootstack

Since commit 20694dda54b5 ("x86: Put the boot PMLs and stacks in BSS"),
we have been unable to backtrace from kernel_init(), up until we are on
a stack from the kernel allocator.

The reason is that the kernel backtracer checks for framepointers above
KERNBASE.  When we used an address from within the boot section, those
addresses are at the bottom of the address space.  For instance, our
stack page was around 0x50f000.

We can still use that page, which isn't present in the binary - we just
need to use the KERNBASE mapping for it.

Note we can't use the normal BSS.  That gets zeroed out manually in
kernel_init(), which is after we start using the stack.

Also note that we don't need to set the stacktop for the IDT right away.
That code was from before we had the kernel stack allocator.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoAttempt to fix recursive panics
Barret Rhoden [Sat, 14 Jul 2018 02:05:49 +0000 (22:05 -0400)]
Attempt to fix recursive panics

Some panics can still lock up and spew a lot of text.  This helps a

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoSerialize printing during panic()
Barret Rhoden [Fri, 13 Jul 2018 21:43:50 +0000 (17:43 -0400)]
Serialize printing during panic()

When multiple cores panicked concurrently, their output would be garbled.
They also didn't have very useful info, and I almost always wanted a
backtrace.  Now we should get each core printing on its own, including a

The monitor() call needs to happen outside the lock, so we'll wait a little
till the other cores are likely done.  They just need to wait long enough
for another core to grab the lock and set 'panic_printing'.  500ms seems to
be enough, even on Qemu.

This is only lightly tested - crazy panics under insane conditions might
break a bit more than before.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoDon't use kmalloc in get_fn_name()
Barret Rhoden [Fri, 13 Jul 2018 21:37:33 +0000 (17:37 -0400)]
Don't use kmalloc in get_fn_name()

Back in commit 290962da6e27 ("Reflects symbol table into the kernel"), we
changed from using the old debuginfo to a autogenerated table of strings.
Those new strings are null-terminated.  The old debuginfo wasn't.
get_fn_name() needed to add the trailing \0, but we don't need to anymore.

The end result is that debug code that looks up a function name for a given
symbol, such as backtrace(), won't need to kmalloc.  This will help when we
are trying to backtrace failures in the allocator.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoDon't use the electric fence in multithreaded code
Barret Rhoden [Tue, 10 Jul 2018 19:51:38 +0000 (15:51 -0400)]
Don't use the electric fence in multithreaded code

The efence doesn't work with uthreads.  Efence intercepts malloc() et al.
When a uthread exits, its TLS is cleaned up.  Ultimately, this calls into
glibc, which calls free() on the TLS region in _dl_deallocate_tls(). That
region was allocated with __libc_memalign() in _dl_allocate_tls_storage().
efence can intercept the free(), but not the _libc function.

Pending other changes, we shouldn't use uthreads and the efence.  One
option would be to briefly disable the efence.  Another would be to not
actually free the TLS if the efence is linked in.  Neither are good

For now, we'd like to not crash our utests.  The only code using it was
utests - some of which would break in a somewhat racy manner.

You can still link in the efence on demand.  If you do, I'd hack up your
2LS to have threads sleep forever when they finish (pthread.c, look for the

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agopthread: Allow new threads in forked children
Barret Rhoden [Mon, 9 Jul 2018 20:20:23 +0000 (16:20 -0400)]
pthread: Allow new threads in forked children

Previously, after forking, a child could not use threads at all.  Any
threads other than thread0 were ignored.  Now, older threads will still be
ignored, but new threads will run.

fork() must still be called from thread0 and while the process is an SCP.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agogtfs: Support intra-directory rename
Barret Rhoden [Wed, 27 Jun 2018 18:48:31 +0000 (14:48 -0400)]
gtfs: Support intra-directory rename

9p can handle it.  This actually has a couple benefits apart from passing a
Go test:
- No needless copies for large files
- Atomic rename for intra-directory files, which is a common pattern for
  updating a file atomically.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agogtfs: Use a kernel message to destroy the gtfs
Barret Rhoden [Wed, 27 Jun 2018 17:55:12 +0000 (13:55 -0400)]
gtfs: Use a kernel message to destroy the gtfs

You can't use blocking RCU primitives, such as rcu_barrier(), from within
an RCU callback.  Release methods, such as gtfs_release(), are often called
from a lot of contexts - anywhere you might decref - including RCU

As they say, all problems in CS can be solved with a level of indirection.
Using a kernel message decouples the work we want to do from the current
thread context, which is unable to use RCU barrier et. al.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agogtfs: Fix has_children()
Barret Rhoden [Tue, 26 Jun 2018 22:36:56 +0000 (18:36 -0400)]
gtfs: Fix has_children()

Two problems: the assert was clearly backwards, and we were using the
locked gtfs_read().  As mentioned in tree_file.h, all ops that take a
parent TF have the file qlocked.  gtfs uses that qlock for its backend
operations.  When we called gtfs_read(), we would deadlock.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoparlib: Fix context detection in __prep_sighandler()
Barret Rhoden [Tue, 19 Jun 2018 17:51:07 +0000 (13:51 -0400)]
parlib: Fix context detection in __prep_sighandler()

In commit f3f00eeae350 ("parlib: Fix aggressively-saved FP state for
signals"), we were checking the wrong context.  If the uthread was not
saved, its context was in VCPD.  That's why we have the ctx variable.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoAllow fchdir() from non-O_PATH fds
Barret Rhoden [Tue, 19 Jun 2018 17:28:04 +0000 (13:28 -0400)]
Allow fchdir() from non-O_PATH fds

If you chdir to an open FD, later when you did something like create a
file from DOT, we'd panic.  The FD in current->dot was opened and not
O_PATH, which you can't walk from (see devclone()).

The regular sys_chdir does a namec(Atodir), which does not call the
device's open, so that chan is a kernel-internal, non-open chan (to use
the parlance of devclone()).

The current fix works for most cases.  If you do something like
dfd = open(some_dir, O_READ); unlink(some_dir); fchdir(dfd);, the lookup
will fail.  Using O_PATH instead of O_READ should work.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoparlib: Use a relative timer for abort_sysc
Barret Rhoden [Fri, 15 Jun 2018 21:30:34 +0000 (17:30 -0400)]
parlib: Use a relative timer for abort_sysc

The issue is that the timer goes off before the syscall could block.  If
the timer was very far in the past, such as due to a go test that put the
alarm 30 seconds in the past, we would do N loops, each of which fires
instantly, until we finally set an alarm for the future.

Using a relative timer fixes that.  Also, one second is a bit much - enough
that an interactive user might notice and wonder if something is broken.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoSet tchain earliest/latest on any removal
Barret Rhoden [Fri, 15 Jun 2018 21:27:05 +0000 (17:27 -0400)]
Set tchain earliest/latest on any removal

Alarm handlers can put themselves back on the tchain during their handler.
The logic for that involves the earliest/latest times.  Those times should
change since the old awaiter (which is running) was yanked off.

I didn't have any actual problems with this, but it popped up as a
potential issue.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoparlib: Fix potential alarm corruption
Barret Rhoden [Fri, 15 Jun 2018 21:21:33 +0000 (17:21 -0400)]
parlib: Fix potential alarm corruption

The user-level alarm service is based off an older version of
kern/src/alarm.c.  That had commit f46e3e7984fb ("Fixes tchain
corruption"), but the fix never propagated to the user-level side.

There are a bunch of other differences between the kernel and user version,
which could be addressed.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agorcu: Fix quiescent state reporting deadlock
Barret Rhoden [Fri, 15 Jun 2018 20:33:54 +0000 (16:33 -0400)]
rcu: Fix quiescent state reporting deadlock

When a core is the last to report in, it will kick the gp_ktask's rendez
variable.  That will wake the gp_ktask, and waking a ktask is done with a
kernel message.  Currently, those messages are sent to the calling core.

When we reported *after* checking the RKMs, we'd halt.  Then the GP ktask
wouldn't run.  We wouldn't see it sleeping (e.g. with "db sem"), since it
was in the process of being awake.  We wouldn't see it running either,
since it was stuck as a KMSG.  With trace_printks, we could see it went
into the rendez (rcu.c L435), but never came out.

By kicking all the cores with "trace coretf -1", we woke the system up.
I thought to try that since it would trigger a QS, but in the trace also
spat out a message for the RKM that hadn't run yet.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoparlib: Always align the sigdata struct
Barret Rhoden [Fri, 15 Jun 2018 19:07:33 +0000 (15:07 -0400)]
parlib: Always align the sigdata struct

The two cases were very similar, but only one had the alignment check.
Odds are, that was an oversight.  When we handled the FP state separately
based on the UTHREAD_SAVED cases, this wasn't as clear.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoparlib: Fix aggressively-saved FP state for signals
Barret Rhoden [Fri, 15 Jun 2018 18:59:07 +0000 (14:59 -0400)]
parlib: Fix aggressively-saved FP state for signals

In commit 5562ccb05015 ("parlib: Aggressively save and restore the FPU"),
we did not fix up the signal handling code.

The old __prep_sighandler() code was assuming that if a uthread didn't have
its GP register state saved, then it had FP state in the hardware and the
FPSAVED was not set.  This would be for e.g. HW contexts that got

With the change to aggressively save the FPU, that was not true: it was
saved and the bit was set.  Your GP state could be not saved, but your FP
state would be.

That would lead to other sorts of confusion, since the FPSAVED flag was on
for the signal handler.  That was causing an assertion when we tried to
run_current_uthread, which was a SW ctx (the signal handler).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agox86: Handle when the PLATFORM_INFO TSC freq = 0
Barret Rhoden [Wed, 13 Jun 2018 23:55:25 +0000 (19:55 -0400)]
x86: Handle when the PLATFORM_INFO TSC freq = 0

I noticed this with QEMU 2.11.1 on an x86_64 Gentoo skylake machine.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoFix binutils-2.30 port (XCC)
Barret Rhoden [Wed, 13 Jun 2018 23:41:14 +0000 (19:41 -0400)]
Fix binutils-2.30 port (XCC)

Commit d3d87f64cda1 ("Updating binutils to 2.30") removed the RISCV
patch, but didn't remove it from the Makefile recipe.

Additionally, the .gitignore was still tracking 2.24 instead of 2.30.

For those keeping score, this is what happens when you hit the 'merge'
button on Github instead of fetching the branch and looking at it
locally.  You'd only notice the .gitignore by running 'git status' after
having built the new toolchain.

Rebuild your toolchain, and remove your old binutils-2.24 files, which
you can see with a 'git status.'  Feel free to keep them if you plan to
git bisect anytime soon.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoFix exec's proc state / owning_proc invariant
Barret Rhoden [Wed, 13 Jun 2018 22:16:20 +0000 (18:16 -0400)]
Fix exec's proc state / owning_proc invariant

We had a binary that failed the load_elf() part of the mess.  That was
after owning_proc was cleared.  proc_destroy() sent the __death message,
since we were still RUNNING_S.  That was OK some of the time, but if we had
another process running, such as the parent of the
process-who-failed-to-exec, then *that* process would get hit with the
__death (which now panics).

To avoid that, we now enforce a previously unstated (and possibly
incorrect) invariant: RUNNING_S processes are the owning_proc.  I think
this is true.  If not, it warrants a closer look.

To do so, we change the process's state very early on, ideally before
blocking, such that we can save the context (in case of recoverable
errors).  We'll change the state too (to WAITING), in accordance with the
aforementioned invariant.  Since the owning_proc and the state are synced
up, we won't get any weird __death messages meant for other processes.

Since we're moving things around, including some checks that were
previously pre-goto-error-style, I attempted to clarify the error handling.
This includes setting the error codes for the load_elf, so we can get a
decent error.  (We had been getting ENOENT, which was generated inside 9ns
during the successful path walk).

It's still a nightmare, and I'll be happy the day we can get rid of exec.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoMake sure __death messages hit the correct proc
Barret Rhoden [Wed, 13 Jun 2018 22:12:49 +0000 (18:12 -0400)]
Make sure __death messages hit the correct proc

Similar to __preempt, we now track the process that the message is meant
for.  AFAIK, we should not be sending __death messages to a process that
isn't the owning_proc, though it might not be the current_proc.

We had a bug where owning_proc was cleared and the __death was getting sent
to the wrong process.  Hilarity ensued.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoUpdating binutils to 2.30
Brian Wheatman [Mon, 11 Jun 2018 20:23:17 +0000 (16:23 -0400)]
Updating binutils to 2.30

Updating binutils from 2.24 to 2.30
Includes patch and updates to Makefile

Change-Id: Ic7a7ac38069b4079175e3def04be179fb5ca0d18
Signed-off-by: Brian Wheatman <wheatman@google.com>
2 years agoFixed NO_CTORS_DTORS_SECTIONS (xcc)
Brian Wheatman [Mon, 11 Jun 2018 20:20:33 +0000 (16:20 -0400)]

Fixed issue with __libc_global_ctors being linked
Found when updating binutils

Change-Id: I54df22c1e55428dd2c324da19e19cf495a780d0c
Signed-off-by: Brian Wheatman <wheatman@google.com>
2 years agoMove linker PROVIDE statements inside sections
Barret Rhoden [Mon, 11 Jun 2018 20:01:14 +0000 (16:01 -0400)]
Move linker PROVIDE statements inside sections

Newer versions of binutils seem to require having the PROVIDE keyword
inside a specific section, instead of just floating between sections.

Specifically, on x86, binutils-2.30 was assigning all symbols outside a
section the value of the kernel load address (0xffffffffc2000000 or
whatever).  This included the linkerfuncs, the devtab, end, and etext.  The
bss symbols were OK.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoradix: Use call_rcu() to free r_nodes
Barret Rhoden [Fri, 8 Jun 2018 16:42:11 +0000 (12:42 -0400)]
radix: Use call_rcu() to free r_nodes

The radix code can be called from call_rcu().  That means it can't use
blocking RCU primitives, such as synchronize_rcu().  Alternatively, we
could have a racy destruction primitive, but that didn't seem worth the

For those curious, you could trigger this bug by deleting a moderately
sized file that was in the page cache.  e.g.

$ get_html; rm bin/get_html

You'll get a panic / BT similar to this:

 #02 [<0xffffffffc2058932>] in synchronize_rcu
 #03 [<0xffffffffc205741f>] in __radix_remove_slot
 #04 [<0xffffffffc2057566>] in rnode_for_each
 #05 [<0xffffffffc20574e8>] in rnode_for_each
 #06 [<0xffffffffc20578db>] in radix_for_each_slot
 #07 [<0xffffffffc204f9af>] in pm_destroy
 #08 [<0xffffffffc203fdcb>] in cleanup_fs_file
 #09 [<0xffffffffc204a418>] in __tf_free
 #10 [<0xffffffffc204a4a0>] in __tf_free_rcu
 #11 [<0xffffffffc2057f92>] in rcu_exec_cb
 #12 [<0xffffffffc2058232>] in rcu_mgmt_ktask

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agorcu: Do not let RCU callbacks block on RCU
Barret Rhoden [Fri, 8 Jun 2018 16:11:12 +0000 (12:11 -0400)]
rcu: Do not let RCU callbacks block on RCU

The callbacks are run from a ktask.  If the callbacks attempt to block on
RCU with e.g. rcu_barrier() or synchronize_rcu(), we'll deadlock.  The
ktask blocks on RCU callbacks, but the ktask is the only thing that will
run the callbacks.

As far as I can tell, this is also illegal on Linux.  For instance, this
will throw a bunch of errors at runtime on Linux:

static void __cb(struct rcu_head *h)
    printk(KERN_INFO "about to sync\n");
    // works only if we comment this out, dies otherwise

static void foo(void)
    struct rcu_head head[1];

    call_rcu(head, __cb);

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoAdd the 'current_kthread' helper
Barret Rhoden [Fri, 8 Jun 2018 16:01:33 +0000 (12:01 -0400)]
Add the 'current_kthread' helper

Similar to current and current_ctx.  Those remain unchanged functionally,
but they now use the pcpui accessors.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoHandle threading after a fork() (XCC)
Barret Rhoden [Thu, 7 Jun 2018 18:59:28 +0000 (14:59 -0400)]
Handle threading after a fork() (XCC)

Threading and fork() do not go together well, especially user-level
threads.  The kernel won't let you fork() an MCP.  However, you can have a
threaded SCP - dropbear is one such example.  It uses the pthread 2LS, but
just happens to be on one core.

Dropbear uses threads internally in its implementation of tty.c.  There are
two threads: one for pushing inbound traffic and another for outbound
traffic between the network and the child's pipes.

Recall another pain in the ass with fork: duplicated state between the
child and parent.  We have a bunch of things implemented in userspace, such
as select() and an alarm service.  Those are FDs that get carried over to
the child.  We have the "fork callbacks" to clean that stuff up.

Now, what happens when you fork a threaded process?  Its forked thread
returns in the child, and the child also has all of the memory structures
for the other threads.  If you exec() immediately, that all gets blown
away.  However, if that thread happens to block on a syscall, then the 2LS
takes over and it can run those other threads.

In dropbear's case, it returns from the fork, it closes the tty threads'
FDs (in one of its functions, not in a fork-cb), does a few other things,
etc.  One of those things was chdir(), which happens to block.  The reason
for that is chdir() calls synchronize_rcu(), which can block until the GP
ktask runs, at least under the current settings.

Once the thread (thread0) blocks in chdir, the other threads run.  However,
their FDs were closed, so they'll return an error.  Depending on whether or
not you have the DB bug fix, it'll either segfault under some circumstances
or just error out with a data_flow error.

To fix this, we now require all 2LSs that want to support forking to have
explicit support.  The thread0 sched trivially supports this.  The pthread
2LS will allow you to fork only from thread0, and it will suspend threading
for the duration of the fork in both the parent and the child.  During that
time, only thread0 will run.  After the fork(), the parent will resume
threading.  In the child, we'll never thread.  Those other threads will sit
on the ready_queue forever and will never run.  In DB's case, we don't want
them to run, since their FDs are closed.

Also, note that this is only a problem for the child, not the parent.
Further, SYS_fork will never appear to block for the child.  The syscall is
marked 'finished' before the child is RUNNABLE_S.

In general, let's just try to stop using fork().

Rebuild glibc, your shells, and dropbear.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoparlib: Add the uthread_is_thread0() helper
Barret Rhoden [Thu, 7 Jun 2018 18:58:12 +0000 (14:58 -0400)]
parlib: Add the uthread_is_thread0() helper

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoFix __this_cpu_add() typo
Barret Rhoden [Tue, 29 May 2018 21:15:09 +0000 (17:15 -0400)]
Fix __this_cpu_add() typo

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoAdd BSD's LIST_PREV
Barret Rhoden [Wed, 9 May 2018 19:23:13 +0000 (15:23 -0400)]

From commit aa34e24a277b ("Report TRAP_BRKPT for breakpoint traps on

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoRemove 'fs' from the gitignore
Barret Rhoden [Thu, 3 May 2018 17:39:24 +0000 (13:39 -0400)]
Remove 'fs' from the gitignore

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoPort Linux's percpu_counters
Barret Rhoden [Fri, 4 May 2018 22:33:17 +0000 (18:33 -0400)]
Port Linux's percpu_counters

Note the hokey per_cpu_ptr(x) -> _PERCPU_VARPTR(*x).

Also, these aren't as big as the WARNING says - neither are Linux's, I

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoSpatch Linux's percpu_counter
Barret Rhoden [Thu, 3 May 2018 19:44:51 +0000 (15:44 -0400)]
Spatch Linux's percpu_counter

Some of these might have been done manually.  I was fixing up the cocci
files concurrently.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoImport Linux's percpu_counter
Barret Rhoden [Thu, 3 May 2018 19:43:02 +0000 (15:43 -0400)]
Import Linux's percpu_counter

From commit 569dbb88e80d ("Linux 4.13").

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoUpdate Linux's cocci files
Barret Rhoden [Thu, 3 May 2018 18:18:40 +0000 (14:18 -0400)]
Update Linux's cocci files

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoUpdate per-cpu helpers in compat_todo
Barret Rhoden [Fri, 4 May 2018 22:32:10 +0000 (18:32 -0400)]
Update per-cpu helpers in compat_todo

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoAdd support for dynamic per-cpu variables
Barret Rhoden [Fri, 4 May 2018 21:51:01 +0000 (17:51 -0400)]
Add support for dynamic per-cpu variables

They are a little hokey.  You get a pointer back, which you have to
dereference each time you use it, even when you want to get a pointer to
a specific core's pointer.  That's different than Linux.  e.g.

u64 *foo = percpu_alloc(u64, MEM_WAIT);
u64 *core_3_ptr = _PERCPU_VARPTR(*foo, 3);

This is because __PERCPU_OFFSET computes &(var), which is how the static
stuff works.  We need to compute the offset from whatever our allocator got
back, which foo, so we need to balance the & with the *.  Not ideal.

Also, there is a limited amount of space - 1024 for now.  We could do
better with a virtual memory region:
- alloc vaddrs for the right size (2x previous)
- map that to the paddr of the previous, existing space
- map the new space (1x previous) above the existing space
- WRITE_ONCE percpu_base.
- maybe free old vaddr after a grace period, which would imply all per-cpu
  accessors are RCU read-side critical sections.

Not worth doing, for now.  It might be a pain to shrink it too.

The right approach might be to port more of Linux's percpu mechanisms.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoktest: Add minor fixes for kernel tests
Barret Rhoden [Fri, 4 May 2018 21:41:39 +0000 (17:41 -0400)]
ktest: Add minor fixes for kernel tests

The main thing is the convenience program 'ktest', which you can run via

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agorcu: Implement RCU
Barret Rhoden [Thu, 26 Apr 2018 19:57:09 +0000 (15:57 -0400)]
rcu: Implement RCU

Our RCU is similar to Linux's rcu_sched - we don't do the same things they

A lot of the changes to the Linux headers were me removing things I'm
fairly sure we won't need, so don't worry about that.  The bulk of this
commit is rcu.c, which implements call_rcu() and rcu_barrier() - which is
the heart of any RCU implementation.

Though note the locations in the rest of the kernel where we call
rcu_report_qs() - those are the locations where we know we aren't in a
read-side critical section.

The big difference between our RCU and Linux's implementation is that we do
not interfere with the CG cores.  We do not use softirq processing or timer
ticks for either callbacks or reporting quiescent states.

call_rcu() callbacks from CG cores do not run on the cores where they were
queued up.  There is a penalty for cache misses for this, but it prevents
us from interfering with the app.  Otherwise, once a grace period elapses,
we'd either have to wait for the user to enter the kernel or we'd have to
force them to.  You could imagine a middle ground where we let a callback
sit for a while or try to work-steal it.

We can check from a management core (core 0) to see if a CG core is in
userspace or idle.  This is similar to what Linux does with dynticks, I
think.  We also expedite the grace periods, though we can change that.

We use Linux's tree structure for tracking quiescent states, but all cores
use the global gpnum to find out which gpnum we're dealing with.  If that
turns out to be a scalability problem, then we can deal with it later.  I
didn't want to deal with certain cores having old gps.

As far as the timing parameters, I went with 25 msec since it wasn't a
multiple of the kernel scheduler tick.  If it is having an effect on FTQ
numbers, being at another frequency will make it stand out.

This hasn't been tested heavily; there are mostly likely bugs and almost
surely memory barrier problems that might require another architectures.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agorcu: Add Linux headers and helpers
Barret Rhoden [Thu, 19 Apr 2018 16:35:14 +0000 (12:35 -0400)]
rcu: Add Linux headers and helpers

These have more than we need, but a lot of it will be useful for us.

From commit 569dbb88e80d ("Linux 4.13").  rcu_helper.h was
kernel/rcu/rcu.h and rcu_tree_helper.c was from kernel/rcu/tree.c.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoAdd a few smp_ helpers from Linux.
Barret Rhoden [Wed, 11 Apr 2018 20:47:01 +0000 (16:47 -0400)]
Add a few smp_ helpers from Linux.

I'll need these for RCU - at least to keep that code a little cleaner.

From commit 569dbb88e80d ("Linux 4.13").

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoFix some minor Linux spatch / conversions
Barret Rhoden [Fri, 27 Apr 2018 20:50:43 +0000 (16:50 -0400)]
Fix some minor Linux spatch / conversions

I noticed these while attempting to port the RCU torture tests.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoAllow PERCPU array types
Barret Rhoden [Fri, 27 Apr 2018 16:22:33 +0000 (12:22 -0400)]
Allow PERCPU array types

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoAdd arch/membar.h
Barret Rhoden [Wed, 11 Apr 2018 20:30:03 +0000 (16:30 -0400)]
Add arch/membar.h

I have a few things I want to add that will be kernel-only for now.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoAdd a bulk interface to sem_down()
Barret Rhoden [Thu, 26 Apr 2018 18:36:47 +0000 (14:36 -0400)]
Add a bulk interface to sem_down()

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agosched: Catch the lack of a scheduler type
Barret Rhoden [Wed, 11 Apr 2018 19:44:11 +0000 (15:44 -0400)]
sched: Catch the lack of a scheduler type

If this happens, it might be a Makefile bug or a buggy .config file.
The #error is a little easier to diagnose.  I got this when I screwed up
the Makefile and turned a CFLAGS -> FLAGS for the CONFIG_ vars.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoRemove ONE_xBYTE #defines
Barret Rhoden [Wed, 11 Apr 2018 19:43:48 +0000 (15:43 -0400)]
Remove ONE_xBYTE #defines


Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoFix "error macro requires 3 arguments" problem
Barret Rhoden [Thu, 19 Apr 2018 19:12:22 +0000 (15:12 -0400)]
Fix "error macro requires 3 arguments" problem

If you try to use the compile_time_assert, for whatever reason, some black
magic in the preprocessor thinks there's a call to error (standalone) in
there, which is the Plan 9 error throwing macro.  It breaks in a nasty way.

I don't know exactly what Linux is doing here, but renaming fixes it.  This
probably means we can't have a macro called error_foo() either.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoUse Linux's compiler headers (XCC)
Barret Rhoden [Wed, 11 Apr 2018 19:29:16 +0000 (15:29 -0400)]
Use Linux's compiler headers (XCC)

This required a few things.  The easy ones were removing our old #defines
for things that Linux's compiler headers handle, e.g. unlikely.  The
tougher things included allowing the use of 'extern inline' and using
__percpu for our own use.  See k/i/compiler.h for details.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoCopy Linux's compiler.h
Barret Rhoden [Wed, 11 Apr 2018 17:27:47 +0000 (13:27 -0400)]
Copy Linux's compiler.h

There are a couple things that Linux has that I'd like to use.  Plus, it's
just a matter of time until we have some horrible bug that we could have
caught by using the stuff instead of rolling our own.  The compiler headers
are less about the OS and more about using the compilers to write an OS.

From commit 569dbb88e80d ("Linux 4.13").

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoUpdate Linux's list.h
Barret Rhoden [Mon, 9 Apr 2018 18:29:55 +0000 (14:29 -0400)]
Update Linux's list.h

Up to date with 569dbb88e80d ("Linux 4.13").

Basically generate a patch on Linux:

$ git diff bc208e0ee0f4..HEAD include/linux/list.h > ~/foo.patch

And apply it to Akaros:

$ cd kern/include/
$ patch -p3 < ~/foo.patch

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoMove PASTE() to common.h
Barret Rhoden [Mon, 23 Apr 2018 17:32:58 +0000 (13:32 -0400)]
Move PASTE() to common.h

We had it defined in two locations.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoAdd pcpui helpers
Barret Rhoden [Mon, 23 Apr 2018 17:14:38 +0000 (13:14 -0400)]
Add pcpui helpers

This commit adds minor helpers for managing per-cpu stuff in smp.h and
shows how to use some of the helpers in syscall.c.

We have two sets of per-cpu data: pcpui (the struct in smp.h) and PER_CPU,
which uses a special section.  Both are accessed by indexing off core_id,
which isn't ideal.  Each reference is a fresh core_id() call; it's fast
(especially now) but not free.

pcpui allows for easy reuse of the pcpui pointer, but all structures need
to be in smp.h.  Perhaps both systems should use gs-relative addressing.
For now, using one of the other is just a matter of convenience.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Remove CCACHE
Barret Rhoden [Fri, 6 Apr 2018 19:36:37 +0000 (15:36 -0400)]
9ns: Remove CCACHE

That was a chan flag that said we were using #mnt's old cache.  It is
unused now, since #gtfs handles all the caching transparently.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: mnt: Don't use a 'bogus' struct
Barret Rhoden [Fri, 6 Apr 2018 19:34:13 +0000 (15:34 -0400)]
9ns: mnt: Don't use a 'bogus' struct

That struct we pass through is mntparams, and they should be kept in sync.
Not sure why Plan 9 / Inferno ever used that crappy bogus struct - maybe a
header problem.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Support setting FD flags (XCC)
Barret Rhoden [Fri, 6 Apr 2018 19:14:52 +0000 (15:14 -0400)]
9ns: Support setting FD flags (XCC)

Similar to back in the VFS code, I'm not entirely happy supporting the
toggling of these flags.  Ideally, we wouldn't even have e.g. FD_CLOEXEC.

Reinstall your kernel headers

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Implement fsync with chan_ctl
Barret Rhoden [Fri, 6 Apr 2018 18:27:02 +0000 (14:27 -0400)]
9ns: Implement fsync with chan_ctl

If you fsync on a directory, we'll sync the entire FS for the given device.
You can use the sync helper to cause fsyncs.

Note your bind order matters.  If you mount or bind with "-a", it'll be at
the bottom of the union mount list.  You probably want -b.  For example:

$ mount -a -c -C /srv/some_chan /mnt
$ sync /mnt  # this calls #kfs.chan_ctl

That will sync kfs's /mnt, not gtfs's, since both kfs and gtfs have a chan
at /mnt/ that can be opened.

$ mount -b -c -C /srv/some_chan /mnt
$ sync /mnt  # this calls #gtfs.chan_ctl

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Make chan_ctl() mandatory
Barret Rhoden [Fri, 6 Apr 2018 15:55:48 +0000 (11:55 -0400)]
9ns: Make chan_ctl() mandatory

Previously, chan_ctl was optional; it was the device's opportunity to do
something, including say 'no', when we set the chan flags.  Instead,
devices must clearly say they will support it.

Part of the issue was the old chan_ctl didn't actually have multiple
operations.  The implied operation was 'set fl.'  That won't work for other
upcoming uses of chan_ctl, such as fsync.  Devices may support e.g. fsync
but not changing flags.

Note we don't have CCTL_GET_FL - the caller already has the chan and its
flags.  The device has nothing to do with it.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Add a helper for getting chan's device's name
Barret Rhoden [Fri, 6 Apr 2018 15:24:58 +0000 (11:24 -0400)]
9ns: Add a helper for getting chan's device's name

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: kfs: Give the CPIO blob to the base arena
Barret Rhoden [Thu, 5 Apr 2018 20:58:20 +0000 (16:58 -0400)]
9ns: kfs: Give the CPIO blob to the base arena

The CPIO's contents are extracted and exist in KFS's structures.  It is
unused at this point, and unlike the old KFS, it won't be used during
regular operation.  The old KFS would use the CPIO as the backing store for

This might trigger a couple bugs, since the allocator will be handing out
more data that isn't already zeroed.  Perhaps there are other bugs with
memory being below _end (and below the boot allocator).  That should be
fine though, just be careful.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Add #gtfs
Barret Rhoden [Thu, 5 Apr 2018 19:03:14 +0000 (15:03 -0400)]
9ns: Add #gtfs

gtfs is a generic tree file system that uses a somewhat arbitrary 9p device
for its backend - specifically #mnt.  #gtfs is the frontend caching layer
for the backend.  It has a page cache, a tree_file tree with RCU-protected
lookups, 'negative' entries, etc - all the things you'd expect.  If the
backend supports symlinks, then it would do that too.  Currently, #mnt does

With this in place, we can mount 9p servers and execute binaries over 9p
with mmap, which wasn't possible before.

The neat thing about it is that it required no changes to the mount driver.

Brief background: the #mnt device is given a channel to a 9p fileserver and
attaches itself in your namespace.  You do an 'ls', which gets converted
into a bunch of operations in the kernel, and the #mnt device converts
those ops to 9p RPCs.  End result: it looks like the remote filesystem is
in your namespace.

The #gtfs takes a channel to *another* device, in this case the #mnt from
above, and when the kernel wants to do a bunch of ops, #gtfs uses the
tree_file code and page cache as a cache.  When it is missing certain info,
it talks to #mnt and gets the info from the remote server.  It does the
same trick as #mnt: take a channel that speaks a version of the 9p
protocol, and convert between two interfaces.  The difference?  #mnt uses
the RPC interface for 9p.  #gtfs uses the in-kernel *functional* interface
for 9p - which is the function pointers in struct dev (e.g. open, close,
read, write, etc).

You can see the caching layer's effect by watching the RPCs to the
fileserver.  When you do an ls, you see a read of the directory (readdir)
followed by a bunch of stat calls, which is the essence of ls.  If you do a
subsequent ls, you just see the read again.  No need to do the stat, since
the frontend cache already has the info.  Why do you need the read again,
you ask?  Because the frontend is a partial cache, and it doesn't
necessarily know about every file in a directory/tree.  So it checks with
the backend (the 9p server).  But for the files it has, it has all of the

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoUse READ_ONCE() for seq counters (XCC)
Barret Rhoden [Thu, 5 Apr 2018 17:37:14 +0000 (13:37 -0400)]
Use READ_ONCE() for seq counters (XCC)

READ_ONCE() is like ACCESS_ONCE(), just clearly a read.

There are concurrent writes to the field, ordering matters, etc.  In
seqctr_retry, it was possible for the compiler to generate two reads from
the data structure for the "is locked" and "!=" tests.  We might have had
strange results there.

The seq stuff might need a closer look.

Reinstall your kernel headers.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Clarify a couple struct dev fields
Barret Rhoden [Thu, 5 Apr 2018 16:46:06 +0000 (12:46 -0400)]
9ns: Clarify a couple struct dev fields

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agopm: Remove the venerable pm_remove_contig()
Barret Rhoden [Tue, 3 Apr 2018 19:42:44 +0000 (15:42 -0400)]
pm: Remove the venerable pm_remove_contig()

It did a lot, but was more complicated than we needed.  It also might have
been doing too much.

It was responsible for attempting to remove pages even if they were being
used by an active mmaping - shootdown, collect dirty bits, writeback, unmap
for real and catch any intermediate users, etc.  I'm not sure we need all
of that, and if we do, maybe we'll fix the PM / MM code before that (more
scalable structures, huge pages, etc).

It also was marking PTEs not present before checking their dirty bits.
That might not be necessary for all uses.  It looks like we wanted to force
any users to fault, which would trigger a pm_load_page, which would clear
the removal flag.  Not 100% on that.  Be careful if you use that old code.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agopm: Add pm_free_unused_pages()
Barret Rhoden [Tue, 3 Apr 2018 19:38:50 +0000 (15:38 -0400)]
pm: Add pm_free_unused_pages()

Devices can call this if they want to free a little memory.  It's a little
niche, since it only really helps with open files that are not mmapped.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agopm: Add pm_writeback_pages()
Barret Rhoden [Mon, 2 Apr 2018 18:58:23 +0000 (14:58 -0400)]
pm: Add pm_writeback_pages()

This allows a TFS/user to writeback an individual file.  It required a few
changes, mostly to buggy PM helpers.  I think pm_remove_contig() isn't
doing the right thing for ranges where index isn't in the VMR, but the
range is.  Not a huge deal - that code is going away soon.

Single-page WB is a little slow, though the real slowdown is using a 9p
server - individual writes take forever.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoFix up bind and mount
Barret Rhoden [Mon, 2 Apr 2018 15:40:37 +0000 (11:40 -0400)]
Fix up bind and mount

mount was a copy-paste from bind, but it was improved over time to have
more than one flag; bind still couldn't.

Apart from that fix, I also touched up the formatting and trailing
whitespace a bit.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Add MEM_WAIT in a few places
Barret Rhoden [Sun, 1 Apr 2018 23:37:22 +0000 (19:37 -0400)]
9ns: Add MEM_WAIT in a few places

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agomm: Hold the pte_lock when doing a memwalk
Barret Rhoden [Thu, 29 Mar 2018 21:33:50 +0000 (17:33 -0400)]
mm: Hold the pte_lock when doing a memwalk

I think all the callers hold that lock.  There are probably other places
that are messing that up.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agomm: Don't decref files while holding a lock
Barret Rhoden [Thu, 29 Mar 2018 21:33:16 +0000 (17:33 -0400)]
mm: Don't decref files while holding a lock

Yes, this code is nasty and needs an overhaul - notably the removal of that

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoAdd pte_clear_dirty()
Barret Rhoden [Thu, 29 Mar 2018 21:32:40 +0000 (17:32 -0400)]
Add pte_clear_dirty()

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agomm: Catch allocation failure
Barret Rhoden [Thu, 29 Mar 2018 18:54:53 +0000 (14:54 -0400)]
mm: Catch allocation failure

Given all this code is hokey, at least we'll panic instead of crashing.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agopm: Allow RCU lookups and qlocked updaters
Barret Rhoden [Thu, 29 Mar 2018 18:42:22 +0000 (14:42 -0400)]
pm: Allow RCU lookups and qlocked updaters

We're going to need to do writeback, and the easiest way to do that is to
hold a qlock on our callback.  We can't just replace the old pm spinlock
with a qlock, since it is grabbed by other spinlock holders (old VMR code,
both for pm_add_vmr and for pm_load_page_nowait()).

Also, this allows lockless lookups, which is nice.

Overall, the VMR and PM/radix code still needs a lot of structural work,
possibly involving thinking more about huge pages.  For now, this is a
modest change and we'll keep the basic infrastructure in place - enough
that we can make progress with the TFS code.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agopm: Implement pm_remove_or_zero_pages()
Barret Rhoden [Thu, 29 Mar 2018 15:35:15 +0000 (11:35 -0400)]
pm: Implement pm_remove_or_zero_pages()

This is what truncate/hole-punch really wants - best effort, and zero if
all else fails.  pm_remove_contig() tries to do too much, and doesn't
handle the failure cases.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agopm: Implement pm_destroy()
Barret Rhoden [Thu, 29 Mar 2018 15:33:57 +0000 (11:33 -0400)]
pm: Implement pm_destroy()

We had been just leaking memory.  Though it is hard to see this, since all
of the pages are actually just sitting in slab magazines, and not freed all
the way back to the arenas.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoradix: Implement radix_tree_destroy()
Barret Rhoden [Wed, 28 Mar 2018 20:33:38 +0000 (16:33 -0400)]
radix: Implement radix_tree_destroy()

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoradix: Add for_each iterators
Barret Rhoden [Wed, 28 Mar 2018 20:32:36 +0000 (16:32 -0400)]
radix: Add for_each iterators

These will help with implementing various page cache helpers.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Allow racy truncations
Barret Rhoden [Tue, 27 Mar 2018 22:27:28 +0000 (18:27 -0400)]
9ns: Allow racy truncations

I'm relaxing the consistency guarantees during truncate/hole_punches.  If
you do concurrent reads, writes, or mmaps during truncate, you might get
weird data: old, new, or a combination of the two.

My primary desire for this is to avoid qlocking the file during what could
be parallel operations: reading or writing to non-overlapping parts of a

Part of this is that the qlock is not held during pm_load_page, especially
for mmap faults.  In an alternate version of this code, pm_load_page held
the qlock, the PM op didn't need to grab the lock, and every mmap hard
fault (i.e. not the nowait, the one with pm_load_page that blocks) would
qlock.  Soft faults (the read fast-path) wouldn't qlock.

I'm not 100% on this, so I haven't squashed this into the original FS file

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agomm: Mark dirty pages when we munmap
Barret Rhoden [Mon, 26 Mar 2018 16:06:44 +0000 (12:06 -0400)]
mm: Mark dirty pages when we munmap

The page cache will need to know which pages are dirty.  I might
overhaul the PM code, but regardless this is a bug and needs to be done
- one way or another.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Add LRU support to tree filesystems
Barret Rhoden [Mon, 26 Mar 2018 14:11:51 +0000 (10:11 -0400)]
9ns: Add LRU support to tree filesystems

Any non-RAMFS will want some form of access to the LRU list.  These
devices will use tree files as caches, referred to as the frontend.  The
"real" filesystem will be elsewhere: typically on a 9p server, though a
disk FS would work as well.

Since the tree_file tree is a cache, both the TFs and the page cache for
the files, devices may want to shed their caches when memory becomes

Similarly, devices may want to perform their own work on the LRU list.
For instance, the #gtfs device, which fronts #mnt, will want to
periodically prune its open FIDs to the backend 9p server.  Stay tuned.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Make QTFILE == 0. Goddamn 9p
Barret Rhoden [Tue, 20 Mar 2018 19:55:00 +0000 (15:55 -0400)]
9ns: Make QTFILE == 0.  Goddamn 9p

This is annoying, but translating qids back and forth just for one bit
isn't worth the bugs.

Zero wouldn't be as bad if there were a bunch of *values* for qid.type, so
that we're just doing == checks or switches  (still, don't use zero).  But
it's bits!  The worst possible decision.

This is OK, and you see it everywhere:

c->qid.type & QTDIR

this isn't, since QTFILE has the value 0:

c->qid.type & QTFILE

This is the same shit with O_READ modes.


Told-off-by: Barret Rhoden <brho@cs.berkeley.edu>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agoexec: Clear owning proc earlier
Barret Rhoden [Tue, 20 Mar 2018 19:47:13 +0000 (15:47 -0400)]
exec: Clear owning proc earlier

We're supposed to clear as soon as we could block, but foc_open() can block
(as the comment says).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Add the cache option (-C) to mount
Barret Rhoden [Fri, 16 Mar 2018 20:02:47 +0000 (16:02 -0400)]
9ns: Add the cache option (-C) to mount

That needs cleaned up a bit, including exporting the mount flags in the
kernel interface.  Same probably goes for bind.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Remove the old mnt cache
Barret Rhoden [Fri, 16 Mar 2018 19:59:19 +0000 (15:59 -0400)]
9ns: Remove the old mnt cache

Plan 9 had a write-through, data only cache.  It would speed up reads,
and it assumed no one else was writing to the server, which is fine.
Since it was write-through, it never needed to sync to the backend.

The tree_file version of #mnt will use the TFS for its caching, so we
don't need the older caching layer - which actually didn't do anything
on Akaros.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Clean up the dir->mode bits
Barret Rhoden [Thu, 15 Mar 2018 15:32:16 +0000 (11:32 -0400)]
9ns: Clean up the dir->mode bits

The lower 9 bits are the classic rwxrwxrwx bits.  The upper bits contain
things like "is a directory."

'mode' is a bit confusing, especially if you are familiar with the
POSIX/glibc world.  dir->mode is the permissions, which we get from the
'perm' argument to create (i.e. SYS_openat with O_CREATE).  That is
different from the 'mode' argument to open(), which is the e.g. O_RDWR
flags for the *chan* (file in Unix) - not the filesystem file (inode in

Good times.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years agostrace: Report errno and errstr on failure
Barret Rhoden [Wed, 14 Mar 2018 19:40:44 +0000 (15:40 -0400)]
strace: Report errno and errstr on failure

I got tired of looking at straces, knowing there was an error, and
wondering what the errno/errstrs were.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Support rename
Barret Rhoden [Wed, 14 Mar 2018 17:27:37 +0000 (13:27 -0400)]
9ns: Support rename

Devices without a rename operation just get an EXDEV.  Usually userspace
can handle that (e.g. busybox's mv).

I added rename to the struct dev ops since it should be a 9p operation,
allowing renames across directories.  9p wstat does allow an
intra-directory rename, but that's not really what you want.  By giving
the device the old chan, the parent chan, and the name, it can
atomically perform the rename.  Atomicity is a critical part of rename.

Previously, we tried mucking around with rename and wstat, and it was
missing some of the namec-magic associated with Acreate (findmounts and
other stuff).  The device wasn't given the parent chan - it had to find
that on its own, and I was worried that there were some TOCTTOU races if
we just gave it the path.

Additionally, the device may need to do various "version" checks, which
can be done in a dev.rename op, but are harder to do generically.  See
tmpfs for an example.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
2 years ago9ns: Add #tmpfs
Barret Rhoden [Tue, 13 Mar 2018 21:43:16 +0000 (17:43 -0400)]
9ns: Add #tmpfs

The tmpfs device can have many instances, each of which are separate
filesystem trees.  When you close the last chan into the instance,
whether that was by unmounting it or by closing an open FD, it will
destroy itself.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>