diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index f01599f656..730a7d0d06 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -175,7 +175,9 @@
source path, destination path and option string, where the latter two are optional. If only a source path is
specified the source and destination is taken to be the same. The option string may be either
rbind or norbind for configuring a recursive or non-recursive bind
- mount. If the destination path is omitted, the option string must be omitted too.
+ mount. If the destination path is omitted, the option string must be omitted too.
+ Each bind mount definition may be prefixed with -, in which case it will be ignored
+ when its source path does not exist.
BindPaths= creates regular writable bind mounts (unless the source file system mount
is already marked read-only), while BindReadOnlyPaths= creates read-only bind mounts. These
diff --git a/src/core/execute.c b/src/core/execute.c
index 06cbb57af4..18ad92c3d9 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -4173,13 +4173,13 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
}
if (c->n_bind_mounts > 0)
- for (i = 0; i < c->n_bind_mounts; i++) {
- fprintf(f, "%s%s: %s:%s:%s\n", prefix,
+ for (i = 0; i < c->n_bind_mounts; i++)
+ fprintf(f, "%s%s: %s%s:%s:%s\n", prefix,
c->bind_mounts[i].read_only ? "BindReadOnlyPaths" : "BindPaths",
+ c->bind_mounts[i].ignore_enoent ? "-": "",
c->bind_mounts[i].source,
c->bind_mounts[i].destination,
c->bind_mounts[i].recursive ? "rbind" : "norbind");
- }
if (c->utmp_id)
fprintf(f,
diff --git a/src/core/namespace.c b/src/core/namespace.c
index a5782ece7a..a42220ebe0 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -262,6 +262,7 @@ static int append_bind_mounts(MountEntry **p, const BindMount *binds, unsigned n
.mode = b->recursive ? BIND_MOUNT_RECURSIVE : BIND_MOUNT,
.read_only = b->read_only,
.source_const = b->source,
+ .ignore = b->ignore_enoent,
};
}
@@ -728,11 +729,11 @@ static int mount_entry_chase(
const char *root_directory,
const MountEntry *m,
const char *path,
+ bool chase_nonexistent,
char **location) {
char *chased;
int r;
- unsigned flags = 0;
assert(m);
@@ -740,18 +741,7 @@ static int mount_entry_chase(
* chase the symlinks on our own first. This is called for the destination path, as well as the source path (if
* that applies). The result is stored in "location". */
- if (IN_SET(m->mode,
- BIND_MOUNT,
- BIND_MOUNT_RECURSIVE,
- PRIVATE_TMP,
- PRIVATE_DEV,
- BIND_DEV,
- EMPTY_DIR,
- SYSFS,
- PROCFS))
- flags |= CHASE_NONEXISTENT;
-
- r = chase_symlinks(path, root_directory, flags, &chased);
+ r = chase_symlinks(path, root_directory, chase_nonexistent ? CHASE_NONEXISTENT : 0, &chased);
if (r == -ENOENT && m->ignore) {
log_debug_errno(r, "Path %s does not exist, ignoring.", path);
return 0;
@@ -777,7 +767,7 @@ static int apply_mount(
assert(m);
- r = mount_entry_chase(root_directory, m, mount_entry_path(m), &m->path_malloc);
+ r = mount_entry_chase(root_directory, m, mount_entry_path(m), !IN_SET(m->mode, INACCESSIBLE, READONLY, READWRITE), &m->path_malloc);
if (r <= 0)
return r;
@@ -822,7 +812,7 @@ static int apply_mount(
case BIND_MOUNT_RECURSIVE:
/* Also chase the source mount */
- r = mount_entry_chase(root_directory, m, mount_entry_source(m), &m->source_malloc);
+ r = mount_entry_chase(root_directory, m, mount_entry_source(m), false, &m->source_malloc);
if (r <= 0)
return r;