Lazy device scanning.
* Makefile.util.def (libgrubkern.a): Add grub-core/kern/emu/raid.c. (grub-setup): Remove util/raid.c. * grub-core/Makefile.core.def (kernel): Add kern/emu/raid.c on emu. * grub-core/disk/lvm.c (scan_depth): New variable. (grub_lvm_iterate): Rescan if necessary. (find_lv): New function based on grub_lvm_open. (grub_lvm_open): Use find_lv. Rescan on error. (is_node_readable): New function. (is_lv_readable): Likewise. (grub_lvm_scan_device): Skip already found disks. (do_lvm_scan): New function. Move grub_lvm_scan_device inside of it. Stop if searched device is found and readable. * grub-core/disk/raid.c (inscnt): New variable. (scan_depth): Likewise. (scan_devices): New function based on grub_raid_register. Abort if looked for device is found. (grub_raid_iterate): Rescan if needed. (find_array): NEw function based on -grub_raid_open. (grub_raid_open): Use find_array and rescan. (insert_array): Set became_readable_at. * grub-core/kern/disk.c (grub_disk_dev_iterate): Iterate though "pull. * grub-core/kern/emu/getroot.c (grub_util_open_dm) [HAVE_DEVICE_MAPPER]: New function. (grub_util_is_lvm) [HAVE_DEVICE_MAPPER]: Use grub_util_open_dm. (grub_util_pull_device): New function. (grub_util_get_grub_dev): Call grub_util_pull_device. * util/raid.c: Moved to .. * grub-core/kern/emu/raid.c: ... here. (grub_util_raid_getmembers): New parameter "bootable". All users updated. Support 1.x. * include/grub/ata.h (grub_ata_dev): Change iterate prototype. All users updated. * include/grub/disk.h (grub_disk_pull_t): New enum. (grub_disk_dev): Change iterate prototype. All users updated. * include/grub/emu/getroot.h (grub_util_raid_getmembers) [__linux__]: New proto. * include/grub/emu/hostdisk.h (grub_util_pull_device): Likewise. * include/grub/lvm.h (grub_lvm_lv): New members fullname and compatname. * include/grub/raid.h (grub_raid_array): New member became_readable_at. * include/grub/scsi.h (grub_scsi_dev): Change iterate prototype. All users updated. * include/grub/util/raid.h: Removed.
This commit is contained in:
commit
9bfdcbbc7d
31 changed files with 1153 additions and 763 deletions
48
ChangeLog
48
ChangeLog
|
@ -1,3 +1,51 @@
|
||||||
|
2011-07-07 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
Lazy device scanning.
|
||||||
|
|
||||||
|
* Makefile.util.def (libgrubkern.a): Add grub-core/kern/emu/raid.c.
|
||||||
|
(grub-setup): Remove util/raid.c.
|
||||||
|
* grub-core/Makefile.core.def (kernel): Add kern/emu/raid.c on emu.
|
||||||
|
* grub-core/disk/lvm.c (scan_depth): New variable.
|
||||||
|
(grub_lvm_iterate): Rescan if necessary.
|
||||||
|
(find_lv): New function based on grub_lvm_open.
|
||||||
|
(grub_lvm_open): Use find_lv. Rescan on error.
|
||||||
|
(is_node_readable): New function.
|
||||||
|
(is_lv_readable): Likewise.
|
||||||
|
(grub_lvm_scan_device): Skip already found disks.
|
||||||
|
(do_lvm_scan): New function. Move grub_lvm_scan_device inside of it.
|
||||||
|
Stop if searched device is found and readable.
|
||||||
|
* grub-core/disk/raid.c (inscnt): New variable.
|
||||||
|
(scan_depth): Likewise.
|
||||||
|
(scan_devices): New function based on grub_raid_register. Abort if
|
||||||
|
looked for device is found.
|
||||||
|
(grub_raid_iterate): Rescan if needed.
|
||||||
|
(find_array): NEw function based on -grub_raid_open.
|
||||||
|
(grub_raid_open): Use find_array and rescan.
|
||||||
|
(insert_array): Set became_readable_at.
|
||||||
|
* grub-core/kern/disk.c (grub_disk_dev_iterate): Iterate though "pull.
|
||||||
|
* grub-core/kern/emu/getroot.c (grub_util_open_dm) [HAVE_DEVICE_MAPPER]:
|
||||||
|
New function.
|
||||||
|
(grub_util_is_lvm) [HAVE_DEVICE_MAPPER]: Use grub_util_open_dm.
|
||||||
|
(grub_util_pull_device): New function.
|
||||||
|
(grub_util_get_grub_dev): Call grub_util_pull_device.
|
||||||
|
* util/raid.c: Moved to ..
|
||||||
|
* grub-core/kern/emu/raid.c: ... here.
|
||||||
|
(grub_util_raid_getmembers): New parameter "bootable".
|
||||||
|
All users updated. Support 1.x.
|
||||||
|
* include/grub/ata.h (grub_ata_dev): Change iterate prototype.
|
||||||
|
All users updated.
|
||||||
|
* include/grub/disk.h (grub_disk_pull_t): New enum.
|
||||||
|
(grub_disk_dev): Change iterate prototype.
|
||||||
|
All users updated.
|
||||||
|
* include/grub/emu/getroot.h (grub_util_raid_getmembers) [__linux__]:
|
||||||
|
New proto.
|
||||||
|
* include/grub/emu/hostdisk.h (grub_util_pull_device): Likewise.
|
||||||
|
* include/grub/lvm.h (grub_lvm_lv): New members fullname and compatname.
|
||||||
|
* include/grub/raid.h (grub_raid_array): New member became_readable_at.
|
||||||
|
* include/grub/scsi.h (grub_scsi_dev): Change iterate prototype.
|
||||||
|
All users updated.
|
||||||
|
* include/grub/util/raid.h: Removed.
|
||||||
|
|
||||||
2011-07-06 Vladimir Serbinenko <phcoder@gmail.com>
|
2011-07-06 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* po/POTFILES.in: Regenerate.
|
* po/POTFILES.in: Regenerate.
|
||||||
|
|
|
@ -10,6 +10,7 @@ library = {
|
||||||
common = grub-core/kern/device.c;
|
common = grub-core/kern/device.c;
|
||||||
common = grub-core/kern/disk.c;
|
common = grub-core/kern/disk.c;
|
||||||
common = grub-core/kern/emu/getroot.c;
|
common = grub-core/kern/emu/getroot.c;
|
||||||
|
common = grub-core/kern/emu/raid.c;
|
||||||
common = grub-core/kern/emu/hostdisk.c;
|
common = grub-core/kern/emu/hostdisk.c;
|
||||||
common = grub-core/kern/emu/misc.c;
|
common = grub-core/kern/emu/misc.c;
|
||||||
common = grub-core/kern/emu/mm.c;
|
common = grub-core/kern/emu/mm.c;
|
||||||
|
@ -271,7 +272,6 @@ program = {
|
||||||
installdir = sbin;
|
installdir = sbin;
|
||||||
mansection = 8;
|
mansection = 8;
|
||||||
common = util/grub-setup.c;
|
common = util/grub-setup.c;
|
||||||
common = util/raid.c;
|
|
||||||
common = util/lvm.c;
|
common = util/lvm.c;
|
||||||
common = grub-core/lib/reed_solomon.c;
|
common = grub-core/lib/reed_solomon.c;
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,7 @@ kernel = {
|
||||||
emu = kern/emu/cache_s.S;
|
emu = kern/emu/cache_s.S;
|
||||||
emu = kern/emu/console.c;
|
emu = kern/emu/console.c;
|
||||||
emu = kern/emu/getroot.c;
|
emu = kern/emu/getroot.c;
|
||||||
|
emu = kern/emu/raid.c;
|
||||||
emu = kern/emu/hostdisk.c;
|
emu = kern/emu/hostdisk.c;
|
||||||
emu = kern/emu/hostfs.c;
|
emu = kern/emu/hostfs.c;
|
||||||
emu = kern/emu/main.c;
|
emu = kern/emu/main.c;
|
||||||
|
|
|
@ -453,10 +453,14 @@ grub_ahci_restore_hw (void)
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_ahci_iterate (int (*hook) (int id, int bus))
|
grub_ahci_iterate (int (*hook) (int id, int bus),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
struct grub_ahci_device *dev;
|
struct grub_ahci_device *dev;
|
||||||
|
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
|
FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
|
||||||
if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num))
|
if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -79,7 +79,8 @@ arcdisk_hash_add (char *devpath)
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_arcdisk_iterate (int (*hook_in) (const char *name))
|
grub_arcdisk_iterate (int (*hook_in) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
auto int hook (const char *name, const struct grub_arc_component *comp);
|
auto int hook (const char *name, const struct grub_arc_component *comp);
|
||||||
int hook (const char *name, const struct grub_arc_component *comp)
|
int hook (const char *name, const struct grub_arc_component *comp)
|
||||||
|
@ -90,6 +91,9 @@ grub_arcdisk_iterate (int (*hook_in) (const char *name))
|
||||||
return 0;
|
return 0;
|
||||||
return hook_in (name);
|
return hook_in (name);
|
||||||
}
|
}
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return grub_arc_iterate_devs (hook, 1);
|
return grub_arc_iterate_devs (hook, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -374,7 +374,8 @@ grub_ata_real_open (int id, int bus)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_ata_iterate (int (*hook_in) (const char *name))
|
grub_ata_iterate (int (*hook_in) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
auto int hook (int id, int bus);
|
auto int hook (int id, int bus);
|
||||||
int hook (int id, int bus)
|
int hook (int id, int bus)
|
||||||
|
@ -405,7 +406,7 @@ grub_ata_iterate (int (*hook_in) (const char *name))
|
||||||
grub_ata_dev_t p;
|
grub_ata_dev_t p;
|
||||||
|
|
||||||
for (p = grub_ata_dev_list; p; p = p->next)
|
for (p = grub_ata_dev_list; p; p = p->next)
|
||||||
if (p->iterate && p->iterate (hook))
|
if (p->iterate && p->iterate (hook, pull))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -541,7 +542,8 @@ grub_atapi_open (int id, int bus, struct grub_scsi *scsi)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_atapi_iterate (int NESTED_FUNC_ATTR (*hook_in) (int id, int bus, int luns))
|
grub_atapi_iterate (int NESTED_FUNC_ATTR (*hook_in) (int id, int bus, int luns),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
auto int hook (int id, int bus);
|
auto int hook (int id, int bus);
|
||||||
int hook (int id, int bus)
|
int hook (int id, int bus)
|
||||||
|
@ -569,7 +571,7 @@ grub_atapi_iterate (int NESTED_FUNC_ATTR (*hook_in) (int id, int bus, int luns))
|
||||||
grub_ata_dev_t p;
|
grub_ata_dev_t p;
|
||||||
|
|
||||||
for (p = grub_ata_dev_list; p; p = p->next)
|
for (p = grub_ata_dev_list; p; p = p->next)
|
||||||
if (p->iterate && p->iterate (hook))
|
if (p->iterate && p->iterate (hook, pull))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -378,23 +378,28 @@ enumerate_disks (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_efidisk_iterate (int (*hook) (const char *name))
|
grub_efidisk_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
struct grub_efidisk_data *d;
|
struct grub_efidisk_data *d;
|
||||||
char buf[16];
|
char buf[16];
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
for (d = fd_devices, count = 0; d; d = d->next, count++)
|
switch (pull)
|
||||||
{
|
{
|
||||||
grub_snprintf (buf, sizeof (buf), "fd%d", count);
|
case GRUB_DISK_PULL_NONE:
|
||||||
|
for (d = hd_devices, count = 0; d; d = d->next, count++)
|
||||||
|
{
|
||||||
|
grub_snprintf (buf, sizeof (buf), "hd%d", count);
|
||||||
grub_dprintf ("efidisk", "iterating %s\n", buf);
|
grub_dprintf ("efidisk", "iterating %s\n", buf);
|
||||||
if (hook (buf))
|
if (hook (buf))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
for (d = hd_devices, count = 0; d; d = d->next, count++)
|
case GRUB_DISK_PULL_REMOVABLE:
|
||||||
|
for (d = fd_devices, count = 0; d; d = d->next, count++)
|
||||||
{
|
{
|
||||||
grub_snprintf (buf, sizeof (buf), "hd%d", count);
|
grub_snprintf (buf, sizeof (buf), "fd%d", count);
|
||||||
grub_dprintf ("efidisk", "iterating %s\n", buf);
|
grub_dprintf ("efidisk", "iterating %s\n", buf);
|
||||||
if (hook (buf))
|
if (hook (buf))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -407,6 +412,10 @@ grub_efidisk_iterate (int (*hook) (const char *name))
|
||||||
if (hook (buf))
|
if (hook (buf))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -734,7 +743,9 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||||
|
|
||||||
sdp = dup_dp;
|
sdp = dup_dp;
|
||||||
|
|
||||||
grub_efidisk_iterate (find_parent_disk);
|
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_NONE);
|
||||||
|
if (!parent)
|
||||||
|
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_REMOVABLE);
|
||||||
grub_free (dup_dp);
|
grub_free (dup_dp);
|
||||||
|
|
||||||
if (! parent)
|
if (! parent)
|
||||||
|
@ -774,7 +785,9 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||||
|
|
||||||
sdp = dp;
|
sdp = dp;
|
||||||
|
|
||||||
grub_efidisk_iterate (find_parent_disk);
|
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_NONE);
|
||||||
|
if (!parent)
|
||||||
|
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_REMOVABLE);
|
||||||
if (!parent)
|
if (!parent)
|
||||||
return NULL;
|
return NULL;
|
||||||
device_name = grub_strdup (parent->name);
|
device_name = grub_strdup (parent->name);
|
||||||
|
|
|
@ -27,8 +27,12 @@
|
||||||
int grub_disk_host_i_want_a_reference;
|
int grub_disk_host_i_want_a_reference;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_host_iterate (int (*hook) (const char *name))
|
grub_host_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (hook ("host"))
|
if (hook ("host"))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -284,12 +284,16 @@ grub_biosdisk_call_hook (int (*hook) (const char *name), int drive)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_biosdisk_iterate (int (*hook) (const char *name))
|
grub_biosdisk_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
int drive;
|
|
||||||
int num_floppies;
|
int num_floppies;
|
||||||
|
int drive;
|
||||||
|
|
||||||
/* For hard disks, attempt to read the MBR. */
|
/* For hard disks, attempt to read the MBR. */
|
||||||
|
switch (pull)
|
||||||
|
{
|
||||||
|
case GRUB_DISK_PULL_NONE:
|
||||||
for (drive = 0x80; drive < 0x90; drive++)
|
for (drive = 0x80; drive < 0x90; drive++)
|
||||||
{
|
{
|
||||||
if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
|
if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
|
||||||
|
@ -302,7 +306,9 @@ grub_biosdisk_iterate (int (*hook) (const char *name))
|
||||||
if (grub_biosdisk_call_hook (hook, drive))
|
if (grub_biosdisk_call_hook (hook, drive))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case GRUB_DISK_PULL_REMOVABLE:
|
||||||
if (cd_drive)
|
if (cd_drive)
|
||||||
{
|
{
|
||||||
if (grub_biosdisk_call_hook (hook, cd_drive))
|
if (grub_biosdisk_call_hook (hook, cd_drive))
|
||||||
|
@ -314,7 +320,10 @@ grub_biosdisk_iterate (int (*hook) (const char *name))
|
||||||
for (drive = 0; drive < num_floppies; drive++)
|
for (drive = 0; drive < num_floppies; drive++)
|
||||||
if (grub_biosdisk_call_hook (hook, drive))
|
if (grub_biosdisk_call_hook (hook, drive))
|
||||||
return 1;
|
return 1;
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,8 @@ struct grub_nand_data
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_nand_iterate (int (*hook) (const char *name))
|
grub_nand_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
auto int dev_iterate (struct grub_ieee1275_devalias *alias);
|
auto int dev_iterate (struct grub_ieee1275_devalias *alias);
|
||||||
int dev_iterate (struct grub_ieee1275_devalias *alias)
|
int dev_iterate (struct grub_ieee1275_devalias *alias)
|
||||||
|
@ -46,6 +47,9 @@ grub_nand_iterate (int (*hook) (const char *name))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return grub_devalias_iterate (dev_iterate);
|
return grub_devalias_iterate (dev_iterate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,9 +152,14 @@ scan (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_ofdisk_iterate (int (*hook) (const char *name))
|
grub_ofdisk_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
scan ();
|
scan ();
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++)
|
for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++)
|
||||||
|
|
|
@ -133,9 +133,12 @@ fail:
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_loopback_iterate (int (*hook) (const char *name))
|
grub_loopback_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
struct grub_loopback *d;
|
struct grub_loopback *d;
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return 0;
|
||||||
for (d = loopback_list; d; d = d->next)
|
for (d = loopback_list; d; d = d->next)
|
||||||
{
|
{
|
||||||
if (hook (d->devname))
|
if (hook (d->devname))
|
||||||
|
|
|
@ -26,12 +26,16 @@
|
||||||
|
|
||||||
#ifdef GRUB_UTIL
|
#ifdef GRUB_UTIL
|
||||||
#include <grub/emu/misc.h>
|
#include <grub/emu/misc.h>
|
||||||
|
#include <grub/emu/hostdisk.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
static struct grub_lvm_vg *vg_list;
|
static struct grub_lvm_vg *vg_list;
|
||||||
static int lv_count;
|
static int lv_count;
|
||||||
|
static int scan_depth = 0;
|
||||||
|
|
||||||
|
static int is_lv_readable (struct grub_lvm_lv *lv);
|
||||||
|
|
||||||
|
|
||||||
/* Go the string STR and return the number after STR. *P will point
|
/* Go the string STR and return the number after STR. *P will point
|
||||||
|
@ -95,48 +99,8 @@ grub_lvm_check_flag (char *p, char *str, char *flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static struct grub_lvm_lv *
|
||||||
grub_lvm_iterate (int (*hook) (const char *name))
|
find_lv (const char *name)
|
||||||
{
|
|
||||||
struct grub_lvm_vg *vg;
|
|
||||||
for (vg = vg_list; vg; vg = vg->next)
|
|
||||||
{
|
|
||||||
struct grub_lvm_lv *lv;
|
|
||||||
if (vg->lvs)
|
|
||||||
for (lv = vg->lvs; lv; lv = lv->next)
|
|
||||||
if (lv->visible && hook (lv->name))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef GRUB_UTIL
|
|
||||||
static grub_disk_memberlist_t
|
|
||||||
grub_lvm_memberlist (grub_disk_t disk)
|
|
||||||
{
|
|
||||||
struct grub_lvm_lv *lv = disk->data;
|
|
||||||
grub_disk_memberlist_t list = NULL, tmp;
|
|
||||||
struct grub_lvm_pv *pv;
|
|
||||||
|
|
||||||
if (lv->vg->pvs)
|
|
||||||
for (pv = lv->vg->pvs; pv; pv = pv->next)
|
|
||||||
{
|
|
||||||
if (!pv->disk)
|
|
||||||
grub_util_error ("Couldn't find PV %s. Check your device.map",
|
|
||||||
pv->name);
|
|
||||||
tmp = grub_malloc (sizeof (*tmp));
|
|
||||||
tmp->disk = pv->disk;
|
|
||||||
tmp->next = list;
|
|
||||||
list = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_lvm_open (const char *name, grub_disk_t disk)
|
|
||||||
{
|
{
|
||||||
struct grub_lvm_vg *vg;
|
struct grub_lvm_vg *vg;
|
||||||
struct grub_lvm_lv *lv = NULL;
|
struct grub_lvm_lv *lv = NULL;
|
||||||
|
@ -144,165 +108,19 @@ grub_lvm_open (const char *name, grub_disk_t disk)
|
||||||
{
|
{
|
||||||
if (vg->lvs)
|
if (vg->lvs)
|
||||||
for (lv = vg->lvs; lv; lv = lv->next)
|
for (lv = vg->lvs; lv; lv = lv->next)
|
||||||
if (! grub_strcmp (lv->name, name))
|
if ((grub_strcmp (lv->fullname, name) == 0
|
||||||
break;
|
|| grub_strcmp (lv->compatname, name) == 0)
|
||||||
|
&& is_lv_readable (lv))
|
||||||
if (lv)
|
return lv;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
if (! lv)
|
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown LVM device %s", name);
|
|
||||||
|
|
||||||
disk->id = lv->number;
|
|
||||||
disk->data = lv;
|
|
||||||
disk->total_sectors = lv->size;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
grub_lvm_close (grub_disk_t disk __attribute ((unused)))
|
do_lvm_scan (const char *scan_for)
|
||||||
{
|
{
|
||||||
return;
|
auto int grub_lvm_scan_device (const char *name);
|
||||||
}
|
int grub_lvm_scan_device (const char *name)
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
|
|
||||||
grub_size_t size, char *buf);
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
read_node (const struct grub_lvm_node *node, grub_disk_addr_t sector,
|
|
||||||
grub_size_t size, char *buf)
|
|
||||||
{
|
|
||||||
/* Check whether we actually know the physical volume we want to
|
|
||||||
read from. */
|
|
||||||
if (node->pv)
|
|
||||||
{
|
|
||||||
if (node->pv->disk)
|
|
||||||
return grub_disk_read (node->pv->disk, sector + node->pv->start, 0,
|
|
||||||
size << GRUB_DISK_SECTOR_BITS, buf);
|
|
||||||
else
|
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
|
||||||
"physical volume %s not found", node->pv->name);
|
|
||||||
|
|
||||||
}
|
|
||||||
if (node->lv)
|
|
||||||
return read_lv (node->lv, sector, size, buf);
|
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
|
|
||||||
grub_size_t size, char *buf)
|
|
||||||
{
|
|
||||||
grub_err_t err = 0;
|
|
||||||
struct grub_lvm_vg *vg = lv->vg;
|
|
||||||
struct grub_lvm_segment *seg = lv->segments;
|
|
||||||
struct grub_lvm_node *node;
|
|
||||||
grub_uint64_t offset;
|
|
||||||
grub_uint64_t extent;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (!lv)
|
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume");
|
|
||||||
|
|
||||||
extent = grub_divmod64 (sector, vg->extent_size, NULL);
|
|
||||||
|
|
||||||
/* Find the right segment. */
|
|
||||||
for (i = 0; i < lv->segment_count; i++)
|
|
||||||
{
|
|
||||||
if ((seg->start_extent <= extent)
|
|
||||||
&& ((seg->start_extent + seg->extent_count) > extent))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
seg++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == lv->segment_count)
|
|
||||||
return grub_error (GRUB_ERR_READ_ERROR, "incorrect segment");
|
|
||||||
|
|
||||||
switch (seg->type)
|
|
||||||
{
|
|
||||||
case GRUB_LVM_STRIPED:
|
|
||||||
if (seg->node_count == 1)
|
|
||||||
{
|
|
||||||
/* This segment is linear, so that's easy. We just need to find
|
|
||||||
out the offset in the physical volume and read SIZE bytes
|
|
||||||
from that. */
|
|
||||||
struct grub_lvm_node *stripe = seg->nodes;
|
|
||||||
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
|
|
||||||
|
|
||||||
node = stripe;
|
|
||||||
seg_offset = ((grub_uint64_t) stripe->start
|
|
||||||
* (grub_uint64_t) vg->extent_size);
|
|
||||||
|
|
||||||
offset = sector - ((grub_uint64_t) seg->start_extent
|
|
||||||
* (grub_uint64_t) vg->extent_size) + seg_offset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This is a striped segment. We have to find the right PV
|
|
||||||
similar to RAID0. */
|
|
||||||
struct grub_lvm_node *stripe = seg->nodes;
|
|
||||||
grub_uint64_t a, b;
|
|
||||||
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
|
|
||||||
grub_uint64_t stripenr;
|
|
||||||
|
|
||||||
offset = sector - ((grub_uint64_t) seg->start_extent
|
|
||||||
* (grub_uint64_t) vg->extent_size);
|
|
||||||
|
|
||||||
a = grub_divmod64 (offset, seg->stripe_size, NULL);
|
|
||||||
grub_divmod64 (a, seg->node_count, &stripenr);
|
|
||||||
|
|
||||||
a = grub_divmod64 (offset, seg->stripe_size * seg->node_count, NULL);
|
|
||||||
grub_divmod64 (offset, seg->stripe_size, &b);
|
|
||||||
offset = a * seg->stripe_size + b;
|
|
||||||
|
|
||||||
stripe += stripenr;
|
|
||||||
node = stripe;
|
|
||||||
|
|
||||||
seg_offset = ((grub_uint64_t) stripe->start
|
|
||||||
* (grub_uint64_t) vg->extent_size);
|
|
||||||
|
|
||||||
offset += seg_offset;
|
|
||||||
}
|
|
||||||
return read_node (node, offset, size, buf);
|
|
||||||
case GRUB_LVM_MIRROR:
|
|
||||||
i = 0;
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
err = read_node (&seg->nodes[i], sector, size, buf);
|
|
||||||
if (!err)
|
|
||||||
return err;
|
|
||||||
if (++i >= seg->node_count)
|
|
||||||
return err;
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return grub_error (GRUB_ERR_IO, "unknown LVM segment");
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|
||||||
grub_size_t size, char *buf)
|
|
||||||
{
|
|
||||||
return read_lv (disk->data, sector, size, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_lvm_write (grub_disk_t disk __attribute ((unused)),
|
|
||||||
grub_disk_addr_t sector __attribute ((unused)),
|
|
||||||
grub_size_t size __attribute ((unused)),
|
|
||||||
const char *buf __attribute ((unused)))
|
|
||||||
{
|
|
||||||
return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
grub_lvm_scan_device (const char *name)
|
|
||||||
{
|
{
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
grub_disk_t disk;
|
grub_disk_t disk;
|
||||||
|
@ -332,6 +150,15 @@ grub_lvm_scan_device (const char *name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (vg = vg_list; vg; vg = vg->next)
|
||||||
|
for (pv = vg->pvs; pv; pv = pv->next)
|
||||||
|
if (pv->disk && pv->disk->id == disk->id
|
||||||
|
&& pv->disk->dev->id == disk->dev->id)
|
||||||
|
{
|
||||||
|
grub_disk_close (disk);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Search for label. */
|
/* Search for label. */
|
||||||
for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++)
|
for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++)
|
||||||
{
|
{
|
||||||
|
@ -573,11 +400,43 @@ grub_lvm_scan_device (const char *name)
|
||||||
q++;
|
q++;
|
||||||
|
|
||||||
s = q - p;
|
s = q - p;
|
||||||
lv->name = grub_malloc (vgname_len + 1 + s + 1);
|
lv->name = grub_strndup (p, s);
|
||||||
grub_memcpy (lv->name, vgname, vgname_len);
|
if (!lv->name)
|
||||||
lv->name[vgname_len] = '-';
|
goto lvs_fail;
|
||||||
grub_memcpy (lv->name + vgname_len + 1, p, s);
|
lv->compatname = grub_malloc (vgname_len + 1 + s + 1);
|
||||||
lv->name[vgname_len + 1 + s] = '\0';
|
if (!lv->compatname)
|
||||||
|
goto lvs_fail;
|
||||||
|
grub_memcpy (lv->compatname, vgname, vgname_len);
|
||||||
|
lv->compatname[vgname_len] = '-';
|
||||||
|
grub_memcpy (lv->compatname + vgname_len + 1, p, s);
|
||||||
|
lv->compatname[vgname_len + 1 + s] = '\0';
|
||||||
|
|
||||||
|
{
|
||||||
|
const char *iptr;
|
||||||
|
char *optr;
|
||||||
|
lv->fullname = grub_malloc (sizeof("lvm/") + 2 * vgname_len
|
||||||
|
+ 1 + 2 * s + 1);
|
||||||
|
if (!lv->fullname)
|
||||||
|
goto lvs_fail;
|
||||||
|
|
||||||
|
optr = lv->fullname;
|
||||||
|
grub_memcpy (optr, "lvm/", sizeof ("lvm/") - 1);
|
||||||
|
optr += sizeof ("lvm/") - 1;
|
||||||
|
for (iptr = vgname; iptr < vgname + vgname_len; iptr++)
|
||||||
|
{
|
||||||
|
*optr++ = *iptr;
|
||||||
|
if (*iptr == '-')
|
||||||
|
*optr++ = '-';
|
||||||
|
}
|
||||||
|
*optr++ = '-';
|
||||||
|
for (iptr = p; iptr < p + s; iptr++)
|
||||||
|
{
|
||||||
|
*optr++ = *iptr;
|
||||||
|
if (*iptr == '-')
|
||||||
|
*optr++ = '-';
|
||||||
|
}
|
||||||
|
*optr++ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
lv->size = 0;
|
lv->size = 0;
|
||||||
|
|
||||||
|
@ -857,9 +716,287 @@ grub_lvm_scan_device (const char *name)
|
||||||
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
grub_print_error ();
|
grub_print_error ();
|
||||||
|
if (scan_for && find_lv (scan_for))
|
||||||
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scan_depth++;
|
||||||
|
grub_device_iterate (&grub_lvm_scan_device);
|
||||||
|
scan_depth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
grub_lvm_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
|
{
|
||||||
|
struct grub_lvm_vg *vg;
|
||||||
|
unsigned old_count = 0;
|
||||||
|
if (pull == GRUB_DISK_PULL_RESCAN && scan_depth)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (pull == GRUB_DISK_PULL_RESCAN)
|
||||||
|
{
|
||||||
|
old_count = lv_count;
|
||||||
|
if (!scan_depth)
|
||||||
|
do_lvm_scan (NULL);
|
||||||
|
}
|
||||||
|
if (pull != GRUB_DISK_PULL_RESCAN && pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
for (vg = vg_list; vg; vg = vg->next)
|
||||||
|
{
|
||||||
|
struct grub_lvm_lv *lv;
|
||||||
|
if (vg->lvs)
|
||||||
|
for (lv = vg->lvs; lv; lv = lv->next)
|
||||||
|
if (lv->visible && lv->number >= old_count)
|
||||||
|
{
|
||||||
|
if (hook (lv->fullname))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
static grub_disk_memberlist_t
|
||||||
|
grub_lvm_memberlist (grub_disk_t disk)
|
||||||
|
{
|
||||||
|
struct grub_lvm_lv *lv = disk->data;
|
||||||
|
grub_disk_memberlist_t list = NULL, tmp;
|
||||||
|
struct grub_lvm_pv *pv;
|
||||||
|
|
||||||
|
if (lv->vg->pvs)
|
||||||
|
for (pv = lv->vg->pvs; pv; pv = pv->next)
|
||||||
|
{
|
||||||
|
if (!pv->disk)
|
||||||
|
grub_util_error ("Couldn't find PV %s. Check your device.map",
|
||||||
|
pv->name);
|
||||||
|
tmp = grub_malloc (sizeof (*tmp));
|
||||||
|
tmp->disk = pv->disk;
|
||||||
|
tmp->next = list;
|
||||||
|
list = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_lvm_open (const char *name, grub_disk_t disk)
|
||||||
|
{
|
||||||
|
struct grub_lvm_lv *lv = NULL;
|
||||||
|
int explicit = 0;
|
||||||
|
|
||||||
|
if (grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) == 0)
|
||||||
|
explicit = 1;
|
||||||
|
|
||||||
|
lv = find_lv (name);
|
||||||
|
|
||||||
|
if (! lv && !scan_depth && explicit)
|
||||||
|
{
|
||||||
|
do_lvm_scan (name);
|
||||||
|
if (grub_errno)
|
||||||
|
{
|
||||||
|
grub_print_error ();
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
lv = find_lv (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! lv)
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown LVM device %s", name);
|
||||||
|
|
||||||
|
disk->id = lv->number;
|
||||||
|
disk->data = lv;
|
||||||
|
disk->total_sectors = lv->size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_lvm_close (grub_disk_t disk __attribute ((unused)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
|
||||||
|
grub_size_t size, char *buf);
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
read_node (const struct grub_lvm_node *node, grub_disk_addr_t sector,
|
||||||
|
grub_size_t size, char *buf)
|
||||||
|
{
|
||||||
|
/* Check whether we actually know the physical volume we want to
|
||||||
|
read from. */
|
||||||
|
if (node->pv)
|
||||||
|
{
|
||||||
|
if (node->pv->disk)
|
||||||
|
return grub_disk_read (node->pv->disk, sector + node->pv->start, 0,
|
||||||
|
size << GRUB_DISK_SECTOR_BITS, buf);
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||||
|
"physical volume %s not found", node->pv->name);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (node->lv)
|
||||||
|
return read_lv (node->lv, sector, size, buf);
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
|
||||||
|
grub_size_t size, char *buf)
|
||||||
|
{
|
||||||
|
grub_err_t err = 0;
|
||||||
|
struct grub_lvm_vg *vg = lv->vg;
|
||||||
|
struct grub_lvm_segment *seg = lv->segments;
|
||||||
|
struct grub_lvm_node *node;
|
||||||
|
grub_uint64_t offset;
|
||||||
|
grub_uint64_t extent;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!lv)
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume");
|
||||||
|
|
||||||
|
extent = grub_divmod64 (sector, vg->extent_size, NULL);
|
||||||
|
|
||||||
|
/* Find the right segment. */
|
||||||
|
for (i = 0; i < lv->segment_count; i++)
|
||||||
|
{
|
||||||
|
if ((seg->start_extent <= extent)
|
||||||
|
&& ((seg->start_extent + seg->extent_count) > extent))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
seg++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == lv->segment_count)
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR, "incorrect segment");
|
||||||
|
|
||||||
|
switch (seg->type)
|
||||||
|
{
|
||||||
|
case GRUB_LVM_STRIPED:
|
||||||
|
if (seg->node_count == 1)
|
||||||
|
{
|
||||||
|
/* This segment is linear, so that's easy. We just need to find
|
||||||
|
out the offset in the physical volume and read SIZE bytes
|
||||||
|
from that. */
|
||||||
|
struct grub_lvm_node *stripe = seg->nodes;
|
||||||
|
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
|
||||||
|
|
||||||
|
node = stripe;
|
||||||
|
seg_offset = ((grub_uint64_t) stripe->start
|
||||||
|
* (grub_uint64_t) vg->extent_size);
|
||||||
|
|
||||||
|
offset = sector - ((grub_uint64_t) seg->start_extent
|
||||||
|
* (grub_uint64_t) vg->extent_size) + seg_offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This is a striped segment. We have to find the right PV
|
||||||
|
similar to RAID0. */
|
||||||
|
struct grub_lvm_node *stripe = seg->nodes;
|
||||||
|
grub_uint64_t a, b;
|
||||||
|
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
|
||||||
|
grub_uint64_t stripenr;
|
||||||
|
|
||||||
|
offset = sector - ((grub_uint64_t) seg->start_extent
|
||||||
|
* (grub_uint64_t) vg->extent_size);
|
||||||
|
|
||||||
|
a = grub_divmod64 (offset, seg->stripe_size, NULL);
|
||||||
|
grub_divmod64 (a, seg->node_count, &stripenr);
|
||||||
|
|
||||||
|
a = grub_divmod64 (offset, seg->stripe_size * seg->node_count, NULL);
|
||||||
|
grub_divmod64 (offset, seg->stripe_size, &b);
|
||||||
|
offset = a * seg->stripe_size + b;
|
||||||
|
|
||||||
|
stripe += stripenr;
|
||||||
|
node = stripe;
|
||||||
|
|
||||||
|
seg_offset = ((grub_uint64_t) stripe->start
|
||||||
|
* (grub_uint64_t) vg->extent_size);
|
||||||
|
|
||||||
|
offset += seg_offset;
|
||||||
|
}
|
||||||
|
return read_node (node, offset, size, buf);
|
||||||
|
case GRUB_LVM_MIRROR:
|
||||||
|
i = 0;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
err = read_node (&seg->nodes[i], sector, size, buf);
|
||||||
|
if (!err)
|
||||||
|
return err;
|
||||||
|
if (++i >= seg->node_count)
|
||||||
|
return err;
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return grub_error (GRUB_ERR_IO, "unknown LVM segment");
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
is_node_readable (const struct grub_lvm_node *node)
|
||||||
|
{
|
||||||
|
/* Check whether we actually know the physical volume we want to
|
||||||
|
read from. */
|
||||||
|
if (node->pv)
|
||||||
|
return !!(node->pv->disk);
|
||||||
|
if (node->lv)
|
||||||
|
return is_lv_readable (node->lv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_lv_readable (struct grub_lvm_lv *lv)
|
||||||
|
{
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
if (!lv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Find the right segment. */
|
||||||
|
for (i = 0; i < lv->segment_count; i++)
|
||||||
|
switch (lv->segments[i].type)
|
||||||
|
{
|
||||||
|
case GRUB_LVM_STRIPED:
|
||||||
|
for (j = 0; j < lv->segments[i].node_count; j++)
|
||||||
|
if (!is_node_readable (lv->segments[i].nodes + j))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case GRUB_LVM_MIRROR:
|
||||||
|
for (j = 0; j < lv->segments[i].node_count; j++)
|
||||||
|
if (is_node_readable (lv->segments[i].nodes + j))
|
||||||
|
break;
|
||||||
|
if (j == lv->segments[i].node_count)
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
|
grub_size_t size, char *buf)
|
||||||
|
{
|
||||||
|
return read_lv (disk->data, sector, size, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_lvm_write (grub_disk_t disk __attribute ((unused)),
|
||||||
|
grub_disk_addr_t sector __attribute ((unused)),
|
||||||
|
grub_size_t size __attribute ((unused)),
|
||||||
|
const char *buf __attribute ((unused)))
|
||||||
|
{
|
||||||
|
return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
||||||
|
}
|
||||||
|
|
||||||
static struct grub_disk_dev grub_lvm_dev =
|
static struct grub_disk_dev grub_lvm_dev =
|
||||||
{
|
{
|
||||||
.name = "lvm",
|
.name = "lvm",
|
||||||
|
@ -878,13 +1015,6 @@ static struct grub_disk_dev grub_lvm_dev =
|
||||||
|
|
||||||
GRUB_MOD_INIT(lvm)
|
GRUB_MOD_INIT(lvm)
|
||||||
{
|
{
|
||||||
grub_device_iterate (&grub_lvm_scan_device);
|
|
||||||
if (grub_errno)
|
|
||||||
{
|
|
||||||
grub_print_error ();
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
grub_disk_dev_register (&grub_lvm_dev);
|
grub_disk_dev_register (&grub_lvm_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,12 @@ static char *memdisk_addr;
|
||||||
static grub_off_t memdisk_size = 0;
|
static grub_off_t memdisk_size = 0;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_memdisk_iterate (int (*hook) (const char *name))
|
grub_memdisk_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return hook ("memdisk");
|
return hook ("memdisk");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -486,10 +486,14 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_pata_iterate (int (*hook) (int id, int bus))
|
grub_pata_iterate (int (*hook) (int id, int bus),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
struct grub_pata_device *dev;
|
struct grub_pata_device *dev;
|
||||||
|
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
for (dev = grub_pata_devices; dev; dev = dev->next)
|
for (dev = grub_pata_devices; dev; dev = dev->next)
|
||||||
if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device))
|
if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -33,6 +33,11 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
static struct grub_raid_array *array_list;
|
static struct grub_raid_array *array_list;
|
||||||
grub_raid5_recover_func_t grub_raid5_recover_func;
|
grub_raid5_recover_func_t grub_raid5_recover_func;
|
||||||
grub_raid6_recover_func_t grub_raid6_recover_func;
|
grub_raid6_recover_func_t grub_raid6_recover_func;
|
||||||
|
static grub_raid_t grub_raid_list;
|
||||||
|
static int inscnt = 0;
|
||||||
|
|
||||||
|
static struct grub_raid_array *
|
||||||
|
find_array (const char *name);
|
||||||
|
|
||||||
|
|
||||||
static char
|
static char
|
||||||
|
@ -78,14 +83,98 @@ grub_is_array_readable (struct grub_raid_array *array)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
|
||||||
|
grub_disk_addr_t start_sector, const char *scanner_name,
|
||||||
|
grub_raid_t raid __attribute__ ((unused)));
|
||||||
|
|
||||||
|
static int scan_depth = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
scan_devices (const char *arname)
|
||||||
|
{
|
||||||
|
grub_raid_t raid;
|
||||||
|
|
||||||
|
auto int hook (const char *name);
|
||||||
|
int hook (const char *name)
|
||||||
|
{
|
||||||
|
grub_disk_t disk;
|
||||||
|
struct grub_raid_array array;
|
||||||
|
struct grub_raid_array *arr;
|
||||||
|
grub_disk_addr_t start_sector;
|
||||||
|
|
||||||
|
grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n",
|
||||||
|
raid->name, name);
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
grub_util_info ("Scanning for %s RAID devices on disk %s",
|
||||||
|
raid->name, name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
disk = grub_disk_open (name);
|
||||||
|
if (!disk)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (arr = array_list; arr != NULL; arr = arr->next)
|
||||||
|
{
|
||||||
|
struct grub_raid_member *m;
|
||||||
|
for (m = arr->members; m < arr->members + arr->nr_devs; m++)
|
||||||
|
if (m->device && m->device->id == disk->id
|
||||||
|
&& m->device->dev->id == m->device->dev->id)
|
||||||
|
{
|
||||||
|
grub_disk_close (disk);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((disk->total_sectors != GRUB_ULONG_MAX) &&
|
||||||
|
(! raid->detect (disk, &array, &start_sector)) &&
|
||||||
|
(! insert_array (disk, &array, start_sector, raid->name,
|
||||||
|
raid)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* This error usually means it's not raid, no need to display
|
||||||
|
it. */
|
||||||
|
if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
|
||||||
|
grub_print_error ();
|
||||||
|
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
|
||||||
|
grub_disk_close (disk);
|
||||||
|
|
||||||
|
if (arname && find_array (arname))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scan_depth)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scan_depth++;
|
||||||
|
for (raid = grub_raid_list; raid; raid = raid->next)
|
||||||
|
grub_device_iterate (&hook);
|
||||||
|
scan_depth--;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_raid_iterate (int (*hook) (const char *name))
|
grub_raid_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
struct grub_raid_array *array;
|
struct grub_raid_array *array;
|
||||||
|
int islcnt = 0;
|
||||||
|
|
||||||
|
if (pull == GRUB_DISK_PULL_RESCAN)
|
||||||
|
{
|
||||||
|
islcnt = inscnt;
|
||||||
|
scan_devices (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE && pull != GRUB_DISK_PULL_RESCAN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
for (array = array_list; array != NULL; array = array->next)
|
for (array = array_list; array != NULL; array = array->next)
|
||||||
{
|
{
|
||||||
if (grub_is_array_readable (array))
|
if (grub_is_array_readable (array) && array->became_readable_at >= islcnt)
|
||||||
if (hook (array->name))
|
if (hook (array->name))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -134,11 +223,10 @@ ascii2hex (char c)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static struct grub_raid_array *
|
||||||
grub_raid_open (const char *name, grub_disk_t disk)
|
find_array (const char *name)
|
||||||
{
|
{
|
||||||
struct grub_raid_array *array;
|
struct grub_raid_array *array;
|
||||||
unsigned n;
|
|
||||||
|
|
||||||
if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0)
|
if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0)
|
||||||
{
|
{
|
||||||
|
@ -155,7 +243,7 @@ grub_raid_open (const char *name, grub_disk_t disk)
|
||||||
if (uuid_len == (unsigned) array->uuid_len
|
if (uuid_len == (unsigned) array->uuid_len
|
||||||
&& grub_memcmp (uuidbin, array->uuid, uuid_len) == 0)
|
&& grub_memcmp (uuidbin, array->uuid, uuid_len) == 0)
|
||||||
if (grub_is_array_readable (array))
|
if (grub_is_array_readable (array))
|
||||||
break;
|
return array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -163,7 +251,32 @@ grub_raid_open (const char *name, grub_disk_t disk)
|
||||||
{
|
{
|
||||||
if (!grub_strcmp (array->name, name))
|
if (!grub_strcmp (array->name, name))
|
||||||
if (grub_is_array_readable (array))
|
if (grub_is_array_readable (array))
|
||||||
break;
|
return array;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_raid_open (const char *name, grub_disk_t disk)
|
||||||
|
{
|
||||||
|
struct grub_raid_array *array;
|
||||||
|
unsigned n;
|
||||||
|
|
||||||
|
if (grub_memcmp (name, "md", sizeof ("md") - 1) != 0)
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s",
|
||||||
|
name);
|
||||||
|
|
||||||
|
array = find_array (name);
|
||||||
|
|
||||||
|
if (! array)
|
||||||
|
{
|
||||||
|
scan_devices (name);
|
||||||
|
if (grub_errno)
|
||||||
|
{
|
||||||
|
grub_print_error ();
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
array = find_array (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!array)
|
if (!array)
|
||||||
|
@ -524,6 +637,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
|
||||||
grub_raid_t raid __attribute__ ((unused)))
|
grub_raid_t raid __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
struct grub_raid_array *array = 0, *p;
|
struct grub_raid_array *array = 0, *p;
|
||||||
|
int was_readable = 0;
|
||||||
|
|
||||||
/* See whether the device is part of an array we have already seen a
|
/* See whether the device is part of an array we have already seen a
|
||||||
device from. */
|
device from. */
|
||||||
|
@ -534,6 +648,8 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
|
||||||
grub_free (new_array->uuid);
|
grub_free (new_array->uuid);
|
||||||
array = p;
|
array = p;
|
||||||
|
|
||||||
|
was_readable = grub_is_array_readable (array);
|
||||||
|
|
||||||
/* Do some checks before adding the device to the array. */
|
/* Do some checks before adding the device to the array. */
|
||||||
|
|
||||||
if (new_array->index >= array->allocated_devs)
|
if (new_array->index >= array->allocated_devs)
|
||||||
|
@ -736,12 +852,12 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
|
||||||
array->members[new_array->index].device = disk;
|
array->members[new_array->index].device = disk;
|
||||||
array->members[new_array->index].start_sector = start_sector;
|
array->members[new_array->index].start_sector = start_sector;
|
||||||
array->nr_devs++;
|
array->nr_devs++;
|
||||||
|
if (!was_readable && grub_is_array_readable (array))
|
||||||
|
array->became_readable_at = inscnt++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_raid_t grub_raid_list;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_array (void)
|
free_array (void)
|
||||||
{
|
{
|
||||||
|
@ -772,45 +888,8 @@ free_array (void)
|
||||||
void
|
void
|
||||||
grub_raid_register (grub_raid_t raid)
|
grub_raid_register (grub_raid_t raid)
|
||||||
{
|
{
|
||||||
auto int hook (const char *name);
|
|
||||||
int hook (const char *name)
|
|
||||||
{
|
|
||||||
grub_disk_t disk;
|
|
||||||
struct grub_raid_array array;
|
|
||||||
grub_disk_addr_t start_sector;
|
|
||||||
|
|
||||||
grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n",
|
|
||||||
grub_raid_list->name, name);
|
|
||||||
#ifdef GRUB_UTIL
|
|
||||||
grub_util_info ("Scanning for %s RAID devices on disk %s",
|
|
||||||
grub_raid_list->name, name);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
disk = grub_disk_open (name);
|
|
||||||
if (!disk)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ((disk->total_sectors != GRUB_ULONG_MAX) &&
|
|
||||||
(! grub_raid_list->detect (disk, &array, &start_sector)) &&
|
|
||||||
(! insert_array (disk, &array, start_sector, grub_raid_list->name,
|
|
||||||
grub_raid_list)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* This error usually means it's not raid, no need to display
|
|
||||||
it. */
|
|
||||||
if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
|
|
||||||
grub_print_error ();
|
|
||||||
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
|
|
||||||
grub_disk_close (disk);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
raid->next = grub_raid_list;
|
raid->next = grub_raid_list;
|
||||||
grub_raid_list = raid;
|
grub_raid_list = raid;
|
||||||
grub_device_iterate (&hook);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -322,7 +322,8 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_scsi_iterate (int (*hook) (const char *name))
|
grub_scsi_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
grub_scsi_dev_t p;
|
grub_scsi_dev_t p;
|
||||||
|
|
||||||
|
@ -363,7 +364,7 @@ grub_scsi_iterate (int (*hook) (const char *name))
|
||||||
}
|
}
|
||||||
|
|
||||||
for (p = grub_scsi_dev_list; p; p = p->next)
|
for (p = grub_scsi_dev_list; p; p = p->next)
|
||||||
if (p->iterate && (p->iterate) (scsi_iterate))
|
if (p->iterate && (p->iterate) (scsi_iterate, pull))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -211,10 +211,14 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns))
|
grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
grub_usb_poll_devices ();
|
grub_usb_poll_devices ();
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++)
|
for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++)
|
||||||
|
|
|
@ -203,9 +203,11 @@ int
|
||||||
grub_disk_dev_iterate (int (*hook) (const char *name))
|
grub_disk_dev_iterate (int (*hook) (const char *name))
|
||||||
{
|
{
|
||||||
grub_disk_dev_t p;
|
grub_disk_dev_t p;
|
||||||
|
grub_disk_pull_t pull;
|
||||||
|
|
||||||
|
for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
|
||||||
for (p = grub_disk_dev_list; p; p = p->next)
|
for (p = grub_disk_dev_list; p; p = p->next)
|
||||||
if (p->iterate && (p->iterate) (hook))
|
if (p->iterate && (p->iterate) (hook, pull))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -648,25 +648,26 @@ grub_guess_root_device (const char *dir)
|
||||||
return os_dev;
|
return os_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DEVICE_MAPPER
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_util_is_lvm (const char *os_dev)
|
grub_util_open_dm (const char *os_dev, struct dm_tree **tree,
|
||||||
|
struct dm_tree_node **node)
|
||||||
{
|
{
|
||||||
|
uint32_t maj, min;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
*node = NULL;
|
||||||
|
*tree = NULL;
|
||||||
|
|
||||||
if ((strncmp ("/dev/mapper/", os_dev, 12) != 0))
|
if ((strncmp ("/dev/mapper/", os_dev, 12) != 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef HAVE_DEVICE_MAPPER
|
|
||||||
{
|
|
||||||
struct dm_tree *tree;
|
|
||||||
uint32_t maj, min;
|
|
||||||
struct dm_tree_node *node = NULL;
|
|
||||||
const char *node_uuid;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (stat (os_dev, &st) < 0)
|
if (stat (os_dev, &st) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
tree = dm_tree_create ();
|
*tree = dm_tree_create ();
|
||||||
if (! tree)
|
if (! *tree)
|
||||||
{
|
{
|
||||||
grub_printf ("Failed to create tree\n");
|
grub_printf ("Failed to create tree\n");
|
||||||
grub_dprintf ("hostdisk", "dm_tree_create failed\n");
|
grub_dprintf ("hostdisk", "dm_tree_create failed\n");
|
||||||
|
@ -676,20 +677,42 @@ grub_util_is_lvm (const char *os_dev)
|
||||||
maj = major (st.st_rdev);
|
maj = major (st.st_rdev);
|
||||||
min = minor (st.st_rdev);
|
min = minor (st.st_rdev);
|
||||||
|
|
||||||
if (! dm_tree_add_dev (tree, maj, min))
|
if (! dm_tree_add_dev (*tree, maj, min))
|
||||||
{
|
{
|
||||||
grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n");
|
grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n");
|
||||||
dm_tree_free (tree);
|
dm_tree_free (*tree);
|
||||||
|
*tree = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = dm_tree_find_node (tree, maj, min);
|
*node = dm_tree_find_node (*tree, maj, min);
|
||||||
if (! node)
|
if (! *node)
|
||||||
{
|
{
|
||||||
grub_dprintf ("hostdisk", "dm_tree_find_node failed\n");
|
grub_dprintf ("hostdisk", "dm_tree_find_node failed\n");
|
||||||
dm_tree_free (tree);
|
dm_tree_free (*tree);
|
||||||
|
*tree = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
grub_util_is_lvm (const char *os_dev)
|
||||||
|
{
|
||||||
|
if ((strncmp ("/dev/mapper/", os_dev, 12) != 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_DEVICE_MAPPER
|
||||||
|
{
|
||||||
|
const char *node_uuid;
|
||||||
|
struct dm_tree *tree;
|
||||||
|
struct dm_tree_node *node;
|
||||||
|
|
||||||
|
if (!grub_util_open_dm (os_dev, &tree, &node))
|
||||||
|
return 0;
|
||||||
|
|
||||||
node_uuid = dm_tree_node_get_uuid (node);
|
node_uuid = dm_tree_node_get_uuid (node);
|
||||||
if (! node_uuid)
|
if (! node_uuid)
|
||||||
{
|
{
|
||||||
|
@ -812,11 +835,61 @@ out:
|
||||||
}
|
}
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_util_pull_device (const char *os_dev)
|
||||||
|
{
|
||||||
|
switch (grub_util_get_dev_abstraction (os_dev))
|
||||||
|
{
|
||||||
|
case GRUB_DEV_ABSTRACTION_LVM:
|
||||||
|
#ifdef HAVE_DEVICE_MAPPER
|
||||||
|
{
|
||||||
|
struct dm_tree *tree;
|
||||||
|
struct dm_tree_node *node;
|
||||||
|
struct dm_tree_node *child;
|
||||||
|
void *handle = NULL;
|
||||||
|
|
||||||
|
if (!grub_util_open_dm (os_dev, &tree, &node))
|
||||||
|
return;
|
||||||
|
|
||||||
|
while ((child = dm_tree_next_child (&handle, node, 0)))
|
||||||
|
{
|
||||||
|
const struct dm_info *dm = dm_tree_node_get_info (child);
|
||||||
|
char *subdev;
|
||||||
|
if (!dm)
|
||||||
|
continue;
|
||||||
|
subdev = grub_find_device ("/dev", makedev (dm->major, dm->minor));
|
||||||
|
if (subdev)
|
||||||
|
grub_util_pull_device (subdev);
|
||||||
|
}
|
||||||
|
dm_tree_free (tree);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
case GRUB_DEV_ABSTRACTION_RAID:
|
||||||
|
#ifdef __linux__
|
||||||
|
{
|
||||||
|
char **devicelist = grub_util_raid_getmembers (os_dev, 0);
|
||||||
|
int i;
|
||||||
|
for (i = 0; devicelist[i];i++)
|
||||||
|
grub_util_pull_device (devicelist[i]);
|
||||||
|
free (devicelist);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
|
||||||
|
default: /* GRUB_DEV_ABSTRACTION_NONE */
|
||||||
|
grub_util_biosdisk_get_grub_dev (os_dev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
grub_util_get_grub_dev (const char *os_dev)
|
grub_util_get_grub_dev (const char *os_dev)
|
||||||
{
|
{
|
||||||
char *grub_dev = NULL;
|
char *grub_dev = NULL;
|
||||||
|
|
||||||
|
grub_util_pull_device (os_dev);
|
||||||
|
|
||||||
switch (grub_util_get_dev_abstraction (os_dev))
|
switch (grub_util_get_dev_abstraction (os_dev))
|
||||||
{
|
{
|
||||||
case GRUB_DEV_ABSTRACTION_LVM:
|
case GRUB_DEV_ABSTRACTION_LVM:
|
||||||
|
@ -826,14 +899,10 @@ grub_util_get_grub_dev (const char *os_dev)
|
||||||
grub_size_t offset = sizeof ("/dev/mapper/") - 1;
|
grub_size_t offset = sizeof ("/dev/mapper/") - 1;
|
||||||
|
|
||||||
len = strlen (os_dev) - offset + 1;
|
len = strlen (os_dev) - offset + 1;
|
||||||
grub_dev = xmalloc (len);
|
grub_dev = xmalloc (len + sizeof ("lvm/"));
|
||||||
|
|
||||||
for (i = 0; i < len; i++, offset++)
|
grub_memcpy (grub_dev, "lvm/", sizeof ("lvm/") - 1);
|
||||||
{
|
grub_memcpy (grub_dev + sizeof ("lvm/") - 1, os_dev + offset, len);
|
||||||
grub_dev[i] = os_dev[offset];
|
|
||||||
if (os_dev[offset] == '-' && os_dev[offset + 1] == '-')
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -214,7 +214,8 @@ find_free_slot (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_util_biosdisk_iterate (int (*hook) (const char *name))
|
grub_util_biosdisk_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <grub/emu/misc.h>
|
#include <grub/emu/misc.h>
|
||||||
#include <grub/util/misc.h>
|
#include <grub/util/misc.h>
|
||||||
#include <grub/util/raid.h>
|
|
||||||
#include <grub/emu/getroot.h>
|
#include <grub/emu/getroot.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -36,7 +35,7 @@
|
||||||
#include <linux/raid/md_u.h>
|
#include <linux/raid/md_u.h>
|
||||||
|
|
||||||
char **
|
char **
|
||||||
grub_util_raid_getmembers (const char *name)
|
grub_util_raid_getmembers (const char *name, int bootable)
|
||||||
{
|
{
|
||||||
int fd, ret, i, j;
|
int fd, ret, i, j;
|
||||||
char **devicelist;
|
char **devicelist;
|
||||||
|
@ -53,7 +52,14 @@ grub_util_raid_getmembers (const char *name)
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
grub_util_error ("ioctl RAID_VERSION error: %s", strerror (errno));
|
grub_util_error ("ioctl RAID_VERSION error: %s", strerror (errno));
|
||||||
|
|
||||||
if (version.major != 0 || version.minor != 90)
|
if ((version.major != 0 || version.minor != 90)
|
||||||
|
&& (version.major != 1 || version.minor != 0)
|
||||||
|
&& (version.major != 1 || version.minor != 1)
|
||||||
|
&& (version.major != 1 || version.minor != 2))
|
||||||
|
grub_util_error ("unsupported RAID version: %d.%d",
|
||||||
|
version.major, version.minor);
|
||||||
|
|
||||||
|
if (bootable && (version.major != 0 || version.minor != 90))
|
||||||
grub_util_error ("unsupported RAID version: %d.%d",
|
grub_util_error ("unsupported RAID version: %d.%d",
|
||||||
version.major, version.minor);
|
version.major, version.minor);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/symbol.h>
|
#include <grub/symbol.h>
|
||||||
|
#include <grub/disk.h>
|
||||||
/* XXX: For now this only works on i386. */
|
/* XXX: For now this only works on i386. */
|
||||||
#include <grub/cpu/io.h>
|
#include <grub/cpu/io.h>
|
||||||
|
|
||||||
|
@ -192,7 +193,8 @@ typedef struct grub_ata *grub_ata_t;
|
||||||
struct grub_ata_dev
|
struct grub_ata_dev
|
||||||
{
|
{
|
||||||
/* Call HOOK with each device name, until HOOK returns non-zero. */
|
/* Call HOOK with each device name, until HOOK returns non-zero. */
|
||||||
int (*iterate) (int (*hook) (int id, int bus));
|
int (*iterate) (int (*hook) (int id, int bus),
|
||||||
|
grub_disk_pull_t pull);
|
||||||
|
|
||||||
/* Open the device named NAME, and set up SCSI. */
|
/* Open the device named NAME, and set up SCSI. */
|
||||||
grub_err_t (*open) (int id, int bus, struct grub_ata *scsi);
|
grub_err_t (*open) (int id, int bus, struct grub_ata *scsi);
|
||||||
|
|
|
@ -51,6 +51,14 @@ struct grub_disk;
|
||||||
struct grub_disk_memberlist;
|
struct grub_disk_memberlist;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GRUB_DISK_PULL_NONE,
|
||||||
|
GRUB_DISK_PULL_REMOVABLE,
|
||||||
|
GRUB_DISK_PULL_RESCAN,
|
||||||
|
GRUB_DISK_PULL_MAX
|
||||||
|
} grub_disk_pull_t;
|
||||||
|
|
||||||
/* Disk device. */
|
/* Disk device. */
|
||||||
struct grub_disk_dev
|
struct grub_disk_dev
|
||||||
{
|
{
|
||||||
|
@ -61,7 +69,8 @@ struct grub_disk_dev
|
||||||
enum grub_disk_dev_id id;
|
enum grub_disk_dev_id id;
|
||||||
|
|
||||||
/* Call HOOK with each device name, until HOOK returns non-zero. */
|
/* Call HOOK with each device name, until HOOK returns non-zero. */
|
||||||
int (*iterate) (int (*hook) (const char *name));
|
int (*iterate) (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull);
|
||||||
|
|
||||||
/* Open the device named NAME, and set up DISK. */
|
/* Open the device named NAME, and set up DISK. */
|
||||||
grub_err_t (*open) (const char *name, struct grub_disk *disk);
|
grub_err_t (*open) (const char *name, struct grub_disk *disk);
|
||||||
|
|
|
@ -34,5 +34,8 @@ char *grub_util_get_grub_dev (const char *os_dev);
|
||||||
char *grub_make_system_path_relative_to_its_root (const char *path);
|
char *grub_make_system_path_relative_to_its_root (const char *path);
|
||||||
const char *grub_util_check_block_device (const char *blk_dev);
|
const char *grub_util_check_block_device (const char *blk_dev);
|
||||||
const char *grub_util_check_char_device (const char *blk_dev);
|
const char *grub_util_check_char_device (const char *blk_dev);
|
||||||
|
#ifdef __linux__
|
||||||
|
char **grub_util_raid_getmembers (const char *name, int bootable);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* ! GRUB_UTIL_GETROOT_HEADER */
|
#endif /* ! GRUB_UTIL_GETROOT_HEADER */
|
||||||
|
|
|
@ -29,5 +29,6 @@ const char *grub_util_biosdisk_get_osdev (grub_disk_t disk);
|
||||||
int grub_util_biosdisk_is_present (const char *name);
|
int grub_util_biosdisk_is_present (const char *name);
|
||||||
int grub_util_biosdisk_is_floppy (grub_disk_t disk);
|
int grub_util_biosdisk_is_floppy (grub_disk_t disk);
|
||||||
grub_err_t grub_util_biosdisk_flush (struct grub_disk *disk);
|
grub_err_t grub_util_biosdisk_flush (struct grub_disk *disk);
|
||||||
|
void grub_util_pull_device (const char *osname);
|
||||||
|
|
||||||
#endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */
|
#endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */
|
||||||
|
|
|
@ -44,6 +44,8 @@ struct grub_lvm_pv {
|
||||||
|
|
||||||
struct grub_lvm_lv {
|
struct grub_lvm_lv {
|
||||||
char *name;
|
char *name;
|
||||||
|
char *fullname;
|
||||||
|
char *compatname;
|
||||||
unsigned int number;
|
unsigned int number;
|
||||||
unsigned int segment_count;
|
unsigned int segment_count;
|
||||||
grub_uint64_t size;
|
grub_uint64_t size;
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct grub_raid_array
|
||||||
int number; /* The device number, taken from md_minor so we
|
int number; /* The device number, taken from md_minor so we
|
||||||
are consistent with the device name in
|
are consistent with the device name in
|
||||||
Linux. */
|
Linux. */
|
||||||
|
int became_readable_at;
|
||||||
int level; /* RAID levels, only 0, 1 or 5 at the moment. */
|
int level; /* RAID levels, only 0, 1 or 5 at the moment. */
|
||||||
int layout; /* Layout for RAID 5/6. */
|
int layout; /* Layout for RAID 5/6. */
|
||||||
unsigned int total_devs; /* Total number of devices in the array. */
|
unsigned int total_devs; /* Total number of devices in the array. */
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#ifndef GRUB_SCSI_H
|
#ifndef GRUB_SCSI_H
|
||||||
#define GRUB_SCSI_H 1
|
#define GRUB_SCSI_H 1
|
||||||
|
|
||||||
|
#include <grub/disk.h>
|
||||||
|
|
||||||
typedef struct grub_scsi_dev *grub_scsi_dev_t;
|
typedef struct grub_scsi_dev *grub_scsi_dev_t;
|
||||||
|
|
||||||
void grub_scsi_dev_register (grub_scsi_dev_t dev);
|
void grub_scsi_dev_register (grub_scsi_dev_t dev);
|
||||||
|
@ -50,7 +52,8 @@ grub_make_scsi_id (int subsystem, int bus, int lun)
|
||||||
struct grub_scsi_dev
|
struct grub_scsi_dev
|
||||||
{
|
{
|
||||||
/* Call HOOK with each device name, until HOOK returns non-zero. */
|
/* Call HOOK with each device name, until HOOK returns non-zero. */
|
||||||
int (*iterate) (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns));
|
int (*iterate) (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns),
|
||||||
|
grub_disk_pull_t pull);
|
||||||
|
|
||||||
/* Open the device named NAME, and set up SCSI. */
|
/* Open the device named NAME, and set up SCSI. */
|
||||||
grub_err_t (*open) (int id, int bus, struct grub_scsi *scsi);
|
grub_err_t (*open) (int id, int bus, struct grub_scsi *scsi);
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* raid.h - RAID support for GRUB utils. */
|
|
||||||
/*
|
|
||||||
* GRUB -- GRand Unified Bootloader
|
|
||||||
* Copyright (C) 2006,2007 Free Software Foundation, Inc.
|
|
||||||
*
|
|
||||||
* GRUB is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* GRUB is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GRUB_RAID_UTIL_HEADER
|
|
||||||
#define GRUB_RAID_UTIL_HEADER 1
|
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
char** grub_util_raid_getmembers (const char *name);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* ! GRUB_RAID_UTIL_HEADER */
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include <grub/machine/kernel.h>
|
#include <grub/machine/kernel.h>
|
||||||
#include <grub/term.h>
|
#include <grub/term.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/util/raid.h>
|
|
||||||
#include <grub/util/lvm.h>
|
#include <grub/util/lvm.h>
|
||||||
#ifdef GRUB_MACHINE_IEEE1275
|
#ifdef GRUB_MACHINE_IEEE1275
|
||||||
#include <grub/util/ofpath.h>
|
#include <grub/util/ofpath.h>
|
||||||
|
@ -972,12 +971,12 @@ main (int argc, char *argv[])
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (arguments.device[0] == '/')
|
if (arguments.device[0] == '/')
|
||||||
devicelist = grub_util_raid_getmembers (arguments.device);
|
devicelist = grub_util_raid_getmembers (arguments.device, 1);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *devname;
|
char *devname;
|
||||||
devname = xasprintf ("/dev/%s", dest_dev);
|
devname = xasprintf ("/dev/%s", dest_dev);
|
||||||
devicelist = grub_util_raid_getmembers (dest_dev);
|
devicelist = grub_util_raid_getmembers (dest_dev, 1);
|
||||||
free (devname);
|
free (devname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue