~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/VMM/PDMAsyncCompletionFileInternal.h

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: PDMAsyncCompletionFileInternal.h $ */
2
 
/** @file
3
 
 * PDM Async I/O - Transport data asynchronous in R3 using EMT.
4
 
 */
5
 
 
6
 
/*
7
 
 * Copyright (C) 2006-2008 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
 
 
18
 
#ifndef ___PDMAsyncCompletionFileInternal_h
19
 
#define ___PDMAsyncCompletionFileInternal_h
20
 
 
21
 
#include <VBox/cfgm.h>
22
 
#include <VBox/stam.h>
23
 
#include <VBox/tm.h>
24
 
#include <iprt/types.h>
25
 
#include <iprt/file.h>
26
 
#include <iprt/thread.h>
27
 
#include <iprt/semaphore.h>
28
 
#include <iprt/critsect.h>
29
 
#include <iprt/avl.h>
30
 
#include <iprt/list.h>
31
 
#include <iprt/spinlock.h>
32
 
#include <iprt/memcache.h>
33
 
 
34
 
#include "PDMAsyncCompletionInternal.h"
35
 
 
36
 
/** @todo: Revise the caching of tasks. We have currently four caches:
37
 
 *  Per endpoint task cache
38
 
 *  Per class cache
39
 
 *  Per endpoint task segment cache
40
 
 *  Per class task segment cache
41
 
 *
42
 
 *  We could use the RT heap for this probably or extend MMR3Heap (uses RTMemAlloc
43
 
 *  instead of managing larger blocks) to have this global for the whole VM.
44
 
 */
45
 
 
46
 
RT_C_DECLS_BEGIN
47
 
 
48
 
/**
49
 
 * A few forward declerations.
50
 
 */
51
 
typedef struct PDMASYNCCOMPLETIONENDPOINTFILE *PPDMASYNCCOMPLETIONENDPOINTFILE;
52
 
/** Pointer to a request segment. */
53
 
typedef struct PDMACTASKFILE *PPDMACTASKFILE;
54
 
/** Pointer to the endpoint class data. */
55
 
typedef struct PDMASYNCCOMPLETIONTASKFILE *PPDMASYNCCOMPLETIONTASKFILE;
56
 
/** Pointer to a cache LRU list. */
57
 
typedef struct PDMACFILELRULIST *PPDMACFILELRULIST;
58
 
/** Pointer to the global cache structure. */
59
 
typedef struct PDMACFILECACHEGLOBAL *PPDMACFILECACHEGLOBAL;
60
 
/** Pointer to a task segment. */
61
 
typedef struct PDMACFILETASKSEG *PPDMACFILETASKSEG;
62
 
 
63
 
/**
64
 
 * Blocking event types.
65
 
 */
66
 
typedef enum PDMACEPFILEAIOMGRBLOCKINGEVENT
67
 
{
68
 
    /** Invalid tye */
69
 
    PDMACEPFILEAIOMGRBLOCKINGEVENT_INVALID = 0,
70
 
    /** An endpoint is added to the manager. */
71
 
    PDMACEPFILEAIOMGRBLOCKINGEVENT_ADD_ENDPOINT,
72
 
    /** An endpoint is removed from the manager. */
73
 
    PDMACEPFILEAIOMGRBLOCKINGEVENT_REMOVE_ENDPOINT,
74
 
    /** An endpoint is about to be closed. */
75
 
    PDMACEPFILEAIOMGRBLOCKINGEVENT_CLOSE_ENDPOINT,
76
 
    /** The manager is requested to terminate */
77
 
    PDMACEPFILEAIOMGRBLOCKINGEVENT_SHUTDOWN,
78
 
    /** The manager is requested to suspend */
79
 
    PDMACEPFILEAIOMGRBLOCKINGEVENT_SUSPEND,
80
 
    /** The manager is requested to resume */
81
 
    PDMACEPFILEAIOMGRBLOCKINGEVENT_RESUME,
82
 
    /** 32bit hack */
83
 
    PDMACEPFILEAIOMGRBLOCKINGEVENT_32BIT_HACK = 0x7fffffff
84
 
} PDMACEPFILEAIOMGRBLOCKINGEVENT;
85
 
 
86
 
/**
87
 
 * I/O manager type.
88
 
 */
89
 
typedef enum PDMACEPFILEMGRTYPE
90
 
{
91
 
    /** Simple aka failsafe */
92
 
    PDMACEPFILEMGRTYPE_SIMPLE = 0,
93
 
    /** Async I/O with host cache enabled. */
94
 
    PDMACEPFILEMGRTYPE_ASYNC,
95
 
    /** 32bit hack */
96
 
    PDMACEPFILEMGRTYPE_32BIT_HACK = 0x7fffffff
97
 
} PDMACEPFILEMGRTYPE;
98
 
/** Pointer to a I/O manager type */
99
 
