Skip to content

Commit 22c5593

Browse files
authored
Merge pull request #28518 from yuwata/fstab-generator-fixes
fstab-generator: fixes for systemd.mount-extra=
2 parents c5afbac + 03de154 commit 22c5593

File tree

66 files changed

+572
-130
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+572
-130
lines changed

man/systemd-fstab-generator.xml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,15 @@
242242

243243
<varlistentry>
244244
<term><varname>systemd.mount-extra=<replaceable>WHAT</replaceable>:<replaceable>WHERE</replaceable>[:<replaceable>FSTYPE</replaceable>[:<replaceable>OPTIONS</replaceable>]]</varname></term>
245+
<term><varname>rd.systemd.mount-extra=<replaceable>WHAT</replaceable>:<replaceable>WHERE</replaceable>[:<replaceable>FSTYPE</replaceable>[:<replaceable>OPTIONS</replaceable>]]</varname></term>
245246

246247
<listitem>
247248
<para>Specifies the mount unit. Takes at least two and at most four fields separated with a colon
248249
(<literal>:</literal>). Each field is handled as the corresponding fstab field. This option can be
249-
specified multiple times.</para>
250+
specified multiple times. <varname>rd.systemd.mount-extra=</varname> is honored only in the initrd,
251+
while <varname>systemd.mount-extra=</varname> is honored by both the main system and the initrd.
252+
In the initrd, the mount point (and also source path if the mount is bind mount) specified in
253+
<varname>systemd.mount-extra=</varname> is prefixed with <filename>/sysroot/</filename>.</para>
250254
<para>Example:
251255
<programlisting>
252256
systemd.mount-extra=/dev/sda1:/mount-point:ext4:rw,noatime</programlisting>
@@ -256,10 +260,13 @@ systemd.mount-extra=/dev/sda1:/mount-point:ext4:rw,noatime</programlisting>
256260

257261
<varlistentry>
258262
<term><varname>systemd.swap-extra=<replaceable>WHAT</replaceable>[:<replaceable>OPTIONS</replaceable>]</varname></term>
263+
<term><varname>rd.systemd.swap-extra=<replaceable>WHAT</replaceable>[:<replaceable>OPTIONS</replaceable>]</varname></term>
259264

260265
<listitem>
261266
<para>Specifies the swap unit. Takes the block device to be used as a swap device, and optionally
262-
takes mount options followed by a colon (<literal>:</literal>).</para>
267+
takes mount options followed by a colon (<literal>:</literal>). This option can be specified
268+
multiple times. <varname>rd.systemd.swap-extra=</varname> is honored only in the initrd, while
269+
<varname>systemd.swap-extra=</varname> is honored by both the main system and the initrd.</para>
263270
<para>Example:
264271
<programlisting>
265272
systemd.swap=/dev/sda2:x-systemd.makefs</programlisting>

src/fstab-generator/fstab-generator.c

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ typedef enum MountPointFlags {
4949
} MountPointFlags;
5050

