fsopen(2)
Open a filesystem context: step one of the fd-based mount API (fsconfig, fsmount, move_mount).
- Since
- Linux 5.2check your kernel →
- glibc
- glibc 2.36
- System
- Linux
- Man page
- fsopen(2)
Synopsis
#include <sys/mount.h>
int fsopen(const char *fsname, unsigned int flags);
int fsconfig(int fd, unsigned int cmd, const char *key,
const void *value, int aux);
int fsmount(int fsfd, unsigned int flags, unsigned int attr_flags);
int move_mount(int from_dirfd, const char *from_path,
int to_dirfd, const char *to_path, unsigned int flags);Rod's take
mount(2) is one void pointer full of comma-separated wishes and a single undifferentiated EINVAL when one of them is wrong. The fd-based API that landed in Linux 5.2 builds a mount like any other kernel object: open a context, feed it options one fsconfig call at a time, commit, get a detached mount fd, attach it with move_mount. Per-option errors. A mount you can hand to another process over a Unix socket before deciding where it lives. No half-built rootfs flashing through the host namespace. More lines of C, sure. Worth every one of them.
Flags and arguments that matter
| Name | What it does |
|---|---|
| FSOPEN_CLOEXEC | fsopen(): set close-on-exec on the new filesystem context fd. |
| FSCONFIG_SET_FLAG | fsconfig(): set a boolean option with no value, e.g. "ro". |
| FSCONFIG_SET_STRING | fsconfig(): set a string option such as "source" or "errors". |
| FSCONFIG_SET_FD | fsconfig(): pass an open file descriptor as the option value. |
| FSCONFIG_CMD_CREATE | fsconfig(): commit the configuration and create (or reuse) the superblock. |
| FSCONFIG_CMD_CREATE_EXCLLinux 6.6 | Like FSCONFIG_CMD_CREATE but fail instead of silently reusing an existing matching superblock. |
| FSCONFIG_CMD_RECONFIGURE | fsconfig(): apply changes to an existing superblock (context from fspick(2) or a used fsmount context). |
| FSMOUNT_CLOEXEC | fsmount(): set close-on-exec on the returned detached mount fd. attr_flags takes MOUNT_ATTR_* values. |
| MOVE_MOUNT_F_EMPTY_PATH | move_mount(): from_path is empty, so the source is from_dirfd itself (e.g. the fd fsmount returned). |
| MOVE_MOUNT_BENEATHLinux 6.5 | move_mount(): mount beneath the top mount at the target instead of on top of it. |
Errors you will actually hit
| errno | Meaning |
|---|---|
| EPERM | fsopen(): caller lacks CAP_SYS_ADMIN. |
| ENODEV | fsopen(): the filesystem named by fsname isn't supported by this kernel. |
| EINVAL | Invalid flags; for fsmount(), also an invalid MOUNT_ATTR_* value in attr_flags. |
| EMFILE | The calling process has too many open files to create another fd. |
| EFAULT | fsopen(): fsname is NULL or points outside the accessible address space. |
Example
int fs = fsopen("ext4", FSOPEN_CLOEXEC);
if (fs < 0) err(1, "fsopen");
if (fsconfig(fs, FSCONFIG_SET_STRING, "source", "/dev/sdb1", 0) < 0 ||
fsconfig(fs, FSCONFIG_SET_FLAG, "ro", NULL, 0) < 0 ||
fsconfig(fs, FSCONFIG_SET_STRING, "errors", "remount-ro", 0) < 0 ||
fsconfig(fs, FSCONFIG_CMD_CREATE, NULL, NULL, 0) < 0)
err(1, "fsconfig");
int mnt = fsmount(fs, FSMOUNT_CLOEXEC, MOUNT_ATTR_NODEV);
if (mnt < 0) err(1, "fsmount");
close(fs);
if (move_mount(mnt, "", AT_FDCWD, "/mnt/data", MOVE_MOUNT_F_EMPTY_PATH) < 0)
err(1, "move_mount");
close(mnt);Trimmed from the full walkthrough in The new mount API: fsopen(2), fsmount(2), and doing it right.
BSD equivalent
FreeBSD: nmount(2) takes structured name/value option iovecs (FreeBSD 5.0), but it's still a one-shot call. OpenBSD: none; plain mount(2).
The long version, from the console
Sources
- fsopen(2), man7.org
- fsconfig(2), man7.org
- fsmount(2), man7.org
- move_mount(2), man7.org
- open_tree(2), man7.org
- nmount(2), FreeBSD
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
