| We're adding the plan 9 file system to akaros.We're bringing in the | 
 | name space interface, including the ability to do binds, union mounts, | 
 | and the like. We will extend it to support things we might need, | 
 | in particular mmap.  We will use it to add things to Akaros we  | 
 | need, such as virtio drivers, ethernet drivers, and TCP. | 
 |  | 
 | By bringing this model in, we can make the Akaros interface more powerful, | 
 | yet simpler. We can remove a number of system calls right away  | 
 | and yet still have the functions they provide, for example.  | 
 |  | 
 | This is not a from scratch effort but a code translation. The Plan 9 code | 
 | deals with very subtle situations and has been hardened over time. No need | 
 | to relearn what they learned from scratch. | 
 |  | 
 | Currently we have a lot of the code in and are testing a first device --  | 
 | the regression device from NxM. | 
 |  | 
 | Issues. | 
 |  | 
 | The biggest issue so far is implementing the Plan 9 error handling. | 
 | In Plan 9, errors are managed via a longjmp-like mechanism. For example, | 
 | in a call chain such as: | 
 | a() | 
 |  b() | 
 |   c() | 
 |    d() | 
 |  | 
 | It is possible for 'd' to invoke an error that returns to 'a' directly.  | 
 | This model has many advantages over the standard model, which looks like | 
 | this: | 
 | a{ b();} | 
 |  b{ if c() return OK; else return -1;} | 
 |   c{ if d() return OK; else return -1;} | 
 |    d{ if something return OK; else return -1;} | 
 |  | 
 | In Plan 9 it can look like this: | 
 |  | 
 | a{ b();} | 
 |  b{ c(); something else();} | 
 |   c{ d(); other thing();} | 
 |    d{ if something return OK; else error("bad");} | 
 |  | 
 | Note that the intermediate functions can be written as though nothing | 
 | went wrong, since anything that goes wrong gets bounced to the first level | 
 | error handler.  | 
 |  | 
 | The handling is implemented via something called waserror(). | 
 | In a() we do this: | 
 |  | 
 | a(){ | 
 |    if (waserror())  { handle error; poperror();} | 
 |    b(); | 
 |    poperror(); | 
 | } | 
 |  | 
 | and in d we might have this: | 
 | d(){ | 
 |    do something;  | 
 |    if (bad) error("bad"); | 
 |    return 0; | 
 | } | 
 |  | 
 | What if there's more than one error? There can be multiple invocations | 
 | of waserror in one function: | 
 | a(){ | 
 |    if (waserror()){ printf("b failed"); poperror(); return -2;} | 
 |    b(); | 
 |    if (waserror()) { printf("z failed"); nexterror(); } | 
 |    z(); | 
 |    poperror(); | 
 |    poperror(); | 
 | } | 
 |  | 
 | Every waserror needs a matching poperror or nexterror in the same function as | 
 | the waserror, covering every exit from the function.  nexterror is like | 
 | to poperror() then error("str"), but without resetting errstr. | 
 |  | 
 | Note that the error could have been anywhere in the call chain; | 
 | we don't care. From the point of view of a(), something failed, and we only | 
 | know about b() or z(), so we blame them. We also show in this example | 
 | nexterror(). Nexterror() pops back to the next error in the error stack, | 
 | which might be in this function or somewhere up the call chain. | 
 |  | 
 | How do we find out the ultimate blame? Recall that error takes a string, | 
 | and that can be anything. We can tell from that.  | 
 |  | 
 | Where does the string in error() go? | 
 | In Plan 9, it goes into the proc struct; in Akaros, | 
 | it's copied to a user-mode buffer via set_errstr().  | 
 |  | 
 | waserror()/error()/nexterror() manipulate an error call stack, similar to | 
 | the function call stack. In Plan 9, this stack is maintained in the proc | 
 | struct. This is cheap in Plan 9, since the compiler has caller-save, and | 
 | hence each stack entry is a stack and a PC. In a callee-save world, the | 
 | stack entries are much, much larger; so large that maintaining the stack | 
 | in the proc struct is impractical. | 
 |  | 
 | Hence, we've had to make changes that add a bit of inconvenience but | 
 | leave the code mostly intact. The error code in Akaros is tested in every | 
 | circumstance at this point due to all the bugs we had in our port | 
 | of the Plan 9 file system code. | 
 |  | 
 | So, we'll go from the easiest case to the hardest. | 
 |  | 
 | Case 1: You're a leaf function that does not use error(). No change. | 
 |  | 
 | Case 2: You're a leaf function that needs error().  Just call error(). | 
 |  | 
 | Case 3: You're an intermediate function that calls functions that use error(), | 
 | even though you do not.  No change. | 
 |  | 
 | Those are in some sense the easier cases. Now it starts to get a | 
 | bit harder. | 
 |  | 
 | Case 4: you're a leaf or intermediate function that uses waserror().  You need | 
 | to use a macro which creates an array of errbuf structs as automatics. The | 
 | waserror() usage does not change.  The macro is ERRSTACK(x), where x is the | 
 | number of calls to waserror() in your function. See kern/sys/chan.c.  Every call | 
 | to waserror needs to have a matching poperror.  You cannot call nexterror or | 
 | poperror unless you are in the same scope as an ERRSTACK that had a waserror | 
 | call. | 
 |  | 
 | Case 5: you're a root node, i.e. you're the start of a chain of calls | 
 | via syscall that must do the "root" errbuf setup, so that all error | 
 | calls eventually return to you. In this case, you need to start the error | 
 | stack.  This uses the same macro as case 4 (ERRSTACK(x)), for now. | 
 |  | 
 | Finally, if, in a waserror, you are finished and want to pop out to the | 
 | next error in the chain, either in the same function or up the call stack, | 
 | just call nexterror(). | 
 |  | 
 | This can be handy for debugging: in any function that supports error(), i.e. | 
 | called from a function that called waserror(), simply call error and it bails | 
 | you out of wherever you are, doing appropriate cleanup on the way out.  No need | 
 | to add return value processing to intermediate functions; if you try this out | 
 | you will likely find it is extremely handy. I really miss it on Linux. It made a | 
 | lot of the port debugging to Akaros a lot easier. | 
 |  | 
 | There is error checking in error()/waserror()/nexterror(). | 
 | If you overflow or underflow the error stack the kernel will panic. | 
 | The implementation is in kern/src/error.c, the macros are in | 
 | kern/include/plan9.h. | 
 |  | 
 | Giant warning: if you access any automatic (local) variables inside the waserror | 
 | block that may have been modified after you started the waserror, those | 
 | variables need to be volatile.  waserror() is implemented with setjmp and | 
 | according to one of the man pages: | 
 |  | 
 | 	automatic variables  are  unspecified  after  a  call  to longjmp() if | 
 | 	they meet all the following criteria: | 
 | 	- they are local to the function that made the corresponding setjmp(3) | 
 | 	  call; | 
 | 	- their  values  are  changed  between  the  calls  to  setjmp(3)  and | 
 | 	  longjmp(); and | 
 | 	- they are not declared as volatile. | 
 |  | 
 | We could ask the compiler to tell us which variables are potentially clobbered | 
 | with -Wclobbered, however it is a noisy warning.  It will warn even if the | 
 | variables are not used in the error case.  That may be because the compiler has | 
 | a hard time deciding whether a variable is used or not, since we often longjmp | 
 | from within an error handler, though on gcc 4.9.2, even if we return | 
 | immediately, we still get a warning.  On a related note, it's not always | 
 | possible to tell which case is the error handling case - consider the "discard" | 
 | pattern for waserror. | 
 |  | 
 | No amount of "returns_twice" or register clobbering or "memory" clobbering is | 
 | enough.  Think about what happens when the variable is changed after the setjmp | 
 | call, i.e. farther down in the function.  It's may be in a register, then we | 
 | call some other function, and that longjmps.  That register value is gone (it | 
 | might be somewhere else on the stack).  The compiler needs to know when it makes | 
 | that write that it needs to go onto the stack storage of the automatic variable. | 
 | That's 'volatile.' | 
 |  | 
 | The best we can hope for is the compiler to know what variables could be written | 
 | from one side of the setjmp and used on the other.  Perhaps that will show up, | 
 | and then we can turn on -Wclobbered.  Until then, we have to be vigilant, or use | 
 | different patterns for waserror.  Note there are a bunch of bugs with | 
 | -Wclobbered detection, e.g. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65041. | 
 |  | 
 | For info on the format of Ms (which are part of the kernel interface): | 
 | 	http://9p.cat-v.org/documentation/rfc/  |