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:
Vladimir 'phcoder' Serbinenko 2011-07-07 23:21:59 +02:00
commit 9bfdcbbc7d
31 changed files with 1153 additions and 763 deletions

View file

@ -453,10 +453,14 @@ grub_ahci_restore_hw (void)
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;
if (pull != GRUB_DISK_PULL_NONE)
return 0;
FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num))
return 1;

View file

@ -79,7 +79,8 @@ arcdisk_hash_add (char *devpath)
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);
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 hook_in (name);
}
if (pull != GRUB_DISK_PULL_NONE)
return 0;
return grub_arc_iterate_devs (hook, 1);
}

View file

@ -374,7 +374,8 @@ grub_ata_real_open (int id, int bus)
}
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);
int hook (int id, int bus)
@ -405,7 +406,7 @@ grub_ata_iterate (int (*hook_in) (const char *name))
grub_ata_dev_t p;
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 0;
}
@ -541,7 +542,8 @@ grub_atapi_open (int id, int bus, struct grub_scsi *scsi)
}
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);
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;
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 0;
}

View file

@ -378,34 +378,43 @@ enumerate_disks (void)
}
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;
char buf[16];
int count;
for (d = fd_devices, count = 0; d; d = d->next, count++)
switch (pull)
{
grub_snprintf (buf, sizeof (buf), "fd%d", count);
grub_dprintf ("efidisk", "iterating %s\n", buf);
if (hook (buf))
return 1;
}
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);
if (hook (buf))
return 1;
}
break;
case GRUB_DISK_PULL_REMOVABLE:
for (d = fd_devices, count = 0; d; d = d->next, count++)
{
grub_snprintf (buf, sizeof (buf), "fd%d", count);
grub_dprintf ("efidisk", "iterating %s\n", buf);
if (hook (buf))
return 1;
}
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);
if (hook (buf))
return 1;
}
for (d = cd_devices, count = 0; d; d = d->next, count++)
{
grub_snprintf (buf, sizeof (buf), "cd%d", count);
grub_dprintf ("efidisk", "iterating %s\n", buf);
if (hook (buf))
return 1;
for (d = cd_devices, count = 0; d; d = d->next, count++)
{
grub_snprintf (buf, sizeof (buf), "cd%d", count);
grub_dprintf ("efidisk", "iterating %s\n", buf);
if (hook (buf))
return 1;
}
break;
default:
return 0;
}
return 0;
@ -734,7 +743,9 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
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);
if (! parent)
@ -774,7 +785,9 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
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)
return NULL;
device_name = grub_strdup (parent->name);

View file

@ -27,8 +27,12 @@
int grub_disk_host_i_want_a_reference;
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"))
return 1;
return 0;

View file

@ -284,37 +284,46 @@ grub_biosdisk_call_hook (int (*hook) (const char *name), int drive)
}
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 drive;
/* For hard disks, attempt to read the MBR. */
for (drive = 0x80; drive < 0x90; drive++)
switch (pull)
{
if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
case GRUB_DISK_PULL_NONE:
for (drive = 0x80; drive < 0x90; drive++)
{
grub_dprintf ("disk", "Read error when probing drive 0x%2x\n", drive);
break;
if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
{
grub_dprintf ("disk", "Read error when probing drive 0x%2x\n", drive);
break;
}
if (grub_biosdisk_call_hook (hook, drive))
return 1;
}
return 0;
case GRUB_DISK_PULL_REMOVABLE:
if (cd_drive)
{
if (grub_biosdisk_call_hook (hook, cd_drive))
return 1;
}
if (grub_biosdisk_call_hook (hook, drive))
return 1;
/* For floppy disks, we can get the number safely. */
num_floppies = grub_biosdisk_get_num_floppies ();
for (drive = 0; drive < num_floppies; drive++)
if (grub_biosdisk_call_hook (hook, drive))
return 1;
return 0;
default:
return 0;
}
if (cd_drive)
{
if (grub_biosdisk_call_hook (hook, cd_drive))
return 1;
}
/* For floppy disks, we can get the number safely. */
num_floppies = grub_biosdisk_get_num_floppies ();
for (drive = 0; drive < num_floppies; drive++)
if (grub_biosdisk_call_hook (hook, drive))
return 1;
return 0;
}

View file

@ -32,7 +32,8 @@ struct grub_nand_data
};
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);
int dev_iterate (struct grub_ieee1275_devalias *alias)
@ -46,6 +47,9 @@ grub_nand_iterate (int (*hook) (const char *name))
return 0;
}
if (pull != GRUB_DISK_PULL_NONE)
return 0;
return grub_devalias_iterate (dev_iterate);
}

View file

@ -152,9 +152,14 @@ scan (void)
}
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;
if (pull != GRUB_DISK_PULL_NONE)
return 0;
scan ();
for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++)

View file

@ -133,9 +133,12 @@ fail:
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;
if (pull != GRUB_DISK_PULL_NONE)
return 0;
for (d = loopback_list; d; d = d->next)
{
if (hook (d->devname))

File diff suppressed because it is too large Load diff

View file

@ -30,8 +30,12 @@ static char *memdisk_addr;
static grub_off_t memdisk_size = 0;
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");
}

View file

@ -486,10 +486,14 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata)
}
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;
if (pull != GRUB_DISK_PULL_NONE)
return 0;
for (dev = grub_pata_devices; dev; dev = dev->next)
if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device))
return 1;

View file

@ -33,6 +33,11 @@ GRUB_MOD_LICENSE ("GPLv3+");
static struct grub_raid_array *array_list;
grub_raid5_recover_func_t grub_raid5_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
@ -78,14 +83,98 @@ grub_is_array_readable (struct grub_raid_array *array)
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
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;
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)
{
if (grub_is_array_readable (array))
if (grub_is_array_readable (array) && array->became_readable_at >= islcnt)
if (hook (array->name))
return 1;
}
@ -134,11 +223,10 @@ ascii2hex (char c)
return 0;
}
static grub_err_t
grub_raid_open (const char *name, grub_disk_t disk)
static struct grub_raid_array *
find_array (const char *name)
{
struct grub_raid_array *array;
unsigned n;
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
&& grub_memcmp (uuidbin, array->uuid, uuid_len) == 0)
if (grub_is_array_readable (array))
break;
return array;
}
}
else
@ -163,8 +251,33 @@ grub_raid_open (const char *name, grub_disk_t disk)
{
if (!grub_strcmp (array->name, name))
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)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s",
@ -524,6 +637,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
grub_raid_t raid __attribute__ ((unused)))
{
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
device from. */
@ -534,6 +648,8 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
grub_free (new_array->uuid);
array = p;
was_readable = grub_is_array_readable (array);
/* Do some checks before adding the device to the array. */
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].start_sector = start_sector;
array->nr_devs++;
if (!was_readable && grub_is_array_readable (array))
array->became_readable_at = inscnt++;
return 0;
}
static grub_raid_t grub_raid_list;
static void
free_array (void)
{
@ -772,45 +888,8 @@ free_array (void)
void
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;
grub_raid_list = raid;
grub_device_iterate (&hook);
}
void

View file

@ -322,7 +322,8 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector,
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;
@ -363,7 +364,7 @@ grub_scsi_iterate (int (*hook) (const char *name))
}
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 0;

View file

@ -211,10 +211,14 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
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;
if (pull != GRUB_DISK_PULL_NONE)
return 0;
grub_usb_poll_devices ();
for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++)