public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Aaron Young" <aaron.young@oracle.com>
To: devel@edk2.groups.io
Subject: [edk2-devel] [PATCH 1/1] MdeModulePkg: Optimize BmExpandPartitionDevicePath
Date: Tue, 10 Oct 2023 08:06:44 -0700	[thread overview]
Message-ID: <20231010150644.37857-1-Aaron.Young@oracle.com> (raw)

Reference: https://github.com/tianocore/edk2/pull/4892

BmExpandPartitionDevicePath is called to expand "short-form" device paths
which are commonly used with OS boot options. To expand a device path, it
calls EfiBootManagerConnectAll to connect all the possible BlockIo
devices in the system to search for a matching partition. However, this
is sometimes unnecessary on certain platforms (such as OVMF/QEMU) because
the boot devices are previously explicity connected
(See: ConnectDevicesFromQemu).  EfiBootManagerConnectAll calls are
extremely costly in terms of boot time and resources and should be avoided
whenever feasible.

Therefore optimize BmExpandPartitionDevicePath to first search the
existing BlockIo handles for a match. If a match is not found, then
fallback to the original code to call EfiBootManagerConnectAll and search
again. Thus, this optimization should be extremely low-risk given the
fallback to previous behavior.

NOTE: The existing optimization in the code to use a "HDDP" variable to
save the last matched device paths does not cover the first time a boot
option is expanded (i.e. before the "HDDP" is created) nor when the device
configuration has changed (resulting in the boot device moving to a
different location in the PCI Bus/Dev hierarchy). This new optimization
covers both of these cases on requisite platforms which explicity connect
boot devices.

In our testing on OVMF/QEMU VMs with dozens of configured vnic devices,
these extraneous calls to EfiBootManagerConnectAll from
BmExpandPartitionDevicePath were found to cause many seconds (or even
minutes) of additional VM boot time in some cases - due to the vnics
being unnecessarily connected.

Cc: Zhichao Gao zhichao.gao@intel.com
Cc: Ray Ni ray.ni@intel.com
Signed-off-by: Aaron Young <aaron.young@oracle.com>
---
 MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c | 90 ++++++++++++--------
 1 file changed, 56 insertions(+), 34 deletions(-)

diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
index c3763c4483c7..7a97f7cdcc6b 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
@@ -880,6 +880,8 @@ BmExpandPartitionDevicePath (
   BOOLEAN                   NeedAdjust;
   EFI_DEVICE_PATH_PROTOCOL  *Instance;
   UINTN                     Size;
+  BOOLEAN                   MatchFound;
+  BOOLEAN                   ConnectAllAttempted;
 
   //
   // Check if there is prestore 'HDDP' variable.
@@ -974,49 +976,69 @@ BmExpandPartitionDevicePath (
   // If we get here we fail to find or 'HDDP' not exist, and now we need
   // to search all devices in the system for a matched partition
   //
-  EfiBootManagerConnectAll ();
-  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);
-  if (EFI_ERROR (Status)) {
-    BlockIoHandleCount = 0;
-    BlockIoBuffer      = NULL;
-  }
-
-  //
-  // Loop through all the device handles that support the BLOCK_IO Protocol
-  //
-  for (Index = 0; Index < BlockIoHandleCount; Index++) {
-    BlockIoDevicePath = DevicePathFromHandle (BlockIoBuffer[Index]);
-    if (BlockIoDevicePath == NULL) {
-      continue;
+  BlockIoBuffer       = NULL;
+  MatchFound          = FALSE;
+  ConnectAllAttempted = FALSE;
+  do {
+    if (BlockIoBuffer != NULL) {
+      FreePool (BlockIoBuffer);
     }
 
-    if (BmMatchPartitionDevicePathNode (BlockIoDevicePath, (HARDDRIVE_DEVICE_PATH *)FilePath)) {
-      //
-      // Find the matched partition device path
-      //
-      TempDevicePath = AppendDevicePath (BlockIoDevicePath, NextDevicePathNode (FilePath));
-      FullPath       = BmGetNextLoadOptionDevicePath (TempDevicePath, NULL);
-      FreePool (TempDevicePath);
+    Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);
+    if (EFI_ERROR (Status)) {
+      BlockIoHandleCount = 0;
+      BlockIoBuffer      = NULL;
+    }
 
-      if (FullPath != NULL) {
-        BmCachePartitionDevicePath (&CachedDevicePath, BlockIoDevicePath);
+    //
+    // Loop through all the device handles that support the BLOCK_IO Protocol
+    //
+    for (Index = 0; Index < BlockIoHandleCount; Index++) {
+      BlockIoDevicePath = DevicePathFromHandle (BlockIoBuffer[Index]);
+      if (BlockIoDevicePath == NULL) {
+        continue;
+      }
 
+      if (BmMatchPartitionDevicePathNode (BlockIoDevicePath, (HARDDRIVE_DEVICE_PATH *)FilePath)) {
         //
-        // Save the matching Device Path so we don't need to do a connect all next time
-        // Failing to save only impacts performance next time expanding the short-form device path
+        // Find the matched partition device path
         //
-        Status = gRT->SetVariable (
-                        L"HDDP",
-                        &mBmHardDriveBootVariableGuid,
-                        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
-                        GetDevicePathSize (CachedDevicePath),
-                        CachedDevicePath
-                        );
+        TempDevicePath = AppendDevicePath (BlockIoDevicePath, NextDevicePathNode (FilePath));
+        FullPath       = BmGetNextLoadOptionDevicePath (TempDevicePath, NULL);
+        FreePool (TempDevicePath);
+
+        if (FullPath != NULL) {
+          BmCachePartitionDevicePath (&CachedDevicePath, BlockIoDevicePath);
 
-        break;
+          //
+          // Save the matching Device Path so we don't need to do a connect all next time
+          // Failing to save only impacts performance next time expanding the short-form device path
+          //
+          Status = gRT->SetVariable (
+                          L"HDDP",
+                          &mBmHardDriveBootVariableGuid,
+                          EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                          EFI_VARIABLE_NON_VOLATILE,
+                          GetDevicePathSize (CachedDevicePath),
+                          CachedDevicePath
+                          );
+          MatchFound = TRUE;
+          break;
+        }
       }
     }
-  }
+
+    //
+    // If we found a matching BLOCK_IO handle or we've already
+    // tried a ConnectAll, we are done searching.
+    //
+    if (MatchFound || ConnectAllAttempted) {
+      break;
+    }
+
+    EfiBootManagerConnectAll ();
+    ConnectAllAttempted = TRUE;
+  } while (1);
 
   if (CachedDevicePath != NULL) {
     FreePool (CachedDevicePath);
-- 
2.39.3



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#109496): https://edk2.groups.io/g/devel/message/109496
Mute This Topic: https://groups.io/mt/101876973/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



             reply	other threads:[~2023-10-10 15:07 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-10 15:06 Aaron Young [this message]
2023-10-10 16:38 ` [edk2-devel] [PATCH 1/1] MdeModulePkg: Optimize BmExpandPartitionDevicePath Laszlo Ersek
2023-10-11 17:36   ` Aaron Young via groups.io
2023-10-12 15:14     ` Laszlo Ersek
2023-10-24  2:18 ` Gao, Zhichao
2023-10-24 12:29   ` Laszlo Ersek
2023-10-24 13:15     ` Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231010150644.37857-1-Aaron.Young@oracle.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox