Blame SOURCES/0448-ieee1275-Avoiding-many-unecessary-open-close.patch

110f85
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
110f85
From: root <root@localhost.localdomain>
110f85
Date: Mon, 1 Mar 2021 13:35:34 -0500
110f85
Subject: [PATCH] ieee1275: Avoiding many unecessary open/close
110f85
110f85
This patch aims to change the grub_ofdisk_open and grub_ofdisk_close behaviors. Since some devices (Fibre Channel and NVMe) can have a long time for shutdown notification, we should avoid open and close the disks as much as we can.
110f85
110f85
So, we are changing how those functions works. The grub_ofdisk_close will take care of just changing the disk element status, by doing a soft close, i.e, the firmware will not be called. On the other hand, the grub_ofdisk_open will take care of closing the current disk opened only if the disk requested in the current call is different from the current one. This close will be responsible to request the firmware to actually close the disk.
110f85
110f85
Yet, this patch modifies the grub_ofdisk_get_block_size function, avoiding open and close calls inside of it.
110f85
---
110f85
 grub-core/disk/ieee1275/ofdisk.c | 76 +++++++++++++++++++++++-----------------
110f85
 1 file changed, 44 insertions(+), 32 deletions(-)
110f85
110f85
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
110f85
index 6870b39587d..5fabe365eca 100644
110f85
--- a/grub-core/disk/ieee1275/ofdisk.c
110f85
+++ b/grub-core/disk/ieee1275/ofdisk.c
110f85
@@ -385,6 +385,36 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
110f85
 
110f85
   grub_dprintf ("disk", "Opening `%s'.\n", devpath);
110f85
 
110f85
+  struct ofdisk_hash_ent *op;
110f85
+  op = ofdisk_hash_find (devpath);
110f85
+  if (!op)
110f85
+    op = ofdisk_hash_add (devpath, NULL);
110f85
+  else
110f85
+    grub_free (devpath);
110f85
+  if (!op)
110f85
+    return grub_errno;
110f85
+
110f85
+  /* Check if the call to open is the same to the last disk already opened */
110f85
+  if (last_devpath && !grub_strcmp(op->open_path,last_devpath))
110f85
+  {
110f85
+      goto finish;
110f85
+  }
110f85
+
110f85
+ /* If not, we need to close the previous disk and open the new one */
110f85
+  else {
110f85
+    if (last_ihandle){
110f85
+        grub_ieee1275_close (last_ihandle);
110f85
+    }
110f85
+    last_ihandle = 0;
110f85
+    last_devpath = NULL;
110f85
+
110f85
+    grub_ieee1275_open (op->open_path, &last_ihandle);
110f85
+    if (! last_ihandle)
110f85
+      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
110f85
+    last_devpath = op->open_path;
110f85
+  }
110f85
+
110f85
+
110f85
   if (grub_ieee1275_finddevice (devpath, &dev))
110f85
     {
110f85
       grub_free (devpath);
110f85
@@ -405,30 +435,28 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
110f85
       return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device");
110f85
     }
110f85
 
110f85
-  grub_uint32_t block_size = 0;
110f85
-  if (grub_ofdisk_get_block_size (devpath, &block_size) == 0)
110f85
-    {
110f85
-      for (disk->log_sector_size = 0;
110f85
-           (1U << disk->log_sector_size) < block_size;
110f85
-           disk->log_sector_size++);
110f85
-    }
110f85
-
110f85
+  finish:
110f85
   /* XXX: There is no property to read the number of blocks.  There
110f85
      should be a property `#blocks', but it is not there.  Perhaps it
110f85
      is possible to use seek for this.  */
110f85
   disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
110f85
 
110f85
   {
110f85
-    struct ofdisk_hash_ent *op;
110f85
-    op = ofdisk_hash_find (devpath);
110f85
-    if (!op)
110f85
-      op = ofdisk_hash_add (devpath, NULL);
110f85
-    else
110f85
-      grub_free (devpath);
110f85
-    if (!op)
110f85
-      return grub_errno;
110f85
     disk->id = (unsigned long) op;
110f85
     disk->data = op->open_path;
110f85
+
110f85
+    grub_uint32_t block_size = 0;
110f85
+    if (grub_ofdisk_get_block_size (devpath, &block_size) == 0)
110f85
+      {
110f85
+        for (disk->log_sector_size = 0;
110f85
+             (1U << disk->log_sector_size) < block_size;
110f85
+             disk->log_sector_size++);
110f85
+      }
110f85
+    else
110f85
+      {
110f85
+        grub_free (devpath);
110f85
+        return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "error getting block size");
110f85
+      }
110f85
   }
110f85
 
110f85
   return 0;
110f85
@@ -437,13 +465,6 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
110f85
 static void
110f85
 grub_ofdisk_close (grub_disk_t disk)
110f85
 {
110f85
-  if (disk->data == last_devpath)
110f85
-    {
110f85
-      if (last_ihandle)
110f85
-	grub_ieee1275_close (last_ihandle);
110f85
-      last_ihandle = 0;
110f85
-      last_devpath = NULL;
110f85
-    }
110f85
   disk->data = 0;
110f85
 }
110f85
 
110f85
@@ -602,15 +623,6 @@ grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size)
110f85
       grub_ieee1275_cell_t size2;
110f85
     } args_ieee1275;
110f85
 
110f85
-  if (last_ihandle)
110f85
-    grub_ieee1275_close (last_ihandle);
110f85
-
110f85
-  last_ihandle = 0;
110f85
-  last_devpath = NULL;
110f85
-
110f85
-  grub_ieee1275_open (device, &last_ihandle);
110f85
-  if (! last_ihandle)
110f85
-    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
110f85
 
110f85
   INIT_IEEE1275_COMMON (&args_ieee1275.common, "call-method", 2, 2);
110f85
   args_ieee1275.method = (grub_ieee1275_cell_t) "block-size";