typedef PDMACEPFILEMGRTYPE *PPDMACEPFILEMGRTYPE;
100
 
 
101
 
/**
102
 
 * States of the I/O manager.
103
 
 */
104
 
typedef enum PDMACEPFILEMGRSTATE
105
 
{
106
 
    /** Invalid state. */
107
 
    PDMACEPFILEMGRSTATE_INVALID = 0,
108
 
    /** Normal running state accepting new requests
109
 
     * and processing them.
110
 
     */
111
 
    PDMACEPFILEMGRSTATE_RUNNING,
112
 
    /** Fault state - not accepting new tasks for endpoints but waiting for
113
 
     * remaining ones to finish.
114
 
     */
115
 
    PDMACEPFILEMGRSTATE_FAULT,
116
 
    /** Suspending state - not accepting new tasks for endpoints but waiting
117
 
     * for remaining ones to finish.
118
 
     */
119
 
    PDMACEPFILEMGRSTATE_SUSPENDING,
120
 
    /** Shutdown state - not accepting new tasks for endpoints but waiting
121
 
     * for remaining ones to finish.
122
 
     */
123
 
    PDMACEPFILEMGRSTATE_SHUTDOWN,
124
 
    /** The I/O manager waits for all active requests to complete and doesn't queue
125
 
     * new ones because it needs to grow to handle more requests.
126
 
     */
127
 
    PDMACEPFILEMGRSTATE_GROWING,
128
 
    /** 32bit hack */
129
 
    PDMACEPFILEMGRSTATE_32BIT_HACK = 0x7fffffff
130
 
} PDMACEPFILEMGRSTATE;
131
 
 
132
 
/**
133
 
 * State of a async I/O manager.
134
 
 */
135
 
typedef struct PDMACEPFILEMGR
136
 
{
137
 
    /** Next Aio manager in the list. */
138
 
    R3PTRTYPE(struct PDMACEPFILEMGR *)     pNext;
139
 
    /** Previous Aio manager in the list. */
140
 
    R3PTRTYPE(struct PDMACEPFILEMGR *)     pPrev;
141
 
    /** Manager type */
142
 
    PDMACEPFILEMGRTYPE                     enmMgrType;
143
 
    /** Current state of the manager. */
144
 
    PDMACEPFILEMGRSTATE                    enmState;
145
 
    /** Event semaphore the manager sleeps on when waiting for new requests. */
146
 
    RTSEMEVENT                             EventSem;
147
 
    /** Flag whether the thread waits in the event semaphore. */
148
 
    volatile bool                          fWaitingEventSem;
149
 
    /** Thread data */
150
 
    RTTHREAD                               Thread;
151
 
    /** The async I/O context for this manager. */
152
 
    RTFILEAIOCTX                           hAioCtx;
153
 
    /** Flag whether the I/O manager was woken up. */
154
 
    volatile bool                          fWokenUp;
155
 
    /** List of endpoints assigned to this manager. */
156
 
    R3PTRTYPE(PPDMASYNCCOMPLETIONENDPOINTFILE) pEndpointsHead;
157
 
    /** Number of endpoints assigned to the manager. */
158
 
    unsigned                               cEndpoints;
159
 
    /** Number of requests active currently. */
160
 
    unsigned                               cRequestsActive;
161
 
    /** Number of maximum requests active. */
162
 
    uint32_t                               cRequestsActiveMax;
163
 
    /** Pointer to an array of free async I/O request handles. */
164
 
    RTFILEAIOREQ                          *pahReqsFree;
165
 
    /** Index of the next free entry in the cache. */
166
 
    uint32_t                               iFreeEntry;
167
 
    /** Size of the array. */
168
 
    unsigned                               cReqEntries;
169
 
    /** Flag whether at least one endpoint reached its bandwidth limit. */
170
 
    bool                                   fBwLimitReached;
171
 
    /** Memory cache for file range locks. */
172
 
    RTMEMCACHE                             hMemCacheRangeLocks;
173
 
    /** Critical section protecting the blocking event handling. */
174
 
    RTCRITSECT                             CritSectBlockingEvent;
175
 
    /** Event sempahore for blocking external events.
176
 
     * The caller waits on it until the async I/O manager
177
 
     * finished processing the event. */
178
 
    RTSEMEVENT                             EventSemBlock;
179
 
    /** Flag whether a blocking event is pending and needs
180
 
     * processing by the I/O manager. */
181
 
    volatile bool                          fBlockingEventPending;
182
 
    /** Blocking event type */
183
 
    volatile PDMACEPFILEAIOMGRBLOCKINGEVENT enmBlockingEvent;
184
 
    /** Event type data */
185
 
    union
186
 
    {
187
 
        /** Add endpoint event. */
188
 
        struct
189
 
        {
190
 
            /** The endpoint to be added */
191
 
            volatile PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
192
 
        } AddEndpoint;
193
 
        /** Remove endpoint event. */
194
 
        struct
195
 
        {
196
 
            /** The endpoint to be removed */
197
 
            volatile PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
198
 
        } RemoveEndpoint;
199
 
        /** Close endpoint event. */
200
 
        struct
201
 
        {
202
 
            /** The endpoint to be closed */
203
 
            volatile PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
204
 
        } CloseEndpoint;
205
 
    } BlockingEventData;
206
 
} PDMACEPFILEMGR;
207
 
