Merge ~smoser/cloud-initramfs-tools:fix/1890803-overlayroot-no-fstab into cloud-initramfs-tools:master

Proposed by Scott Moser
Status: Merged
Merged at revision: aea2ecf4035051a4e4faf5b5c910af887de50844
Proposed branch: ~smoser/cloud-initramfs-tools:fix/1890803-overlayroot-no-fstab
Merge into: cloud-initramfs-tools:master
Diff against target: 118 lines (+59/-19)
1 file modified
overlayroot/scripts/init-bottom/overlayroot (+59/-19)
Reviewer Review Type Date Requested Status
Ryan Harper (community) Approve
cloud-initramfs-tools Pending
Review via email: mp+389242@code.launchpad.net

Commit message

overlayroot: initialize /etc/fstab if root does not have one and read-only

A root filesystem may not have an /etc/fstab. That could be for either:
a.) not needed - the kernel command line has root mount options and no
  other filesystems are mounted.
b.) system has systemd.mounts - this is currently not supported by
overlayroot.

If the kernel command line contains 'ro', then overlayroot will
correctly leave root mounted 'ro'. The problem was that without an
/etc/fstab, systemd would not remount the root filesystem rw, and
thus failure would ensue.

The change here is to initialize an fstab in the case that the root
filesystem did not contain one, *and* 'ro' is present on the cmdline.
In cases where 'ro' is not present, then overlayroot will leave /
mounted as rw, so systemd does not need to remount rw.

LP: #1890803

Description of the change

see commit message

To post a comment you must log in.
Revision history for this message
Scott Moser (smoser) wrote :

Changes compared to https://code.launchpad.net/~raharper/cloud-initramfs-tools/+git/cloud-initramfs-tools/+merge/389177

a.) only generate "source_fstab" if read-only on kernel cmdline.
b.) debug messages and better hint left in /etc/fstab that this happened.
c.) do not read /proc/mounts, but read initramfs-provided globals and /dev/root for fstab

I'm not opposed to reading /proc/mounts, it just seems like unneccessary work.

Revision history for this message
Ryan Harper (raharper) wrote :

Thanks, this is great improvement. I'm +1 on this as-is, I left some in-line comments/suggestions.

review: Approve
Revision history for this message
Scott Moser (smoser) :
Revision history for this message
Scott Moser (smoser) wrote :

This is untested...
so before landing, it'd be good to have someone test it.

Revision history for this message
Ryan Harper (raharper) wrote :

Thanks for the update. I can test.

Revision history for this message
Ryan Harper (raharper) wrote :

OK, so rooturl, modifies ROOTFLAGS for the mount command.

{
    echo 'ROOTFSTYPE="root_url"'
    echo "ROOTFLAGS=\"-o move\""
    echo "ROOT=\"$rootmnt.tmp\""
}

and then '-o move' ends up in source_fstab and then is carried through. systemd-fstab-generator won't parse it so; with the ro option this leaves the rootfs in ro mode. Even if we didn't have the remount,ro any mount commands that attempt to parse fstab will fail.

/proc/mount parsing may be better here since it wont contain anything that fstab doesn't expect.

review: Needs Fixing
Revision history for this message
Scott Moser (smoser) wrote :

force-pushed over the top with parsing of /proc/mounts

probably just using '/dev/root / auto defaults 0 0' would have been sufficient.

I'm happy to go back tot hat if you want.

Revision history for this message
Ryan Harper (raharper) wrote :

Yes, either work. I don't yet see the update here.

Revision history for this message
Ryan Harper (raharper) wrote :

There we go; let me test

Revision history for this message
Ryan Harper (raharper) wrote :

