VirtualBox

source: vbox/trunk/src/VBox/VMM/include/PDMBlkCacheInternal.h@ 87815

Last change on this file since 87815 was 87766, checked in by vboxsync, 4 years ago

VMM/TM,VMM/*: Refactored the TM timer APIs to use 'handles' and take a pVM parameter. Only internal callbacks have been updated with a hTimer parameter, so far. bugref:9943

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.7 KB
Line 
1/* $Id: PDMBlkCacheInternal.h 87766 2021-02-16 14:27:43Z vboxsync $ */
2/** @file
3 * PDM Block Cache.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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 VMM_INCLUDED_SRC_include_PDMBlkCacheInternal_h
19#define VMM_INCLUDED_SRC_include_PDMBlkCacheInternal_h
20#ifndef RT_WITHOUT_PRAGMA_ONCE
21# pragma once
22#endif
23
24#include <VBox/vmm/cfgm.h>
25#include <VBox/vmm/stam.h>
26#include <VBox/vmm/tm.h>
27#include <VBox/vmm/pdmblkcache.h>
28#include <iprt/types.h>
29#include <iprt/file.h>
30#include <iprt/thread.h>
31#include <iprt/semaphore.h>
32#include <iprt/critsect.h>
33#include <iprt/avl.h>
34#include <iprt/list.h>
35#include <iprt/spinlock.h>
36#include <iprt/memcache.h>
37
38RT_C_DECLS_BEGIN
39
40/**
41 * A few forward declarations.
42 */
43/** Pointer to a cache LRU list. */
44typedef struct PDMBLKLRULIST *PPDMBLKLRULIST;
45/** Pointer to the global cache structure. */
46typedef struct PDMBLKCACHEGLOBAL *PPDMBLKCACHEGLOBAL;
47/** Pointer to a cache entry waiter structure. */
48typedef struct PDMBLKCACHEWAITER *PPDMBLKCACHEWAITER;
49
50/**
51 * A cache entry
52 */
53typedef struct PDMBLKCACHEENTRY
54{
55 /** The AVL entry data. */
56 AVLRU64NODECORE Core;
57 /** Pointer to the previous element. Used in one of the LRU lists.*/
58 struct PDMBLKCACHEENTRY *pPrev;
59 /** Pointer to the next element. Used in one of the LRU lists.*/
60 struct PDMBLKCACHEENTRY *pNext;
61 /** Pointer to the list the entry is in. */
62 PPDMBLKLRULIST pList;
63 /** Cache the entry belongs to. */
64 PPDMBLKCACHE pBlkCache;
65 /** Flags for this entry. Combinations of PDMACFILECACHE_* \#defines */
66 volatile uint32_t fFlags;
67 /** Reference counter. Prevents eviction of the entry if > 0. */
68 volatile uint32_t cRefs;
69 /** Size of the entry. */
70 uint32_t cbData;
71 /** Pointer to the memory containing the data. */
72 uint8_t *pbData;
73 /** Head of list of tasks waiting for this one to finish. */
74 PPDMBLKCACHEWAITER pWaitingHead;
75 /** Tail of list of tasks waiting for this one to finish. */
76 PPDMBLKCACHEWAITER pWaitingTail;
77 /** Node for dirty but not yet committed entries list per endpoint. */
78 RTLISTNODE NodeNotCommitted;
79} PDMBLKCACHEENTRY, *PPDMBLKCACHEENTRY;
80/** I/O is still in progress for this entry. This entry is not evictable. */
81#define PDMBLKCACHE_ENTRY_IO_IN_PROGRESS RT_BIT(0)
82/** Entry is locked and thus not evictable. */
83#define PDMBLKCACHE_ENTRY_LOCKED RT_BIT(1)
84/** Entry is dirty */
85#define PDMBLKCACHE_ENTRY_IS_DIRTY RT_BIT(2)
86/** Entry is not evictable. */
87#define PDMBLKCACHE_NOT_EVICTABLE (PDMBLKCACHE_ENTRY_LOCKED | PDMBLKCACHE_ENTRY_IO_IN_PROGRESS | PDMBLKCACHE_ENTRY_IS_DIRTY)
88
89/**
90 * LRU list data
91 */
92typedef struct PDMBLKLRULIST
93{
94 /** Head of the list. */
95 PPDMBLKCACHEENTRY pHead;
96 /** Tail of the list. */
97 PPDMBLKCACHEENTRY pTail;
98 /** Number of bytes cached in the list. */
99 uint32_t cbCached;
100} PDMBLKLRULIST;
101
102/**
103 * Global cache data.
104 */
105typedef struct PDMBLKCACHEGLOBAL
106{
107 /** Pointer to the owning VM instance. */
108 PVM pVM;
109 /** Maximum size of the cache in bytes. */
110 uint32_t cbMax;
111 /** Current size of the cache in bytes. */
112 uint32_t cbCached;
113 /** Critical section protecting the cache. */
114 RTCRITSECT CritSect;
115 /** Maximum number of bytes cached. */
116 uint32_t cbRecentlyUsedInMax;
117 /** Maximum number of bytes in the paged out list .*/
118 uint32_t cbRecentlyUsedOutMax;
119 /** Recently used cache entries list */
120 PDMBLKLRULIST LruRecentlyUsedIn;
121 /** Scorecard cache entry list. */
122 PDMBLKLRULIST LruRecentlyUsedOut;
123 /** List of frequently used cache entries */
124 PDMBLKLRULIST LruFrequentlyUsed;
125 /** Commit timeout in milli seconds */
126 uint32_t u32CommitTimeoutMs;
127 /** Number of dirty bytes needed to start a commit of the data to the disk. */
128 uint32_t cbCommitDirtyThreshold;
129 /** Current number of dirty bytes in the cache. */
130 volatile uint32_t cbDirty;
131 /** Flag whether the VM was suspended becaus of an I/O error. */
132 volatile bool fIoErrorVmSuspended;
133 /** Flag whether a commit is currently in progress. */
134 volatile bool fCommitInProgress;
135 /** Commit interval timer */
136 TMTIMERHANDLE hTimerCommit;
137 /** Number of endpoints using the cache. */
138 uint32_t cRefs;
139 /** List of all users of this cache. */
140 RTLISTANCHOR ListUsers;
141#ifdef VBOX_WITH_STATISTICS
142 /** Hit counter. */
143 STAMCOUNTER cHits;
144 /** Partial hit counter. */
145 STAMCOUNTER cPartialHits;
146 /** Miss counter. */
147 STAMCOUNTER cMisses;
148 /** Bytes read from cache. */
149 STAMCOUNTER StatRead;
150 /** Bytes written to the cache. */
151 STAMCOUNTER StatWritten;
152 /** Time spend to get an entry in the AVL tree. */
153 STAMPROFILEADV StatTreeGet;
154 /** Time spend to insert an entry in the AVL tree. */
155 STAMPROFILEADV StatTreeInsert;
156 /** Time spend to remove an entry in the AVL tree. */
157 STAMPROFILEADV StatTreeRemove;
158 /** Number of times a buffer could be reused. */
159 STAMCOUNTER StatBuffersReused;
160#endif
161} PDMBLKCACHEGLOBAL;
162#ifdef VBOX_WITH_STATISTICS
163AssertCompileMemberAlignment(PDMBLKCACHEGLOBAL, cHits, sizeof(uint64_t));
164#endif
165
166/**
167 * Block cache type.
168 */
169typedef enum PDMBLKCACHETYPE
170{
171 /** Device . */
172 PDMBLKCACHETYPE_DEV = 1,
173 /** Driver consumer. */
174 PDMBLKCACHETYPE_DRV,
175 /** Internal consumer. */
176 PDMBLKCACHETYPE_INTERNAL,
177 /** Usb consumer. */
178 PDMBLKCACHETYPE_USB
179} PDMBLKCACHETYPE;
180
181/**
182 * Per user cache data.
183 */
184typedef struct PDMBLKCACHE
185{
186 /** Pointer to the id for the cache. */
187 char *pszId;
188 /** AVL tree managing cache entries. */
189 PAVLRU64TREE pTree;
190 /** R/W semaphore protecting cached entries for this endpoint. */
191 RTSEMRW SemRWEntries;
192 /** Pointer to the gobal cache data */
193 PPDMBLKCACHEGLOBAL pCache;
194 /** Lock protecting the dirty entries list. */
195 RTSPINLOCK LockList;
196 /** List of dirty but not committed entries for this endpoint. */
197 RTLISTANCHOR ListDirtyNotCommitted;
198 /** Node of the cache user list. */
199 RTLISTNODE NodeCacheUser;
200 /** Block cache type. */
201 PDMBLKCACHETYPE enmType;
202 /** Type specific data. */
203 union
204 {
205 /** PDMASYNCCOMPLETIONTEMPLATETYPE_DEV */
206 struct
207 {
208 /** Pointer to the device instance owning the block cache. */
209 R3PTRTYPE(PPDMDEVINS) pDevIns;
210 /** Complete callback to the user. */
211 R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEDEV) pfnXferComplete;
212 /** I/O enqueue callback. */
213 R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDEV) pfnXferEnqueue;
214 /** Discard enqueue callback. */
215 R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDISCARDDEV) pfnXferEnqueueDiscard;
216 } Dev;
217 /** PDMASYNCCOMPLETIONTEMPLATETYPE_DRV */
218 struct
219 {
220 /** Pointer to the driver instance owning the block cache. */
221 R3PTRTYPE(PPDMDRVINS) pDrvIns;
222 /** Complete callback to the user. */
223 R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEDRV) pfnXferComplete;
224 /** I/O enqueue callback. */
225 R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDRV) pfnXferEnqueue;
226 /** Discard enqueue callback. */
227 R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV) pfnXferEnqueueDiscard;
228 } Drv;
229 /** PDMASYNCCOMPLETIONTEMPLATETYPE_INTERNAL */
230 struct
231 {
232 /** Pointer to user data. */
233 R3PTRTYPE(void *) pvUser;
234 /** Complete callback to the user. */
235 R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEINT) pfnXferComplete;
236 /** I/O enqueue callback. */
237 R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEINT) pfnXferEnqueue;
238 /** Discard enqueue callback. */
239 R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDISCARDINT) pfnXferEnqueueDiscard;
240 } Int;
241 /** PDMASYNCCOMPLETIONTEMPLATETYPE_USB */
242 struct
243 {
244 /** Pointer to the usb instance owning the template. */
245 R3PTRTYPE(PPDMUSBINS) pUsbIns;
246 /** Complete callback to the user. */
247 R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEUSB) pfnXferComplete;
248 /** I/O enqueue callback. */
249 R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEUSB) pfnXferEnqueue;
250 /** Discard enqueue callback. */
251 R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDISCARDUSB) pfnXferEnqueueDiscard;
252 } Usb;
253 } u;
254
255#ifdef VBOX_WITH_STATISTICS
256
257#if HC_ARCH_BITS == 64
258 uint32_t u32Alignment;
259#endif
260 /** Number of times a write was deferred because the cache entry was still in progress */
261 STAMCOUNTER StatWriteDeferred;
262 /** Number appended cache entries. */
263 STAMCOUNTER StatAppendedWrites;
264#endif
265
266 /** Flag whether the cache was suspended. */
267 volatile bool fSuspended;
268 /** Number of outstanding I/O transfers. */
269 volatile uint32_t cIoXfersActive;
270
271} PDMBLKCACHE, *PPDMBLKCACHE;
272#ifdef VBOX_WITH_STATISTICS
273AssertCompileMemberAlignment(PDMBLKCACHE, StatWriteDeferred, sizeof(uint64_t));
274#endif
275
276/**
277 * I/O task.
278 */
279typedef struct PDMBLKCACHEREQ
280{
281 /** Opaque user data returned on completion. */
282 void *pvUser;
283 /** Number of pending transfers (waiting for a cache entry and passed through). */
284 volatile uint32_t cXfersPending;
285 /** Status code. */
286 volatile int rcReq;
287} PDMBLKCACHEREQ, *PPDMBLKCACHEREQ;
288
289/**
290 * I/O transfer from the cache to the underlying medium.
291 */
292typedef struct PDMBLKCACHEIOXFER
293{
294 /** Flag whether the I/O xfer updates a cache entry or updates the request directly. */
295 bool fIoCache;
296 /** Type dependent data. */
297 union
298 {
299 /** Pointer to the entry the transfer updates. */
300 PPDMBLKCACHEENTRY pEntry;
301 /** Pointer to the request the transfer updates. */
302 PPDMBLKCACHEREQ pReq;
303 };
304 /** Transfer direction. */
305 PDMBLKCACHEXFERDIR enmXferDir;
306 /** Segment used if a cache entry is updated. */
307 RTSGSEG SgSeg;
308 /** S/G buffer. */
309 RTSGBUF SgBuf;
310} PDMBLKCACHEIOXFER;
311
312/**
313 * Cache waiter
314 */
315typedef struct PDMBLKCACHEWAITER
316{
317 /* Next waiter in the list. */
318 struct PDMBLKCACHEWAITER *pNext;
319 /** S/G buffer holding or receiving data. */
320 RTSGBUF SgBuf;
321 /** Offset into the cache entry to start the transfer. */
322 uint32_t offCacheEntry;
323 /** How many bytes to transfer. */
324 size_t cbTransfer;
325 /** Flag whether the task wants to read or write into the entry. */
326 bool fWrite;
327 /** Task the waiter is for. */
328 PPDMBLKCACHEREQ pReq;
329} PDMBLKCACHEWAITER;
330
331RT_C_DECLS_END
332
333#endif /* !VMM_INCLUDED_SRC_include_PDMBlkCacheInternal_h */
334
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