/** Pointer to a async I/O manager state. */
208
 
typedef PDMACEPFILEMGR *PPDMACEPFILEMGR;
209
 
/** Pointer to a async I/O manager state pointer. */
210
 
typedef PPDMACEPFILEMGR *PPPDMACEPFILEMGR;
211
 
 
212
 
/**
213
 
 * Bandwidth control manager instance data
214
 
 */
215
 
typedef struct PDMACFILEBWMGR
216
 
{
217
 
    /** Maximum number of bytes the VM is allowed to transfer (Max is 4GB/s) */
218
 
    uint32_t          cbVMTransferPerSecMax;
219
 
    /** Number of bytes we start with */
220
 
    uint32_t          cbVMTransferPerSecStart;
221
 
    /** Step after each update */
222
 
    uint32_t          cbVMTransferPerSecStep;
223
 
    /** Number of bytes we are allowed to transfer till the next update.
224
 
     * Resetted by the refresh timer. */
225
 
    volatile uint32_t cbVMTransferAllowed;
226
 
    /** Timestamp of the last update */
227
 
    volatile uint64_t tsUpdatedLast;
228
 
    /** Reference counter - How many endpoints are associated with this manager. */
229
 
    uint32_t          cRefs;
230
 
} PDMACFILEBWMGR;
231
 
/** Pointer to a bandwidth control manager */
232
 
typedef PDMACFILEBWMGR *PPDMACFILEBWMGR;
233
 
/** Pointer to a bandwidth control manager pointer */
234
 
typedef PPDMACFILEBWMGR *PPPDMACFILEBWMGR;
235
 
 
236
 
/**
237
 
 * A file access range lock.
238
 
 */
239
 
typedef struct PDMACFILERANGELOCK
240
 
{
241
 
    /** AVL node in the locked range tree of the endpoint. */
242
 
    AVLRFOFFNODECORE            Core;
243
 
    /** How many tasks have locked this range. */
244
 
    uint32_t                    cRefs;
245
 
    /** Flag whether this is a read or write lock. */
246
 
    bool                        fReadLock;
247
 
    /** List of tasks which are waiting that the range gets unlocked. */
248
 
    PPDMACTASKFILE              pWaitingTasksHead;
249
 
    /** List of tasks which are waiting that the range gets unlocked. */
250
 
    PPDMACTASKFILE              pWaitingTasksTail;
251
 
} PDMACFILERANGELOCK, *PPDMACFILERANGELOCK;
252
 
 
253
 
/**
254
 
 * Data for one request segment waiting for cache entry.
255
 
 */
256
 
typedef struct PDMACFILETASKSEG
257
 
{
258
 
    /** Next task segment in the list. */
259
 
    struct PDMACFILETASKSEG    *pNext;
260
 
    /** Task this segment is for. */
261
 
    PPDMASYNCCOMPLETIONTASKFILE pTask;
262
 
    /** Offset into the cache entry buffer to start reading from. */
263
 
    uint32_t                    uBufOffset;
264
 
    /** Number of bytes to transfer. */
265
 
    size_t                      cbTransfer;
266
 
    /** Pointer to the buffer. */
267
 
    void                       *pvBuf;
268
 
    /** Flag whether this entry writes data to the cache. */
269
 
    bool                        fWrite;
270
 
} PDMACFILETASKSEG;
271
 
 
272
 
/**
273
 
 * A cache entry
274
 
 */
275
 
typedef struct PDMACFILECACHEENTRY
276
 
{
277
 
    /** The AVL entry data. */
278
 
    AVLRFOFFNODECORE                Core;
279
 
    /** Pointer to the previous element. Used in one of the LRU lists.*/
280
 
    struct PDMACFILECACHEENTRY     *pPrev;
281
 
    /** Pointer to the next element. Used in one of the LRU lists.*/
282
 
    struct PDMACFILECACHEENTRY     *pNext;
283
 
    /** Pointer to the list the entry is in. */
284
 
    PPDMACFILELRULIST               pList;
285
 
    /** Pointer to the global cache structure. */
286
 
    PPDMACFILECACHEGLOBAL           pCache;
287
 
    /** Endpoint the entry belongs to. */
288
 
    PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
289
 
    /** Flags for this entry. Combinations of PDMACFILECACHE_* #defines */
290
 
    volatile uint32_t               fFlags;
291
 
    /** Reference counter. Prevents eviction of the entry if > 0. */
292
 
    volatile uint32_t               cRefs;
293
 
    /** Size of the entry. */
294
 
    size_t                          cbData;
295
 
    /** Pointer to the memory containing the data. */
296
 
    uint8_t                        *pbData;
297
 
    /** Head of list of tasks waiting for this one to finish. */
298
 
    PPDMACFILETASKSEG               pWaitingHead;
299
 
    /** Tail of list of tasks waiting for this one to finish. */
300
 
    PPDMACFILETASKSEG               pWaitingTail;
301
 
    /** Node for dirty but not yet committed entries list per endpoint. */
302
 
    RTLISTNODE                      NodeNotCommitted;
303
 
} PDMACFILECACHEENTRY, *PPDMACFILECACHEENTRY;
304
 
