Fix two bugs the Fedora move exposed
Neither is Fedora-specific. A different host and a freshly built
userland simply drove code that Windows never reached.
tools/mkfs.c did not compile at all. The DT_UNKNOWN/DT_DIR/DT_REG
fallbacks sat above <dirent.h>, so on glibc -- which spells them as
enumerators -- the #ifndef asked before the header was read, always
answered "missing", and then the header's own enum expanded to
`enum { 0 = 0, ... }`. Move the fallbacks below the include. The
include cannot move up instead: it has to follow the #undef that ends
the `#define dirent schfs_dirent` block.
getstackpcs() page-faulted. It dereferenced rbp[1] without validating
rbp, and the guard rejected 0xffffffff -- dead code on x86-64, already
caught by the KERNBASE test -- while the value that actually turns up
is all-ones, which is above KERNBASE. rbp[1] then wrapped to 0x7 and
took trap 14. `cp` panicked the kernel every time. Bound rbp from
above and require 8-byte alignment.
That second one masks other bugs: getcallerpcs() runs on every lock
acquisition and again from the trap handler, so a walker that can
fault replaces a real diagnosis with a bogus one.
Baseline on the Fedora laptop is now green: make ports, make,
make schfs-check including the round-trip that had never run, and
bootcheck at 27/27 plus 108 [ok] across the extended suites.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
1147834cd6
commit
15331d4399
5 changed files with 112 additions and 23 deletions
38
tools/mkfs.c
38
tools/mkfs.c
|
|
@ -41,21 +41,6 @@
|
|||
#define bzero(p, n) memset((p), 0, (n))
|
||||
#define bcopy(src, dst, n) memmove((dst), (src), (n))
|
||||
|
||||
// struct dirent's d_type is a BSD/glibc extension; mingw-w64 has no such
|
||||
// field. The loops below already handle DT_UNKNOWN by probing with opendir(),
|
||||
// which is the portable answer and was written for filesystems that decline to
|
||||
// report a type -- so on Windows every entry simply takes that path.
|
||||
#ifndef DT_UNKNOWN
|
||||
#define DT_UNKNOWN 0
|
||||
#define DT_DIR 4
|
||||
#define DT_REG 8
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#define DIRENT_TYPE(dp) DT_UNKNOWN
|
||||
#else
|
||||
#define DIRENT_TYPE(dp) ((dp)->d_type)
|
||||
#endif
|
||||
|
||||
#define stat xv6_stat
|
||||
#define sigset_t xv6_sigset_t
|
||||
#define dirent schfs_dirent
|
||||
|
|
@ -69,6 +54,29 @@
|
|||
// After the #undef above, so this gets the host's struct stat and not xv6's.
|
||||
#include <sys/stat.h>
|
||||
|
||||
// struct dirent's d_type is a BSD/glibc extension; mingw-w64 has no such
|
||||
// field. The loops below already handle DT_UNKNOWN by probing with opendir(),
|
||||
// which is the portable answer and was written for filesystems that decline to
|
||||
// report a type -- so on Windows every entry simply takes that path.
|
||||
//
|
||||
// This block must stay *below* <dirent.h>, not up with the other compatibility
|
||||
// shims. glibc spells these as enumerators with matching macros, so asking
|
||||
// #ifndef before the header is read always says "missing" -- and then the
|
||||
// header's own `enum { DT_UNKNOWN = 0, ... }` expands to `enum { 0 = 0, ... }`
|
||||
// and the build dies on a syntax error a long way from the cause. The header
|
||||
// cannot move up either: it has to follow the `#undef dirent` above, or it
|
||||
// would define the xv6 struct dirent instead of the host's.
|
||||
#ifndef DT_UNKNOWN
|
||||
#define DT_UNKNOWN 0
|
||||
#define DT_DIR 4
|
||||
#define DT_REG 8
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#define DIRENT_TYPE(dp) DT_UNKNOWN
|
||||
#else
|
||||
#define DIRENT_TYPE(dp) ((dp)->d_type)
|
||||
#endif
|
||||
|
||||
#ifndef static_assert
|
||||
#define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0)
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue