olivier2222
09/11/2026, 8:29 PMJohn Knipper
09/11/2026, 8:33 PMnum and num + nblocks - 1, so "3024 - 3039" tells me the failing request was 16 sectors, 8192 bytes, starting at device sector 3024.
3024 is your partition's first sector. The handler computes first_device_sector = de_BlocksPerTrack * de_Surfaces * de_LowCyl at volume.c:97, and 63 Γ 16 Γ 3 = 3024, so the partition begins at cylinder 3. The FAT cache works in fixed 32-sector ranges (RANGE_SHIFT 5 in cache.c:62). The range holding the volume's first FAT sector (3025) has base 3008, which starts before the partition, so AccessDisk clamps it to num=3024, nblocks=16. That is why you get a 16-sector window at an address that is 16-aligned but not 32-aligned, and why it is the very first multi-sector transfer this volume ever attempts.
Now the driver side. nvme_io.c:73 refuses the request on length:
} else if ((len == 0) || (len > (1 << unit->au_Bus->ab_Dev->dev_mdts) * unit->au_Bus->ab_Dev->pagesize)) {
dev_mdts is taken straight from Identify Controller at nvme_controllerclass.c:420 with no interpretation, and pagesize is 4096 (PAGESHIFT 12, MPSMIN 0). In the NVMe spec, MDTS = 0 means there is no maximum transfer size. AROS reads it as a power of two unconditionally, so 0 becomes (1 << 0) * 4096 = one page. Every transfer over 4096 bytes gets IOERR_BADLENGTH.
The arithmetic pins this down rather than leaving it a guess: for an 8192-byte request to be refused, the cap has to be below 8192, and (1 << mdts) * 4096 < 8192 only when mdts == 0. So your controller reports MDTS 0 and AROS is treating "no limit" as "one page, 8 sectors".
Why only FAT breaks
nvme_busclass.c:616 sets DE_MAXTRANSFER from the same expression, so every partition on that drive advertises MaxTransfer 4096. SFS and FFS honour MaxTransfer and split their transfers, so your system partition keeps working. The FAT handler ignores MaxTransfer completely, AccessDisk never looks at it, so FAT walks straight into the cap. That asymmetry is the giveaway.
Why it lands in the same place after a reboot
Nothing random is involved. Mounting reads the FAT through the same cache, and first_fat_sector is 1 for FAT12/16, so the first cache fill is sector 3025 again, same clamp, same 8192 bytes (fat.c:51). On FAT32 the FSInfo read at first_device_sector + 1 (volume.c:381) does exactly the same thing. Since the error hit during format at 3024 rather than at 3040, your partition is under 512 MiB and got FAT16 (volume.c:495 picks FAT16 below 1024Γ1024 sectors).
Format also aborts at the first FAT block, so the boot sector is on disk but the FAT is never written. You are left with something that looks like a FAT16 volume and fails the moment anything reads its FAT.
Why Wanderer goes away
Two things stack up. ErrorMessage calls EasyRequestArgs and blocks the handler process until you answer, so every DOS packet to that volume stalls while the requester is up. And once any block is dirty, Cache_Flush puts the failed block back at the head of the dirty list, while HandleTimer calls UpdateDisk once a second (timer.c:95). So the requester returns every second, indefinitely. Retry can never succeed, because the size is refused deterministically before the command ever reaches the controller.
Confirming it in one line
The BADLENGTH bug() is not wrapped in D(), so it prints on a normal build. On a serial log or under sashimi you should see:
[NVME00] nvme_sector_rw: BADLENGTH (read 8192 bytes at block bd0, cmd 24, task 'FAT filesystem')
0xbd0 is 3024, cmd 24 is TD_READ64. If that line is there, it is MDTS and the fix is to treat mdts == 0 as unlimited, capped by the 16-bit NLB field. If you instead see BADADDRESS, or no line at all (meaning the controller itself completed with an error status), then I am wrong about the cause and I would look at the PRP list construction in nvme_prp.c next.
Worth knowing: no partition alignment will dodge this. The cap is 8 sectors and the cache always asks for 32, so aligning the partition just moves the failure from an 8192-byte request to a 16384-byte one.
Three nearby problems I noticed while reading, none of them your symptom: the bounds check at nvme_io.c:70 tests only the starting LBA against au_High, so a transfer starting inside the namespace but ending past it still gets submitted; cmdio.rw.length = (len >> au_SecShift) - 1 silently truncates a length that is not a whole number of LBAs; and pagesize is a UWORD in nvme_intern.h:159, so a controller reporting MPSMIN 4 would truncate 65536 to 0 and then fail every single transfer.olivier2222
09/11/2026, 9:43 PMolivier2222
09/11/2026, 9:47 PMolivier2222
09/11/2026, 9:47 PMolivier2222
09/11/2026, 9:48 PMJohn Knipper
09/11/2026, 9:56 PMolivier2222
09/11/2026, 10:07 PMolivier2222
09/11/2026, 10:07 PMolivier2222
09/11/2026, 10:08 PMJohn Knipper
09/11/2026, 10:13 PMolivier2222
09/11/2026, 10:43 PM