SimpleFsDelete.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /** @file
  2. EFI_FILE_PROTOCOL.Delete() member function for the Virtio Filesystem driver.
  3. Copyright (C) 2020, Red Hat, Inc.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Library/BaseLib.h> // RemoveEntryList()
  7. #include <Library/MemoryAllocationLib.h> // FreePool()
  8. #include "VirtioFsDxe.h"
  9. EFI_STATUS
  10. EFIAPI
  11. VirtioFsSimpleFileDelete (
  12. IN EFI_FILE_PROTOCOL *This
  13. )
  14. {
  15. VIRTIO_FS_FILE *VirtioFsFile;
  16. VIRTIO_FS *VirtioFs;
  17. EFI_STATUS Status;
  18. VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
  19. VirtioFs = VirtioFsFile->OwnerFs;
  20. //
  21. // All actions in this function are "best effort"; the UEFI spec requires
  22. // EFI_FILE_PROTOCOL.Delete() to release resources unconditionally. If a step
  23. // related to removing the file fails, it's only reflected in the return
  24. // status (EFI_WARN_DELETE_FAILURE rather than EFI_SUCCESS).
  25. //
  26. // Release, remove, and (if needed) forget. We don't waste time flushing and
  27. // syncing; if the EFI_FILE_PROTOCOL user cares enough, they should keep the
  28. // parent directory open until after this function call returns, and then
  29. // force a sync on *that* EFI_FILE_PROTOCOL instance, using either the
  30. // Flush() member function, or the Close() member function.
  31. //
  32. // If any action fails below, we still try the others.
  33. //
  34. VirtioFsFuseReleaseFileOrDir (
  35. VirtioFs,
  36. VirtioFsFile->NodeId,
  37. VirtioFsFile->FuseHandle,
  38. VirtioFsFile->IsDirectory
  39. );
  40. //
  41. // VirtioFsFile->FuseHandle is gone at this point, but VirtioFsFile->NodeId
  42. // is still valid. Continue with removing the file or directory. The result
  43. // of this operation determines the return status of the function.
  44. //
  45. if (VirtioFsFile->IsOpenForWriting) {
  46. UINT64 ParentNodeId;
  47. CHAR8 *LastComponent;
  48. //
  49. // Split our canonical pathname into most specific parent directory
  50. // (identified by NodeId), and single-component filename within that
  51. // directory. If This stands for the root directory "/", then the following
  52. // function call will gracefully fail.
  53. //
  54. Status = VirtioFsLookupMostSpecificParentDir (
  55. VirtioFs,
  56. VirtioFsFile->CanonicalPathname,
  57. &ParentNodeId,
  58. &LastComponent
  59. );
  60. if (!EFI_ERROR (Status)) {
  61. //
  62. // Attempt the actual removal. Regardless of the outcome, ParentNodeId
  63. // must be forgotten right after (unless it stands for the root
  64. // directory).
  65. //
  66. Status = VirtioFsFuseRemoveFileOrDir (
  67. VirtioFs,
  68. ParentNodeId,
  69. LastComponent,
  70. VirtioFsFile->IsDirectory
  71. );
  72. if (ParentNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
  73. VirtioFsFuseForget (VirtioFs, ParentNodeId);
  74. }
  75. }
  76. if (EFI_ERROR (Status)) {
  77. //
  78. // Map any failure to the spec-mandated warning code.
  79. //
  80. Status = EFI_WARN_DELETE_FAILURE;
  81. }
  82. } else {
  83. Status = EFI_WARN_DELETE_FAILURE;
  84. }
  85. //
  86. // Finally, if we've known VirtioFsFile->NodeId from a lookup, then we should
  87. // also ask the server to forget it *once*.
  88. //
  89. if (VirtioFsFile->NodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
  90. VirtioFsFuseForget (VirtioFs, VirtioFsFile->NodeId);
  91. }
  92. //
  93. // One fewer file left open for the owner filesystem.
  94. //
  95. RemoveEntryList (&VirtioFsFile->OpenFilesEntry);
  96. FreePool (VirtioFsFile->CanonicalPathname);
  97. if (VirtioFsFile->FileInfoArray != NULL) {
  98. FreePool (VirtioFsFile->FileInfoArray);
  99. }
  100. FreePool (VirtioFsFile);
  101. return Status;
  102. }