FuseSetAttr.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /** @file
  2. FUSE_SETATTR wrapper for the Virtio Filesystem device.
  3. Copyright (C) 2020, Red Hat, Inc.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "VirtioFsDxe.h"
  7. /**
  8. Send the FUSE_SETATTR request to the Virtio Filesystem device, for changing
  9. the attributes of an inode.
  10. The function may only be called after VirtioFsFuseInitSession() returns
  11. successfully and before VirtioFsUninit() is called.
  12. @param[in,out] VirtioFs The Virtio Filesystem device to send the
  13. FUSE_SETATTR request to. On output, the FUSE request
  14. counter "VirtioFs->RequestId" will have been
  15. incremented.
  16. @param[in] NodeId The inode number representing the regular file or
  17. directory whose attributes should be changed.
  18. @param[in] Size The new size to set for the regular file. If NULL,
  19. then the file size will not be changed. If NodeId
  20. refers to a directory, then the caller is
  21. responsible for passing NULL as Size.
  22. @param[in] Atime The new last access time to set for the regular file
  23. or directory (seconds since the Epoch). If NULL,
  24. then the last access time is not changed.
  25. @param[in] Mtime The new last modification time to set for the
  26. regular file or directory (seconds since the Epoch).
  27. If NULL, then the last modification time is not
  28. changed.
  29. @param[in] Mode The new file mode bits to set for the regular file
  30. or directory. If NULL, then the file mode bits are
  31. not changed.
  32. @retval EFI_SUCCESS The attributes have been updated.
  33. @return The "errno" value mapped to an EFI_STATUS code, if the
  34. Virtio Filesystem device explicitly reported an error.
  35. @return Error codes propagated from VirtioFsSgListsValidate(),
  36. VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
  37. VirtioFsFuseCheckResponse().
  38. **/
  39. EFI_STATUS
  40. VirtioFsFuseSetAttr (
  41. IN OUT VIRTIO_FS *VirtioFs,
  42. IN UINT64 NodeId,
  43. IN UINT64 *Size OPTIONAL,
  44. IN UINT64 *Atime OPTIONAL,
  45. IN UINT64 *Mtime OPTIONAL,
  46. IN UINT32 *Mode OPTIONAL
  47. )
  48. {
  49. VIRTIO_FS_FUSE_REQUEST CommonReq;
  50. VIRTIO_FS_FUSE_SETATTR_REQUEST AttrReq;
  51. VIRTIO_FS_IO_VECTOR ReqIoVec[2];
  52. VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
  53. VIRTIO_FS_FUSE_RESPONSE CommonResp;
  54. VIRTIO_FS_FUSE_GETATTR_RESPONSE GetAttrResp;
  55. VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE AttrResp;
  56. VIRTIO_FS_IO_VECTOR RespIoVec[3];
  57. VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
  58. EFI_STATUS Status;
  59. //
  60. // Set up the scatter-gather lists.
  61. //
  62. ReqIoVec[0].Buffer = &CommonReq;
  63. ReqIoVec[0].Size = sizeof CommonReq;
  64. ReqIoVec[1].Buffer = &AttrReq;
  65. ReqIoVec[1].Size = sizeof AttrReq;
  66. ReqSgList.IoVec = ReqIoVec;
  67. ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
  68. RespIoVec[0].Buffer = &CommonResp;
  69. RespIoVec[0].Size = sizeof CommonResp;
  70. RespIoVec[1].Buffer = &GetAttrResp;
  71. RespIoVec[1].Size = sizeof GetAttrResp;
  72. RespIoVec[2].Buffer = &AttrResp;
  73. RespIoVec[2].Size = sizeof AttrResp;
  74. RespSgList.IoVec = RespIoVec;
  75. RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
  76. //
  77. // Validate the scatter-gather lists; calculate the total transfer sizes.
  78. //
  79. Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
  80. if (EFI_ERROR (Status)) {
  81. return Status;
  82. }
  83. //
  84. // Populate the common request header.
  85. //
  86. Status = VirtioFsFuseNewRequest (
  87. VirtioFs,
  88. &CommonReq,
  89. ReqSgList.TotalSize,
  90. VirtioFsFuseOpSetAttr,
  91. NodeId
  92. );
  93. if (EFI_ERROR (Status)) {
  94. return Status;
  95. }
  96. //
  97. // Populate the FUSE_SETATTR-specific fields.
  98. //
  99. AttrReq.Valid = 0;
  100. AttrReq.Padding = 0;
  101. AttrReq.FileHandle = 0;
  102. AttrReq.Size = (Size == NULL) ? 0 : *Size;
  103. AttrReq.LockOwner = 0;
  104. AttrReq.Atime = (Atime == NULL) ? 0 : *Atime;
  105. AttrReq.Mtime = (Mtime == NULL) ? 0 : *Mtime;
  106. AttrReq.Ctime = 0;
  107. AttrReq.AtimeNsec = 0;
  108. AttrReq.MtimeNsec = 0;
  109. AttrReq.CtimeNsec = 0;
  110. AttrReq.Mode = (Mode == NULL) ? 0 : *Mode;
  111. AttrReq.Unused4 = 0;
  112. AttrReq.Uid = 0;
  113. AttrReq.Gid = 0;
  114. AttrReq.Unused5 = 0;
  115. if (Size != NULL) {
  116. AttrReq.Valid |= VIRTIO_FS_FUSE_SETATTR_REQ_F_SIZE;
  117. }
  118. if (Atime != NULL) {
  119. AttrReq.Valid |= VIRTIO_FS_FUSE_SETATTR_REQ_F_ATIME;
  120. }
  121. if (Mtime != NULL) {
  122. AttrReq.Valid |= VIRTIO_FS_FUSE_SETATTR_REQ_F_MTIME;
  123. }
  124. if (Mode != NULL) {
  125. AttrReq.Valid |= VIRTIO_FS_FUSE_SETATTR_REQ_F_MODE;
  126. }
  127. //
  128. // Submit the request.
  129. //
  130. Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
  131. if (EFI_ERROR (Status)) {
  132. return Status;
  133. }
  134. //
  135. // Verify the response (all response buffers are fixed size).
  136. //
  137. Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
  138. if (Status == EFI_DEVICE_ERROR) {
  139. DEBUG ((
  140. DEBUG_ERROR,
  141. "%a: Label=\"%s\" NodeId=%Lu",
  142. __FUNCTION__,
  143. VirtioFs->Label,
  144. NodeId
  145. ));
  146. if (Size != NULL) {
  147. DEBUG ((DEBUG_ERROR, " Size=0x%Lx", *Size));
  148. }
  149. if (Atime != NULL) {
  150. DEBUG ((DEBUG_ERROR, " Atime=%Lu", *Atime));
  151. }
  152. if (Mtime != NULL) {
  153. DEBUG ((DEBUG_ERROR, " Mtime=%Lu", *Mtime));
  154. }
  155. if (Mode != NULL) {
  156. DEBUG ((DEBUG_ERROR, " Mode=0x%x", *Mode)); // no support for octal :/
  157. }
  158. DEBUG ((DEBUG_ERROR, " Errno=%d\n", CommonResp.Error));
  159. Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
  160. }
  161. return Status;
  162. }