mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-03-11 04:58:19 +03:00
mount: handle bind mount of file with non-existing target
When the target (Where=) of a mount does not exist, systemd tries to create it. But previously, it'd always been created as a directory. That doesn't work if one wants to bind-mount a file to a target that doesn't exist. Fixes: #17184 (cherry picked from commit 218cfe23354397ded28ac898f82b52724f48dae7) (cherry picked from commit 25e30725d7d31d747a40a5c0ab387dc9f48f09e3)
This commit is contained in:
parent
cf62f6b727
commit
48251e428f
@ -476,7 +476,9 @@
|
||||
<term><varname>Where=</varname></term>
|
||||
<listitem><para>Takes an absolute path of a file or directory for the mount point; in particular, the
|
||||
destination cannot be a symbolic link. If the mount point does not exist at the time of mounting, it
|
||||
is created as directory. This string must be reflected in the unit filename. (See above.) This option
|
||||
is created as either a directory or a file. The former is the usual case; the latter is done only if this mount
|
||||
is a bind mount and the source (<varname>What=</varname>) is not a directory.
|
||||
This string must be reflected in the unit filename. (See above.) This option
|
||||
is mandatory.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "device.h"
|
||||
#include "exit-status.h"
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "fstab-util.h"
|
||||
#include "libmount-util.h"
|
||||
#include "log.h"
|
||||
@ -26,11 +27,13 @@
|
||||
#include "process-util.h"
|
||||
#include "serialize.h"
|
||||
#include "special.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "unit-name.h"
|
||||
#include "unit.h"
|
||||
#include "user-util.h"
|
||||
|
||||
#define RETRY_UMOUNT_MAX 32
|
||||
|
||||
@ -1043,6 +1046,7 @@ fail:
|
||||
static void mount_enter_mounting(Mount *m) {
|
||||
int r;
|
||||
MountParameters *p;
|
||||
bool source_is_dir = true;
|
||||
|
||||
assert(m);
|
||||
|
||||
@ -1050,16 +1054,28 @@ static void mount_enter_mounting(Mount *m) {
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
(void) mkdir_p_label(m->where, m->directory_mode);
|
||||
p = get_mount_parameters_fragment(m);
|
||||
if (p && mount_is_bind(p)) {
|
||||
r = is_dir(p->what, /* follow = */ true);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_unit_info_errno(UNIT(m), r, "Failed to determine type of bind mount source '%s', ignoring: %m", p->what);
|
||||
else if (r == 0)
|
||||
source_is_dir = false;
|
||||
}
|
||||
|
||||
unit_warn_if_dir_nonempty(UNIT(m), m->where);
|
||||
if (source_is_dir)
|
||||
(void) mkdir_p_label(m->where, m->directory_mode);
|
||||
else
|
||||
(void) touch_file(m->where, /* parents = */ true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
|
||||
|
||||
if (source_is_dir)
|
||||
unit_warn_if_dir_nonempty(UNIT(m), m->where);
|
||||
unit_warn_leftover_processes(UNIT(m), unit_log_leftover_process_start);
|
||||
|
||||
m->control_command_id = MOUNT_EXEC_MOUNT;
|
||||
m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
|
||||
|
||||
/* Create the source directory for bind-mounts if needed */
|
||||
p = get_mount_parameters_fragment(m);
|
||||
if (p && mount_is_bind(p)) {
|
||||
r = mkdir_p_label(p->what, m->directory_mode);
|
||||
/* mkdir_p_label() can return -EEXIST if the target path exists and is not a directory - which is
|
||||
|
Loading…
x
Reference in New Issue
Block a user