grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2] osdep/linux: handle autofs entries in /proc/self/mountinfo


From: Andrei Borzenkov
Subject: [PATCH v2] osdep/linux: handle autofs entries in /proc/self/mountinfo
Date: Thu, 19 Jan 2017 19:37:04 +0300

These entries have placeholder for device name and so are useless for our
purpose. grub failed with something like

grub-install: error: failed to get canonical path of `systemd-1'.

When we see autofs entry, record it (to keep parent-child relationship) but
continue to look for real mount. If it is found, we process it as usual. If
only autofs entry exists, attempt to trigger mount by opening mount point
and retry. Mount point itself is then kept open to avoid timeout.

Recent systemd is by default using automount for /boot/efi so this should
become more popular problem on EFI systems.

Closes: 49942

---

v2:
  - remove bogus autofs check in main mountinfo read loop, it was result of
    misunderstanding

  - consolidate cleanup code to avoid memory leak on retry.

If there are no objections in next days, I'll commit it. It was confirmed to
fix the problem.


 grub-core/osdep/linux/getroot.c | 45 +++++++++++++++++++++++++++++++----------
 1 file changed, 34 insertions(+), 11 deletions(-)

diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
index 09e7e6e..90d92d3 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 *
-- 
tg: (972765f..) bug/49942 (depends on: master)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]