Yeah, this works correctly with a local and an VMtest (rooturl).

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/overlayroot/scripts/init-bottom/overlayroot b/overlayroot/scripts/init-bottom/overlayroot
2index c13c02b..43d9a83 100755
3--- a/overlayroot/scripts/init-bottom/overlayroot
4+++ b/overlayroot/scripts/init-bottom/overlayroot
5@@ -299,6 +299,32 @@ get_workdir() {
6 clean_path "${root_rw}/${dir_prefix%/}-workdir/${file}"
7 }
8
9+gen_fstab() {
10+ # gen_fstab(mp) - generate a fabricated /etc/fstab for mount point $mp
11+ local mp="$1" m_spec="" m_opts="" m_fstype=""
12+ local spec file vfstype opts pass freq
13+
14+ # just remove any trailing /
15+ [ "$mp" != "/" ] && mp=${mp%/}
16+ while read spec file vfstype opts pass freq; do
17+ [ "$file" = "$mp" ] && {
18+ m_spec="$spec"
19+ m_opts="$opts"
20+ m_fstype="$vfstype"
21+ break
22+ }
23+ done </proc/mounts
24+ [ -z "$m_spec" ] && {
25+ log_warn "did not find root mount point $mp in /proc/mounts"
26+ m_opts="/dev/root"
27+ m_opts="defaults"
28+ m_fstype="auto"
29+ }
30+
31+ echo "# fabricated by overlayroot, rootfs did not contain /etc/fstab"
32+ echo "${m_spec} / ${m_fstype} ${m_opts} 0 0 "
33+}
34+
35 overlayrootify_fstab() {
36 # overlayrootify_fstab(input, root_ro, root_rw, dir_prefix, recurse, swap)
37 # read input fstab file, write an overlayroot version to stdout
38@@ -312,6 +338,18 @@ overlayrootify_fstab() {
39
40 [ -f "$input" ] || return 1
41
42+ cat <<EOF
43+#
44+# This fstab is for overlayroot. The real one can be found at
45+# ${root_ro}/etc/fstab
46+# The original entry for '/' and other mounts have been updated to be placed
47+# under $root_ro.
48+# To permanently modify this (or any other file), you should change-root into
49+# a writable view of the underlying filesystem using:
50+# sudo overlayroot-chroot
51+#
52+EOF
53+
54 needs_workdir && needs_workdir=true || needs_workdir=false
55 while read spec file vfstype opts pass freq; do
56 [ "$file" = "/" ] && noauto="noauto" || noauto=""
57@@ -660,6 +698,10 @@ OVERLAYROOT_DEBUG=${_RET_common_debug:-${OVERLAYROOT_DEBUG}}
58 dir_prefix=${_RET_common_dir:-"/overlay"}
59 overlayroot_driver=${_RET_common_driver}
60
61+read cmdline </proc/cmdline
62+cmdline=" $cmdline "
63+[ "${cmdline#* ro }" != "$cmdline" ] && cmdline_ro=true || cmdline_ro=false
64+
65 if [ "${overlayroot_driver:-auto}" = "auto" ]; then
66 search_fs_driver overlay overlayfs ||
67 fail "Unable to find a driver. searched: overlay overlayfs"
68@@ -791,23 +833,23 @@ mount --move "${root_rw}" "${ROOTMNT}${root_rw}" ||
69 # Remember we are still on the initramfs root fs here, so we have to work
70 # on ${ROOTMNT}/etc/fstab. The original fstab is
71 # ${ROOTMNT}${root_ro}/etc/fstab.
72-cat <<EOF >${ROOTMNT}/etc/fstab
73-#
74-# This fstab is in an ${overlayroot_driver}. The real one can be found at
75-# ${root_ro}/etc/fstab
76-# The original entry for '/' and other mounts have been updated to be placed
77-# under $root_ro.
78-# To permanently modify this (or any other file), you should change-root into
79-# a writable view of the underlying filesystem using:
80-# sudo overlayroot-chroot
81-#
82-EOF
83+source_fstab="$ROOTMNT/${root_ro}/etc/fstab"
84+if [ ! -f "$source_fstab" ] && [ "$cmdline_ro" = "true" ]; then
85+ debug "rootfs did not contain /etc/fstab, creating" \
86+ "based on kernel cmdline"
87+ source_fstab="${TEMP_D}/fstab"
88+ gen_fstab "${ROOTMNT}${root_ro}" > "$source_fstab" ||
89+ log_fail "gen_fstab failed for $ROOTMNT/$root_ro"
90+fi
91
92-[ $? -eq 0 ] || log_fail "failed to modify /etc/fstab (step 1)"
93-overlayrootify_fstab "${ROOTMNT}${root_ro}/etc/fstab" "$root_ro" \
94- "$root_rw" "$dir_prefix" "$recurse" "$swap" "${overlayroot_driver}" \
95- >> "${ROOTMNT}/etc/fstab" ||
96- log_fail "failed to modify /etc/fstab (step 2)"
97+if [ -f "$source_fstab" ]; then
98+ overlayrootify_fstab "$source_fstab" "$root_ro" \
99+ "$root_rw" "$dir_prefix" "$recurse" "$swap" "${overlayroot_driver}" \
100+ >> "${ROOTMNT}/etc/fstab" ||
101+ log_fail "failed to modify /etc/fstab"
102+else
103+ debug "rootfs did not contain /etc/fstab."
104+fi
105
106 # we have to make the directories in ${root_rw} because if they do not
107 # exist, then the 'upper=' argument to overlayfs will fail.
108@@ -822,9 +864,7 @@ fi
109
110 # if / is supposed to be mounted read-only (cmdline with 'ro')
111 # then mount our overlayfs as read-only just to be more normal
112-read cmdline < /proc/cmdline
113-cmdline=" $cmdline "
114-if [ "${cmdline#* ro }" != "$cmdline" ]; then
115+if [ "${cmdline_ro}" = "true" ]; then
116 mount -o remount,ro "$ROOTMNT" ||
117 log_fail "failed to remount overlayroot read-only"
118 debug "mounted $ROOTMNT read-only per kernel cmdline"

Subscribers

People subscribed via source and target branches