* grub-core/disk/diskfilter.c (is_lv_readable): New argument "easily".

All users updated. If easily=1 require raid-5/-6 to be full.
	(is_node_readable): Likewise.
	(scan_devices): Scan incomplete but readable LVs at the end.
	(grub_diskfilter_memberlist): Pull missing devices.
	(insert_array): Skip scanning until device is complete or scan is
	done otherwise.
	* grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Fix wrong
	check.
	* include/grub/diskfilter.h (grub_diskfilter_lv): New member scanned.
	* util/raid.c (grub_util_raid_getmembers): Handle "removed" disks.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2012-03-04 01:33:09 +01:00
parent aff05d45f9
commit 49de079bbe
5 changed files with 89 additions and 35 deletions

View file

@ -1,3 +1,17 @@
2012-03-03 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/disk/diskfilter.c (is_lv_readable): New argument "easily".
All users updated. If easily=1 require raid-5/-6 to be full.
(is_node_readable): Likewise.
(scan_devices): Scan incomplete but readable LVs at the end.
(grub_diskfilter_memberlist): Pull missing devices.
(insert_array): Skip scanning until device is complete or scan is
done otherwise.
* grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Fix wrong
check.
* include/grub/diskfilter.h (grub_diskfilter_lv): New member scanned.
* util/raid.c (grub_util_raid_getmembers): Handle "removed" disks.
2012-03-03 Matthew Garrett <mjg@redhat.com> 2012-03-03 Matthew Garrett <mjg@redhat.com>
2012-03-03 Vladimir Serbinenko <phcoder@gmail.com> 2012-03-03 Vladimir Serbinenko <phcoder@gmail.com>

View file

@ -41,24 +41,24 @@ static int lv_num = 0;
static struct grub_diskfilter_lv * static struct grub_diskfilter_lv *
find_lv (const char *name); find_lv (const char *name);
static int is_lv_readable (struct grub_diskfilter_lv *lv); static int is_lv_readable (struct grub_diskfilter_lv *lv, int easily);
static grub_err_t static grub_err_t
is_node_readable (const struct grub_diskfilter_node *node) is_node_readable (const struct grub_diskfilter_node *node, int easily)
{ {
/* Check whether we actually know the physical volume we want to /* Check whether we actually know the physical volume we want to
read from. */ read from. */
if (node->pv) if (node->pv)
return !!(node->pv->disk); return !!(node->pv->disk);
if (node->lv) if (node->lv)
return is_lv_readable (node->lv); return is_lv_readable (node->lv, easily);
return 0; return 0;
} }
static int static int
is_lv_readable (struct grub_diskfilter_lv *lv) is_lv_readable (struct grub_diskfilter_lv *lv, int easily)
{ {
unsigned i, j; unsigned i, j;
if (!lv) if (!lv)
@ -69,9 +69,11 @@ is_lv_readable (struct grub_diskfilter_lv *lv)
switch (lv->segments[i].type) switch (lv->segments[i].type)
{ {
case GRUB_DISKFILTER_RAID6: case GRUB_DISKFILTER_RAID6:
if (!easily)
need--; need--;
case GRUB_DISKFILTER_RAID4: case GRUB_DISKFILTER_RAID4:
case GRUB_DISKFILTER_RAID5: case GRUB_DISKFILTER_RAID5:
if (!easily)
need--; need--;
case GRUB_DISKFILTER_STRIPED: case GRUB_DISKFILTER_STRIPED:
break; break;
@ -92,7 +94,7 @@ is_lv_readable (struct grub_diskfilter_lv *lv)
} }
for (j = 0; j < lv->segments[i].node_count; j++) for (j = 0; j < lv->segments[i].node_count; j++)
{ {
if (is_node_readable (lv->segments[i].nodes + j)) if (is_node_readable (lv->segments[i].nodes + j, easily))
have++; have++;
if (have >= need) if (have >= need)
break; break;
@ -192,6 +194,8 @@ scan_devices (const char *arname)
{ {
grub_disk_dev_t p; grub_disk_dev_t p;
grub_disk_pull_t pull; grub_disk_pull_t pull;
struct grub_diskfilter_vg *vg;
struct grub_diskfilter_lv *lv = NULL;
for (pull = 0; pull < GRUB_DISK_PULL_MAX; 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)
@ -200,9 +204,20 @@ scan_devices (const char *arname)
{ {
if ((p->iterate) (scan_disk, pull)) if ((p->iterate) (scan_disk, pull))
return; return;
if (arname && is_lv_readable (find_lv (arname))) if (arname && is_lv_readable (find_lv (arname), 1))
return; return;
} }
for (vg = array_list; vg; vg = vg->next)
{
if (vg->lvs)
for (lv = vg->lvs; lv; lv = lv->next)
if (!lv->scanned && lv->fullname && lv->became_readable_at)
{
scan_disk (lv->fullname);
lv->scanned = 1;
}
}
} }
static int static int
@ -243,8 +258,26 @@ grub_diskfilter_memberlist (grub_disk_t disk)
struct grub_diskfilter_lv *lv = disk->data; struct grub_diskfilter_lv *lv = disk->data;
grub_disk_memberlist_t list = NULL, tmp; grub_disk_memberlist_t list = NULL, tmp;
struct grub_diskfilter_pv *pv; struct grub_diskfilter_pv *pv;
grub_disk_pull_t pull;
grub_disk_dev_t p;
if (!lv->vg->pvs)
return NULL;
pv = lv->vg->pvs;
while (pv && pv->disk)
pv = pv->next;
for (pull = 0; pv && pull < GRUB_DISK_PULL_MAX; pull++)
for (p = grub_disk_dev_list; pv && p; p = p->next)
if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
&& p->iterate)
{
(p->iterate) (scan_disk, pull);
while (pv && pv->disk)
pv = pv->next;
}
if (lv->vg->pvs)
for (pv = lv->vg->pvs; pv; pv = pv->next) for (pv = lv->vg->pvs; pv; pv = pv->next)
{ {
if (!pv->disk) if (!pv->disk)
@ -318,7 +351,7 @@ find_lv (const char *name)
{ {
if (uuid_len == vg->uuid_len if (uuid_len == vg->uuid_len
&& grub_memcmp (uuidbin, vg->uuid, uuid_len) == 0) && grub_memcmp (uuidbin, vg->uuid, uuid_len) == 0)
if (is_lv_readable (vg->lvs)) if (is_lv_readable (vg->lvs, 0))
return vg->lvs; return vg->lvs;
} }
} }
@ -328,7 +361,7 @@ find_lv (const char *name)
if (vg->lvs) if (vg->lvs)
for (lv = vg->lvs; lv; lv = lv->next) for (lv = vg->lvs; lv; lv = lv->next)
if (lv->fullname && grub_strcmp (lv->fullname, name) == 0 if (lv->fullname && grub_strcmp (lv->fullname, name) == 0
&& is_lv_readable (lv)) && is_lv_readable (lv, 0))
return lv; return lv;
} }
return NULL; return NULL;
@ -997,10 +1030,14 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id,
pv->start_sector += pv->part_start; pv->start_sector += pv->part_start;
/* Add the device to the array. */ /* Add the device to the array. */
for (lv = array->lvs; lv; lv = lv->next) for (lv = array->lvs; lv; lv = lv->next)
if (!lv->became_readable_at && lv->fullname && is_lv_readable (lv)) if (!lv->became_readable_at && lv->fullname && is_lv_readable (lv, 0))
{ {
lv->became_readable_at = ++inscnt; lv->became_readable_at = ++inscnt;
if (is_lv_readable (lv, 1))
{
scan_disk (lv->fullname); scan_disk (lv->fullname);
lv->scanned = 1;
}
} }
break; break;
} }

