SchOS/include/buf.h
Nexoniarz 527e6eac42 Raise the disk ceiling: 64-bit blocks, no FSSIZE panic, LBA48
SchFS is a 64-bit format addressing 64 ZB. The stack under it was not,
and the lowest limit was three orders of magnitude below the one anybody
would have guessed:

  ide.c   panicked on any block >= FSSIZE -- 150000 blocks, 614 MB
  ide.c   computed the sector in an int, and addressed it with LBA28
  bio.c   took a 32-bit block number, capping any device at 16 TB
  schfs   refused blocks past 0xffffffff, mirroring the cache

The FSSIZE check is the one that mattered. FSSIZE describes the size of a
v1 filesystem *image*; it had no business bounding a physical device, and
it meant a disk larger than half a gigabyte panicked the kernel rather
than being read.

struct buf's blockno is uint64 now, and so is bread's. idestart computes
the sector in 64 bits and picks LBA48 when it does not fit in 28 -- per
request, so everything that fits stays on the LBA28 path every existing
image has been read through. The 48-bit registers are written high half
first, because each is a two-deep FIFO and the other order leaves the
drive addressing whatever the low bytes alone describe.

Verified with a 2 GB disk carrying a marker at 1 GiB -- block 262144,
well past the old panic at 150000. The guest reads it back:
"MARKER-PAST-THE-OLD-LIMIT". schfs-check passes including the round-trip;
bootcheck 108 [ok].

Two limits deliberately left, both noted rather than guessed at: raw
/dev/hdN access still goes through devsw's 32-bit offset, so a raw device
is addressable to 4 GB; and usb_storage computes a 32-bit LBA, which is
what SCSI READ(10) carries -- READ(16) is a different command, not a
wider variable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 18:50:31 +02:00

18 lines
589 B
C

struct buf {
int flags;
uint dev;
// 64-bit, because the filesystem's block numbers are. This was a uint, which
// capped any device at 2^32 blocks (16 TB at 4 KB) no matter what the format
// above it could address -- SchFS is a 64-bit format and was being served by
// a 32-bit cache.
uint64 blockno;
struct sleeplock lock;
uint refcnt;
struct buf *prev; // LRU cache list
struct buf *next;
struct buf *qnext; // disk queue
uchar data[BSIZE];
};
#define B_VALID 0x2 // buffer has been read from disk
#define B_DIRTY 0x4 // buffer needs to be written to disk