4.8 Failure Modes
This section consolidates the conditions under which a stratafs operation fails and the error each produces. The sections above remain authoritative for the conditions themselves.
4.8.1 Mount-time #
| Condition | Error |
|---|---|
| Caller lacks the access to resolve a stratum path or read its attributes | EACCES |
Empty stratum stack, or strata= absent | EINVAL |
| Stack longer than 16 strata | EINVAL |
More than one stratum carries create | EINVAL |
A stratum carries both create and ro | EINVAL |
| The same directory appears twice in the stack | EINVAL |
Any malformed strata= value (§4.2.2) | EINVAL |
strata= supplied on a remount | EINVAL |
| An allocation failure while parsing | ENOMEM |
A create-bearing stack established outside the initial user namespace, or without CAP_SYS_ADMIN there | EPERM |
| A stratum path names a non-directory | ENOTDIR |
A stratum is absent without am | ENOENT |
| A stratum lies within the mount point, or within another stratafs mount whose strata include this mount point | ELOOP |
| The composed stack reaches the kernel's maximum stacking depth | ELOOP |
| Sixteen consecutive collisions allocating a mount cookie | EAGAIN |
The option-only conditions are decided before any path is touched, and
the EPERM admission test before any path is resolved. The per-path
conditions follow. §4.2.3 records the one place the specified ordering
is not achieved.
4.8.2 Resolution #
| Condition | Error |
|---|---|
| No participating stratum holds the name | ENOENT |
| An ancestor of the path is masked by a non-directory provider | ENOTDIR |
| Operation requires a non-directory; provider is a directory | EISDIR |
| Traverse or list refused on any participating directory | EACCES |
| A stratum walk fails for a reason other than absence | that error |
A joined stratum path or child relative path exceeds PATH_MAX | ENAMETOOLONG |
| A task re-enters the same superblock while resolving | ELOOP |
4.8.3 Mutation #
| Condition | Error |
|---|---|
| Provider will not accept modification, and no create stratum has higher precedence | EROFS |
| Any mutation on a read-only-mounted stratafs | EROFS |
| Creation, unnamed-file creation, or unnamed-file link with no create stratum, or it absent | EROFS |
| Create stratum holds a path component as a non-directory | ENOTDIR |
| Exclusive creation where any stratum holds the name | EEXIST |
| Copy-up cannot preserve an extended attribute | EIO |
| Copy-up cannot preserve the descriptor | EACCES, EOPNOTSUPP, EINVAL, ESTALE or ENOMEM, as KACS reported it |
| Copy-up for a descriptor whose object is no longer the provider, or whose target name is taken at publication | ESTALE |
| Copy-up of a device node, FIFO or socket | EROFS |
| Unlink where the provider will not accept modification | EROFS, or EPERM where the provider inode is immutable |
| Rmdir where another stratum holds entries within | ENOTEMPTY |
| Rmdir or directory rename where list is refused on a participant | EACCES |
| Modifying a special file's mode, descriptor or extended attributes where its provider will not accept modification | EROFS |
| Establishing a shared write-capable mapping where routing yields read-only | EROFS |
| Replacing disposition where §4.5.4 would refuse the removal, or where a stratum above the create stratum would still hold the name | EROFS |
| Replacing disposition on anything but a regular file | EOPNOTSUPP |
| Rename where the source's provider will not accept modification | EROFS |
| Rename where a stratum above the source's provider provides the destination | EROFS |
| Rename where the source's provider does not hold the destination's directory | EXDEV |
| Rename of a directory containing entries from other strata | EXDEV |
| Rename of a non-directory onto a directory provider | EISDIR |
| Rename of a directory onto a non-directory provider | ENOTDIR |
| Rename onto a destination directory not empty across every stratum | ENOTEMPTY |
RENAME_NOREPLACE where any stratum holds the destination | EEXIST |
RENAME_EXCHANGE where the two names are not provided by one stratum that accepts modification | EROFS |
RENAME_EXCHANGE where another stratum holds entries under either directory name | EXDEV |
RENAME_WHITEOUT | EINVAL |
| Hard link whose source's provider will not accept modification, or does not hold the destination's directory | EXDEV |
| Hard link where any stratum holds the destination | EEXIST |
| Linking an unnamed file into a different mount | EXDEV |
| A dentry whose private state is missing, or whose provider identity no longer matches | ESTALE |
ioctl on a regular file | ENOTTY, or ENOIOCTLCMD for the compat form |
remap_file_range with flags outside dedupe and advisory | EINVAL |
4.8.4 Interface #
| Condition | Error |
|---|---|
| Set or remove of any reserved attribute | EPERM |
Read of a reserved attribute other than origin | ENODATA |
| Origin read where read-EA is refused on any participant | EACCES |
| Origin read into an undersized buffer | ERANGE |
| Freezing the filesystem | EOPNOTSUPP |
| Reading a mount's policy without TCB privilege | refused by KACS |
4.8.5 Intended divergences #
None of the following is a defect. Each is described above, and each follows from stratafs having no way to record that a name should be absent, or from a merged path standing for objects in more than one stratum.
- Removing a name may not remove it from the view. Where a lower stratum also holds the name, it becomes the provider and the name remains, now resolving to different content (§4.5.4).
- A name may be unremovable. Where the provider will not accept modification, removal fails however the caller is privileged (§4.5.4).
- Rename may be refused for an unmodified file. Where the source's provider will not accept modification, rename fails rather than silently copying (§4.5.5).
- Hard links may be refused within one directory. Where the
source's provider will not accept modification, linking fails with
EXDEV(§4.5.6). - An object's inode number may change. Where the provider for a path changes, a new inode is presented (§4.4.3).
- Two callers may hold non-contending locks on one path. Locks are held on the object a descriptor resolved to, so callers who opened either side of a change of provider — including one caused by a copy-up neither of them performed — have locked different objects (§4.5.7).
- Copy-up severs hard links. Two names that shared an object in a lower stratum, and compared equal by inode number, refer to different objects once one of them is written through the mount; only the written one is copied up (§4.5.2).
- An open may succeed where the first write then fails. Routing
happens when a modifying operation is performed, not at open, so an
open for writing against a provider that will not accept modification
succeeds and the
EROFSarrives at the write, the truncate, or the attempt to establish a shared writable mapping (§4.5.1). - A copy-up moves an object out from under descriptors already open on it. Only the descriptor whose operation caused the copy-up refers to the copy; others continue to refer to the original, and locks held on it stay there (§4.5.1, §4.5.7).
- A write may fail
ESTALEon a descriptor that was valid when opened. Where another descriptor, another mount, or a direct writer has since caused that name to be provided by a different object, a copy-up cannot proceed and the caller must reopen (§4.5.2). fstatandstatmay report different inode numbers for one file. After a copy-up, the descriptor that caused it keeps the inode it was opened against while a fresh resolution of the path yields a new one, so the two disagree for as long as that descriptor lives — though both name the copy (§4.4.3).- A directory's link count is always 1. The true count of subdirectories spans strata and cannot be maintained (§4.4.3).
- Directory positions do not survive a reopen. A
readdiroffset is an ordinal into a per-descriptor capture, carrying no provider cookie (§4.3.4).
Every one of the first four is the result of refusing to invent a hidden record — a whiteout — that would make an entry in someone else's directory unreachable without their knowledge. The alternative buys POSIX fidelity at the cost of a stratum no longer meaning what its owner wrote in it, which is the property §4.2.1 exists to protect.