Skip to content

filesys: route packets by unit; consolidate per-unit state into FilesysUnit#172

Merged
LinuxJedi merged 4 commits into
LinuxJedi:mainfrom
codewiz:feat/filesys-route-by-unit
Jul 13, 2026
Merged

filesys: route packets by unit; consolidate per-unit state into FilesysUnit#172
LinuxJedi merged 4 commits into
LinuxJedi:mainfrom
codewiz:feat/filesys-route-by-unit

Conversation

@codewiz

@codewiz codewiz commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Follow-up refactor on top of the merged HOSTFS filesys work (#159). No
behavior change intended; a manual boot with four mounts still works.

What changed

Route packets by explicit mount unit, not MsgPort address. The guest
handler reads its unit from the startup packet's DeviceNode once and passes
it in D2 on every trap. The host routes by that unit directly, dropping the
MsgPort -> unit map and the "first packet on a port" startup heuristic.
The MsgPort is still passed (A1) and stamped into the dn_Task/dol_Task/
fl_Task fields DOS uses to reach the handler, but is no longer a lookup
key. This also lines up with a possible future per-unit register interface,
where the unit is implicit in which register is written.

Consolidate per-unit state into a FilesysUnit struct. Several parallel
per-unit maps (volumes, device_nodes) plus globally-keyed locks/files become
a Vec<FilesysUnit> indexed by unit, each owning its MountSpec, handler
MsgPort, DeviceNode/volume addresses, files, and locks. Every lookup now goes
straight to the owning unit.

Move packet handling onto FilesysUnit; per-unit LockPool.
handle_packet and its helpers become methods on FilesysUnit;
FilesysHle::handle_packet shrinks to a dispatcher (bounds-check the unit,
delegate). Each unit owns a LockPool: a fixed, non-overlapping slice of the
board-window FileLock pool, sized by the board's maximum unit count and at
stable offsets, so a unit's lock addresses never move when units are
added/removed at runtime (the eventual mount/eject-on-the-fly goal).

Cap host mounts at 8 units, drop the guest-side clamp. 16 was excessive
(real controllers carry fewer). The guest no longer re-clamps the count:
the host writes and bounds it (board_image asserts, config rejects
over-limit), so MOUNT_MAX_COUNT is now host-only.

Testing

  • cargo test --lib filesys (6/6), cargo clippy --all-targets clean
  • Manual four-mount boot to Workbench, verified by the author

🤖 Generated with Claude Code

codewiz and others added 4 commits July 13, 2026 10:27
The handler reads its unit from the startup packet's DeviceNode once and
passes it in D2 on every trap. The host routes by that unit directly,
dropping the MsgPort->unit map and the "first packet on a port" startup
heuristic. The MsgPort is still passed (A1) and stamped into the
dn_Task/dol_Task/fl_Task fields DOS uses to reach the handler, but is no
longer a lookup key. This also lines up with a future per-unit register
interface, where the unit is implicit in which register is written.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
FilesysHle held several parallel per-unit maps (volumes, device_nodes)
plus locks/files keyed globally but scanned by unit. Replace them with a
Vec<FilesysUnit> indexed by unit, each owning its MountSpec, handler
MsgPort, DeviceNode/volume addresses, and its own files and locks. Now
that packets route by explicit unit, every lookup goes straight to the
owning unit instead of a map keyed by unit or a linear scan.

The handler MsgPort is captured into the unit at the startup packet, so
alloc_lock/build_volume_node read it from there and no longer take it as
an argument. The board-wide lock pool (free_slots, pool_next) and the
open-file cookie counter stay on FilesysHle, since they are shared across
units. Expansion init still rebuilds from a fresh default, preserving only
each unit's MountSpec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
handle_packet and its helpers (resolve, lock_path, fill_fib, dir_listing,
alloc_lock, build_volume_node) are now methods on FilesysUnit, operating on
their own unit's state. FilesysHle::handle_packet shrinks to a dispatcher:
bounds-check the unit, then delegate. board_base is passed into the unit
methods, so FilesysUnit needs no back-reference to the owner.

Each unit owns a LockPool: a fixed, non-overlapping slice of the
board-window FileLock pool. The slices are sized by the board's *maximum*
unit count and sit at stable offsets, so a unit's slice -- and the lock
addresses handed out from it -- never move when units are added or removed
at runtime (the eventual mount/eject-on-the-fly goal). The open-file cookie
counter likewise moves per-unit. LockRec drops its now-redundant unit
field, since every lock lives in its owning unit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
16 was excessive: real storage controllers carry fewer (SCSI's 7 targets
plus host, IDE two, floppies four). Halving the maximum also doubles each
unit's fixed board-window lock-pool slice to ~170 locks.

The guest handler no longer re-clamps the mount count against
MOUNT_MAX_COUNT: the host writes that count into the mount table and already
bounds it (board_image asserts, config rejects over-limit configs), so the
check was guarding against a state the host cannot produce. MOUNT_MAX_COUNT
is now host-only; the guest board header drops its duplicate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the HOSTFS/filesys packet routing and state management to be explicitly unit-indexed end-to-end (guest passes unit in D2; host dispatches by unit), while consolidating all per-mount runtime state into a FilesysUnit structure and introducing a per-unit lock-pool slice for stable guest lock addresses.

Changes:

  • Route filesys packets by mount unit (D2) instead of MsgPort -> unit inference.
  • Consolidate per-unit state into FilesysUnit and move packet handling/helpers onto the unit.
  • Cap host mounts at 8 units and remove the guest-side mount-count clamp.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated no comments.

File Description
src/filesys.rs Implements unit-based dispatch, introduces FilesysUnit + per-unit LockPool, and updates mount max to 8.
guest/services/handler.c Caches mount unit from the startup packet’s DeviceNode and passes it in D2 on every packet trap; removes guest clamp.
guest/services/copperline_board.h Removes the guest-visible MOUNT_MAX_COUNT define now that the host bounds mount count.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@LinuxJedi LinuxJedi merged commit dbf909d into LinuxJedi:main Jul 13, 2026
7 checks passed
@codewiz codewiz deleted the feat/filesys-route-by-unit branch July 13, 2026 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants