From 3e77c5494fd06f430588ae9c304fea370439d531 Mon Sep 17 00:00:00 2001 From: Wen Xiong Date: Thu, 15 Dec 2022 21:33:41 -0500 Subject: [PATCH] grub2: Set multiple device path for a nvmf boot device nvmf support native multipath(ANA) by default. The patch added the support for setting multiple device path for a nvmf boot device. localhost:~ grub2-install -v /dev/nvme1n1p1 ... ... ... grub2-install: info: executing nvsetenv boot-device /pci@800000020000132/fibre-channel@0,1/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0,1/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec. Installation finished. No error reported. localhost:~ # bootlist -m normal -o nvme7n1 nvme5n1 nvme1n1 nvme4n1 localhost:~ # bootlist -m normal -r /pci@800000020000132/fibre-channel@0,1/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0,1/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec Signed-off-by: Wen Xiong --- grub-core/osdep/linux/ofpath.c | 6 ++--- grub-core/osdep/unix/platform.c | 48 +++++++++++++++++++++++++++++++++ include/grub/util/install.h | 3 +++ include/grub/util/ofpath.h | 9 +++++++ 4 files changed, 63 insertions(+), 3 deletions(-) --- a/grub-core/osdep/linux/ofpath.c +++ b/grub-core/osdep/linux/ofpath.c @@ -209,7 +209,7 @@ } } -static char * +char * xrealpath (const char *in) { char *out; @@ -224,7 +224,7 @@ return out; } -static char * +char * block_device_get_sysfs_path_and_link(const char *devicenode) { char *rpath; @@ -535,7 +535,7 @@ } -static char * +char * nvme_get_syspath(const char *nvmedev) { char *sysfs_path, *controller_node; --- a/grub-core/osdep/unix/platform.c +++ b/grub-core/osdep/unix/platform.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -131,6 +132,51 @@ return rc; } +char * +build_multi_boot_device(const char *install_device) +{ + char *sysfs_path; + char *nvme_ns; + unsigned int nsid; + char *ptr; + char *boot_device_string; + struct dirent *ep; + DIR *dp; + + nvme_ns = strchr(install_device, 'n'); + nsid = of_path_get_nvme_nsid(nvme_ns); + sysfs_path = nvme_get_syspath(nvme_ns); + strcat(sysfs_path, "/device"); + sysfs_path = xrealpath(sysfs_path); + + dp = opendir(sysfs_path); + ptr = boot_device_string = xmalloc (1000); + + /* We cannot have a boot list with more than five entries */ + while((ep = readdir(dp)) != NULL){ + char *nvme_device; + + if (grub_strstr(ep->d_name, "nvme")) { + nvme_device = xasprintf ("%s%s%x ", + get_ofpathname(ep->d_name),"/namespace@", nsid); + if ((strlen(boot_device_string) + strlen(nvme_device)) >= 200*5 - 1) { + grub_util_warn (_("More than five entries cannot be specified in the bootlist")); + free(nvme_device); + break; + } + + strncpy(ptr, nvme_device, strlen(nvme_device)); + ptr += strlen(nvme_device); + free(nvme_device); + } + } + + *--ptr = '\0'; + closedir(dp); + + return boot_device_string; +} + int grub_install_register_efi (const grub_disk_t *efidir_grub_disk, const char *efifile_path, @@ -242,6 +288,8 @@ } *ptr = '\0'; } + else if (grub_strstr(install_device, "nvme")) + boot_device = build_multi_boot_device(install_device); else boot_device = get_ofpathname (install_device); --- a/include/grub/util/install.h +++ b/include/grub/util/install.h @@ -241,6 +241,9 @@ const char *efi_distributor, const char *force_disk); +char * +build_multi_boot_device(const char *install_device); + void grub_install_register_ieee1275 (int is_prep, const char *install_device, int partno, const char *relpath); --- a/include/grub/util/ofpath.h +++ b/include/grub/util/ofpath.h @@ -32,4 +32,13 @@ char* of_find_fc_host(char* host_wwpn); +char* nvme_get_syspath(const char *nvmedev); + +char* block_device_get_sysfs_path_and_link(const char *devicenode); + +char* xrealpath (const char *in); + +unsigned int of_path_get_nvme_nsid(const char* devname); + + #endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */