On Mon, May 19, 2025 at 04:34:34PM +0530, Avnish Chouhan wrote:
> This patch sets mupltiple NVMe boot-devices for more robust boot.
> Scenario where NVMe multipaths are available, all the available bootpaths 
> (Max 5)
> will be added as the boot-device.
>
> Signed-off-by: Avnish Chouhan <avn...@linux.ibm.com>
> ---
>  grub-core/osdep/unix/platform.c | 114 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  grub-core/osdep/linux/ofpath.c  |   6 +++---
>  include/grub/util/install.h     |   3 +++
>  include/grub/util/ofpath.h      |   4 ++++
>  4 files changed, 123 insertions(+), 4 deletion(-)
>
> diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
> index 55b8f40..124e0ed 100644
> --- a/grub-core/osdep/unix/platform.c
> +++ b/grub-core/osdep/unix/platform.c
> @@ -28,6 +28,8 @@
>  #include <dirent.h>
>  #include <string.h>
>  #include <errno.h>
> +#include <grub/util/ofpath.h>

Please add empty line here.

> +#define BOOTDEV_BUFFER  1000
>
>  static char *
>  get_ofpathname (const char *dev)
> @@ -176,6 +178,105 @@ grub_install_register_efi (grub_device_t 
> efidir_grub_dev,
>    return ret;
>  }
>
> +
> +char *
> +add_multiple_nvme_bootdevices (const char *install_device)
> +{
> +  char *sysfs_path, *nvme_ns, *ptr, *non_splitter_path;
> +  unsigned int nsid;
> +  char *multipath_boot, *ofpath, *ext_dir;
> +  struct dirent *ep, *splitter_ep;
> +  DIR *dp, *splitter_dp;
> +  char *cntl_id, *dirR1, *dirR2, *splitter_info_path;
> +  int is_FC = 0, is_splitter = 0;

Please use bool type here.

> +  nvme_ns = grub_strstr (install_device, "nvme");

grub_strstr() may return NULL. If it is not possible here then it should
be explained.

> +  nsid = of_path_get_nvme_nsid (nvme_ns);
> +  if (nsid == 0)
> +    return NULL;
> +
> +  sysfs_path = nvme_get_syspath (nvme_ns);
> +  ofpath = xasprintf ("%s",get_ofpathname (nvme_ns));

Missing space after ",".

> +  if (grub_strstr (ofpath, "fibre-channel"))
> +    {
> +      strcat (sysfs_path, "/device");
> +      is_FC = 1;
> +    }
> +  else
> +    {
> +      strcat (sysfs_path, "/subsystem");
> +      is_FC = 0;
> +    }
> +  if (is_FC == 0)
> +    {
> +      cntl_id = grub_strstr (nvme_ns, "e");

Again, missing NULL check and s/grub_strstr/grub_strchr/...

> +      dirR1 = xasprintf ("nvme%c",cntl_id[1]);
> +
> +      splitter_info_path = xasprintf ("%s%s%s", "/sys/block/", nvme_ns, 
> "/device");

... xasprintf ("/sys/block/%s/device", nvme_ns);

> +      splitter_dp = opendir (splitter_info_path);
> +      if (!splitter_dp)
> +        return NULL;
> +
> +      while ((splitter_ep = readdir (splitter_dp)) != NULL)
> +        {
> +          if (grub_strstr (splitter_ep->d_name, "nvme"))
> +          {
> +            if (grub_strstr (splitter_ep->d_name, dirR1))
> +              continue;
> +
> +              ext_dir = grub_strstr (splitter_ep->d_name, "e");

s/grub_strstr/grub_strchr/

Missing NULL check too...

> +              if (!(grub_strstr (ext_dir, "n")))

s/grub_strstr/grub_strchr/

grub_strchr (ext_dir, 'n') == NULL

> +              {
> +                  dirR2 = xasprintf("%s", splitter_ep->d_name);

Something is off with indention...

> +                is_splitter = 1;
> +                break;
> +              }
> +         }
> +        }
> +      closedir (splitter_dp);
> +    }
> +  sysfs_path = xrealpath (sysfs_path);
> +  dp = opendir (sysfs_path);
> +  if (!dp)
> +    return NULL;
> +
> +  ptr = multipath_boot = xmalloc (BOOTDEV_BUFFER);
> +  if (is_splitter == 0 && is_FC == 0)
> +    {
> +      non_splitter_path = xasprintf ("%s%s%x:1 ", get_ofpathname (dirR1), 
> "/namespace@", nsid);

... xasprintf ("%s/namespace@%x:1 ", get_ofpathname (dirR1), nsid);

> +      strncpy (ptr, non_splitter_path, strlen (non_splitter_path));
> +      ptr += strlen (non_splitter_path);
> +      free (non_splitter_path);
> +    }
> +  else
> +    {
> +      while ((ep = readdir (dp)) != NULL)
> +        {
> +          char *path;

Please add empty line here...

> +          if (grub_strstr (ep->d_name, "nvme"))

grub_strstr (ep->d_name, "nvme") != NULL

> +            {
> +              if (is_FC == 0 && !grub_strstr (ep->d_name, dirR1) && 
> !grub_strstr (ep->d_name, dirR2))

... grub_strstr (ep->d_name, dirR1) == NULL && grub_strstr (ep->d_name, dirR2) 
== NULL ...

> +                continue;
> +              path = xasprintf ("%s%s%x ", get_ofpathname (ep->d_name), 
> "/namespace@", nsid);

... xasprintf ("%s/namespace@%x:1 ", get_ofpathname (ep->d_name), nsid);

> +              if ((strlen (multipath_boot) + strlen (path)) > BOOTDEV_BUFFER)
> +                {
> +                  grub_util_warn (_("Maximum five entries are allowed in the 
> bootlist"));
> +                  free (path);
> +                  break;
> +                }
> +              strncpy (ptr, path, strlen (path));
> +              ptr += strlen (path);
> +              free (path);
> +            }
> +        }
> +    }
> +  *--ptr = '\0';
> +  closedir (dp);
> +
> +  return multipath_boot;
> +}
> +
>  void
>  grub_install_register_ieee1275 (int is_prep, const char *install_device,
>                               int partno, const char *relpath)
> @@ -215,8 +316,19 @@ grub_install_register_ieee1275 (int is_prep, const char 
> *install_device,
>       }
>        *ptr = '\0';
>      }
> +  else if (grub_strstr (install_device, "nvme"))
> +    {
> +      boot_device = add_multiple_nvme_bootdevices (install_device);
> +    }
>    else
> -    boot_device = get_ofpathname (install_device);
> +    {
> +      boot_device = get_ofpathname (install_device);
> +      if (grub_strstr (boot_device, "nvme-of"))
> +        {
> +          free (boot_device);
> +          boot_device = add_multiple_nvme_bootdevices (install_device);
> +        }
> +    }
>
>    if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device",
>         boot_device, NULL }))
> diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
> index 7158c8c..48f11c9 100644
> --- a/grub-core/osdep/linux/ofpath.c
> +++ b/grub-core/osdep/linux/ofpath.c
> @@ -209,7 +209,7 @@ find_obppath (const char *sysfs_path_orig)
>      }
>  }
>
> -static char *
> +char *
>  xrealpath (const char *in)
>  {
>    char *out;
> @@ -224,7 +224,7 @@ xrealpath (const char *in)
>    return out;
>  }
>
> -static char *
> +char *

