grub-devel
[Top][All Lists]
Advanced

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

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


From: Andrei Borzenkov
Subject: [PATCH] osdep/linux: handle autofs entries in /proc/self/mountinfo
Date: Wed, 18 Jan 2017 19:47:24 +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

---

@felix, could you give it a try? Works for me.

Note that the problem happens only when probing for exact mount point. Otherwise
realpath() triggers mounting before. It is theoretically possible that this will
timeout before we scan mountinfo, although it is probably unlikely.

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

diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
index 09e7e6e..d630cf3 100644
--- a/grub-core/osdep/linux/getroot.c
+++ b/grub-core/osdep/linux/getroot.c
@@ -383,21 +383,30 @@ grub_find_root_devices_from_mountinfo (const char *dir, 
char **relroot)
   FILE *fp;
   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 */
+    {
+      free (entries);
+      return NULL; /* 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)
@@ -458,6 +467,9 @@ grub_find_root_devices_from_mountinfo (const char *dir, 
char **relroot)
        }
       else
        {
+         /* If this is automounted directory, continue to search for real 
device */
+         int autofs = (grub_strcmp (entry.fstype, "autofs") == 0);
+
          for (i = entry_len - 1; i >= 0; i--)
            {
              if (entries[i].id == parent_entry.id)
@@ -465,7 +477,8 @@ grub_find_root_devices_from_mountinfo (const char *dir, 
char **relroot)
                  /* Insert at end, pruning anything previously above this.  */
                  entry_len = i + 2;
                  entries[i + 1] = entry;
-                 break;
+                 if (!autofs)
+                   break;
                }
              else if (i == 0 && entries[i].id == entry.id)
                {
@@ -475,7 +488,8 @@ grub_find_root_devices_from_mountinfo (const char *dir, 
char **relroot)
                           (entry_len - 1) * sizeof (*entries));
                  entries[0] = parent_entry;
                  entries[1] = entry;
-                 break;
+                 if (!autofs)
+                   break;
                }
            }
        }
@@ -484,7 +498,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 +528,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 +574,15 @@ 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;
     }
 
   free (buf);
   free (entries);
   fclose (fp);
-  return NULL;
+  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]