B1: a boot area on the disk, reserved by arithmetic that was already there
The first rung of booting from disk. A boot area is blocks between the superblock and the directory that the filesystem never allocates and never sees, and NOTHING WAS ADDED TO RESERVE THEM: both implementations work out the first usable block as directoryStart + directoryBlocks, and directoryStart has always been a field rather than a constant. Formatting with the directory moved up reserves everything below it. Neither allocator changed, on either side. Two new superblock fields in bytes that were reserved: bootBlocks at 14, per slot, and bootSlot at 16. A disk made before this has zero in both, which reads as "no boot area" - true, and the same shape as the version two parent field, where the value an older disk already held was the right answer without conversion. TWO SLOTS, ALWAYS. A boot slot is raw blocks with no entry to rename, so the write-a-temporary-and-rename ordering that protects every file cannot protect it, and a machine interrupted while updating its only slot would not boot at all - the one failure on this disk with no way back. Writing the slot that is not live and then moving one byte makes that a machine that boots what it had before. bootBlocks and directoryStart say the same thing from two sides, so a disk where they disagree is refused rather than guessed at, as is one naming a slot that does not exist. Checked where it matters: the HOST formats a disk with a boot area and the MACHINE fills it, then the reserved blocks are compared against zero. The machine's allocator is the one that had no idea any of this was happening, which is what makes that the check worth having. Six host checks besides, including both halves of the superblock disagreeing.
This commit is contained in:
@@ -244,7 +244,7 @@ increment, decrement, addition, and subtraction when their inputs are known.
|
||||
|
||||
| Command | What it does |
|
||||
| --- | --- |
|
||||
| `format <image> [blocks] [dirblocks]` | Lay down a fresh filesystem. 512 blocks and 8 of directory by default, which is 128K and room for 64 entries. |
|
||||
| `format <image> [blocks] [dirblocks] [bootblocks]` | Lay down a fresh filesystem. 512 blocks and 8 of directory by default, which is 128K and room for 64 entries. A fourth number reserves a boot area of two slots that size. |
|
||||
| `list <image> [path]` | Show the whole disk, or one directory of it. |
|
||||
| `put <image> <file> [path]` | Put a host file onto it. Without a path it uses the file's own name, which is often longer than the 22 characters a name may be. |
|
||||
| `get <image> <path> [file]` | Take one off it. |
|
||||
@@ -252,6 +252,27 @@ increment, decrement, addition, and subtraction when their inputs are known.
|
||||
| `mkdir <image> <path>` | Make a directory. |
|
||||
| `rmdir <image> <path>` | Remove an empty one. |
|
||||
|
||||
### The Boot Area:
|
||||
|
||||
Blocks between the superblock and the directory, which the filesystem never allocates and
|
||||
never sees. **Nothing was added to reserve them.** Both implementations work out the first
|
||||
usable block as `directoryStart + directoryBlocks`, and `directoryStart` has always been a
|
||||
field in the superblock rather than a constant, so moving the directory up reserves
|
||||
everything below it by arithmetic that was already there. Neither allocator changed.
|
||||
|
||||
A disk made before any of this has `directoryStart` of 1 and a boot area of zero, which
|
||||
reads as *not bootable* - true, and the same shape as the version two parent field, where
|
||||
the value an older disk already held turned out to be the right answer.
|
||||
|
||||
**There are always two slots**, because a boot slot is raw blocks. A file being rewritten
|
||||
is protected by writing a temporary and renaming it, and there is no name here to rename -
|
||||
so a machine interrupted while updating its only boot slot would not boot at all, which is
|
||||
the one failure on this disk with no way back. Writing the slot that is *not* live and then
|
||||
moving one byte in the superblock turns that into a machine that boots what it had before.
|
||||
|
||||
`bootBlocks` and `directoryStart` describe the same fact from two sides, so a disk where
|
||||
they disagree is refused rather than guessed at.
|
||||
|
||||
SplitDisk speaks the same on disk format SplitBit does, so an image it makes is one the machine can read, and one the machine writes is one it can read back. It is a convenience rather than a necessity: SplitBit writes its own filesystem, and now assembles its own programs, so a disk can be filled without leaving the machine.
|
||||
|
||||
Files are laid down contiguously, so a disk can have free blocks without having them in one piece. When that happens `put` says so rather than putting part of a file on.
|
||||
|
||||
Reference in New Issue
Block a user