VirtualBox

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

最後變更 在這個檔案從69716是 69618,由 vboxsync 提交於 7 年 前

dvm.h: Added RTDVMVOLTYPE_FAT12.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 21.5 KB
 
1/* $Id: dvm.cpp 69618 2017-11-08 15:45:35Z 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.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*********************************************************************************************************************************/
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 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
477 AssertPtrReturn(pfAllocated, VERR_INVALID_POINTER);
478 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
479 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_WRONG_ORDER);
480 AssertMsgReturn( off <= pThis->DvmDisk.cbDisk
481 || cb <= pThis->DvmDisk.cbDisk
482 || off + cb <= pThis->DvmDisk.cbDisk,
483 ("off=%#RX64 cb=%#RX64 cbDisk=%#RX64\n", off, cb, pThis->DvmDisk.cbDisk),
484 VERR_OUT_OF_RANGE);
485
486 /* Check whether the range is inuse by the volume manager metadata first. */
487 int rc = pThis->pDvmFmtOps->pfnQueryRangeUse(pThis->hVolMgrFmt, off, cb, pfAllocated);
488 if (RT_FAILURE(rc))
489 return rc;
490
491 if (!*pfAllocated)
492 {
493 bool fAllocated = false;
494
495 while ( cb > 0
496 && !fAllocated)
497 {
498 bool fVolFound = false;
499 uint64_t cbIntersect;
500 uint64_t offVol;
501
502 /*
503 * Search through all volumes. It is not possible to
504 * get all start sectors and sizes of all volumes here
505 * because volumes can be scattered around the disk for certain formats.
506 * Linux LVM is one example, extents of logical volumes don't need to be
507 * contigous on the medium.
508 */
509 PRTDVMVOLUMEINTERNAL pVol;
510 RTListForEach(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode)
511 {
512 bool fIntersect = pThis->pDvmFmtOps->pfnVolumeIsRangeIntersecting(pVol->hVolFmt, off,
513 cb, &offVol,
514 &cbIntersect);
515 if (fIntersect)
516 {
517 fVolFound = true;
518 if (pVol->pfnQueryBlockStatus)
519 {
520 bool fVolAllocated = true;
521 rc = pVol->pfnQueryBlockStatus(pVol->pvUser, offVol, cbIntersect, &fVolAllocated);
522 if (RT_FAILURE(rc))
523 break;
524 if (fVolAllocated)
525 {
526 fAllocated = true;
527 break;
528 }
529 }
530 else if (!(pThis->fFlags & DVM_FLAGS_NO_STATUS_CALLBACK_MARK_AS_UNUSED))
531 fAllocated = true;
532 /* else, flag is set, continue. */
533
534 cb -= cbIntersect;
535 off += cbIntersect;
536 break;
537 }
538 }
539
540 if (!fVolFound)
541 {
542 if (pThis->fFlags & DVM_FLAGS_UNUSED_SPACE_MARK_AS_USED)
543 fAllocated = true;
544
545 cb -= pThis->DvmDisk.cbSector;
546 off += pThis->DvmDisk.cbSector;
547 }
548 }
549
550 *pfAllocated = fAllocated;
551 }
552
553 return rc;
554}
555
556RTDECL(uint32_t) RTDvmVolumeRetain(RTDVMVOLUME hVol)
557{
558 PRTDVMVOLUMEINTERNAL pThis = hVol;
559 AssertPtrReturn(pThis, UINT32_MAX);
560 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
561
562 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
563 AssertMsg(cRefs >= 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
564 if (cRefs == 1)
565 RTDvmRetain(pThis->pVolMgr);
566 return cRefs;
567}
568
569RTDECL(uint32_t) RTDvmVolumeRelease(RTDVMVOLUME hVol)
570{
571 PRTDVMVOLUMEINTERNAL pThis = hVol;
572 if (pThis == NIL_RTDVMVOLUME)
573 return 0;
574 AssertPtrReturn(pThis, UINT32_MAX);
575 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
576
577 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
578 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
579 if (cRefs == 0)
580 {
581 /* Release the volume manager. */
582 pThis->pfnQueryBlockStatus = NULL;
583 RTDvmRelease(pThis->pVolMgr);
584 }
585 return cRefs;
586}
587
588RTDECL(void) RTDvmVolumeSetQueryBlockStatusCallback(RTDVMVOLUME hVol,
589 PFNDVMVOLUMEQUERYBLOCKSTATUS pfnQueryBlockStatus,
590 void *pvUser)
591{
592 PRTDVMVOLUMEINTERNAL pThis = hVol;
593 AssertPtrReturnVoid(pThis);
594 AssertReturnVoid(pThis->u32Magic == RTDVMVOLUME_MAGIC);
595
596 pThis->pfnQueryBlockStatus = pfnQueryBlockStatus;
597 pThis->pvUser = pvUser;
598}
599
600RTDECL(uint64_t) RTDvmVolumeGetSize(RTDVMVOLUME hVol)
601{
602 PRTDVMVOLUMEINTERNAL pThis = hVol;
603 AssertPtrReturn(pThis, 0);
604 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, 0);
605
606 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetSize(pThis->hVolFmt);
607}
608
609RTDECL(int) RTDvmVolumeQueryName(RTDVMVOLUME hVol, char **ppszVolName)
610{
611 PRTDVMVOLUMEINTERNAL pThis = hVol;
612 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
613 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
614 AssertReturn(ppszVolName, VERR_INVALID_POINTER);
615
616 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryName(pThis->hVolFmt, ppszVolName);
617}
618
619RTDECL(RTDVMVOLTYPE) RTDvmVolumeGetType(RTDVMVOLUME hVol)
620{
621 PRTDVMVOLUMEINTERNAL pThis = hVol;
622 AssertPtrReturn(pThis, RTDVMVOLTYPE_INVALID);
623 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, RTDVMVOLTYPE_INVALID);
624
625 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetType(pThis->hVolFmt);
626}
627
628RTDECL(uint64_t) RTDvmVolumeGetFlags(RTDVMVOLUME hVol)
629{
630 PRTDVMVOLUMEINTERNAL pThis = hVol;
631 AssertPtrReturn(pThis, UINT64_MAX);
632 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT64_MAX);
633
634 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetFlags(pThis->hVolFmt);
635}
636
637RTDECL(int) RTDvmVolumeRead(RTDVMVOLUME hVol, uint64_t off, void *pvBuf, size_t cbRead)
638{
639 PRTDVMVOLUMEINTERNAL pThis = hVol;
640 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
641 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
642 AssertReturn(pvBuf, VERR_INVALID_POINTER);
643 AssertReturn(cbRead > 0, VERR_INVALID_PARAMETER);
644
645 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeRead(pThis->hVolFmt, off, pvBuf, cbRead);
646}
647
648RTDECL(int) RTDvmVolumeWrite(RTDVMVOLUME hVol, uint64_t off, const void *pvBuf, size_t cbWrite)
649{
650 PRTDVMVOLUMEINTERNAL pThis = hVol;
651 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
652 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
653 AssertReturn(pvBuf, VERR_INVALID_POINTER);
654 AssertReturn(cbWrite > 0, VERR_INVALID_PARAMETER);
655
656 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeWrite(pThis->hVolFmt, off, pvBuf, cbWrite);
657}
658
659RTDECL(const char *) RTDvmVolumeTypeGetDescr(RTDVMVOLTYPE enmVolType)
660{
661 AssertReturn(enmVolType >= RTDVMVOLTYPE_INVALID && enmVolType < RTDVMVOLTYPE_END, NULL);
662
663 return g_apszDvmVolTypes[enmVolType];
664}
665
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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