2 FUSE_WRITE wrapper for the Virtio Filesystem device.
4 Copyright (C) 2020, Red Hat, Inc.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "VirtioFsDxe.h"
12 Write a chunk to a regular file, by sending the FUSE_WRITE request to the
13 Virtio Filesystem device.
15 The function may only be called after VirtioFsFuseInitSession() returns
16 successfully and before VirtioFsUninit() is called.
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.
22 @param[in] NodeId The inode number of the regular file to write to.
24 @param[in] FuseHandle The open handle to the regular file to write to.
26 @param[in] Offset The absolute file position at which to start
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
34 @param[in] Data The buffer to write to the regular file.
36 @retval EFI_SUCCESS Write successful. The caller is responsible for
37 checking Size to learn the actual byte count
40 @retval EFI_BAD_BUFFER_SIZE On input, Size is larger than
43 @return The "errno" value mapped to an EFI_STATUS code,
44 if the Virtio Filesystem device explicitly
47 @return Error codes propagated from
48 VirtioFsSgListsValidate(),
49 VirtioFsFuseNewRequest(),
50 VirtioFsSgListsSubmit(),
51 VirtioFsFuseCheckResponse().
55 IN OUT VIRTIO_FS
*VirtioFs
,
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
;
74 // Honor the write buffer size limit of the Virtio Filesystem device.
76 if (*Size
> VirtioFs
->MaxWrite
) {
77 return EFI_BAD_BUFFER_SIZE
;
81 // Set up the scatter-gather lists.
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
);
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
);
100 // Validate the scatter-gather lists; calculate the total transfer sizes.
102 Status
= VirtioFsSgListsValidate (VirtioFs
, &ReqSgList
, &RespSgList
);
103 if (EFI_ERROR (Status
)) {
108 // Populate the common request header.
110 Status
= VirtioFsFuseNewRequest (
117 if (EFI_ERROR (Status
)) {
122 // Populate the FUSE_WRITE-specific fields.
124 WriteReq
.FileHandle
= FuseHandle
;
125 WriteReq
.Offset
= Offset
;
126 WriteReq
.Size
= *Size
;
127 WriteReq
.WriteFlags
= 0;
128 WriteReq
.LockOwner
= 0;
130 WriteReq
.Padding
= 0;
133 // Submit the request.
135 Status
= VirtioFsSgListsSubmit (VirtioFs
, &ReqSgList
, &RespSgList
);
136 if (EFI_ERROR (Status
)) {
141 // Verify the response (all response buffers are fixed size).
143 Status
= VirtioFsFuseCheckResponse (&RespSgList
, CommonReq
.Unique
, NULL
);
144 if (EFI_ERROR (Status
)) {
145 if (Status
== EFI_DEVICE_ERROR
) {
148 "%a: Label=\"%s\" NodeId=%Lu FuseHandle=%Lu "
149 "Offset=0x%Lx Size=0x%x Data@%p Errno=%d\n",
159 Status
= VirtioFsErrnoToEfiStatus (CommonResp
.Error
);
166 // Report the actual transfer size.
168 *Size
= WriteResp
.Size
;