Lazy LVM and RAID assembly
This commit is contained in:
parent
9b710a888e
commit
24b905a11c
13 changed files with 365 additions and 114 deletions
|
@ -666,10 +666,14 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_ata_iterate (int (*hook) (const char *name))
|
grub_ata_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
struct grub_ata_device *dev;
|
struct grub_ata_device *dev;
|
||||||
|
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
for (dev = grub_ata_devices; dev; dev = dev->next)
|
for (dev = grub_ata_devices; dev; dev = dev->next)
|
||||||
{
|
{
|
||||||
char devname[10];
|
char devname[10];
|
||||||
|
@ -696,7 +700,8 @@ grub_ata_iterate (int (*hook) (const char *name))
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_ata_open (const char *name, grub_disk_t disk)
|
grub_ata_open (const char *name, grub_disk_t disk,
|
||||||
|
grub_disk_pull_t pull __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
struct grub_ata_device *dev;
|
struct grub_ata_device *dev;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
|
|
@ -27,15 +27,20 @@
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_host_open (const char *name, grub_disk_t disk)
|
grub_host_open (const char *name, grub_disk_t disk,
|
||||||
|
grub_disk_pull_t pull __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
if (grub_strcmp (name, "host"))
|
if (grub_strcmp (name, "host"))
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a host disk");
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a host disk");
|
||||||
|
|
|
@ -284,42 +284,52 @@ 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. */
|
||||||
for (drive = 0x80; drive < 0x90; drive++)
|
switch (pull)
|
||||||
{
|
{
|
||||||
if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
|
case GRUB_DISK_PULL_NONE:
|
||||||
GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
|
for (drive = 0x80; drive < 0x90; drive++)
|
||||||
{
|
{
|
||||||
grub_dprintf ("disk", "Read error when probing drive 0x%2x\n", drive);
|
if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
|
||||||
break;
|
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))
|
/* For floppy disks, we can get the number safely. */
|
||||||
return 1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_biosdisk_open (const char *name, grub_disk_t disk)
|
grub_biosdisk_open (const char *name, grub_disk_t disk,
|
||||||
|
grub_disk_pull_t pull __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
grub_uint64_t total_sectors = 0;
|
grub_uint64_t total_sectors = 0;
|
||||||
int drive;
|
int drive;
|
||||||
|
|
|
@ -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))
|
||||||
|
@ -145,7 +148,8 @@ grub_loopback_iterate (int (*hook) (const char *name))
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_loopback_open (const char *name, grub_disk_t disk)
|
grub_loopback_open (const char *name, grub_disk_t disk,
|
||||||
|
grub_disk_pull_t pull __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
struct grub_loopback *dev;
|
struct grub_loopback *dev;
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,12 @@ 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);
|
||||||
|
|
||||||
|
static int
|
||||||
|
grub_lvm_scan_device (const char *name);
|
||||||
|
|
||||||
/* 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
|
||||||
at the number. In case STR is not found, *P will be NULL and the
|
at the number. In case STR is not found, *P will be NULL and the
|
||||||
|
@ -96,16 +101,39 @@ grub_lvm_check_flag (char *p, char *str, char *flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_lvm_iterate (int (*hook) (const char *name))
|
grub_lvm_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
struct grub_lvm_vg *vg;
|
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)
|
||||||
|
{
|
||||||
|
scan_depth++;
|
||||||
|
grub_device_iterate (&grub_lvm_scan_device);
|
||||||
|
scan_depth--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pull != GRUB_DISK_PULL_RESCAN && pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
for (vg = vg_list; vg; vg = vg->next)
|
for (vg = vg_list; vg; vg = vg->next)
|
||||||
{
|
{
|
||||||
struct grub_lvm_lv *lv;
|
struct grub_lvm_lv *lv;
|
||||||
if (vg->lvs)
|
if (vg->lvs)
|
||||||
for (lv = vg->lvs; lv; lv = lv->next)
|
for (lv = vg->lvs; lv; lv = lv->next)
|
||||||
if (lv->visible && hook (lv->name))
|
if (lv->visible && lv->number >= old_count)
|
||||||
return 1;
|
{
|
||||||
|
char lvname[sizeof ("lvm/") + grub_strlen (lv->name)];
|
||||||
|
grub_memcpy (lvname, "lvm/", sizeof ("lvm/") - 1);
|
||||||
|
grub_strcpy (lvname + sizeof ("lvm/") - 1, lv->name);
|
||||||
|
if (hook (lvname))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -135,8 +163,8 @@ grub_lvm_memberlist (grub_disk_t disk)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static grub_err_t
|
static struct grub_lvm_lv *
|
||||||
grub_lvm_open (const char *name, grub_disk_t disk)
|
find_lv (const char *name)
|
||||||
{
|
{
|
||||||
struct grub_lvm_vg *vg;
|
struct grub_lvm_vg *vg;
|
||||||
struct grub_lvm_lv *lv = NULL;
|
struct grub_lvm_lv *lv = NULL;
|
||||||
|
@ -144,11 +172,43 @@ 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->name, name) && is_lv_readable (lv))
|
||||||
break;
|
return lv;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (lv)
|
static const char *scan_for = NULL;
|
||||||
break;
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_lvm_open (const char *name, grub_disk_t disk,
|
||||||
|
grub_disk_pull_t pull)
|
||||||
|
{
|
||||||
|
struct grub_lvm_lv *lv = NULL;
|
||||||
|
int explicit = 0;
|
||||||
|
|
||||||
|
if (grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) == 0)
|
||||||
|
{
|
||||||
|
name += sizeof ("lvm/") - 1;
|
||||||
|
explicit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv = find_lv (name);
|
||||||
|
|
||||||
|
if (! lv && !scan_depth &&
|
||||||
|
pull == (explicit ? GRUB_DISK_PULL_RESCAN : GRUB_DISK_PULL_RESCAN_UNTYPED))
|
||||||
|
{
|
||||||
|
scan_for = name;
|
||||||
|
scan_depth++;
|
||||||
|
grub_device_iterate (&grub_lvm_scan_device);
|
||||||
|
scan_depth--;
|
||||||
|
scan_for = NULL;
|
||||||
|
if (grub_errno)
|
||||||
|
{
|
||||||
|
grub_print_error ();
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
lv = find_lv (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! lv)
|
if (! lv)
|
||||||
|
@ -285,6 +345,49 @@ read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
|
||||||
return grub_error (GRUB_ERR_IO, "unknown LVM segment");
|
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
|
static grub_err_t
|
||||||
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
|
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
grub_size_t size, char *buf)
|
grub_size_t size, char *buf)
|
||||||
|
@ -332,6 +435,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++)
|
||||||
{
|
{
|
||||||
|
@ -857,6 +969,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -878,13 +992,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,13 +30,18 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_memdisk_open (const char *name, grub_disk_t disk)
|
grub_memdisk_open (const char *name, grub_disk_t disk,
|
||||||
|
grub_disk_pull_t pull __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
if (grub_strcmp (name, "memdisk"))
|
if (grub_strcmp (name, "memdisk"))
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a memdisk");
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a memdisk");
|
||||||
|
|
|
@ -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,8 +251,33 @@ 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, grub_disk_pull_t pull)
|
||||||
|
{
|
||||||
|
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 && pull == GRUB_DISK_PULL_RESCAN)
|
||||||
|
{
|
||||||
|
scan_devices (name);
|
||||||
|
if (grub_errno)
|
||||||
|
{
|
||||||
|
grub_print_error ();
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
array = find_array (name);
|
||||||
|
}
|
||||||
|
|
||||||
if (!array)
|
if (!array)
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s",
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s",
|
||||||
|
@ -690,15 +803,19 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the device to the array. */
|
/* Add the device to the array. */
|
||||||
array->members[new_array->index].device = disk;
|
{
|
||||||
array->members[new_array->index].start_sector = start_sector;
|
int was_readable = grub_is_array_readable (array);
|
||||||
array->nr_devs++;
|
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_raid_t grub_raid_list;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_array (void)
|
free_array (void)
|
||||||
{
|
{
|
||||||
|
@ -729,45 +846,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
|
||||||
|
|
|
@ -316,7 +316,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;
|
||||||
|
|
||||||
|
@ -356,6 +357,9 @@ grub_scsi_iterate (int (*hook) (const char *name))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
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))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -364,7 +368,8 @@ grub_scsi_iterate (int (*hook) (const char *name))
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_scsi_open (const char *name, grub_disk_t disk)
|
grub_scsi_open (const char *name, grub_disk_t disk,
|
||||||
|
grub_disk_pull_t pull __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
grub_scsi_dev_t p;
|
grub_scsi_dev_t p;
|
||||||
grub_scsi_t scsi;
|
grub_scsi_t scsi;
|
||||||
|
|
|
@ -104,8 +104,12 @@ grub_pxe_scan (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_pxe_iterate (int (*hook) (const char *name))
|
grub_pxe_iterate (int (*hook) (const char *name),
|
||||||
|
grub_disk_pull_t pull)
|
||||||
{
|
{
|
||||||
|
if (pull != GRUB_DISK_PULL_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (hook ("pxe"))
|
if (hook ("pxe"))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -139,7 +143,8 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_pxe_open (const char *name, grub_disk_t disk)
|
grub_pxe_open (const char *name, grub_disk_t disk,
|
||||||
|
grub_disk_pull_t pull __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
struct grub_pxe_disk_data *data;
|
struct grub_pxe_disk_data *data;
|
||||||
|
|
||||||
|
|
|
@ -207,10 +207,16 @@ 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 (p = grub_disk_dev_list; p; p = p->next)
|
for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
|
||||||
if (p->iterate && (p->iterate) (hook))
|
{
|
||||||
return 1;
|
if (pull == GRUB_DISK_PULL_RESCAN_UNTYPED)
|
||||||
|
continue;
|
||||||
|
for (p = grub_disk_dev_list; p; p = p->next)
|
||||||
|
if (p->iterate && (p->iterate) (hook, pull))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -241,6 +247,7 @@ grub_disk_open (const char *name)
|
||||||
grub_disk_dev_t dev;
|
grub_disk_dev_t dev;
|
||||||
char *raw = (char *) name;
|
char *raw = (char *) name;
|
||||||
grub_uint64_t current_time;
|
grub_uint64_t current_time;
|
||||||
|
grub_disk_pull_t pull;
|
||||||
|
|
||||||
grub_dprintf ("disk", "Opening `%s'...\n", name);
|
grub_dprintf ("disk", "Opening `%s'...\n", name);
|
||||||
|
|
||||||
|
@ -266,15 +273,19 @@ grub_disk_open (const char *name)
|
||||||
if (! disk->name)
|
if (! disk->name)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
|
||||||
for (dev = grub_disk_dev_list; dev; dev = dev->next)
|
|
||||||
{
|
{
|
||||||
if ((dev->open) (raw, disk) == GRUB_ERR_NONE)
|
for (dev = grub_disk_dev_list; dev; dev = dev->next)
|
||||||
|
{
|
||||||
|
if ((dev->open) (raw, disk, pull) == GRUB_ERR_NONE)
|
||||||
|
break;
|
||||||
|
else if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE)
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
else
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (dev)
|
||||||
break;
|
break;
|
||||||
else if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE)
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
else
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! dev)
|
if (! dev)
|
||||||
|
|
|
@ -212,7 +212,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;
|
||||||
|
|
||||||
|
@ -224,7 +225,8 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name))
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
grub_util_biosdisk_open (const char *name, grub_disk_t disk,
|
||||||
|
grub_disk_pull_t pull __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
int drive;
|
int drive;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
|
@ -50,6 +50,15 @@ 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_RESCAN_UNTYPED,
|
||||||
|
GRUB_DISK_PULL_MAX
|
||||||
|
} grub_disk_pull_t;
|
||||||
|
|
||||||
/* Disk device. */
|
/* Disk device. */
|
||||||
struct grub_disk_dev
|
struct grub_disk_dev
|
||||||
{
|
{
|
||||||
|
@ -60,10 +69,12 @@ 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,
|
||||||
|
grub_disk_pull_t pull);
|
||||||
|
|
||||||
/* Close the disk DISK. */
|
/* Close the disk DISK. */
|
||||||
void (*close) (struct grub_disk *disk);
|
void (*close) (struct grub_disk *disk);
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
Loading…
Reference in a new issue