support bind and subvolume mount

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-12-02 14:26:46 +01:00
parent 98042add0c
commit 228cfb40bf
3 changed files with 38 additions and 15 deletions

View file

@ -103,8 +103,8 @@ xgetcwd (void)
can't deal with the multiple-device case yet, but in the meantime, we can can't deal with the multiple-device case yet, but in the meantime, we can
at least cope with the single-device case by scanning at least cope with the single-device case by scanning
/proc/self/mountinfo. */ /proc/self/mountinfo. */
static char * char *
find_root_device_from_mountinfo (const char *dir) grub_find_root_device_from_mountinfo (const char *dir, char **relroot)
{ {
FILE *fp; FILE *fp;
char *buf = NULL; char *buf = NULL;
@ -115,6 +115,9 @@ find_root_device_from_mountinfo (const char *dir)
if (! fp) if (! fp)
return NULL; /* fall through to other methods */ return NULL; /* fall through to other methods */
if (relroot)
*relroot = NULL;
while (getline (&buf, &len, fp) > 0) while (getline (&buf, &len, fp) > 0)
{ {
int mnt_id, parent_mnt_id; int mnt_id, parent_mnt_id;
@ -131,9 +134,6 @@ find_root_device_from_mountinfo (const char *dir)
&count) < 6) &count) < 6)
continue; continue;
if (strcmp (enc_root, "/") != 0)
continue; /* only a subtree is mounted */
enc_path_len = strlen (enc_path); enc_path_len = strlen (enc_path);
if (strncmp (dir, enc_path, enc_path_len) != 0 || if (strncmp (dir, enc_path, enc_path_len) != 0 ||
(dir[enc_path_len] && dir[enc_path_len] != '/')) (dir[enc_path_len] && dir[enc_path_len] != '/'))
@ -147,9 +147,6 @@ find_root_device_from_mountinfo (const char *dir)
free (ret); free (ret);
ret = NULL; ret = NULL;
if (major != 0)
continue; /* not a virtual device */
sep = strstr (buf + count, " - "); sep = strstr (buf + count, " - ");
if (!sep) if (!sep)
continue; continue;
@ -158,13 +155,9 @@ find_root_device_from_mountinfo (const char *dir)
if (sscanf (sep, "%s %s", fstype, device) != 2) if (sscanf (sep, "%s %s", fstype, device) != 2)
continue; continue;
if (stat (device, &st) < 0)
continue;
if (!S_ISBLK (st.st_mode))
continue; /* not a block device */
ret = strdup (device); ret = strdup (device);
if (relroot)
*relroot = strdup (enc_root);
} }
free (buf); free (buf);
@ -531,7 +524,7 @@ grub_guess_root_device (const char *dir)
struct stat st; struct stat st;
#ifdef __linux__ #ifdef __linux__
os_dev = find_root_device_from_mountinfo (dir); os_dev = grub_find_root_device_from_mountinfo (dir, NULL);
if (os_dev) if (os_dev)
return os_dev; return os_dev;
#endif /* __linux__ */ #endif /* __linux__ */

View file

@ -415,6 +415,18 @@ grub_make_system_path_relative_to_its_root (const char *path)
if (offset == 0) if (offset == 0)
{ {
free (buf); free (buf);
#ifdef __linux__
{
char *bind;
grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
if (bind && bind[0] && bind[1])
{
buf3 = bind;
goto parsedir;
}
grub_free (bind);
}
#endif
free (buf2); free (buf2);
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
if (poolfs) if (poolfs)
@ -437,6 +449,21 @@ grub_make_system_path_relative_to_its_root (const char *path)
} }
free (buf); free (buf);
buf3 = xstrdup (buf2 + offset); buf3 = xstrdup (buf2 + offset);
buf2[offset] = 0;
#ifdef __linux__
{
char *bind;
grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
if (bind && bind[0] && bind[1])
{
char *temp = buf3;
buf3 = grub_xasprintf ("%s%s%s", bind, buf3[0] == '/' ?"":"/", buf3);
grub_free (temp);
}
grub_free (bind);
}
#endif
free (buf2); free (buf2);
#ifdef __CYGWIN__ #ifdef __CYGWIN__
@ -452,6 +479,7 @@ grub_make_system_path_relative_to_its_root (const char *path)
} }
#endif #endif
parsedir:
/* Remove trailing slashes, return empty string if root directory. */ /* Remove trailing slashes, return empty string if root directory. */
len = strlen (buf3); len = strlen (buf3);
while (len > 0 && buf3[len - 1] == '/') while (len > 0 && buf3[len - 1] == '/')

View file

@ -78,4 +78,6 @@ extern char * canonicalize_file_name (const char *path);
int grub_device_mapper_supported (void); int grub_device_mapper_supported (void);
#endif #endif
char *grub_find_root_device_from_mountinfo (const char *dir, char **relroot);
#endif /* GRUB_EMU_MISC_H */ #endif /* GRUB_EMU_MISC_H */