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>
This commit is contained in:
parent
8b7b8df74f
commit
527e6eac42
5 changed files with 63 additions and 20 deletions
|
|
@ -112,10 +112,9 @@ kd_read(void *ctx, uint64_t blk, void *out)
|
|||
|
||||
if (blk == 0)
|
||||
return -1;
|
||||
// The buffer cache addresses blocks with a uint, which caps the volume long
|
||||
// before the on-disk format does. Refusing out here beats truncating and
|
||||
// reading some unrelated sector, which would surface as corruption.
|
||||
if (blk > 0xffffffffULL / SCHFS_BPB)
|
||||
// The buffer cache takes 64-bit block numbers now, so this no longer caps the
|
||||
// volume; the check remains as an overflow guard on the multiply below.
|
||||
if (blk > (~0ULL) / SCHFS_BPB)
|
||||
return -1;
|
||||
|
||||
for (int i = 0; i < SCHFS_BPB; i++) {
|
||||
|
|
@ -133,7 +132,7 @@ kd_write(void *ctx, uint64_t blk, const void *in)
|
|||
|
||||
if (blk == 0)
|
||||
return -1;
|
||||
if (blk > 0xffffffffULL / SCHFS_BPB)
|
||||
if (blk > (~0ULL) / SCHFS_BPB)
|
||||
return -1;
|
||||
|
||||
// Straight through the buffer cache, with no log. The xv6 log exists to make
|
||||
|
|
|
|||
Loading…
Reference in a new issue