]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
* util/grub.d/10_linux.in: Skip vmlinux-* on x86 platforms.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 29 Mar 2011 17:47:34 +0000 (19:47 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 29 Mar 2011 17:47:34 +0000 (19:47 +0200)
ChangeLog
grub-core/disk/lvm.c
include/grub/lvm.h
util/grub.d/10_linux.in

index cf7b1b0d6f610bf1c698392c74589e9c2d15f81b..dcacc600c42fec1a8bdf7bd39c66822b50789fb2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
        * docs/grub.texi (loopback): New section.
index 39fa84d917adba0d198a28c88b8b5c24dc07ebe0..b1a7a50a9d57adb015806aa526224d2825112de0 100644 (file)
@@ -45,6 +45,7 @@ grub_lvm_getvalue (char **p, char *str)
   return grub_strtoul (*p, NULL, 10);
 }
 
+#if 0
 static int
 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 (grub_memcmp (*p + 1, tmpl, tmpllen) == 0 && (*p)[tmpllen + 1] == '"');
 }
+#endif
 
 static int
 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;
       if (vg->lvs)
        for (lv = vg->lvs; lv; lv = lv->next)
-         if (hook (lv->name))
+         if (lv->visible && hook (lv->name))
            return 1;
     }
 
@@ -164,11 +166,10 @@ grub_lvm_close (grub_disk_t disk __attribute ((unused)))
 }
 
 static grub_err_t
-grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
-               grub_size_t size, char *buf)
+read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
+        grub_size_t size, char *buf)
 {
   grub_err_t err = 0;
-  struct grub_lvm_lv *lv = disk->data;
   struct grub_lvm_vg *vg = lv->vg;
   struct grub_lvm_segment *seg = lv->segments;
   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;
   unsigned int i;
 
+  if (!lv)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume");
+
   extent = grub_divmod64 (sector, vg->extent_size, NULL);
 
   /* Find the right segment.  */
@@ -190,59 +194,88 @@ grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
       seg++;
     }
 
-  if (seg->stripe_count == 1)
-    {
-      /* This segment is linear, so that's easy.  We just need to find
-        out the offset in the physical volume and read SIZE bytes
-        from that.  */
-      struct grub_lvm_stripe *stripe = seg->stripes;
-      grub_uint64_t seg_offset; /* Offset of the segment in PV device.  */
-
-      pv = stripe->pv;
-      seg_offset = ((grub_uint64_t) stripe->start
-                   * (grub_uint64_t) vg->extent_size) + pv->start;
-
-      offset = sector - ((grub_uint64_t) seg->start_extent
-                        * (grub_uint64_t) vg->extent_size) + seg_offset;
-    }
-  else
+  if (i == lv->segment_count)
+    return grub_error (GRUB_ERR_READ_ERROR, "incorrect segment");
+
+  switch (seg->type)
     {
-      /* This is a striped segment. We have to find the right PV
-        similar to RAID0. */
-      struct grub_lvm_stripe *stripe = seg->stripes;
-      grub_uint32_t a, b;
-      grub_uint64_t seg_offset; /* Offset of the segment in PV device.  */
-      unsigned int stripenr;
+    case GRUB_LVM_STRIPED:
+      if (seg->stripe_count == 1)
+       {
+         /* This segment is linear, so that's easy.  We just need to find
+            out the offset in the physical volume and read SIZE bytes
+            from that.  */
+         struct grub_lvm_stripe *stripe = seg->stripes;
+         grub_uint64_t seg_offset; /* Offset of the segment in PV device.  */
+
+         pv = stripe->pv;
+         seg_offset = ((grub_uint64_t) stripe->start
+                       * (grub_uint64_t) vg->extent_size) + pv->start;
+
+         offset = sector - ((grub_uint64_t) seg->start_extent
+                            * (grub_uint64_t) vg->extent_size) + seg_offset;
+       }
+      else
+       {
+         /* This is a striped segment. We have to find the right PV
+            similar to RAID0. */
+         struct grub_lvm_stripe *stripe = seg->stripes;
+         grub_uint32_t a, b;
+         grub_uint64_t seg_offset; /* Offset of the segment in PV device.  */
+         unsigned int stripenr;
 
-      offset = sector - ((grub_uint64_t) seg->start_extent
-                        * (grub_uint64_t) vg->extent_size);
+         offset = sector - ((grub_uint64_t) seg->start_extent
+                            * (grub_uint64_t) vg->extent_size);
 
-      a = grub_divmod64 (offset, seg->stripe_size, NULL);
-      grub_divmod64 (a, seg->stripe_count, &stripenr);
+         a = grub_divmod64 (offset, seg->stripe_size, NULL);
+         grub_divmod64 (a, seg->stripe_count, &stripenr);
 
-      a = grub_divmod64 (offset, seg->stripe_size * seg->stripe_count, NULL);
-      grub_divmod64 (offset, seg->stripe_size, &b);
-      offset = a * seg->stripe_size + b;
+         a = grub_divmod64 (offset, seg->stripe_size * seg->stripe_count, NULL);
+         grub_divmod64 (offset, seg->stripe_size, &b);
+         offset = a * seg->stripe_size + b;
 
-      stripe += stripenr;
-      pv = stripe->pv;
+         stripe += stripenr;
+         pv = stripe->pv;
 
-      seg_offset = ((grub_uint64_t) stripe->start
-                   * (grub_uint64_t) vg->extent_size) + pv->start;
+         seg_offset = ((grub_uint64_t) stripe->start
+                       * (grub_uint64_t) vg->extent_size) + pv->start;
 
-      offset += seg_offset;
+         offset += seg_offset;
+       }
+      /* Check whether we actually know the physical volume we want to
+        read from.  */
+      if (pv->disk)
+       err = grub_disk_read (pv->disk, offset, 0,
+                             size << GRUB_DISK_SECTOR_BITS, buf);
+      else
+       err = grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                         "physical volume %s not found", pv->name);
+
+      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");
+}
 
