FDS/OS 1.0
This commit is contained in:
+138
@@ -0,0 +1,138 @@
|
||||
# Writable DATA and managed programs
|
||||
|
||||
[Documentation index](README.md) · [Cartridges](cartridges.md) · [Services](services.md)
|
||||
|
||||
M7 implements writable DATA. Its sustained-write, safe-eject and surrounding
|
||||
image regression checks [passed in the ARM VM](m7-validation.md). 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](media-tools.md) 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:
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
```sh
|
||||
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](cartridges.md); 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:
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
```sh
|
||||
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](desktop.md)
|
||||
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](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html).
|
||||
|
||||
## Eject and remove DATA
|
||||
|
||||
```sh
|
||||
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](https://man7.org/linux/man-pages/man2/syncfs.2.html)
|
||||
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](power.md#data-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:
|
||||
|
||||
```sh
|
||||
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.
|
||||
Reference in New Issue
Block a user