Changeset 27211 in vbox
- Timestamp:
- Mar 9, 2010 12:41:26 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VBoxHDD.cpp
r27134 r27211 300 300 * will give us. 301 301 */ 302 static int vdReadHelper(PVBOXHDD pDisk, PVDIMAGE pImage, uint64_t uOffset,303 void *pvBuf, size_t cbRead)302 static int vdReadHelper(PVBOXHDD pDisk, PVDIMAGE pImage, PVDIMAGE pImageParentOverride, 303 uint64_t uOffset, void *pvBuf, size_t cbRead) 304 304 { 305 305 int rc; … … 313 313 * stale data when different block sizes are used for the images. */ 314 314 cbThisRead = cbRead; 315 rc = VERR_VD_BLOCK_FREE; 316 for (PVDIMAGE pCurrImage = pImage; 317 pCurrImage != NULL && rc == VERR_VD_BLOCK_FREE; 318 pCurrImage = pCurrImage->pPrev) 319 { 320 rc = pCurrImage->Backend->pfnRead(pCurrImage->pvBackendData, 321 uOffset, pvBuf, cbThisRead, 322 &cbThisRead); 315 316 /* 317 * Try to read from the given image. 318 * If the block is not allocated read from override chain if present. 319 */ 320 rc = pImage->Backend->pfnRead(pImage->pvBackendData, 321 uOffset, pvBuf, cbThisRead, 322 &cbThisRead); 323 324 if (rc == VERR_VD_BLOCK_FREE) 325 { 326 for (PVDIMAGE pCurrImage = pImageParentOverride ? pImageParentOverride : pImage->pPrev; 327 pCurrImage != NULL && rc == VERR_VD_BLOCK_FREE; 328 pCurrImage = pCurrImage->pPrev) 329 { 330 rc = pCurrImage->Backend->pfnRead(pCurrImage->pvBackendData, 331 uOffset, pvBuf, cbThisRead, 332 &cbThisRead); 333 } 323 334 } 324 335 … … 345 356 { 346 357 PVDPARENTSTATEDESC pParentState = (PVDPARENTSTATEDESC)pvUser; 347 return vdReadHelper(pParentState->pDisk, pParentState->pImage, uOffset,358 return vdReadHelper(pParentState->pDisk, pParentState->pImage, NULL, uOffset, 348 359 pvBuf, cbRead); 349 360 } … … 395 406 */ 396 407 static int vdWriteHelperStandard(PVBOXHDD pDisk, PVDIMAGE pImage, 408 PVDIMAGE pImageParentOverride, 397 409 uint64_t uOffset, size_t cbWrite, 398 410 size_t cbThisWrite, size_t cbPreRead, … … 405 417 if (cbPreRead) 406 418 { 407 rc = vdReadHelper(pDisk, pImage, uOffset - cbPreRead, pvTmp,408 cbPreRead);419 rc = vdReadHelper(pDisk, pImage, pImageParentOverride, 420 uOffset - cbPreRead, pvTmp, cbPreRead); 409 421 if (RT_FAILURE(rc)) 410 422 return rc; … … 440 452 (char *)pvBuf + cbThisWrite, cbWriteCopy); 441 453 if (cbReadImage) 442 rc = vdReadHelper(pDisk, pImage, 454 rc = vdReadHelper(pDisk, pImage, pImageParentOverride, 443 455 uOffset + cbThisWrite + cbWriteCopy, 444 456 (char *)pvTmp + cbPreRead + cbThisWrite + cbWriteCopy, … … 472 484 */ 473 485 static int vdWriteHelperOptimized(PVBOXHDD pDisk, PVDIMAGE pImage, 486 PVDIMAGE pImageParentOverride, 474 487 uint64_t uOffset, size_t cbWrite, 475 488 size_t cbThisWrite, size_t cbPreRead, … … 501 514 /* Read the entire data of the block so that we can compare whether it will 502 515 * be modified by the write or not. */ 503 rc = vdReadHelper(pDisk, pImage, uOffset - cbPreRead, pvTmp,516 rc = vdReadHelper(pDisk, pImage, pImageParentOverride, uOffset - cbPreRead, pvTmp, 504 517 cbPreRead + cbThisWrite + cbPostRead - cbFill); 505 518 if (RT_FAILURE(rc)) … … 548 561 * write optimizations. 549 562 */ 550 static int vdWriteHelper(PVBOXHDD pDisk, PVDIMAGE pImage, uint64_t uOffset,551 const void *pvBuf, size_t cbWrite)563 static int vdWriteHelper(PVBOXHDD pDisk, PVDIMAGE pImage, PVDIMAGE pImageParentOverride, 564 uint64_t uOffset, const void *pvBuf, size_t cbWrite) 552 565 { 553 566 int rc; … … 580 593 /* Optimized write, suppress writing to a so far unallocated 581 594 * block if the data is in fact not changed. */ 582 rc = vdWriteHelperOptimized(pDisk, pImage, uOffset, cbWrite, 595 rc = vdWriteHelperOptimized(pDisk, pImage, pImageParentOverride, 596 uOffset, cbWrite, 583 597 cbThisWrite, cbPreRead, cbPostRead, 584 598 pvBuf, pvTmp); … … 590 604 * backend has some further optimization enabled) cause the 591 605 * block to be allocated. */ 592 rc = vdWriteHelperStandard(pDisk, pImage, uOffset, cbWrite, 606 rc = vdWriteHelperStandard(pDisk, pImage, pImageParentOverride, 607 uOffset, cbWrite, 593 608 cbThisWrite, cbPreRead, cbPostRead, 594 609 pvBuf, pvTmp); … … 1839 1854 return rc; 1840 1855 } 1856 1841 1857 1842 1858 /** … … 1944 1960 if (RT_FAILURE(rc)) 1945 1961 break; 1946 rc = vdWriteHelper(pDisk, pImageTo, uOffset, pvBuf, 1962 rc = vdWriteHelper(pDisk, pImageTo, pImageFrom->pPrev, 1963 uOffset, pvBuf, 1947 1964 cbThisRead); 1948 1965 if (RT_FAILURE(rc)) … … 1970 1987 else 1971 1988 { 1989 /* 1990 * We may need to update the parent uuid of the child coming after the 1991 * last image to be merged. We have to reopen it read/write. 1992 * 1993 * This is done before we do the actual merge to prevent an incosistent 1994 * chain if the mode change fails for some reason. 1995 */ 1996 if (pImageFrom->pNext) 1997 { 1998 PVDIMAGE pImageChild = pImageFrom->pNext; 1999 2000 /* We need to open the image in read/write mode. */ 2001 uOpenFlags = pImageChild->Backend->pfnGetOpenFlags(pImageChild->pvBackendData); 2002 2003 if (uOpenFlags & VD_OPEN_FLAGS_READONLY) 2004 { 2005 uOpenFlags &= ~VD_OPEN_FLAGS_READONLY; 2006 rc = pImageChild->Backend->pfnSetOpenFlags(pImageChild->pvBackendData, 2007 uOpenFlags); 2008 if (RT_FAILURE(rc)) 2009 break; 2010 } 2011 } 2012 1972 2013 /* Merge child state into parent. This means writing all blocks 1973 2014 * which are allocated in the image up to the source image to the … … 1996 2037 if (RT_FAILURE(rc)) 1997 2038 break; 1998 rc = vdWriteHelper(pDisk, pImageTo, uOffset, pvBuf,2039 rc = vdWriteHelper(pDisk, pImageTo, NULL, uOffset, pvBuf, 1999 2040 cbThisRead); 2000 2041 if (RT_FAILURE(rc)) … … 2036 2077 else 2037 2078 { 2079 /* Update the parent uuid of the child of the last merged image. */ 2038 2080 if (pImageFrom->pNext) 2039 2081 { … … 2041 2083 &Uuid); 2042 2084 AssertRC(rc); 2085 2043 2086 rc = pImageFrom->Backend->pfnSetParentUuid(pImageFrom->pNext->pvBackendData, 2044 2087 &Uuid); 2045 2088 AssertRC(rc); 2089 2090 /* Reopen readonly if neccessary */ 2091 if (pImageFrom->pNext != pDisk->pLast) 2092 { 2093 PVDIMAGE pImageChild = pImageFrom->pNext; 2094 2095 uOpenFlags = pImageChild->Backend->pfnGetOpenFlags(pImageChild->pvBackendData); 2096 uOpenFlags |= VD_OPEN_FLAGS_READONLY; 2097 rc = pImageChild->Backend->pfnSetOpenFlags(pImageChild->pvBackendData, 2098 uOpenFlags); 2099 /** @todo: What to do if this fails?. Breaking would 2100 * prevent the merged images from being removed 2101 * from the chain possibly causing inconsistent behavior. 2102 */ 2103 if (RT_FAILURE(rc)) 2104 break; 2105 } 2046 2106 } 2047 2107 } … … 2308 2368 size_t cbThisRead = RT_MIN(VD_MERGE_BUFFER_SIZE, cbRemaining); 2309 2369 2310 rc = vdReadHelper(pDiskFrom, pImageFrom, uOffset, pvBuf,2370 rc = vdReadHelper(pDiskFrom, pImageFrom, NULL, uOffset, pvBuf, 2311 2371 cbThisRead); 2312 2372 if (RT_FAILURE(rc)) 2313 2373 break; 2314 2374 2315 rc = vdWriteHelper(pDiskTo, pImageTo, uOffset, pvBuf,2375 rc = vdWriteHelper(pDiskTo, pImageTo, NULL, uOffset, pvBuf, 2316 2376 cbThisRead); 2317 2377 if (RT_FAILURE(rc)) … … 2650 2710 AssertPtrBreakStmt(pImage, rc = VERR_VD_NOT_OPENED); 2651 2711 2652 rc = vdReadHelper(pDisk, pImage, uOffset, pvBuf, cbRead);2712 rc = vdReadHelper(pDisk, pImage, NULL, uOffset, pvBuf, cbRead); 2653 2713 } while (0); 2654 2714 … … 2697 2757 2698 2758 vdSetModifiedFlag(pDisk); 2699 rc = vdWriteHelper(pDisk, pImage, uOffset, pvBuf, cbWrite);2759 rc = vdWriteHelper(pDisk, pImage, NULL, uOffset, pvBuf, cbWrite); 2700 2760 } while (0); 2701 2761
Note:
See TracChangeset
for help on using the changeset viewer.