From 24b905a11c90e47cb271397bd507e0496fe130e7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 00:09:07 +0200 Subject: [PATCH] Lazy LVM and RAID assembly --- grub-core/disk/ata.c | 9 +- grub-core/disk/host.c | 9 +- grub-core/disk/i386/pc/biosdisk.c | 56 ++++++---- grub-core/disk/loopback.c | 8 +- grub-core/disk/lvm.c | 139 ++++++++++++++++++++--- grub-core/disk/memdisk.c | 9 +- grub-core/disk/raid.c | 178 ++++++++++++++++++++++-------- grub-core/disk/scsi.c | 9 +- grub-core/fs/i386/pc/pxe.c | 9 +- grub-core/kern/disk.c | 31 ++++-- grub-core/kern/emu/hostdisk.c | 6 +- include/grub/disk.h | 15 ++- include/grub/raid.h | 1 + 13 files changed, 365 insertions(+), 114 deletions(-) diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 7f261560d..3a43a8cae 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -666,10 +666,14 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, 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; + if (pull != GRUB_DISK_PULL_NONE) + return 0; + for (dev = grub_ata_devices; dev; dev = dev->next) { char devname[10]; @@ -696,7 +700,8 @@ grub_ata_iterate (int (*hook) (const char *name)) } 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; grub_err_t err; diff --git a/grub-core/disk/host.c b/grub-core/disk/host.c index c51966293..5376cc6ce 100644 --- a/grub-core/disk/host.c +++ b/grub-core/disk/host.c @@ -27,15 +27,20 @@ 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; } 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")) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a host disk"); diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 1d47dc727..e75ab184b 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -284,42 +284,52 @@ 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; } 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; int drive; diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c index d50f353b1..21345af57 100644 --- a/grub-core/disk/loopback.c +++ b/grub-core/disk/loopback.c @@ -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)) @@ -145,7 +148,8 @@ grub_loopback_iterate (int (*hook) (const char *name)) } 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; diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 206e3e220..72f493540 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -32,7 +32,12 @@ GRUB_MOD_LICENSE ("GPLv3+"); static struct grub_lvm_vg *vg_list; 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 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 -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; + 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) { struct grub_lvm_lv *lv; if (vg->lvs) for (lv = vg->lvs; lv; lv = lv->next) - if (lv->visible && hook (lv->name)) - return 1; + if (lv->visible && lv->number >= old_count) + { + 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; @@ -135,8 +163,8 @@ grub_lvm_memberlist (grub_disk_t disk) } #endif -static grub_err_t -grub_lvm_open (const char *name, grub_disk_t disk) +static struct grub_lvm_lv * +find_lv (const char *name) { struct grub_lvm_vg *vg; struct grub_lvm_lv *lv = NULL; @@ -144,11 +172,43 @@ grub_lvm_open (const char *name, grub_disk_t disk) { if (vg->lvs) for (lv = vg->lvs; lv; lv = lv->next) - if (! grub_strcmp (lv->name, name)) - break; + if (! grub_strcmp (lv->name, name) && is_lv_readable (lv)) + return lv; + } + return NULL; +} - if (lv) - break; +static const char *scan_for = NULL; + +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) @@ -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"); } +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) @@ -332,6 +435,15 @@ grub_lvm_scan_device (const char *name) 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. */ 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) grub_errno = GRUB_ERR_NONE; grub_print_error (); + if (scan_for && find_lv (scan_for)) + return 1; return 0; } @@ -878,13 +992,6 @@ static struct grub_disk_dev grub_lvm_dev = 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); } diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c index 114ac0d9e..775234055 100644 --- a/grub-core/disk/memdisk.c +++ b/grub-core/disk/memdisk.c @@ -30,13 +30,18 @@ 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"); } 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")) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a memdisk"); diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index 946e6d2c2..78453ac88 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -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, 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) 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. */ - array->members[new_array->index].device = disk; - array->members[new_array->index].start_sector = start_sector; - array->nr_devs++; + { + int was_readable = grub_is_array_readable (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) { @@ -729,45 +846,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 diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 25f0e3aea..e85036860 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -316,7 +316,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; @@ -356,6 +357,9 @@ grub_scsi_iterate (int (*hook) (const char *name)) return 0; } + if (pull != GRUB_DISK_PULL_NONE) + return 0; + for (p = grub_scsi_dev_list; p; p = p->next) if (p->iterate && (p->iterate) (scsi_iterate)) return 1; @@ -364,7 +368,8 @@ grub_scsi_iterate (int (*hook) (const char *name)) } 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_t scsi; diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index d6dc2c22d..929f44587 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -104,8 +104,12 @@ grub_pxe_scan (void) } 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")) return 1; return 0; @@ -139,7 +143,8 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest) } 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; diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 807ee4277..9c2c70b80 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -207,10 +207,16 @@ int grub_disk_dev_iterate (int (*hook) (const char *name)) { grub_disk_dev_t p; + grub_disk_pull_t pull; - for (p = grub_disk_dev_list; p; p = p->next) - if (p->iterate && (p->iterate) (hook)) - return 1; + for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++) + { + 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; } @@ -241,6 +247,7 @@ grub_disk_open (const char *name) grub_disk_dev_t dev; char *raw = (char *) name; grub_uint64_t current_time; + grub_disk_pull_t pull; grub_dprintf ("disk", "Opening `%s'...\n", name); @@ -266,15 +273,19 @@ grub_disk_open (const char *name) if (! disk->name) goto fail; - - for (dev = grub_disk_dev_list; dev; dev = dev->next) + for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++) { - 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; - else if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE) - grub_errno = GRUB_ERR_NONE; - else - goto fail; } if (! dev) diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 63bca37ee..3ee6174d0 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -212,7 +212,8 @@ find_free_slot (void) } 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; @@ -224,7 +225,8 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name)) } 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; struct stat st; diff --git a/include/grub/disk.h b/include/grub/disk.h index 66db1149a..2678ad5eb 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -50,6 +50,15 @@ struct grub_disk; struct grub_disk_memberlist; #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. */ struct grub_disk_dev { @@ -60,10 +69,12 @@ struct grub_disk_dev enum grub_disk_dev_id id; /* 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. */ - 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. */ void (*close) (struct grub_disk *disk); diff --git a/include/grub/raid.h b/include/grub/raid.h index d5853639d..1eb43721a 100644 --- a/include/grub/raid.h +++ b/include/grub/raid.h @@ -42,6 +42,7 @@ struct grub_raid_array int number; /* The device number, taken from md_minor so we are consistent with the device name in Linux. */ + int became_readable_at; int level; /* RAID levels, only 0, 1 or 5 at the moment. */ int layout; /* Layout for RAID 5/6. */ unsigned int total_devs; /* Total number of devices in the array. */