VirtualBox

source: vbox/trunk/src/VBox/VMM/PDMAsyncCompletionFileFailsafe.cpp@ 28800

Last change on this file since 28800 was 28800, checked in by vboxsync, 14 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.0 KB
Line 
1/* $Id: PDMAsyncCompletionFileFailsafe.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
2/** @file
3 * PDM Async I/O - Transport data asynchronous in R3 using EMT.
4 * Simple File I/O manager.
5 */
6
7/*
8 * Copyright (C) 2006-2008 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18#define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION
19#include <iprt/types.h>
20#include <iprt/assert.h>
21#include <VBox/log.h>
22
23#include "PDMAsyncCompletionFileInternal.h"
24
25static int pdmacFileAioMgrFailsafeProcessEndpointTaskList(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
26 PPDMACTASKFILE pTasks)
27{
28 int rc = VINF_SUCCESS;
29
30 while (pTasks)
31 {
32 PPDMACTASKFILE pCurr = pTasks;
33
34 pTasks = pTasks->pNext;
35
36 switch (pCurr->enmTransferType)
37 {
38 case PDMACTASKFILETRANSFER_FLUSH:
39 {
40 rc = RTFileFlush(pEndpoint->File);
41 break;
42 }
43 case PDMACTASKFILETRANSFER_READ:
44 case PDMACTASKFILETRANSFER_WRITE:
45 {
46 if (pCurr->enmTransferType == PDMACTASKFILETRANSFER_READ)
47 {
48 rc = RTFileReadAt(pEndpoint->File, pCurr->Off,
49 pCurr->DataSeg.pvSeg,
50 pCurr->DataSeg.cbSeg,
51 NULL);
52 }
53 else
54 {
55 if (RT_UNLIKELY((uint64_t)pCurr->Off + pCurr->DataSeg.cbSeg > pEndpoint->cbFile))
56 {
57 ASMAtomicWriteU64(&pEndpoint->cbFile, pCurr->Off + pCurr->DataSeg.cbSeg);
58 RTFileSetSize(pEndpoint->File, pCurr->Off + pCurr->DataSeg.cbSeg);
59 }
60
61 rc = RTFileWriteAt(pEndpoint->File, pCurr->Off,
62 pCurr->DataSeg.pvSeg,
63 pCurr->DataSeg.cbSeg,
64 NULL);
65 }
66
67 break;
68 }
69 default:
70 AssertMsgFailed(("Invalid transfer type %d\n", pTasks->enmTransferType));
71 }
72
73 pCurr->pfnCompleted(pCurr, pCurr->pvUser, rc);
74 pdmacFileTaskFree(pEndpoint, pCurr);
75 }
76
77 return VINF_SUCCESS;
78}
79
80static int pdmacFileAioMgrFailsafeProcessEndpoint(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint)
81{
82 int rc = VINF_SUCCESS;
83 PPDMACTASKFILE pTasks = pEndpoint->AioMgr.pReqsPendingHead;
84
85 pEndpoint->AioMgr.pReqsPendingHead = NULL;
86 pEndpoint->AioMgr.pReqsPendingTail = NULL;
87
88 /* Process the request pending list first in case the endpoint was migrated due to an error. */
89 if (pTasks)
90 rc = pdmacFileAioMgrFailsafeProcessEndpointTaskList(pEndpoint, pTasks);
91
92 if (RT_SUCCESS(rc))
93 {
94 pTasks = pdmacFileEpGetNewTasks(pEndpoint);
95
96 if (pTasks)
97 rc = pdmacFileAioMgrFailsafeProcessEndpointTaskList(pEndpoint, pTasks);
98 }
99
100 return rc;
101}
102
103/**
104 * A fallback method in case something goes wrong with the normal
105 * I/O manager.
106 */
107int pdmacFileAioMgrFailsafe(RTTHREAD ThreadSelf, void *pvUser)
108{
109 int rc = VINF_SUCCESS;
110 PPDMACEPFILEMGR pAioMgr = (PPDMACEPFILEMGR)pvUser;
111
112 while ( (pAioMgr->enmState == PDMACEPFILEMGRSTATE_RUNNING)
113 || (pAioMgr->enmState == PDMACEPFILEMGRSTATE_SUSPENDING))
114 {
115 if (!ASMAtomicReadBool(&pAioMgr->fWokenUp))
116 {
117 ASMAtomicWriteBool(&pAioMgr->fWaitingEventSem, true);
118 rc = RTSemEventWait(pAioMgr->EventSem, RT_INDEFINITE_WAIT);
119 ASMAtomicWriteBool(&pAioMgr->fWaitingEventSem, false);
120 AssertRC(rc);
121 }
122 ASMAtomicXchgBool(&pAioMgr->fWokenUp, false);
123
124 /* Process endpoint events first. */
125 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint = pAioMgr->pEndpointsHead;
126 while (pEndpoint)
127 {
128 rc = pdmacFileAioMgrFailsafeProcessEndpoint(pEndpoint);
129 AssertRC(rc);
130 pEndpoint = pEndpoint->AioMgr.pEndpointNext;
131 }
132
133 /* Now check for an external blocking event. */
134 if (pAioMgr->fBlockingEventPending)
135 {
136 switch (pAioMgr->enmBlockingEvent)
137 {
138 case PDMACEPFILEAIOMGRBLOCKINGEVENT_ADD_ENDPOINT:
139 {
140 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointNew = pAioMgr->BlockingEventData.AddEndpoint.pEndpoint;
141 AssertMsg(VALID_PTR(pEndpointNew), ("Adding endpoint event without a endpoint to add\n"));
142
143 pEndpointNew->enmState = PDMASYNCCOMPLETIONENDPOINTFILESTATE_ACTIVE;
144
145 pEndpointNew->AioMgr.pEndpointNext = pAioMgr->pEndpointsHead;
146 pEndpointNew->AioMgr.pEndpointPrev = NULL;
147 if (pAioMgr->pEndpointsHead)
148 pAioMgr->pEndpointsHead->AioMgr.pEndpointPrev = pEndpointNew;
149 pAioMgr->pEndpointsHead = pEndpointNew;
150
151 pAioMgr->cEndpoints++;
152
153 /*
154 * Process the task list the first time. There might be pending requests
155 * if the endpoint was migrated from another endpoint.
156 */
157 rc = pdmacFileAioMgrFailsafeProcessEndpoint(pEndpointNew);
158 AssertRC(rc);
159 break;
160 }
161 case PDMACEPFILEAIOMGRBLOCKINGEVENT_REMOVE_ENDPOINT:
162 {
163 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointRemove = pAioMgr->BlockingEventData.RemoveEndpoint.pEndpoint;
164 AssertMsg(VALID_PTR(pEndpointRemove), ("Removing endpoint event without a endpoint to remove\n"));
165
166 pEndpointRemove->enmState = PDMASYNCCOMPLETIONENDPOINTFILESTATE_REMOVING;
167
168 PPDMASYNCCOMPLETIONENDPOINTFILE pPrev = pEndpointRemove->AioMgr.pEndpointPrev;
169 PPDMASYNCCOMPLETIONENDPOINTFILE pNext = pEndpointRemove->AioMgr.pEndpointNext;
170
171 if (pPrev)
172 pPrev->AioMgr.pEndpointNext = pNext;
173 else
174 pAioMgr->pEndpointsHead = pNext;
175
176 if (pNext)
177 pNext->AioMgr.pEndpointPrev = pPrev;
178
179 pAioMgr->cEndpoints--;
180 break;
181 }
182 case PDMACEPFILEAIOMGRBLOCKINGEVENT_CLOSE_ENDPOINT:
183 {
184 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointClose = pAioMgr->BlockingEventData.CloseEndpoint.pEndpoint;
185 AssertMsg(VALID_PTR(pEndpointClose), ("Close endpoint event without a endpoint to Close\n"));
186
187 pEndpointClose->enmState = PDMASYNCCOMPLETIONENDPOINTFILESTATE_CLOSING;
188
189 /* Make sure all tasks finished. */
190 rc = pdmacFileAioMgrFailsafeProcessEndpoint(pEndpointClose);
191 AssertRC(rc);
192 break;
193 }
194 case PDMACEPFILEAIOMGRBLOCKINGEVENT_SHUTDOWN:
195 pAioMgr->enmState = PDMACEPFILEMGRSTATE_SHUTDOWN;
196 break;
197 case PDMACEPFILEAIOMGRBLOCKINGEVENT_SUSPEND:
198 pAioMgr->enmState = PDMACEPFILEMGRSTATE_SUSPENDING;
199 break;
200 case PDMACEPFILEAIOMGRBLOCKINGEVENT_RESUME:
201 pAioMgr->enmState = PDMACEPFILEMGRSTATE_RUNNING;
202 break;
203 default:
204 AssertMsgFailed(("Invalid event type %d\n", pAioMgr->enmBlockingEvent));
205 }
206
207 /* Release the waiting thread. */
208 rc = RTSemEventSignal(pAioMgr->EventSemBlock);
209 AssertRC(rc);
210 }
211 }
212
213 return rc;
214}
215
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use