mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-22 20:23:57 +08:00
521 lines
23 KiB
Plaintext
521 lines
23 KiB
Plaintext
|
<head>
|
||
|
<style> p { max-width:50em} ol, ul {max-width: 40em}</style>
|
||
|
</head>
|
||
|
|
||
|
autofs - how it works
|
||
|
=====================
|
||
|
|
||
|
Purpose
|
||
|
-------
|
||
|
|
||
|
The goal of autofs is to provide on-demand mounting and race free
|
||
|
automatic unmounting of various other filesystems. This provides two
|
||
|
key advantages:
|
||
|
|
||
|
1. There is no need to delay boot until all filesystems that
|
||
|
might be needed are mounted. Processes that try to access those
|
||
|
slow filesystems might be delayed but other processes can
|
||
|
continue freely. This is particularly important for
|
||
|
network filesystems (e.g. NFS) or filesystems stored on
|
||
|
media with a media-changing robot.
|
||
|
|
||
|
2. The names and locations of filesystems can be stored in
|
||
|
a remote database and can change at any time. The content
|
||
|
in that data base at the time of access will be used to provide
|
||
|
a target for the access. The interpretation of names in the
|
||
|
filesystem can even be programmatic rather than database-backed,
|
||
|
allowing wildcards for example, and can vary based on the user who
|
||
|
first accessed a name.
|
||
|
|
||
|
Context
|
||
|
-------
|
||
|
|
||
|
The "autofs4" filesystem module is only one part of an autofs system.
|
||
|
There also needs to be a user-space program which looks up names
|
||
|
and mounts filesystems. This will often be the "automount" program,
|
||
|
though other tools including "systemd" can make use of "autofs4".
|
||
|
This document describes only the kernel module and the interactions
|
||
|
required with any user-space program. Subsequent text refers to this
|
||
|
as the "automount daemon" or simply "the daemon".
|
||
|
|
||
|
"autofs4" is a Linux kernel module with provides the "autofs"
|
||
|
filesystem type. Several "autofs" filesystems can be mounted and they
|
||
|
can each be managed separately, or all managed by the same daemon.
|
||
|
|
||
|
Content
|
||
|
-------
|
||
|
|
||
|
An autofs filesystem can contain 3 sorts of objects: directories,
|
||
|
symbolic links and mount traps. Mount traps are directories with
|
||
|
extra properties as described in the next section.
|
||
|
|
||
|
Objects can only be created by the automount daemon: symlinks are
|
||
|
created with a regular `symlink` system call, while directories and
|
||
|
mount traps are created with `mkdir`. The determination of whether a
|
||
|
directory should be a mount trap or not is quite _ad hoc_, largely for
|
||
|
historical reasons, and is determined in part by the
|
||
|
*direct*/*indirect*/*offset* mount options, and the *maxproto* mount option.
|
||
|
|
||
|
If neither the *direct* or *offset* mount options are given (so the
|
||
|
mount is considered to be *indirect*), then the root directory is
|
||
|
always a regular directory, otherwise it is a mount trap when it is
|
||
|
empty and a regular directory when not empty. Note that *direct* and
|
||
|
*offset* are treated identically so a concise summary is that the root
|
||
|
directory is a mount trap only if the filesystem is mounted *direct*
|
||
|
and the root is empty.
|
||
|
|
||
|
Directories created in the root directory are mount traps only if the
|
||
|
filesystem is mounted *indirect* and they are empty.
|
||
|
|
||
|
Directories further down the tree depend on the *maxproto* mount
|
||
|
option and particularly whether it is less than five or not.
|
||
|
When *maxproto* is five, no directories further down the
|
||
|
tree are ever mount traps, they are always regular directories. When
|
||
|
the *maxproto* is four (or three), these directories are mount traps
|
||
|
precisely when they are empty.
|
||
|
|
||
|
So: non-empty (i.e. non-leaf) directories are never mount traps. Empty
|
||
|
directories are sometimes mount traps, and sometimes not depending on
|
||
|
where in the tree they are (root, top level, or lower), the *maxproto*,
|
||
|
and whether the mount was *indirect* or not.
|
||
|
|
||
|
Mount Traps
|
||
|
---------------
|
||
|
|
||
|
A core element of the implementation of autofs is the Mount Traps
|
||
|
which are provided by the Linux VFS. Any directory provided by a
|
||
|
filesystem can be designated as a trap. This involves two separate
|
||
|
features that work together to allow autofs to do its job.
|
||
|
|
||
|
**DCACHE_NEED_AUTOMOUNT**
|
||
|
|
||
|
If a dentry has the DCACHE_NEED_AUTOMOUNT flag set (which gets set if
|
||
|
the inode has S_AUTOMOUNT set, or can be set directly) then it is
|
||
|
(potentially) a mount trap. Any access to this directory beyond a
|
||
|
"`stat`" will (normally) cause the `d_op->d_automount()` dentry operation
|
||
|
to be called. The task of this method is to find the filesystem that
|
||
|
should be mounted on the directory and to return it. The VFS is
|
||
|
responsible for actually mounting the root of this filesystem on the
|
||
|
directory.
|
||
|
|
||
|
autofs doesn't find the filesystem itself but sends a message to the
|
||
|
automount daemon asking it to find and mount the filesystem. The
|
||
|
autofs `d_automount` method then waits for the daemon to report that
|
||
|
everything is ready. It will then return "`NULL`" indicating that the
|
||
|
mount has already happened. The VFS doesn't try to mount anything but
|
||
|
follows down the mount that is already there.
|
||
|
|
||
|
This functionality is sufficient for some users of mount traps such
|
||
|
as NFS which creates traps so that mountpoints on the server can be
|
||
|
reflected on the client. However it is not sufficient for autofs. As
|
||
|
mounting onto a directory is considered to be "beyond a `stat`", the
|
||
|
automount daemon would not be able to mount a filesystem on the 'trap'
|
||
|
directory without some way to avoid getting caught in the trap. For
|
||
|
that purpose there is another flag.
|
||
|
|
||
|
**DCACHE_MANAGE_TRANSIT**
|
||
|
|
||
|
If a dentry has DCACHE_MANAGE_TRANSIT set then two very different but
|
||
|
related behaviors are invoked, both using the `d_op->d_manage()`
|
||
|
dentry operation.
|
||
|
|
||
|
Firstly, before checking to see if any filesystem is mounted on the
|
||
|
directory, d_manage() will be called with the `rcu_walk` parameter set
|
||
|
to `false`. It may return one of three things:
|
||
|
|
||
|
- A return value of zero indicates that there is nothing special
|
||
|
about this dentry and normal checks for mounts and automounts
|
||
|
should proceed.
|
||
|
|
||
|
autofs normally returns zero, but first waits for any
|
||
|
expiry (automatic unmounting of the mounted filesystem) to
|
||
|
complete. This avoids races.
|
||
|
|
||
|
- A return value of `-EISDIR` tells the VFS to ignore any mounts
|
||
|
on the directory and to not consider calling `->d_automount()`.
|
||
|
This effectively disables the **DCACHE_NEED_AUTOMOUNT** flag
|
||
|
causing the directory not be a mount trap after all.
|
||
|
|
||
|
autofs returns this if it detects that the process performing the
|
||
|
lookup is the automount daemon and that the mount has been
|
||
|
requested but has not yet completed. How it determines this is
|
||
|
discussed later. This allows the automount daemon not to get
|
||
|
caught in the mount trap.
|
||
|
|
||
|
There is a subtlety here. It is possible that a second autofs
|
||
|
filesystem can be mounted below the first and for both of them to
|
||
|
be managed by the same daemon. For the daemon to be able to mount
|
||
|
something on the second it must be able to "walk" down past the
|
||
|
first. This means that d_manage cannot *always* return -EISDIR for
|
||
|
the automount daemon. It must only return it when a mount has
|
||
|
been requested, but has not yet completed.
|
||
|
|
||
|
`d_manage` also returns `-EISDIR` if the dentry shouldn't be a
|
||
|
mount trap, either because it is a symbolic link or because it is
|
||
|
not empty.
|
||
|
|
||
|
- Any other negative value is treated as an error and returned
|
||
|
to the caller.
|
||
|
|
||
|
autofs can return
|
||
|
|
||
|
- -ENOENT if the automount daemon failed to mount anything,
|
||
|
- -ENOMEM if it ran out of memory,
|
||
|
- -EINTR if a signal arrived while waiting for expiry to
|
||
|
complete
|
||
|
- or any other error sent down by the automount daemon.
|
||
|
|
||
|
|
||
|
The second use case only occurs during an "RCU-walk" and so `rcu_walk`
|
||
|
will be set.
|
||
|
|
||
|
An RCU-walk is a fast and lightweight process for walking down a
|
||
|
filename path (i.e. it is like running on tip-toes). RCU-walk cannot
|
||
|
cope with all situations so when it finds a difficulty it falls back
|
||
|
to "REF-walk", which is slower but more robust.
|
||
|
|
||
|
RCU-walk will never call `->d_automount`; the filesystems must already
|
||
|
be mounted or RCU-walk cannot handle the path.
|
||
|
To determine if a mount-trap is safe for RCU-walk mode it calls
|
||
|
`->d_manage()` with `rcu_walk` set to `true`.
|
||
|
|
||
|
In this case `d_manage()` must avoid blocking and should avoid taking
|
||
|
spinlocks if at all possible. Its sole purpose is to determine if it
|
||
|
would be safe to follow down into any mounted directory and the only
|
||
|
reason that it might not be is if an expiry of the mount is
|
||
|
underway.
|
||
|
|
||
|
In the `rcu_walk` case, `d_manage()` cannot return -EISDIR to tell the
|
||
|
VFS that this is a directory that doesn't require d_automount. If
|
||
|
`rcu_walk` sees a dentry with DCACHE_NEED_AUTOMOUNT set but nothing
|
||
|
mounted, it *will* fall back to REF-walk. `d_manage()` cannot make the
|
||
|
VFS remain in RCU-walk mode, but can only tell it to get out of
|
||
|
RCU-walk mode by returning `-ECHILD`.
|
||
|
|
||
|
So `d_manage()`, when called with `rcu_walk` set, should either return
|
||
|
-ECHILD if there is any reason to believe it is unsafe to end the
|
||
|
mounted filesystem, and otherwise should return 0.
|
||
|
|
||
|
autofs will return `-ECHILD` if an expiry of the filesystem has been
|
||
|
initiated or is being considered, otherwise it returns 0.
|
||
|
|
||
|
|
||
|
Mountpoint expiry
|
||
|
-----------------
|
||
|
|
||
|
The VFS has a mechansim for automatically expiring unused mounts,
|
||
|
much as it can expire any unused dentry information from the dcache.
|
||
|
This is guided by the MNT_SHRINKABLE flag. This only applies to
|
||
|
mounts that were created by `d_automount()` returning a filesystem to be
|
||
|
mounted. As autofs doesn't return such a filesystem but leaves the
|
||
|
mounting to the automount daemon, it must involve the automount daemon
|
||
|
in unmounting as well. This also means that autofs has more control
|
||
|
of expiry.
|
||
|
|
||
|
The VFS also supports "expiry" of mounts using the MNT_EXPIRE flag to
|
||
|
the `umount` system call. Unmounting with MNT_EXPIRE will fail unless
|
||
|
a previous attempt had been made, and the filesystem has been inactive
|
||
|
and untouched since that previous attempt. autofs4 does not depend on
|
||
|
this but has its own internal tracking of whether filesystems were
|
||
|
recently used. This allows individual names in the autofs directory
|
||
|
to expire separately.
|
||
|
|
||
|
With version 4 of the protocol, the automount daemon can try to
|
||
|
unmount any filesystems mounted on the autofs filesystem or remove any
|
||
|
symbolic links or empty directories any time it likes. If the unmount
|
||
|
or removal is successful the filesystem will be returned to the state
|
||
|
it was before the mount or creation, so that any access of the name
|
||
|
will trigger normal auto-mount processing. In particlar, `rmdir` and
|
||
|
`unlink` do not leave negative entries in the dcache as a normal
|
||
|
filesystem would, so an attempt to access a recently-removed object is
|
||
|
passed to autofs for handling.
|
||
|
|
||
|
With version 5, this is not safe except for unmounting from top-level
|
||
|
directories. As lower-level directories are never mount traps, other
|
||
|
processes will see an empty directory as soon as the filesystem is
|
||
|
unmounted. So it is generally safest to use the autofs expiry
|
||
|
protocol described below.
|
||
|
|
||
|
Normally the daemon only wants to remove entries which haven't been
|
||
|
used for a while. For this purpose autofs maintains a "`last_used`"
|
||
|
time stamp on each directory or symlink. For symlinks it genuinely
|
||
|
does record the last time the symlink was "used" or followed to find
|
||
|
out where it points to. For directories the field is a slight
|
||
|
misnomer. It actually records the last time that autofs checked if
|
||
|
the directory or one of its descendents was busy and found that it
|
||
|
was. This is just as useful and doesn't require updating the field so
|
||
|
often.
|
||
|
|
||
|
The daemon is able to ask autofs if anything is due to be expired,
|
||
|
using an `ioctl` as discussed later. For a *direct* mount, autofs
|
||
|
considers if the entire mount-tree can be unmounted or not. For an
|
||
|
*indirect* mount, autofs considers each of the names in the top level
|
||
|
directory to determine if any of those can be unmounted and cleaned
|
||
|
up.
|
||
|
|
||
|
There is an option with indirect mounts to consider each of the leaves
|
||
|
that has been mounted on instead of considering the top-level names.
|
||
|
This is intended for compatability with version 4 of autofs and should
|
||
|
be considered as deprecated.
|
||
|
|
||
|
When autofs considers a directory it checks the `last_used` time and
|
||
|
compares it with the "timeout" value set when the filesystem was
|
||
|
mounted, though this check is ignored in some cases. It also checks if
|
||
|
the directory or anything below it is in use. For symbolic links,
|
||
|
only the `last_used` time is ever considered.
|
||
|
|
||
|
If both appear to support expiring the directory or symlink, an action
|
||
|
is taken.
|
||
|
|
||
|
There are two ways to ask autofs to consider expiry. The first is to
|
||
|
use the **AUTOFS_IOC_EXPIRE** ioctl. This only works for indirect
|
||
|
mounts. If it finds something in the root directory to expire it will
|
||
|
return the name of that thing. Once a name has been returned the
|
||
|
automount daemon needs to unmount any filesystems mounted below the
|
||
|
name normally. As described above, this is unsafe for non-toplevel
|
||
|
mounts in a version-5 autofs. For this reason the current `automountd`
|
||
|
does not use this ioctl.
|
||
|
|
||
|
The second mechanism uses either the **AUTOFS_DEV_IOCTL_EXPIRE_CMD** or
|
||
|
the **AUTOFS_IOC_EXPIRE_MULTI** ioctl. This will work for both direct and
|
||
|
indirect mounts. If it selects an object to expire, it will notify
|
||
|
the daemon using the notification mechanism described below. This
|
||
|
will block until the daemon acknowledges the expiry notification.
|
||
|
This implies that the "`EXPIRE`" ioctl must be sent from a different
|
||
|
thread than the one which handles notification.
|
||
|
|
||
|
While the ioctl is blocking, the entry is marked as "expiring" and
|
||
|
`d_manage` will block until the daemon affirms that the unmount has
|
||
|
completed (together with removing any directories that might have been
|
||
|
necessary), or has been aborted.
|
||
|
|
||
|
Communicating with autofs: detecting the daemon
|
||
|
-----------------------------------------------
|
||
|
|
||
|
There are several forms of communication between the automount daemon
|
||
|
and the filesystem. As we have already seen, the daemon can create and
|
||
|
remove directories and symlinks using normal filesystem operations.
|
||
|
autofs knows whether a process requesting some operation is the daemon
|
||
|
or not based on its process-group id number (see getpgid(1)).
|
||
|
|
||
|
When an autofs filesystem it mounted the pgid of the mounting
|
||
|
processes is recorded unless the "pgrp=" option is given, in which
|
||
|
case that number is recorded instead. Any request arriving from a
|
||
|
process in that process group is considered to come from the daemon.
|
||
|
If the daemon ever has to be stopped and restarted a new pgid can be
|
||
|
provided through an ioctl as will be described below.
|
||
|
|
||
|
Communicating with autofs: the event pipe
|
||
|
-----------------------------------------
|
||
|
|
||
|
When an autofs filesystem is mounted, the 'write' end of a pipe must
|
||
|
be passed using the 'fd=' mount option. autofs will write
|
||
|
notification messages to this pipe for the daemon to respond to.
|
||
|
For version 5, the format of the message is:
|
||
|
|
||
|
struct autofs_v5_packet {
|
||
|
int proto_version; /* Protocol version */
|
||
|
int type; /* Type of packet */
|
||
|
autofs_wqt_t wait_queue_token;
|
||
|
__u32 dev;
|
||
|
__u64 ino;
|
||
|
__u32 uid;
|
||
|
__u32 gid;
|
||
|
__u32 pid;
|
||
|
__u32 tgid;
|
||
|
__u32 len;
|
||
|
char name[NAME_MAX+1];
|
||
|
};
|
||
|
|
||
|
where the type is one of
|
||
|
|
||
|
autofs_ptype_missing_indirect
|
||
|
autofs_ptype_expire_indirect
|
||
|
autofs_ptype_missing_direct
|
||
|
autofs_ptype_expire_direct
|
||
|
|
||
|
so messages can indicate that a name is missing (something tried to
|
||
|
access it but it isn't there) or that it has been selected for expiry.
|
||
|
|
||
|
The pipe will be set to "packet mode" (equivalent to passing
|
||
|
`O_DIRECT`) to _pipe2(2)_ so that a read from the pipe will return at
|
||
|
most one packet, and any unread portion of a packet will be discarded.
|
||
|
|
||
|
The `wait_queue_token` is a unique number which can identify a
|
||
|
particular request to be acknowledged. When a message is sent over
|
||
|
the pipe the affected dentry is marked as either "active" or
|
||
|
"expiring" and other accesses to it block until the message is
|
||
|
acknowledged using one of the ioctls below and the relevant
|
||
|
`wait_queue_token`.
|
||
|
|
||
|
Communicating with autofs: root directory ioctls
|
||
|
------------------------------------------------
|
||
|
|
||
|
The root directory of an autofs filesystem will respond to a number of
|
||
|
ioctls. The process issuing the ioctl must have the CAP_SYS_ADMIN
|
||
|
capability, or must be the automount daemon.
|
||
|
|
||
|
The available ioctl commands are:
|
||
|
|
||
|
- **AUTOFS_IOC_READY**: a notification has been handled. The argument
|
||
|
to the ioctl command is the "wait_queue_token" number
|
||
|
corresponding to the notification being acknowledged.
|
||
|
- **AUTOFS_IOC_FAIL**: similar to above, but indicates failure with
|
||
|
the error code `ENOENT`.
|
||
|
- **AUTOFS_IOC_CATATONIC**: Causes the autofs to enter "catatonic"
|
||
|
mode meaning that it stops sending notifications to the daemon.
|
||
|
This mode is also entered if a write to the pipe fails.
|
||
|
- **AUTOFS_IOC_PROTOVER**: This returns the protocol version in use.
|
||
|
- **AUTOFS_IOC_PROTOSUBVER**: Returns the protocol sub-version which
|
||
|
is really a version number for the implementation. It is
|
||
|
currently 2.
|
||
|
- **AUTOFS_IOC_SETTIMEOUT**: This passes a pointer to an unsigned
|
||
|
long. The value is used to set the timeout for expiry, and
|
||
|
the current timeout value is stored back through the pointer.
|
||
|
- **AUTOFS_IOC_ASKUMOUNT**: Returns, in the pointed-to `int`, 1 if
|
||
|
the filesystem could be unmounted. This is only a hint as
|
||
|
the situation could change at any instant. This call can be
|
||
|
use to avoid a more expensive full unmount attempt.
|
||
|
- **AUTOFS_IOC_EXPIRE**: as described above, this asks if there is
|
||
|
anything suitable to expire. A pointer to a packet:
|
||
|
|
||
|
struct autofs_packet_expire_multi {
|
||
|
int proto_version; /* Protocol version */
|
||
|
int type; /* Type of packet */
|
||
|
autofs_wqt_t wait_queue_token;
|
||
|
int len;
|
||
|
char name[NAME_MAX+1];
|
||
|
};
|
||
|
|
||
|
is required. This is filled in with the name of something
|
||
|
that can be unmounted or removed. If nothing can be expired,
|
||
|
`errno` is set to `EAGAIN`. Even though a `wait_queue_token`
|
||
|
is present in the structure, no "wait queue" is established
|
||
|
and no acknowledgment is needed.
|
||
|
- **AUTOFS_IOC_EXPIRE_MULTI**: This is similar to
|
||
|
**AUTOFS_IOC_EXPIRE** except that it causes notification to be
|
||
|
sent to the daemon, and it blocks until the daemon acknowledges.
|
||
|
The argument is an integer which can contain two different flags.
|
||
|
|
||
|
**AUTOFS_EXP_IMMEDIATE** causes `last_used` time to be ignored
|
||
|
and objects are expired if the are not in use.
|
||
|
|
||
|
**AUTOFS_EXP_LEAVES** will select a leaf rather than a top-level
|
||
|
name to expire. This is only safe when *maxproto* is 4.
|
||
|
|
||
|
Communicating with autofs: char-device ioctls
|
||
|
---------------------------------------------
|
||
|
|
||
|
It is not always possible to open the root of an autofs filesystem,
|
||
|
particularly a *direct* mounted filesystem. If the automount daemon
|
||
|
is restarted there is no way for it to regain control of existing
|
||
|
mounts using any of the above communication channels. To address this
|
||
|
need there is a "miscellaneous" character device (major 10, minor 235)
|
||
|
which can be used to communicate directly with the autofs filesystem.
|
||
|
It requires CAP_SYS_ADMIN for access.
|
||
|
|
||
|
The `ioctl`s that can be used on this device are described in a separate
|
||
|
document `autofs4-mount-control.txt`, and are summarized briefly here.
|
||
|
Each ioctl is passed a pointer to an `autofs_dev_ioctl` structure:
|
||
|
|
||
|
struct autofs_dev_ioctl {
|
||
|
__u32 ver_major;
|
||
|
__u32 ver_minor;
|
||
|
__u32 size; /* total size of data passed in
|
||
|
* including this struct */
|
||
|
__s32 ioctlfd; /* automount command fd */
|
||
|
|
||
|
__u32 arg1; /* Command parameters */
|
||
|
__u32 arg2;
|
||
|
|
||
|
char path[0];
|
||
|
};
|
||
|
|
||
|
For the **OPEN_MOUNT** and **IS_MOUNTPOINT** commands, the target
|
||
|
filesystem is identified by the `path`. All other commands identify
|
||
|
the filesystem by the `ioctlfd` which is a file descriptor open on the
|
||
|
root, and which can be returned by **OPEN_MOUNT**.
|
||
|
|
||
|
The `ver_major` and `ver_minor` are in/out parameters which check that
|
||
|
the requested version is supported, and report the maximum version
|
||
|
that the kernel module can support.
|
||
|
|
||
|
Commands are:
|
||
|
|
||
|
- **AUTOFS_DEV_IOCTL_VERSION_CMD**: does nothing, except validate and
|
||
|
set version numbers.
|
||
|
- **AUTOFS_DEV_IOCTL_OPENMOUNT_CMD**: return an open file descriptor
|
||
|
on the root of an autofs filesystem. The filesystem is identified
|
||
|
by name and device number, which is stored in `arg1`. Device
|
||
|
numbers for existing filesystems can be found in
|
||
|
`/proc/self/mountinfo`.
|
||
|
- **AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD**: same as `close(ioctlfd)`.
|
||
|
- **AUTOFS_DEV_IOCTL_SETPIPEFD_CMD**: if the filesystem is in
|
||
|
catatonic mode, this can provide the write end of a new pipe
|
||
|
in `arg1` to re-establish communication with a daemon. The
|
||
|
process group of the calling process is used to identify the
|
||
|
daemon.
|
||
|
- **AUTOFS_DEV_IOCTL_REQUESTER_CMD**: `path` should be a
|
||
|
name within the filesystem that has been auto-mounted on.
|
||
|
arg1 is the dev number of the underlying autofs. On successful
|
||
|
return, `arg1` and `arg2` will be the UID and GID of the process
|
||
|
which triggered that mount.
|
||
|
|
||
|
- **AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD**: Check if path is a
|
||
|
mountpoint of a particular type - see separate documentation for
|
||
|
details.
|
||
|
|
||
|
- **AUTOFS_DEV_IOCTL_PROTOVER_CMD**:
|
||
|
- **AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD**:
|
||
|
- **AUTOFS_DEV_IOCTL_READY_CMD**:
|
||
|
- **AUTOFS_DEV_IOCTL_FAIL_CMD**:
|
||
|
- **AUTOFS_DEV_IOCTL_CATATONIC_CMD**:
|
||
|
- **AUTOFS_DEV_IOCTL_TIMEOUT_CMD**:
|
||
|
- **AUTOFS_DEV_IOCTL_EXPIRE_CMD**:
|
||
|
- **AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD**: These all have the same
|
||
|
function as the similarly named **AUTOFS_IOC** ioctls, except
|
||
|
that **FAIL** can be given an explicit error number in `arg1`
|
||
|
instead of assuming `ENOENT`, and this **EXPIRE** command
|
||
|
corresponds to **AUTOFS_IOC_EXPIRE_MULTI**.
|
||
|
|
||
|
Catatonic mode
|
||
|
--------------
|
||
|
|
||
|
As mentioned, an autofs mount can enter "catatonic" mode. This
|
||
|
happens if a write to the notification pipe fails, or if it is
|
||
|
explicitly requested by an `ioctl`.
|
||
|
|
||
|
When entering catatonic mode, the pipe is closed and any pending
|
||
|
notifications are acknowledged with the error `ENOENT`.
|
||
|
|
||
|
Once in catatonic mode attempts to access non-existing names will
|
||
|
result in `ENOENT` while attempts to access existing directories will
|
||
|
be treated in the same way as if they came from the daemon, so mount
|
||
|
traps will not fire.
|
||
|
|
||
|
When the filesystem is mounted a _uid_ and _gid_ can be given which
|
||
|
set the ownership of directories and symbolic links. When the
|
||
|
filesystem is in catatonic mode, any process with a matching UID can
|
||
|
create directories or symlinks in the root directory, but not in other
|
||
|
directories.
|
||
|
|
||
|
Catatonic mode can only be left via the
|
||
|
**AUTOFS_DEV_IOCTL_OPENMOUNT_CMD** ioctl on the `/dev/autofs`.
|
||
|
|
||
|
autofs, name spaces, and shared mounts
|
||
|
--------------------------------------
|
||
|
|
||
|
With bind mounts and name spaces it is possible for an autofs
|
||
|
filesystem to appear at multiple places in one or more filesystem
|
||
|
name spaces. For this to work sensibly, the autofs filesystem should
|
||
|
always be mounted "shared". e.g.
|
||
|
|
||
|
> `mount --make-shared /autofs/mount/point`
|
||
|
|
||
|
The automount daemon is only able to mange a single mount location for
|
||
|
an autofs filesystem and if mounts on that are not 'shared', other
|
||
|
locations will not behave as expected. In particular access to those
|
||
|
other locations will likely result in the `ELOOP` error
|
||
|
|
||
|
> Too many levels of symbolic links
|