581 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			581 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| =====================
 | |
| 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 "autofs" 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 "autofs".
 | |
| 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".
 | |
| 
 | |
| "autofs" 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 is based on a master map. This master
 | |
| map is consulted by autofs to determine which directories are mount
 | |
| points. Mount points can be *direct*/*indirect*/*offset*.
 | |
| On most systems, the default master map is located at */etc/auto.master*.
 | |
| 
 | |
| 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 behaviours 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 enter the
 | |
| mounted filesystem, otherwise it 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 mechanism 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
 | |
| over 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.  autofs 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 particular, `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 used slightly
 | |
| differently.  The field is updated at mount time and during expire
 | |
| checks if it is found to be in use (ie. open file descriptor or
 | |
| process working directory) and during path walks. The update done
 | |
| during path walks prevents frequent expire and immediate mount of
 | |
| frequently accessed automounts. But in the case where a GUI continually
 | |
| access or an application frequently scans an autofs directory tree
 | |
| there can be an accumulation of mounts that aren't actually being
 | |
| used. To cater for this case the "`strictexpire`" autofs mount option
 | |
| can be used to avoid the "`last_used`" update on path walk thereby
 | |
| preventing this apparent inability to expire mounts that aren't
 | |
| really in use.
 | |
| 
 | |
| 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 was originally intended for compatibility with version 4 of autofs
 | |
| and should be considered as deprecated for Sun Format automount maps.
 | |
| However, it may be used again for amd format mount maps (which are
 | |
| generally indirect maps) because the amd automounter allows for the
 | |
| setting of an expire timeout for individual mounts. But there are
 | |
| some difficulties in making the needed changes for this.
 | |
| 
 | |
| 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 `automount(8)`
 | |
| 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 is 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 {
 | |
| 		struct autofs_packet_hdr hdr;
 | |
| 		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];
 | |
|         };
 | |
| 
 | |
| And the format of the header is::
 | |
| 
 | |
| 	struct autofs_packet_hdr {
 | |
| 		int proto_version;		/* Protocol version */
 | |
| 		int type;			/* Type of packet */
 | |
| 	};
 | |
| 
 | |
| 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 with 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.
 | |
| - **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
 | |
| 	used 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 {
 | |
| 			struct autofs_packet_hdr hdr;
 | |
| 			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_FORCED** causes the in use status to be ignored
 | |
| 	and objects are expired ieven if they are in use. This assumes
 | |
| 	that the daemon has requested this because it is capable of
 | |
| 	performing the umount.
 | |
| 
 | |
| 	**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 `autofs-mount-control.txt`, and are summarised 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 */
 | |
| 
 | |
| 		/* Command parameters */
 | |
| 		union {
 | |
| 			struct args_protover		protover;
 | |
| 			struct args_protosubver		protosubver;
 | |
| 			struct args_openmount		openmount;
 | |
| 			struct args_ready		ready;
 | |
| 			struct args_fail		fail;
 | |
| 			struct args_setpipefd		setpipefd;
 | |
| 			struct args_timeout		timeout;
 | |
| 			struct args_requester		requester;
 | |
| 			struct args_expire		expire;
 | |
| 			struct args_askumount		askumount;
 | |
| 			struct args_ismountpoint	ismountpoint;
 | |
| 		};
 | |
| 
 | |
|                 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 `openmount.devid`.
 | |
| 	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 `setpipefd.pipefd` 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.
 | |
| 	On successful return, `requester.uid` and `requester.gid` 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 `fail.status`
 | |
| 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`.
 | |
| 
 | |
| The "ignore" mount option
 | |
| =========================
 | |
| 
 | |
| The "ignore" mount option can be used to provide a generic indicator
 | |
| to applications that the mount entry should be ignored when displaying
 | |
| mount information.
 | |
| 
 | |
| In other OSes that provide autofs and that provide a mount list to user
 | |
| space based on the kernel mount list a no-op mount option ("ignore" is
 | |
| the one use on the most common OSes) is allowed so that autofs file
 | |
| system users can optionally use it.
 | |
| 
 | |
| This is intended to be used by user space programs to exclude autofs
 | |
| mounts from consideration when reading the mounts list.
 | |
| 
 | |
| 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 manage 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
 |