VirtualBox

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

Last change on this file since 42891 was 38878, checked in by vboxsync, 13 years ago

PDM,Devices,Drivers: Add async discard API and make us of it

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.7 KB
Line 
1/* $Id: VSCSIIoReq.cpp 38878 2011-09-27 09:07:07Z vboxsync $ */
2/** @file
3 * Virtual SCSI driver: I/O request handling.
4 */
5
6/*
7 * Copyright (C) 2006-2011 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17#define LOG_GROUP LOG_GROUP_VSCSI
18#include <VBox/log.h>
19#include <VBox/err.h>
20#include <VBox/types.h>
21#include <VBox/vscsi.h>
22#include <iprt/assert.h>
23#include <iprt/mem.h>
24#include <iprt/asm.h>
25
26#include "VSCSIInternal.h"
27
28int vscsiIoReqFlushEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)
29{
30 int rc = VINF_SUCCESS;
31 PVSCSIIOREQINT pVScsiIoReq = NULL;
32
33 pVScsiIoReq = (PVSCSIIOREQINT)RTMemAllocZ(sizeof(VSCSIIOREQINT));
34 if (!pVScsiIoReq)
35 return VERR_NO_MEMORY;
36
37 pVScsiIoReq->pVScsiReq = pVScsiReq;
38 pVScsiIoReq->pVScsiLun = pVScsiLun;
39 pVScsiIoReq->enmTxDir = VSCSIIOREQTXDIR_FLUSH;
40
41 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
42
43 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
44 if (RT_FAILURE(rc))
45 {
46 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
47 RTMemFree(pVScsiIoReq);
48 }
49
50 return rc;
51}
52
53
54int vscsiIoReqTransferEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq,
55 VSCSIIOREQTXDIR enmTxDir, uint64_t uOffset,
56 size_t cbTransfer)
57{
58 int rc = VINF_SUCCESS;
59 PVSCSIIOREQINT pVScsiIoReq = NULL;
60
61 LogFlowFunc(("pVScsiLun=%#p pVScsiReq=%#p enmTxDir=%u uOffset=%llu cbTransfer=%u\n",
62 pVScsiLun, pVScsiReq, enmTxDir, uOffset, cbTransfer));
63
64 pVScsiIoReq = (PVSCSIIOREQINT)RTMemAllocZ(sizeof(VSCSIIOREQINT));
65 if (!pVScsiIoReq)
66 return VERR_NO_MEMORY;
67
68 pVScsiIoReq->pVScsiReq = pVScsiReq;
69 pVScsiIoReq->pVScsiLun = pVScsiLun;
70 pVScsiIoReq->enmTxDir = enmTxDir;
71 pVScsiIoReq->u.Io.uOffset = uOffset;
72 pVScsiIoReq->u.Io.cbTransfer = cbTransfer;
73 pVScsiIoReq->u.Io.paSeg = pVScsiReq->SgBuf.paSegs;
74 pVScsiIoReq->u.Io.cSeg = pVScsiReq->SgBuf.cSegs;
75
76 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
77
78 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
79 if (RT_FAILURE(rc))
80 {
81 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
82 RTMemFree(pVScsiIoReq);
83 }
84
85 return rc;
86}
87
88
89int vscsiIoReqUnmapEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq,
90 PRTRANGE paRanges, unsigned cRanges)
91{
92 int rc = VINF_SUCCESS;
93 PVSCSIIOREQINT pVScsiIoReq = NULL;
94
95 LogFlowFunc(("pVScsiLun=%#p pVScsiReq=%#p paRanges=%#p cRanges=%u\n",
96 pVScsiLun, pVScsiReq, paRanges, cRanges));
97
98 pVScsiIoReq = (PVSCSIIOREQINT)RTMemAllocZ(sizeof(VSCSIIOREQINT));
99 if (!pVScsiIoReq)
100 return VERR_NO_MEMORY;
101
102 pVScsiIoReq->pVScsiReq = pVScsiReq;
103 pVScsiIoReq->pVScsiLun = pVScsiLun;
104 pVScsiIoReq->enmTxDir = VSCSIIOREQTXDIR_UNMAP;
105 pVScsiIoReq->u.Unmap.paRanges = paRanges;
106 pVScsiIoReq->u.Unmap.cRanges = cRanges;
107
108 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
109
110 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
111 if (RT_FAILURE(rc))
112 {
113 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
114 RTMemFree(pVScsiIoReq);
115 }
116
117 return rc;
118}
119
120
121uint32_t vscsiIoReqOutstandingCountGet(PVSCSILUNINT pVScsiLun)
122{
123 return ASMAtomicReadU32(&pVScsiLun->IoReq.cReqOutstanding);
124}
125
126
127VBOXDDU_DECL(int) VSCSIIoReqCompleted(VSCSIIOREQ hVScsiIoReq, int rcIoReq, bool fRedoPossible)
128{
129 PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
130 PVSCSILUNINT pVScsiLun;
131 PVSCSIREQINT pVScsiReq;
132 int rcReq = SCSI_STATUS_OK;
133
134 AssertPtrReturn(pVScsiIoReq, VERR_INVALID_HANDLE);
135
136 LogFlowFunc(("hVScsiIoReq=%#p rcIoReq=%Rrc\n", hVScsiIoReq, rcIoReq));
137
138 pVScsiLun = pVScsiIoReq->pVScsiLun;
139 pVScsiReq = pVScsiIoReq->pVScsiReq;
140
141 AssertMsg(pVScsiLun->IoReq.cReqOutstanding > 0,
142 ("Unregistered I/O request completed\n"));
143
144 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
145
146 if (RT_SUCCESS(rcIoReq))
147 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
148 else if (!fRedoPossible)
149 {
150 /** @todo Not 100% correct for the write case as the 0x00 ASCQ for write errors
151 * is not used for SBC devices. */
152 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_MEDIUM_ERROR,
153 pVScsiIoReq->enmTxDir == VSCSIIOREQTXDIR_READ
154 ? SCSI_ASC_READ_ERROR
155 : SCSI_ASC_WRITE_ERROR,
156 0x00);
157 }
158 else
159 rcReq = SCSI_STATUS_CHECK_CONDITION;
160
161 if (pVScsiIoReq->enmTxDir == VSCSIIOREQTXDIR_UNMAP)
162 RTMemFree(pVScsiIoReq->u.Unmap.paRanges);
163
164 /* Free the I/O request */
165 RTMemFree(pVScsiIoReq);
166
167 /* Notify completion of the SCSI request. */
168 vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, fRedoPossible, rcIoReq);
169
170 return VINF_SUCCESS;
171}
172
173
174VBOXDDU_DECL(VSCSIIOREQTXDIR) VSCSIIoReqTxDirGet(VSCSIIOREQ hVScsiIoReq)
175{
176 PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
177
178 AssertPtrReturn(pVScsiIoReq, VSCSIIOREQTXDIR_INVALID);
179
180 return pVScsiIoReq->enmTxDir;
181}
182
183
184VBOXDDU_DECL(int) VSCSIIoReqParamsGet(VSCSIIOREQ hVScsiIoReq, uint64_t *puOffset,
185 size_t *pcbTransfer, unsigned *pcSeg,
186 size_t *pcbSeg, PCRTSGSEG *ppaSeg)
187{
188 PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
189
190 AssertPtrReturn(pVScsiIoReq, VERR_INVALID_HANDLE);
191 AssertReturn( pVScsiIoReq->enmTxDir != VSCSIIOREQTXDIR_FLUSH
192 && pVScsiIoReq->enmTxDir != VSCSIIOREQTXDIR_UNMAP,
193 VERR_NOT_SUPPORTED);
194
195 *puOffset = pVScsiIoReq->u.Io.uOffset;
196 *pcbTransfer = pVScsiIoReq->u.Io.cbTransfer;
197 *pcSeg = pVScsiIoReq->u.Io.cSeg;
198 *pcbSeg = pVScsiIoReq->u.Io.cbSeg;
199 *ppaSeg = pVScsiIoReq->u.Io.paSeg;
200
201 return VINF_SUCCESS;
202}
203
204VBOXDDU_DECL(int) VSCSIIoReqUnmapParamsGet(VSCSIIOREQ hVScsiIoReq, PCRTRANGE *ppaRanges,
205 unsigned *pcRanges)
206{
207 PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
208
209 AssertPtrReturn(pVScsiIoReq, VERR_INVALID_HANDLE);
210 AssertReturn(pVScsiIoReq->enmTxDir == VSCSIIOREQTXDIR_UNMAP, VERR_NOT_SUPPORTED);
211
212 *ppaRanges = pVScsiIoReq->u.Unmap.paRanges;
213 *pcRanges = pVScsiIoReq->u.Unmap.cRanges;
214
215 return VINF_SUCCESS;
216}
217
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette