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 <ard.biesheuvel@arm.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3097
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <
20201216211125.19496-36-lersek@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
RemoveEntryList (&VirtioFsFile->OpenFilesEntry);\r
\r
FreePool (VirtioFsFile->CanonicalPathname);\r
+ if (VirtioFsFile->FileInfoArray != NULL) {\r
+ FreePool (VirtioFsFile->FileInfoArray);\r
+ }\r
FreePool (VirtioFsFile);\r
return EFI_SUCCESS;\r
}\r
RemoveEntryList (&VirtioFsFile->OpenFilesEntry);\r
\r
FreePool (VirtioFsFile->CanonicalPathname);\r
+ if (VirtioFsFile->FileInfoArray != NULL) {\r
+ FreePool (VirtioFsFile->FileInfoArray);\r
+ }\r
FreePool (VirtioFsFile);\r
return Status;\r
}\r
NewVirtioFsFile->FilePosition = 0;\r
NewVirtioFsFile->NodeId = NewNodeId;\r
NewVirtioFsFile->FuseHandle = NewFuseHandle;\r
+ NewVirtioFsFile->FileInfoArray = NULL;\r
+ NewVirtioFsFile->SingleFileInfoSize = 0;\r
+ NewVirtioFsFile->NumFileInfo = 0;\r
+ NewVirtioFsFile->NextFileInfo = 0;\r
\r
//\r
// One more file is now open for the filesystem.\r
VirtioFsFile->FilePosition = 0;\r
VirtioFsFile->NodeId = VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID;\r
VirtioFsFile->FuseHandle = RootDirHandle;\r
+ VirtioFsFile->FileInfoArray = NULL;\r
+ VirtioFsFile->SingleFileInfoSize = 0;\r
+ VirtioFsFile->NumFileInfo = 0;\r
+ VirtioFsFile->NextFileInfo = 0;\r
\r
//\r
// One more file open for the filesystem.\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
**/\r
\r
+#include <Library/MemoryAllocationLib.h> // FreePool()\r
+\r
#include "VirtioFsDxe.h"\r
\r
EFI_STATUS\r
return EFI_UNSUPPORTED;\r
}\r
VirtioFsFile->FilePosition = 0;\r
+ if (VirtioFsFile->FileInfoArray != NULL) {\r
+ FreePool (VirtioFsFile->FileInfoArray);\r
+ VirtioFsFile->FileInfoArray = NULL;\r
+ }\r
+ VirtioFsFile->SingleFileInfoSize = 0;\r
+ VirtioFsFile->NumFileInfo = 0;\r
+ VirtioFsFile->NextFileInfo = 0;\r
return EFI_SUCCESS;\r
}\r
\r
//\r
#define VIRTIO_FS_MAX_PATHNAME_LENGTH ((UINTN)65535)\r
\r
+//\r
+// Maximum value for VIRTIO_FS_FILE.NumFileInfo.\r
+//\r
+#define VIRTIO_FS_FILE_MAX_FILE_INFO 256\r
+\r
//\r
// Filesystem label encoded in UCS-2, transformed from the UTF-8 representation\r
// in "VIRTIO_FS_CONFIG.Tag", and NUL-terminated. Only the printable ASCII code\r
//\r
UINT64 NodeId;\r
UINT64 FuseHandle;\r
+ //\r
+ // EFI_FILE_INFO objects cached for an in-flight directory read.\r
+ //\r
+ // For reading through a directory stream with tolerable performance, we have\r
+ // to call FUSE_READDIRPLUS each time with such a buffer that can deliver a\r
+ // good number of variable size records (VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE\r
+ // elements). Every time we do that, we turn the whole bunch into an array of\r
+ // EFI_FILE_INFOs immediately. EFI_FILE_PROTOCOL.Read() invocations (on\r
+ // directories) will be served from this EFI_FILE_INFO cache.\r
+ //\r
+ UINT8 *FileInfoArray;\r
+ UINTN SingleFileInfoSize;\r
+ UINTN NumFileInfo;\r
+ UINTN NextFileInfo;\r
} VIRTIO_FS_FILE;\r
\r
#define VIRTIO_FS_FILE_FROM_SIMPLE_FILE(SimpleFileReference) \\r