[systemd-devel] [PATCH] mount: create mount point correctly in case of bind mount

Alban Crequy alban.crequy at gmail.com
Fri Feb 20 09:39:50 PST 2015


From: Alban Crequy <alban at endocode.com>

Manpage systemd.mount(5) says: "If the mount point does not exist at the
time of mounting, it is created." However, it was not working for bind
mounts of non-directory files (regular, device, socket, etc).

This patch checks the type of the resource to bind mount and does a
"touch" instead of a "mkdir" when necessary.
---
 src/core/mount.c | 32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/src/core/mount.c b/src/core/mount.c
index f3977e6..5a373ba 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -904,19 +904,43 @@ fail:
 static void mount_enter_mounting(Mount *m) {
         int r;
         MountParameters *p;
+        bool is_bind;
+        bool is_file_bind;
 
         assert(m);
 
         m->control_command_id = MOUNT_EXEC_MOUNT;
         m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
 
-        mkdir_p_label(m->where, m->directory_mode);
+        p = get_mount_parameters_fragment(m);
+
+        /* Bind-mounts: A directory can be bind-mounted only on directories. A
+         * non-directory file (regular, device, socket etc.) can be bind
+         * mounted on any non-directory file (even of a different kind).
+         *
+         * Non-bind mounts: they are only mounted on directories.
+         */
+
+        is_bind = p && mount_is_bind(p);
+        is_file_bind = false;
+        if (is_bind) {
+                struct stat st;
+
+                /* both stat(2) and mount(8) follow symlinks, so it's fine */
+                r = stat(p->what, &st);
+                if (r == 0 && !S_ISDIR(st.st_mode))
+                        is_file_bind = true;
+        }
 
-        warn_if_dir_nonempty(m->meta.id, m->where);
+        if (is_file_bind) {
+                touch_file(m->where, true, USEC_INFINITY, 0, 0, m->directory_mode);
+        } else {
+                mkdir_p_label(m->where, m->directory_mode);
+                warn_if_dir_nonempty(m->meta.id, m->where);
+        }
 
         /* Create the source directory for bind-mounts if needed */
-        p = get_mount_parameters_fragment(m);
-        if (p && mount_is_bind(p))
+        if (is_bind)
                 mkdir_p_label(p->what, m->directory_mode);
 
         r = fail_if_symlink(m->meta.id, m->where);
-- 
2.1.4



More information about the systemd-devel mailing list