/** I/O is still in progress for this entry. This entry is not evictable. */
305
 
#define PDMACFILECACHE_ENTRY_IO_IN_PROGRESS RT_BIT(0)
306
 
/** Entry is locked and thus not evictable. */
307
 
#define PDMACFILECACHE_ENTRY_LOCKED         RT_BIT(1)
308
 
/** Entry is dirty */
309
 
#define PDMACFILECACHE_ENTRY_IS_DIRTY       RT_BIT(2)
310
 
/** Entry is not evictable. */
311
 
#define PDMACFILECACHE_NOT_EVICTABLE  (PDMACFILECACHE_ENTRY_LOCKED | PDMACFILECACHE_ENTRY_IO_IN_PROGRESS | PDMACFILECACHE_ENTRY_IS_DIRTY)
312
 
 
313
 
/**
314
 
 * LRU list data
315
 
 */
316
 
typedef struct PDMACFILELRULIST
317
 
{
318
 
    /** Head of the list. */
319
 
    PPDMACFILECACHEENTRY  pHead;
320
 
    /** Tail of the list. */
321
 
    PPDMACFILECACHEENTRY  pTail;
322
 
    /** Number of bytes cached in the list. */
323
 
    uint32_t              cbCached;
324
 
} PDMACFILELRULIST;
325
 
 
326
 
/**
327
 
 * Global cache data.
328
 
 */
329
 
typedef struct PDMACFILECACHEGLOBAL
330
 
{
331
 
    /** Maximum size of the cache in bytes. */
332
 
    uint32_t         cbMax;
333
 
    /** Current size of the cache in bytes. */
334
 
    uint32_t         cbCached;
335
 
    /** Critical section protecting the cache. */
336
 
    RTCRITSECT       CritSect;
337
 
    /** Maximum number of bytes cached. */
338
 
    uint32_t         cbRecentlyUsedInMax;
339
 
    /** Maximum number of bytes in the paged out list .*/
340
 
    uint32_t         cbRecentlyUsedOutMax;
341
 
    /** Recently used cache entries list */
342
 
    PDMACFILELRULIST LruRecentlyUsedIn;
343
 
    /** Scorecard cache entry list. */
344
 
    PDMACFILELRULIST LruRecentlyUsedOut;
345
 
    /** List of frequently used cache entries */
346
 
    PDMACFILELRULIST LruFrequentlyUsed;
347
 
    /** Commit timeout in milli seconds */
348
 
    uint32_t         u32CommitTimeoutMs;
349
 
    /** Number of dirty bytes needed to start a commit of the data to the disk. */
350
 
    uint32_t         cbCommitDirtyThreshold;
351
 
    /** Current number of dirty bytes in the cache. */
352
 
    volatile uint32_t cbDirty;
353
 
    /** Flag whether a commit is currently in progress. */
354
 
    volatile bool     fCommitInProgress;
355
 
    /** Commit interval timer */
356
 
    PTMTIMERR3        pTimerCommit;
357
 
    /** Number of endpoints using the cache. */
358
 
    uint32_t          cRefs;
359
 
    /** List of all endpoints using this cache. */
360
 
    RTLISTNODE        ListEndpoints;
361
 
#ifdef VBOX_WITH_STATISTICS
362
 
    /** Alignment */
363
 
    uint32_t         u32Alignment;
364
 
    /** Hit counter. */
365
 
    STAMCOUNTER      cHits;
366
 
    /** Partial hit counter. */
367
 
    STAMCOUNTER      cPartialHits;
368
 
    /** Miss counter. */
369
 
    STAMCOUNTER      cMisses;
370
 
    /** Bytes read from cache. */
371
 
    STAMCOUNTER      StatRead;
372
 
    /** Bytes written to the cache. */
373
 
    STAMCOUNTER      StatWritten;
374
 
    /** Time spend to get an entry in the AVL tree. */
375
 
    STAMPROFILEADV   StatTreeGet;
376
 
    /** Time spend to insert an entry in the AVL tree. */
377
 
    STAMPROFILEADV   StatTreeInsert;
378
 
    /** Time spend to remove an entry in the AVL tree. */
379
 
    STAMPROFILEADV   StatTreeRemove;
380
 
    /** Number of times a buffer could be reused. */
381
 
    STAMCOUNTER      StatBuffersReused;
382
 
#endif
383
 
} PDMACFILECACHEGLOBAL;
384
 
