* 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:
parent
aff05d45f9
commit
49de079bbe
5 changed files with 89 additions and 35 deletions
14
ChangeLog
14
ChangeLog
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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,10 +69,12 @@ 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:
|
||||||
need--;
|
if (!easily)
|
||||||
|
need--;
|
||||||
case GRUB_DISKFILTER_RAID4:
|
case GRUB_DISKFILTER_RAID4:
|
||||||
case GRUB_DISKFILTER_RAID5:
|
case GRUB_DISKFILTER_RAID5:
|
||||||
need--;
|
if (!easily)
|
||||||
|
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,18 +258,36 @@ 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)
|
if (!lv->vg->pvs)
|
||||||
for (pv = lv->vg->pvs; pv; pv = pv->next)
|
return NULL;
|
||||||
{
|
|
||||||
if (!pv->disk)
|
pv = lv->vg->pvs;
|
||||||
grub_util_error (_("Couldn't find physical volume `%s'."
|
while (pv && pv->disk)
|
||||||
" Check your device.map"), pv->name);
|
pv = pv->next;
|
||||||
tmp = grub_malloc (sizeof (*tmp));
|
|
||||||
tmp->disk = pv->disk;
|
for (pull = 0; pv && pull < GRUB_DISK_PULL_MAX; pull++)
|
||||||
tmp->next = list;
|
for (p = grub_disk_dev_list; pv && p; p = p->next)
|
||||||
list = tmp;
|
if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
|
||||||
}
|
&& p->iterate)
|
||||||
|
{
|
||||||
|
(p->iterate) (scan_disk, pull);
|
||||||
|
while (pv && pv->disk)
|
||||||
|
pv = pv->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (pv = lv->vg->pvs; pv; pv = pv->next)
|
||||||
|
{
|
||||||
|
if (!pv->disk)
|
||||||
|
grub_util_error (_("Couldn't find physical volume `%s'."
|
||||||
|
" Check your device.map"), pv->name);
|
||||||
|
tmp = grub_malloc (sizeof (*tmp));
|
||||||
|
tmp->disk = pv->disk;
|
||||||
|
tmp->next = list;
|
||||||
|
list = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
scan_disk (lv->fullname);
|
if (is_lv_readable (lv, 1))
|
||||||
|
{
|
||||||
|
scan_disk (lv->fullname);
|
||||||
|
lv->scanned = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
15
util/raid.c
15
util/raid.c
|
@ -70,19 +70,22 @@ 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
|
||||||
j++;
|
devicelist[j] = NULL;
|
||||||
}
|
j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
devicelist[j] = NULL;
|
devicelist[j] = NULL;
|
||||||
|
|
Loading…
Reference in a new issue