diff --git a/grub2-diskfilter-support-pv-without-metadatacopies.patch b/grub2-diskfilter-support-pv-without-metadatacopies.patch new file mode 100644 index 0000000..a740d75 --- /dev/null +++ b/grub2-diskfilter-support-pv-without-metadatacopies.patch @@ -0,0 +1,223 @@ +From a28bc19400b4e70725ce5532bc5e4c374c72d7a9 Mon Sep 17 00:00:00 2001 +From: Lidong Zhong +Date: Wed, 26 Apr 2017 15:52:40 +0800 +Subject: [PATCH] diskfilter: implementation of processing no metadata recorded + in PV + +If one PV underlying the root LV is created with no metadata, such as + +pvcreate --metadatacopies 0 /dev/sda + +then we could get a lot of error messages when generating a new +configuration file. + +Generating grub configuration file ... +error: unknown LVM metadata header. +error: unknown LVM metadata header. +/usr/sbin/grub2-probe: warning: Couldn't find physical volume `pv1'. +Some modules may be missing from core image.. +(For details, please refer to + https://bugzilla.suse.com/show_bug.cgi?id=1027526) + +When one labelled PV which dose not have any metadata is found, we put +it into a global grub_detached_pv list. and we search all the PVs in the +current array list to check if it is a member of grub_detached_pv list. +So we can know if the PV is really missing or just without metadata. + +Signed-off-by: Lidong Zhong +--- + grub-core/disk/diskfilter.c | 112 +++++++++++++++++++++++++++++++++++++++++++- + grub-core/disk/lvm.c | 15 ++++-- + 2 files changed, 121 insertions(+), 6 deletions(-) + +Index: grub-2.02/grub-core/disk/diskfilter.c +=================================================================== +--- grub-2.02.orig/grub-core/disk/diskfilter.c ++++ grub-2.02/grub-core/disk/diskfilter.c +@@ -28,6 +28,7 @@ + #include + #include + #endif ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -43,7 +44,17 @@ static struct grub_diskfilter_lv * + find_lv (const char *name); + static int is_lv_readable (struct grub_diskfilter_lv *lv, int easily); + +- ++struct grub_detached_pv { ++ struct grub_detached_pv *next; ++ struct grub_detached_pv **prev; ++ struct grub_diskfilter_pv_id id; ++ grub_disk_t disk; ++ grub_diskfilter_t diskfilter; ++} ; ++ ++static struct grub_detached_pv *detached_pv_list; ++ ++#define FOR_DETACHED_PVS(var) for (var = detached_pv_list; var; var = var->next) + + static grub_err_t + is_node_readable (const struct grub_diskfilter_node *node, int easily) +@@ -132,6 +143,7 @@ scan_disk_partition_iter (grub_disk_t di + grub_disk_addr_t start_sector; + struct grub_diskfilter_pv_id id; + grub_diskfilter_t diskfilter; ++ struct grub_detached_pv *pv; + + grub_dprintf ("diskfilter", "Scanning for DISKFILTER devices on disk %s\n", + name); +@@ -168,6 +180,28 @@ scan_disk_partition_iter (grub_disk_t di + grub_free (id.uuid); + return 0; + } ++ /*insert the special LVM PV into detached_pv_list*/ ++ if (!arr && (id.uuidlen > 0) && (grub_strcmp(diskfilter->name, "lvm") == 0)) ++ { ++ pv = grub_zalloc(sizeof(*pv)); ++ if (!pv) ++ return 1; ++ pv->id.uuidlen = GRUB_LVM_ID_STRLEN; ++ pv->id.uuid = grub_malloc(GRUB_LVM_ID_STRLEN); ++ if (!pv->id.uuid) ++ goto fail_id; ++ grub_memcpy(pv->id.uuid, id.uuid, GRUB_LVM_ID_STRLEN); ++ /*It's safe to save disk into this standalone pv list*/ ++ pv->disk = grub_disk_open(name); ++ if (!pv->disk) ++ goto fail_id; ++ pv->diskfilter = diskfilter; ++ grub_list_push (GRUB_AS_LIST_P (&detached_pv_list), ++ GRUB_AS_LIST(pv)); ++#ifdef GRUB_UTIL ++ grub_util_info ("adding disk %s into detached pv list", name); ++#endif ++ } + if (arr && id.uuidlen) + grub_free (id.uuid); + +@@ -180,6 +214,65 @@ scan_disk_partition_iter (grub_disk_t di + } + + return 0; ++fail_id: ++ if (pv->id.uuidlen) ++ grub_free(pv->id.uuid); ++ grub_free(pv); ++ return 1; ++} ++ ++static int ++process_detached_pv_list(void) ++{ ++ struct grub_diskfilter_vg *arr; ++ struct grub_diskfilter_pv *pv1; ++ struct grub_detached_pv *pv2; ++ unsigned found = 0; ++ ++ for (arr = array_list; arr != NULL; arr = arr->next) ++ { ++ for (pv1 = arr->pvs; pv1; pv1 = pv1->next) ++ { ++ if (pv1->disk) ++ continue; ++ FOR_DETACHED_PVS(pv2) ++ { ++ if (pv2->id.uuidlen == pv1->id.uuidlen && ++ !grub_memcmp(pv2->id.uuid, pv1->id.uuid, pv1->id.uuidlen)) ++ { ++ if (insert_array(pv2->disk, &(pv2->id), arr, -1, pv2->diskfilter)) ++ return grub_errno; ++ else ++ { ++#ifdef GRUB_UTIL ++ grub_util_info ("found disk %s in detached pv list", pv1->disk->name); ++#endif ++ found = 1; ++ break; ++ } ++ } ++ } ++ /*remove pv2 from the list*/ ++ if (found) ++ { ++#ifdef GRUB_UTIL ++ grub_util_info ("removing disk %s from detached pv list", pv1->disk->name); ++#endif ++ grub_list_remove(GRUB_AS_LIST (pv2)); ++ if (pv2->id.uuidlen) ++ { ++ pv2->id.uuidlen = 0; ++ grub_free(pv2->id.uuid); ++ } ++ grub_disk_close(pv2->disk); ++ grub_free(pv2); ++ break; ++ } ++ } ++ if (found) ++ break; ++ } ++ return 0; + } + + static int +@@ -206,6 +299,9 @@ scan_disk (const char *name, int accept_ + grub_partition_iterate (disk, scan_disk_partition_iter, (void *) name); + grub_disk_close (disk); + scan_depth--; ++ ++ /*process the detached_pv_list*/ ++ process_detached_pv_list(); + return 0; + } + +@@ -1249,6 +1345,20 @@ insert_array (grub_disk_t disk, const st + static void + free_array (void) + { ++ while(detached_pv_list) ++ { ++ struct grub_detached_pv *pv; ++ pv = detached_pv_list; ++ detached_pv_list = detached_pv_list->next; ++#ifdef GRUB_UTIL ++ grub_util_warn (_("Couldn't find disk for physical volume `%s'." ++ "Some LVs may not work normally."),pv->disk->name); ++#endif ++ if (pv->id.uuidlen) ++ grub_free(pv->id.uuid); ++ grub_disk_close(pv->disk); ++ grub_free(pv); ++ } + while (array_list) + { + struct grub_diskfilter_vg *vg; +Index: grub-2.02/grub-core/disk/lvm.c +=================================================================== +--- grub-2.02.orig/grub-core/disk/lvm.c ++++ grub-2.02/grub-core/disk/lvm.c +@@ -182,11 +182,16 @@ grub_lvm_detect (grub_disk_t disk, + sizeof (mdah->magic))) + || (grub_le_to_cpu32 (mdah->version) != GRUB_LVM_FMTT_VERSION)) + { +- grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, +- "unknown LVM metadata header"); +-#ifdef GRUB_UTIL +- grub_util_info ("unknown LVM metadata header"); +-#endif ++ /* ++ * It's not necessarily an error. There is no metadata recorded when ++ * PV is created with pvmetadatacopies set to zero. We need to process ++ * this kind of PV seperately. ++ */ ++ id->uuid = grub_malloc(GRUB_LVM_ID_STRLEN); ++ if (!id->uuid) ++ goto fail; ++ grub_memcpy(id->uuid, pv_id, GRUB_LVM_ID_STRLEN); ++ id->uuidlen = GRUB_LVM_ID_STRLEN; + goto fail; + } + diff --git a/grub2-efi-uga-64bit-fb.patch b/grub2-efi-uga-64bit-fb.patch new file mode 100644 index 0000000..da99f8b --- /dev/null +++ b/grub2-efi-uga-64bit-fb.patch @@ -0,0 +1,104 @@ +From: Andrei Borzenkov +Subject: [PATCH] efi/uga: use 64 bit for fb_base + +We get 64 bit from PCI BAR but then truncate by assigning to 32 bit. +Make sure to check that pointer does not overflow on 32 bit platform. + +Closes: 50931 + +--- + grub-core/video/efi_uga.c | 31 ++++++++++++++++--------------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +Index: grub-2.02/grub-core/video/efi_uga.c +=================================================================== +--- grub-2.02.orig/grub-core/video/efi_uga.c ++++ grub-2.02/grub-core/video/efi_uga.c +@@ -34,7 +34,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID; + static struct grub_efi_uga_draw_protocol *uga; +-static grub_uint32_t uga_fb; ++static grub_uint64_t uga_fb; + static grub_uint32_t uga_pitch; + + static struct +@@ -52,7 +52,7 @@ static struct + #define FBTEST_COUNT 8 + + static int +-find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len) ++find_line_len (grub_uint64_t *fb_base, grub_uint32_t *line_len) + { + grub_uint32_t *base = (grub_uint32_t *) (grub_addr_t) *fb_base; + int i; +@@ -67,7 +67,7 @@ find_line_len (grub_uint32_t *fb_base, g + { + if ((base[j] & RGB_MASK) == RGB_MAGIC) + { +- *fb_base = (grub_uint32_t) (grub_addr_t) base; ++ *fb_base = (grub_uint64_t) (grub_addr_t) base; + *line_len = j << 2; + + return 1; +@@ -84,7 +84,7 @@ find_line_len (grub_uint32_t *fb_base, g + /* Context for find_framebuf. */ + struct find_framebuf_ctx + { +- grub_uint32_t *fb_base; ++ grub_uint64_t *fb_base; + grub_uint32_t *line_len; + int found; + }; +@@ -120,7 +120,9 @@ find_card (grub_pci_device_t dev, grub_p + if (i == 5) + break; + +- old_bar2 = grub_pci_read (addr + 4); ++ i++; ++ addr += 4; ++ old_bar2 = grub_pci_read (addr); + } + else + old_bar2 = 0; +@@ -129,10 +131,15 @@ find_card (grub_pci_device_t dev, grub_p + base64 <<= 32; + base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK); + +- grub_dprintf ("fb", "%s(%d): 0x%llx\n", ++ grub_dprintf ("fb", "%s(%d): 0x%" PRIxGRUB_UINT64_T "\n", + ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ? +- "VMEM" : "MMIO"), i, +- (unsigned long long) base64); ++ "VMEM" : "MMIO"), type == GRUB_PCI_ADDR_MEM_TYPE_64 ? i - 1 : i, ++ base64); ++ ++#if GRUB_CPU_SIZEOF_VOID_P == 4 ++ if (old_bar2) ++ continue; ++#endif + + if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! ctx->found)) + { +@@ -140,12 +147,6 @@ find_card (grub_pci_device_t dev, grub_p + if (find_line_len (ctx->fb_base, ctx->line_len)) + ctx->found++; + } +- +- if (type == GRUB_PCI_ADDR_MEM_TYPE_64) +- { +- i++; +- addr += 4; +- } + } + } + +@@ -153,7 +154,7 @@ find_card (grub_pci_device_t dev, grub_p + } + + static int +-find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len) ++find_framebuf (grub_uint64_t *fb_base, grub_uint32_t *line_len) + { + struct find_framebuf_ctx ctx = { + .fb_base = fb_base, diff --git a/grub2.changes b/grub2.changes index edfa131..1d2cfae 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Thu Jun 1 09:45:44 UTC 2017 - mchang@suse.com + +- Support LVM physical volume created without metadatacopies (bsc#1027526) + * grub2-diskfilter-support-pv-without-metadatacopies.patch +- Fix page fault exception when grub loads with Nvidia cards (bsc#1038533) + * grub2-efi-uga-64bit-fb.patch +- Require 'kexec-tools' for System z. (bsc#944358) + * modified grub2.spec + ------------------------------------------------------------------- Thu May 11 08:56:57 UTC 2017 - mchang@suse.com diff --git a/grub2.spec b/grub2.spec index ecb77c2..3b56112 100644 --- a/grub2.spec +++ b/grub2.spec @@ -208,6 +208,8 @@ Patch78: grub2-commands-introduce-read_file-subcommand.patch Patch79: grub2-efi-chainload-harder.patch Patch80: grub2-emu-4-all.patch Patch81: grub2-lvm-allocate-metadata-buffer-from-raw-contents.patch +Patch82: grub2-diskfilter-support-pv-without-metadatacopies.patch +Patch83: grub2-efi-uga-64bit-fb.patch # Btrfs snapshot booting related patches Patch101: grub2-btrfs-01-add-ability-to-boot-from-subvolumes.patch Patch102: grub2-btrfs-02-export-subvolume-envvars.patch @@ -332,6 +334,7 @@ Requires(post): perl-Bootloader # required utilities by grub2-s390x-04-grub2-install.patch # use 'showconsole' to determine console device. (bnc#876743) Requires: /sbin/showconsole +Requires: kexec-tools # for /sbin/zipl used by grub2-zipl-setup Requires: s390-tools %endif @@ -471,6 +474,8 @@ swap partition while in resuming %patch79 -p1 %patch80 -p1 %patch81 -p1 +%patch82 -p1 +%patch83 -p1 %patch101 -p1 %patch102 -p1 %patch103 -p1