VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/dvm/dvm.cpp@ 85126

最後變更 在這個檔案從85126是 85126,由 vboxsync 提交於 5 年 前

iprt/cdefs.h,*: Adding DECL_HIDDEN_CALLBACK to shorten the relatively common DECLHIDDEN(DECLCALLBACK()) combination and to help tweaking DECLHIDDEN to include nothrow. bugref:9794

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 22.4 KB
 
1/* $Id: dvm.cpp 85126 2020-07-08 23:04:57Z vboxsync $ */
2/** @file
3 * IPRT Disk Volume Management API (DVM) - generic code.
4 */
5
6/*
7 * Copyright (C) 2011-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/types.h>
32#include <iprt/assert.h>
33#include <iprt/mem.h>
34#include <iprt/dvm.h>
35#include <iprt/err.h>
36#include <iprt/asm.h>
37#include <iprt/string.h>
38#include <iprt/list.h>
39#include "internal/dvm.h"
40
41
42/*********************************************************************************************************************************
43* Structures and Typedefs *
44*********************************************************************************************************************************/
45
46/**
47 * The internal volume manager structure.
48 */
49typedef struct RTDVMINTERNAL
50{
51 /** The DVM magic (RTDVM_MAGIC). */
52 uint32_t u32Magic;
53 /** The disk descriptor. */
54 RTDVMDISK DvmDisk;
55 /** Pointer to the backend operations table after a successful probe. */
56 PCRTDVMFMTOPS pDvmFmtOps;
57 /** The format specific volume manager data. */
58 RTDVMFMT hVolMgrFmt;
59 /** Flags passed on manager creation. */
60 uint32_t fFlags;
61 /** Reference counter. */
62 uint32_t volatile cRefs;
63 /** List of recognised volumes (RTDVMVOLUMEINTERNAL). */
64 RTLISTANCHOR VolumeList;
65} RTDVMINTERNAL;
66/** Pointer to an internal volume manager. */
67typedef RTDVMINTERNAL *PRTDVMINTERNAL;
68
69/**
70 * The internal volume structure.
71 */
72typedef struct RTDVMVOLUMEINTERNAL
73{
74 /** The DVM volume magic (RTDVMVOLUME_MAGIC). */
75 uint32_t u32Magic;
76 /** Node for the volume list. */
77 RTLISTNODE VolumeNode;
78 /** Pointer to the owning volume manager. */
79 PRTDVMINTERNAL pVolMgr;
80 /** Format specific volume data. */
81 RTDVMVOLUMEFMT hVolFmt;
82 /** Set block status.callback */
83 PFNDVMVOLUMEQUERYBLOCKSTATUS pfnQueryBlockStatus;
84 /** Opaque user data. */
85 void *pvUser;
86 /** Reference counter. */
87 uint32_t volatile cRefs;
88} RTDVMVOLUMEINTERNAL;
89/** Pointer to an internal volume. */
90typedef RTDVMVOLUMEINTERNAL *PRTDVMVOLUMEINTERNAL;
91
92
93/*********************************************************************************************************************************
94* Global variables *
95*********************************************************************************************************************************/
96/**
97 * Supported volume formats.
98 */
99static PCRTDVMFMTOPS const g_aDvmFmts[] =
100{
101 &g_rtDvmFmtMbr,
102 &g_rtDvmFmtGpt,
103 &g_rtDvmFmtBsdLbl
104};
105
106/**
107 * Descriptions of the volume types.
108 *
109 * This is indexed by RTDVMVOLTYPE.
110 */
111static const char * const g_apszDvmVolTypes[] =
112{
113 "Invalid",
114 "Unknown",
115 "NTFS",
116 "FAT12",
117 "FAT16",
118 "FAT32",
119
120 "EFI system partition",
121
122 "Mac OS X HFS or HFS+",
123 "Mac OS X APFS",
124
125 "Linux swap",
126 "Linux native",
127 "Linux LVM",
128 "Linux SoftRaid",
129
130 "FreeBSD",
131 "NetBSD",
132 "OpenBSD",
133 "Solaris",
134
135 "Basic data partition",
136 "Microsoft reserved partition",
137 "Windows LDM metadata",
138 "Windows LDM data",
139 "Windows recovery partition",
140 "Windows storage spaces",
141
142 "IBM GPFS",
143};
144AssertCompile(RT_ELEMENTS(g_apszDvmVolTypes) == RTDVMVOLTYPE_END);
145
146
147/**
148 * Creates a new volume.
149 *
150 * @returns IPRT status code.
151 * @param pThis The DVM map instance.
152 * @param hVolFmt The format specific volume handle.
153 * @param phVol Where to store the generic volume handle on success.
154 */
155static int rtDvmVolumeCreate(PRTDVMINTERNAL pThis, RTDVMVOLUMEFMT hVolFmt, PRTDVMVOLUME phVol)
156{
157 PRTDVMVOLUMEINTERNAL pVol = (PRTDVMVOLUMEINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEINTERNAL));
158 if (pVol)
159 {
160 pVol->u32Magic = RTDVMVOLUME_MAGIC;
161 pVol->cRefs = 0;
162 pVol->pVolMgr = pThis;
163 pVol->hVolFmt = hVolFmt;
164
165 *phVol = pVol;
166 return VINF_SUCCESS;
167 }
168 return VERR_NO_MEMORY;
169}
170
171/**
172 * Destroys a volume handle.
173 *
174 * @param pThis The volume manager instance.
175 * @param pVol The volume to destroy.
176 */
177static void rtDvmVolumeDestroy(PRTDVMINTERNAL pThis, PRTDVMVOLUMEINTERNAL pVol)
178{
179 AssertPtr(pThis);
180 AssertPtr(pThis->pDvmFmtOps);
181 Assert(pVol->pVolMgr == pThis);
182
183 /* Close the volume. */
184 pThis->pDvmFmtOps->pfnVolumeClose(pVol->hVolFmt);
185
186 pVol->u32Magic = RTDVMVOLUME_MAGIC_DEAD;
187 pVol->pVolMgr = NULL;
188 pVol->hVolFmt = NIL_RTDVMVOLUMEFMT;
189 RTMemFree(pVol);
190}
191
192
193RTDECL(int) RTDvmCreate(PRTDVM phVolMgr, RTVFSFILE hVfsFile, uint32_t cbSector, uint32_t fFlags)
194{
195 AssertMsgReturn(!(fFlags & ~DVM_FLAGS_VALID_MASK), ("Invalid flags given %#x\n", fFlags), VERR_INVALID_FLAGS);
196 uint32_t cRefs = RTVfsFileRetain(hVfsFile);
197 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
198
199 uint64_t cbDisk;
200 int rc = RTVfsFileQuerySize(hVfsFile, &cbDisk);
201 if (RT_SUCCESS(rc))
202 {
203 PRTDVMINTERNAL pThis = (PRTDVMINTERNAL)RTMemAllocZ(sizeof(RTDVMINTERNAL));
204 if (pThis)
205 {
206 pThis->u32Magic = RTDVM_MAGIC;
207 pThis->DvmDisk.cbDisk = cbDisk;
208 pThis->DvmDisk.cbSector = cbSector;
209 pThis->DvmDisk.hVfsFile = hVfsFile;
210
211 pThis->pDvmFmtOps = NULL;
212 pThis->hVolMgrFmt = NIL_RTDVMFMT;
213 pThis->fFlags = fFlags;
214 pThis->cRefs = 1;
215 RTListInit(&pThis->VolumeList);
216
217 *phVolMgr = pThis;
218 return VINF_SUCCESS;
219 }
220 rc = VERR_NO_MEMORY;
221 }
222 RTVfsFileRelease(hVfsFile);
223 return rc;
224}
225
226
227RTDECL(uint32_t) RTDvmRetain(RTDVM hVolMgr)
228{
229 PRTDVMINTERNAL pThis = hVolMgr;
230 AssertPtrReturn(pThis, UINT32_MAX);
231 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
232
233 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
234 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
235 return cRefs;
236}
237
238/**
239 * Destroys a volume manager handle.
240 *
241 * @param pThis The volume manager to destroy.
242 */
243static void rtDvmDestroy(PRTDVMINTERNAL pThis)
244{
245 pThis->u32Magic = RTDVM_MAGIC_DEAD;
246
247 if (pThis->hVolMgrFmt != NIL_RTDVMFMT)
248 {
249 AssertPtr(pThis->pDvmFmtOps);
250
251 /* */
252 PRTDVMVOLUMEINTERNAL pItNext, pIt;
253 RTListForEachSafe(&pThis->VolumeList, pIt, pItNext, RTDVMVOLUMEINTERNAL, VolumeNode)
254 {
255 RTListNodeRemove(&pIt->VolumeNode);
256 rtDvmVolumeDestroy(pThis, pIt);
257 }
258
259 /* Let the backend do it's own cleanup first. */
260 pThis->pDvmFmtOps->pfnClose(pThis->hVolMgrFmt);
261 pThis->hVolMgrFmt = NIL_RTDVMFMT;
262 pThis->pDvmFmtOps = NULL;
263 }
264
265 pThis->DvmDisk.cbDisk = 0;
266 pThis->DvmDisk.cbSector = 0;
267 if (pThis->DvmDisk.hVfsFile != NIL_RTVFSFILE)
268 {
269 RTVfsFileRelease(pThis->DvmDisk.hVfsFile);
270 pThis->DvmDisk.hVfsFile = NIL_RTVFSFILE;
271 }
272
273 RTMemFree(pThis);
274}
275
276RTDECL(uint32_t) RTDvmRelease(RTDVM hVolMgr)
277{
278 PRTDVMINTERNAL pThis = hVolMgr;
279 if (pThis == NIL_RTDVM)
280 return 0;
281 AssertPtrReturn(pThis, UINT32_MAX);
282 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
283
284 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
285 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
286 if (cRefs == 0)
287 rtDvmDestroy(pThis);
288 return cRefs;
289}
290
291RTDECL(int) RTDvmMapOpen(RTDVM hVolMgr)
292{
293 PRTDVMINTERNAL pThis = hVolMgr;
294 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
295 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
296 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_WRONG_ORDER);
297
298 Assert(!pThis->pDvmFmtOps);
299
300 /*
301 * Let each format backend have a go at the disk, pick the one which scores the highest.
302 */
303 int rc = VINF_SUCCESS;
304 uint32_t uScoreMax = RTDVM_MATCH_SCORE_UNSUPPORTED;
305 PCRTDVMFMTOPS pDvmFmtOpsMatch = NULL;
306 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++)
307 {
308 uint32_t uScore = 0;
309 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i];
310
311 rc = pDvmFmtOps->pfnProbe(&pThis->DvmDisk, &uScore);
312 if (RT_SUCCESS(rc))
313 {
314 if (uScore > uScoreMax)
315 {
316 pDvmFmtOpsMatch = pDvmFmtOps;
317 uScoreMax = uScore;
318 }
319 }
320 else
321 return rc;
322 }
323 if (uScoreMax > RTDVM_MATCH_SCORE_UNSUPPORTED)
324 {
325 AssertPtr(pDvmFmtOpsMatch);
326
327 /*
328 * Open the format.
329 */
330 rc = pDvmFmtOpsMatch->pfnOpen(&pThis->DvmDisk, &pThis->hVolMgrFmt);
331 if (RT_SUCCESS(rc))
332 {
333 pThis->pDvmFmtOps = pDvmFmtOpsMatch;
334
335 /*
336 * Construct volume list (we're done if none).
337 */
338 uint32_t cVols = pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt);
339 if (cVols == 0)
340 return VINF_SUCCESS;
341
342 /* First volume. */
343 RTDVMVOLUMEFMT hVolFmt = NIL_RTDVMVOLUMEFMT;
344 rc = pThis->pDvmFmtOps->pfnQueryFirstVolume(pThis->hVolMgrFmt, &hVolFmt);
345 if (RT_SUCCESS(rc))
346 {
347 for (;;)
348 {
349 PRTDVMVOLUMEINTERNAL pVol = NULL;
350 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol);
351 if (RT_FAILURE(rc))
352 {
353 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt);
354 break;
355 }
356 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode);
357
358 /* Done?*/
359 cVols--;
360 if (cVols < 1)
361 return VINF_SUCCESS;
362
363 /* Next volume. */
364 rc = pThis->pDvmFmtOps->pfnQueryNextVolume(pThis->hVolMgrFmt, pVol->hVolFmt, &hVolFmt);
365 if (RT_FAILURE(rc))
366 break;
367 }
368
369 /* Bail out. */
370 PRTDVMVOLUMEINTERNAL pItNext, pIt;
371 RTListForEachSafe(&pThis->VolumeList, pIt, pItNext, RTDVMVOLUMEINTERNAL, VolumeNode)
372 {
373 RTListNodeRemove(&pIt->VolumeNode);
374 rtDvmVolumeDestroy(pThis, pIt);
375 }
376 }
377
378 pDvmFmtOpsMatch->pfnClose(pThis->hVolMgrFmt);
379 }
380 }
381 else
382 rc = VERR_NOT_SUPPORTED;
383 return rc;
384}
385
386RTDECL(int) RTDvmMapInitialize(RTDVM hVolMgr, const char *pszFmt)
387{
388 PRTDVMINTERNAL pThis = hVolMgr;
389 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
390 AssertPtrReturn(pszFmt, VERR_INVALID_POINTER);
391 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
392 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_WRONG_ORDER);
393
394 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++)
395 {
396 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i];
397 if (!RTStrCmp(pDvmFmtOps->pszFmt, pszFmt))
398 {
399 int rc = pDvmFmtOps->pfnInitialize(&pThis->DvmDisk, &pThis->hVolMgrFmt);
400 if (RT_SUCCESS(rc))
401 pThis->pDvmFmtOps = pDvmFmtOps;
402 return rc;
403 }
404 }
405 return VERR_NOT_SUPPORTED;
406}
407
408RTDECL(const char *) RTDvmMapGetFormatName(RTDVM hVolMgr)
409{
410 PRTDVMINTERNAL pThis = hVolMgr;
411 AssertPtrReturn(pThis, NULL);
412 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, NULL);
413 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, NULL);
414
415 return pThis->pDvmFmtOps->pszFmt;
416}
417
418RTDECL(RTDVMFORMATTYPE) RTDvmMapGetFormatType(RTDVM hVolMgr)
419{
420 PRTDVMINTERNAL pThis = hVolMgr;
421 AssertPtrReturn(pThis, RTDVMFORMATTYPE_INVALID);
422 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, RTDVMFORMATTYPE_INVALID);
423 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, RTDVMFORMATTYPE_INVALID);
424
425 return pThis->pDvmFmtOps->enmFormat;
426}
427
428RTDECL(uint32_t) RTDvmMapGetValidVolumes(RTDVM hVolMgr)
429{
430 PRTDVMINTERNAL pThis = hVolMgr;
431 AssertPtrReturn(pThis, UINT32_MAX);
432 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
433 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, UINT32_MAX);
434
435 return pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt);
436}
437
438RTDECL(uint32_t) RTDvmMapGetMaxVolumes(RTDVM hVolMgr)
439{
440 PRTDVMINTERNAL pThis = hVolMgr;
441 AssertPtrReturn(pThis, UINT32_MAX);
442 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
443 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, UINT32_MAX);
444
445 return pThis->pDvmFmtOps->pfnGetMaxVolumes(pThis->hVolMgrFmt);
446}
447
448RTDECL(int) RTDvmMapQueryFirstVolume(RTDVM hVolMgr, PRTDVMVOLUME phVol)
449{
450 PRTDVMINTERNAL pThis = hVolMgr;
451 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
452 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
453 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
454 AssertPtrReturn(phVol, VERR_INVALID_POINTER);
455
456 int rc = VERR_DVM_MAP_EMPTY;
457 PRTDVMVOLUMEINTERNAL pVol = RTListGetFirst(&pThis->VolumeList, RTDVMVOLUMEINTERNAL, VolumeNode);
458 if (pVol)
459 {
460 rc = VINF_SUCCESS;
461 RTDvmVolumeRetain(pVol);
462 *phVol = pVol;
463 }
464
465 return rc;
466}
467
468RTDECL(int) RTDvmMapQueryNextVolume(RTDVM hVolMgr, RTDVMVOLUME hVol, PRTDVMVOLUME phVolNext)
469{
470 PRTDVMINTERNAL pThis = hVolMgr;
471 PRTDVMVOLUMEINTERNAL pVol = hVol;
472 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
473 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
474 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
475 AssertPtrReturn(pVol, VERR_INVALID_HANDLE);
476 AssertReturn(pVol->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
477 AssertPtrReturn(phVolNext, VERR_INVALID_POINTER);
478
479 int rc = VERR_DVM_MAP_NO_VOLUME;
480 PRTDVMVOLUMEINTERNAL pVolNext = RTListGetNext(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode);
481 if (pVolNext)
482 {
483 rc = VINF_SUCCESS;
484 RTDvmVolumeRetain(pVolNext);
485 *phVolNext = pVolNext;
486 }
487
488 return rc;
489}
490
491RTDECL(int) RTDvmMapQueryBlockStatus(RTDVM hVolMgr, uint64_t off, uint64_t cb, bool *pfAllocated)
492{
493 PRTDVMINTERNAL pThis = hVolMgr;
494
495 /*
496 * Input validation.
497 */
498 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
499 AssertPtrReturn(pfAllocated, VERR_INVALID_POINTER);
500 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
501 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_WRONG_ORDER);
502 AssertMsgReturn( off <= pThis->DvmDisk.cbDisk
503 || cb <= pThis->DvmDisk.cbDisk
504 || off + cb <= pThis->DvmDisk.cbDisk,
505 ("off=%#RX64 cb=%#RX64 cbDisk=%#RX64\n", off, cb, pThis->DvmDisk.cbDisk),
506 VERR_OUT_OF_RANGE);
507
508 /*
509 * Check whether the range is inuse by the volume manager metadata first.
510 */
511 int rc = pThis->pDvmFmtOps->pfnQueryRangeUse(pThis->hVolMgrFmt, off, cb, pfAllocated);
512 if (RT_FAILURE(rc) || *pfAllocated)
513 return rc;
514
515 /*
516 * Not used by volume manager metadata, so work thru the specified range one
517 * volume / void (free space) at a time. All must be unallocated for us to
518 * reach the end, we return immediately if any portion is allocated.
519 */
520 while (cb > 0)
521 {
522 /*
523 * Search through all volumes.
524 *
525 * It is not possible to get all start sectors and sizes of all volumes
526 * here because volumes can be scattered around the disk for certain formats.
527 * Linux LVM is one example, it extents of logical volumes don't need to be
528 * contiguous on the medium.
529 */
530 bool fVolFound = false;
531 PRTDVMVOLUMEINTERNAL pVol;
532 RTListForEach(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode)
533 {
534 uint64_t cbIntersect;
535 uint64_t offVol;
536 bool fIntersect = pThis->pDvmFmtOps->pfnVolumeIsRangeIntersecting(pVol->hVolFmt, off, cb, &offVol, &cbIntersect);
537 if (fIntersect)
538 {
539 fVolFound = true;
540 if (pVol->pfnQueryBlockStatus)
541 {
542 bool fVolAllocated = true;
543 rc = pVol->pfnQueryBlockStatus(pVol->pvUser, offVol, cbIntersect, &fVolAllocated);
544 if (RT_FAILURE(rc) || fVolAllocated)
545 {
546 *pfAllocated = true;
547 return rc;
548 }
549 }
550 else if (!(pThis->fFlags & DVM_FLAGS_NO_STATUS_CALLBACK_MARK_AS_UNUSED))
551 {
552 *pfAllocated = true;
553 return VINF_SUCCESS;
554 }
555 /* else, flag is set, continue. */
556
557 cb -= cbIntersect;
558 off += cbIntersect;
559 break;
560 }
561 }
562
563 if (!fVolFound)
564 {
565 if (pThis->fFlags & DVM_FLAGS_UNUSED_SPACE_MARK_AS_USED)
566 {
567 *pfAllocated = true;
568 return VINF_SUCCESS;
569 }
570
571 cb -= pThis->DvmDisk.cbSector;
572 off += pThis->DvmDisk.cbSector;
573 }
574 }
575
576 *pfAllocated = false;
577 return rc;
578}
579
580RTDECL(uint32_t) RTDvmVolumeRetain(RTDVMVOLUME hVol)
581{
582 PRTDVMVOLUMEINTERNAL pThis = hVol;
583 AssertPtrReturn(pThis, UINT32_MAX);
584 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
585
586 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
587 AssertMsg(cRefs >= 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
588 if (cRefs == 1)
589 RTDvmRetain(pThis->pVolMgr);
590 return cRefs;
591}
592
593RTDECL(uint32_t) RTDvmVolumeRelease(RTDVMVOLUME hVol)
594{
595 PRTDVMVOLUMEINTERNAL pThis = hVol;
596 if (pThis == NIL_RTDVMVOLUME)
597 return 0;
598 AssertPtrReturn(pThis, UINT32_MAX);
599 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
600
601 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
602 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
603 if (cRefs == 0)
604 {
605 /* Release the volume manager. */
606 pThis->pfnQueryBlockStatus = NULL;
607 RTDvmRelease(pThis->pVolMgr);
608 }
609 return cRefs;
610}
611
612RTDECL(void) RTDvmVolumeSetQueryBlockStatusCallback(RTDVMVOLUME hVol,
613 PFNDVMVOLUMEQUERYBLOCKSTATUS pfnQueryBlockStatus,
614 void *pvUser)
615{
616 PRTDVMVOLUMEINTERNAL pThis = hVol;
617 AssertPtrReturnVoid(pThis);
618 AssertReturnVoid(pThis->u32Magic == RTDVMVOLUME_MAGIC);
619
620 pThis->pfnQueryBlockStatus = pfnQueryBlockStatus;
621 pThis->pvUser = pvUser;
622}
623
624RTDECL(uint64_t) RTDvmVolumeGetSize(RTDVMVOLUME hVol)
625{
626 PRTDVMVOLUMEINTERNAL pThis = hVol;
627 AssertPtrReturn(pThis, 0);
628 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, 0);
629
630 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetSize(pThis->hVolFmt);
631}
632
633RTDECL(int) RTDvmVolumeQueryName(RTDVMVOLUME hVol, char **ppszVolName)
634{
635 PRTDVMVOLUMEINTERNAL pThis = hVol;
636 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
637 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
638 AssertReturn(ppszVolName, VERR_INVALID_POINTER);
639
640 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryName(pThis->hVolFmt, ppszVolName);
641}
642
643RTDECL(RTDVMVOLTYPE) RTDvmVolumeGetType(RTDVMVOLUME hVol)
644{
645 PRTDVMVOLUMEINTERNAL pThis = hVol;
646 AssertPtrReturn(pThis, RTDVMVOLTYPE_INVALID);
647 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, RTDVMVOLTYPE_INVALID);
648
649 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetType(pThis->hVolFmt);
650}
651
652RTDECL(uint64_t) RTDvmVolumeGetFlags(RTDVMVOLUME hVol)
653{
654 PRTDVMVOLUMEINTERNAL pThis = hVol;
655 AssertPtrReturn(pThis, UINT64_MAX);
656 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT64_MAX);
657
658 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetFlags(pThis->hVolFmt);
659}
660
661RTDECL(int) RTDvmVolumeQueryRange(RTDVMVOLUME hVol, uint64_t *poffStart, uint64_t *poffLast)
662{
663 PRTDVMVOLUMEINTERNAL pThis = hVol;
664 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
665 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
666 AssertPtrReturn(poffStart, VERR_INVALID_POINTER);
667 AssertPtrReturn(poffLast, VERR_INVALID_POINTER);
668
669 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryRange(pThis->hVolFmt, poffStart, poffLast);
670}
671
672RTDECL(int) RTDvmVolumeRead(RTDVMVOLUME hVol, uint64_t off, void *pvBuf, size_t cbRead)
673{
674 PRTDVMVOLUMEINTERNAL pThis = hVol;
675 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
676 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
677 AssertReturn(pvBuf, VERR_INVALID_POINTER);
678 AssertReturn(cbRead > 0, VERR_INVALID_PARAMETER);
679
680 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeRead(pThis->hVolFmt, off, pvBuf, cbRead);
681}
682
683RTDECL(int) RTDvmVolumeWrite(RTDVMVOLUME hVol, uint64_t off, const void *pvBuf, size_t cbWrite)
684{
685 PRTDVMVOLUMEINTERNAL pThis = hVol;
686 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
687 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
688 AssertReturn(pvBuf, VERR_INVALID_POINTER);
689 AssertReturn(cbWrite > 0, VERR_INVALID_PARAMETER);
690
691 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeWrite(pThis->hVolFmt, off, pvBuf, cbWrite);
692}
693
694RTDECL(const char *) RTDvmVolumeTypeGetDescr(RTDVMVOLTYPE enmVolType)
695{
696 AssertReturn(enmVolType >= RTDVMVOLTYPE_INVALID && enmVolType < RTDVMVOLTYPE_END, NULL);
697
698 return g_apszDvmVolTypes[enmVolType];
699}
700
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette