summaryrefslogtreecommitdiffstats
path: root/src/VBox/Storage/VDInternal.h
blob: cf649f16947d92b0e2c81e0099afd8e71830ed7f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
/* $Id: VDInternal.h $ */
/** @file
 * VD - Virtual Disk container implementation, internal header file.
 */

/*
 * Copyright (C) 2017-2020 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 */

/*********************************************************************************************************************************
*   Header Files                                                                                                                 *
*********************************************************************************************************************************/

#ifndef VBOX_INCLUDED_SRC_Storage_VDInternal_h
#define VBOX_INCLUDED_SRC_Storage_VDInternal_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include <VBox/vd.h>
#include <VBox/vd-plugin.h>

#include <iprt/avl.h>
#include <iprt/list.h>
#include <iprt/memcache.h>

/** Disable dynamic backends on non x86 architectures. This feature
 * requires the SUPR3 library which is not available there.
 */
#if !defined(VBOX_HDD_NO_DYNAMIC_BACKENDS) && !defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64)
# define VBOX_HDD_NO_DYNAMIC_BACKENDS
#endif

/** Magic number contained in the VDISK instance data, used for checking that the passed
 * pointer contains a valid instance in debug builds. */
#define VDISK_SIGNATURE 0x6f0e2a7d

/**
 * Structure containing everything I/O related
 * for the image and cache descriptors.
 */
typedef struct VDIO
{
    /** I/O interface to the upper layer. */
    PVDINTERFACEIO      pInterfaceIo;

    /** Per image internal I/O interface. */
    VDINTERFACEIOINT    VDIfIoInt;

    /** Fallback I/O interface, only used if the caller doesn't provide it. */
    VDINTERFACEIO       VDIfIo;

    /** Opaque backend data. */
    void               *pBackendData;
    /** Disk this image is part of */
    PVDISK              pDisk;
    /** Flag whether to ignore flush requests. */
    bool                fIgnoreFlush;
} VDIO, *PVDIO;

/** Forward declaration of an I/O task */
typedef struct VDIOTASK *PVDIOTASK;

/**
 * Virtual disk container image descriptor.
 */
typedef struct VDIMAGE
{
    /** Link to parent image descriptor, if any. */
    struct VDIMAGE     *pPrev;
    /** Link to child image descriptor, if any. */
    struct VDIMAGE     *pNext;
    /** Cached image size. */
    uint64_t           cbImage;
    /** Container base filename. (UTF-8) */
    char               *pszFilename;
    /** Data managed by the backend which keeps the actual info. */
    void               *pBackendData;
    /** Cached sanitized image flags. */
    unsigned            uImageFlags;
    /** Image open flags (only those handled generically in this code and which
     * the backends will never ever see). */
    unsigned            uOpenFlags;

    /** Function pointers for the various backend methods. */
    PCVDIMAGEBACKEND    Backend;
    /** Pointer to list of VD interfaces, per-image. */
    PVDINTERFACE        pVDIfsImage;
    /** I/O related things. */
    VDIO                VDIo;
} VDIMAGE, *PVDIMAGE;

/** The special uninitialized size value for he image. */
#define VD_IMAGE_SIZE_UNINITIALIZED UINT64_C(0)

/**
 * Virtual disk cache image descriptor.
 */
typedef struct VDCACHE
{
    /** Cache base filename. (UTF-8) */
    char               *pszFilename;
    /** Data managed by the backend which keeps the actual info. */
    void               *pBackendData;
    /** Cached sanitized image flags. */
    unsigned            uImageFlags;
    /** Image open flags (only those handled generically in this code and which
     * the backends will never ever see). */
    unsigned            uOpenFlags;

    /** Function pointers for the various backend methods. */
    PCVDCACHEBACKEND    Backend;

    /** Pointer to list of VD interfaces, per-cache. */
    PVDINTERFACE        pVDIfsCache;
    /** I/O related things. */
    VDIO                VDIo;
} VDCACHE, *PVDCACHE;

/**
 * A block waiting for a discard.
 */
typedef struct VDDISCARDBLOCK
{
    /** AVL core. */
    AVLRU64NODECORE    Core;
    /** LRU list node. */
    RTLISTNODE         NodeLru;
    /** Number of bytes to discard. */
    size_t             cbDiscard;
    /** Bitmap of allocated sectors. */
    void              *pbmAllocated;
} VDDISCARDBLOCK, *PVDDISCARDBLOCK;

/**
 * VD discard state.
 */
typedef struct VDDISCARDSTATE
{
    /** Number of bytes waiting for a discard. */
    size_t              cbDiscarding;
    /** AVL tree with blocks waiting for a discard.
     * The uOffset + cbDiscard range is the search key. */
    PAVLRU64TREE        pTreeBlocks;
    /** LRU list of the least frequently discarded blocks.
     * If there are to many blocks waiting the least frequently used
     * will be removed and the range will be set to 0.
     */
    RTLISTNODE          ListLru;
} VDDISCARDSTATE, *PVDDISCARDSTATE;

/**
 * VD filter instance.
 */
typedef struct VDFILTER
{
    /** List node for the read filter chain. */
    RTLISTNODE         ListNodeChainRead;
    /** List node for the write filter chain. */
    RTLISTNODE         ListNodeChainWrite;
    /** Number of references to this filter. */
    uint32_t           cRefs;
    /** Opaque VD filter backend instance data. */
    void              *pvBackendData;
    /** Pointer to the filter backend interface. */
    PCVDFILTERBACKEND  pBackend;
    /** Pointer to list of VD interfaces, per-filter. */
    PVDINTERFACE        pVDIfsFilter;
    /** I/O related things. */
    VDIO                VDIo;
} VDFILTER;
/** Pointer to a VD filter instance. */
typedef VDFILTER *PVDFILTER;