5151
typedef struct Mount {
52+
bool for_initrd;
5253
char *what;
5354
char *where;
5455
char *fstype;
@@ -102,7 +103,13 @@ static void mount_array_free(Mount *mounts, size_t n) {
102103
free(mounts);
103104
}
104105

105-
static int mount_array_add_internal(char *in_what, char *in_where, const char *in_fstype, const char *in_options) {
106+
static int mount_array_add_internal(
107+
bool for_initrd,
108+
char *in_what,
109+
char *in_where,
110+
const char *in_fstype,
111+
const char *in_options) {
112+
106113
_cleanup_free_ char *what = NULL, *where = NULL, *fstype = NULL, *options = NULL;
107114
int r;
108115

@@ -135,6 +142,7 @@ static int mount_array_add_internal(char *in_what, char *in_where, const char *i
135142
return -ENOMEM;
136143

137144
arg_mounts[arg_n_mounts++] = (Mount) {
145+
.for_initrd = for_initrd,
138146
.what = TAKE_PTR(what),
139147
.where = TAKE_PTR(where),
140148
.fstype = TAKE_PTR(fstype),
@@ -144,7 +152,7 @@ static int mount_array_add_internal(char *in_what, char *in_where, const char *i
144152
return 0;
145153
}
146154

147-
static int mount_array_add(const char *str) {
155+
static int mount_array_add(bool for_initrd, const char *str) {
148156
_cleanup_free_ char *what = NULL, *where = NULL, *fstype = NULL, *options = NULL;
149157
int r;
150158

@@ -159,10 +167,10 @@ static int mount_array_add(const char *str) {
159167
if (!isempty(str))
160168
return -EINVAL;
161169

162-
return mount_array_add_internal(TAKE_PTR(what), TAKE_PTR(where), fstype, options);
170+
return mount_array_add_internal(for_initrd, TAKE_PTR(what), TAKE_PTR(where), fstype, options);
163171
}
164172

165-
static int mount_array_add_swap(const char *str) {
173+
static int mount_array_add_swap(bool for_initrd, const char *str) {
166174
_cleanup_free_ char *what = NULL, *options = NULL;
167175
int r;
168176

@@ -177,7 +185,7 @@ static int mount_array_add_swap(const char *str) {
177185
if (!isempty(str))
178186
return -EINVAL;
179187

180-
return mount_array_add_internal(TAKE_PTR(what), NULL, "swap", options);
188+
return mount_array_add_internal(for_initrd, TAKE_PTR(what), NULL, "swap", options);
181189
}
182190

183191
static int write_options(FILE *f, const char *options) {
@@ -306,9 +314,9 @@ static bool mount_is_network(const char *fstype, const char *options) {
306314
(fstype && fstype_is_network(fstype));
307315
}
308316

309-
static bool mount_in_initrd(const char *where, const char *options) {
317+
static bool mount_in_initrd(const char *where, const char *options, bool accept_root) {
310318
return fstab_test_option(options, "x-initrd.mount\0") ||
311-
(where && path_equal(where, "/usr"));
319+
(where && PATH_IN_SET(where, "/usr", accept_root ? "/" : NULL));
312320
}
313321

314322
static int write_timeout(
@@ -801,7 +809,7 @@ static MountPointFlags fstab_options_to_flags(const char *options, bool is_swap)
801809
return flags;
802810
}
803811

804-
static int canonicalize_mount_path(const char *path, const char *type, bool initrd, char **ret) {
812+
static int canonicalize_mount_path(const char *path, const char *type, bool prefix_sysroot, char **ret) {
805813
_cleanup_free_ char *p = NULL;
806814
bool changed;
807815
int r;
@@ -813,11 +821,11 @@ static int canonicalize_mount_path(const char *path, const char *type, bool init
813821

814822
// FIXME: when chase() learns to chase non-existent paths, use this here and drop the prefixing with
815823
// /sysroot on error below.
816-
r = chase(path, initrd ? "/sysroot" : NULL, CHASE_PREFIX_ROOT | CHASE_NONEXISTENT, &p, NULL);
824+
r = chase(path, prefix_sysroot ? "/sysroot" : NULL, CHASE_PREFIX_ROOT | CHASE_NONEXISTENT, &p, NULL);
817825
if (r < 0) {
818826
log_debug_errno(r, "Failed to chase '%s', using as-is: %m", path);
819827

820-
if (initrd)
828+
if (prefix_sysroot)
821829
p = path_join("/sysroot", path);
822830
else
823831
p = strdup(path);
@@ -842,7 +850,8 @@ static int parse_fstab_one(
842850
const char *fstype,
843851
const char *options,
844852
int passno,
845-
bool initrd,
853+
bool prefix_sysroot,
854+
bool accept_root, /* This takes an effect only when prefix_sysroot is true. */
846855
bool use_swap_enabled) {
847856

848857
_cleanup_free_ char *what = NULL, *where = NULL;
@@ -854,7 +863,7 @@ static int parse_fstab_one(
854863
assert(fstype);
855864
assert(options);
856865

857-
if (initrd && !mount_in_initrd(where_original, options))
866+
if (prefix_sysroot && !mount_in_initrd(where_original, options, accept_root))
858867
return 0;
859868

860869
is_swap = streq_ptr(fstype, "swap");
@@ -891,16 +900,16 @@ static int parse_fstab_one(
891900
* /etc/fstab. So we canonicalize here. Note that we use CHASE_NONEXISTENT to handle the case
892901
* where a symlink refers to another mount target; this works assuming the sub-mountpoint
893902
* target is the final directory. */
894-
r = canonicalize_mount_path(where_original, "where", initrd, &where);
903+
r = canonicalize_mount_path(where_original, "where", prefix_sysroot, &where);
895904
if (r < 0)
896905
return r;
897906
where_changed = r > 0;
898907

899-
if (initrd && fstab_is_bind(options, fstype)) {
908+
if (prefix_sysroot && fstab_is_bind(options, fstype)) {
900909
/* When in initrd, the source of bind mount needs to be prepended with /sysroot as well. */
901910
_cleanup_free_ char *p = NULL;
902911

903-
r = canonicalize_mount_path(what, "what", initrd, &p);
912+
r = canonicalize_mount_path(what, "what", prefix_sysroot, &p);
904913
if (r < 0)
905914
return r;
906915

@@ -919,9 +928,9 @@ static int parse_fstab_one(
919928
bool is_sysroot_usr = in_initrd() && path_equal(where, "/sysroot/usr");
920929

921930
const char *target_unit =
922-
initrd ? SPECIAL_INITRD_FS_TARGET :
923931
is_sysroot ? SPECIAL_INITRD_ROOT_FS_TARGET :
924932
is_sysroot_usr ? SPECIAL_INITRD_USR_FS_TARGET :
933+
prefix_sysroot ? SPECIAL_INITRD_FS_TARGET :
925934
mount_is_network(fstype, options) ? SPECIAL_REMOTE_FS_TARGET :
926935
SPECIAL_LOCAL_FS_TARGET;
927936

@@ -948,13 +957,13 @@ static int parse_fstab_one(
948957
return true;
949958
}
950959

951-
static int parse_fstab(bool initrd) {
960+
static int parse_fstab(bool prefix_sysroot) {
952961
_cleanup_endmntent_ FILE *f = NULL;
953962
const char *fstab;
954963
struct mntent *me;
955964
int r, ret = 0;
956965

957-
if (initrd)
966+
if (prefix_sysroot)
958967
fstab = sysroot_fstab_path();
959968
else {
960969
fstab = fstab_path();
@@ -974,7 +983,9 @@ static int parse_fstab(bool initrd) {
974983
while ((me = getmntent(f))) {
975984
r = parse_fstab_one(fstab,
976985
me->mnt_fsname, me->mnt_dir, me->mnt_type, me->mnt_opts, me->mnt_passno,
977-
initrd, /* use_swap_enabled = */ true);
986+
prefix_sysroot,
987+
/* accept_root = */ false,
988+
/* use_swap_enabled = */ true);
978989
if (r < 0 && ret >= 0)
979990
ret = r;
980991
if (arg_sysroot_check && r > 0)
@@ -1282,14 +1293,18 @@ static int add_mounts_from_cmdline(void) {
12821293
/* Handle each entries found in cmdline as a fstab entry. */
12831294

12841295
FOREACH_ARRAY(m, arg_mounts, arg_n_mounts) {
1296+
if (m->for_initrd && !in_initrd())
1297+
continue;
1298+
12851299
r = parse_fstab_one(
12861300
"/proc/cmdline",
12871301
m->what,
12881302
m->where,
12891303
m->fstype,
12901304
m->options,
12911305
/* passno = */ 0,
1292-
/* initrd = */ false,
1306+
/* prefix_sysroot = */ !m->for_initrd && in_initrd(),
1307+
/* accept_root = */ true,
12931308
/* use_swap_enabled = */ false);
12941309
if (r < 0 && ret >= 0)
12951310
ret = r;
@@ -1298,14 +1313,16 @@ static int add_mounts_from_cmdline(void) {
12981313
return ret;
12991314
}
13001315

1301-
static int add_mounts_from_creds(void) {
1316+
static int add_mounts_from_creds(bool prefix_sysroot) {
13021317
_cleanup_free_ void *b = NULL;
13031318
struct mntent *me;
13041319
int r, ret = 0;
13051320
size_t bs;
13061321

1322+
assert(in_initrd() || !prefix_sysroot);
1323+
13071324
r = read_credential_with_decryption(
1308-
in_initrd() ? "fstab.extra.initrd" : "fstab.extra",
1325+
in_initrd() && !prefix_sysroot ? "fstab.extra.initrd" : "fstab.extra",
13091326
&b, &bs);
13101327
if (r <= 0)
13111328
return r;
@@ -1323,7 +1340,8 @@ static int add_mounts_from_creds(void) {
13231340
me->mnt_type,
13241341
me->mnt_opts,
13251342
me->mnt_passno,
1326-
/* initrd = */ false,
1343+
/* prefix_sysroot = */ prefix_sysroot,
1344+
/* accept_root = */ true,
13271345
/* use_swap_enabled = */ true);
13281346
if (r < 0 && ret >= 0)
13291347
ret = r;
@@ -1437,21 +1455,21 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
14371455
else
14381456
arg_verity = r;
14391457

1440-
} else if (streq(key, "systemd.mount-extra")) {
1458+
} else if (STR_IN_SET(key, "systemd.mount-extra", "rd.systemd.mount-extra")) {
14411459

14421460
if (proc_cmdline_value_missing(key, value))
14431461
return 0;
14441462

1445-
r = mount_array_add(value);
1463+
r = mount_array_add(startswith(key, "rd."), value);
14461464
if (r < 0)
14471465
log_warning("Failed to parse systemd.mount-extra= option, ignoring: %s", value);
14481466

1449-
} else if (streq(key, "systemd.swap-extra")) {
1467+
} else if (STR_IN_SET(key, "systemd.swap-extra", "rd.systemd.swap-extra")) {
14501468

14511469
if (proc_cmdline_value_missing(key, value))
14521470
return 0;
14531471

1454-
r = mount_array_add_swap(value);
1472+
r = mount_array_add_swap(startswith(key, "rd."), value);
14551473
if (r < 0)
14561474
log_warning("Failed to parse systemd.swap-extra= option, ignoring: %s", value);
14571475
}
@@ -1517,7 +1535,7 @@ static int run_generator(void) {
15171535
(void) determine_usr();
15181536

15191537
if (arg_sysroot_check) {
1520-
r = parse_fstab(/* initrd= */ true);
1538+
r = parse_fstab(/* prefix_sysroot = */ true);
15211539
if (r == 0)
15221540
log_debug("Nothing interesting found, not doing daemon-reload.");
15231541
if (r > 0)
@@ -1547,13 +1565,13 @@ static int run_generator(void) {
15471565
/* Honour /etc/fstab only when that's enabled */
15481566
if (arg_fstab_enabled) {
15491567
/* Parse the local /etc/fstab, possibly from the initrd */
1550-
r = parse_fstab(/* initrd= */ false);
1568+
r = parse_fstab(/* prefix_sysroot = */ false);
15511569
if (r < 0 && ret >= 0)
15521570
ret = r;
15531571

15541572
/* If running in the initrd also parse the /etc/fstab from the host */
15551573
if (in_initrd())
1556-
r = parse_fstab(/* initrd= */ true);
1574+
r = parse_fstab(/* prefix_sysroot = */ true);
15571575
else
15581576
r = generator_enable_remount_fs_service(arg_dest);
15591577
if (r < 0 && ret >= 0)
@@ -1564,10 +1582,16 @@ static int run_generator(void) {
15641582
if (r < 0 && ret >= 0)
15651583
ret = r;
15661584

1567-
r = add_mounts_from_creds();
1585+
r = add_mounts_from_creds(/* prefix_sysroot = */ false);
15681586
if (r < 0 && ret >= 0)
15691587
ret = r;
15701588

1589+
if (in_initrd()) {
1590+
r = add_mounts_from_creds(/* prefix_sysroot = */ true);
1591+
if (r < 0 && ret >= 0)
1592+
ret = r;
1593+
}
1594+
15711595
return ret;
15721596
}
15731597

0 commit comments

Comments
 (0)