here's an updated, but still incomplete patch.  

the main problem with the previous patch was that the extent_count variable was
being overwritten when fetching the type option value.  simply removing
that fixed that problem.  there were further problems with the lv's though, as
it seems (i'm not an lvm guru by any means) that a snapshot consists of
two entries, one named "snapshot0" (this was the one the previous patch
would skip), and another one with the snapshot name, which is notably
different from the others in that the "status" field does not contain
"VISIBLE" like the others.

i updated the patch to also skip such lv entries, which cleared further
problems.  after these two steps, running update-grub/grub-install/grub-probe
all work without reporting errors.

*HOWEVER*, the system still doesn't boot.  after reinstalling grub and
regenerating /boot/grub/grub.cfg, the user is greeted with the error:

        error: no such disk
        error: physical volume pv0 not found
        Entering rescue mode...
        grub rescue>

so it looks like there is yet another failure in grub_lvm_read causing this.
honestly the code is so full of spaghetti i'm having trouble making it much
further.  i have a test setup running under kvm so if anyone has something
they want me to try please let me know.  otherwise i'll continue to hack at
it but i'm not too optomistic.


        sean

-- 
--- a/disk/lvm.c
+++ b/disk/lvm.c
@@ -413,9 +413,11 @@ grub_lvm_scan_device (const char *name)
 	  /* And add all the lvs to the volume group. */
 	  while (1)
 	    {
-	      int s;
+	      int s, skip_lv = 0, status_visible = 0;
 	      struct grub_lvm_lv *lv;
 	      struct grub_lvm_segment *seg;
+              char *status = NULL, *status_end = NULL;
+              grub_size_t status_len = 0;
 
 	      while (grub_isspace (*p))
 		p++;
@@ -424,6 +426,8 @@ grub_lvm_scan_device (const char *name)
 		break;
 
 	      lv = grub_malloc (sizeof (*lv));
+	      skip_lv = 0; /*Flag to skip snapshots */
+	      status_visible = 0; /*Flag to skip snapshots */
 
 	      q = p;
 	      while (*q != ' ')
@@ -438,6 +442,24 @@ grub_lvm_scan_device (const char *name)
 
 	      lv->size = 0;
 
+	      /* read lv status and ignore ones not listed as "visible" */
+	      grub_lvm_getvalue (&p, "status = "); 
+	      if (p == NULL)
+		      goto lvs_fail;
+	      status_end = grub_strchr(p, ']');
+	      if (status_end == NULL)
+		      goto lvs_fail;
+	      status_len = (status_end - p) + 1;
+	      status = grub_malloc(status_len + 1);
+	      if (status == NULL)
+		      goto lvs_fail;
+	      grub_memcpy(status, p, status_len);
+	      status[status_len] = '\0';
+	      if (grub_strstr(status, "VISIBLE") != NULL) {
+		      status_visible = 1;
+	      }
+	      grub_free(status);
+
 	      lv->segment_count = grub_lvm_getvalue (&p, "segment_count = ");
 	      if (p == NULL)
 		goto lvs_fail;
@@ -458,6 +480,13 @@ grub_lvm_scan_device (const char *name)
 		  seg->extent_count = grub_lvm_getvalue (&p, "extent_count = ");
 		  if (p == NULL)
 		    goto lvs_segment_fail;
+		  grub_lvm_getvalue (&p, "type = ");
+		  if (p == NULL)
+		    goto lvs_segment_fail;
+		  if (!grub_strncmp(p, "\"snapshot\"", 10)) {
+		    skip_lv=1; /* Found a snapshot LV */
+	            break;  
+		  }
 		  seg->stripe_count = grub_lvm_getvalue (&p, "stripe_count = ");
 		  if (p == NULL)
 		    goto lvs_segment_fail;
@@ -530,6 +559,12 @@ grub_lvm_scan_device (const char *name)
 		goto lvs_fail;
 	      p += 3;
 
+	      if (skip_lv || ! status_visible) {
+	        grub_free (lv->name);
+	        grub_free (lv);
+		continue;
+	      }
+
 	      lv->number = lv_count++;
 	      lv->vg = vg;
 	      lv->next = vg->lvs;

Attachment: signature.asc
Description: Digital signature

Reply via email to