* util/grub.d/10_linux.in: Skip vmlinux-* on x86 platforms.

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-03-29 19:47:34 +02:00
parent 5c650f4c8e
commit fc18f6a3cb
4 changed files with 260 additions and 125 deletions

View file

@ -1,3 +1,7 @@
2011-03-29 Vladimir Serbinenko <phcoder@gmail.com>
* util/grub.d/10_linux.in: Skip vmlinux-* on x86 platforms.
2011-03-29 Colin Watson <cjwatson@ubuntu.com> 2011-03-29 Colin Watson <cjwatson@ubuntu.com>
* docs/grub.texi (loopback): New section. * docs/grub.texi (loopback): New section.

View file

@ -45,6 +45,7 @@ grub_lvm_getvalue (char **p, char *str)
return grub_strtoul (*p, NULL, 10); return grub_strtoul (*p, NULL, 10);
} }
#if 0
static int static int
grub_lvm_checkvalue (char **p, char *str, char *tmpl) grub_lvm_checkvalue (char **p, char *str, char *tmpl)
{ {
@ -57,6 +58,7 @@ grub_lvm_checkvalue (char **p, char *str, char *tmpl)
return 0; return 0;
return (grub_memcmp (*p + 1, tmpl, tmpllen) == 0 && (*p)[tmpllen + 1] == '"'); return (grub_memcmp (*p + 1, tmpl, tmpllen) == 0 && (*p)[tmpllen + 1] == '"');
} }
#endif
static int static int
grub_lvm_check_flag (char *p, char *str, char *flag) grub_lvm_check_flag (char *p, char *str, char *flag)
@ -100,7 +102,7 @@ grub_lvm_iterate (int (*hook) (const char *name))
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 (hook (lv->name)) if (lv->visible && hook (lv->name))
return 1; return 1;
} }
@ -164,11 +166,10 @@ grub_lvm_close (grub_disk_t disk __attribute ((unused)))
} }
static grub_err_t static grub_err_t
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector, read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
grub_size_t size, char *buf) grub_size_t size, char *buf)
{ {
grub_err_t err = 0; grub_err_t err = 0;
struct grub_lvm_lv *lv = disk->data;
struct grub_lvm_vg *vg = lv->vg; struct grub_lvm_vg *vg = lv->vg;
struct grub_lvm_segment *seg = lv->segments; struct grub_lvm_segment *seg = lv->segments;
struct grub_lvm_pv *pv; struct grub_lvm_pv *pv;
@ -176,6 +177,9 @@ grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_uint64_t extent; grub_uint64_t extent;
unsigned int i; unsigned int i;
if (!lv)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume");
extent = grub_divmod64 (sector, vg->extent_size, NULL); extent = grub_divmod64 (sector, vg->extent_size, NULL);
/* Find the right segment. */ /* Find the right segment. */
@ -190,6 +194,12 @@ grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
seg++; seg++;
} }
if (i == lv->segment_count)
return grub_error (GRUB_ERR_READ_ERROR, "incorrect segment");
switch (seg->type)
{
case GRUB_LVM_STRIPED:
if (seg->stripe_count == 1) if (seg->stripe_count == 1)
{ {
/* This segment is linear, so that's easy. We just need to find /* This segment is linear, so that's easy. We just need to find
@ -232,7 +242,6 @@ grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
offset += seg_offset; offset += seg_offset;
} }
/* 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 (pv->disk) if (pv->disk)
@ -243,6 +252,30 @@ grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
"physical volume %s not found", pv->name); "physical volume %s not found", pv->name);
return err; return err;
case GRUB_LVM_MIRROR:
i = 0;
while (1)
{
if (!seg->mirrors[i].lv)
err = grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume '%s'",
seg->mirrors[i].lvname);
else
err = read_lv (seg->mirrors[i].lv, sector, size, buf);
if (!err)
return err;
if (++i >= seg->mirror_count)
return err;
grub_errno = GRUB_ERR_NONE;
}
}
return grub_error (GRUB_ERR_IO, "unknown LVM segment");
}
static grub_err_t
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
return read_lv (disk->data, sector, size, buf);
} }
static grub_err_t static grub_err_t
@ -533,11 +566,7 @@ grub_lvm_scan_device (const char *name)
lv->size = 0; lv->size = 0;
if (!grub_lvm_check_flag (p, "status", "VISIBLE")) lv->visible = grub_lvm_check_flag (p, "status", "VISIBLE");
{
skip_lv = 1;
goto lv_parsed;
}
lv->segment_count = grub_lvm_getvalue (&p, "segment_count = "); lv->segment_count = grub_lvm_getvalue (&p, "segment_count = ");
if (p == NULL) if (p == NULL)
@ -552,7 +581,6 @@ grub_lvm_scan_device (const char *name)
for (i = 0; i < lv->segment_count; i++) for (i = 0; i < lv->segment_count; i++)
{ {
struct grub_lvm_stripe *stripe;
p = grub_strstr (p, "segment"); p = grub_strstr (p, "segment");
if (p == NULL) if (p == NULL)
@ -580,13 +608,19 @@ grub_lvm_scan_device (const char *name)
goto lvs_segment_fail; goto lvs_segment_fail;
} }
if (grub_lvm_checkvalue (&p, "type = ", "snapshot")) p = grub_strstr (p, "type = \"");
{ if (p == NULL)
/* Found a snapshot, give up and move on. */ goto lvs_segment_fail;
skip_lv = 1; p += sizeof("type = \"") - 1;
break;
}
lv->size += seg->extent_count * vg->extent_size;
if (grub_memcmp (p, "striped\"",
sizeof ("striped\"") - 1) == 0)
{
struct grub_lvm_stripe *stripe;
seg->type = GRUB_LVM_STRIPED;
seg->stripe_count = grub_lvm_getvalue (&p, "stripe_count = "); seg->stripe_count = grub_lvm_getvalue (&p, "stripe_count = ");
if (p == NULL) if (p == NULL)
{ {
@ -596,8 +630,6 @@ grub_lvm_scan_device (const char *name)
goto lvs_segment_fail; goto lvs_segment_fail;
} }
lv->size += seg->extent_count * vg->extent_size;
if (seg->stripe_count != 1) if (seg->stripe_count != 1)
seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
@ -653,6 +685,71 @@ grub_lvm_scan_device (const char *name)
stripe++; stripe++;
} }
}
else if (grub_memcmp (p, "mirror\"", sizeof ("mirror\"") - 1)
== 0)
{
seg->type = GRUB_LVM_MIRROR;
seg->mirror_count = grub_lvm_getvalue (&p, "mirror_count = ");
if (p == NULL)
{
#ifdef GRUB_UTIL
grub_util_info ("unknown mirror_count\n");
#endif
goto lvs_segment_fail;
}
seg->mirrors = grub_zalloc (sizeof (seg->mirrors[0])
* seg->mirror_count);
p = grub_strstr (p, "mirrors = [");
if (p == NULL)
{
#ifdef GRUB_UTIL
grub_util_info ("unknown mirrors\n");
#endif
goto lvs_segment_fail2;
}
p += sizeof("mirrors = [") - 1;
for (j = 0; j < seg->mirror_count; j++)
{
char *lvname;
p = grub_strchr (p, '"');
if (p == NULL)
continue;
q = ++p;
while (*q != '"')
q++;
s = q - p;
lvname = grub_malloc (s + 1);
if (lvname == NULL)
goto lvs_segment_fail2;
grub_memcpy (lvname, p, s);
lvname[s] = '\0';
seg->mirrors[j].lvname = lvname;
p = q + 1;
}
}
else
{
#ifdef GRUB_UTIL
char *p2;
p2 = grub_strchr (p, '"');
if (p2)
*p2 = 0;
grub_util_info ("unknown LVM type %s\n", p);
if (p2)
*p2 ='"';
#endif
/* Found a non-supported type, give up and move on. */
skip_lv = 1;
break;
}
seg++; seg++;
@ -663,7 +760,6 @@ grub_lvm_scan_device (const char *name)
goto fail4; goto fail4;
} }
lv_parsed:
if (p != NULL) if (p != NULL)
p = grub_strchr (p, '}'); p = grub_strchr (p, '}');
if (p == NULL) if (p == NULL)
@ -690,6 +786,20 @@ grub_lvm_scan_device (const char *name)
} }
} }
/* Match mirrors */
{
struct grub_lvm_lv *lv1;
struct grub_lvm_lv *lv2;
for (lv1 = vg->lvs; lv1; lv1 = lv1->next)
for (i = 0; i < lv1->segment_count; i++)
if (lv1->segments[i].type == GRUB_LVM_MIRROR)
for (j = 0; j < lv1->segments[i].mirror_count; j++)
for (lv2 = vg->lvs; lv2; lv2 = lv2->next)
if (grub_strcmp (lv2->name + grub_strlen (vg->name) + 1,
lv1->segments[i].mirrors[j].lvname) == 0)
lv1->segments[i].mirrors[j].lv = lv2;
}
vg->next = vg_list; vg->next = vg_list;
vg_list = vg; vg_list = vg;
} }

