Support btrfs multi-volume probe.

* util/getroot.c (btrfs_ioctl_dev_info_args) [__linux__]: New struct.
	(btrfs_ioctl_fs_info_args) [__linux__]: Likewise.
	(BTRFS_IOC_DEV_INFO) [__linux__]: New define.
	(BTRFS_IOC_FS_INFO) [__linux__]: Likewise.
	(grub_find_root_devices_from_btrfs) [__linux__]: New function.
	(grub_find_root_devices_from_mountinfo) [__linux__]: Use
	grub_find_root_devices_from_btrfs if on btrfs.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2012-02-27 14:56:28 +01:00
parent c36e5cd162
commit b913642798
2 changed files with 92 additions and 4 deletions

View file

@ -1,3 +1,15 @@
2012-02-27 Vladimir Serbinenko <phcoder@gmail.com>
Support btrfs multi-volume probe.
* util/getroot.c (btrfs_ioctl_dev_info_args) [__linux__]: New struct.
(btrfs_ioctl_fs_info_args) [__linux__]: Likewise.
(BTRFS_IOC_DEV_INFO) [__linux__]: New define.
(BTRFS_IOC_FS_INFO) [__linux__]: Likewise.
(grub_find_root_devices_from_btrfs) [__linux__]: New function.
(grub_find_root_devices_from_mountinfo) [__linux__]: Use
grub_find_root_devices_from_btrfs if on btrfs.
2012-02-27 Vladimir Serbinenko <phcoder@gmail.com> 2012-02-27 Vladimir Serbinenko <phcoder@gmail.com>
Remove any awareness of *.c util files about target. Remove any awareness of *.c util files about target.

View file

@ -142,6 +142,33 @@
# endif /* ! RAW_FLOPPY_MAJOR */ # endif /* ! RAW_FLOPPY_MAJOR */
#endif /* defined(__NetBSD__) */ #endif /* defined(__NetBSD__) */
#ifdef __linux__
/* Defines taken from btrfs/ioctl.h. */
struct btrfs_ioctl_dev_info_args
{
grub_uint64_t devid;
grub_uint8_t uuid[16];
grub_uint64_t bytes_used;
grub_uint64_t total_bytes;
grub_uint64_t unused[379];
grub_uint8_t path[1024];
};
struct btrfs_ioctl_fs_info_args
{
grub_uint64_t max_id;
grub_uint64_t num_devices;
grub_uint8_t fsid[16];
grub_uint64_t reserved[124];
};
#define BTRFS_IOC_DEV_INFO _IOWR(0x94, 30, \
struct btrfs_ioctl_dev_info_args)
#define BTRFS_IOC_FS_INFO _IOR(0x94, 31, \
struct btrfs_ioctl_fs_info_args)
#endif
static void static void
strip_extra_slashes (char *dir) strip_extra_slashes (char *dir)
{ {
@ -365,13 +392,52 @@ unescape (char *str)
*optr = 0; *optr = 0;
} }
static char **
grub_find_root_devices_from_btrfs (const char *dir)
{
int fd;
struct btrfs_ioctl_fs_info_args fsi;
int i, j;
char **ret;
fd = open (dir, 0);
if (!fd)
return NULL;
if (ioctl (fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
{
close (fd);
return NULL;
}
ret = xmalloc ((fsi.num_devices + 1) * sizeof (ret[0]));
for (i = 1; i <= fsi.max_id && j < fsi.num_devices; i++)
{
struct btrfs_ioctl_dev_info_args devi;
memset (&devi, 0, sizeof (devi));
devi.devid = i;
if (ioctl (fd, BTRFS_IOC_DEV_INFO, &devi) < 0)
{
close (fd);
free (ret);
return NULL;
}
ret[j++] = xstrdup ((char *) devi.path);
if (j >= fsi.num_devices)
break;
}
close (fd);
ret[j] = 0;
return ret;
}
static char ** static char **
grub_find_root_devices_from_mountinfo (const char *dir, char **relroot) grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
{ {
FILE *fp; FILE *fp;
char *buf = NULL; char *buf = NULL;
size_t len = 0; size_t len = 0;
char **ret = NULL;
grub_size_t entry_len = 0, entry_max = 4; grub_size_t entry_len = 0, entry_max = 4;
struct mountinfo_entry *entries; struct mountinfo_entry *entries;
struct mountinfo_entry parent_entry = { 0, 0, 0, "", "", "", "" }; struct mountinfo_entry parent_entry = { 0, 0, 0, "", "", "", "" };
@ -471,6 +537,7 @@ grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
/* Now scan visible mounts for the ones we're interested in. */ /* Now scan visible mounts for the ones we're interested in. */
for (i = entry_len - 1; i >= 0; i--) for (i = entry_len - 1; i >= 0; i--)
{ {
char **ret = NULL;
if (!*entries[i].device) if (!*entries[i].device)
continue; continue;
@ -493,7 +560,13 @@ grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
*relroot = xasprintf ("/%s@%s", slash + 1, entries[i].enc_root); *relroot = xasprintf ("/%s@%s", slash + 1, entries[i].enc_root);
} }
} }
else else if (grub_strcmp (entries[i].fstype, "btrfs") == 0)
{
ret = grub_find_root_devices_from_btrfs (dir);
if (relroot)
*relroot = strdup (entries[i].enc_root);
}
if (!ret)
{ {
ret = xmalloc (2 * sizeof (ret[0])); ret = xmalloc (2 * sizeof (ret[0]));
ret[0] = strdup (entries[i].device); ret[0] = strdup (entries[i].device);
@ -501,13 +574,16 @@ grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
if (relroot) if (relroot)
*relroot = strdup (entries[i].enc_root); *relroot = strdup (entries[i].enc_root);
} }
break; free (buf);
free (entries);
fclose (fp);
return ret;
} }
free (buf); free (buf);
free (entries); free (entries);
fclose (fp); fclose (fp);
return ret; return NULL;
} }
#endif /* __linux__ */ #endif /* __linux__ */