All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: devel@edk2.groups.io, virtio-fs@redhat.com, lersek@redhat.com
Cc: "Jordan Justen" <jordan.l.justen@intel.com>,
	"Philippe Mathieu-Daudé" <philmd@redhat.com>,
	"Ard Biesheuvel" <ard.biesheuvel@arm.com>
Subject: [Virtio-fs] [edk2 PATCH 15/48] OvmfPkg/VirtioFsDxe: flush, sync, release and forget in Close() / Delete()
Date: Wed, 16 Dec 2020 22:10:52 +0100	[thread overview]
Message-ID: <20201216211125.19496-16-lersek@redhat.com> (raw)
In-Reply-To: <20201216211125.19496-1-lersek@redhat.com>

The two member functions that free the EFI_FILE_PROTOCOL object are
Close() and Delete(). Before we create VIRTIO_FS_FILE objects with
EFI_FILE_PROTOCOL.Open() later in this patch series, extend each of these
"destructor" functions to get rid of the FuseHandle and NodeId resources
properly -- in a way that matches each function's own purpose.

For the time being, VirtioFsSimpleFileDelete() only gets a reminder about
its core task (namely, removing the file), as the needed machinery will
become only later. But we can already outline the "task list", and deal
with the FuseHandle and NodeId resources. The "task list" of
VirtioFsSimpleFileDelete() is different from that of
VirtioFsSimpleFileClose(), thus both destructors diverge at this point.

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>
---
 OvmfPkg/VirtioFsDxe/VirtioFsDxe.h        |  1 +
 OvmfPkg/VirtioFsDxe/SimpleFsClose.c      | 34 ++++++++----
 OvmfPkg/VirtioFsDxe/SimpleFsDelete.c     | 55 +++++++++++++++++---
 OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c |  1 +
 4 files changed, 74 insertions(+), 17 deletions(-)

