grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH][RFC] efidisk: Retries in case of read failure


From: Francois
Subject: [PATCH][RFC] efidisk: Retries in case of read failure
Date: Fri, 23 Apr 2021 17:02:40 +0200

When booting on a Virtual Media (typically, an URL to an img file on
an object store), the BMC translates the block IO requests into HTTP
GET requests with a Range header. Depending on the size of the media,
they can be thousands of small requests being issued, and it is
possible that some the queries time out or get throttled by the
object store.

We implement a naive retry and throttling logic to try to
complete the boot even if some of the requests fail.
---
 grub-core/disk/efi/efidisk.c | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
index f077b5f55..29649130b 100644
--- a/grub-core/disk/efi/efidisk.c
+++ b/grub-core/disk/efi/efidisk.c
@@ -26,6 +26,7 @@
 #include <grub/efi/api.h>
 #include <grub/efi/efi.h>
 #include <grub/efi/disk.h>
+#include <grub/time.h>

 struct grub_efidisk_data
 {
@@ -589,13 +590,32 @@ grub_efidisk_read (struct grub_disk *disk,
grub_disk_addr_t sector,
     grub_size_t size, char *buf)
 {
   grub_efi_status_t status;
+  static int error_count = 0;

   grub_dprintf ("efidisk",
  "reading 0x%lx sectors at the sector 0x%llx from %s\n",
  (unsigned long) size, (unsigned long long) sector, disk->name);

-  status = grub_efidisk_readwrite (disk, sector, size, buf, 0);
-
+  do
+    {
+      status = grub_efidisk_readwrite (disk, sector, size, buf, 0);
+
+      /* Throttle when too many errors occured already */
+      if (error_count > 3)
+        grub_millisleep(10);
+
+      /* Increase error count and report */
+      if (status != GRUB_EFI_SUCCESS)
+ {
+   error_count += 1;
+   grub_millisleep(error_count * 100);
+   grub_err_printf("E");
+ }
+    }
+  while ((error_count < 10)
+         && (status != GRUB_EFI_SUCCESS)
+         && (status != GRUB_EFI_NO_MEDIA));
+
   if (status == GRUB_EFI_NO_MEDIA)
     return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("no media in `%s'"),
disk->name);
   else if (status != GRUB_EFI_SUCCESS)
-- 
2.17.1



reply via email to

[Prev in Thread] Current Thread [Next in Thread]