View file

@ -177,17 +177,17 @@ grub_mdraid_detect (grub_disk_t disk,
/* Spares aren't implemented. */ /* Spares aren't implemented. */
return NULL; return NULL;
if (grub_le_to_cpu32 (sb.dev_number)
>= grub_le_to_cpu32 (sb.raid_disks))
/* Spares aren't implemented. */
return NULL;
if (grub_disk_read (disk, sector, if (grub_disk_read (disk, sector,
(char *) &sb.dev_roles[sb.dev_number] (char *) &sb.dev_roles[sb.dev_number]
- (char *) &sb, - (char *) &sb,
sizeof (role), &role)) sizeof (role), &role))
return NULL; return NULL;
if (grub_le_to_cpu16 (role)
>= grub_le_to_cpu32 (sb.raid_disks))
/* Spares aren't implemented. */
return NULL;
id->uuidlen = 0; id->uuidlen = 0;
id->id = grub_le_to_cpu16 (role); id->id = grub_le_to_cpu16 (role);

View file

@ -87,7 +87,7 @@ struct grub_diskfilter_lv {
grub_size_t segment_alloc; grub_size_t segment_alloc;
grub_uint64_t size; grub_uint64_t size;
int became_readable_at; int became_readable_at;
int scanned;
int visible; int visible;
/* Pointer to segment_count segments. */ /* Pointer to segment_count segments. */

View file

@ -70,20 +70,23 @@ grub_util_raid_getmembers (const char *name, int bootable)
devicelist = xmalloc ((info.nr_disks + 1) * sizeof (char *)); devicelist = xmalloc ((info.nr_disks + 1) * sizeof (char *));
for (i = 0, j = 0; i <info.nr_disks; i++) for (i = 0, j = 0; j < info.nr_disks; i++)
{ {
disk.number = i; disk.number = i;
ret = ioctl (fd, GET_DISK_INFO, &disk); ret = ioctl (fd, GET_DISK_INFO, &disk);
if (ret != 0) if (ret != 0)
grub_util_error (_("ioctl GET_DISK_INFO error: %s"), strerror (errno)); grub_util_error (_("ioctl GET_DISK_INFO error: %s"), strerror (errno));
if (disk.state & (1 << MD_DISK_REMOVED))
continue;
if (disk.state & (1 << MD_DISK_ACTIVE)) if (disk.state & (1 << MD_DISK_ACTIVE))
{
devicelist[j] = grub_find_device (NULL, devicelist[j] = grub_find_device (NULL,
makedev (disk.major, disk.minor)); makedev (disk.major, disk.minor));
else
devicelist[j] = NULL;
j++; j++;
} }
}
devicelist[j] = NULL; devicelist[j] = NULL;