From 99299d0d5a722812cedc0a23e4987f90a257c2d2 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Wed, 26 Jul 2023 12:04:07 +0800 Subject: [PATCH 1/2] fstab-util: add fstab_is_mount_point_full which takes a source path to compare --- src/shared/fstab-util.c | 42 +++++++++++++++++++++++++++++++++++------ src/shared/fstab-util.h | 6 +++++- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c index 6efdcd6896..4ffec25c75 100644 --- a/src/shared/fstab-util.c +++ b/src/shared/fstab-util.c @@ -63,23 +63,53 @@ bool fstab_is_extrinsic(const char *mount, const char *opts) { return false; } -int fstab_is_mount_point(const char *mount) { +static int fstab_is_mount_point_of(const char *what_fstab, const char *path) { + _cleanup_free_ char *node = NULL; + + assert(what_fstab); + assert(path); + + node = fstab_node_to_udev_node(what_fstab); + if (!node) + return -ENOMEM; + + if (path_equal(node, path)) + return true; + + if (is_device_node(path) && is_device_node(node)) + return devnode_same(node, path); + + return false; +} + +int fstab_is_mount_point_full(const char *where, const char *path) { _cleanup_endmntent_ FILE *f = NULL; - struct mntent *m; + int r; + + assert(where); f = setmntent(fstab_path(), "re"); if (!f) return errno == ENOENT ? false : -errno; for (;;) { + struct mntent *me; + errno = 0; - m = getmntent(f); - if (!m) + me = getmntent(f); + if (!me) return errno != 0 ? -errno : false; - if (path_equal(m->mnt_dir, mount)) - return true; + if (path_equal(where, me->mnt_dir)) { + if (!path) + return true; + + r = fstab_is_mount_point_of(me->mnt_fsname, path); + if (r > 0 || (r < 0 && !ERRNO_IS_DEVICE_ABSENT(r))) + return r; + } } + return false; } diff --git a/src/shared/fstab-util.h b/src/shared/fstab-util.h index 5979b476b6..cb3686bee3 100644 --- a/src/shared/fstab-util.h +++ b/src/shared/fstab-util.h @@ -7,9 +7,13 @@ #include "macro.h" bool fstab_is_extrinsic(const char *mount, const char *opts); -int fstab_is_mount_point(const char *mount); int fstab_has_fstype(const char *fstype); +int fstab_is_mount_point_full(const char *where, const char *path); +static inline int fstab_is_mount_point(const char *where) { + return fstab_is_mount_point_full(where, NULL); +} + int fstab_filter_options( const char *opts, const char *names, From 69d7f35ce4b642910575a3d973e713a27285663d Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Wed, 26 Jul 2023 12:10:43 +0800 Subject: [PATCH 2/2] gpt-auto: skip mounting ESP if fstab for /boot/ uses the same device as discovered one Follow-up for 6a488fa7cce8124fa885adf8a2f31363fe62f636 Currently, if an fstab entry for /boot/ exists, we'll skip to try /efi/ instead. However, if it's already using the same device as the discovered one, we should not duplicate the mount. --- src/gpt-auto-generator/gpt-auto-generator.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index 08338bdd93..840d3b6ed1 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -590,6 +590,16 @@ static int add_partition_esp(DissectedPartition *p, bool has_xbootldr) { esp_path = "/boot"; id = "boot"; } + } else { + /* Check if the fstab entry for /boot/ is already the ESP. If so, we don't need to + * check /efi/ or duplicate the mount there. */ + r = fstab_is_mount_point_full("/boot", p->node); + if (r < 0) + return log_error_errno(r, + "Failed to check if fstab entry for /boot uses the same device as '%s': %m", + p->node); + if (r > 0) + return 0; } }