#ifdef VBOX_WITH_STATISTICS
385
 
AssertCompileMemberAlignment(PDMACFILECACHEGLOBAL, cHits, sizeof(uint64_t));
386
 
#endif
387
 
 
388
 
/**
389
 
 * Per endpoint cache data.
390
 
 */
391
 
typedef struct PDMACFILEENDPOINTCACHE
392
 
{
393
 
    /** AVL tree managing cache entries. */
394
 
    PAVLRFOFFTREE                        pTree;
395
 
    /** R/W semaphore protecting cached entries for this endpoint. */
396
 
    RTSEMRW                              SemRWEntries;
397
 
    /** Pointer to the gobal cache data */
398
 
    PPDMACFILECACHEGLOBAL                pCache;
399
 
    /** Lock protecting the dirty entries list. */
400
 
    RTSPINLOCK                           LockList;
401
 
    /** List of dirty but not committed entries for this endpoint. */
402
 
    RTLISTNODE                           ListDirtyNotCommitted;
403
 
    /** Node of the cache endpoint list. */
404
 
    RTLISTNODE                           NodeCacheEndpoint;
405
 
#ifdef VBOX_WITH_STATISTICS
406
 
    /** Number of times a write was deferred because the cache entry was still in progress */
407
 
    STAMCOUNTER                          StatWriteDeferred;
408
 
#endif
409
 
} PDMACFILEENDPOINTCACHE, *PPDMACFILEENDPOINTCACHE;
410
 
#ifdef VBOX_WITH_STATISTICS
411
 
AssertCompileMemberAlignment(PDMACFILEENDPOINTCACHE, StatWriteDeferred, sizeof(uint64_t));
412
 
#endif
413
 
 
414
 
/**
415
 
 * Backend type for the endpoint.
416
 
 */
417
 
typedef enum PDMACFILEEPBACKEND
418
 
{
419
 
    /** Non buffered. */
420
 
    PDMACFILEEPBACKEND_NON_BUFFERED = 0,
421
 
    /** Buffered (i.e host cache enabled) */
422
 
    PDMACFILEEPBACKEND_BUFFERED,
423
 
    /** 32bit hack */
424
 
    PDMACFILEEPBACKEND_32BIT_HACK = 0x7fffffff
425
 
} PDMACFILEEPBACKEND;
426
 
/** Pointer to a backend type. */
427
 
typedef PDMACFILEEPBACKEND *PPDMACFILEEPBACKEND;
428
 
 
429
 
/**
430
 
 * Global data for the file endpoint class.
431
 
 */
432
 
typedef struct PDMASYNCCOMPLETIONEPCLASSFILE
433
 
{
434
 
    /** Common data. */
435
 
    PDMASYNCCOMPLETIONEPCLASS           Core;
436
 
    /** Override I/O manager type - set to SIMPLE after failure. */
437
 
    PDMACEPFILEMGRTYPE                  enmMgrTypeOverride;
438
 
    /** Default backend type for the endpoint. */
439
 
    PDMACFILEEPBACKEND                  enmEpBackendDefault;
440
 
    /** Flag whether the file data cache is enabled. */
441
 
    bool                                fCacheEnabled;
442
 
    /** Critical section protecting the list of async I/O managers. */
443
 
    RTCRITSECT                          CritSect;
444
 
    /** Pointer to the head of the async I/O managers. */
445
 
    R3PTRTYPE(PPDMACEPFILEMGR)          pAioMgrHead;
446
 
    /** Number of async I/O managers currently running. */
447
 
    unsigned                            cAioMgrs;
448
 
    /** Maximum number of segments to cache per endpoint */
449
 
    unsigned                            cTasksCacheMax;
450
 
    /** Maximum number of simultaneous outstandingrequests. */
451
 
    uint32_t                            cReqsOutstandingMax;
452
 
    /** Bitmask for checking the alignment of a buffer. */
453
 
    RTR3UINTPTR                         uBitmaskAlignment;
454
 
#ifdef VBOX_WITH_STATISTICS
455
 
    uint32_t                            u32Alignment;
456
 
#endif
457
 
    /** Global cache data. */
458
 
    PDMACFILECACHEGLOBAL                Cache;
459
 
    /** Flag whether the out of resources warning was printed already. */
460
 
    bool                                fOutOfResourcesWarningPrinted;
461
 
    /** The global bandwidth control manager */
462
 
    PPDMACFILEBWMGR                     pBwMgr;
463
 
} PDMASYNCCOMPLETIONEPCLASSFILE;
464
 
/** Pointer to the endpoint class data. */
465
 
typedef PDMASYNCCOMPLETIONEPCLASSFILE *PPDMASYNCCOMPLETIONEPCLASSFILE;
466
 
