Changeset 10715 in vbox for trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
- Timestamp:
- Jul 16, 2008 10:38:23 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r10539 r10715 179 179 } VMDKACCESS, *PVMDKACCESS; 180 180 181 /** Forward declaration for PVMDKIMAGE. */ 182 typedef struct VMDKIMAGE *PVMDKIMAGE; 183 184 /** 185 * Extents files entry. Used for opening a particular file only once. 186 */ 187 typedef struct VMDKFILE 188 { 189 /** Pointer to filename. Local copy. */ 190 const char *pszFilename; 191 /** File open flags for consistency checking. */ 192 unsigned fOpen; 193 /** File handle. */ 194 RTFILE File; 195 /** Handle for asnychronous access if requested.*/ 196 void *pStorage; 197 /** Flag whether to use File or pStorage. */ 198 bool fAsyncIO; 199 /** Reference counter. */ 200 unsigned uReferences; 201 /** Flag whether the file should be deleted on last close. */ 202 bool fDelete; 203 /** Pointer to the image we belong to. */ 204 PVMDKIMAGE pImage; 205 /** Pointer to next file descriptor. */ 206 struct VMDKFILE *pNext; 207 /** Pointer to the previous file descriptor. */ 208 struct VMDKFILE *pPrev; 209 } VMDKFILE, *PVMDKFILE; 210 181 211 /** 182 212 * VMDK extent data structure. … … 185 215 { 186 216 /** File handle. */ 187 RTFILEFile;217 PVMDKFILE pFile; 188 218 /** Base name of the image extent. */ 189 219 const char *pszBasename; … … 239 269 240 270 /** 241 * Extents files entry. Used for opening a particular file only once.242 */243 typedef struct VMDKFILE244 {245 /** Pointer to filename. Local copy. */246 const char *pszFilename;247 /** File open flags for consistency checking. */248 unsigned fOpen;249 /** File handle. */250 RTFILE File;251 /** Reference counter. */252 unsigned uReferences;253 /** Flag whether the file should be deleted on last close. */254 bool fDelete;255 /** Pointer to next file descriptor. Singly linked list is fast enough. */256 struct VMDKFILE *pNext;257 } VMDKFILE, *PVMDKFILE;258 259 /**260 271 * Grain table cache size. Allocated per image. 261 272 */ … … 346 357 const char *pszFilename; 347 358 /** Descriptor file if applicable. */ 348 RTFILE File; 349 350 /** Error callback. */ 351 PFNVDERROR pfnError; 352 /** Opaque data for error callback. */ 353 void *pvErrorUser; 359 PVMDKFILE pFile; 360 361 /** Error interface. */ 362 PVDINTERFACE pInterfaceError; 363 /** Error interface callbacks. */ 364 PVDINTERFACEERROR pInterfaceErrorCallbacks; 365 366 /** Async I/O interface. */ 367 PVDINTERFACE pInterfaceAsyncIO; 368 /** Async I/O interface callbacks. */ 369 PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks; 370 /** 371 * Pointer to an array of task handles for task submission. 372 * This is an optimization because the task number to submit is not known 373 * and allocating/freeing an array in the read/write functions every time 374 * is too expensive. 375 */ 376 void **apTask; 377 /** Entries available in the task handle array. */ 378 unsigned cTask; 354 379 355 380 /** Open flags passed by VBoxHD layer. */ … … 382 407 /** Parsed descriptor file content. */ 383 408 VMDKDESCRIPTOR Descriptor; 384 } VMDKIMAGE , *PVMDKIMAGE;409 } VMDKIMAGE; 385 410 386 411 … … 408 433 va_list va; 409 434 va_start(va, pszFormat); 410 if (pImage->p fnError)411 pImage->p fnError(pImage->pvErrorUser, rc, RT_SRC_POS_ARGS,412 pszFormat, va);435 if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks) 436 pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS, 437 pszFormat, va); 413 438 va_end(va); 414 439 return rc; … … 419 444 * is only opened once - anything else can cause locking problems). 420 445 */ 421 static int vmdkFileOpen(PVMDKIMAGE pImage, P RTFILE pFile,422 const char *pszFilename, unsigned fOpen )446 static int vmdkFileOpen(PVMDKIMAGE pImage, PVMDKFILE *ppVmdkFile, 447 const char *pszFilename, unsigned fOpen, bool fAsyncIO) 423 448 { 424 449 int rc = VINF_SUCCESS; … … 433 458 Assert(fOpen == pVmdkFile->fOpen); 434 459 pVmdkFile->uReferences++; 435 *pFile = pVmdkFile->File; 460 461 *ppVmdkFile = pVmdkFile; 462 436 463 return rc; 437 464 } … … 442 469 if (!VALID_PTR(pVmdkFile)) 443 470 { 444 *p File = NIL_RTFILE;471 *ppVmdkFile = NULL; 445 472 return VERR_NO_MEMORY; 446 473 } … … 450 477 { 451 478 RTMemFree(pVmdkFile); 452 *p File = NIL_RTFILE;479 *ppVmdkFile = NULL; 453 480 return VERR_NO_MEMORY; 454 481 } 455 482 pVmdkFile->fOpen = fOpen; 456 rc = RTFileOpen(&pVmdkFile->File, pszFilename, fOpen); 483 if ((pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) && (fAsyncIO)) 484 { 485 rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser, 486 pszFilename, 487 pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY 488 ? true 489 : false, 490 &pVmdkFile->pStorage); 491 pVmdkFile->fAsyncIO = true; 492 } 493 else 494 { 495 rc = RTFileOpen(&pVmdkFile->File, pszFilename, fOpen); 496 pVmdkFile->fAsyncIO = false; 497 } 457 498 if (VBOX_SUCCESS(rc)) 458 499 { 459 500 pVmdkFile->uReferences = 1; 501 pVmdkFile->pImage = pImage; 460 502 pVmdkFile->pNext = pImage->pFiles; 503 if (pImage->pFiles) 504 pImage->pFiles->pPrev = pVmdkFile; 461 505 pImage->pFiles = pVmdkFile; 462 *p File = pVmdkFile->File;506 *ppVmdkFile = pVmdkFile; 463 507 } 464 508 else … … 466 510 RTStrFree((char *)(void *)pVmdkFile->pszFilename); 467 511 RTMemFree(pVmdkFile); 468 *p File = NIL_RTFILE;512 *ppVmdkFile = NULL; 469 513 } 470 514 … … 475 519 * Internal: close a file, updating the file descriptor cache. 476 520 */ 477 static int vmdkFileClose(PVMDKIMAGE pImage, P RTFILE pFile, bool fDelete)521 static int vmdkFileClose(PVMDKIMAGE pImage, PVMDKFILE *ppVmdkFile, bool fDelete) 478 522 { 479 523 int rc = VINF_SUCCESS; 480 RTFILE File; 481 PVMDKFILE pVmdkFile, pPrev; 482 483 Assert(VALID_PTR(pFile) && *pFile != NIL_RTFILE); 484 File = *pFile; 485 486 pPrev = NULL; 487 for (pVmdkFile = pImage->pFiles; 488 pVmdkFile != NULL; 489 pVmdkFile = pVmdkFile->pNext) 490 { 491 if (File == pVmdkFile->File) 492 { 493 pVmdkFile->fDelete |= fDelete; 494 Assert(pVmdkFile->uReferences); 495 pVmdkFile->uReferences--; 496 if (pVmdkFile->uReferences == 0) 497 { 498 /* Unchain the element from the list. */ 499 if (pPrev == NULL) 500 pImage->pFiles = pVmdkFile->pNext; 501 else 502 pPrev->pNext = pVmdkFile->pNext; 503 rc = RTFileClose(File); 504 *pFile = NIL_RTFILE; 505 if (VBOX_SUCCESS(rc) && pVmdkFile->fDelete) 506 rc = RTFileDelete(pVmdkFile->pszFilename); 507 RTStrFree((char *)(void *)pVmdkFile->pszFilename); 508 RTMemFree(pVmdkFile); 509 } 510 return rc; 511 } 512 pPrev = pVmdkFile; 513 } 514 515 AssertMsgFailed(("trying to close unknown file %#p", File)); 516 return VERR_INVALID_PARAMETER; 524 PVMDKFILE pVmdkFile = *ppVmdkFile; 525 526 Assert(VALID_PTR(pVmdkFile)); 527 528 pVmdkFile->fDelete |= fDelete; 529 Assert(pVmdkFile->uReferences); 530 pVmdkFile->uReferences--; 531 if (pVmdkFile->uReferences == 0) 532 { 533 PVMDKFILE pPrev; 534 PVMDKFILE pNext; 535 536 /* Unchain the element from the list. */ 537 pPrev = pVmdkFile->pPrev; 538 pNext = pVmdkFile->pNext; 539 540 if (pNext) 541 pNext->pPrev = pPrev; 542 if (pPrev) 543 pPrev->pNext = pNext; 544 else 545 pImage->pFiles = pNext; 546 547 if (pVmdkFile->fAsyncIO) 548 { 549 rc = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser, 550 pVmdkFile->pStorage); 551 } 552 else 553 { 554 rc = RTFileClose(pVmdkFile->File); 555 } 556 if (VBOX_SUCCESS(rc) && pVmdkFile->fDelete) 557 rc = RTFileDelete(pVmdkFile->pszFilename); 558 RTStrFree((char *)(void *)pVmdkFile->pszFilename); 559 RTMemFree(pVmdkFile); 560 } 561 562 *ppVmdkFile = NULL; 563 return rc; 564 } 565 566 /** 567 * Internal: read from a file distinguishing between async and normal operation 568 */ 569 DECLINLINE(int) vmdkFileReadAt(PVMDKFILE pVmdkFile, 570 uint64_t uOffset, void *pvBuf, 571 size_t cbToRead, size_t *pcbRead) 572 { 573 PVMDKIMAGE pImage = pVmdkFile->pImage; 574 575 if (pVmdkFile->fAsyncIO) 576 return pImage->pInterfaceAsyncIOCallbacks->pfnRead(pImage->pInterfaceAsyncIO->pvUser, 577 pVmdkFile->pStorage, uOffset, 578 cbToRead, pvBuf, pcbRead); 579 else 580 return RTFileReadAt(pVmdkFile->File, uOffset, pvBuf, cbToRead, pcbRead); 581 } 582 583 /** 584 * Internal: write to a file distinguishing between async and normal operation 585 */ 586 DECLINLINE(int) vmdkFileWriteAt(PVMDKFILE pVmdkFile, 587 uint64_t uOffset, const void *pvBuf, 588 size_t cbToWrite, size_t *pcbWritten) 589 { 590 PVMDKIMAGE pImage = pVmdkFile->pImage; 591 592 if (pVmdkFile->fAsyncIO) 593 return pImage->pInterfaceAsyncIOCallbacks->pfnWrite(pImage->pInterfaceAsyncIO->pvUser, 594 pVmdkFile->pStorage, uOffset, 595 cbToWrite, pvBuf, pcbWritten); 596 else 597 return RTFileWriteAt(pVmdkFile->File, uOffset, pvBuf, cbToWrite, pcbWritten); 598 } 599 600 /** 601 * Internal: get the size of a file distinguishing beween async and normal operation 602 */ 603 DECLINLINE(int) vmdkFileGetSize(PVMDKFILE pVmdkFile, uint64_t *pcbSize) 604 { 605 if (pVmdkFile->fAsyncIO) 606 { 607 AssertMsgFailed(("TODO\n")); 608 return 0; 609 } 610 else 611 return RTFileGetSize(pVmdkFile->File, pcbSize); 612 } 613 614 /** 615 * Internal: set the size of a file distinguishing beween async and normal operation 616 */ 617 DECLINLINE(int) vmdkFileSetSize(PVMDKFILE pVmdkFile, uint64_t cbSize) 618 { 619 if (pVmdkFile->fAsyncIO) 620 { 621 AssertMsgFailed(("TODO\n")); 622 return VERR_NOT_SUPPORTED; 623 } 624 else 625 return RTFileSetSize(pVmdkFile->File, cbSize); 626 } 627 628 /** 629 * Internal: flush a file distinguishing between async and normal operation 630 */ 631 DECLINLINE(int) vmdkFileFlush(PVMDKFILE pVmdkFile) 632 { 633 PVMDKIMAGE pImage = pVmdkFile->pImage; 634 635 if (pVmdkFile->fAsyncIO) 636 return pImage->pInterfaceAsyncIOCallbacks->pfnFlush(pImage->pInterfaceAsyncIO->pvUser, 637 pVmdkFile->pStorage); 638 else 639 return RTFileFlush(pVmdkFile->File); 517 640 } 518 641 … … 533 656 pVmdkFile->pszFilename)); 534 657 pImage->pFiles = pVmdkFile->pNext; 535 rc2 = RTFileClose(pVmdkFile->File); 658 659 if (pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) 660 rc2 = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser, 661 pVmdkFile->pStorage); 662 else 663 rc2 = RTFileClose(pVmdkFile->File); 664 536 665 if (VBOX_SUCCESS(rc) && pVmdkFile->fDelete) 537 666 rc2 = RTFileDelete(pVmdkFile->pszFilename); … … 649 778 } 650 779 pExtent->pGD = pGD; 651 rc = RTFileReadAt(pExtent->File, VMDK_SECTOR2BYTE(pExtent->uSectorGD),652 pGD, cbGD, NULL);780 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(pExtent->uSectorGD), 781 pGD, cbGD, NULL); 653 782 AssertRC(rc); 654 783 if (VBOX_FAILURE(rc)) … … 669 798 } 670 799 pExtent->pRGD = pRGD; 671 rc = RTFileReadAt(pExtent->File, VMDK_SECTOR2BYTE(pExtent->uSectorRGD),672 pRGD, cbGD, NULL);800 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(pExtent->uSectorRGD), 801 pRGD, cbGD, NULL); 673 802 AssertRC(rc); 674 803 if (VBOX_FAILURE(rc)) … … 714 843 goto out; 715 844 } 716 rc = RTFileReadAt(pExtent->File, VMDK_SECTOR2BYTE(*pGDTmp),717 pTmpGT1, cbGT, NULL);845 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(*pGDTmp), 846 pTmpGT1, cbGT, NULL); 718 847 if (VBOX_FAILURE(rc)) 719 848 { … … 723 852 goto out; 724 853 } 725 rc = RTFileReadAt(pExtent->File, VMDK_SECTOR2BYTE(*pRGDTmp),726 pTmpGT2, cbGT, NULL);854 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(*pRGDTmp), 855 pTmpGT2, cbGT, NULL); 727 856 if (VBOX_FAILURE(rc)) 728 857 { … … 782 911 783 912 cbOverhead = RT_ALIGN_64(VMDK_SECTOR2BYTE(uStartSector) + 2 * (cbGDRounded + cbGTRounded), VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)); 784 rc = RTFileSetSize(pExtent->File, cbOverhead);913 rc = vmdkFileSetSize(pExtent->pFile, cbOverhead); 785 914 if (VBOX_FAILURE(rc)) 786 915 goto out; … … 799 928 uGTSectorLE = RT_H2LE_U64(uOffsetSectors); 800 929 /* Write the redundant grain directory entry to disk. */ 801 rc = RTFileWriteAt(pExtent->File,802 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE),803 &uGTSectorLE, sizeof(uGTSectorLE), NULL);930 rc = vmdkFileWriteAt(pExtent->pFile, 931 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE), 932 &uGTSectorLE, sizeof(uGTSectorLE), NULL); 804 933 if (VBOX_FAILURE(rc)) 805 934 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new redundant grain directory entry in '%s'"), pExtent->pszFullname); … … 813 942 uGTSectorLE = RT_H2LE_U64(uOffsetSectors); 814 943 /* Write the grain directory entry to disk. */ 815 rc = RTFileWriteAt(pExtent->File,816 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE),817 &uGTSectorLE, sizeof(uGTSectorLE), NULL);944 rc = vmdkFileWriteAt(pExtent->pFile, 945 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE), 946 &uGTSectorLE, sizeof(uGTSectorLE), NULL); 818 947 if (VBOX_FAILURE(rc)) 819 948 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new grain directory entry in '%s'"), pExtent->pszFullname); … … 1819 1948 uint64_t cbLimit; 1820 1949 uint64_t uOffset; 1821 RTFILEDescFile;1950 PVMDKFILE pDescFile; 1822 1951 1823 1952 if (pImage->pDescData) … … 1826 1955 uOffset = 0; 1827 1956 cbLimit = 0; 1828 DescFile = pImage->File;1957 pDescFile = pImage->pFile; 1829 1958 } 1830 1959 else … … 1834 1963 cbLimit = VMDK_SECTOR2BYTE(pImage->pExtents[0].cDescriptorSectors); 1835 1964 cbLimit += uOffset; 1836 DescFile = pImage->pExtents[0].File;1965 pDescFile = pImage->pExtents[0].pFile; 1837 1966 } 1838 1967 for (unsigned i = 0; i < pImage->Descriptor.cLines; i++) … … 1843 1972 if (cbLimit && uOffset + cb + 1 > cbLimit) 1844 1973 return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too long in '%s'"), pImage->pszFilename); 1845 rc = RTFileWriteAt(DescFile, uOffset, psz, cb, NULL);1974 rc = vmdkFileWriteAt(pDescFile, uOffset, psz, cb, NULL); 1846 1975 if (VBOX_FAILURE(rc)) 1847 1976 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename); 1848 1977 uOffset += cb; 1849 rc = RTFileWriteAt(DescFile, uOffset, "\n", 1, NULL);1978 rc = vmdkFileWriteAt(pDescFile, uOffset, "\n", 1, NULL); 1850 1979 if (VBOX_FAILURE(rc)) 1851 1980 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename); … … 1857 1986 while (uOffset < cbLimit) 1858 1987 { 1859 rc = RTFileWriteAt(DescFile, uOffset, "", 1, NULL);1988 rc = vmdkFileWriteAt(pDescFile, uOffset, "", 1, NULL); 1860 1989 if (VBOX_FAILURE(rc)) 1861 1990 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename); … … 1865 1994 else 1866 1995 { 1867 rc = RTFileSetSize(DescFile, uOffset);1996 rc = vmdkFileSetSize(pDescFile, uOffset); 1868 1997 if (VBOX_FAILURE(rc)) 1869 1998 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename); … … 1881 2010 uint64_t cbExtentSize, cSectorsPerGDE; 1882 2011 1883 int rc = RTFileReadAt(pExtent->File, 0, &Header, sizeof(Header), NULL);2012 int rc = vmdkFileReadAt(pExtent->pFile, 0, &Header, sizeof(Header), NULL); 1884 2013 AssertRC(rc); 1885 2014 if (VBOX_FAILURE(rc)) … … 1896 2025 /* The image must be a multiple of a sector in size. If not, it means the 1897 2026 * image is at least truncated, or even seriously garbled. */ 1898 rc = RTFileGetSize(pExtent->File, &cbExtentSize);2027 rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize); 1899 2028 if (VBOX_FAILURE(rc)) 1900 2029 { … … 2005 2134 Header.doubleEndLineChar2 = '\n'; 2006 2135 2007 int rc = RTFileWriteAt(pExtent->File, 0, &Header, sizeof(Header), NULL);2136 int rc = vmdkFileWriteAt(pExtent->pFile, 0, &Header, sizeof(Header), NULL); 2008 2137 AssertRC(rc); 2009 2138 if (VBOX_FAILURE(rc)) … … 2023 2152 uint64_t cSectorsPerGDE; 2024 2153 2025 int rc = RTFileReadAt(pExtent->File, 0, &Header, sizeof(Header), NULL);2154 int rc = vmdkFileReadAt(pExtent->pFile, 0, &Header, sizeof(Header), NULL); 2026 2155 AssertRC(rc); 2027 2156 if (VBOX_FAILURE(rc)) … … 2093 2222 pExtent->pDescData = NULL; 2094 2223 } 2095 if (pExtent-> File != NIL_RTFILE)2096 { 2097 vmdkFileClose(pImage, &pExtent-> File,2224 if (pExtent->pFile != NULL) 2225 { 2226 vmdkFileClose(pImage, &pExtent->pFile, 2098 2227 fDelete 2099 2228 && pExtent->pszFullname … … 2157 2286 for (unsigned i = 0; i < cExtents; i++) 2158 2287 { 2159 pExtents[i]. File = NIL_RTFILE;2288 pExtents[i].pFile = NULL; 2160 2289 pExtents[i].pszBasename = NULL; 2161 2290 pExtents[i].pszFullname = NULL; … … 2182 2311 int rc; 2183 2312 uint32_t u32Magic; 2184 RTFILEFile;2313 PVMDKFILE pFile; 2185 2314 PVMDKEXTENT pExtent; 2186 2315 … … 2189 2318 /* 2190 2319 * Open the image. 2320 * We don't have to check for asynchronous access because 2321 * we only support raw access and the opened file is a description 2322 * file were no data is stored. 2191 2323 */ 2192 rc = vmdkFileOpen(pImage, & File, pImage->pszFilename,2324 rc = vmdkFileOpen(pImage, &pFile, pImage->pszFilename, 2193 2325 uOpenFlags & VD_OPEN_FLAGS_READONLY 2194 2326 ? RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE 2195 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE );2327 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, false); 2196 2328 if (VBOX_FAILURE(rc)) 2197 2329 { … … 2200 2332 goto out; 2201 2333 } 2202 pImage-> File =File;2334 pImage->pFile = pFile; 2203 2335 2204 2336 /* Read magic (if present). */ 2205 rc = RTFileReadAt(File, 0, &u32Magic, sizeof(u32Magic), NULL);2337 rc = vmdkFileReadAt(pFile, 0, &u32Magic, sizeof(u32Magic), NULL); 2206 2338 if (VBOX_FAILURE(rc)) 2207 2339 { … … 2220 2352 * file, so no need to keep anything open for the image. */ 2221 2353 pExtent = &pImage->pExtents[0]; 2222 pExtent-> File =File;2223 pImage-> File = NIL_RTFILE;2354 pExtent->pFile = pFile; 2355 pImage->pFile = NULL; 2224 2356 pExtent->pszFullname = RTStrDup(pImage->pszFilename); 2225 2357 if (!pExtent->pszFullname) … … 2245 2377 goto out; 2246 2378 } 2247 rc = RTFileReadAt(pExtent->File,2248 VMDK_SECTOR2BYTE(pExtent->uDescriptorSector),2249 pExtent->pDescData,2250 VMDK_SECTOR2BYTE(pExtent->cDescriptorSectors), NULL);2379 rc = vmdkFileReadAt(pExtent->pFile, 2380 VMDK_SECTOR2BYTE(pExtent->uDescriptorSector), 2381 pExtent->pDescData, 2382 VMDK_SECTOR2BYTE(pExtent->cDescriptorSectors), NULL); 2251 2383 AssertRC(rc); 2252 2384 if (VBOX_FAILURE(rc)) … … 2279 2411 2280 2412 size_t cbRead; 2281 rc = RTFileReadAt(pImage->File, 0, pImage->pDescData,2282 pImage->cbDescAlloc, &cbRead);2413 rc = vmdkFileReadAt(pImage->pFile, 0, pImage->pDescData, 2414 pImage->cbDescAlloc, &cbRead); 2283 2415 if (VBOX_FAILURE(rc)) 2284 2416 { … … 2298 2430 if (VBOX_FAILURE(rc)) 2299 2431 goto out; 2432 2433 /* 2434 * We have to check for the asynchronous open flag. The 2435 * extents are parsed and the type of all are known now. 2436 * Check if every extent is either FLAT or ZERO. 2437 */ 2438 if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) 2439 { 2440 for (unsigned i = 0; i < pImage->cExtents; i++) 2441 { 2442 PVMDKEXTENT pExtent = &pImage->pExtents[i]; 2443 2444 if ( (pExtent->enmType != VMDKETYPE_FLAT) 2445 && (pExtent->enmType != VMDKETYPE_ZERO)) 2446 { 2447 /* 2448 * Opened image contains at least one none flat or zero extent. 2449 * Return error but don't set error message as the caller 2450 * has the chance to open in non async I/O mode. 2451 */ 2452 rc = VERR_NOT_SUPPORTED; 2453 goto out; 2454 } 2455 } 2456 } 2300 2457 2301 2458 for (unsigned i = 0; i < pImage->cExtents; i++) … … 2344 2501 { 2345 2502 case VMDKETYPE_HOSTED_SPARSE: 2346 rc = vmdkFileOpen(pImage, &pExtent-> File, pExtent->pszFullname,2503 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 2347 2504 uOpenFlags & VD_OPEN_FLAGS_READONLY 2348 2505 ? RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE 2349 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE );2506 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, false); 2350 2507 if (VBOX_FAILURE(rc)) 2351 2508 { … … 2367 2524 break; 2368 2525 case VMDKETYPE_FLAT: 2369 rc = vmdkFileOpen(pImage, &pExtent-> File, pExtent->pszFullname,2526 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 2370 2527 uOpenFlags & VD_OPEN_FLAGS_READONLY 2371 2528 ? RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE 2372 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE );2529 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, true); 2373 2530 if (VBOX_FAILURE(rc)) 2374 2531 { … … 2469 2626 pExtent = &pImage->pExtents[0]; 2470 2627 /* Create raw disk descriptor file. */ 2471 rc = vmdkFileOpen(pImage, &pImage->File, pImage->pszFilename, 2472 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED); 2628 rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename, 2629 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED, 2630 false); 2473 2631 if (VBOX_FAILURE(rc)) 2474 2632 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename); … … 2492 2650 2493 2651 /* Open flat image, the raw disk. */ 2494 rc = vmdkFileOpen(pImage, &pExtent-> File, pExtent->pszFullname,2495 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE );2652 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 2653 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, false); 2496 2654 if (VBOX_FAILURE(rc)) 2497 2655 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw disk file '%s'"), pExtent->pszFullname); … … 2541 2699 2542 2700 /* Create raw partition descriptor file. */ 2543 rc = vmdkFileOpen(pImage, &pImage->File, pImage->pszFilename, 2544 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED); 2701 rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename, 2702 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED, 2703 false); 2545 2704 if (VBOX_FAILURE(rc)) 2546 2705 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename); … … 2612 2771 2613 2772 /* Create partition table flat image. */ 2614 rc = vmdkFileOpen(pImage, &pExtent->File, pExtent->pszFullname, 2615 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED); 2773 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 2774 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED, 2775 false); 2616 2776 if (VBOX_FAILURE(rc)) 2617 2777 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new partition data file '%s'"), pExtent->pszFullname); 2618 rc = RTFileWriteAt(pExtent->File,2619 VMDK_SECTOR2BYTE(uPartOffset),2620 pPart->pvPartitionData,2621 pPart->cbPartitionData, NULL);2778 rc = vmdkFileWriteAt(pExtent->pFile, 2779 VMDK_SECTOR2BYTE(uPartOffset), 2780 pPart->pvPartitionData, 2781 pPart->cbPartitionData, NULL); 2622 2782 if (VBOX_FAILURE(rc)) 2623 2783 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not write partition data to '%s'"), pExtent->pszFullname); … … 2659 2819 2660 2820 /* Open flat image, the raw partition. */ 2661 rc = vmdkFileOpen(pImage, &pExtent->File, pExtent->pszFullname, 2662 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); 2821 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 2822 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, 2823 false); 2663 2824 if (VBOX_FAILURE(rc)) 2664 2825 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw partition file '%s'"), pExtent->pszFullname); … … 2731 2892 if (cExtents != 1 || enmType == VD_IMAGE_TYPE_FIXED) 2732 2893 { 2733 rc = vmdkFileOpen(pImage, &pImage->File, pImage->pszFilename, 2734 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED); 2894 rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename, 2895 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED, 2896 false); 2735 2897 if (VBOX_FAILURE(rc)) 2736 2898 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new sparse descriptor file '%s'"), pImage->pszFilename); … … 2738 2900 } 2739 2901 else 2740 pImage-> File = NIL_RTFILE;2902 pImage->pFile = NULL; 2741 2903 2742 2904 /* Set up all extents. */ … … 2801 2963 2802 2964 /* Create file for extent. */ 2803 rc = vmdkFileOpen(pImage, &pExtent->File, pExtent->pszFullname, 2804 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED); 2965 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 2966 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED, 2967 false); 2805 2968 if (VBOX_FAILURE(rc)) 2806 2969 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname); 2807 2970 if (enmType == VD_IMAGE_TYPE_FIXED) 2808 2971 { 2809 rc = RTFileSetSize(pExtent->File, cbExtent);2972 rc = vmdkFileSetSize(pExtent->pFile, cbExtent); 2810 2973 if (VBOX_FAILURE(rc)) 2811 2974 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set size of new file '%s'"), pExtent->pszFullname); … … 2830 2993 unsigned cbChunk = (unsigned)RT_MIN(cbExtent, cbBuf); 2831 2994 2832 rc = RTFileWriteAt(pExtent->File, uOff, pvBuf, cbChunk, NULL);2995 rc = vmdkFileWriteAt(pExtent->pFile, uOff, pvBuf, cbChunk, NULL); 2833 2996 if (VBOX_FAILURE(rc)) 2834 2997 { … … 3140 3303 pImage->pExtents = NULL; 3141 3304 } 3142 if (pImage-> File != NIL_RTFILE)3143 vmdkFileClose(pImage, &pImage-> File, fDelete);3305 if (pImage->pFile != NULL) 3306 vmdkFileClose(pImage, &pImage->pFile, fDelete); 3144 3307 vmdkFileCheckAllClose(pImage); 3145 3308 } … … 3164 3327 { 3165 3328 pExtent = &pImage->pExtents[i]; 3166 if (pExtent-> File != NIL_RTFILE&& pExtent->fMetaDirty)3329 if (pExtent->pFile != NULL && pExtent->fMetaDirty) 3167 3330 { 3168 3331 switch (pExtent->enmType) … … 3196 3359 case VMDKETYPE_FLAT: 3197 3360 /** @todo implement proper path absolute check. */ 3198 if ( pExtent-> File != NIL_RTFILE3361 if ( pExtent->pFile != NULL 3199 3362 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 3200 3363 && !(pExtent->pszBasename[0] == RTPATH_SLASH)) 3201 rc = RTFileFlush(pExtent->File);3364 rc = vmdkFileFlush(pExtent->pFile); 3202 3365 break; 3203 3366 case VMDKETYPE_ZERO: … … 3285 3448 { 3286 3449 /* Cache miss, fetch data from disk. */ 3287 rc = RTFileReadAt(pExtent->File,3288 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),3289 aGTDataTmp, sizeof(aGTDataTmp), NULL);3450 rc = vmdkFileReadAt(pExtent->pFile, 3451 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 3452 aGTDataTmp, sizeof(aGTDataTmp), NULL); 3290 3453 if (VBOX_FAILURE(rc)) 3291 3454 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in '%s'"), pExtent->pszFullname); … … 3334 3497 * entry. So there is absolutely no data in this area. Allocate 3335 3498 * a new grain table and put the reference to it in the GDs. */ 3336 rc = RTFileGetSize(pExtent->File, &cbExtentSize);3499 rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize); 3337 3500 if (VBOX_FAILURE(rc)) 3338 3501 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); … … 3353 3516 i++) 3354 3517 { 3355 rc = RTFileWriteAt(pExtent->File,3356 VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp),3357 aGTDataTmp, sizeof(aGTDataTmp), NULL);3518 rc = vmdkFileWriteAt(pExtent->pFile, 3519 VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp), 3520 aGTDataTmp, sizeof(aGTDataTmp), NULL); 3358 3521 if (VBOX_FAILURE(rc)) 3359 3522 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname); … … 3362 3525 { 3363 3526 AssertReturn(!uRGTSector, VERR_VDI_INVALID_HEADER); 3364 rc = RTFileGetSize(pExtent->File, &cbExtentSize);3527 rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize); 3365 3528 if (VBOX_FAILURE(rc)) 3366 3529 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); … … 3380 3543 i++) 3381 3544 { 3382 rc = RTFileWriteAt(pExtent->File,3383 VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp),3384 aGTDataTmp, sizeof(aGTDataTmp), NULL);3545 rc = vmdkFileWriteAt(pExtent->pFile, 3546 VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp), 3547 aGTDataTmp, sizeof(aGTDataTmp), NULL); 3385 3548 if (VBOX_FAILURE(rc)) 3386 3549 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname); … … 3393 3556 * some unused sectors in the extent. */ 3394 3557 uint32_t uGTSectorLE = RT_H2LE_U64(uGTSector); 3395 rc = RTFileWriteAt(pExtent->File,3396 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),3397 &uGTSectorLE, sizeof(uGTSectorLE), NULL);3558 rc = vmdkFileWriteAt(pExtent->pFile, 3559 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE), 3560 &uGTSectorLE, sizeof(uGTSectorLE), NULL); 3398 3561 if (VBOX_FAILURE(rc)) 3399 3562 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname); … … 3401 3564 { 3402 3565 uint32_t uRGTSectorLE = RT_H2LE_U64(uRGTSector); 3403 rc = RTFileWriteAt(pExtent->File,3404 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE),3405 &uRGTSectorLE, sizeof(uRGTSectorLE), NULL);3566 rc = vmdkFileWriteAt(pExtent->pFile, 3567 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE), 3568 &uRGTSectorLE, sizeof(uRGTSectorLE), NULL); 3406 3569 if (VBOX_FAILURE(rc)) 3407 3570 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname); … … 3414 3577 } 3415 3578 3416 rc = RTFileGetSize(pExtent->File, &cbExtentSize);3579 rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize); 3417 3580 if (VBOX_FAILURE(rc)) 3418 3581 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); … … 3420 3583 3421 3584 /* Write the data. */ 3422 rc = RTFileWriteAt(pExtent->File, cbExtentSize, pvBuf, cbWrite, NULL);3585 rc = vmdkFileWriteAt(pExtent->pFile, cbExtentSize, pvBuf, cbWrite, NULL); 3423 3586 if (VBOX_FAILURE(rc)) 3424 3587 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname); … … 3432 3595 { 3433 3596 /* Cache miss, fetch data from disk. */ 3434 rc = RTFileReadAt(pExtent->File,3435 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),3436 aGTDataTmp, sizeof(aGTDataTmp), NULL);3597 rc = vmdkFileReadAt(pExtent->pFile, 3598 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 3599 aGTDataTmp, sizeof(aGTDataTmp), NULL); 3437 3600 if (VBOX_FAILURE(rc)) 3438 3601 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname); … … 3453 3616 pGTCacheEntry->aGTData[uGTBlockIndex] = VMDK_BYTE2SECTOR(cbExtentSize); 3454 3617 /* Update grain table on disk. */ 3455 rc = RTFileWriteAt(pExtent->File,3456 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),3457 aGTDataTmp, sizeof(aGTDataTmp), NULL);3618 rc = vmdkFileWriteAt(pExtent->pFile, 3619 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 3620 aGTDataTmp, sizeof(aGTDataTmp), NULL); 3458 3621 if (VBOX_FAILURE(rc)) 3459 3622 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname); … … 3461 3624 { 3462 3625 /* Update backup grain table on disk. */ 3463 rc = RTFileWriteAt(pExtent->File,3464 VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),3465 aGTDataTmp, sizeof(aGTDataTmp), NULL);3626 rc = vmdkFileWriteAt(pExtent->pFile, 3627 VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 3628 aGTDataTmp, sizeof(aGTDataTmp), NULL); 3466 3629 if (VBOX_FAILURE(rc)) 3467 3630 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname); … … 3500 3663 } 3501 3664 pImage->pszFilename = pszFilename; 3502 pImage-> File = NIL_RTFILE;3665 pImage->pFile = NULL; 3503 3666 pImage->pExtents = NULL; 3504 3667 pImage->pFiles = NULL; 3505 3668 pImage->pGTCache = NULL; 3506 3669 pImage->pDescData = NULL; 3507 pImage->p fnError = NULL;3508 pImage->p vErrorUser= NULL;3670 pImage->pInterfaceError = NULL; 3671 pImage->pInterfaceErrorCallbacks = NULL; 3509 3672 /** @todo speed up this test open (VD_OPEN_FLAGS_INFO) by skipping as 3510 3673 * much as possible in vmdkOpenImage. */ … … 3519 3682 /** @copydoc VBOXHDDBACKEND::pfnOpen */ 3520 3683 static int vmdkOpen(const char *pszFilename, unsigned uOpenFlags, 3521 P FNVDERROR pfnError, void *pvErrorUser,3684 PVDINTERFACE pInterfaces, 3522 3685 void **ppBackendData) 3523 3686 { … … 3550 3713 } 3551 3714 pImage->pszFilename = pszFilename; 3552 pImage-> File = NIL_RTFILE;3715 pImage->pFile = NULL; 3553 3716 pImage->pExtents = NULL; 3554 3717 pImage->pFiles = NULL; 3555 3718 pImage->pGTCache = NULL; 3556 3719 pImage->pDescData = NULL; 3557 pImage->pfnError = pfnError; 3558 pImage->pvErrorUser = pvErrorUser; 3720 pImage->pInterfaceError = NULL; 3721 pImage->pInterfaceErrorCallbacks = NULL; 3722 3723 /* Try to get error interface. */ 3724 pImage->pInterfaceError = VDGetInterfaceFromList(pInterfaces, VDINTERFACETYPE_ERROR); 3725 if (pImage->pInterfaceError) 3726 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError->pCallbacks); 3727 3728 /* Try to get async I/O interfaec. */ 3729 pImage->pInterfaceAsyncIO = VDGetInterfaceFromList(pInterfaces, VDINTERFACETYPE_ASYNCIO); 3730 if (pImage->pInterfaceAsyncIO) 3731 pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO->pCallbacks); 3732 3559 3733 3560 3734 rc = vmdkOpenImage(pImage, uOpenFlags); … … 3575 3749 unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, 3576 3750 void *pvUser, unsigned uPercentStart, 3577 unsigned uPercentSpan, P FNVDERROR pfnError,3578 void * pvErrorUser, void **ppBackendData)3579 { 3580 LogFlowFunc(("pszFilename=\"%s\" enmType=%d cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p uOpenFlags=%#x pfnProgress=%#p pvUser=%#p uPercentStart=%u uPercentSpan=%u p fnError=%#p pvErrorUser=%#p ppBackendData=%#p", pszFilename, enmType, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, uOpenFlags, pfnProgress, pvUser, uPercentStart, uPercentSpan, pfnError, pvErrorUser, ppBackendData));3751 unsigned uPercentSpan, PVDINTERFACE pInterfaces, 3752 void **ppBackendData) 3753 { 3754 LogFlowFunc(("pszFilename=\"%s\" enmType=%d cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p uOpenFlags=%#x pfnProgress=%#p pvUser=%#p uPercentStart=%u uPercentSpan=%u pInterfaces=%#p ppBackendData=%#p", pszFilename, enmType, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, uOpenFlags, pfnProgress, pvUser, uPercentStart, uPercentSpan, pInterfaces, ppBackendData)); 3581 3755 int rc; 3582 3756 PVMDKIMAGE pImage; … … 3612 3786 } 3613 3787 pImage->pszFilename = pszFilename; 3614 pImage-> File = NIL_RTFILE;3788 pImage->pFile = NULL; 3615 3789 pImage->pExtents = NULL; 3616 3790 pImage->pFiles = NULL; 3617 3791 pImage->pGTCache = NULL; 3618 3792 pImage->pDescData = NULL; 3619 pImage->p fnError = pfnError;3620 pImage->p vErrorUser = pvErrorUser;3793 pImage->pInterfaceError = NULL; 3794 pImage->pInterfaceErrorCallbacks = NULL; 3621 3795 pImage->cbDescAlloc = VMDK_SECTOR2BYTE(20); 3622 3796 pImage->pDescData = (char *)RTMemAllocZ(pImage->cbDescAlloc); … … 3626 3800 goto out; 3627 3801 } 3802 3803 /* Get error interface. */ 3804 pImage->pInterfaceError = VDGetInterfaceFromList(pInterfaces, VDINTERFACETYPE_ERROR); 3805 if (pImage->pInterfaceError) 3806 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 3628 3807 3629 3808 rc = vmdkCreateImage(pImage, enmType, cbSize, uImageFlags, pszComment, … … 3780 3959 goto rollback; 3781 3960 /* Close the extent file. */ 3782 vmdkFileClose(pImage, &pExtent-> File, false);3961 vmdkFileClose(pImage, &pExtent->pFile, false); 3783 3962 /* Rename the extent file. */ 3784 3963 rc = RTFileMove(pExtent->pszFullname, apszNewName[i], 0); … … 3846 4025 } 3847 4026 /* Restore the old descriptor. */ 3848 RTFILEFile;3849 rrc = RTFileOpen(&File, pszOldDescName,3850 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE );4027 PVMDKFILE pFile; 4028 rrc = vmdkFileOpen(pImage, &pFile, pszOldDescName, 4029 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, false); 3851 4030 AssertRC(rrc); 3852 4031 if (fEmbeddedDesc) 3853 4032 { 3854 ExtentCopy. File =File;4033 ExtentCopy.pFile = pFile; 3855 4034 pImage->pExtents = &ExtentCopy; 3856 4035 } 3857 4036 else 3858 pImage-> File =File;4037 pImage->pFile = pFile; 3859 4038 pImage->Descriptor = DescriptorCopy; 3860 4039 vmdkWriteDescriptor(pImage); 3861 RTFileClose(File);4040 vmdkFileClose(pImage, &pFile, false); 3862 4041 RTStrFree(pszOldDescName); 3863 4042 /* Re-open the image back. */ … … 3950 4129 rc = VERR_VDI_BLOCK_FREE; 3951 4130 else 3952 rc = RTFileReadAt(pExtent->File,3953 VMDK_SECTOR2BYTE(uSectorExtentAbs),3954 pvBuf, cbToRead, NULL);4131 rc = vmdkFileReadAt(pExtent->pFile, 4132 VMDK_SECTOR2BYTE(uSectorExtentAbs), 4133 pvBuf, cbToRead, NULL); 3955 4134 break; 3956 4135 case VMDKETYPE_FLAT: 3957 rc = RTFileReadAt(pExtent->File,3958 VMDK_SECTOR2BYTE(uSectorExtentRel),3959 pvBuf, cbToRead, NULL);4136 rc = vmdkFileReadAt(pExtent->pFile, 4137 VMDK_SECTOR2BYTE(uSectorExtentRel), 4138 pvBuf, cbToRead, NULL); 3960 4139 break; 3961 4140 case VMDKETYPE_ZERO: … … 4057 4236 } 4058 4237 else 4059 rc = RTFileWriteAt(pExtent->File,4060 VMDK_SECTOR2BYTE(uSectorExtentAbs),4061 pvBuf, cbToWrite, NULL);4238 rc = vmdkFileWriteAt(pExtent->pFile, 4239 VMDK_SECTOR2BYTE(uSectorExtentAbs), 4240 pvBuf, cbToWrite, NULL); 4062 4241 break; 4063 4242 case VMDKETYPE_FLAT: 4064 4243 /* Clip write range to remain in this extent. */ 4065 4244 cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 4066 rc = RTFileWriteAt(pExtent->File,4067 VMDK_SECTOR2BYTE(uSectorExtentRel),4068 pvBuf, cbToWrite, NULL);4245 rc = vmdkFileWriteAt(pExtent->pFile, 4246 VMDK_SECTOR2BYTE(uSectorExtentRel), 4247 pvBuf, cbToWrite, NULL); 4069 4248 break; 4070 4249 case VMDKETYPE_ZERO: … … 4154 4333 { 4155 4334 uint64_t cbFile; 4156 if (pImage-> File != NIL_RTFILE)4157 { 4158 int rc = RTFileGetSize(pImage->File, &cbFile);4335 if (pImage->pFile != NULL) 4336 { 4337 int rc = vmdkFileGetSize(pImage->pFile, &cbFile); 4159 4338 if (VBOX_SUCCESS(rc)) 4160 4339 cb += cbFile; 4161 4340 for (unsigned i = 0; i <= pImage->cExtents; i++) 4162 4341 { 4163 rc = RTFileGetSize(pImage->File, &cbFile);4342 rc = vmdkFileGetSize(pImage->pFile, &cbFile); 4164 4343 if (VBOX_SUCCESS(rc)) 4165 4344 cb += cbFile; … … 4336 4515 /* Image must be opened and the new flags must be valid. Just readonly flag 4337 4516 * is supported. */ 4338 if (!pImage || uOpenFlags & ~ VD_OPEN_FLAGS_READONLY)4517 if (!pImage || uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_ASYNC_IO)) 4339 4518 { 4340 4519 rc = VERR_INVALID_PARAMETER; … … 4672 4851 } 4673 4852 4853 static bool vmdkIsAsyncIOSupported(void *pvBackendData) 4854 { 4855 PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData; 4856 bool fAsyncIOSupported = false; 4857 4858 if (pImage) 4859 { 4860 /* We only support async I/O support if the image only consists of FLAT or ZERO extents. */ 4861 fAsyncIOSupported = true; 4862 for (unsigned i = 0; i < pImage->cExtents; i++) 4863 { 4864 if ( (pImage->pExtents[i].enmType != VMDKETYPE_FLAT) 4865 && (pImage->pExtents[i].enmType != VMDKETYPE_ZERO)) 4866 { 4867 fAsyncIOSupported = false; 4868 break; /* Stop search */ 4869 } 4870 } 4871 } 4872 4873 return fAsyncIOSupported; 4874 } 4875 4876 static int vmdkAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead, 4877 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser) 4878 { 4879 PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData; 4880 PVMDKEXTENT pExtent; 4881 int rc = VINF_SUCCESS; 4882 unsigned cTasksToSubmit = 0; 4883 PPDMDATASEG paSegCurrent = paSeg; 4884 unsigned cbLeftInCurrentSegment = paSegCurrent->cbSeg; 4885 unsigned uOffsetInCurrentSegment = 0; 4886 4887 Assert(pImage); 4888 Assert(uOffset % 512 == 0); 4889 Assert(cbRead % 512 == 0); 4890 4891 if ( uOffset + cbRead > pImage->cbSize 4892 || cbRead == 0) 4893 { 4894 rc = VERR_INVALID_PARAMETER; 4895 goto out; 4896 } 4897 4898 while (cbRead && cSeg) 4899 { 4900 unsigned cbToRead; 4901 uint64_t uSectorExtentRel; 4902 4903 rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffset), 4904 &pExtent, &uSectorExtentRel); 4905 if (VBOX_FAILURE(rc)) 4906 goto out; 4907 4908 /* Check access permissions as defined in the extent descriptor. */ 4909 if (pExtent->enmAccess == VMDKACCESS_NOACCESS) 4910 { 4911 rc = VERR_VDI_INVALID_STATE; 4912 goto out; 4913 } 4914 4915 /* Clip read range to remain in this extent. */ 4916 cbToRead = RT_MIN(cbRead, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 4917 /* Clip read range to remain into current data segment. */ 4918 cbToRead = RT_MIN(cbToRead, cbLeftInCurrentSegment); 4919 4920 switch (pExtent->enmType) 4921 { 4922 case VMDKETYPE_FLAT: 4923 { 4924 /* Setup new task. */ 4925 void *pTask; 4926 rc = pImage->pInterfaceAsyncIOCallbacks->pfnPrepareRead(pImage->pInterfaceAsyncIO->pvUser, pExtent->pFile->pStorage, 4927 VMDK_SECTOR2BYTE(uSectorExtentRel), 4928 (uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment, 4929 cbToRead, &pTask); 4930 if (VBOX_FAILURE(rc)) 4931 { 4932 AssertMsgFailed(("Preparing read failed rc=%Vrc\n", rc)); 4933 goto out; 4934 } 4935 4936 /* Check for enough room first. */ 4937 if (cTasksToSubmit >= pImage->cTask) 4938 { 4939 /* We reached maximum, resize array. Try to realloc memory first. */ 4940 void **apTaskNew = (void **)RTMemRealloc(pImage->apTask, (cTasksToSubmit + 10)*sizeof(void *)); 4941 4942 if (!apTaskNew) 4943 { 4944 /* We failed. Allocate completely new. */ 4945 apTaskNew = (void **)RTMemAllocZ((cTasksToSubmit + 10)* sizeof(void *)); 4946 if (!apTaskNew) 4947 { 4948 /* Damn, we are out of memory. */ 4949 rc = VERR_NO_MEMORY; 4950 goto out; 4951 } 4952 4953 /* Copy task handles over. */ 4954 for (unsigned i = 0; i < cTasksToSubmit; i++) 4955 apTaskNew[i] = pImage->apTask[i]; 4956 4957 /* Free old memory. */ 4958 RTMemFree(pImage->apTask); 4959 } 4960 4961 pImage->cTask = cTasksToSubmit + 10; 4962 pImage->apTask = apTaskNew; 4963 } 4964 4965 pImage->apTask[cTasksToSubmit] = pTask; 4966 cTasksToSubmit++; 4967 break; 4968 } 4969 case VMDKETYPE_ZERO: 4970 memset((uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment, 0, cbToRead); 4971 break; 4972 default: 4973 AssertMsgFailed(("Unsupported extent type %u\n", pExtent->enmType)); 4974 } 4975 4976 cbRead -= cbToRead; 4977 uOffset += cbToRead; 4978 cbLeftInCurrentSegment -= cbToRead; 4979 uOffsetInCurrentSegment += cbToRead; 4980 /* Go to next extent if there is no space left in current one. */ 4981 if (!cbLeftInCurrentSegment) 4982 { 4983 uOffsetInCurrentSegment = 0; 4984 paSegCurrent++; 4985 cSeg--; 4986 cbLeftInCurrentSegment = paSegCurrent->cbSeg; 4987 } 4988 } 4989 4990 AssertMsg((cSeg >= 0) && (cbRead == 0), ("No segment left but there is still data to read\n")); 4991 4992 if (cTasksToSubmit == 0) 4993 { 4994 /* The request was completely in a ZERO extent nothing to do. */ 4995 rc = VINF_VDI_ASYNC_IO_FINISHED; 4996 } 4997 else 4998 { 4999 /* Submit tasks. */ 5000 rc = pImage->pInterfaceAsyncIOCallbacks->pfnTasksSubmit(pImage->pInterfaceAsyncIO->pvUser, 5001 pImage->apTask, cTasksToSubmit, 5002 NULL, pvUser, 5003 NULL /* Nothing required after read. */); 5004 AssertMsg(VBOX_SUCCESS(rc), ("Failed to enqueue tasks rc=%Vrc\n", rc)); 5005 } 5006 5007 out: 5008 LogFlowFunc(("returns %Vrc\n", rc)); 5009 return rc; 5010 } 5011 5012 static int vmdkAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite, 5013 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser) 5014 { 5015 PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData; 5016 PVMDKEXTENT pExtent; 5017 int rc = VINF_SUCCESS; 5018 unsigned cTasksToSubmit = 0; 5019 PPDMDATASEG paSegCurrent = paSeg; 5020 unsigned cbLeftInCurrentSegment = paSegCurrent->cbSeg; 5021 unsigned uOffsetInCurrentSegment = 0; 5022 5023 Assert(pImage); 5024 Assert(uOffset % 512 == 0); 5025 Assert(cbWrite % 512 == 0); 5026 5027 if ( uOffset + cbWrite > pImage->cbSize 5028 || cbWrite == 0) 5029 { 5030 rc = VERR_INVALID_PARAMETER; 5031 goto out; 5032 } 5033 5034 while (cbWrite && cSeg) 5035 { 5036 unsigned cbToWrite; 5037 uint64_t uSectorExtentRel; 5038 5039 rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffset), 5040 &pExtent, &uSectorExtentRel); 5041 if (VBOX_FAILURE(rc)) 5042 goto out; 5043 5044 /* Check access permissions as defined in the extent descriptor. */ 5045 if (pExtent->enmAccess == VMDKACCESS_NOACCESS) 5046 { 5047 rc = VERR_VDI_INVALID_STATE; 5048 goto out; 5049 } 5050 5051 /* Clip write range to remain in this extent. */ 5052 cbToWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 5053 /* Clip write range to remain into current data segment. */ 5054 cbToWrite = RT_MIN(cbToWrite, cbLeftInCurrentSegment); 5055 5056 switch (pExtent->enmType) 5057 { 5058 case VMDKETYPE_FLAT: 5059 { 5060 /* Setup new task. */ 5061 void *pTask; 5062 rc = pImage->pInterfaceAsyncIOCallbacks->pfnPrepareWrite(pImage->pInterfaceAsyncIO->pvUser, pExtent->pFile->pStorage, 5063 VMDK_SECTOR2BYTE(uSectorExtentRel), 5064 (uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment, 5065 cbToWrite, &pTask); 5066 if (VBOX_FAILURE(rc)) 5067 { 5068 AssertMsgFailed(("Preparing read failed rc=%Vrc\n", rc)); 5069 goto out; 5070 } 5071 5072 /* Check for enough room first. */ 5073 if (cTasksToSubmit >= pImage->cTask) 5074 { 5075 /* We reached maximum, resize array. Try to realloc memory first. */ 5076 void **apTaskNew = (void **)RTMemRealloc(pImage->apTask, (cTasksToSubmit + 10)*sizeof(void *)); 5077 5078 if (!apTaskNew) 5079 { 5080 /* We failed. Allocate completely new. */ 5081 apTaskNew = (void **)RTMemAllocZ((cTasksToSubmit + 10)* sizeof(void *)); 5082 if (!apTaskNew) 5083 { 5084 /* Damn, we are out of memory. */ 5085 rc = VERR_NO_MEMORY; 5086 goto out; 5087 } 5088 5089 /* Copy task handles over. */ 5090 for (unsigned i = 0; i < cTasksToSubmit; i++) 5091 apTaskNew[i] = pImage->apTask[i]; 5092 5093 /* Free old memory. */ 5094 RTMemFree(pImage->apTask); 5095 } 5096 5097 pImage->cTask = cTasksToSubmit + 10; 5098 pImage->apTask = apTaskNew; 5099 } 5100 5101 pImage->apTask[cTasksToSubmit] = pTask; 5102 cTasksToSubmit++; 5103 break; 5104 } 5105 case VMDKETYPE_ZERO: 5106 /* Nothing left to do. */ 5107 break; 5108 default: 5109 AssertMsgFailed(("Unsupported extent type %u\n", pExtent->enmType)); 5110 } 5111 5112 cbWrite -= cbToWrite; 5113 uOffset += cbToWrite; 5114 cbLeftInCurrentSegment -= cbToWrite; 5115 uOffsetInCurrentSegment += cbToWrite; 5116 /* Go to next extent if there is no space left in current one. */ 5117 if (!cbLeftInCurrentSegment) 5118 { 5119 uOffsetInCurrentSegment = 0; 5120 paSegCurrent++; 5121 cSeg--; 5122 cbLeftInCurrentSegment = paSegCurrent->cbSeg; 5123 } 5124 } 5125 5126 AssertMsg((cSeg >= 0) && (cbWrite == 0), ("No segment left but there is still data to read\n")); 5127 5128 if (cTasksToSubmit == 0) 5129 { 5130 /* The request was completely in a ZERO extent nothing to do. */ 5131 rc = VINF_VDI_ASYNC_IO_FINISHED; 5132 } 5133 else 5134 { 5135 /* Submit tasks. */ 5136 rc = pImage->pInterfaceAsyncIOCallbacks->pfnTasksSubmit(pImage->pInterfaceAsyncIO->pvUser, 5137 pImage->apTask, cTasksToSubmit, 5138 NULL, pvUser, 5139 NULL /* Nothing required after read. */); 5140 AssertMsg(VBOX_SUCCESS(rc), ("Failed to enqueue tasks rc=%Vrc\n", rc)); 5141 } 5142 5143 out: 5144 LogFlowFunc(("returns %Vrc\n", rc)); 5145 return rc; 5146 5147 } 5148 5149 4674 5150 VBOXHDDBACKEND g_VmdkBackend = 4675 5151 { … … 4680 5156 /* uBackendCaps */ 4681 5157 VD_CAP_UUID | VD_CAP_CREATE_FIXED | VD_CAP_CREATE_DYNAMIC 4682 | VD_CAP_CREATE_SPLIT_2G | VD_CAP_DIFF | VD_CAP_FILE ,5158 | VD_CAP_CREATE_SPLIT_2G | VD_CAP_DIFF | VD_CAP_FILE |VD_CAP_ASYNC, 4683 5159 /* pfnCheckIfValid */ 4684 5160 vmdkCheckIfValid, … … 4750 5226 vmdkGetParentFilename, 4751 5227 /* pfnSetParentFilename */ 4752 vmdkSetParentFilename 5228 vmdkSetParentFilename, 5229 /* pfnIsAsyncIOSupported */ 5230 vmdkIsAsyncIOSupported, 5231 /* pfnAsyncRead */ 5232 vmdkAsyncRead, 5233 /* pfnAsyncWrite */ 5234 vmdkAsyncWrite 4753 5235 };
Note:
See TracChangeset
for help on using the changeset viewer.