A listing says what is left of the disk, and what will fit
dir said what was there and nothing about what was left. SplitDisk has printed the free figure since it was written, so the machine's own listing was the poorer of the two implementations at describing the same disk. 43 files, 3 directories 46 of 64 entries, 1893 blocks free Entries first, because they are the ceiling nobody notices until they hit it: a disk of small files runs out of directory slots long before it runs out of blocks. COUNTED RATHER THAN ASKED. The superblock keeps a free count and this file calls it "a note rather than the truth" in three places. sbfsSpace reads the whole directory table instead, which costs a read per directory block and is the answer rather than a guess. SplitDisk goes on reading the note and saying when it is stale, which is the right place for that check - the host tool is what you audit a disk with. ---- And it is a fact about the disk, not about where you are ---- The first version added the blocks up as the LISTING walked past them, which cost no extra read and was wrong: that walk stops only on entries in the working directory, so the same disk came out as 1,996 blocks free from the root and 2,025 from /Apps. Comparing against SplitDisk is what said so, which is what having two implementations is for. ---- The longest run, which is what decides whether a file fits ---- 4 of 16 entries, 37 blocks free the longest run is 25 Files are laid down contiguously, so the free total does not say whether a file will fit. Both implementations learn it, from one specification. Said only when it differs from the free total. Deleting is what fragments a contiguous store, and a disk that has only been appended to has one gap at the end - so on a healthy disk this is silent, and a line that appears only when something is wrong is a line somebody reads. There is no sort on this machine and the entries are in no order, so a candidate walks the disk: each pass finds the used extent nearest at or after it, and anything the candidate stands inside pushes it to the far end and starts the pass again. The same trick allocating uses. So it costs a pass per gap rather than per file - nearly nothing on a disk with one gap, more the more fragmented the disk is, which is the right way round. holes.img is six files with the second and fourth deleted, because no other disk here can show any of this: none of them has ever had anything deleted from it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
2ad8edf9bc
commit
323d7a0330
@@ -3938,6 +3938,102 @@ dirFolderCount:
|
||||
CALL printString
|
||||
dirNoFolders:
|
||||
CALL newLine
|
||||
|
||||
; ---- And what is left of the disk ----
|
||||
;
|
||||
; A listing that says what is there and not what is left says half of what anybody wants
|
||||
; to know. SplitDisk has printed this since it was written; the machine's own listing had
|
||||
; nothing to say about the disk it was listing.
|
||||
;
|
||||
; COUNTED RATHER THAN ASKED. The superblock keeps a free count, and sbfs.asm calls it "a
|
||||
; note rather than the truth" in three separate places. The truth is what the entries add
|
||||
; up to, and the walk above has just added them up - so this costs no disk read at all,
|
||||
; where believing the note would cost one and be a guess. SplitDisk reads the note as well
|
||||
; and says so when the two disagree, which is the right place for that check: the host tool
|
||||
; is what you audit a disk with, and this is what you work on one with.
|
||||
;
|
||||
; ---- AND IT IS THE DISK, NOT THIS DIRECTORY ----
|
||||
;
|
||||
; The first version of this added the blocks up as the listing walked past them, which cost
|
||||
; no extra read and was wrong: that walk stops only on entries in the working directory, so
|
||||
; the same disk was called 1,996 blocks free from the root and 2,025 from /Apps. Free space
|
||||
; is a fact about the disk, so sbfsSpace reads the whole directory table for it - and the
|
||||
; two implementations of this format disagreeing is what said so.
|
||||
CALL sbfsSpace
|
||||
BNQ dirNoSpace
|
||||
|
||||
; Entries first, because they are the ceiling nobody notices until they hit it - a disk of
|
||||
; small files runs out of directory slots long before it runs out of blocks, and saying
|
||||
; both means never having to work out which one is about to bite.
|
||||
SETD.0 DirEntries
|
||||
SETD.2 SbfsDirBlocks
|
||||
CALL sbfsSetWord
|
||||
INIA 0d3
|
||||
SETD.0 DirDoubles
|
||||
STA.0
|
||||
dirEntriesTimes:
|
||||
; Eight entries to a directory block, which is three doublings on a machine with no
|
||||
; multiply. Adding a number to itself is what a doubling is.
|
||||
SETD.0 DirEntries
|
||||
SETD.2 DirEntries
|
||||
CALL sbfsAddWord
|
||||
SETD.0 DirDoubles
|
||||
LDA.0
|
||||
DECA
|
||||
STA.0
|
||||
BNA dirEntriesTimes
|
||||
|
||||
SETD.0 SbfsUsedEntries
|
||||
CALL printWordDecimal
|
||||
SETD.0 OfText
|
||||
CALL printString
|
||||
SETD.0 DirEntries
|
||||
CALL printWordDecimal
|
||||
SETD.0 EntriesText
|
||||
CALL printString
|
||||
|
||||
; What is left is the disk, less where the files begin, less what they hold.
|
||||
SETD.0 DirFree
|
||||
SETD.2 SbfsDiskBlocks
|
||||
CALL sbfsSetWord
|
||||
CALL sbfsFirstData
|
||||
SETD.0 DirFree
|
||||
SETD.2 SbfsCandidate
|
||||
CALL sbfsSubWord
|
||||
SETD.0 DirFree
|
||||
SETD.2 SbfsUsedBlocks
|
||||
CALL sbfsSubWord
|
||||
|
||||
SETD.0 DirFree
|
||||
CALL printWordDecimal
|
||||
SETD.0 FreeText
|
||||
CALL printString
|
||||
CALL newLine
|
||||
|
||||
; ---- And how much of that is in one piece ----
|
||||
;
|
||||
; Said only when it is not all of it, which is the common case and the quiet one. Files are
|
||||
; laid down contiguously, so the free total is not what decides whether a file will fit -
|
||||
; the longest run is. A disk with a thousand blocks free in ten pieces refuses a file of two
|
||||
; hundred, and nothing in the listing would have hinted at it.
|
||||
;
|
||||
; A LISTING THAT SAID "longest run 1893" UNDER "1893 blocks free" WOULD BE NOISE on every
|
||||
; healthy disk, and a line that only appears when something is wrong is a line somebody
|
||||
; reads. It is also what makes the measurement worth its cost: a disk with one gap at the
|
||||
; end, which is what an append-only disk is, walks the table twice and says nothing.
|
||||
CALL sbfsLargestRun
|
||||
BNQ dirNoSpace
|
||||
SETD.0 DirFree
|
||||
SETD.2 SbfsBiggest
|
||||
CALL sbfsCompareWord
|
||||
BRQ dirNoSpace
|
||||
|
||||
SETD.0 RunText
|
||||
CALL printString
|
||||
SETD.0 SbfsBiggest
|
||||
CALL printWordDecimal
|
||||
CALL newLine
|
||||
dirNoSpace:
|
||||
BRI prompt
|
||||
|
||||
dirNoDisk:
|
||||
@@ -7927,6 +8023,15 @@ IsDirectory:
|
||||
"that is a directory"
|
||||
AndText:
|
||||
", "
|
||||
OfText:
|
||||
" of "
|
||||
EntriesText:
|
||||
" entries, "
|
||||
FreeText:
|
||||
" blocks free"
|
||||
RunText:
|
||||
"the longest run is "
|
||||
|
||||
FoldersText:
|
||||
" directories"
|
||||
FolderText:
|
||||
@@ -8219,6 +8324,14 @@ DirFolders:
|
||||
0x00
|
||||
DirTaken:
|
||||
0x00
|
||||
; What the entries add up to, what is left, and how many slots there are to fill. Counted on
|
||||
; the way past rather than asked of the superblock, whose count sbfs.asm calls a note.
|
||||
DirFree:
|
||||
0x00 0x00
|
||||
DirEntries:
|
||||
0x00 0x00
|
||||
DirDoubles:
|
||||
0x00
|
||||
DiskReady:
|
||||
0x00
|
||||
LoadedOk:
|
||||
|
||||
Reference in New Issue
Block a user