VirtualBox

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

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

© 2023 Oracle
ContactPrivacy policyTerms of Use