]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/VirtioFsDxe: implement the wrapper function for FUSE_SETATTR
authorLaszlo Ersek <lersek@redhat.com>
Wed, 16 Dec 2020 21:11:21 +0000 (22:11 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 21 Dec 2020 17:16:23 +0000 (17:16 +0000)
Add the VirtioFsFuseSetAttr() function, for sending the FUSE_SETATTR
command to the Virtio Filesystem device.

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-45-lersek@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
OvmfPkg/Include/IndustryStandard/VirtioFs.h
OvmfPkg/VirtioFsDxe/FuseSetAttr.c [new file with mode: 0644]
OvmfPkg/VirtioFsDxe/VirtioFsDxe.h
OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf

index 0b2ed701004672acd543ce28bdd786fc8055253a..15fb28f95a28f0c5ce917205b708b7e9f66c97d8 100644 (file)
@@ -102,6 +102,15 @@ typedef struct {
 #define VIRTIO_FS_FUSE_MODE_PERM_ROTH 0000004u\r
 #define VIRTIO_FS_FUSE_MODE_PERM_WOTH 0000002u\r
 \r
+//\r
+// Flags for VirtioFsFuseOpSetAttr, in the VIRTIO_FS_FUSE_SETATTR_REQUEST.Valid\r
+// field.\r
+//\r
+#define VIRTIO_FS_FUSE_SETATTR_REQ_F_MODE  BIT0\r
+#define VIRTIO_FS_FUSE_SETATTR_REQ_F_SIZE  BIT3\r
+#define VIRTIO_FS_FUSE_SETATTR_REQ_F_ATIME BIT4\r
+#define VIRTIO_FS_FUSE_SETATTR_REQ_F_MTIME BIT5\r
+\r
 //\r
 // Flags for VirtioFsFuseOpOpen.\r
 //\r
@@ -153,6 +162,7 @@ typedef enum {
   VirtioFsFuseOpLookup      =  1,\r
   VirtioFsFuseOpForget      =  2,\r
   VirtioFsFuseOpGetAttr     =  3,\r
+  VirtioFsFuseOpSetAttr     =  4,\r
   VirtioFsFuseOpMkDir       =  9,\r
   VirtioFsFuseOpUnlink      = 10,\r
   VirtioFsFuseOpRmDir       = 11,\r
@@ -240,7 +250,8 @@ typedef struct {
 } VIRTIO_FS_FUSE_FORGET_REQUEST;\r
 \r
 //\r
-// Headers for VirtioFsFuseOpGetAttr.\r
+// Headers for VirtioFsFuseOpGetAttr (VIRTIO_FS_FUSE_GETATTR_RESPONSE is also\r
+// for VirtioFsFuseOpSetAttr).\r
 //\r
 typedef struct {\r
   UINT32 GetAttrFlags;\r
@@ -254,6 +265,28 @@ typedef struct {
   UINT32 Dummy;\r
 } VIRTIO_FS_FUSE_GETATTR_RESPONSE;\r
 \r
+//\r
+// Header for VirtioFsFuseOpSetAttr.\r
+//\r
+typedef struct {\r
+  UINT32 Valid;\r
+  UINT32 Padding;\r
+  UINT64 FileHandle;\r
+  UINT64 Size;\r
+  UINT64 LockOwner;\r
+  UINT64 Atime;\r
+  UINT64 Mtime;\r
+  UINT64 Ctime;\r
+  UINT32 AtimeNsec;\r
+  UINT32 MtimeNsec;\r
+  UINT32 CtimeNsec;\r
+  UINT32 Mode;\r
+  UINT32 Unused4;\r
+  UINT32 Uid;\r
+  UINT32 Gid;\r
+  UINT32 Unused5;\r
+} VIRTIO_FS_FUSE_SETATTR_REQUEST;\r
+\r
 //\r
 // Header for VirtioFsFuseOpMkDir.\r
 //\r
diff --git a/OvmfPkg/VirtioFsDxe/FuseSetAttr.c b/OvmfPkg/VirtioFsDxe/FuseSetAttr.c
new file mode 100644 (file)
index 0000000..dcd0141
--- /dev/null
@@ -0,0 +1,174 @@
+/** @file\r
+  FUSE_SETATTR wrapper for the Virtio Filesystem device.\r
+\r
+  Copyright (C) 2020, Red Hat, Inc.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#include "VirtioFsDxe.h"\r
+\r
+/**\r
+  Send the FUSE_SETATTR request to the Virtio Filesystem device, for changing\r
+  the attributes of an inode.\r
+\r
+  The function may only be called after VirtioFsFuseInitSession() returns\r
+  successfully and before VirtioFsUninit() is called.\r
+\r
+  @param[in,out] VirtioFs  The Virtio Filesystem device to send the\r
+                           FUSE_SETATTR request to. On output, the FUSE request\r
+                           counter "VirtioFs->RequestId" will have been\r
+                           incremented.\r
+\r
+  @param[in] NodeId        The inode number representing the regular file or\r
+                           directory whose attributes should be changed.\r
+\r
+  @param[in] Size          The new size to set for the regular file. If NULL,\r
+                           then the file size will not be changed. If NodeId\r
+                           refers to a directory, then the caller is\r
+                           responsible for passing NULL as Size.\r
+\r
+  @param[in] Atime         The new last access time to set for the regular file\r
+                           or directory (seconds since the Epoch). If NULL,\r
+                           then the last access time is not changed.\r
+\r
+  @param[in] Mtime         The new last modification time to set for the\r
+                           regular file or directory (seconds since the Epoch).\r
+                           If NULL, then the last modification time is not\r
+                           changed.\r
+\r
+  @param[in] Mode          The new file mode bits to set for the regular file\r
+                           or directory. If NULL, then the file mode bits are\r
+                           not changed.\r
+\r
+  @retval EFI_SUCCESS  The attributes have been updated.\r
+\r
+  @return              The "errno" value mapped to an EFI_STATUS code, if the\r
+                       Virtio Filesystem device explicitly reported an error.\r
+\r
+  @return              Error codes propagated from VirtioFsSgListsValidate(),\r
+                       VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),\r
+                       VirtioFsFuseCheckResponse().\r
+**/\r
+EFI_STATUS\r
+VirtioFsFuseSetAttr (\r
+  IN OUT VIRTIO_FS *VirtioFs,\r
+  IN     UINT64    NodeId,\r
+  IN     UINT64    *Size      OPTIONAL,\r
+  IN     UINT64    *Atime     OPTIONAL,\r
+  IN     UINT64    *Mtime     OPTIONAL,\r
+  IN     UINT32    *Mode      OPTIONAL\r
+  )\r
+{\r
+  VIRTIO_FS_FUSE_REQUEST             CommonReq;\r
+  VIRTIO_FS_FUSE_SETATTR_REQUEST     AttrReq;\r
+  VIRTIO_FS_IO_VECTOR                ReqIoVec[2];\r
+  VIRTIO_FS_SCATTER_GATHER_LIST      ReqSgList;\r
+  VIRTIO_FS_FUSE_RESPONSE            CommonResp;\r
+  VIRTIO_FS_FUSE_GETATTR_RESPONSE    GetAttrResp;\r
+  VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE AttrResp;\r
+  VIRTIO_FS_IO_VECTOR                RespIoVec[3];\r
+  VIRTIO_FS_SCATTER_GATHER_LIST      RespSgList;\r
+  EFI_STATUS                         Status;\r
+\r
+  //\r
+  // Set up the scatter-gather lists.\r
+  //\r
+  ReqIoVec[0].Buffer = &CommonReq;\r
+  ReqIoVec[0].Size   = sizeof CommonReq;\r
+  ReqIoVec[1].Buffer = &AttrReq;\r
+  ReqIoVec[1].Size   = sizeof AttrReq;\r
+  ReqSgList.IoVec    = ReqIoVec;\r
+  ReqSgList.NumVec   = ARRAY_SIZE (ReqIoVec);\r
+\r
+  RespIoVec[0].Buffer = &CommonResp;\r
+  RespIoVec[0].Size   = sizeof CommonResp;\r
+  RespIoVec[1].Buffer = &GetAttrResp;\r
+  RespIoVec[1].Size   = sizeof GetAttrResp;\r
+  RespIoVec[2].Buffer = &AttrResp;\r
+  RespIoVec[2].Size   = sizeof AttrResp;\r
+  RespSgList.IoVec    = RespIoVec;\r
+  RespSgList.NumVec   = ARRAY_SIZE (RespIoVec);\r
+\r
+  //\r
+  // Validate the scatter-gather lists; calculate the total transfer sizes.\r
+  //\r
+  Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Populate the common request header.\r
+  //\r
+  Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,\r
+             VirtioFsFuseOpSetAttr, NodeId);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Populate the FUSE_SETATTR-specific fields.\r
+  //\r
+  AttrReq.Valid      = 0;\r
+  AttrReq.Padding    = 0;\r
+  AttrReq.FileHandle = 0;\r
+  AttrReq.Size       = (Size == NULL) ? 0 : *Size;\r
+  AttrReq.LockOwner  = 0;\r
+  AttrReq.Atime      = (Atime == NULL) ? 0 : *Atime;\r
+  AttrReq.Mtime      = (Mtime == NULL) ? 0 : *Mtime;\r
+  AttrReq.Ctime      = 0;\r
+  AttrReq.AtimeNsec  = 0;\r
+  AttrReq.MtimeNsec  = 0;\r
+  AttrReq.CtimeNsec  = 0;\r
+  AttrReq.Mode       = (Mode == NULL) ? 0 : *Mode;\r
+  AttrReq.Unused4    = 0;\r
+  AttrReq.Uid        = 0;\r
+  AttrReq.Gid        = 0;\r
+  AttrReq.Unused5    = 0;\r
+\r
+  if (Size != NULL) {\r
+    AttrReq.Valid |= VIRTIO_FS_FUSE_SETATTR_REQ_F_SIZE;\r
+  }\r
+  if (Atime != NULL) {\r
+    AttrReq.Valid |= VIRTIO_FS_FUSE_SETATTR_REQ_F_ATIME;\r
+  }\r
+  if (Mtime != NULL) {\r
+    AttrReq.Valid |= VIRTIO_FS_FUSE_SETATTR_REQ_F_MTIME;\r
+  }\r
+  if (Mode != NULL) {\r
+    AttrReq.Valid |= VIRTIO_FS_FUSE_SETATTR_REQ_F_MODE;\r
+  }\r
+\r
+  //\r
+  // Submit the request.\r
+  //\r
+  Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Verify the response (all response buffers are fixed size).\r
+  //\r
+  Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);\r
+  if (Status == EFI_DEVICE_ERROR) {\r
+    DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" NodeId=%Lu", __FUNCTION__,\r
+      VirtioFs->Label, NodeId));\r
+    if (Size != NULL) {\r
+      DEBUG ((DEBUG_ERROR, " Size=0x%Lx", *Size));\r
+    }\r
+    if (Atime != NULL) {\r
+      DEBUG ((DEBUG_ERROR, " Atime=%Lu", *Atime));\r
+    }\r
+    if (Mtime != NULL) {\r
+      DEBUG ((DEBUG_ERROR, " Mtime=%Lu", *Mtime));\r
+    }\r
+    if (Mode != NULL) {\r
+      DEBUG ((DEBUG_ERROR, " Mode=0x%x", *Mode)); // no support for octal :/\r
+    }\r
+    DEBUG ((DEBUG_ERROR, " Errno=%d\n",  CommonResp.Error));\r
+    Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);\r
+  }\r
+  return Status;\r
+}\r
index a6dfac71f4a7fac2459f033657341cc6c7c19cd8..9e6348f9386e738ab7b454e6ceec1352d168c994 100644 (file)
@@ -308,6 +308,16 @@ VirtioFsFuseGetAttr (
      OUT VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE *FuseAttr\r
   );\r
 \r
+EFI_STATUS\r
+VirtioFsFuseSetAttr (\r
+  IN OUT VIRTIO_FS *VirtioFs,\r
+  IN     UINT64    NodeId,\r
+  IN     UINT64    *Size      OPTIONAL,\r
+  IN     UINT64    *Atime     OPTIONAL,\r
+  IN     UINT64    *Mtime     OPTIONAL,\r
+  IN     UINT32    *Mode      OPTIONAL\r
+  );\r
+\r
 EFI_STATUS\r
 VirtioFsFuseMkDir (\r
   IN OUT VIRTIO_FS *VirtioFs,\r
index 9dccd7d6a9ef44a0013b14f3bbe0f4d5bddc93a8..8d962bcdc18c7a93b61f04ddda2f20a449249c3c 100644 (file)
@@ -96,6 +96,7 @@
   FuseRead.c\r
   FuseRelease.c\r
   FuseRename.c\r
+  FuseSetAttr.c\r
   FuseStatFs.c\r
   FuseUnlink.c\r
   FuseWrite.c\r