This is loosely based on the original documentation written by David
Howells and later maintained by Christian Brauner, but has been
rewritten to be more from a user perspective (as well as fixing a few
critical mistakes).
Co-authored-by: David Howells <dhowells@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Co-authored-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
---
man/man2/move_mount.2 | 646 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 646 insertions(+)
diff --git a/man/man2/move_mount.2 b/man/man2/move_mount.2
new file mode 100644
index 0000000000000000000000000000000000000000..f954f36c43c444afb167088cc665607dfeb10676
--- /dev/null
+++ b/man/man2/move_mount.2
@@ -0,0 +1,646 @@
+.\" Copyright, the authors of the Linux man-pages project
+.\"
+.\" SPDX-License-Identifier: Linux-man-pages-copyleft
+.\"
+.TH move_mount 2 (date) "Linux man-pages (unreleased)"
+.SH NAME
+move_mount \- move or attach mount object to filesystem
+.SH LIBRARY
+Standard C library
+.RI ( libc ,\~ \-lc )
+.SH SYNOPSIS
+.nf
+.BR "#include <fcntl.h>" " /* Definition of " AT_* " constants */"
+.B #include <sys/mount.h>
+.P
+.BI "int move_mount(int " from_dirfd ", const char *" from_path ,
+.BI " int " to_dirfd ", const char *" to_path ,
+.BI " unsigned int " flags );
+.fi
+.SH DESCRIPTION
+The
+.BR move_mount ()
+system call is part of
+the suite of file-descriptor-based mount facilities in Linux.
+.P
+.BR move_mount ()
+moves the mount object indicated by
+.I from_dirfd
+and
+.I from_path
+to the path indicated by
+.I to_dirfd
+and
+.IR to_path .
+The mount object being moved
+can be an existing mount point in the current mount namespace,
+or a detached mount object created by
+.BR fsmount (2)
+or
+.BR open_tree (2)
+with
+.BR \%OPEN_TREE_CLONE .
+.P
+To access the source mount object
+or the destination mount point,
+no permissions are required on the object itself,
+but if either pathname is supplied,
+execute (search) permission is required
+on all of the directories specified in
+.I from_path
+or
+.IR to_path .
+.P
+The calling process must have the
+.B \%CAP_SYS_ADMIN
+capability in order to move or attach a mount object.
+.P
+As with "*at()" system calls,
+.BR move_mount ()
+uses the
+.I from_dirfd
+and
+.I to_dirfd
+arguments
+in conjunction with the
+.I from_path
+and
+.I to_path
+arguments to determine the source and destination objects to operate on
+(respectively), as follows:
+.IP \[bu] 3
+If the pathname given in
+.I *_path
+is absolute, then
+the corresponding
+.I *_dirfd
+is ignored.
+.IP \[bu]
+If the pathname given in
+.I *_path
+is relative and
+the corresponding
+.I *_dirfd
+is the special value
+.BR \%AT_FDCWD ,
+then
+.I *_path
+is interpreted relative to
+the current working directory
+of the calling process (like
+.BR open (2)).
+.IP \[bu]
+If the pathname given in
+.I *_path
+is relative,
+then it is interpreted relative to
+the directory referred to by
+the corresponding file descriptor
+.I *_dirfd
+(rather than relative to
+the current working directory
+of the calling process,
+as is done by
+.BR open (2)
+for a relative pathname).
+In this case,
+the corresponding
+.I *_dirfd
+must be a directory
+that was opened for reading
+.RB ( O_RDONLY )
+or using the
+.B O_PATH
+flag.
+.IP \[bu]
+If
+.I *_path
+is an empty string,
+and
+.I flags
+contains the appropriate
+.BI \%MOVE_MOUNT_ * _EMPTY_PATH
+flag,
+then the corresponding file descriptor
+.I *_dirfd
+is operated on directly.
+In this case,
+the corresponding
+.I *_dirfd
+may refer to any type of file,
+not just a directory.
+.P
+See
+.BR openat (2)
+for an explanation of why the
+.I *_dirfd
+arguments are useful.
+.P
+.I flags
+can be used to control aspects of the path lookup
+for both the source and destination objects,
+as well as other properties of the mount operation.
+A value for
+.I flags
+is constructed by bitwise ORing
+zero or more of the following constants:
+.RS
+.TP
+.B MOVE_MOUNT_F_EMPTY_PATH
+If
+.I from_path
+is an empty string, operate on the file referred to by
+.I from_dirfd
+(which may have been obtained from
+.BR open (2),
+.BR fsmount (2),
+or
+.BR open_tree (2)).
+In this case,
+.I from_dirfd
+may refer to any type of file,
+not just a directory.
+If
+.I from_dirfd
+is
+.BR \%AT_FDCWD ,
+.BR move_mount ()
+will operate on the current working directory
+of the calling process.
+.IP
+This is the most common mechanism
+used to attach detached mount objects
+produced by
+.BR fsmount (2)
+and
+.BR open_tree (2)
+to a mount point.
+.TP
+.B MOVE_MOUNT_T_EMPTY_PATH
+As with
+.BR \%MOVE_MOUNT_F_EMPTY_PATH ,
+except operating on
+.I to_dirfd
+and
+.IR to_path .
+.TP
+.B MOVE_MOUNT_F_SYMLINKS
+If
+.I from_path
+references a symbolic link,
+then dereference it.
+The default behaviour for
+.BR move_mount ()
+is to
+.I not follow
+symbolic links.
+.TP
+.B MOVE_MOUNT_T_SYMLINKS
+As with
+.BR \%MOVE_MOUNT_F_SYMLINKS ,
+except operating on
+.I to_dirfd
+and
+.IR to_path .
+.TP
+.B MOVE_MOUNT_F_NO_AUTOMOUNT
+Do not automount the terminal ("basename") component of
+.I \%from_path
+if it is a directory that is an automount point.
+This allows a mount object
+that has an automount point at its root
+to be moved
+and prevents unintended triggering of an automount point.
+This flag has no effect
+if the automount point has already been mounted over.
+.TP
+.B MOVE_MOUNT_T_NO_AUTOMOUNT
+As with
+.BR \%MOVE_MOUNT_F_NO_AUTOMOUNT ,
+except operating on
+.I to_dirfd
+and
+.IR to_path .
+This allows an automount point to be manually mounted over.
+.TP
+.BR MOVE_MOUNT_SET_GROUP " (since Linux 5.15)"
+Add the attached private-propagation mount object indicated by
+.I to_dirfd
+and
+.I to_path
+into the mount propagation "peer group"
+of the attached non-private-propagation mount object indicated by
+.I from_dirfd
+and
+.IR from_path .
+.IP
+Unlike other
+.BR move_mount ()
+operations,
+this operation does not move or attach any mount objects.
+Instead, it only updates the metadata
+of attached mount objects.
+(Also, take careful note of
+the argument order\[em]\c
+the mount object being modified
+by this operation is the one specified by
+.I to_dirfd
+and
+.IR to_path .)
+.IP
+This makes it possible to first create a mount tree
+consisting only of private mounts
+and then configure the desired propagation layout afterwards.
+(See the "SHARED SUBTREES" section of
+.BR mount_namespaces (7)
+for more information about mount propagation and peer groups.)
+.TP
+.BR MOVE_MOUNT_BENEATH " (since Linux 6.5)"
+If the path indicated by
+.I to_dirfd
+and
+.I to_path
+is an existing mount object,
+rather than attaching or moving the mount object
+indicated by
+.I from_dirfd
+and
+.I from_path
+on top of the mount stack,
+attach or move it beneath the current top mount
+on the mount stack.
+.IP
+After using
+.BR \%MOVE_MOUNT_BENEATH ,
+it is possible to
+.BR umount (2)
+the top mount
+in order to reveal the mount object
+which was attached beneath it earlier.
+This allows for the seamless (and atomic) replacement
+of intricate mount trees,
+which can further be used
+to "upgrade" a mount tree with a newer version.
+.IP
+This operation has several restrictions:
+.RS
+.IP \[bu] 3
+Mount objects cannot be attached beneath the filesystem root,
+including cases where
+the filesystem root was configured by
+.BR chroot (2)
+or
+.BR pivot_root (2).
+To mount beneath the filesystem root,
+.BR pivot_root (2)
+must be used.
+.IP \[bu]
+The target path indicated by
+.I to_dirfd
+and
+.I to_path
+must not be a detached mount object,
+such as those produced by
+.BR open_tree (2)
+with
+.B \%OPEN_TREE_CLONE
+or
+.BR fsmount (2).
+.IP \[bu]
+The current top mount
+of the target path's mount stack
+and its parent mount
+must be in the calling process's mount namespace.
+.IP \[bu]
+The caller must have sufficient privileges
+to unmount the top mount
+of the target path's mount stack,
+to prove they have privileges
+to reveal the underlying mount.
+.IP \[bu]
+Mount propagation events triggered by this
+.BR move_mount ()
+operation
+(as described in
+.BR mount_namespaces (7))
+are calculated based on the parent mount
+of the current top mount
+of the target path's mount stack.
+.IP \[bu]
+The target path's mount
+cannot be an ancestor in the mount tree of
+the source mount object.
+.IP \[bu]
+The source mount object
+must not have any overmounts,
+otherwise it would be possible to create "shadow mounts"
+(i.e., two mounts mounted on the same parent mount at the same mount point).
+.IP \[bu]
+It is not possible to move a mount
+beneath a top mount
+if the parent mount
+of the current top mount
+propagates to the top mount itself.
+Otherwise,
+.B \%MOVE_MOUNT_BENEATH
+would cause the mount object
+to be propagated
+to the top mount
+from the parent mount,
+defeating the purpose of using
+.BR \%MOVE_MOUNT_BENEATH .
+.IP \[bu]
+It is not possible to move a mount
+beneath a top mount
+if the parent mount
+of the current top mount
+propagates to the mount object
+being mounted beneath.
+Otherwise, this would cause a similar propagation issue
+to the previous point,
+also defeating the purpose of using
+.BR \%MOVE_MOUNT_BENEATH .
+.RE
+.RE
+.P
+If
+.I from_dirfd
+is a mount object file descriptor and
+.BR move_mount ()
+is operating on it directly,
+.I from_dirfd
+will remain associated with the mount object after
+.BR move_mount ()
+succeeds,
+so you may repeatedly use
+.I from_dirfd
+with
+.BR move_mount (2)
+and/or "*at()" system calls
+as many times as necessary.
+.SH RETURN VALUE
+On success,
+.BR move_mount ()
+returns 0.
+On error, \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EACCES
+Search permission is denied
+for one of the directories
+in the path prefix of one of
+.I from_path
+or
+.IR to_path .
+(See also
+.BR path_resolution (7).)
+.TP
+.B EBADF
+One of
+.I from_dirfd
+or
+.I to_dirfd
+is not a valid file descriptor.
+.TP
+.B EFAULT
+One of
+.I from_path
+or
+.I to_path
+is NULL
+or a pointer to a location
+outside the calling process's accessible address space.
+.TP
+.B EINVAL
+Invalid flag specified in
+.IR flags .
+.TP
+.B EINVAL
+The path indicated by
+.I from_dirfd
+and
+.I from_path
+is not a mount object.
+.TP
+.B EINVAL
+The mount object type
+of the source mount object and target inode
+are not compatible
+(i.e., the source is a file but the target is a directory, or vice-versa).
+.TP
+.B EINVAL
+The source mount object or target path
+are not in the calling process's mount namespace
+(or an anonymous mount namespace of the calling process).
+.TP
+.B EINVAL
+The source mount object's parent mount
+has shared mount propagation,
+and thus cannot be moved
+(as described in
+.BR mount_namespaces (7)).
+.TP
+.B EINVAL
+The source mount has
+.B MS_UNBINDABLE
+child mounts
+but the target path
+resides on a mount tree with shared mount propagation,
+which would otherwise cause the unbindable mounts to be propagated
+(as described in
+.BR mount_namespaces (7)).
+.TP
+.B EINVAL
+.B \%MOVE_MOUNT_BENEATH
+was attempted,
+but one of the listed restrictions was violated.
+.TP
+.B ELOOP
+Too many symbolic links encountered
+when resolving one of
+.I from_path
+or
+.IR to_path .
+.TP
+.B ENAMETOOLONG
+One of
+.I from_path
+or
+.I to_path
+is longer than
+.BR PATH_MAX .
+.TP
+.B ENOENT
+A component of one of
+.I from_path
+or
+.I to_path
+does not exist.
+.TP
+.B ENOENT
+One of
+.I from_path
+or
+.I to_path
+is an empty string,
+but the corresponding
+.BI MOVE_MOUNT_ * _EMPTY_PATH
+flag is not specified in
+.IR flags .
+.TP
+.B ENOTDIR
+A component of the path prefix of one of
+.I from_path
+or
+.I to_path
+is not a directory,
+or one of
+.I from_path
+or
+.I to_path
+is relative
+and the corresponding
+.I from_dirfd
+or
+.I to_dirfd
+is a file descriptor referring to a file other than a directory.
+.TP
+.B ENOMEM
+The kernel could not allocate sufficient memory to complete the operation.
+.TP
+.B EPERM
+The calling process does not have the required
+.B \%CAP_SYS_ADMIN
+capability.
+.SH STANDARDS
+Linux.
+.SH HISTORY
+Linux 5.2.
+.\" commit 2db154b3ea8e14b04fee23e3fdfd5e9d17fbc6ae
+.\" commit 400913252d09f9cfb8cce33daee43167921fc343
+glibc 2.36.
+.SH EXAMPLES
+.BR move_mount ()
+can be used to move attached mounts like the following:
+.P
+.in +4n
+.EX
+move_mount(AT_FDCWD, "/a", AT_FDCWD, "/b", 0);
+.EE
+.in
+.P
+This would move the mount object mounted on
+.I /a
+to
+.IR /b .
+The above procedure is functionally equivalent to
+the following mount operation
+using
+.BR mount (2):
+.P
+.in +4n
+.EX
+mount("/a", "/b", NULL, MS_MOVE, NULL);
+.EE
+.in
+.P
+.BR move_mount ()
+can also be used in conjunction with file descriptors returned from
+.BR open_tree (2)
+or
+.BR open (2):
+.P
+.in +4n
+.EX
+int fd = open_tree(AT_FDCWD, "/mnt", 0); /* open("/mnt", O_PATH); */
+move_mount(fd, "", AT_FDCWD, "/mnt2", MOVE_MOUNT_F_EMPTY_PATH);
+move_mount(fd, "", AT_FDCWD, "/mnt3", MOVE_MOUNT_F_EMPTY_PATH);
+move_mount(fd, "", AT_FDCWD, "/mnt4", MOVE_MOUNT_F_EMPTY_PATH);
+.EE
+.in
+.P
+This would move the mount object mounted at
+.I /mnt
+to
+.IR /mnt2 ,
+then
+.IR /mnt3 ,
+and then
+.IR /mnt4 .
+.P
+If the source mount object
+indicated by
+.I from_dirfd
+and
+.I from_path
+is a detached mount object,
+.BR move_mount ()
+can be used to attach it to a mount point:
+.P
+.in +4n
+.EX
+int fsfd, mntfd;
+\&
+fsfd = fsopen("ext4", FSOPEN_CLOEXEC);
+fsconfig(fsfd, FSCONFIG_SET_STRING, "source", "/dev/sda1", 0);
+fsconfig(fsfd, FSCONFIG_SET_FLAG, "user_xattr", NULL, 0);
+fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0);
+mntfd = fsmount(fsfd, FSMOUNT_CLOEXEC, MOUNT_ATTR_NODEV);
+move_mount(mntfd, "", AT_FDCWD, "/home", MOVE_MOUNT_F_EMPTY_PATH);
+.EE
+.in
+.P
+This would create a new filesystem configuration context for ext4,
+configure it,
+create a detached mount object,
+and then attach it to
+.IR /home .
+The above procedure is functionally equivalent to
+the following mount operation
+using
+.BR mount (2):
+.P
+.in +4n
+.EX
+mount("/dev/sda1", "/home", "ext4", MS_NODEV, "user_xattr");
+.EE
+.in
+.P
+The same operation also works with detached bind-mounts created with
+.BR open_tree (2)
+with
+.BR OPEN_TREE_CLONE :
+.P
+.in +4n
+.EX
+int mntfd = open_tree(AT_FDCWD, "/home/cyphar", OPEN_TREE_CLONE);
+move_mount(mntfd, "", AT_FDCWD, "/root", MOVE_MOUNT_F_EMPTY_PATH);
+.EE
+.in
+.P
+This would create a new bind-mount of
+.I /home/cyphar
+as a detached mount object,
+and then attach it to
+.IR /root .
+The above procedure is functionally equivalent to
+the following mount operation
+using
+.BR mount (2):
+.P
+.in +4n
+.EX
+mount("/home/cyphar", "/root", NULL, MS_BIND, NULL);
+.EE
+.in
+.SH SEE ALSO
+.BR fsconfig (2),
+.BR fsmount (2),
+.BR fsopen (2),
+.BR fspick (2),
+.BR mount (2),
+.BR mount_setattr (2),
+.BR open_tree (2),
+.BR mount_namespaces (7)
--
2.51.0
Hi Aleksa, On Thu, Sep 25, 2025 at 01:31:27AM +1000, Aleksa Sarai wrote: > This is loosely based on the original documentation written by David > Howells and later maintained by Christian Brauner, but has been > rewritten to be more from a user perspective (as well as fixing a few > critical mistakes). > > Co-authored-by: David Howells <dhowells@redhat.com> > Signed-off-by: David Howells <dhowells@redhat.com> > Co-authored-by: Christian Brauner <brauner@kernel.org> > Signed-off-by: Christian Brauner <brauner@kernel.org> > Signed-off-by: Aleksa Sarai <cyphar@cyphar.com> Thanks! I've applied this patch, with some minor amendments (see below). <https://www.alejandro-colomar.es/src/alx/linux/man-pages/man-pages.git/commit/?h=contrib&id=eb37a3066ccce4f44ab69fae559016a524e4eac> > --- > man/man2/move_mount.2 | 646 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 646 insertions(+) > > diff --git a/man/man2/move_mount.2 b/man/man2/move_mount.2 > new file mode 100644 > index 0000000000000000000000000000000000000000..f954f36c43c444afb167088cc665607dfeb10676 > --- /dev/null > +++ b/man/man2/move_mount.2 > @@ -0,0 +1,646 @@ > +.\" Copyright, the authors of the Linux man-pages project > +.\" > +.\" SPDX-License-Identifier: Linux-man-pages-copyleft > +.\" > +.TH move_mount 2 (date) "Linux man-pages (unreleased)" > +.SH NAME > +move_mount \- move or attach mount object to filesystem > +.SH LIBRARY > +Standard C library > +.RI ( libc ,\~ \-lc ) > +.SH SYNOPSIS > +.nf > +.BR "#include <fcntl.h>" " /* Definition of " AT_* " constants */" > +.B #include <sys/mount.h> > +.P > +.BI "int move_mount(int " from_dirfd ", const char *" from_path , > +.BI " int " to_dirfd ", const char *" to_path , > +.BI " unsigned int " flags ); > +.fi > +.SH DESCRIPTION > +The > +.BR move_mount () > +system call is part of > +the suite of file-descriptor-based mount facilities in Linux. > +.P > +.BR move_mount () > +moves the mount object indicated by > +.I from_dirfd > +and > +.I from_path > +to the path indicated by > +.I to_dirfd > +and > +.IR to_path . > +The mount object being moved > +can be an existing mount point in the current mount namespace, > +or a detached mount object created by > +.BR fsmount (2) > +or > +.BR open_tree (2) > +with > +.BR \%OPEN_TREE_CLONE . > +.P > +To access the source mount object > +or the destination mount point, > +no permissions are required on the object itself, > +but if either pathname is supplied, > +execute (search) permission is required > +on all of the directories specified in > +.I from_path > +or > +.IR to_path . > +.P > +The calling process must have the > +.B \%CAP_SYS_ADMIN > +capability in order to move or attach a mount object. > +.P > +As with "*at()" system calls, > +.BR move_mount () > +uses the > +.I from_dirfd > +and > +.I to_dirfd > +arguments > +in conjunction with the > +.I from_path > +and > +.I to_path > +arguments to determine the source and destination objects to operate on > +(respectively), as follows: > +.IP \[bu] 3 > +If the pathname given in > +.I *_path In this case, where the non-variable part is already in italics, the variable part is written in roman, for distinguishing it. (See groff_man(7).) Have a lovely day! Alex > +is absolute, then > +the corresponding > +.I *_dirfd > +is ignored. > +.IP \[bu] > +If the pathname given in > +.I *_path > +is relative and > +the corresponding > +.I *_dirfd > +is the special value > +.BR \%AT_FDCWD , > +then > +.I *_path > +is interpreted relative to > +the current working directory > +of the calling process (like > +.BR open (2)). > +.IP \[bu] > +If the pathname given in > +.I *_path > +is relative, > +then it is interpreted relative to > +the directory referred to by > +the corresponding file descriptor > +.I *_dirfd > +(rather than relative to > +the current working directory > +of the calling process, > +as is done by > +.BR open (2) > +for a relative pathname). > +In this case, > +the corresponding > +.I *_dirfd > +must be a directory > +that was opened for reading > +.RB ( O_RDONLY ) > +or using the > +.B O_PATH > +flag. > +.IP \[bu] > +If > +.I *_path > +is an empty string, > +and > +.I flags > +contains the appropriate > +.BI \%MOVE_MOUNT_ * _EMPTY_PATH > +flag, > +then the corresponding file descriptor > +.I *_dirfd > +is operated on directly. > +In this case, > +the corresponding > +.I *_dirfd > +may refer to any type of file, > +not just a directory. > +.P > +See > +.BR openat (2) > +for an explanation of why the > +.I *_dirfd > +arguments are useful. > +.P > +.I flags > +can be used to control aspects of the path lookup > +for both the source and destination objects, > +as well as other properties of the mount operation. > +A value for > +.I flags > +is constructed by bitwise ORing > +zero or more of the following constants: > +.RS > +.TP > +.B MOVE_MOUNT_F_EMPTY_PATH > +If > +.I from_path > +is an empty string, operate on the file referred to by > +.I from_dirfd > +(which may have been obtained from > +.BR open (2), > +.BR fsmount (2), > +or > +.BR open_tree (2)). > +In this case, > +.I from_dirfd > +may refer to any type of file, > +not just a directory. > +If > +.I from_dirfd > +is > +.BR \%AT_FDCWD , > +.BR move_mount () > +will operate on the current working directory > +of the calling process. > +.IP > +This is the most common mechanism > +used to attach detached mount objects > +produced by > +.BR fsmount (2) > +and > +.BR open_tree (2) > +to a mount point. > +.TP > +.B MOVE_MOUNT_T_EMPTY_PATH > +As with > +.BR \%MOVE_MOUNT_F_EMPTY_PATH , > +except operating on > +.I to_dirfd > +and > +.IR to_path . > +.TP > +.B MOVE_MOUNT_F_SYMLINKS > +If > +.I from_path > +references a symbolic link, > +then dereference it. > +The default behaviour for > +.BR move_mount () > +is to > +.I not follow > +symbolic links. > +.TP > +.B MOVE_MOUNT_T_SYMLINKS > +As with > +.BR \%MOVE_MOUNT_F_SYMLINKS , > +except operating on > +.I to_dirfd > +and > +.IR to_path . > +.TP > +.B MOVE_MOUNT_F_NO_AUTOMOUNT > +Do not automount the terminal ("basename") component of > +.I \%from_path > +if it is a directory that is an automount point. > +This allows a mount object > +that has an automount point at its root > +to be moved > +and prevents unintended triggering of an automount point. > +This flag has no effect > +if the automount point has already been mounted over. > +.TP > +.B MOVE_MOUNT_T_NO_AUTOMOUNT > +As with > +.BR \%MOVE_MOUNT_F_NO_AUTOMOUNT , > +except operating on > +.I to_dirfd > +and > +.IR to_path . > +This allows an automount point to be manually mounted over. > +.TP > +.BR MOVE_MOUNT_SET_GROUP " (since Linux 5.15)" > +Add the attached private-propagation mount object indicated by > +.I to_dirfd > +and > +.I to_path > +into the mount propagation "peer group" > +of the attached non-private-propagation mount object indicated by > +.I from_dirfd > +and > +.IR from_path . > +.IP > +Unlike other > +.BR move_mount () > +operations, > +this operation does not move or attach any mount objects. > +Instead, it only updates the metadata > +of attached mount objects. > +(Also, take careful note of > +the argument order\[em]\c > +the mount object being modified > +by this operation is the one specified by > +.I to_dirfd > +and > +.IR to_path .) > +.IP > +This makes it possible to first create a mount tree > +consisting only of private mounts > +and then configure the desired propagation layout afterwards. > +(See the "SHARED SUBTREES" section of > +.BR mount_namespaces (7) > +for more information about mount propagation and peer groups.) > +.TP > +.BR MOVE_MOUNT_BENEATH " (since Linux 6.5)" > +If the path indicated by > +.I to_dirfd > +and > +.I to_path > +is an existing mount object, > +rather than attaching or moving the mount object > +indicated by > +.I from_dirfd > +and > +.I from_path > +on top of the mount stack, > +attach or move it beneath the current top mount > +on the mount stack. > +.IP > +After using > +.BR \%MOVE_MOUNT_BENEATH , > +it is possible to > +.BR umount (2) > +the top mount > +in order to reveal the mount object > +which was attached beneath it earlier. > +This allows for the seamless (and atomic) replacement > +of intricate mount trees, > +which can further be used > +to "upgrade" a mount tree with a newer version. > +.IP > +This operation has several restrictions: > +.RS > +.IP \[bu] 3 > +Mount objects cannot be attached beneath the filesystem root, > +including cases where > +the filesystem root was configured by > +.BR chroot (2) > +or > +.BR pivot_root (2). > +To mount beneath the filesystem root, > +.BR pivot_root (2) > +must be used. > +.IP \[bu] > +The target path indicated by > +.I to_dirfd > +and > +.I to_path > +must not be a detached mount object, > +such as those produced by > +.BR open_tree (2) > +with > +.B \%OPEN_TREE_CLONE > +or > +.BR fsmount (2). > +.IP \[bu] > +The current top mount > +of the target path's mount stack > +and its parent mount > +must be in the calling process's mount namespace. > +.IP \[bu] > +The caller must have sufficient privileges > +to unmount the top mount > +of the target path's mount stack, > +to prove they have privileges > +to reveal the underlying mount. > +.IP \[bu] > +Mount propagation events triggered by this > +.BR move_mount () > +operation > +(as described in > +.BR mount_namespaces (7)) > +are calculated based on the parent mount > +of the current top mount > +of the target path's mount stack. > +.IP \[bu] > +The target path's mount > +cannot be an ancestor in the mount tree of > +the source mount object. > +.IP \[bu] > +The source mount object > +must not have any overmounts, > +otherwise it would be possible to create "shadow mounts" > +(i.e., two mounts mounted on the same parent mount at the same mount point). > +.IP \[bu] > +It is not possible to move a mount > +beneath a top mount > +if the parent mount > +of the current top mount > +propagates to the top mount itself. > +Otherwise, > +.B \%MOVE_MOUNT_BENEATH > +would cause the mount object > +to be propagated > +to the top mount > +from the parent mount, > +defeating the purpose of using > +.BR \%MOVE_MOUNT_BENEATH . > +.IP \[bu] > +It is not possible to move a mount > +beneath a top mount > +if the parent mount > +of the current top mount > +propagates to the mount object > +being mounted beneath. > +Otherwise, this would cause a similar propagation issue > +to the previous point, > +also defeating the purpose of using > +.BR \%MOVE_MOUNT_BENEATH . > +.RE > +.RE > +.P > +If > +.I from_dirfd > +is a mount object file descriptor and > +.BR move_mount () > +is operating on it directly, > +.I from_dirfd > +will remain associated with the mount object after > +.BR move_mount () > +succeeds, > +so you may repeatedly use > +.I from_dirfd > +with > +.BR move_mount (2) > +and/or "*at()" system calls > +as many times as necessary. > +.SH RETURN VALUE > +On success, > +.BR move_mount () > +returns 0. > +On error, \-1 is returned, and > +.I errno > +is set to indicate the error. > +.SH ERRORS > +.TP > +.B EACCES > +Search permission is denied > +for one of the directories > +in the path prefix of one of > +.I from_path > +or > +.IR to_path . > +(See also > +.BR path_resolution (7).) > +.TP > +.B EBADF > +One of > +.I from_dirfd > +or > +.I to_dirfd > +is not a valid file descriptor. > +.TP > +.B EFAULT > +One of > +.I from_path > +or > +.I to_path > +is NULL > +or a pointer to a location > +outside the calling process's accessible address space. > +.TP > +.B EINVAL > +Invalid flag specified in > +.IR flags . > +.TP > +.B EINVAL > +The path indicated by > +.I from_dirfd > +and > +.I from_path > +is not a mount object. > +.TP > +.B EINVAL > +The mount object type > +of the source mount object and target inode > +are not compatible > +(i.e., the source is a file but the target is a directory, or vice-versa). > +.TP > +.B EINVAL > +The source mount object or target path > +are not in the calling process's mount namespace > +(or an anonymous mount namespace of the calling process). > +.TP > +.B EINVAL > +The source mount object's parent mount > +has shared mount propagation, > +and thus cannot be moved > +(as described in > +.BR mount_namespaces (7)). > +.TP > +.B EINVAL > +The source mount has > +.B MS_UNBINDABLE > +child mounts > +but the target path > +resides on a mount tree with shared mount propagation, > +which would otherwise cause the unbindable mounts to be propagated > +(as described in > +.BR mount_namespaces (7)). > +.TP > +.B EINVAL > +.B \%MOVE_MOUNT_BENEATH > +was attempted, > +but one of the listed restrictions was violated. > +.TP > +.B ELOOP > +Too many symbolic links encountered > +when resolving one of > +.I from_path > +or > +.IR to_path . > +.TP > +.B ENAMETOOLONG > +One of > +.I from_path > +or > +.I to_path > +is longer than > +.BR PATH_MAX . > +.TP > +.B ENOENT > +A component of one of > +.I from_path > +or > +.I to_path > +does not exist. > +.TP > +.B ENOENT > +One of > +.I from_path > +or > +.I to_path > +is an empty string, > +but the corresponding > +.BI MOVE_MOUNT_ * _EMPTY_PATH > +flag is not specified in > +.IR flags . > +.TP > +.B ENOTDIR > +A component of the path prefix of one of > +.I from_path > +or > +.I to_path > +is not a directory, > +or one of > +.I from_path > +or > +.I to_path > +is relative > +and the corresponding > +.I from_dirfd > +or > +.I to_dirfd > +is a file descriptor referring to a file other than a directory. > +.TP > +.B ENOMEM > +The kernel could not allocate sufficient memory to complete the operation. > +.TP > +.B EPERM > +The calling process does not have the required > +.B \%CAP_SYS_ADMIN > +capability. > +.SH STANDARDS > +Linux. > +.SH HISTORY > +Linux 5.2. > +.\" commit 2db154b3ea8e14b04fee23e3fdfd5e9d17fbc6ae > +.\" commit 400913252d09f9cfb8cce33daee43167921fc343 > +glibc 2.36. > +.SH EXAMPLES > +.BR move_mount () > +can be used to move attached mounts like the following: > +.P > +.in +4n > +.EX > +move_mount(AT_FDCWD, "/a", AT_FDCWD, "/b", 0); > +.EE > +.in > +.P > +This would move the mount object mounted on > +.I /a > +to > +.IR /b . > +The above procedure is functionally equivalent to > +the following mount operation > +using > +.BR mount (2): > +.P > +.in +4n > +.EX > +mount("/a", "/b", NULL, MS_MOVE, NULL); > +.EE > +.in > +.P > +.BR move_mount () > +can also be used in conjunction with file descriptors returned from > +.BR open_tree (2) > +or > +.BR open (2): > +.P > +.in +4n > +.EX > +int fd = open_tree(AT_FDCWD, "/mnt", 0); /* open("/mnt", O_PATH); */ > +move_mount(fd, "", AT_FDCWD, "/mnt2", MOVE_MOUNT_F_EMPTY_PATH); > +move_mount(fd, "", AT_FDCWD, "/mnt3", MOVE_MOUNT_F_EMPTY_PATH); > +move_mount(fd, "", AT_FDCWD, "/mnt4", MOVE_MOUNT_F_EMPTY_PATH); > +.EE > +.in > +.P > +This would move the mount object mounted at > +.I /mnt > +to > +.IR /mnt2 , > +then > +.IR /mnt3 , > +and then > +.IR /mnt4 . > +.P > +If the source mount object > +indicated by > +.I from_dirfd > +and > +.I from_path > +is a detached mount object, > +.BR move_mount () > +can be used to attach it to a mount point: > +.P > +.in +4n > +.EX > +int fsfd, mntfd; > +\& > +fsfd = fsopen("ext4", FSOPEN_CLOEXEC); > +fsconfig(fsfd, FSCONFIG_SET_STRING, "source", "/dev/sda1", 0); > +fsconfig(fsfd, FSCONFIG_SET_FLAG, "user_xattr", NULL, 0); > +fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0); > +mntfd = fsmount(fsfd, FSMOUNT_CLOEXEC, MOUNT_ATTR_NODEV); > +move_mount(mntfd, "", AT_FDCWD, "/home", MOVE_MOUNT_F_EMPTY_PATH); > +.EE > +.in > +.P > +This would create a new filesystem configuration context for ext4, > +configure it, > +create a detached mount object, > +and then attach it to > +.IR /home . > +The above procedure is functionally equivalent to > +the following mount operation > +using > +.BR mount (2): > +.P > +.in +4n > +.EX > +mount("/dev/sda1", "/home", "ext4", MS_NODEV, "user_xattr"); > +.EE > +.in > +.P > +The same operation also works with detached bind-mounts created with > +.BR open_tree (2) > +with > +.BR OPEN_TREE_CLONE : > +.P > +.in +4n > +.EX > +int mntfd = open_tree(AT_FDCWD, "/home/cyphar", OPEN_TREE_CLONE); > +move_mount(mntfd, "", AT_FDCWD, "/root", MOVE_MOUNT_F_EMPTY_PATH); > +.EE > +.in > +.P > +This would create a new bind-mount of > +.I /home/cyphar > +as a detached mount object, > +and then attach it to > +.IR /root . > +The above procedure is functionally equivalent to > +the following mount operation > +using > +.BR mount (2): > +.P > +.in +4n > +.EX > +mount("/home/cyphar", "/root", NULL, MS_BIND, NULL); > +.EE > +.in > +.SH SEE ALSO > +.BR fsconfig (2), > +.BR fsmount (2), > +.BR fsopen (2), > +.BR fspick (2), > +.BR mount (2), > +.BR mount_setattr (2), > +.BR open_tree (2), > +.BR mount_namespaces (7) > > -- > 2.51.0 > > -- <https://www.alejandro-colomar.es> Use port 80 (that is, <...:80/>).
© 2016 - 2025 Red Hat, Inc.