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;
signature.asc
Description: Digital signature