Changeset 26986 in vbox for trunk/src/VBox
- Timestamp:
- Mar 3, 2010 1:26:28 PM (15 years ago)
- Location:
- trunk/src/VBox/Devices/Storage
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VBoxHDD.cpp
r26163 r26986 41 41 42 42 #include <VBox/VBoxHDD-Plugin.h> 43 44 45 #define VBOXHDDDISK_SIGNATURE 0x6f0e2a7d 46 47 /** Buffer size used for merging images. */ 48 #define VD_MERGE_BUFFER_SIZE (16 * _1M) 49 50 /** 51 * VD async I/O interface storage descriptor. 52 */ 53 typedef struct VDIASYNCIOSTORAGE 54 { 55 /** File handle. */ 56 RTFILE File; 57 /** Completion callback. */ 58 PFNVDCOMPLETED pfnCompleted; 59 /** Thread for async access. */ 60 RTTHREAD ThreadAsync; 61 } VDIASYNCIOSTORAGE, *PVDIASYNCIOSTORAGE; 62 63 /** 64 * VBox HDD Container image descriptor. 65 */ 66 typedef struct VDIMAGE 67 { 68 /** Link to parent image descriptor, if any. */ 69 struct VDIMAGE *pPrev; 70 /** Link to child image descriptor, if any. */ 71 struct VDIMAGE *pNext; 72 /** Container base filename. (UTF-8) */ 73 char *pszFilename; 74 /** Data managed by the backend which keeps the actual info. */ 75 void *pvBackendData; 76 /** Cached sanitized image flags. */ 77 unsigned uImageFlags; 78 /** Image open flags (only those handled generically in this code and which 79 * the backends will never ever see). */ 80 unsigned uOpenFlags; 81 82 /** Function pointers for the various backend methods. */ 83 PCVBOXHDDBACKEND Backend; 84 85 /** Pointer to list of VD interfaces, per-image. */ 86 PVDINTERFACE pVDIfsImage; 87 } VDIMAGE, *PVDIMAGE; 88 89 /** 90 * uModified bit flags. 91 */ 92 #define VD_IMAGE_MODIFIED_FLAG RT_BIT(0) 93 #define VD_IMAGE_MODIFIED_FIRST RT_BIT(1) 94 #define VD_IMAGE_MODIFIED_DISABLE_UUID_UPDATE RT_BIT(2) 95 96 97 /** 98 * VBox HDD Container main structure, private part. 99 */ 100 struct VBOXHDD 101 { 102 /** Structure signature (VBOXHDDDISK_SIGNATURE). */ 103 uint32_t u32Signature; 104 105 /** Number of opened images. */ 106 unsigned cImages; 107 108 /** Base image. */ 109 PVDIMAGE pBase; 110 111 /** Last opened image in the chain. 112 * The same as pBase if only one image is used. */ 113 PVDIMAGE pLast; 114 115 /** Flags representing the modification state. */ 116 unsigned uModified; 117 118 /** Cached size of this disk. */ 119 uint64_t cbSize; 120 /** Cached PCHS geometry for this disk. */ 121 PDMMEDIAGEOMETRY PCHSGeometry; 122 /** Cached LCHS geometry for this disk. */ 123 PDMMEDIAGEOMETRY LCHSGeometry; 124 125 /** Pointer to list of VD interfaces, per-disk. */ 126 PVDINTERFACE pVDIfsDisk; 127 /** Pointer to the common interface structure for error reporting. */ 128 PVDINTERFACE pInterfaceError; 129 /** Pointer to the error interface we use if available. */ 130 PVDINTERFACEERROR pInterfaceErrorCallbacks; 131 132 /** Fallback async interface. */ 133 VDINTERFACE VDIAsyncIO; 134 /** Fallback async I/O interface callback table. */ 135 VDINTERFACEASYNCIO VDIAsyncIOCallbacks; 136 }; 137 138 139 /** 140 * VBox parent read descriptor, used internally for compaction. 141 */ 142 typedef struct VDPARENTSTATEDESC 143 { 144 /** Pointer to disk descriptor. */ 145 PVBOXHDD pDisk; 146 /** Pointer to image descriptor. */ 147 PVDIMAGE pImage; 148 } VDPARENTSTATEDESC, *PVDPARENTSTATEDESC; 43 #include "VBoxHDDInternal.h" 149 44 150 45 … … 283 178 * internal: find image by index into the images list. 284 179 */ 285 staticPVDIMAGE vdGetImageByNumber(PVBOXHDD pDisk, unsigned nImage)180 PVDIMAGE vdGetImageByNumber(PVBOXHDD pDisk, unsigned nImage) 286 181 { 287 182 PVDIMAGE pImage = pDisk->pBase; … … 373 268 * internal: mark the disk as modified. 374 269 */ 375 staticvoid vdSetModifiedFlag(PVBOXHDD pDisk)270 void vdSetModifiedFlag(PVBOXHDD pDisk) 376 271 { 377 272 pDisk->uModified |= VD_IMAGE_MODIFIED_FLAG; … … 870 765 } 871 766 767 /** 768 * internal: send output to the log (unconditionally). 769 */ 770 void vdLogError(void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va) 771 { 772 NOREF(pvUser); 773 RTLogPrintf("Error occurred: %Rrc\n", rc); 774 RTLogPrintf(pszFormat, va); 775 } 872 776 873 777 /** … … 1044 948 if (pDisk->pInterfaceError) 1045 949 pDisk->pInterfaceErrorCallbacks = VDGetInterfaceError(pDisk->pInterfaceError); 950 else 951 { 952 /* Provide our own interface */ 953 pDisk->VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR); 954 pDisk->VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 955 pDisk->VDIErrorCallbacks.pfnMessage = vdLogMessage; 956 pDisk->VDIErrorCallbacks.pfnError = vdLogError; 957 rc = VDInterfaceAdd(&pDisk->VDIError, "VD_Error", VDINTERFACETYPE_ERROR, 958 &pDisk->VDIErrorCallbacks, pDisk, &pDisk->pVDIfsDisk); 959 AssertRC(rc); 960 } 1046 961 1047 962 /* Use the fallback async I/O interface if the caller doesn't provide one. */ … … 3725 3640 } 3726 3641 3727 /**3728 * Query if asynchronous operations are supported for this disk.3729 *3730 * @returns VBox status code.3731 * @returns VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.3732 * @param pDisk Pointer to the HDD container.3733 * @param nImage Image number, counts from 0. 0 is always base image of container.3734 * @param pfAIOSupported Where to store if async IO is supported.3735 */3736 VBOXDDU_DECL(int) VDImageIsAsyncIOSupported(PVBOXHDD pDisk, unsigned nImage, bool *pfAIOSupported)3737 {3738 int rc = VINF_SUCCESS;3739 3740 LogFlowFunc(("pDisk=%#p nImage=%u pfAIOSupported=%#p\n", pDisk, nImage, pfAIOSupported));3741 do3742 {3743 /* sanity check */3744 AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER);3745 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));3746 3747 /* Check arguments. */3748 AssertMsgBreakStmt(VALID_PTR(pfAIOSupported),3749 ("pfAIOSupported=%#p\n", pfAIOSupported),3750 rc = VERR_INVALID_PARAMETER);3751 3752 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage);3753 AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND);3754 3755 if (pImage->Backend->uBackendCaps & VD_CAP_ASYNC)3756 *pfAIOSupported = pImage->Backend->pfnIsAsyncIOSupported(pImage->pvBackendData);3757 else3758 *pfAIOSupported = false;3759 } while (0);3760 3761 LogFlowFunc(("returns %Rrc, fAIOSupported=%u\n", rc, *pfAIOSupported));3762 return rc;3763 }3764 3765 /**3766 * Start a asynchronous read request.3767 *3768 * @returns VBox status code.3769 * @param pDisk Pointer to the HDD container.3770 * @param uOffset The offset of the virtual disk to read from.3771 * @param cbRead How many bytes to read.3772 * @param paSeg Pointer to an array of segments.3773 * @param cSeg Number of segments in the array.3774 * @param pvUser User data which is passed on completion3775 */3776 VBOXDDU_DECL(int) VDAsyncRead(PVBOXHDD pDisk, uint64_t uOffset, size_t cbRead,3777 PPDMDATASEG paSeg, unsigned cSeg,3778 void *pvUser)3779 {3780 int rc = VERR_VD_BLOCK_FREE;3781 3782 LogFlowFunc(("pDisk=%#p uOffset=%llu paSeg=%p cSeg=%u cbRead=%zu\n",3783 pDisk, uOffset, paSeg, cSeg, cbRead));3784 do3785 {3786 /* sanity check */3787 AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER);3788 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));3789 3790 /* Check arguments. */3791 AssertMsgBreakStmt(cbRead,3792 ("cbRead=%zu\n", cbRead),3793 rc = VERR_INVALID_PARAMETER);3794 AssertMsgBreakStmt(uOffset + cbRead <= pDisk->cbSize,3795 ("uOffset=%llu cbRead=%zu pDisk->cbSize=%llu\n",3796 uOffset, cbRead, pDisk->cbSize),3797 rc = VERR_INVALID_PARAMETER);3798 AssertMsgBreakStmt(VALID_PTR(paSeg),3799 ("paSeg=%#p\n", paSeg),3800 rc = VERR_INVALID_PARAMETER);3801 AssertMsgBreakStmt(cSeg,3802 ("cSeg=%zu\n", cSeg),3803 rc = VERR_INVALID_PARAMETER);3804 3805 3806 PVDIMAGE pImage = pDisk->pLast;3807 AssertPtrBreakStmt(pImage, rc = VERR_VD_NOT_OPENED);3808 3809 /* @todo: This does not work for images which do not have all meta data in memory. */3810 for (PVDIMAGE pCurrImage = pImage;3811 pCurrImage != NULL && rc == VERR_VD_BLOCK_FREE;3812 pCurrImage = pCurrImage->pPrev)3813 {3814 rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pvBackendData,3815 uOffset, cbRead, paSeg, cSeg,3816 pvUser);3817 }3818 3819 /* No image in the chain contains the data for the block. */3820 if (rc == VERR_VD_BLOCK_FREE)3821 {3822 for (unsigned i = 0; i < cSeg && (cbRead > 0); i++)3823 {3824 memset(paSeg[i].pvSeg, '\0', paSeg[i].cbSeg);3825 cbRead -= paSeg[i].cbSeg;3826 }3827 /* Request finished without the need to enqueue a async I/O request. Tell caller. */3828 rc = VINF_VD_ASYNC_IO_FINISHED;3829 }3830 3831 } while (0);3832 3833 LogFlowFunc(("returns %Rrc\n", rc));3834 return rc;3835 }3836 3837 3838 /**3839 * Start a asynchronous write request.3840 *3841 * @returns VBox status code.3842 * @param pDisk Pointer to the HDD container.3843 * @param uOffset The offset of the virtual disk to write to.3844 * @param cbWrtie How many bytes to write.3845 * @param paSeg Pointer to an array of segments.3846 * @param cSeg Number of segments in the array.3847 * @param pvUser User data which is passed on completion.3848 */3849 VBOXDDU_DECL(int) VDAsyncWrite(PVBOXHDD pDisk, uint64_t uOffset, size_t cbWrite,3850 PPDMDATASEG paSeg, unsigned cSeg,3851 void *pvUser)3852 {3853 int rc;3854 3855 LogFlowFunc(("pDisk=%#p uOffset=%llu paSeg=%p cSeg=%u cbWrite=%zu\n",3856 pDisk, uOffset, paSeg, cSeg, cbWrite));3857 do3858 {3859 /* sanity check */3860 AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER);3861 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));3862 3863 /* Check arguments. */3864 AssertMsgBreakStmt(cbWrite,3865 ("cbWrite=%zu\n", cbWrite),3866 rc = VERR_INVALID_PARAMETER);3867 AssertMsgBreakStmt(uOffset + cbWrite <= pDisk->cbSize,3868 ("uOffset=%llu cbWrite=%zu pDisk->cbSize=%llu\n",3869 uOffset, cbWrite, pDisk->cbSize),3870 rc = VERR_INVALID_PARAMETER);3871 AssertMsgBreakStmt(VALID_PTR(paSeg),3872 ("paSeg=%#p\n", paSeg),3873 rc = VERR_INVALID_PARAMETER);3874 AssertMsgBreakStmt(cSeg,3875 ("cSeg=%zu\n", cSeg),3876 rc = VERR_INVALID_PARAMETER);3877 3878 3879 PVDIMAGE pImage = pDisk->pLast;3880 AssertPtrBreakStmt(pImage, rc = VERR_VD_NOT_OPENED);3881 3882 vdSetModifiedFlag(pDisk);3883 rc = pImage->Backend->pfnAsyncWrite(pImage->pvBackendData,3884 uOffset, cbWrite,3885 paSeg, cSeg, pvUser);3886 } while (0);3887 3888 LogFlowFunc(("returns %Rrc\n", rc));3889 return rc;3890 3891 }3892 3893 3642 #if 0 3894 3643 /** @copydoc VBOXHDDBACKEND::pfnComposeLocation */ -
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r26008 r26986 4571 4571 pImage->pGTCache = NULL; 4572 4572 pImage->pDescData = NULL; 4573 pImage->pVDIfsDisk = NULL;4573 pImage->pVDIfsDisk = pVDIfsDisk; 4574 4574 /* Descriptors for split images can be pretty large, especially if the 4575 4575 * filename is long. So prepare for the worst, and allocate quite some
Note:
See TracChangeset
for help on using the changeset viewer.