#ifdef VBOX_WITH_STATISTICS
467
 
AssertCompileMemberAlignment(PDMASYNCCOMPLETIONEPCLASSFILE, Cache, sizeof(uint64_t));
468
 
#endif
469
 
 
470
 
typedef enum PDMACEPFILEBLOCKINGEVENT
471
 
{
472
 
    /** The invalid event type */
473
 
    PDMACEPFILEBLOCKINGEVENT_INVALID = 0,
474
 
    /** A task is about to be canceled */
475
 
    PDMACEPFILEBLOCKINGEVENT_CANCEL,
476
 
    /** Usual 32bit hack */
477
 
    PDMACEPFILEBLOCKINGEVENT_32BIT_HACK = 0x7fffffff
478
 
} PDMACEPFILEBLOCKINGEVENT;
479
 
 
480
 
/**
481
 
 * States of the endpoint.
482
 
 */
483
 
typedef enum PDMASYNCCOMPLETIONENDPOINTFILESTATE
484
 
{
485
 
    /** Invalid state. */
486
 
    PDMASYNCCOMPLETIONENDPOINTFILESTATE_INVALID = 0,
487
 
    /** Normal running state accepting new requests
488
 
     * and processing them.
489
 
     */
490
 
    PDMASYNCCOMPLETIONENDPOINTFILESTATE_ACTIVE,
491
 
    /** The endpoint is about to be closed - not accepting new tasks for endpoints but waiting for
492
 
     *  remaining ones to finish.
493
 
     */
494
 
    PDMASYNCCOMPLETIONENDPOINTFILESTATE_CLOSING,
495
 
    /** Removing from current I/O manager state - not processing new tasks for endpoints but waiting
496
 
     * for remaining ones to finish.
497
 
     */
498
 
    PDMASYNCCOMPLETIONENDPOINTFILESTATE_REMOVING,
499
 
    /** The current endpoint will be migrated to another I/O manager. */
500
 
    PDMASYNCCOMPLETIONENDPOINTFILESTATE_MIGRATING,
501
 
    /** 32bit hack */
502
 
    PDMASYNCCOMPLETIONENDPOINTFILESTATE_32BIT_HACK = 0x7fffffff
503
 
} PDMASYNCCOMPLETIONENDPOINTFILESTATE;
504
 
 
505
 
/**
506
 
 * Data for the file endpoint.
507
 
 */
508
 
typedef struct PDMASYNCCOMPLETIONENDPOINTFILE
509
 