/**
 * Virtual disk container main structure, private part.
 */
struct VDISK
{
    /** Structure signature (VDISK_SIGNATURE). */
    uint32_t               u32Signature;

    /** Image type. */
    VDTYPE                 enmType;

    /** Number of opened images. */
    unsigned               cImages;

    /** Base image. */
    PVDIMAGE               pBase;

    /** Last opened image in the chain.
     * The same as pBase if only one image is used. */
    PVDIMAGE               pLast;

    /** If a merge to one of the parents is running this may be non-NULL
     * to indicate to what image the writes should be additionally relayed. */
    PVDIMAGE               pImageRelay;

    /** Flags representing the modification state. */
    unsigned               uModified;

    /** Cached size of this disk. */
    uint64_t               cbSize;
    /** Cached PCHS geometry for this disk. */
    VDGEOMETRY             PCHSGeometry;
    /** Cached LCHS geometry for this disk. */
    VDGEOMETRY             LCHSGeometry;

    /** Pointer to list of VD interfaces, per-disk. */
    PVDINTERFACE           pVDIfsDisk;
    /** Pointer to the common interface structure for error reporting. */
    PVDINTERFACEERROR      pInterfaceError;
    /** Pointer to the optional thread synchronization callbacks. */
    PVDINTERFACETHREADSYNC pInterfaceThreadSync;

    /** Memory cache for I/O contexts */
    RTMEMCACHE             hMemCacheIoCtx;
    /** Memory cache for I/O tasks. */
    RTMEMCACHE             hMemCacheIoTask;
    /** An I/O context is currently using the disk structures
     * Every I/O context must be placed on one of the lists below. */
    volatile bool          fLocked;
    /** Head of pending I/O tasks waiting for completion - LIFO order. */
    volatile PVDIOTASK     pIoTasksPendingHead;
    /** Head of newly queued I/O contexts - LIFO order. */
    volatile PVDIOCTX      pIoCtxHead;
    /** Head of halted I/O contexts which are given back to generic
     * disk framework by the backend. - LIFO order. */
    volatile PVDIOCTX      pIoCtxHaltedHead;

    /** Head of blocked I/O contexts, processed only
     * after pIoCtxLockOwner was freed - LIFO order. */
    volatile PVDIOCTX      pIoCtxBlockedHead;
    /** I/O context which locked the disk for a growing write or flush request.
     * Other flush or growing write requests need to wait until
     * the current one completes. - NIL_VDIOCTX if unlocked. */
    volatile PVDIOCTX      pIoCtxLockOwner;
    /** If the disk was locked by a growing write, flush or discard request this
     * contains the start offset to check for interfering I/O while it is in progress. */
    uint64_t               uOffsetStartLocked;
    /** If the disk was locked by a growing write, flush or discard request this contains
     * the first non affected offset to check for interfering I/O while it is in progress. */
    uint64_t               uOffsetEndLocked;

    /** Pointer to the L2 disk cache if any. */
    PVDCACHE               pCache;
    /** Pointer to the discard state if any. */
    PVDDISCARDSTATE        pDiscard;

    /** Read filter chain - PVDFILTER. */
    RTLISTANCHOR           ListFilterChainRead;
    /** Write filter chain - PVDFILTER. */
    RTLISTANCHOR           ListFilterChainWrite;
};


DECLHIDDEN(int)      vdPluginInit(void);
DECLHIDDEN(int)      vdPluginTerm(void);
DECLHIDDEN(bool)     vdPluginIsInitialized(void);
DECLHIDDEN(int)      vdPluginUnloadFromPath(const char *pszPath);
DECLHIDDEN(int)      vdPluginUnloadFromFilename(const char *pszFilename);
DECLHIDDEN(int)      vdPluginLoadFromPath(const char *pszPath);
DECLHIDDEN(int)      vdPluginLoadFromFilename(const char *pszFilename);

DECLHIDDEN(uint32_t) vdGetImageBackendCount(void);
DECLHIDDEN(int)      vdQueryImageBackend(uint32_t idx, PCVDIMAGEBACKEND *ppBackend);
DECLHIDDEN(int)      vdFindImageBackend(const char *pszBackend, PCVDIMAGEBACKEND *ppBackend);
DECLHIDDEN(uint32_t) vdGetCacheBackendCount(void);
DECLHIDDEN(int)      vdQueryCacheBackend(uint32_t idx, PCVDCACHEBACKEND *ppBackend);
DECLHIDDEN(int)      vdFindCacheBackend(const char *pszBackend, PCVDCACHEBACKEND *ppBackend);
DECLHIDDEN(uint32_t) vdGetFilterBackendCount(void);
DECLHIDDEN(int)      vdQueryFilterBackend(uint32_t idx, PCVDFILTERBACKEND *ppBackend);
DECLHIDDEN(int)      vdFindFilterBackend(const char *pszFilter, PCVDFILTERBACKEND *ppBackend);

DECLHIDDEN(int)      vdIoIterQueryStartNext(VDIOITER hVdIoIter, uint64_t *pu64Start);
DECLHIDDEN(int)      vdIoIterQuerySegSizeByStart(VDIOITER hVdIoIter, uint64_t u64Start, size_t *pcRegSize);
DECLHIDDEN(int)      vdIoIterAdvance(VDIOITER hVdIoIter, uint64_t cBlocksOrBytes);

#endif /* !VBOX_INCLUDED_SRC_Storage_VDInternal_h */