View file

@ -47,6 +47,9 @@ struct grub_lvm_lv {
unsigned int number; unsigned int number;
unsigned int segment_count; unsigned int segment_count;
grub_uint64_t size; grub_uint64_t size;
int visible;
struct grub_lvm_segment *segments; /* Pointer to segment_count segments. */ struct grub_lvm_segment *segments; /* Pointer to segment_count segments. */
struct grub_lvm_vg *vg; struct grub_lvm_vg *vg;
struct grub_lvm_lv *next; struct grub_lvm_lv *next;
@ -55,6 +58,11 @@ struct grub_lvm_lv {
struct grub_lvm_segment { struct grub_lvm_segment {
unsigned int start_extent; unsigned int start_extent;
unsigned int extent_count; unsigned int extent_count;
enum { GRUB_LVM_STRIPED, GRUB_LVM_MIRROR } type;
unsigned int mirror_count;
struct grub_lvm_mirror *mirrors;
unsigned int stripe_count; unsigned int stripe_count;
unsigned int stripe_size; unsigned int stripe_size;
struct grub_lvm_stripe *stripes; /* Pointer to stripe_count stripes. */ struct grub_lvm_stripe *stripes; /* Pointer to stripe_count stripes. */
@ -65,6 +73,11 @@ struct grub_lvm_stripe {
struct grub_lvm_pv *pv; struct grub_lvm_pv *pv;
}; };
struct grub_lvm_mirror {
char *lvname;
struct grub_lvm_lv *lv;
};
#define GRUB_LVM_LABEL_SIZE GRUB_DISK_SECTOR_SIZE #define GRUB_LVM_LABEL_SIZE GRUB_DISK_SECTOR_SIZE
#define GRUB_LVM_LABEL_SCAN_SECTORS 4L #define GRUB_LVM_LABEL_SCAN_SECTORS 4L

View file

@ -111,9 +111,17 @@ EOF
EOF EOF
} }
list=`for i in /boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* ; do case x`uname -m` in
xi?86 | xx86_64)
list=`for i in /boot/vmlinuz-* /vmlinuz-* ; do
if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
done` done` ;;
*)
list=`for i in /boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* ; do
if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
done` ;;
esac
prepare_boot_cache= prepare_boot_cache=
while [ "x$list" != "x" ] ; do while [ "x$list" != "x" ] ; do