Disks and mounts
Single-page view · as markdown
mount
Peios / Using Peios / Peiosutils / Disks and mounts
mount attaches a filesystem to the Peios mount tree. With no operands it instead lists what is currently mounted. It is a faithful reworking of the util-linux mount(8) surface for Peios, with two structural differences: Peios has no /etc/fstab and no /etc/mtab, so every mount is described entirely on the command line and live mount state is read from the kernel; and a mount can apply a KACS mount policy to the new filesystem at attach time (see Mount policies).
mount [-t TYPE] [-o OPTIONS] SOURCE TARGET
mount [-o remount,OPTIONS] TARGET
mount --bind|--rbind|--move SOURCE TARGET
mount --make-shared|--make-private|... TARGET
mount [-l] [-t TYPE]
Internally mount uses the fd-based mount API (fsopen / fsconfig / fsmount / move_mount, plus open_tree and mount_setattr), never the classic single-shot mount(2). This matters in one place you can see: when a mount fails, the kernel's fs_context message log is drained and printed as the reason, even without -v.
Operands and argument shapes #
Because there is no fstab to consult, operand resolution is strict:
- No operands, no verb — list mode (see below).
- Two operands —
SOURCE TARGET. - One operand — an error. In util-linux a lone operand is resolved through fstab; Peios has none, so a single operand cannot be turned into a
SOURCE TARGETpair. Supply both, or use--source/--target. - A lone target is valid only for
-o remountand for a standalone propagation change (--make-*), which act on an existing mount point.
--source SRC and --target DIR name the operands explicitly and may be combined with a single positional. --target-prefix DIR prepends DIR/ to the target after it is chosen. Options may be interspersed with operands (mount SRC -o ro TGT), matching util-linux.
Paths, -o key=value values, labels and UUIDs are handled as opaque byte strings, never assumed to be UTF-8; an embedded NUL is a usage error.
Canonicalisation #
By default source and target paths are canonicalised (made absolute, symlinks resolved). -c / --no-canonicalize disables that; X-mount.nocanonicalize[=source|target] is the -o form and can disable it for just one side. The final path handed to the kernel is protected against a TOCTOU symlink swap on its last component.
Operation modes (verbs) #
mount performs one of several operations. The structural verbs — bind, rbind, move, beneath and remount — are mutually exclusive with one another. A propagation change is not a structural verb: it may stand alone on a target, or trail another verb or a new mount in the same command (applied afterwards as one or more mount_setattr steps), and several may be combined.
| Verb | How to request it | What it does |
|---|---|---|
| New mount | mount [-t T] SRC TGT | Attach a fresh instance of the filesystem at SRC onto TGT. |
| Bind | -B / --bind, or -o bind | Make an existing subtree visible at a second location. |
| Recursive bind | -R / --rbind, or -o rbind | Bind a subtree together with every mount underneath it. |
| Move | -M / --move, or -o move | Relocate an existing mount to a new mount point. |
| Move beneath | --beneath SRC TGT | Attach SRC beneath the mount currently at TGT (the kernel enforces several constraints; violations surface as exit 32). |
| Remount | -o remount[,...] TGT | Change the options of an existing mount (see Remounting). |
| Propagation | --make-* / --make-r*, or the -o tokens below | Change how mount/unmount events propagate across a subtree. |
| List | mount / mount -l | Print the current mounts. |
Propagation flags #
Each of these sets the propagation type of the mount at the target. The --make-r* (and r-prefixed -o) forms apply recursively to the whole subtree; the recursive form is all-or-nothing (it either applies to the entire subtree or to none of it).
| Flag | -o token | Recursive flag | Recursive -o token | Meaning |
|---|---|---|---|---|
--make-shared | shared | --make-rshared | rshared | Events propagate to and from peer mounts. |
--make-slave | slave | --make-rslave | rslave | Events propagate in from the master but not back out. |
--make-private | private | --make-rprivate | rprivate | No propagation either way. |
--make-unbindable | unbindable | --make-runbindable | runbindable | Private, and cannot be bind-mounted. |
A freshly created mount, bind or move is private by default unless its destination's parent is shared, in which case it joins that peer group — the standard kernel rule.
Source specification #
| Form | Resolution |
|---|---|
Device path (/dev/sda1) | Used directly. |
-L LABEL / LABEL=, -U UUID / UUID=, PARTLABEL=, PARTUUID= | Resolved to a device via libblkid. No match is a mount failure (exit 32). |
| A directory or regular file | Used directly (a bind source or target; a file may be a bind target). |
A pseudo source (tmpfs, proc, sysfs, none, …) | Passed through; -t is required because it cannot be probed. |
| An image file | Attached through a loop device (see Loop devices). |
Filesystem type #
-t TYPE names the type explicitly. -t auto, or omitting -t entirely, asks libblkid to safely probe the source; an ambiguous or multiply-signed device is refused (exit 32) rather than guessed at. X-mount.auto-fstypes=LIST constrains the probe candidates. Type lists and no<type> negation are not accepted in the mounting path (they remain meaningful only as a listing filter).
The -o option language #
-o takes a comma-separated list of key or key=value tokens and is repeatable (all occurrences are joined). A key="..." double-quoted value protects embedded commas; the key=value split is on the first =. Every token is sorted into one of the following categories.
Per-mount attributes #
Applied to the mount itself. Each accepts its negation; ro/rw additionally accept a =vfs / =fs / =recursive scope qualifier (bare is =vfs, non-recursive; =fs targets the superblock read-only flag; =recursive applies to the whole subtree).
| Option | Effect |
|---|---|
ro / rw | Read-only / read-write. |
suid / nosuid | Honour / ignore set-user-ID bits. |
dev / nodev | Allow / disallow device nodes. |
exec / noexec | Allow / disallow execution. |
atime / noatime | Update / never update access times. |
relatime / norelatime | Relative-atime updates on or off. |
strictatime / nostrictatime | Strict-atime updates on or off. |
diratime / nodiratime | Directory access-time updates on or off. |
nosymfollow | Do not follow symlinks on this mount. There is no positive symfollow token — the attribute is cleared only via a remount mask. |
The atime tokens share a single mode field; the last one specified wins.
Superblock flags #
| Option | Effect |
|---|---|
sync / async | Synchronous / asynchronous writes. |
dirsync | Synchronous directory updates. |
lazytime / nolazytime | Lazy on-disk timestamp updates on or off. |
iversion / noiversion | Inode version counting on or off. |
silent / loud | Suppress or emit certain kernel messages. |
mand / nomand | Obsolete (removed from the kernel). Accepted and ignored with a note under -v. |
Filesystem-specific parameters #
Any token not recognised above is forwarded verbatim to the filesystem: key=value as a string parameter, a bare key as a flag. There is no built-in allow-list and no length limit; a rejection by the filesystem is reported with the offending key and the kernel's message.
For example, StrataFS takes its precedence-ordered directory stack through
strata=:
See StrataFS for the stack flags, merge
and write-routing model, and the stratafs inspection command.
Userspace-only tokens #
These never reach the filesystem. They include the meta-verbs remount, bind, rbind, move; the loop controls loop / loop=/dev/loopN, offset=, sizelimit= (numeric values accept K/M/G/T and KiB/MiB/… suffixes); the propagation tokens listed above; and defaults, which expands to rw,suid,dev,exec,async (later tokens override it).
Functional X-mount.* options #
| Option | Effect |
|---|---|
X-mount.mkdir[=mode] | Create the target directory if missing (default mode 0755; the alias of -m). |
X-mount.subdir=DIR | Attach subdirectory DIR of a freshly mounted filesystem at the target. Effective only for a new-instance mount; silently ignored (noted under -v) for bind/move/remount/propagation. |
X-mount.noloop | Suppress the implicit loop device for a regular-file source. |
X-mount.auto-fstypes=LIST | Constrain the -t auto probe to these types. |
X-mount.nocanonicalize[=source|target] | The -o form of -c; with =source or =target it disables canonicalisation for just that path. |
X-mount.idmap and X-mount.owner / group / mode are not supported and are rejected with a usage error: Peios ownership is SID/security-descriptor based, so the fix is to add a SID/ACE to the descriptor rather than remap or chown.
KACS mount policy #
This is the genuinely Peios-specific part of mount. A mount policy is a per-superblock setting that governs how FACS treats the filesystem; the full model is described in Mount policies and its detail pages. mount can set that policy at attach time:
| Option | Policy class |
|---|---|
-o policy=deny-missing | facs_deny_missing — a file with no SD is unreachable. |
-o policy=synth-ephemeral | facs_synthesize_ephemeral — a missing SD is synthesised in memory only. |
-o policy=synth-persist | facs_synthesize_persistent — a missing SD is synthesised and written back. |
--synth-sddl SDDL | Provide the mount-level SD template used during synthesis (only valid with a synth-* policy). |
policy=unmanaged is not user-settable; only the kernel sets the unmanaged class, for its own pseudo-filesystems. policy= is valid only on a new mount of a real filesystem — combining it with bind/move/remount/propagation, or with list mode, is a usage error. See Policy classes for what each class does and SD storage by filesystem for how the SD is physically stored.
The policy is applied to the detached filesystem before it is attached: if setting it fails, nothing is ever published with an unintended policy (no rollback needed). Because setting a mount policy is a SeTcbPrivilege-gated operation (see Managing mounts), a caller without that privilege gets a clean EPERM (exit 1) and no mount. --synth-sddl is validated client-side first — it must be well-formed SDDL and must include an owner.
Peios applies no coarse uid==0 check anywhere: the mount applet is not installed set-user-ID, and every privileged action is authorised per-operation by KACS.
Remounting #
-o remount changes the options of an existing mount without detaching it. Peios does not perform the util-linux "read the old flags and re-supply them" dance — the fd-based API applies deltas rather than resetting, so each remount touches only what you name. Per-mount attributes (ro/rw, nosuid, atime, …) are changed via mount_setattr; superblock flags, filesystem parameters and ro=fs/rw=fs go through the superblock reconfigure path. =recursive remounts the whole subtree, all-or-nothing.
A bind mount shares its source's superblock, so any superblock-level option on a bind remount (a Category-B flag, a filesystem parameter, or ro=fs/rw=fs) is refused as a usage error rather than silently mutating the shared superblock for every mount of that filesystem. Only per-mount VFS attributes are valid on a bind remount.
Loop devices #
A regular-file source is backed by a loop device automatically when the type is unspecified or the filesystem is recognised by libblkid; X-mount.noloop suppresses this. -o loop forces auto-allocation of a free device, loop=/dev/loopN names one, and offset= / sizelimit= select a region of the file (they imply loop and are an error against a real block device). A backing file already attached at the same offset and size is reused rather than doubly attached, to avoid corruption. Loops created by mount are auto-cleared by the kernel on unmount, so they do not leak; umount -d force-clears the rest (see umount).
Other flags #
| Flag | Effect |
|---|---|
-t, --types TYPE | Filesystem type, or auto. |
-o, --options LIST | Mount options (above); repeatable. |
-r, --ro, --read-only | Mount read-only (-o ro). |
-w, --rw, --read-write | Mount read-write and forbid the automatic read-only fallback on a write-protected device (-o rw). |
--source SRC / --target DIR | Name the operands explicitly. |
--target-prefix DIR | Prepend DIR/ to the target. |
-B, --bind / -R, --rbind / -M, --move / --beneath | The structural verbs. |
--make-*, --make-r* | Propagation changes. |
--exclusive | Force a unique superblock instance (no reuse). Meaningful only for multi-instance filesystems (e.g. tmpfs) or read-only block mounts; on an already-mounted writable block device it fails with EBUSY (exit 32). |
-m, --mkdir[=MODE] | Create the target directory if missing (default mode 0755). |
-L, --label LABEL / -U, --uuid UUID | Select the source by filesystem label / UUID. |
-c, --no-canonicalize | Do not canonicalise paths. |
-f, --fake | Dry run: parse, resolve and plan everything but skip the mount syscalls and the policy step. |
-v, --verbose | Narrate resolved values and each syscall; drain the kernel fs_context log. Repeatable but -vv is the same as -v. |
-l, --show-labels | In list mode, append each filesystem's label. |
--onlyonce | Skip the mount if it is already present (a driver-aware check against live mount state, not a naive string match). |
-N, --namespace NS | Operate inside mount namespace NS (a PID, an ns file path, or a named namespace). Source resolution happens in the caller's namespace; the mount lands in the target namespace. |
-i, --internal-only | Do not invoke a mount.<type> helper. |
-n, --no-mtab | Accepted and ignored (Peios has no mtab). |
--synth-sddl SDDL | KACS synth-policy template SD (above). |
-h, --help / -V, --version | Standard. |
No external mount helpers ship in this version, so a network or FUSE type fails with "no helper for type" (exit 1) — a clean deferral, not a crash.
List mode #
With no operands, mount prints one line per mount, read from /proc/self/mountinfo:
SOURCE on TARGET type FSTYPE (OPTIONS)
mount -t TYPE with no operands filters the list by filesystem type instead of mounting; here type lists (-t ext4,xfs) and no<type> negation (-t nosysfs) are honoured. -l appends [LABEL] to each line when a label is known.
Details of the rendering: the option field is the positional VFS-then-superblock merge with a coalesced ro/rw, not sorted; mountinfo octal escapes are decoded; control characters in the mount point become ?; and the source is shown as the kernel recorded it, with /dev/loopN resolved to its backing file and /dev/dm-N to /dev/mapper/<name>. The listing shows only mounts the caller's token may observe; a partial or empty view is correct, not an error, and the paths of filtered-out parents are never reconstructed.
For a device-oriented view of what is available to mount, use lsblk.
Exit status #
| Code | Meaning |
|---|---|
0 | Success. |
1 | Incorrect invocation or a permission denial — bad flags, mutually-exclusive verbs, a lone operand, an invalid policy= or --synth-sddl, an authorisation failure (EPERM/EACCES), an embedded NUL, or "no helper for type". |
2 | System error (out of memory, no free loop device, cannot fork). |
4 | Internal error (an invariant failure). |
8 | Interrupted (SIGINT), after signal-safe cleanup. |
32 | Mount failure — a syscall in the flow failed, a label/UUID had no match, a probe was undetermined, or a --beneath/move/--exclusive kernel refusal. |
126 | An external mount.<type> helper was found but failed to execute (moot until a helper ships). |
Code 16 (mtab) is never produced. Code 64 (some succeeded, some failed) only arises when several source arguments are given and at least one succeeds while another fails.
umount
Peios / Using Peios / Peiosutils / Disks and mounts
umount detaches a filesystem from the Peios mount tree. It is the counterpart of mount and, like it, reads live mount state from the kernel (/proc/self/mountinfo) rather than any /etc/mtab — Peios has none. Each operand is resolved against that live state and unmounted with umount2(2).
umount [-lfRA] [-dr] TARGET|SOURCE...
Operands and how they are resolved #
Each operand is either a mount point or a source:
- If the (canonicalised) operand is itself a mount point in the current mount table, it is unmounted directly. This is always unambiguous.
- Otherwise the operand is treated as a source and matched against the sources in the mount table. If it is mounted in exactly one place, that place is unmounted. If it is mounted in several places,
umountrefuses with an error naming the candidates — resolve it by naming a specific mount point, or use-Ato unmount all of them.
If an operand matches nothing, it is "not mounted": normally an error (exit 32), but -g makes that a success and -q suppresses the message.
Several operands may be given in one invocation, and options may be interspersed with them (umount /a -f /b). Paths are handled as opaque bytes; an embedded NUL is a usage error. By default each operand is canonicalised; -c disables that and additionally selects UMOUNT_NOFOLLOW so the kernel does not follow a symlink in the final component.
Recursive and all-targets unmounts #
Two flags expand a single operand into multiple unmounts. Within one operand the expansion stops on the first failure.
-R/--recursiveunmounts the target and everything mounted underneath it, including any over-mount stack at a single point, ordered deepest-first.-A/--all-targetsunmounts every mount point of the given source in the current mount namespace. This is the live-mountinfo "unmount everywhere" complement to source resolution; it is not an fstab feature.-A -Rtogether compose: for each mount point of the source, recurse underneath it.
-R and -r are mutually exclusive (combining them is a usage error, exit 1).
Flags #
| Flag | Effect |
|---|---|
-l, --lazy | Detach the filesystem now and clean up references later (MNT_DETACH). |
-f, --force | Force the unmount (MNT_FORCE), e.g. for an unreachable server. |
-R, --recursive | Unmount the target and everything under it (see above). |
-A, --all-targets | Unmount every mount point of the given source (see above). |
-d, --detach-loop | After unmounting, free the backing loop device. Best-effort and verified: it clears the device only if it still backs the mount just removed, so a recycled loop number is never clobbered. Usually redundant, since mount-created loops auto-clear on unmount. |
-r, --read-only | If the unmount fails, remount the filesystem read-only instead (via mount_setattr). Mutually exclusive with -R. |
-g, --graceful | Exit 0 when the target is absent or not mounted (rather than failing). Applied unconditionally. |
-q, --quiet | Suppress "not mounted" messages. |
-c, --no-canonicalize | Do not canonicalise paths; selects UMOUNT_NOFOLLOW. Applied unconditionally. |
-v, --verbose | Say what is being unmounted. Repeatable. |
-N, --namespace NS | Enter mount namespace NS (a PID, an ns file path, or a named namespace) before reading its mount table and unmounting. All work happens inside that namespace. |
-n, --no-mtab | Accepted and ignored (no mtab on Peios). |
-i, --internal-only | Do not invoke a umount.<type> helper (none ship). |
--fake | Dry run: resolve operands and report, but skip the unmount syscalls. |
-h, --help / -V, --version | Standard. |
The umount2 flag mapping is direct: -l → MNT_DETACH, -f → MNT_FORCE, -c (or a symlinked final component) → UMOUNT_NOFOLLOW. MNT_EXPIRE is deliberately not exposed, matching util-linux.
On privilege #
As with mount, there is no coarse uid==0 check: the applet is not set-user-ID and every unmount is authorised per-operation by KACS. Where util-linux silently suppresses an option for non-root users (-c, and -g's effectiveness), Peios applies it unconditionally.
Exit status #
| Code | Meaning |
|---|---|
0 | Success (or a -g no-op on an absent target). |
1 | Incorrect invocation or a permission denial — including -R with -r, a missing operand, an ambiguous source, an embedded NUL, or an authorisation failure. |
2 | System error (e.g. cannot read the mount table). |
8 | Interrupted (SIGINT). |
32 | Unmount failed, or the target is not mounted (unless -g). |
64 | Several source/target arguments were given and at least one succeeded while another failed. |
126 | An external umount.<type> helper was found but failed to execute (moot until a helper ships). |
A single -R / -A / -A -R invocation stops on the first failure and yields 32; the aggregate 64 only appears across multiple top-level arguments. To see what is currently mounted before unmounting, use mount with no arguments or lsblk.
lsblk
Peios / Using Peios / Peiosutils / Disks and mounts
lsblk lists the block devices on the system and their relationships — disks, their partitions, and the device-mapper and loop devices layered on top. It is the device-oriented companion to mount: where mount with no arguments shows what is mounted, lsblk shows what is available to mount and what filesystem sits on each device.
lsblk [options] [DEVICE...]
By default it prints a tree, one row per device with children indented beneath their parent. Given one or more DEVICE operands (a name like sda, a full path like /dev/sda, or anything resolving to a device node), it re-roots the output at those devices.
Where the data comes from #
Each column is sourced from one of four places, and any that cannot be read degrades to an empty cell rather than aborting the run:
- sysfs (
/sys/block) — the device tree, sizes, and the topology/hardware columns. Peios leaves/sys/blockunpatched, so this is the standard no-udev path. - libblkid — filesystem identity:
FSTYPE,FSVER,UUID,LABEL, and the partition-table columns. libblkid is opened at runtime. - The device node's security descriptor —
OWNERandMODE, read the same wayls -lreads them. - The
/dev/disk/by-*symlink farm —ID-LINK. Populated by the device manager once it has run; there is deliberately no/run/udev/dataparser, so the column reads the links themselves and is empty in the initramfs, where no device manager runs.
Output modes #
The mode selects how the rows are formatted; it does not change which columns are shown.
| Flag | Mode |
|---|---|
| (default) | Indented tree. |
-l, --list | Flat list — the same columns, no tree glyphs. |
-J, --json | JSON. Flag columns render as bare booleans and MOUNTPOINTS as an array; children nest under a children key. |
-P, --pairs | KEY="value" pairs, one device per line. |
-r, --raw | Raw, space-separated. Values that could contain a space or control character are hex-escaped (\xNN) so fields stay parseable. |
-T, --tree[=COLUMN] | Force tree output even alongside -l, optionally attaching the tree glyphs to COLUMN instead of NAME. |
Columns #
With no column flag, lsblk prints the default set: NAME, MAJ:MIN, RM, SIZE, RO, TYPE, MOUNTPOINTS. Three flags swap in a preset, and -o names an explicit list (which wins over all of them):
| Flag | Column set |
|---|---|
-o, --output LIST | Exactly the comma-separated columns named (case-insensitive; an unknown name is a usage error). |
-O, --output-all | Every available column. |
-f, --fs | Filesystem view: NAME, FSTYPE, FSVER, LABEL, UUID, MOUNTPOINTS. |
-m, --perms | Permissions view: NAME, SIZE, OWNER, MODE. |
The available columns are NAME, KNAME, PATH, MAJ:MIN, FSTYPE, FSVER, LABEL, UUID, PTUUID, PTTYPE, PARTTYPE, PARTLABEL, PARTUUID, MOUNTPOINT, MOUNTPOINTS, SIZE, RO, RM, HOTPLUG, TYPE, OWNER, MODE, MODEL, VENDOR, REV, SERIAL, TRAN, HCTL, ALIGNMENT, MIN-IO, OPT-IO, PHY-SEC, LOG-SEC, STATE, ROTA, SCHED, PKNAME, and ID-LINK.
The OWNER and MODE columns #
OWNER and MODE describe the device node, not the filesystem on it, and they mirror ls -l exactly — there is no GROUP column and no POSIX permission bits, because access to a device node is governed by its security descriptor, not by a mode. OWNER is the owner SID (S-1-…); MODE is a three-character [type][x][+]: the device-type character (b for a block device, c for a character device), an x slot (never set for a block device), and a + when the DACL is inheritance-protected. When the SD cannot be read — for instance on a non-Peios host with no KACS syscalls — OWNER shows ? and MODE degrades honestly.
Filtering, sorting and shaping #
| Flag | Effect |
|---|---|
-a, --all | Include empty (zero-size) devices, which are hidden by default. |
-d, --nodeps | Do not print a device's holders or slaves (drop the children). |
-I, --include LIST | Show only devices with these major numbers (comma-separated). |
-e, --exclude LIST | Exclude devices by major number. The default is 1 (RAM disks); an explicit -e replaces that default, and -a clears exclusions entirely. |
-s, --inverse | Print dependencies in inverse order (holders above the devices they depend on). |
-M, --merge | Collapse a subtree shared by several parents (a multipath device) to a single occurrence. |
-E, --dedup COLUMN | Drop rows whose COLUMN value duplicates an earlier one. |
-x, --sort COLUMN | Sort siblings by COLUMN (numeric columns sort by value, not text). |
Formatting #
| Flag | Effect |
|---|---|
-b, --bytes | Print SIZE as an exact byte count instead of a human-readable value. |
-p, --paths | Print full /dev paths in the NAME column. |
-n, --noheadings | Omit the header row. |
-i, --ascii | Draw the tree with ASCII characters instead of box-drawing glyphs. |
-y, --shell | Render column keys shell-safe (MAJ:MIN becomes MAJ_MIN). |
-w, --width NUM | Truncate each table row to NUM columns wide. |
--sysroot DIR | Read sysfs, the mount table and /dev from DIR instead of / (chiefly for testing against a fixture). |
-h, --help / -V, --version | Standard. |
Exit status #
| Code | Meaning |
|---|---|
0 | Success. |
1 | Incorrect invocation (an unknown column, a malformed major-number or width value) or a failed run (for example, /sys/block is unreadable). |
lsblk uses this single non-zero code, matching util-linux. A per-device read failure is not fatal: it degrades the affected columns to empty or ? and the run continues. A broken output pipe (piping into head, for instance) is treated as success.