{
510
 
    /** Common data. */
511
 
    PDMASYNCCOMPLETIONENDPOINT             Core;
512
 
    /** Current state of the endpoint. */
513
 
    PDMASYNCCOMPLETIONENDPOINTFILESTATE    enmState;
514
 
    /** The backend to use for this endpoint. */
515
 
    PDMACFILEEPBACKEND                     enmBackendType;
516
 
    /** async I/O manager this endpoint is assigned to. */
517
 
    R3PTRTYPE(volatile PPDMACEPFILEMGR)    pAioMgr;
518
 
    /** Flags for opening the file. */
519
 
    unsigned                               fFlags;
520
 
    /** File handle. */
521
 
    RTFILE                                 File;
522
 
    /** Size of the endpoint.
523
 
     * Updated while data is appended even if it is
524
 
     * only in the cache yet and not written to the file.
525
 
     */
526
 
    volatile uint64_t                      cbEndpoint;
527
 
    /**
528
 
     * Real size of the file. Only updated if
529
 
     * data is appended.
530
 
     */
531
 
    volatile uint64_t                      cbFile;
532
 
    /** List of new tasks. */
533
 
    R3PTRTYPE(volatile PPDMACTASKFILE)     pTasksNewHead;
534
 
 
535
 
    /** Head of the small cache for allocated task segments for exclusive
536
 
     * use by this endpoint. */
537
 
    R3PTRTYPE(volatile PPDMACTASKFILE)     pTasksFreeHead;
538
 
    /** Tail of the small cache for allocated task segments for exclusive
539
 
     * use by this endpoint. */
540
 
    R3PTRTYPE(volatile PPDMACTASKFILE)     pTasksFreeTail;
541
 
    /** Number of elements in the cache. */
542
 
    volatile uint32_t                      cTasksCached;
543
 
 
544
 
#ifdef VBOX_WITH_STATISTICS
545
 
    uint32_t                               u32Alignment;
546
 
#endif
547
 
    /** Cache of endpoint data. */
548
 
    PDMACFILEENDPOINTCACHE                 DataCache;
549
 
    /** Pointer to the associated bandwidth control manager */
550
 
    PPDMACFILEBWMGR                        pBwMgr;
551
 
 
552
 
    /** Flag whether a flush request is currently active */
553
 
    PPDMACTASKFILE                         pFlushReq;
554
 
 
555
 
#ifdef VBOX_WITH_STATISTICS
556
 
    /** Time spend in a read. */
557
 
    STAMPROFILEADV                         StatRead;
558
 
    /** Time spend in a write. */
559
 
    STAMPROFILEADV                         StatWrite;
560
 
#endif
561
 
 
562
 
    /** Event sempahore for blocking external events.
563
 
     * The caller waits on it until the async I/O manager
564
 
     * finished processing the event. */
565
 
    RTSEMEVENT                             EventSemBlock;
566
 
    /** Flag whether caching is enabled for this file. */
567
 
    bool                                   fCaching;
568
 
    /** Flag whether the file was opened readonly. */
569
 
    bool                                   fReadonly;
570
 
    /** Flag whether the host supports the async flush API. */
571
 
    bool                                   fAsyncFlushSupported;
572
 
    /** Flag whether a blocking event is pending and needs
573
 
     * processing by the I/O manager. */
574
 
    bool                                   fBlockingEventPending;
575
 
    /** Blocking event type */
576
 
    PDMACEPFILEBLOCKINGEVENT               enmBlockingEvent;
577
 
 
578
 
    /** Additional data needed for the event types. */
579
 
    union
580
 
    {
581
 
        /** Cancelation event. */
582
 
        struct
583
 
        {
584
 
            /** The task to cancel. */
585
 
            PPDMACTASKFILE                 pTask;
586
 
        } Cancel;
587
 
    } BlockingEventData;
588
 
    /** Data for exclusive use by the assigned async I/O manager. */
589
 
    struct
590
 
    {
591
 
        /** Pointer to the next endpoint assigned to the manager. */
592
 
        R3PTRTYPE(PPDMASYNCCOMPLETIONENDPOINTFILE) pEndpointNext;
593
 
        /** Pointer to the previous endpoint assigned to the manager. */
594
 
        R3PTRTYPE(PPDMASYNCCOMPLETIONENDPOINTFILE) pEndpointPrev;
595
 
        /** List of pending requests (not submitted due to usage restrictions
596
 
         *  or a pending flush request) */
597
 
        R3PTRTYPE(PPDMACTASKFILE)                  pReqsPendingHead;
598
 
        /** Tail of pending requests. */
599
 
        R3PTRTYPE(PPDMACTASKFILE)                  pReqsPendingTail;
600
 
        /** Tree of currently locked ranges.
601
 
         * If a write task is enqueued the range gets locked and any other
602
 
         * task writing to that range has to wait until the task completes.
603
 
         */
604
 
        PAVLRFOFFTREE                              pTreeRangesLocked;
605
 
        /** Number of requests currently being processed for this endpoint
606
 
         * (excluded flush requests). */
607
 
        unsigned                                   cRequestsActive;
608
 
        /** Number of requests processed during the last second. */
609
 
        unsigned                                   cReqsPerSec;
610
 
        /** Current number of processed requests for the current update period. */
611
 
        unsigned                                   cReqsProcessed;
612
 
        /** Flag whether the endpoint is about to be moved to another manager. */
613
 
        bool                                       fMoving;
614
 
        /** Destination I/O manager. */
615
 
        PPDMACEPFILEMGR                            pAioMgrDst;
616
 
    } AioMgr;
617
 
} PDMASYNCCOMPLETIONENDPOINTFILE;
618
 
/** Pointer to the endpoint class data. */
619
 
typedef PDMASYNCCOMPLETIONENDPOINTFILE *PPDMASYNCCOMPLETIONENDPOINTFILE;
620
 
#ifdef VBOX_WITH_STATISTICS
621
 
AssertCompileMemberAlignment(PDMASYNCCOMPLETIONENDPOINTFILE, StatRead, sizeof(uint64_t));
622
 
AssertCompileMemberAlignment(PDMASYNCCOMPLETIONENDPOINTFILE, DataCache, sizeof(uint64_t));
623
 
#endif
624
 
 
625
 
/** Request completion function */
626
 
typedef DECLCALLBACK(void)   FNPDMACTASKCOMPLETED(PPDMACTASKFILE pTask, void *pvUser, int rc);
627
 
/** Pointer to a request completion function. */
628
 
typedef FNPDMACTASKCOMPLETED *PFNPDMACTASKCOMPLETED;
629
 
 
630
 
/**
631
 
 * Transfer type.
632
 
 */
633
 
typedef enum PDMACTASKFILETRANSFER
634
 
{
635
 
    /** Invalid. */
636
 
    PDMACTASKFILETRANSFER_INVALID = 0,
637
 
    /** Read transfer. */
638
 
    PDMACTASKFILETRANSFER_READ,
639
 
    /** Write transfer. */
640
 
    PDMACTASKFILETRANSFER_WRITE,
641
 
    /** Flush transfer. */
642
 
    PDMACTASKFILETRANSFER_FLUSH
643
 
} PDMACTASKFILETRANSFER;
644
 
 
645
 