diff --git a/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h b/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h
index 7151a62bb42b..1cbd27d8fb52 100644
--- a/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h
+++ b/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h
@@ -105,16 +105,17 @@ typedef struct {
 //
 // Private context structure that exposes EFI_FILE_PROTOCOL on top of an open
 // FUSE file reference.
 //
 typedef struct {
   UINT64            Signature;
   EFI_FILE_PROTOCOL SimpleFile;
   BOOLEAN           IsDirectory;
+  BOOLEAN           IsOpenForWriting;
   VIRTIO_FS         *OwnerFs;
   LIST_ENTRY        OpenFilesEntry;
   //
   // In the FUSE wire protocol, every request except FUSE_INIT refers to a
   // file, namely by the "VIRTIO_FS_FUSE_REQUEST.NodeId" field; that is, by the
   // inode number of the file. However, some of the FUSE requests that we need
   // for some of the EFI_FILE_PROTOCOL member functions require an open file
   // handle *in addition* to the inode number. For simplicity, whenever a
diff --git a/OvmfPkg/VirtioFsDxe/SimpleFsClose.c b/OvmfPkg/VirtioFsDxe/SimpleFsClose.c
index 01bbeae21473..bc91ad726b2c 100644
--- a/OvmfPkg/VirtioFsDxe/SimpleFsClose.c
+++ b/OvmfPkg/VirtioFsDxe/SimpleFsClose.c
@@ -19,30 +19,46 @@ VirtioFsSimpleFileClose (
 {
   VIRTIO_FS_FILE *VirtioFsFile;
   VIRTIO_FS      *VirtioFs;
 
   VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
   VirtioFs     = VirtioFsFile->OwnerFs;
 
   //
-  // At this point, the implementation is only suitable for closing the
-  // VIRTIO_FS_FILE that was created by VirtioFsOpenVolume().
+  // All actions in this function are "best effort"; the UEFI spec requires
+  // EFI_FILE_PROTOCOL.Close() to sync all data to the device, but it also
+  // requires EFI_FILE_PROTOCOL.Close() to release resources unconditionally,
+  // and to return EFI_SUCCESS unconditionally.
   //
-  ASSERT (VirtioFsFile->IsDirectory);
-  ASSERT (VirtioFsFile->NodeId == VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID);
-  //
-  // Close the root directory.
-  //
-  // Ignore any errors, because EFI_FILE_PROTOCOL.Close() is required to
-  // release the EFI_FILE_PROTOCOL object unconditionally.
+  // Flush, sync, release, and (if needed) forget. If any action fails, we
+  // still try the others.
   //
+  if (VirtioFsFile->IsOpenForWriting) {
+    if (!VirtioFsFile->IsDirectory) {
+      VirtioFsFuseFlush (VirtioFs, VirtioFsFile->NodeId,
+        VirtioFsFile->FuseHandle);
+    }
+
+    VirtioFsFuseFsyncFileOrDir (VirtioFs, VirtioFsFile->NodeId,
+      VirtioFsFile->FuseHandle, VirtioFsFile->IsDirectory);
+  }
+
   VirtioFsFuseReleaseFileOrDir (VirtioFs, VirtioFsFile->NodeId,
     VirtioFsFile->FuseHandle, VirtioFsFile->IsDirectory);
 
+  //
+  // VirtioFsFile->FuseHandle is gone at this point, but VirtioFsFile->NodeId
+  // is still valid. If we've known VirtioFsFile->NodeId from a lookup, then
+  // now we should ask the server to forget it *once*.
+  //
+  if (VirtioFsFile->NodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
+    VirtioFsFuseForget (VirtioFs, VirtioFsFile->NodeId);
+  }
+
   //
   // One fewer file left open for the owner filesystem.
   //
   RemoveEntryList (&VirtioFsFile->OpenFilesEntry);
 
   FreePool (VirtioFsFile);
   return EFI_SUCCESS;
 }
diff --git a/OvmfPkg/VirtioFsDxe/SimpleFsDelete.c b/OvmfPkg/VirtioFsDxe/SimpleFsDelete.c
index 3209923d1e49..bbad64bf7886 100644
--- a/OvmfPkg/VirtioFsDxe/SimpleFsDelete.c
+++ b/OvmfPkg/VirtioFsDxe/SimpleFsDelete.c
@@ -1,29 +1,68 @@
 /** @file
   EFI_FILE_PROTOCOL.Delete() member function for the Virtio Filesystem driver.
 
   Copyright (C) 2020, Red Hat, Inc.
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
+#include <Library/BaseLib.h>             // RemoveEntryList()
+#include <Library/MemoryAllocationLib.h> // FreePool()
+
 #include "VirtioFsDxe.h"
 
 EFI_STATUS
 EFIAPI
 VirtioFsSimpleFileDelete (
   IN EFI_FILE_PROTOCOL *This
   )
 {
+  VIRTIO_FS_FILE *VirtioFsFile;
+  VIRTIO_FS      *VirtioFs;
+  EFI_STATUS     Status;
+
+  VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+  VirtioFs     = VirtioFsFile->OwnerFs;
+
   //
-  // At this point, the implementation is only suitable for closing the
-  // VIRTIO_FS_FILE that was created by VirtioFsOpenVolume().
+  // All actions in this function are "best effort"; the UEFI spec requires
+  // EFI_FILE_PROTOCOL.Delete() to release resources unconditionally. If a step
+  // related to removing the file fails, it's only reflected in the return
+  // status (EFI_WARN_DELETE_FAILURE rather than EFI_SUCCESS).
   //
-  // Actually deleting the root directory is not possible, so we're only going
-  // to release resources, and return EFI_WARN_DELETE_FAILURE.
+  // Release, remove, and (if needed) forget. We don't waste time flushing and
+  // syncing; if the EFI_FILE_PROTOCOL user cares enough, they should keep the
+  // parent directory open until after this function call returns, and then
+  // force a sync on *that* EFI_FILE_PROTOCOL instance, using either the
+  // Flush() member function, or the Close() member function.
   //
-  // In order to release resources, VirtioFsSimpleFileClose() is just right
-  // here.
+  // If any action fails below, we still try the others.
   //
-  VirtioFsSimpleFileClose (This);
-  return EFI_WARN_DELETE_FAILURE;
+  VirtioFsFuseReleaseFileOrDir (VirtioFs, VirtioFsFile->NodeId,
+    VirtioFsFile->FuseHandle, VirtioFsFile->IsDirectory);
+
+  //
+  // VirtioFsFile->FuseHandle is gone at this point, but VirtioFsFile->NodeId
+  // is still valid. Continue with removing the file or directory. The result
+  // of this operation determines the return status of the function.
+  //
+  // TODO
+  //
+  Status = EFI_WARN_DELETE_FAILURE;
+
+  //
+  // Finally, if we've known VirtioFsFile->NodeId from a lookup, then we should
+  // also ask the server to forget it *once*.
+  //
+  if (VirtioFsFile->NodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
+    VirtioFsFuseForget (VirtioFs, VirtioFsFile->NodeId);
+  }
+
+  //
+  // One fewer file left open for the owner filesystem.
+  //
+  RemoveEntryList (&VirtioFsFile->OpenFilesEntry);
+
+  FreePool (VirtioFsFile);
+  return Status;
 }
diff --git a/OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c b/OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c
index 8c1457a68aad..67d2deb6bdf2 100644
--- a/OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c
+++ b/OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c
@@ -57,16 +57,17 @@ VirtioFsOpenVolume (
   VirtioFsFile->SimpleFile.Read        = VirtioFsSimpleFileRead;
   VirtioFsFile->SimpleFile.Write       = VirtioFsSimpleFileWrite;
   VirtioFsFile->SimpleFile.GetPosition = VirtioFsSimpleFileGetPosition;
   VirtioFsFile->SimpleFile.SetPosition = VirtioFsSimpleFileSetPosition;
   VirtioFsFile->SimpleFile.GetInfo     = VirtioFsSimpleFileGetInfo;
   VirtioFsFile->SimpleFile.SetInfo     = VirtioFsSimpleFileSetInfo;
   VirtioFsFile->SimpleFile.Flush       = VirtioFsSimpleFileFlush;
   VirtioFsFile->IsDirectory            = TRUE;
+  VirtioFsFile->IsOpenForWriting       = FALSE;
   VirtioFsFile->OwnerFs                = VirtioFs;
   VirtioFsFile->NodeId                 = VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID;
   VirtioFsFile->FuseHandle             = RootDirHandle;
 
   //
   // One more file open for the filesystem.
   //
   InsertTailList (&VirtioFs->OpenFiles, &VirtioFsFile->OpenFilesEntry);
-- 
2.19.1.3.g30247aa5d201




  parent reply	other threads:[~2020-12-16 21:10 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-16 21:10 [Virtio-fs] [edk2 PATCH 00/48] ArmVirtPkg, OvmfPkg: virtio filesystem driver Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 01/48] OvmfPkg: introduce VirtioFsDxe Laszlo Ersek
2020-12-18 17:42   ` Ard Biesheuvel
2020-12-18 18:13     ` Dr. David Alan Gilbert
2020-12-19 21:16       ` Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 02/48] ArmVirtPkg: include VirtioFsDxe in the ArmVirtQemu* platforms Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 03/48] OvmfPkg/VirtioFsDxe: DriverBinding: open VirtioDevice, install SimpleFs Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 04/48] OvmfPkg/VirtioFsDxe: implement virtio device (un)initialization Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 05/48] OvmfPkg/VirtioFsDxe: add a scatter-gather list data type Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 06/48] OvmfPkg/VirtioFsDxe: introduce the basic FUSE request/response headers Laszlo Ersek
2020-12-17 11:49   ` Dr. David Alan Gilbert
2020-12-17 13:57     ` Laszlo Ersek
2020-12-17 14:06       ` Dr. David Alan Gilbert
2020-12-17 14:32       ` Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 07/48] OvmfPkg/VirtioFsDxe: map "errno" values to EFI_STATUS Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 08/48] OvmfPkg/VirtioFsDxe: submit the FUSE_INIT request to the device Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 09/48] OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_OPENDIR Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 10/48] OvmfPkg/VirtioFsDxe: add shared wrapper for FUSE_RELEASE / FUSE_RELEASEDIR Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 11/48] OvmfPkg/VirtioFsDxe: implement EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.OpenVolume() Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 12/48] OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_FORGET Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 13/48] OvmfPkg/VirtioFsDxe: add a shared wrapper for FUSE_FSYNC / FUSE_FSYNCDIR Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 14/48] OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_FLUSH Laszlo Ersek
2020-12-16 21:10 ` Laszlo Ersek [this message]
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 16/48] OvmfPkg/VirtioFsDxe: add helper for appending and sanitizing paths Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 17/48] OvmfPkg/VirtioFsDxe: manage path lifecycle in OpenVolume, Close, Delete Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 18/48] OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_OPEN Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 19/48] OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_MKDIR Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 20/48] OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_CREATE Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 21/48] OvmfPkg/VirtioFsDxe: convert FUSE inode attributes to EFI_FILE_INFO Laszlo Ersek
2020-12-16 21:10 ` [Virtio-fs] [edk2 PATCH 22/48] OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_LOOKUP Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 23/48] OvmfPkg/VirtioFsDxe: split canon. path into last parent + last component Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 24/48] OvmfPkg/VirtioFsDxe: add a shared wrapper for FUSE_UNLINK / FUSE_RMDIR Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 25/48] OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_GETATTR Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 26/48] OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.Open() Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 27/48] OvmfPkg/VirtioFsDxe: erase the dir. entry in EFI_FILE_PROTOCOL.Delete() Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 28/48] OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_STATFS Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 29/48] OvmfPkg/VirtioFsDxe: add helper for formatting UEFI basenames Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 30/48] OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.GetInfo() Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 31/48] OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.GetPosition, .SetPosition Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 32/48] OvmfPkg/VirtioFsDxe: add a shared wrapper for FUSE_READ / FUSE_READDIRPLUS Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 33/48] OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.Read() for regular files Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 34/48] OvmfPkg/VirtioFsDxe: convert FUSE dirent filename to EFI_FILE_INFO Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 35/48] OvmfPkg/VirtioFsDxe: add EFI_FILE_INFO cache fields to VIRTIO_FS_FILE Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 36/48] OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.Read() for directories Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 37/48] OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.Flush() Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 38/48] OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_WRITE Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 39/48] OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.Write() Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 40/48] OvmfPkg/VirtioFsDxe: handle the volume label in EFI_FILE_PROTOCOL.SetInfo Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 41/48] OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_RENAME2 Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 42/48] OvmfPkg/VirtioFsDxe: add helper for composing rename/move destination path Laszlo Ersek
2020-12-18 17:39   ` Ard Biesheuvel
2020-12-19 22:40     ` Laszlo Ersek
2020-12-19 22:54       ` Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 43/48] OvmfPkg/VirtioFsDxe: handle file rename/move in EFI_FILE_PROTOCOL.SetInfo Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 44/48] OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_SETATTR Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 45/48] OvmfPkg/VirtioFsDxe: add helper for determining file size update Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 46/48] OvmfPkg/VirtioFsDxe: add helper for determining access time updates Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 47/48] OvmfPkg/VirtioFsDxe: add helper for determining file mode bits update Laszlo Ersek
2020-12-16 21:11 ` [Virtio-fs] [edk2 PATCH 48/48] OvmfPkg/VirtioFsDxe: handle attribute updates in EFI_FILE_PROTOCOL.SetInfo Laszlo Ersek
2020-12-18 17:44 ` [Virtio-fs] [edk2 PATCH 00/48] ArmVirtPkg, OvmfPkg: virtio filesystem driver Ard Biesheuvel
2020-12-20  0:09   ` Laszlo Ersek
2020-12-20 10:15     ` Ard Biesheuvel
2020-12-21  1:46       ` Laszlo Ersek
2020-12-21 10:10         ` Ard Biesheuvel
2020-12-21 18:02           ` [Virtio-fs] [edk2-devel] " 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-all 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=20201216211125.19496-16-lersek@redhat.com \
    --to=lersek@redhat.com \
    --cc=ard.biesheuvel@arm.com \
    --cc=devel@edk2.groups.io \
    --cc=jordan.l.justen@intel.com \
    --cc=philmd@redhat.com \
    --cc=virtio-fs@redhat.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.