]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioFsDxe/FuseWrite.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / VirtioFsDxe / FuseWrite.c
1 /** @file
2 FUSE_WRITE wrapper for the Virtio Filesystem device.
3
4 Copyright (C) 2020, Red Hat, Inc.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8
9 #include "VirtioFsDxe.h"
10
11 /**
12 Write a chunk to a regular file, by sending the FUSE_WRITE request to the
13 Virtio Filesystem device.
14
15 The function may only be called after VirtioFsFuseInitSession() returns
16 successfully and before VirtioFsUninit() is called.
17
18 @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_WRITE
19 request to. On output, the FUSE request counter
20 "VirtioFs->RequestId" will have been incremented.
21
22 @param[in] NodeId The inode number of the regular file to write to.
23
24 @param[in] FuseHandle The open handle to the regular file to write to.
25
26 @param[in] Offset The absolute file position at which to start
27 writing.
28
29 @param[in,out] Size On input, the number of bytes to write. On
30 successful return, the number of bytes actually
31 written, which may be smaller than the value on
32 input.
33
34 @param[in] Data The buffer to write to the regular file.
35
36 @retval EFI_SUCCESS Write successful. The caller is responsible for
37 checking Size to learn the actual byte count
38 transferred.
39
40 @retval EFI_BAD_BUFFER_SIZE On input, Size is larger than
41 "VirtioFs->MaxWrite".
42
43 @return The "errno" value mapped to an EFI_STATUS code,
44 if the Virtio Filesystem device explicitly
45 reported an error.
46
47 @return Error codes propagated from
48 VirtioFsSgListsValidate(),
49 VirtioFsFuseNewRequest(),
50 VirtioFsSgListsSubmit(),
51 VirtioFsFuseCheckResponse().
52 **/
53 EFI_STATUS
54 VirtioFsFuseWrite (
55 IN OUT VIRTIO_FS *VirtioFs,
56 IN UINT64 NodeId,
57 IN UINT64 FuseHandle,
58 IN UINT64 Offset,
59 IN OUT UINT32 *Size,
60 IN VOID *Data
61 )
62 {
63 VIRTIO_FS_FUSE_REQUEST CommonReq;
64 VIRTIO_FS_FUSE_WRITE_REQUEST WriteReq;
65 VIRTIO_FS_IO_VECTOR ReqIoVec[3];
66 VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
67 VIRTIO_FS_FUSE_RESPONSE CommonResp;
68 VIRTIO_FS_FUSE_WRITE_RESPONSE WriteResp;
69 VIRTIO_FS_IO_VECTOR RespIoVec[2];
70 VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
71 EFI_STATUS Status;
72
73 //
74 // Honor the write buffer size limit of the Virtio Filesystem device.
75 //
76 if (*Size > VirtioFs->MaxWrite) {
77 return EFI_BAD_BUFFER_SIZE;
78 }
79
80 //
81 // Set up the scatter-gather lists.
82 //
83 ReqIoVec[0].Buffer = &CommonReq;
84 ReqIoVec[0].Size = sizeof CommonReq;
85 ReqIoVec[1].Buffer = &WriteReq;
86 ReqIoVec[1].Size = sizeof WriteReq;
87 ReqIoVec[2].Buffer = Data;
88 ReqIoVec[2].Size = *Size;
89 ReqSgList.IoVec = ReqIoVec;
90 ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
91
92 RespIoVec[0].Buffer = &CommonResp;
93 RespIoVec[0].Size = sizeof CommonResp;
94 RespIoVec[1].Buffer = &WriteResp;
95 RespIoVec[1].Size = sizeof WriteResp;
96 RespSgList.IoVec = RespIoVec;
97 RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
98
99 //
100 // Validate the scatter-gather lists; calculate the total transfer sizes.
101 //
102 Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
103 if (EFI_ERROR (Status)) {
104 return Status;
105 }
106
107 //
108 // Populate the common request header.
109 //
110 Status = VirtioFsFuseNewRequest (
111 VirtioFs,
112 &CommonReq,
113 ReqSgList.TotalSize,
114 VirtioFsFuseOpWrite,
115 NodeId
116 );
117 if (EFI_ERROR (Status)) {
118 return Status;
119 }
120
121 //
122 // Populate the FUSE_WRITE-specific fields.
123 //
124 WriteReq.FileHandle = FuseHandle;
125 WriteReq.Offset = Offset;
126 WriteReq.Size = *Size;
127 WriteReq.WriteFlags = 0;
128 WriteReq.LockOwner = 0;
129 WriteReq.Flags = 0;
130 WriteReq.Padding = 0;
131
132 //
133 // Submit the request.
134 //
135 Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
136 if (EFI_ERROR (Status)) {
137 return Status;
138 }
139
140 //
141 // Verify the response (all response buffers are fixed size).
142 //
143 Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
144 if (EFI_ERROR (Status)) {
145 if (Status == EFI_DEVICE_ERROR) {
146 DEBUG ((
147 DEBUG_ERROR,
148 "%a: Label=\"%s\" NodeId=%Lu FuseHandle=%Lu "
149 "Offset=0x%Lx Size=0x%x Data@%p Errno=%d\n",
150 __FUNCTION__,
151 VirtioFs->Label,
152 NodeId,
153 FuseHandle,
154 Offset,
155 *Size,
156 Data,
157 CommonResp.Error
158 ));
159 Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
160 }
161
162 return Status;
163 }
164
165 //
166 // Report the actual transfer size.
167 //
168 *Size = WriteResp.Size;
169 return EFI_SUCCESS;
170 }