diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c index 09e7e6e6d..90d92d3ad 100644 --- a/grub-core/osdep/linux/getroot.c +++ b/grub-core/osdep/linux/getroot.c @@ -380,24 +380,30 @@ get_btrfs_fs_prefix (const char *mount_path) char ** grub_find_root_devices_from_mountinfo (const char *dir, char **relroot) { - FILE *fp; + FILE *fp = NULL; char *buf = NULL; size_t len = 0; - grub_size_t entry_len = 0, entry_max = 4; + grub_size_t entry_len, entry_max = 4; struct mountinfo_entry *entries; struct mountinfo_entry parent_entry = { 0, 0, 0, "", "", "", "" }; int i; + int retry = 0; + int dir_fd = -1; + char **ret = NULL; if (! *dir) dir = "/"; if (relroot) *relroot = NULL; + entries = xmalloc (entry_max * sizeof (*entries)); + +again: fp = grub_util_fopen ("/proc/self/mountinfo", "r"); if (! fp) - return NULL; /* fall through to other methods */ + goto out; /* fall through to other methods */ - entries = xmalloc (entry_max * sizeof (*entries)); + entry_len = 0; /* First, build a list of relevant visible mounts. */ while (getline (&buf, &len, fp) > 0) @@ -484,7 +490,6 @@ grub_find_root_devices_from_mountinfo (const char *dir, char **relroot) /* Now scan visible mounts for the ones we're interested in. */ for (i = entry_len - 1; i >= 0; i--) { - char **ret = NULL; char *fs_prefix = NULL; if (!*entries[i].device) continue; @@ -515,6 +520,23 @@ grub_find_root_devices_from_mountinfo (const char *dir, char **relroot) ret = grub_find_root_devices_from_btrfs (dir); fs_prefix = get_btrfs_fs_prefix (entries[i].enc_path); } + else if (!retry && grub_strcmp (entries[i].fstype, "autofs") == 0) + { + /* If the best match is automounted, try to trigger mount. We cannot + simply return here because stat() on automounted directory does not + trigger mount and returns bogus (pseudo)device number instead. + We keep mountpoint open until end of scan to prevent timeout. */ + + int flags = O_RDONLY|O_DIRECTORY; + + fclose (fp); +#ifdef O_LARGEFILE + flags |= O_LARGEFILE; +#endif + dir_fd = open (entries[i].enc_path, flags); + retry = 1; + goto again; + } if (!ret) { ret = xmalloc (2 * sizeof (ret[0])); @@ -544,16 +566,17 @@ grub_find_root_devices_from_mountinfo (const char *dir, char **relroot) } if (fs_prefix != entries[i].enc_root) free (fs_prefix); - free (buf); - free (entries); - fclose (fp); - return ret; + break; } +out: free (buf); free (entries); - fclose (fp); - return NULL; + if (fp) + fclose (fp); + if (dir_fd != -1) + close (dir_fd); + return ret; } static char *