From b845de89d02b9822d184179c622e6517e8477827 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Wed, 16 Dec 2020 22:11:12 +0100 Subject: [PATCH] OvmfPkg/VirtioFsDxe: add EFI_FILE_INFO cache fields to VIRTIO_FS_FILE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For reading through a directory stream with tolerable performance, we'll have to call FUSE_READDIRPLUS each time with such a buffer that can deliver a good number of variable size records (VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE elements). Every time we'll do that, we'll turn the whole bunch into an array of EFI_FILE_INFOs immediately. EFI_FILE_PROTOCOL.Read() invocations (on directories) will be served from this EFI_FILE_INFO cache. Add the fields for the EFI_FILE_INFO cache to VIRTIO_FS_FILE: - initialize them in Open() and OpenVolume(), - release the cache in Close() and Delete(), - also release the cache when the directory is rewound, in SetPosition(). Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Philippe Mathieu-Daudé Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3097 Signed-off-by: Laszlo Ersek Message-Id: <20201216211125.19496-36-lersek@redhat.com> Acked-by: Ard Biesheuvel --- OvmfPkg/VirtioFsDxe/SimpleFsClose.c | 3 +++ OvmfPkg/VirtioFsDxe/SimpleFsDelete.c | 3 +++ OvmfPkg/VirtioFsDxe/SimpleFsOpen.c | 4 ++++ OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c | 4 ++++ OvmfPkg/VirtioFsDxe/SimpleFsSetPosition.c | 9 +++++++++ OvmfPkg/VirtioFsDxe/VirtioFsDxe.h | 19 +++++++++++++++++++ 6 files changed, 42 insertions(+) diff --git a/OvmfPkg/VirtioFsDxe/SimpleFsClose.c b/OvmfPkg/VirtioFsDxe/SimpleFsClose.c index 04b4f2c382..4c1cf52112 100644 --- a/OvmfPkg/VirtioFsDxe/SimpleFsClose.c +++ b/OvmfPkg/VirtioFsDxe/SimpleFsClose.c @@ -60,6 +60,9 @@ VirtioFsSimpleFileClose ( RemoveEntryList (&VirtioFsFile->OpenFilesEntry); FreePool (VirtioFsFile->CanonicalPathname); + if (VirtioFsFile->FileInfoArray != NULL) { + FreePool (VirtioFsFile->FileInfoArray); + } FreePool (VirtioFsFile); return EFI_SUCCESS; } diff --git a/OvmfPkg/VirtioFsDxe/SimpleFsDelete.c b/OvmfPkg/VirtioFsDxe/SimpleFsDelete.c index 76cfee5bce..76a868b3c2 100644 --- a/OvmfPkg/VirtioFsDxe/SimpleFsDelete.c +++ b/OvmfPkg/VirtioFsDxe/SimpleFsDelete.c @@ -102,6 +102,9 @@ VirtioFsSimpleFileDelete ( RemoveEntryList (&VirtioFsFile->OpenFilesEntry); FreePool (VirtioFsFile->CanonicalPathname); + if (VirtioFsFile->FileInfoArray != NULL) { + FreePool (VirtioFsFile->FileInfoArray); + } FreePool (VirtioFsFile); return Status; } diff --git a/OvmfPkg/VirtioFsDxe/SimpleFsOpen.c b/OvmfPkg/VirtioFsDxe/SimpleFsOpen.c index 7c50ce9c0e..d73d23fe86 100644 --- a/OvmfPkg/VirtioFsDxe/SimpleFsOpen.c +++ b/OvmfPkg/VirtioFsDxe/SimpleFsOpen.c @@ -482,6 +482,10 @@ VirtioFsSimpleFileOpen ( NewVirtioFsFile->FilePosition = 0; NewVirtioFsFile->NodeId = NewNodeId; NewVirtioFsFile->FuseHandle = NewFuseHandle; + NewVirtioFsFile->FileInfoArray = NULL; + NewVirtioFsFile->SingleFileInfoSize = 0; + NewVirtioFsFile->NumFileInfo = 0; + NewVirtioFsFile->NextFileInfo = 0; // // One more file is now open for the filesystem. diff --git a/OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c b/OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c index 1181191d27..058e7a41ab 100644 --- a/OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c +++ b/OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c @@ -75,6 +75,10 @@ VirtioFsOpenVolume ( VirtioFsFile->FilePosition = 0; VirtioFsFile->NodeId = VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID; VirtioFsFile->FuseHandle = RootDirHandle; + VirtioFsFile->FileInfoArray = NULL; + VirtioFsFile->SingleFileInfoSize = 0; + VirtioFsFile->NumFileInfo = 0; + VirtioFsFile->NextFileInfo = 0; // // One more file open for the filesystem. diff --git a/OvmfPkg/VirtioFsDxe/SimpleFsSetPosition.c b/OvmfPkg/VirtioFsDxe/SimpleFsSetPosition.c index ac62853026..a548012d9c 100644 --- a/OvmfPkg/VirtioFsDxe/SimpleFsSetPosition.c +++ b/OvmfPkg/VirtioFsDxe/SimpleFsSetPosition.c @@ -7,6 +7,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ +#include // FreePool() + #include "VirtioFsDxe.h" EFI_STATUS @@ -31,6 +33,13 @@ VirtioFsSimpleFileSetPosition ( return EFI_UNSUPPORTED; } VirtioFsFile->FilePosition = 0; + if (VirtioFsFile->FileInfoArray != NULL) { + FreePool (VirtioFsFile->FileInfoArray); + VirtioFsFile->FileInfoArray = NULL; + } + VirtioFsFile->SingleFileInfoSize = 0; + VirtioFsFile->NumFileInfo = 0; + VirtioFsFile->NextFileInfo = 0; return EFI_SUCCESS; } diff --git a/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h b/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h index 2b419048c2..a704acdd52 100644 --- a/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h +++ b/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h @@ -47,6 +47,11 @@ // #define VIRTIO_FS_MAX_PATHNAME_LENGTH ((UINTN)65535) +// +// Maximum value for VIRTIO_FS_FILE.NumFileInfo. +// +#define VIRTIO_FS_FILE_MAX_FILE_INFO 256 + // // Filesystem label encoded in UCS-2, transformed from the UTF-8 representation // in "VIRTIO_FS_CONFIG.Tag", and NUL-terminated. Only the printable ASCII code @@ -154,6 +159,20 @@ typedef struct { // UINT64 NodeId; UINT64 FuseHandle; + // + // EFI_FILE_INFO objects cached for an in-flight directory read. + // + // For reading through a directory stream with tolerable performance, we have + // to call FUSE_READDIRPLUS each time with such a buffer that can deliver a + // good number of variable size records (VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE + // elements). Every time we do that, we turn the whole bunch into an array of + // EFI_FILE_INFOs immediately. EFI_FILE_PROTOCOL.Read() invocations (on + // directories) will be served from this EFI_FILE_INFO cache. + // + UINT8 *FileInfoArray; + UINTN SingleFileInfoSize; + UINTN NumFileInfo; + UINTN NextFileInfo; } VIRTIO_FS_FILE; #define VIRTIO_FS_FILE_FROM_SIMPLE_FILE(SimpleFileReference) \