OvmfPkg/VirtioFsDxe: add a shared wrapper for FUSE_READ / FUSE_READDIRPLUS

Add the VirtioFsFuseReadFileOrDir() function, for sending the FUSE_READ or
FUSE_READDIRPLUS command to the Virtio Filesystem device.

Parsing the structured FUSE_READDIRPLUS output is complex, and cannot be
integrated into the wrapper function. Given that fact, FUSE_READ and
FUSE_READDIRPLUS turn out to need identical low-level handling, except for
the opcode. Hence the shared wrapper function.

(It's prudent to verify whether the FUSE server supports FUSE_READDIRPLUS,
so update the session init code accordingly.)

This is the first FUSE request wrapper function that deals with a variable
size tail buffer.

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-33-lersek@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
This commit is contained in:
Laszlo Ersek
2020-12-16 22:11:09 +01:00
committed by mergify[bot]
parent c4edb49b4f
commit d98d7e3005
5 changed files with 276 additions and 4 deletions

View File

@@ -108,6 +108,39 @@ typedef struct {
#define VIRTIO_FS_FUSE_OPEN_REQ_F_RDONLY 0
#define VIRTIO_FS_FUSE_OPEN_REQ_F_RDWR 2
//
// Flags for VirtioFsFuseOpInit.
//
#define VIRTIO_FS_FUSE_INIT_REQ_F_DO_READDIRPLUS BIT13
/**
Macro for calculating the size of a directory stream entry.
The macro may evaluate Namelen multiple times.
The macro evaluates to a UINTN value that is safe to cast to UINT32.
@param[in] Namelen The size of the filename byte array that follows
VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE in the directory
stream, as reported by
VIRTIO_FS_FUSE_STATFS_RESPONSE.Namelen or
VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE.Namelen. The filename
byte array is not NUL-terminated.
@retval 0 Namelen was zero or greater than SIZE_4KB.
@return The number of bytes in the directory entry, including the
VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE header.
**/
#define VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE(Namelen) \
((Namelen) == 0 || (Namelen) > SIZE_4KB ? \
(UINTN)0 : \
ALIGN_VALUE ( \
sizeof (VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE) + (UINTN)(Namelen), \
sizeof (UINT64) \
) \
)
//
// FUSE operation codes.
//
@@ -119,6 +152,7 @@ typedef enum {
VirtioFsFuseOpUnlink = 10,
VirtioFsFuseOpRmDir = 11,
VirtioFsFuseOpOpen = 14,
VirtioFsFuseOpRead = 15,
VirtioFsFuseOpStatFs = 17,
VirtioFsFuseOpRelease = 18,
VirtioFsFuseOpFsync = 20,
@@ -128,6 +162,7 @@ typedef enum {
VirtioFsFuseOpReleaseDir = 29,
VirtioFsFuseOpFsyncDir = 30,
VirtioFsFuseOpCreate = 35,
VirtioFsFuseOpReadDirPlus = 44,
} VIRTIO_FS_FUSE_OPCODE;
#pragma pack (1)
@@ -234,6 +269,19 @@ typedef struct {
UINT32 Padding;
} VIRTIO_FS_FUSE_OPEN_RESPONSE;
//
// Header for VirtioFsFuseOpRead and VirtioFsFuseOpReadDirPlus.
//
typedef struct {
UINT64 FileHandle;
UINT64 Offset;
UINT32 Size;
UINT32 ReadFlags;
UINT64 LockOwner;
UINT32 Flags;
UINT32 Padding;
} VIRTIO_FS_FUSE_READ_REQUEST;
//
// Header for VirtioFsFuseOpStatFs.
//
@@ -312,6 +360,25 @@ typedef struct {
UINT32 Umask;
UINT32 Padding;
} VIRTIO_FS_FUSE_CREATE_REQUEST;
//
// Header for VirtioFsFuseOpReadDirPlus.
//
// Diverging from the rest of the headers, this structure embeds other
// structures. The reason is that a scatter list cannot be used to receive
// NodeResp and AttrResp separately; the record below is followed by a variable
// size filename byte array, and then such pairs are repeated a number of
// times. Thus, later header start offsets depend on earlier filename array
// sizes.
//
typedef struct {
VIRTIO_FS_FUSE_NODE_RESPONSE NodeResp;
VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE AttrResp;
UINT64 NodeId;
UINT64 CookieForNextEntry;
UINT32 Namelen;
UINT32 Type;
} VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE;
#pragma pack ()
#endif // VIRTIO_FS_H_