VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/VSCSI/VSCSIIoReq.cpp

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/* $Id: VSCSIIoReq.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * Virtual SCSI driver: I/O request handling.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27#define LOG_GROUP LOG_GROUP_VSCSI
28#include <VBox/log.h>
29#include <iprt/errcore.h>
30#include <VBox/types.h>
31#include <VBox/vscsi.h>
32#include <iprt/assert.h>
33#include <iprt/mem.h>
34#include <iprt/asm.h>
35
36#include "VSCSIInternal.h"
37
38int vscsiIoReqInit(PVSCSILUNINT pVScsiLun)
39{
40 return vscsiLunReqAllocSizeSet(pVScsiLun, sizeof(VSCSIIOREQINT));
41}
42
43int vscsiIoReqFlushEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)
44{
45 int rc = VINF_SUCCESS;
46 PVSCSIIOREQINT pVScsiIoReq = NULL;
47
48 rc = vscsiLunReqAlloc(pVScsiLun, (uintptr_t)pVScsiReq, &pVScsiIoReq);
49 if (RT_SUCCESS(rc))
50 {
51 pVScsiIoReq->pVScsiReq = pVScsiReq;
52 pVScsiIoReq->pVScsiLun = pVScsiLun;
53 pVScsiIoReq->enmTxDir = VSCSIIOREQTXDIR_FLUSH;
54
55 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
56
57 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
58 if (RT_FAILURE(rc))
59 {
60 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
61 vscsiLunReqFree(pVScsiLun, pVScsiIoReq);
62 }
63 }
64
65 return rc;
66}
67
68
69int vscsiIoReqTransferEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq,
70 VSCSIIOREQTXDIR enmTxDir, uint64_t uOffset,
71 size_t cbTransfer)
72{
73 int rc = VINF_SUCCESS;
74 PVSCSIIOREQINT pVScsiIoReq = NULL;
75
76 LogFlowFunc(("pVScsiLun=%#p pVScsiReq=%#p enmTxDir=%u uOffset=%llu cbTransfer=%u\n",
77 pVScsiLun, pVScsiReq, enmTxDir, uOffset, cbTransfer));
78
79 rc = vscsiLunReqAlloc(pVScsiLun, (uintptr_t)pVScsiReq, &pVScsiIoReq);
80 if (RT_SUCCESS(rc))
81 {
82 pVScsiIoReq->pVScsiReq = pVScsiReq;
83 pVScsiIoReq->pVScsiLun = pVScsiLun;
84 pVScsiIoReq->enmTxDir = enmTxDir;
85 pVScsiIoReq->u.Io.uOffset = uOffset;
86 pVScsiIoReq->u.Io.cbTransfer = cbTransfer;
87 pVScsiIoReq->u.Io.paSeg = pVScsiReq->SgBuf.paSegs;
88 pVScsiIoReq->u.Io.cSeg = pVScsiReq->SgBuf.cSegs;
89
90 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
91
92 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
93 if (RT_FAILURE(rc))
94 {
95 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
96 vscsiLunReqFree(pVScsiLun, pVScsiIoReq);
97 }
98 }
99
100 return rc;
101}
102
103
104int vscsiIoReqTransferEnqueueEx(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq,
105 VSCSIIOREQTXDIR enmTxDir, uint64_t uOffset,
106 PCRTSGSEG paSegs, unsigned cSegs, size_t cbTransfer)
107{
108 int rc = VINF_SUCCESS;
109 PVSCSIIOREQINT pVScsiIoReq = NULL;
110
111 LogFlowFunc(("pVScsiLun=%#p pVScsiReq=%#p enmTxDir=%u uOffset=%llu cbTransfer=%u\n",
112 pVScsiLun, pVScsiReq, enmTxDir, uOffset, cbTransfer));
113
114 rc = vscsiLunReqAlloc(pVScsiLun, (uintptr_t)pVScsiReq, &pVScsiIoReq);
115 if (RT_SUCCESS(rc))
116 {
117 pVScsiIoReq->pVScsiReq = pVScsiReq;
118 pVScsiIoReq->pVScsiLun = pVScsiLun;
119 pVScsiIoReq->enmTxDir = enmTxDir;
120 pVScsiIoReq->u.Io.uOffset = uOffset;
121 pVScsiIoReq->u.Io.cbTransfer = cbTransfer;
122 pVScsiIoReq->u.Io.paSeg = paSegs;
123 pVScsiIoReq->u.Io.cSeg = cSegs;
124
125 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
126
127 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
128 if (RT_FAILURE(rc))
129 {
130 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
131 vscsiLunReqFree(pVScsiLun, pVScsiIoReq);
132 }
133 }
134
135 return rc;
136}
137
138
139int vscsiIoReqUnmapEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq,
140 PRTRANGE paRanges, unsigned cRanges)
141{
142 int rc = VINF_SUCCESS;
143 PVSCSIIOREQINT pVScsiIoReq = NULL;
144
145 LogFlowFunc(("pVScsiLun=%#p pVScsiReq=%#p paRanges=%#p cRanges=%u\n",
146 pVScsiLun, pVScsiReq, paRanges, cRanges));
147
148 rc = vscsiLunReqAlloc(pVScsiLun, (uintptr_t)pVScsiReq, &pVScsiIoReq);
149 if (RT_SUCCESS(rc))
150 {
151 pVScsiIoReq->pVScsiReq = pVScsiReq;
152 pVScsiIoReq->pVScsiLun = pVScsiLun;
153 pVScsiIoReq->enmTxDir = VSCSIIOREQTXDIR_UNMAP;
154 pVScsiIoReq->u.Unmap.paRanges = paRanges;
155 pVScsiIoReq->u.Unmap.cRanges = cRanges;
156
157 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
158
159 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
160 if (RT_FAILURE(rc))
161 {
162 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
163 vscsiLunReqFree(pVScsiLun, pVScsiIoReq);
164 }
165 }
166
167 return rc;
168}
169
170
171uint32_t vscsiIoReqOutstandingCountGet(PVSCSILUNINT pVScsiLun)
172{
173 return ASMAtomicReadU32(&pVScsiLun->IoReq.cReqOutstanding);
174}
175
176
177VBOXDDU_DECL(int) VSCSIIoReqCompleted(VSCSIIOREQ hVScsiIoReq, int rcIoReq, bool fRedoPossible)
178{
179 PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
180 PVSCSILUNINT pVScsiLun;
181 PVSCSIREQINT pVScsiReq;
182 int rcReq = SCSI_STATUS_OK;
183
184 AssertPtrReturn(pVScsiIoReq, VERR_INVALID_HANDLE);
185
186 LogFlowFunc(("hVScsiIoReq=%#p rcIoReq=%Rrc\n", hVScsiIoReq, rcIoReq));
187
188 pVScsiLun = pVScsiIoReq->pVScsiLun;
189 pVScsiReq = pVScsiIoReq->pVScsiReq;
190
191 AssertMsg(pVScsiLun->IoReq.cReqOutstanding > 0,
192 ("Unregistered I/O request completed\n"));
193
194 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
195
196 if (RT_SUCCESS(rcIoReq))
197 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
198 else if (!fRedoPossible)
199 {
200 /** @todo Not 100% correct for the write case as the 0x00 ASCQ for write errors
201 * is not used for SBC devices. */
202 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_MEDIUM_ERROR,
203 pVScsiIoReq->enmTxDir == VSCSIIOREQTXDIR_READ
204 ? SCSI_ASC_READ_ERROR
205 : SCSI_ASC_WRITE_ERROR,
206 0x00);
207 }
208 else
209 rcReq = SCSI_STATUS_CHECK_CONDITION;
210
211 if (pVScsiIoReq->enmTxDir == VSCSIIOREQTXDIR_UNMAP)
212 RTMemFree(pVScsiIoReq->u.Unmap.paRanges);
213
214 /* Free the I/O request */
215 vscsiLunReqFree(pVScsiLun, pVScsiIoReq);
216
217 /* Notify completion of the SCSI request. */
218 vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, fRedoPossible, rcIoReq);
219
220 return VINF_SUCCESS;
221}
222
223
224VBOXDDU_DECL(VSCSIIOREQTXDIR) VSCSIIoReqTxDirGet(VSCSIIOREQ hVScsiIoReq)
225{
226 PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
227
228 AssertPtrReturn(pVScsiIoReq, VSCSIIOREQTXDIR_INVALID);
229
230 return pVScsiIoReq->enmTxDir;
231}
232
233
234VBOXDDU_DECL(int) VSCSIIoReqParamsGet(VSCSIIOREQ hVScsiIoReq, uint64_t *puOffset,
235 size_t *pcbTransfer, unsigned *pcSeg,
236 size_t *pcbSeg, PCRTSGSEG *ppaSeg)
237{
238 PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
239
240 AssertPtrReturn(pVScsiIoReq, VERR_INVALID_HANDLE);
241 AssertReturn( pVScsiIoReq->enmTxDir != VSCSIIOREQTXDIR_FLUSH
242 && pVScsiIoReq->enmTxDir != VSCSIIOREQTXDIR_UNMAP,
243 VERR_NOT_SUPPORTED);
244
245 *puOffset = pVScsiIoReq->u.Io.uOffset;
246 *pcbTransfer = pVScsiIoReq->u.Io.cbTransfer;
247 *pcSeg = pVScsiIoReq->u.Io.cSeg;
248 *pcbSeg = pVScsiIoReq->u.Io.cbSeg;
249 *ppaSeg = pVScsiIoReq->u.Io.paSeg;
250
251 return VINF_SUCCESS;
252}
253
254VBOXDDU_DECL(int) VSCSIIoReqUnmapParamsGet(VSCSIIOREQ hVScsiIoReq, PCRTRANGE *ppaRanges,
255 unsigned *pcRanges)
256{
257 PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
258
259 AssertPtrReturn(pVScsiIoReq, VERR_INVALID_HANDLE);
260 AssertReturn(pVScsiIoReq->enmTxDir == VSCSIIOREQTXDIR_UNMAP, VERR_NOT_SUPPORTED);
261
262 *ppaRanges = pVScsiIoReq->u.Unmap.paRanges;
263 *pcRanges = pVScsiIoReq->u.Unmap.cRanges;
264
265 return VINF_SUCCESS;
266}
267
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use