From 92a4d30e0449da2940ff24d159d687afc6672e9c Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Wed, 16 Dec 2020 22:10:49 +0100 Subject: OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_FORGET MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the VirtioFsFuseForget() function, for sending the FUSE_FORGET command to the Virtio Filesystem device. This is an unusual command in that it doesn't generate any response from the FUSE server. 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-13-lersek@redhat.com> Acked-by: Ard Biesheuvel --- OvmfPkg/Include/IndustryStandard/VirtioFs.h | 8 +++ OvmfPkg/VirtioFsDxe/FuseForget.c | 85 +++++++++++++++++++++++++++++ OvmfPkg/VirtioFsDxe/VirtioFsDxe.h | 6 ++ OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf | 1 + 4 files changed, 100 insertions(+) create mode 100644 OvmfPkg/VirtioFsDxe/FuseForget.c diff --git a/OvmfPkg/Include/IndustryStandard/VirtioFs.h b/OvmfPkg/Include/IndustryStandard/VirtioFs.h index 67fcf975e8..0241daf1e8 100644 --- a/OvmfPkg/Include/IndustryStandard/VirtioFs.h +++ b/OvmfPkg/Include/IndustryStandard/VirtioFs.h @@ -85,6 +85,7 @@ typedef struct { // FUSE operation codes. // typedef enum { + VirtioFsFuseOpForget = 2, VirtioFsFuseOpRelease = 18, VirtioFsFuseOpInit = 26, VirtioFsFuseOpOpenDir = 27, @@ -112,6 +113,13 @@ typedef struct { UINT64 Unique; } VIRTIO_FS_FUSE_RESPONSE; +// +// Header for VirtioFsFuseOpForget. +// +typedef struct { + UINT64 NumberOfLookups; +} VIRTIO_FS_FUSE_FORGET_REQUEST; + // // Header for VirtioFsFuseOpRelease and VirtioFsFuseOpReleaseDir. // diff --git a/OvmfPkg/VirtioFsDxe/FuseForget.c b/OvmfPkg/VirtioFsDxe/FuseForget.c new file mode 100644 index 0000000000..fdee42cffb --- /dev/null +++ b/OvmfPkg/VirtioFsDxe/FuseForget.c @@ -0,0 +1,85 @@ +/** @file + FUSE_FORGET wrapper for the Virtio Filesystem device. + + Copyright (C) 2020, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "VirtioFsDxe.h" + +/** + Make the Virtio Filesysem device drop one reference count from a NodeId that + the driver looked up by filename. + + Send the FUSE_FORGET request to the Virtio Filesysem device for this. Unlike + most other FUSE requests, FUSE_FORGET doesn't elicit a response, not even the + common VIRTIO_FS_FUSE_RESPONSE header. + + The function may only be called after VirtioFsFuseInitSession() returns + successfully and before VirtioFsUninit() is called. + + @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_FORGET + request to. On output, the FUSE request counter + "VirtioFs->RequestId" will have been incremented. + + @param[in] NodeId The inode number that the client learned by way of + lookup, and that the server should now un-reference + exactly once. + + @retval EFI_SUCCESS The FUSE_FORGET request has been submitted. + + @return Error codes propagated from VirtioFsSgListsValidate(), + VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(). +**/ +EFI_STATUS +VirtioFsFuseForget ( + IN OUT VIRTIO_FS *VirtioFs, + IN UINT64 NodeId + ) +{ + VIRTIO_FS_FUSE_REQUEST CommonReq; + VIRTIO_FS_FUSE_FORGET_REQUEST ForgetReq; + VIRTIO_FS_IO_VECTOR ReqIoVec[2]; + VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList; + EFI_STATUS Status; + + // + // Set up the scatter-gather list (note: only request). + // + ReqIoVec[0].Buffer = &CommonReq; + ReqIoVec[0].Size = sizeof CommonReq; + ReqIoVec[1].Buffer = &ForgetReq; + ReqIoVec[1].Size = sizeof ForgetReq; + ReqSgList.IoVec = ReqIoVec; + ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec); + + // + // Validate the scatter-gather list (request only); calculate the total + // transfer size. + // + Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Populate the common request header. + // + Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize, + VirtioFsFuseOpForget, NodeId); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Populate the FUSE_FORGET-specific fields. + // + ForgetReq.NumberOfLookups = 1; + + // + // Submit the request. There's not going to be a response. + // + Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, NULL); + return Status; +} diff --git a/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h b/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h index 34574d0596..68ed6cd7e6 100644 --- a/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h +++ b/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h @@ -195,6 +195,12 @@ VirtioFsErrnoToEfiStatus ( // Wrapper functions for FUSE commands (primitives). // +EFI_STATUS +VirtioFsFuseForget ( + IN OUT VIRTIO_FS *VirtioFs, + IN UINT64 NodeId + ); + EFI_STATUS VirtioFsFuseReleaseFileOrDir ( IN OUT VIRTIO_FS *VirtioFs, diff --git a/OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf b/OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf index 28e66082ec..baeb741be1 100644 --- a/OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf +++ b/OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf @@ -82,6 +82,7 @@ [Sources] DriverBinding.c + FuseForget.c FuseInit.c FuseOpenDir.c FuseRelease.c -- cgit v1.2.3