You do not need this change.

>  block_device_get_sysfs_path_and_link(const char *devicenode)
>  {
>    char *rpath;
> @@ -684,7 +684,7 @@ of_path_get_nvme_nsid (const char* devname)
>    return nsid;
>  }
>
> -static char *
> +char *
>  nvme_get_syspath (const char *nvmedev)
>  {
>    char *sysfs_path;
> diff --git a/include/grub/util/install.h b/include/grub/util/install.h
> index 51f3b13..a67e225 100644
> --- a/include/grub/util/install.h
> +++ b/include/grub/util/install.h
> @@ -235,6 +235,9 @@ grub_install_register_efi (grub_device_t efidir_grub_dev,
>                          const char *efifile_path,
>                          const char *efi_distributor);
>
> +char *
> +add_multiple_nvme_bootdevices (const char *install_device);
> +
>  void
>  grub_install_register_ieee1275 (int is_prep, const char *install_device,
>                               int partno, const char *relpath);
> diff --git a/include/grub/util/ofpath.h b/include/grub/util/ofpath.h
> index 5962322..78e78e7 100644
> --- a/include/grub/util/ofpath.h
> +++ b/include/grub/util/ofpath.h
> @@ -30,5 +30,9 @@ int add_filename_to_pile (char *filename, struct 
> ofpath_files_list_root* root);
>  void find_file (char* filename, char* directory, struct 
> ofpath_files_list_root* root, int max_depth, int depth);
>  char* of_find_fc_host (char* host_wwpn);
>  void free_ofpath_files_list (struct ofpath_files_list_root* root);
> +char* nvme_get_syspath (const char *nvmedev);
> +char* block_device_get_sysfs_path_and_link (const char *devicenode);

Please drop this declaration.

Daniel

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to