-  /* Check whether we actually know the physical volume we want to
-     read from.  */
-  if (pv->disk)
-    err = grub_disk_read (pv->disk, offset, 0,
-                         size << GRUB_DISK_SECTOR_BITS, buf);
-  else
-    err = grub_error (GRUB_ERR_UNKNOWN_DEVICE,
-                     "physical volume %s not found", pv->name);
-
-  return err;
+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
@@ -533,11 +566,7 @@ grub_lvm_scan_device (const char *name)
 
              lv->size = 0;
 
-             if (!grub_lvm_check_flag (p, "status", "VISIBLE"))
-               {
-                 skip_lv = 1;
-                 goto lv_parsed;
-               }
+             lv->visible = grub_lvm_check_flag (p, "status", "VISIBLE");
 
              lv->segment_count = grub_lvm_getvalue (&p, "segment_count = ");
              if (p == NULL)
@@ -552,7 +581,6 @@ grub_lvm_scan_device (const char *name)
 
              for (i = 0; i < lv->segment_count; i++)
                {
-                 struct grub_lvm_stripe *stripe;
 
                  p = grub_strstr (p, "segment");
                  if (p == NULL)
@@ -580,78 +608,147 @@ grub_lvm_scan_device (const char *name)
                      goto lvs_segment_fail;
                    }
 
-                 if (grub_lvm_checkvalue (&p, "type = ", "snapshot"))
-                   {
-                     /* Found a snapshot, give up and move on. */
-                     skip_lv = 1;
-                     break;
-                   }
-
-                 seg->stripe_count = grub_lvm_getvalue (&p, "stripe_count = ");
+                 p = grub_strstr (p, "type = \"");
                  if (p == NULL)
+                   goto lvs_segment_fail;
+                 p += sizeof("type = \"") - 1;
+
+                 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 = ");
+                     if (p == NULL)
+                       {
 #ifdef GRUB_UTIL
-                     grub_util_info ("unknown stripe_count\n");
+                         grub_util_info ("unknown stripe_count\n");
 #endif
-                     goto lvs_segment_fail;
-                   }
-
-                 lv->size += seg->extent_count * vg->extent_size;
+                         goto lvs_segment_fail;
+                       }
 
-                 if (seg->stripe_count != 1)
-                   seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
+                     if (seg->stripe_count != 1)
+                       seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
 
-                 seg->stripes = grub_malloc (sizeof (*stripe)
-                                             * seg->stripe_count);
-                 stripe = seg->stripes;
+                     seg->stripes = grub_malloc (sizeof (*stripe)
+                                                 * seg->stripe_count);
+                     stripe = seg->stripes;
 
