fat/harness: filesystems coexist without the shared vfs name; two-volume proof (S3)
A second usb-storage device (a generated data volume, serial da7a0001, an empty FAT with no /system) plugged in beside the boot volume: the volume manager adopts both devices and spawns a confined fat per volume, each mounted at its own content id-path. The test surfaced a real coexistence bug. Every filesystem bound the single "vfs" contract name under /protocol; the second volume's fat lost the race, service.run refused-and-exited on the held name, and that volume never mounted. Clients don't reach filesystems by that name — fs_resolve routes a path to its backing endpoint through the kernel mount table by prefix — and nothing consumes "vfs", so the fix is to bind no shared name: the harness's service_name now defaults to null. This is the "this fades" the harness comment anticipated for the volume-manager era; a filesystem's endpoint still serves as its mount backend without a name. fat logs "is a data volume" for the non-system branch so the test can positively assert content-based detection. make-fat-image gains --serial/--label (default unchanged) so a second image gets a distinct id-path; the data image is generated per run, never committed. The case fails against the pre-fix harness (the data volume's fat exits on the refused bind) — toggle-demonstrated. Full suite 129/129 (128 + two-volumes); the single-volume path is unaffected by dropping the vestigial name bind.
This commit is contained in:
+31
-7
@@ -47,8 +47,14 @@ def fat32_geometry(total_sectors):
|
||||
|
||||
|
||||
class Fat32Image:
|
||||
def __init__(self, total_sectors):
|
||||
def __init__(self, total_sectors, volume_id=0x12345678, label="DANOS"):
|
||||
self.total_sectors = total_sectors
|
||||
# The FAT volume serial (its content identity — the /volumes/fat-<id>
|
||||
# mount path danos derives from it) and the display label. A second image
|
||||
# needs a distinct serial so its id-path does not collide with the boot
|
||||
# volume's.
|
||||
self.volume_id = volume_id & 0xFFFFFFFF
|
||||
self.label = label
|
||||
self.fat_size, self.cluster_count = fat32_geometry(total_sectors)
|
||||
if self.cluster_count < 65525:
|
||||
sys.exit(f"error: image too small for FAT32 ({self.cluster_count} clusters "
|
||||
@@ -146,8 +152,8 @@ class Fat32Image:
|
||||
0x80, # drive number
|
||||
0, # reserved
|
||||
0x29, # extended boot signature
|
||||
0x12345678, # volume id
|
||||
b"DANOS ", # volume label
|
||||
self.volume_id, # volume id
|
||||
self.label.encode("ascii", "replace")[:11].ljust(11, b" "), # volume label
|
||||
b"FAT32 ", # filesystem type
|
||||
)
|
||||
sector[510] = 0x55
|
||||
@@ -276,9 +282,9 @@ def build_tree(pairs):
|
||||
return root
|
||||
|
||||
|
||||
def build(out_path, size_mib, pairs):
|
||||
def build(out_path, size_mib, pairs, volume_id=0x12345678, label="DANOS"):
|
||||
total_sectors = size_mib * 1024 * 1024 // SECTOR
|
||||
image = Fat32Image(total_sectors)
|
||||
image = Fat32Image(total_sectors, volume_id, label)
|
||||
tree = build_tree(pairs)
|
||||
write_directory(image, 2, tree, 0, True)
|
||||
with open(out_path, "wb") as handle:
|
||||
@@ -350,14 +356,32 @@ def main(argv):
|
||||
if len(argv) == 3 and argv[1] == "--verify":
|
||||
verify(argv[2])
|
||||
return 0
|
||||
# Optional flags ahead of the positionals: --serial <hex> sets the FAT volume
|
||||
# id (the /volumes/fat-<id> content identity), --label <name> its display
|
||||
# label. A second FAT image passes a distinct --serial so its id-path cannot
|
||||
# collide with the boot volume's.
|
||||
argv = list(argv)
|
||||
volume_id = 0x12345678
|
||||
label = "DANOS"
|
||||
i = 1
|
||||
while i < len(argv):
|
||||
if argv[i] == "--serial" and i + 1 < len(argv):
|
||||
volume_id = int(argv[i + 1], 16)
|
||||
del argv[i:i + 2]
|
||||
elif argv[i] == "--label" and i + 1 < len(argv):
|
||||
label = argv[i + 1]
|
||||
del argv[i:i + 2]
|
||||
else:
|
||||
i += 1
|
||||
if len(argv) < 3 or (len(argv) - 3) % 2 != 0:
|
||||
sys.exit("usage: make-fat-image.py <out.img> <size-MiB> [<dest> <host>]...\n"
|
||||
sys.exit("usage: make-fat-image.py [--serial <hex>] [--label <name>] "
|
||||
"<out.img> <size-MiB> [<dest> <host>]...\n"
|
||||
" make-fat-image.py --verify <out.img>")
|
||||
out_path = argv[1]
|
||||
size_mib = int(argv[2])
|
||||
rest = argv[3:]
|
||||
pairs = [(rest[i], rest[i + 1]) for i in range(0, len(rest), 2)]
|
||||
build(out_path, size_mib, pairs)
|
||||
build(out_path, size_mib, pairs, volume_id, label)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user