dvm.cpp revision f5f42fa2ec9924006cad8e5adc646b34b35ba3c3
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * IPRT Disk Volume Management API (DVM) - generic code.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Copyright (C) 2011 Oracle Corporation
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * available from http://www.virtualbox.org. This file is free software;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * you can redistribute it and/or modify it under the terms of the GNU
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * General Public License (GPL) as published by the Free Software
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * The contents of this file may alternatively be used under the terms
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * of the Common Development and Distribution License Version 1.0
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * VirtualBox OSE distribution, in which case the provisions of the
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * CDDL are applicable instead of those of the GPL.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * You may elect to license modified versions of this file under the
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * terms and conditions of either the GPL or the CDDL or both.
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync/*******************************************************************************
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync* Header Files *
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync*******************************************************************************/
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/*******************************************************************************
956a0e3c076406b83d635174a201fd8761ee5133vboxsync* Structures and Typedefs *
956a0e3c076406b83d635174a201fd8761ee5133vboxsync*******************************************************************************/
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * The internal volume manager structure.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** The DVM magic (RTDVM_MAGIC). */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** The disk descriptor. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** Pointer to the backend operations table after a successful probe. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** The format specific volume manager data. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** Reference counter. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/** Pointer to an internal volume manager. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * The internal volume structure.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** The DVM volume magic (RTDVMVOLUME_MAGIC). */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** Pointer to the owning volume manager. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** Format specific volume data. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** Reference counter. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/** Pointer to an internal volume. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/*******************************************************************************
956a0e3c076406b83d635174a201fd8761ee5133vboxsync* Global variables *
956a0e3c076406b83d635174a201fd8761ee5133vboxsync*******************************************************************************/
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Supported volume formats.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Descriptions of the volume types.
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync * This is indexed by RTDVMVOLTYPE.
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic const char * g_apcszDvmVolTypes[] =
956a0e3c076406b83d635174a201fd8761ee5133vboxsync "Linux swap",
956a0e3c076406b83d635174a201fd8761ee5133vboxsync "Linux native",
956a0e3c076406b83d635174a201fd8761ee5133vboxsync "Linux LVM",
956a0e3c076406b83d635174a201fd8761ee5133vboxsync "Linux SoftRaid",
956a0e3c076406b83d635174a201fd8761ee5133vboxsync "Mac OS X HFS or HFS+",
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(int) RTDvmCreate(PRTDVM phVolMgr, PFNDVMREAD pfnRead,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync pThis = (PRTDVMINTERNAL)RTMemAllocZ(sizeof(RTDVMINTERNAL));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Destroys a volume manager handle.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param pThis The volume manager to destroy.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Let the backend do it's own cleanup first. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync uint32_t uScoreMax = RTDVM_MATCH_SCORE_UNSUPPORTED;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_INVALID_HANDLE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync rc = pDvmFmtOps->pfnProbe(&pThis->DvmDisk, &uScore);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Open the format. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync rc = pDvmFmtOpsMatch->pfnOpen(&pThis->DvmDisk, &pThis->hVolMgrFmt);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(int) RTDvmMapInitialize(RTDVM hVolMgr, const char *pszFmt)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_INVALID_HANDLE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync rc = pDvmFmtOps->pfnInitialize(&pThis->DvmDisk, &pThis->hVolMgrFmt);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(const char *) RTDvmMapGetFormat(RTDVM hVolMgr)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVM_MAGIC, NULL);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, NULL);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(uint32_t) RTDvmMapGetValidVolumes(RTDVM hVolMgr)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, UINT32_MAX);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(uint32_t) RTDvmMapGetMaxVolumes(RTDVM hVolMgr)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, UINT32_MAX);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return pThis->pDvmFmtOps->pfnGetMaxVolumes(pThis->hVolMgrFmt);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic int rtDvmVolumeCreate(PRTDVMINTERNAL pThis, RTDVMVOLUMEFMT hVolFmt,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync pVol = (PRTDVMVOLUMEINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEINTERNAL));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Reference the volume manager. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(int) RTDvmMapQueryFirstVolume(RTDVM hVolMgr, PRTDVMVOLUME phVol)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync rc = pThis->pDvmFmtOps->pfnQueryFirstVolume(pThis->hVolMgrFmt, &hVolFmt);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(int) RTDvmMapQueryNextVolume(RTDVM hVolMgr, RTDVMVOLUME hVol, PRTDVMVOLUME phVolNext)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pVol->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync rc = pThis->pDvmFmtOps->pfnQueryNextVolume(pThis->hVolMgrFmt, pVol->hVolFmt, &hVolFmtNext);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync rc = rtDvmVolumeCreate(pThis, hVolFmtNext, phVolNext);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(uint32_t) RTDvmVolumeRetain(RTDVMVOLUME hVol)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Destroys a volume handle.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param pThis The volume to destroy.
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic void rtDvmVolumeDestroy(PRTDVMVOLUMEINTERNAL pThis)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Close the volume. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync pVolMgr->pDvmFmtOps->pfnVolumeClose(pThis->hVolFmt);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Release the reference of the volume manager. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(uint32_t) RTDvmVolumeRelease(RTDVMVOLUME hVol)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(uint64_t) RTDvmVolumeGetSize(RTDVMVOLUME hVol)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, 0);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetSize(pThis->hVolFmt);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(int) RTDvmVolumeQueryName(RTDVMVOLUME hVol, char **ppszVolName)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryName(pThis->hVolFmt, ppszVolName);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(RTDVMVOLTYPE) RTDvmVolumeGetType(RTDVMVOLUME hVol)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, RTDVMVOLTYPE_INVALID);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetType(pThis->hVolFmt);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(uint64_t) RTDvmVolumeGetFlags(RTDVMVOLUME hVol)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT64_MAX);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetFlags(pThis->hVolFmt);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(int) RTDvmVolumeRead(RTDVMVOLUME hVol, uint64_t off, void *pvBuf, size_t cbRead)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return pThis->pVolMgr->pDvmFmtOps->pfnVolumeRead(pThis->hVolFmt, off, pvBuf, cbRead);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(int) RTDvmVolumeWrite(RTDVMVOLUME hVol, uint64_t off, const void *pvBuf, size_t cbWrite)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return pThis->pVolMgr->pDvmFmtOps->pfnVolumeWrite(pThis->hVolFmt, off, pvBuf, cbWrite);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncRTDECL(const char *) RTDvmVolumeTypeGetDescr(RTDVMVOLTYPE enmVolType)