/**
646
 
 * Data of a request.
647
 
 */
648
 
typedef struct PDMACTASKFILE
649
 
{
650
 
    /** Pointer to the range lock we are waiting for */
651
 
    PPDMACFILERANGELOCK                  pRangeLock;
652
 
    /** Next task in the list. (Depending on the state) */
653
 
    struct PDMACTASKFILE                *pNext;
654
 
    /** Endpoint */
655
 
    PPDMASYNCCOMPLETIONENDPOINTFILE      pEndpoint;
656
 
    /** Transfer type. */
657
 
    PDMACTASKFILETRANSFER                enmTransferType;
658
 
    /** Start offset */
659
 
    RTFOFF                               Off;
660
 
    /** Data segment. */
661
 
    RTSGSEG                              DataSeg;
662
 
    /** When non-zero the segment uses a bounce buffer because the provided buffer
663
 
     * doesn't meet host requirements. */
664
 
    size_t                               cbBounceBuffer;
665
 
    /** Pointer to the used bounce buffer if any. */
666
 
    void                                *pvBounceBuffer;
667
 
    /** Start offset in the bounce buffer to copy from. */
668
 
    uint32_t                             offBounceBuffer;
669
 
    /** Flag whether this is a prefetch request. */
670
 
    bool                                 fPrefetch;
671
 
    /** Already prepared native I/O request.
672
 
     * Used if the request is prepared already but
673
 
     * was not queued because the host has not enough
674
 
     * resources. */
675
 
    RTFILEAIOREQ                         hReq;
676
 
    /** Completion function to call on completion. */
677
 
    PFNPDMACTASKCOMPLETED                pfnCompleted;
678
 
    /** User data */
679
 
    void                                *pvUser;
680
 
} PDMACTASKFILE;
681
 
 
682
 
/**
683
 
 * Per task data.
684
 
 */
685
 
typedef struct PDMASYNCCOMPLETIONTASKFILE
686
 
{
687
 
    /** Common data. */
688
 
    PDMASYNCCOMPLETIONTASK Core;
689
 
    /** Number of bytes to transfer until this task completes. */
690
 
    volatile int32_t      cbTransferLeft;
691
 
    /** Flag whether the task completed. */
692
 
    volatile bool         fCompleted;
693
 
    /** Return code. */
694
 
    volatile int          rc;
695
 
} PDMASYNCCOMPLETIONTASKFILE;
696
 
 
697
 
int pdmacFileAioMgrFailsafe(RTTHREAD ThreadSelf, void *pvUser);
698
 
int pdmacFileAioMgrNormal(RTTHREAD ThreadSelf, void *pvUser);
699
 
 
700
 
int pdmacFileAioMgrNormalInit(PPDMACEPFILEMGR pAioMgr);
701
 
void pdmacFileAioMgrNormalDestroy(PPDMACEPFILEMGR pAioMgr);
702
 
 
703
 
int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr, PDMACEPFILEMGRTYPE enmMgrType);
704
 
 
705
 
int pdmacFileAioMgrAddEndpoint(PPDMACEPFILEMGR pAioMgr, PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
706
 
 
707
 
PPDMACTASKFILE pdmacFileEpGetNewTasks(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
708
 
PPDMACTASKFILE pdmacFileTaskAlloc(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
709
 
void pdmacFileTaskFree(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
710
 
                       PPDMACTASKFILE pTask);
711
 
 
712
 
int pdmacFileEpAddTask(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMACTASKFILE pTask);
713
 
 
714
 
void pdmacFileEpTaskCompleted(PPDMACTASKFILE pTask, void *pvUser, int rc);
715
 
 
716
 
bool pdmacFileBwMgrIsTransferAllowed(PPDMACFILEBWMGR pBwMgr, uint32_t cbTransfer);
717
 
 
718
 
int pdmacFileCacheInit(PPDMASYNCCOMPLETIONEPCLASSFILE pClassFile, PCFGMNODE pCfgNode);
719
 
void pdmacFileCacheDestroy(PPDMASYNCCOMPLETIONEPCLASSFILE pClassFile);
720
 
int pdmacFileEpCacheInit(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONEPCLASSFILE pClassFile);
721
 
void pdmacFileEpCacheDestroy(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
722
 
 
723
 
int pdmacFileEpCacheRead(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONTASKFILE pTask,
724
 
                         RTFOFF off, PCRTSGSEG paSegments, size_t cSegments,
725
 
                         size_t cbRead);
726
 
int pdmacFileEpCacheWrite(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONTASKFILE pTask,
727
 
                          RTFOFF off, PCRTSGSEG paSegments, size_t cSegments,
728
 
                          size_t cbWrite);
729
 
int pdmacFileEpCacheFlush(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
730
 
 
731
 
RT_C_DECLS_END
732
 
 
733
 
#endif
734