-                 p = grub_strstr (p, "stripes = [");
-                 if (p == NULL)
-                   {
+                     p = grub_strstr (p, "stripes = [");
+                     if (p == NULL)
+                       {
 #ifdef GRUB_UTIL
-                     grub_util_info ("unknown stripes\n");
+                         grub_util_info ("unknown stripes\n");
 #endif
-                     goto lvs_segment_fail2;
-                   }
-                 p += sizeof("stripes = [") - 1;
+                         goto lvs_segment_fail2;
+                       }
+                     p += sizeof("stripes = [") - 1;
 
-                 for (j = 0; j < seg->stripe_count; j++)
-                   {
-                     char *pvname;
+                     for (j = 0; j < seg->stripe_count; j++)
+                       {
+                         char *pvname;
 
-                     p = grub_strchr (p, '"');
-                     if (p == NULL)
-                       continue;
-                     q = ++p;
-                     while (*q != '"')
-                       q++;
+                         p = grub_strchr (p, '"');
+                         if (p == NULL)
+                           continue;
+                         q = ++p;
+                         while (*q != '"')
+                           q++;
 
-                     s = q - p;
+                         s = q - p;
 
-                     pvname = grub_malloc (s + 1);
-                      if (pvname == NULL)
-                        goto lvs_segment_fail2;
+                         pvname = grub_malloc (s + 1);
+                         if (pvname == NULL)
+                           goto lvs_segment_fail2;
 
-                     grub_memcpy (pvname, p, s);
-                     pvname[s] = '\0';
+                         grub_memcpy (pvname, p, s);
+                         pvname[s] = '\0';
 
-                     if (vg->pvs)
-                       for (pv = vg->pvs; pv; pv = pv->next)
-                         {
-                           if (! grub_strcmp (pvname, pv->name))
+                         if (vg->pvs)
+                           for (pv = vg->pvs; pv; pv = pv->next)
                              {
-                               stripe->pv = pv;
-                               break;
+                               if (! grub_strcmp (pvname, pv->name))
+                                 {
+                                   stripe->pv = pv;
+                                   break;
+                                 }
                              }
-                         }
 
-                     grub_free(pvname);
+                         grub_free(pvname);
+
+                         stripe->start = grub_lvm_getvalue (&p, ",");
+                         if (p == NULL)
+                           continue;
 
-                     stripe->start = grub_lvm_getvalue (&p, ",");
+                         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)
-                       continue;
+                       {
+#ifdef GRUB_UTIL
+                         grub_util_info ("unknown mirror_count\n");
+#endif
+                         goto lvs_segment_fail;
+                       }
 
-                     stripe++;
+                     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++;
@@ -663,7 +760,6 @@ grub_lvm_scan_device (const char *name)
                  goto fail4;
                }
 
-           lv_parsed:
              if (p != NULL)
                p = grub_strchr (p, '}');
              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_list = vg;
     }
index a4bf3b28846e1312952140eb0ae8ff893c0aeefa..2205171839359cacfcae26a77aa07ea579febadd 100644 (file)
@@ -47,6 +47,9 @@ struct grub_lvm_lv {
   unsigned int number;
   unsigned int segment_count;
   grub_uint64_t size;
+
+  int visible;
+
   struct grub_lvm_segment *segments; /* Pointer to segment_count segments. */
   struct grub_lvm_vg *vg;
   struct grub_lvm_lv *next;
@@ -55,6 +58,11 @@ struct grub_lvm_lv {
 struct grub_lvm_segment {
   unsigned int start_extent;
   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_size;
   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_mirror {
+  char *lvname;
+  struct grub_lvm_lv *lv;
+};
+
 #define GRUB_LVM_LABEL_SIZE GRUB_DISK_SECTOR_SIZE
 #define GRUB_LVM_LABEL_SCAN_SECTORS 4L
 
index 491d2b5ceed71075a4b0d98b74a02e6caca2ddcb..d12902e334978147373c414501200ab9eab3bc25 100644 (file)
@@ -111,9 +111,17 @@ EOF
 EOF
 }
 
-list=`for i in /boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* ; do
-        if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
-      done`
+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
+              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=
 
 while [ "x$list" != "x" ] ; do