VirtualBox

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

Last change on this file since 69886 was 69886, checked in by vboxsync, 7 years ago

dvm.cpp/RTDvmMapQueryBlockStatus: Cleanups, comments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.5 KB
Line 
1/* $Id: dvm.cpp 69886 2017-11-30 17:43:25Z vboxsync $ */
2/** @file
3 * IPRT Disk Volume Management API (DVM) - generic code.
4 */
5
6/*
7 * Copyright (C) 2011-2017 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 * 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*********************************************************************************************************************************/
96extern RTDVMFMTOPS g_rtDvmFmtMbr;
97extern RTDVMFMTOPS g_rtDvmFmtGpt;
98extern RTDVMFMTOPS g_rtDvmFmtBsdLbl;
99
100/**
101 * Supported volume formats.
102 */
103static PCRTDVMFMTOPS const g_aDvmFmts[] =
104{
105 &g_rtDvmFmtMbr,
106 &g_rtDvmFmtGpt,
107 &g_rtDvmFmtBsdLbl
108};
109
110/**
111 * Descriptions of the volume types.
112 *
113 * This is indexed by RTDVMVOLTYPE.
114 */
115static const char * const g_apszDvmVolTypes[] =
116{
117 "Invalid",
118 "Unknown",
119 "NTFS",
120 "FAT12",
121 "FAT16",
122 "FAT32",
123 "Linux swap",
124 "Linux native",
125 "Linux LVM",
126 "Linux SoftRaid",
127 "FreeBSD",
128 "NetBSD",
129 "OpenBSD",
130 "Mac OS X HFS or HFS+",
131 "Solaris"
132};
133AssertCompile(RT_ELEMENTS(g_apszDvmVolTypes) == RTDVMVOLTYPE_END);
134
135
136/**
137 * Creates a new volume.
138 *
139 * @returns IPRT status code.
140 * @param pThis The DVM map instance.
141 * @param hVolFmt The format specific volume handle.
142 * @param phVol Where to store the generic volume handle on success.
143 */
144static int rtDvmVolumeCreate(PRTDVMINTERNAL pThis, RTDVMVOLUMEFMT hVolFmt, PRTDVMVOLUME phVol)
145{
146 PRTDVMVOLUMEINTERNAL pVol = (PRTDVMVOLUMEINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEINTERNAL));
147 if (pVol)
148 {
149 pVol->u32Magic = RTDVMVOLUME_MAGIC;
150 pVol->cRefs = 0;
151 pVol->pVolMgr = pThis;
152 pVol->hVolFmt = hVolFmt;
153
154 *phVol = pVol;
155 return VINF_SUCCESS;
156 }
157 return VERR_NO_MEMORY;
158}
159
160/**
161 * Destroys a volume handle.
162 *
163 * @param pThis The volume to destroy.
164 */
165static void rtDvmVolumeDestroy(PRTDVMVOLUMEINTERNAL pThis)
166{
167 PRTDVMINTERNAL pVolMgr = pThis->pVolMgr;
168
169 AssertPtr(pVolMgr);
170
171 /* Close the volume. */
172 pVolMgr->pDvmFmtOps->pfnVolumeClose(pThis->hVolFmt);
173
174 pThis->u32Magic = RTDVMVOLUME_MAGIC_DEAD;
175 pThis->pVolMgr = NULL;
176 pThis->hVolFmt = NIL_RTDVMVOLUMEFMT;
177 RTMemFree(pThis);
178
179 /* Release the reference of the volume manager. */
180 RTDvmRelease(pVolMgr);
181}
182
183
184RTDECL(int) RTDvmCreate(PRTDVM phVolMgr, RTVFSFILE hVfsFile, uint32_t cbSector, uint32_t fFlags)
185{
186 AssertMsgReturn(!(fFlags & ~DVM_FLAGS_VALID_MASK), ("Invalid flags given %#x\n", fFlags), VERR_INVALID_FLAGS);
187 uint32_t cRefs = RTVfsFileRetain(hVfsFile);
188 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
189
190 uint64_t cbDisk;
191 int rc = RTVfsFileGetSize(hVfsFile, &cbDisk);
192 if (RT_SUCCESS(rc))
193 {
194 PRTDVMINTERNAL pThis = (PRTDVMINTERNAL)RTMemAllocZ(sizeof(RTDVMINTERNAL));
195 if (pThis)
196 {
197 pThis->u32Magic = RTDVM_MAGIC;
198 pThis->DvmDisk.cbDisk = cbDisk;
199 pThis->DvmDisk.cbSector = cbSector;
200 pThis->DvmDisk.hVfsFile = hVfsFile;
201
202 pThis->pDvmFmtOps = NULL;
203 pThis->hVolMgrFmt = NIL_RTDVMFMT;
204 pThis->fFlags = fFlags;
205 pThis->cRefs = 1;
206 RTListInit(&pThis->VolumeList);
207
208 *phVolMgr = pThis;
209 return VINF_SUCCESS;
210 }
211 rc = VERR_NO_MEMORY;
212 }
213 RTVfsFileRelease(hVfsFile);
214 return rc;
215}
216
217
218RTDECL(uint32_t) RTDvmRetain(RTDVM hVolMgr)
219{
220 PRTDVMINTERNAL pThis = hVolMgr;
221 AssertPtrReturn(pThis, UINT32_MAX);
222 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
223
224 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
225 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
226 return cRefs;
227}
228
229/**
230 * Destroys a volume manager handle.
231 *
232 * @param pThis The volume manager to destroy.
233 */
234static void rtDvmDestroy(PRTDVMINTERNAL pThis)
235{
236 pThis->u32Magic = RTDVM_MAGIC_DEAD;
237
238 if (pThis->hVolMgrFmt != NIL_RTDVMFMT)
239 {
240 AssertPtr(pThis->pDvmFmtOps);
241
242 /* Let the backend do it's own cleanup first. */
243 pThis->pDvmFmtOps->pfnClose(pThis->hVolMgrFmt);
244 pThis->hVolMgrFmt = NIL_RTDVMFMT;
245 pThis->pDvmFmtOps = NULL;
246 }
247
248 pThis->DvmDisk.cbDisk = 0;
249 pThis->DvmDisk.cbSector = 0;
250 if (pThis->DvmDisk.hVfsFile != NIL_RTVFSFILE)
251 {
252 RTVfsFileRelease(pThis->DvmDisk.hVfsFile);
253 pThis->DvmDisk.hVfsFile = NIL_RTVFSFILE;
254 }
255 RTMemFree(pThis);
256}
257
258RTDECL(uint32_t) RTDvmRelease(RTDVM hVolMgr)
259{
260 PRTDVMINTERNAL pThis = hVolMgr;
261 if (pThis == NIL_RTDVM)
262 return 0;
263 AssertPtrReturn(pThis, UINT32_MAX);
264 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
265
266 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
267 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
268 if (cRefs == 0)
269 rtDvmDestroy(pThis);
270 return cRefs;
271}
272
273RTDECL(int) RTDvmMapOpen(RTDVM hVolMgr)
274{
275 PRTDVMINTERNAL pThis = hVolMgr;
276 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
277 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
278 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_WRONG_ORDER);
279
280 Assert(!pThis->pDvmFmtOps);
281
282 /*
283 * Let each format backend have a go at the disk, pick the one which scores the highest.
284 */
285 int rc = VINF_SUCCESS;
286 uint32_t uScoreMax = RTDVM_MATCH_SCORE_UNSUPPORTED;
287 PCRTDVMFMTOPS pDvmFmtOpsMatch = NULL;
288 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++)
289 {
290 uint32_t uScore = 0;
291 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i];
292
293 rc = pDvmFmtOps->pfnProbe(&pThis->DvmDisk, &uScore);
294 if (RT_SUCCESS(rc))
295 {
296 if (uScore > uScoreMax)
297 {
298 pDvmFmtOpsMatch = pDvmFmtOps;
299 uScoreMax = uScore;
300 }
301 }
302 else
303 return rc;
304 }
305 if (uScoreMax > RTDVM_MATCH_SCORE_UNSUPPORTED)
306 {
307 AssertPtr(pDvmFmtOpsMatch);
308
309 /*
310 * Open the format.
311 */
312 rc = pDvmFmtOpsMatch->pfnOpen(&pThis->DvmDisk, &pThis->hVolMgrFmt);
313 if (RT_SUCCESS(rc))
314 {
315 pThis->pDvmFmtOps = pDvmFmtOpsMatch;
316
317 /*
318 * Construct volume list (we're done if none).
319 */
320 uint32_t cVols = pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt);
321 if (cVols == 0)
322 return VINF_SUCCESS;
323
324 /* First volume. */
325 RTDVMVOLUMEFMT hVolFmt = NIL_RTDVMVOLUMEFMT;
326 rc = pThis->pDvmFmtOps->pfnQueryFirstVolume(pThis->hVolMgrFmt, &hVolFmt);
327 if (RT_SUCCESS(rc))
328 {
329 for (;;)
330 {
331 PRTDVMVOLUMEINTERNAL pVol = NULL;
332 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol);
333 if (RT_FAILURE(rc))
334 {
335 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt);
336 break;
337 }
338 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode);
339
340 /* Done?*/
341 cVols--;
342 if (cVols < 1)
343 return VINF_SUCCESS;
344
345 /* Next volume. */
346 rc = pThis->pDvmFmtOps->pfnQueryNextVolume(pThis->hVolMgrFmt, pVol->hVolFmt, &hVolFmt);
347 if (RT_FAILURE(rc))
348 break;
349 }
350
351 /* Bail out. */
352 PRTDVMVOLUMEINTERNAL pItNext, pIt;
353 RTListForEachSafe(&pThis->VolumeList, pIt, pItNext, RTDVMVOLUMEINTERNAL, VolumeNode)
354 {
355 RTListNodeRemove(&pIt->VolumeNode);
356 rtDvmVolumeDestroy(pIt);
357 }
358 }
359
360 /** @todo shouldn't we close the format too here? */
361 }
362 }
363 else
364 rc = VERR_NOT_SUPPORTED;
365 return rc;
366}
367
368RTDECL(int) RTDvmMapInitialize(RTDVM hVolMgr, const char *pszFmt)
369{
370 PRTDVMINTERNAL pThis = hVolMgr;
371 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
372 AssertPtrReturn(pszFmt, VERR_INVALID_POINTER);
373 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
374 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_WRONG_ORDER);
375
376 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++)
377 {
378 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i];
379 if (!RTStrCmp(pDvmFmtOps->pszFmt, pszFmt))
380 {
381 int rc = pDvmFmtOps->pfnInitialize(&pThis->DvmDisk, &pThis->hVolMgrFmt);
382 if (RT_SUCCESS(rc))
383 pThis->pDvmFmtOps = pDvmFmtOps;
384 return rc;
385 }
386 }
387 return VERR_NOT_SUPPORTED;
388}
389
390RTDECL(const char *) RTDvmMapGetFormatName(RTDVM hVolMgr)
391{
392 PRTDVMINTERNAL pThis = hVolMgr;
393 AssertPtrReturn(pThis, NULL);
394 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, NULL);
395 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, NULL);
396
397 return pThis->pDvmFmtOps->pszFmt;
398}
399
400RTDECL(RTDVMFORMATTYPE) RTDvmMapGetFormatType(RTDVM hVolMgr)
401{
402 PRTDVMINTERNAL pThis = hVolMgr;
403 AssertPtrReturn(pThis, RTDVMFORMATTYPE_INVALID);
404 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, RTDVMFORMATTYPE_INVALID);
405 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, RTDVMFORMATTYPE_INVALID);
406
407 return pThis->pDvmFmtOps->enmFormat;
408}
409
410RTDECL(uint32_t) RTDvmMapGetValidVolumes(RTDVM hVolMgr)
411{
412 PRTDVMINTERNAL pThis = hVolMgr;
413 AssertPtrReturn(pThis, UINT32_MAX);
414 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
415 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, UINT32_MAX);
416
417 return pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt);
418}
419
420RTDECL(uint32_t) RTDvmMapGetMaxVolumes(RTDVM hVolMgr)
421{
422 PRTDVMINTERNAL pThis = hVolMgr;
423 AssertPtrReturn(pThis, UINT32_MAX);
424 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
425 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, UINT32_MAX);
426
427 return pThis->pDvmFmtOps->pfnGetMaxVolumes(pThis->hVolMgrFmt);
428}
429
430RTDECL(int) RTDvmMapQueryFirstVolume(RTDVM hVolMgr, PRTDVMVOLUME phVol)
431{
432 PRTDVMINTERNAL pThis = hVolMgr;
433 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
434 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
435 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
436 AssertPtrReturn(phVol, VERR_INVALID_POINTER);
437
438 int rc = VERR_DVM_MAP_EMPTY;
439 PRTDVMVOLUMEINTERNAL pVol = RTListGetFirst(&pThis->VolumeList, RTDVMVOLUMEINTERNAL, VolumeNode);
440 if (pVol)
441 {
442 rc = VINF_SUCCESS;
443 RTDvmVolumeRetain(pVol);
444 *phVol = pVol;
445 }
446
447 return rc;
448}
449
450RTDECL(int) RTDvmMapQueryNextVolume(RTDVM hVolMgr, RTDVMVOLUME hVol, PRTDVMVOLUME phVolNext)
451{
452 PRTDVMINTERNAL pThis = hVolMgr;
453 PRTDVMVOLUMEINTERNAL pVol = hVol;
454 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
455 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
456 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
457 AssertPtrReturn(pVol, VERR_INVALID_HANDLE);
458 AssertReturn(pVol->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
459 AssertPtrReturn(phVolNext, VERR_INVALID_POINTER);
460
461 int rc = VERR_DVM_MAP_NO_VOLUME;
462 PRTDVMVOLUMEINTERNAL pVolNext = RTListGetNext(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode);
463 if (pVolNext)
464 {
465 rc = VINF_SUCCESS;
466 RTDvmVolumeRetain(pVolNext);
467 *phVolNext = pVolNext;
468 }
469
470 return rc;
471}
472
473RTDECL(int) RTDvmMapQueryBlockStatus(RTDVM hVolMgr, uint64_t off, uint64_t cb, bool *pfAllocated)
474{
475 PRTDVMINTERNAL pThis = hVolMgr;
476
477 /*
478 * Input validation.
479 */
480 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
481 AssertPtrReturn(pfAllocated, VERR_INVALID_POINTER);
482 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
483 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_WRONG_ORDER);
484 AssertMsgReturn( off <= pThis->DvmDisk.cbDisk
485 || cb <= pThis->DvmDisk.cbDisk
486 || off + cb <= pThis->DvmDisk.cbDisk,
487 ("off=%#RX64 cb=%#RX64 cbDisk=%#RX64\n", off, cb, pThis->DvmDisk.cbDisk),
488 VERR_OUT_OF_RANGE);
489
490 /*
491 * Check whether the range is inuse by the volume manager metadata first.
492 */
493 int rc = pThis->pDvmFmtOps->pfnQueryRangeUse(pThis->hVolMgrFmt, off, cb, pfAllocated);
494 if (RT_FAILURE(rc) || *pfAllocated)
495 return rc;
496
497 /*
498 * Not used by volume manager metadata, so work thru the specified range one
499 * volume / void (free space) at a time. All must be unallocated for us to
500 * reach the end, we return immediately if any portion is allocated.
501 */
502 while (cb > 0)
503 {
504 /*
505 * Search through all volumes.
506 *
507 * It is not possible to get all start sectors and sizes of all volumes
508 * here because volumes can be scattered around the disk for certain formats.
509 * Linux LVM is one example, it extents of logical volumes don't need to be
510 * contiguous on the medium.
511 */
512 bool fVolFound = false;
513 PRTDVMVOLUMEINTERNAL pVol;
514 RTListForEach(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode)
515 {
516 uint64_t cbIntersect;
517 uint64_t offVol;
518 bool fIntersect = pThis->pDvmFmtOps->pfnVolumeIsRangeIntersecting(pVol->hVolFmt, off, cb, &offVol, &cbIntersect);
519 if (fIntersect)
520 {
521 fVolFound = true;
522 if (pVol->pfnQueryBlockStatus)
523 {
524 bool fVolAllocated = true;
525 rc = pVol->pfnQueryBlockStatus(pVol->pvUser, offVol, cbIntersect, &fVolAllocated);
526 if (RT_FAILURE(rc) || fVolAllocated)
527 {
528 *pfAllocated = true;
529 return rc;
530 }
531 }
532 else if (!(pThis->fFlags & DVM_FLAGS_NO_STATUS_CALLBACK_MARK_AS_UNUSED))
533 {
534 *pfAllocated = true;
535 return VINF_SUCCESS;
536 }
537 /* else, flag is set, continue. */
538
539 cb -= cbIntersect;
540 off += cbIntersect;
541 break;
542 }
543 }
544
545 if (!fVolFound)
546 {
547 if (pThis->fFlags & DVM_FLAGS_UNUSED_SPACE_MARK_AS_USED)
548 {
549 *pfAllocated = true;
550 return VINF_SUCCESS;
551 }
552
553 cb -= pThis->DvmDisk.cbSector;
554 off += pThis->DvmDisk.cbSector;
555 }
556 }
557
558 *pfAllocated = false;
559 return rc;
560}
561
562RTDECL(uint32_t) RTDvmVolumeRetain(RTDVMVOLUME hVol)
563{
564 PRTDVMVOLUMEINTERNAL pThis = hVol;
565 AssertPtrReturn(pThis, UINT32_MAX);
566 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
567
568 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
569 AssertMsg(cRefs >= 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
570 if (cRefs == 1)
571 RTDvmRetain(pThis->pVolMgr);
572 return cRefs;
573}
574
575RTDECL(uint32_t) RTDvmVolumeRelease(RTDVMVOLUME hVol)
576{
577 PRTDVMVOLUMEINTERNAL pThis = hVol;
578 if (pThis == NIL_RTDVMVOLUME)
579 return 0;
580 AssertPtrReturn(pThis, UINT32_MAX);
581 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
582
583 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
584 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
585 if (cRefs == 0)
586 {
587 /* Release the volume manager. */
588 pThis->pfnQueryBlockStatus = NULL;
589 RTDvmRelease(pThis->pVolMgr);
590 }
591 return cRefs;
592}
593
594RTDECL(void) RTDvmVolumeSetQueryBlockStatusCallback(RTDVMVOLUME hVol,
595 PFNDVMVOLUMEQUERYBLOCKSTATUS pfnQueryBlockStatus,
596 void *pvUser)
597{
598 PRTDVMVOLUMEINTERNAL pThis = hVol;
599 AssertPtrReturnVoid(pThis);
600 AssertReturnVoid(pThis->u32Magic == RTDVMVOLUME_MAGIC);
601
602 pThis->pfnQueryBlockStatus = pfnQueryBlockStatus;
603 pThis->pvUser = pvUser;
604}
605
606RTDECL(uint64_t) RTDvmVolumeGetSize(RTDVMVOLUME hVol)
607{
608 PRTDVMVOLUMEINTERNAL pThis = hVol;
609 AssertPtrReturn(pThis, 0);
610 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, 0);
611
612 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetSize(pThis->hVolFmt);
613}
614
615RTDECL(int) RTDvmVolumeQueryName(RTDVMVOLUME hVol, char **ppszVolName)
616{
617 PRTDVMVOLUMEINTERNAL pThis = hVol;
618 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
619 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
620 AssertReturn(ppszVolName, VERR_INVALID_POINTER);
621
622 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryName(pThis->hVolFmt, ppszVolName);
623}
624
625RTDECL(RTDVMVOLTYPE) RTDvmVolumeGetType(RTDVMVOLUME hVol)
626{
627 PRTDVMVOLUMEINTERNAL pThis = hVol;
628 AssertPtrReturn(pThis, RTDVMVOLTYPE_INVALID);
629 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, RTDVMVOLTYPE_INVALID);
630
631 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetType(pThis->hVolFmt);
632}
633
634RTDECL(uint64_t) RTDvmVolumeGetFlags(RTDVMVOLUME hVol)
635{
636 PRTDVMVOLUMEINTERNAL pThis = hVol;
637 AssertPtrReturn(pThis, UINT64_MAX);
638 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT64_MAX);
639
640 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetFlags(pThis->hVolFmt);
641}
642
643RTDECL(int) RTDvmVolumeRead(RTDVMVOLUME hVol, uint64_t off, void *pvBuf, size_t cbRead)
644{
645 PRTDVMVOLUMEINTERNAL pThis = hVol;
646 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
647 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
648 AssertReturn(pvBuf, VERR_INVALID_POINTER);
649 AssertReturn(cbRead > 0, VERR_INVALID_PARAMETER);
650
651 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeRead(pThis->hVolFmt, off, pvBuf, cbRead);
652}
653
654RTDECL(int) RTDvmVolumeWrite(RTDVMVOLUME hVol, uint64_t off, const void *pvBuf, size_t cbWrite)
655{
656 PRTDVMVOLUMEINTERNAL pThis = hVol;
657 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
658 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
659 AssertReturn(pvBuf, VERR_INVALID_POINTER);
660 AssertReturn(cbWrite > 0, VERR_INVALID_PARAMETER);
661
662 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeWrite(pThis->hVolFmt, off, pvBuf, cbWrite);
663}
664
665RTDECL(const char *) RTDvmVolumeTypeGetDescr(RTDVMVOLTYPE enmVolType)
666{
667 AssertReturn(enmVolType >= RTDVMVOLTYPE_INVALID && enmVolType < RTDVMVOLTYPE_END, NULL);
668
669 return g_apszDvmVolTypes[enmVolType];
670}
671
Note: See TracBrowser for help on using the repository browser.

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