Files
fds-os/docs/data.md
T
2026-09-21 22:29:23 +08:00

6.3 KiB

Writable DATA and managed programs

Documentation index · Cartridges · Services

M7 implements writable DATA. Its sustained-write, safe-eject and surrounding image regression checks passed in the ARM VM. A DATA cartridge uses a GPT partition named FDS_DATA, ext4, and a validated /FDS/CARTRIDGE.TOML declaring class data and writable = true. Use the M9 media tools to create new DATA media. The virtual tests construct disposable image files and never format a workstation disk.

Where your files live

/home/fds remains a temporary home, whether DATA is present or absent. Its contents disappear at power-off. Persistent user files belong under /data. Separating these paths lets you eject DATA without hiding the active shell's home directory or substituting another cartridge underneath it.

After inserting a DATA cartridge into a configured bay:

fds bays
fds cartridge 2
ls /data

If exactly one valid DATA candidate is available and none is active, the daemon activates it at /data. The filesystem must grant UID/GID 1000 the intended write permissions; insertion does not recursively change ownership of user files. M9's DATA formatter supplies that ownership for fresh media.

An active DATA session stays attached to its current cartridge when another is inserted. If a discovery snapshot contains multiple candidates with none active, they remain read-only until you select one:

fds data use 4

Eject the existing active DATA before selecting a replacement. The daemon never changes /data underneath an active session. EMPTY, ERROR and SAFE states retain the meanings in the cartridge guide; MOUNTED READ WRITE means that the displayed DATA filesystem is available for user writes.

Run a program that participates in eject

Ordinary console commands work as usual. They are not automatically killed when you request eject: an open file or working directory may make eject fail as busy. For a background task that should stop when its DATA is ejected, use:

fds run 2 -- /usr/bin/bash -c 'date > /data/managed-example.txt'

This starts a background managed program and prints its process ID. It has no interactive input. Output goes to the bounded, volatile cartridge service log:

tail /run/log/cartridged/current
fds cartridge 2

The executable path must be absolute. The child starts with /data as its working directory, the ordinary FDS UID/GID, no supplementary groups, no effective capabilities, a small explicit environment, and no_new_privs. Programs cannot gain privileges through setuid executables. The limit is 256 managed processes per bay. This interface accepts healthy writable DATA; the desktop guide also explains M8's explicit PROGRAM-media launch interface.

A root-owned Linux cgroup tracks the program and its descendants, including children that outlive their parent. Cgroups are kernel process tracking, not a new init system or runtime package. The configured kernel already includes the required cgroup v2 and process-limit support. The daemon sets up its hierarchy independently of the console. See the kernel cgroup interface.

Eject and remove DATA

cd "$HOME"
fds eject 2

Eject checks for additional mounts, stops managed consumers, flushes the DATA filesystem with syncfs, and performs a normal unmount. Only successful completion produces SAFE. A retained filesystem descriptor observes writeback errors during the session. M10 additionally makes the filesystem read-only and checks writeback again before closing that descriptor for unmount, preventing an error-reporting gap when a busy mount needs a later retry. Linux's syncfs interface reports filesystem errors that must not be ignored.

Managed programs receive TERM first. The daemon waits on actual cgroup exit notifications; programs that have not exited after a one-second deadline are killed as a group, including newly forked descendants. A further bounded exit check must succeed. These are failure deadlines, not delays imposed on a program that has already stopped. Requesting eject therefore ends those background jobs; it does not promise that unfinished application work is completed.

An unmanaged busy shell/file, extra mount, failed flush or failed unmount prevents SAFE. Close the reported use and retry. A recorded DATA writeback fault requires investigation or recovery; a later successful call is not used to erase it and pretend the failed write succeeded. The daemon never uses lazy/forced unmount to claim successful eject. A successfully ejected insertion remains unmounted across a daemon restart until removal/reinsertion.

M10 records writable sessions and faults outside the daemon process. If it crashes before verified unmount, the same insertion stays quarantined and read-only on restart. A later flush cannot reconstruct the lost error history. See Shutdown and recovery records for the current implementation and its acceptance status.

Pulling DATA during writes is an error. The daemon stops its managed consumers, cleans up the vanished mount and logs that writes may have been lost. This path never produces SAFE and makes no filesystem-cleanliness promise. Use recovery inspection/repair before trusting media that was removed during I/O.

Build and verify on the workstation

After changing DATA code or image configuration, build fresh inputs in order:

make rootfs PROFILE=cli
make initramfs
make system-card
make data-test

The test boots disposable virtual media, writes continuously, verifies ordinary user privileges and descendant shutdown, checks busy and additional mounts, reopens persisted data, tests multiple candidates and simulates surprise removal. After safe eject it extracts the ext4 partition into an ordinary file, runs read-only e2fsck -fn, and compares the sustained-write payload byte-for-byte. No host mount or physical USB device is used.

Run make cartridge-test, make init-test, make boot-test and make console-test for the surrounding regressions. Test logs and VM evidence are written under out/. Real flash-controller caches, battery loss, USB power and physical Pi eject/shutdown latency remain hardware acceptance work.