- Timestamp:
- Oct 27, 2010 8:24:45 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VCICacheCore.cpp
r32688 r33481 27 27 #include <iprt/alloc.h> 28 28 #include <iprt/file.h> 29 #include <iprt/asm.h> 29 30 30 31 /******************************************************************************* … … 155 156 AssertCompileSize(VciTreeNode, 8 * VCI_BLOCK_SIZE); 156 157 157 /** Node type: Root of the tree (VciTreeNodeInternal). */158 #define VCI_TREE_NODE_TYPE_ROOT UINT32_C(0x00000001)159 158 /** Node type: Internal node containing links to other nodes (VciTreeNodeInternal). */ 160 #define VCI_TREE_NODE_TYPE_INTERNAL UINT 32_C(0x00000002)159 #define VCI_TREE_NODE_TYPE_INTERNAL UINT8_C(0x00000001) 161 160 /** Node type: Leaf of the tree (VciCacheExtent). */ 162 #define VCI_TREE_NODE_TYPE_LEAF UINT32_C(0x00000003) 161 #define VCI_TREE_NODE_TYPE_LEAF UINT8_C(0x00000002) 162 163 /** Number of cache extents described by one node. */ 164 #define VCI_TREE_EXTENTS_PER_NODE (sizeof(VciTreeNode)-1 / sizeof(VciCacheExtent)) 165 /** Number of internal nodes managed by one tree node. */ 166 #define VCI_TREE_INTERNAL_NODES_PER_NODE (sizeof(VciTreeNode)-1 / sizeof(VciTreeNodeInternal)) 163 167 164 168 /** … … 236 240 PVCIBLKRANGEDESC pRangesTail; 237 241 238 /** Pointer to the block bitmap. */239 VciBlkMapEnt *pBlkBitmap;240 242 } VCIBLKMAP; 241 243 /** Pointer to a block map. */ 242 244 typedef VCIBLKMAP *PVCIBLKMAP; 245 246 /** 247 * B+-Tree node header. 248 */ 249 typedef struct VCITREENODE 250 { 251 /** Type of the node (VCI_TREE_NODE_TYPE_*). */ 252 uint8_t u8Type; 253 /** Block address where the node is stored. */ 254 uint64_t u64BlockAddr; 255 /** Pointer to the parent. */ 256 struct VCITREENODE *pParent; 257 } VCITREENODE, *PVCITREENODE; 258 259 /** 260 * B+-Tree node pointer. 261 */ 262 typedef struct VCITREENODEPTR 263 { 264 /** Flag whether the node is in memory or still on the disk. */ 265 bool fInMemory; 266 /** Type dependent data. */ 267 union 268 { 269 /** Pointer to a in memory node. */ 270 PVCITREENODE pNode; 271 /** Start block address of the node. */ 272 uint64_t offAddrBlockNode; 273 } u; 274 } VCITREENODEPTR, *PVCITREENODEPTR; 275 276 /** 277 * Internal node. 278 */ 279 typedef struct VCINODEINTERNAL 280 { 281 /** First block of cached data the internal node represents. */ 282 uint64_t u64BlockOffset; 283 /** Number of blocks the internal node represents. */ 284 uint32_t u32Blocks; 285 /** Pointer to the child node. */ 286 VCITREENODEPTR PtrChild; 287 } VCINODEINTERNAL, *PVCINODEINTERNAL; 288 289 /** 290 * A in memory internal B+-tree node. 291 */ 292 typedef struct VCITREENODEINT 293 { 294 /** Node core. */ 295 VCITREENODE Core; 296 /** Number of used nodes. */ 297 unsigned cUsedNodes; 298 /** Array of internal nodes. */ 299 VCINODEINTERNAL aIntNodes[VCI_TREE_INTERNAL_NODES_PER_NODE]; 300 } VCITREENODEINT, *PVCITREENODEINT; 301 302 /** 303 * A in memory cache extent. 304 */ 305 typedef struct VCICACHEEXTENT 306 { 307 /** First block of cached data the extent represents. */ 308 uint64_t u64BlockOffset; 309 /** Number of blocks the extent represents. */ 310 uint32_t u32Blocks; 311 /** First block in the image where the data is stored. */ 312 uint64_t u64BlockAddr; 313 } VCICACHEEXTENT, *PVCICACHEEXTENT; 314 315 /** 316 * A in memory leaf B+-tree node. 317 */ 318 typedef struct VCITREENODELEAF 319 { 320 /** Node core. */ 321 VCITREENODE Core; 322 /** Number of used nodes. */ 323 unsigned cUsedNodes; 324 /** The extents in the node. */ 325 VCICACHEEXTENT aExtents[VCI_TREE_EXTENTS_PER_NODE]; 326 } VCITREENODELEAF, *PVCITREENODELEAF; 243 327 244 328 /** … … 275 359 /** Offset of the B+-Tree in the image in bytes. */ 276 360 uint64_t offTreeRoot; 277 /** @todo Pointer to the root of the tree in memory. */ 278 279 361 /** Pointer to the root node of the B+-Tree. */ 362 PVCITREENODE pRoot; 280 363 /** Offset to the block allocation bitmap in bytes. */ 281 364 uint64_t offBlksBitmap; … … 284 367 } VCICACHE, *PVCICACHE; 285 368 369 /** No block free in bitmap error code. */ 370 #define VERR_VCI_NO_BLOCKS_FREE (-65536) 371 286 372 /******************************************************************************* 287 373 * Static Variables * … … 302 388 * Internal: signal an error to the frontend. 303 389 */ 304 DECLINLINE(int) vciError(PVCICACHE p Image, int rc, RT_SRC_POS_DECL,390 DECLINLINE(int) vciError(PVCICACHE pCache, int rc, RT_SRC_POS_DECL, 305 391 const char *pszFormat, ...) 306 392 { 307 393 va_list va; 308 394 va_start(va, pszFormat); 309 if (p Image->pInterfaceError)310 p Image->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS,395 if (pCache->pInterfaceError) 396 pCache->pInterfaceErrorCallbacks->pfnError(pCache->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS, 311 397 pszFormat, va); 312 398 va_end(va); … … 317 403 * Internal: signal an informational message to the frontend. 318 404 */ 319 DECLINLINE(int) vciMessage(PVCICACHE p Image, const char *pszFormat, ...)405 DECLINLINE(int) vciMessage(PVCICACHE pCache, const char *pszFormat, ...) 320 406 { 321 407 int rc = VINF_SUCCESS; 322 408 va_list va; 323 409 va_start(va, pszFormat); 324 if (p Image->pInterfaceError)325 rc = p Image->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser,410 if (pCache->pInterfaceError) 411 rc = pCache->pInterfaceErrorCallbacks->pfnMessage(pCache->pInterfaceError->pvUser, 326 412 pszFormat, va); 327 413 va_end(va); … … 330 416 331 417 332 DECLINLINE(int) vciFileOpen(PVCICACHE p Image, const char *pszFilename,418 DECLINLINE(int) vciFileOpen(PVCICACHE pCache, const char *pszFilename, 333 419 uint32_t fOpen) 334 420 { 335 return p Image->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,421 return pCache->pInterfaceIOCallbacks->pfnOpen(pCache->pInterfaceIO->pvUser, 336 422 pszFilename, fOpen, 337 &p Image->pStorage);338 } 339 340 DECLINLINE(int) vciFileClose(PVCICACHE p Image)341 { 342 return p Image->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,343 p Image->pStorage);344 } 345 346 DECLINLINE(int) vciFileDelete(PVCICACHE p Image, const char *pszFilename)347 { 348 return p Image->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser,423 &pCache->pStorage); 424 } 425 426 DECLINLINE(int) vciFileClose(PVCICACHE pCache) 427 { 428 return pCache->pInterfaceIOCallbacks->pfnClose(pCache->pInterfaceIO->pvUser, 429 pCache->pStorage); 430 } 431 432 DECLINLINE(int) vciFileDelete(PVCICACHE pCache, const char *pszFilename) 433 { 434 return pCache->pInterfaceIOCallbacks->pfnDelete(pCache->pInterfaceIO->pvUser, 349 435 pszFilename); 350 436 } 351 437 352 DECLINLINE(int) vciFileMove(PVCICACHE p Image, const char *pszSrc,438 DECLINLINE(int) vciFileMove(PVCICACHE pCache, const char *pszSrc, 353 439 const char *pszDst, unsigned fMove) 354 440 { 355 return p Image->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser,441 return pCache->pInterfaceIOCallbacks->pfnMove(pCache->pInterfaceIO->pvUser, 356 442 pszSrc, pszDst, fMove); 357 443 } 358 444 359 DECLINLINE(int) vciFileGetFreeSpace(PVCICACHE p Image, const char *pszFilename,445 DECLINLINE(int) vciFileGetFreeSpace(PVCICACHE pCache, const char *pszFilename, 360 446 int64_t *pcbFree) 361 447 { 362 return p Image->pInterfaceIOCallbacks->pfnGetFreeSpace(pImage->pInterfaceIO->pvUser,448 return pCache->pInterfaceIOCallbacks->pfnGetFreeSpace(pCache->pInterfaceIO->pvUser, 363 449 pszFilename, pcbFree); 364 450 } 365 451 366 DECLINLINE(int) vciFileGetSize(PVCICACHE p Image, uint64_t *pcbSize)367 { 368 return p Image->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,369 p Image->pStorage, pcbSize);370 } 371 372 DECLINLINE(int) vciFileSetSize(PVCICACHE p Image, uint64_t cbSize)373 { 374 return p Image->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,375 p Image->pStorage, cbSize);376 } 377 378 DECLINLINE(int) vciFileWriteSync(PVCICACHE p Image, uint64_t uOffset,452 DECLINLINE(int) vciFileGetSize(PVCICACHE pCache, uint64_t *pcbSize) 453 { 454 return pCache->pInterfaceIOCallbacks->pfnGetSize(pCache->pInterfaceIO->pvUser, 455 pCache->pStorage, pcbSize); 456 } 457 458 DECLINLINE(int) vciFileSetSize(PVCICACHE pCache, uint64_t cbSize) 459 { 460 return pCache->pInterfaceIOCallbacks->pfnSetSize(pCache->pInterfaceIO->pvUser, 461 pCache->pStorage, cbSize); 462 } 463 464 DECLINLINE(int) vciFileWriteSync(PVCICACHE pCache, uint64_t uOffset, 379 465 const void *pvBuffer, size_t cbBuffer) 380 466 { 381 return p Image->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,382 p Image->pStorage, uOffset,467 return pCache->pInterfaceIOCallbacks->pfnWriteSync(pCache->pInterfaceIO->pvUser, 468 pCache->pStorage, uOffset, 383 469 pvBuffer, cbBuffer, NULL); 384 470 } 385 471 386 DECLINLINE(int) vciFileReadSync(PVCICACHE p Image, uint64_t uOffset,472 DECLINLINE(int) vciFileReadSync(PVCICACHE pCache, uint64_t uOffset, 387 473 void *pvBuffer, size_t cbBuffer) 388 474 { 389 return p Image->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,390 p Image->pStorage, uOffset,475 return pCache->pInterfaceIOCallbacks->pfnReadSync(pCache->pInterfaceIO->pvUser, 476 pCache->pStorage, uOffset, 391 477 pvBuffer, cbBuffer, NULL); 392 478 } 393 479 394 DECLINLINE(int) vciFileFlushSync(PVCICACHE p Image)395 { 396 return p Image->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,397 p Image->pStorage);398 } 399 400 DECLINLINE(int) vciFileReadUserAsync(PVCICACHE p Image, uint64_t uOffset,480 DECLINLINE(int) vciFileFlushSync(PVCICACHE pCache) 481 { 482 return pCache->pInterfaceIOCallbacks->pfnFlushSync(pCache->pInterfaceIO->pvUser, 483 pCache->pStorage); 484 } 485 486 DECLINLINE(int) vciFileReadUserAsync(PVCICACHE pCache, uint64_t uOffset, 401 487 PVDIOCTX pIoCtx, size_t cbRead) 402 488 { 403 return p Image->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,404 p Image->pStorage,489 return pCache->pInterfaceIOCallbacks->pfnReadUserAsync(pCache->pInterfaceIO->pvUser, 490 pCache->pStorage, 405 491 uOffset, pIoCtx, 406 492 cbRead); 407 493 } 408 494 409 DECLINLINE(int) vciFileWriteUserAsync(PVCICACHE p Image, uint64_t uOffset,495 DECLINLINE(int) vciFileWriteUserAsync(PVCICACHE pCache, uint64_t uOffset, 410 496 PVDIOCTX pIoCtx, size_t cbWrite, 411 497 PFNVDXFERCOMPLETED pfnComplete, 412 498 void *pvCompleteUser) 413 499 { 414 return p Image->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,415 p Image->pStorage,500 return pCache->pInterfaceIOCallbacks->pfnWriteUserAsync(pCache->pInterfaceIO->pvUser, 501 pCache->pStorage, 416 502 uOffset, pIoCtx, 417 503 cbWrite, … … 420 506 } 421 507 422 DECLINLINE(int) vciFileFlushAsync(PVCICACHE p Image, PVDIOCTX pIoCtx,508 DECLINLINE(int) vciFileFlushAsync(PVCICACHE pCache, PVDIOCTX pIoCtx, 423 509 PFNVDXFERCOMPLETED pfnComplete, 424 510 void *pvCompleteUser) 425 511 { 426 return p Image->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser,427 p Image->pStorage,512 return pCache->pInterfaceIOCallbacks->pfnFlushAsync(pCache->pInterfaceIO->pvUser, 513 pCache->pStorage, 428 514 pIoCtx, pfnComplete, 429 515 pvCompleteUser); … … 433 519 * Internal. Flush image data to disk. 434 520 */ 435 static int vciFlushImage(PVCICACHE p Image)521 static int vciFlushImage(PVCICACHE pCache) 436 522 { 437 523 int rc = VINF_SUCCESS; 438 524 439 if ( p Image->pStorage440 && !(p Image->uOpenFlags & VD_OPEN_FLAGS_READONLY))441 rc = vciFileFlushSync(p Image);442 443 return rc; 444 } 445 446 /** 447 * Internal. Free all allocated space for representing an image except p Image,525 if ( pCache->pStorage 526 && !(pCache->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 527 rc = vciFileFlushSync(pCache); 528 529 return rc; 530 } 531 532 /** 533 * Internal. Free all allocated space for representing an image except pCache, 448 534 * and optionally delete the image from disk. 449 535 */ 450 static int vciFreeImage(PVCICACHE p Image, bool fDelete)536 static int vciFreeImage(PVCICACHE pCache, bool fDelete) 451 537 { 452 538 int rc = VINF_SUCCESS; … … 454 540 /* Freeing a never allocated image (e.g. because the open failed) is 455 541 * not signalled as an error. After all nothing bad happens. */ 456 if (p Image)457 { 458 if (p Image->pStorage)542 if (pCache) 543 { 544 if (pCache->pStorage) 459 545 { 460 546 /* No point updating the file that is deleted anyway. */ 461 547 if (!fDelete) 462 vciFlushImage(p Image);463 464 vciFileClose(p Image);465 p Image->pStorage = NULL;466 } 467 468 if (fDelete && p Image->pszFilename)469 vciFileDelete(p Image, pImage->pszFilename);548 vciFlushImage(pCache); 549 550 vciFileClose(pCache); 551 pCache->pStorage = NULL; 552 } 553 554 if (fDelete && pCache->pszFilename) 555 vciFileDelete(pCache, pCache->pszFilename); 470 556 } 471 557 … … 490 576 uint32_t cbBlkMap = RT_ALIGN_Z(cBlocks / sizeof(VciBlkMapEnt) / 8, VCI_BLOCK_SIZE); 491 577 PVCIBLKMAP pBlkMap = (PVCIBLKMAP)RTMemAllocZ(sizeof(VCIBLKMAP)); 492 VciBlkMapEnt *pBlkBitmap = (VciBlkMapEnt *)RTMemAllocZ(cbBlkMap);493 578 PVCIBLKRANGEDESC pFree = (PVCIBLKRANGEDESC)RTMemAllocZ(sizeof(VCIBLKRANGEDESC)); 494 579 495 580 LogFlowFunc(("cBlocks=%u ppBlkMap=%#p pcBlkMap=%#p\n", cBlocks, ppBlkMap, pcBlkMap)); 496 581 497 if (pBlkMap && p BlkBitmap && pFree)582 if (pBlkMap && pFree) 498 583 { 499 584 pBlkMap->cBlocks = cBlocks; … … 501 586 pBlkMap->cBlocksAllocData = 0; 502 587 pBlkMap->cBlocksFree = cBlocks; 503 pBlkMap->pBlkBitmap = pBlkBitmap;504 588 505 589 pFree->pPrev = NULL; … … 520 604 if (pBlkMap) 521 605 RTMemFree(pBlkMap); 522 if (pBlkBitmap)523 RTMemFree(pBlkBitmap);524 606 if (pFree) 525 607 RTMemFree(pFree); … … 553 635 } 554 636 555 RTMemFree(pBlkMap->pBlkBitmap);556 637 RTMemFree(pBlkMap); 557 638 … … 581 662 cBlkMap -= VCI_BYTE2BLOCK(sizeof(VciBlkMap)); 582 663 583 rc = vciFileReadSync(pStorage, offBlkMap, &BlkMap, VCI_BYTE2BLOCK(sizeof(VciBlkMap)));664 rc = vciFileReadSync(pStorage, VCI_BLOCK2BYTE(offBlkMap), &BlkMap, VCI_BYTE2BLOCK(sizeof(VciBlkMap))); 584 665 if (RT_SUCCESS(rc)) 585 666 { … … 606 687 pBlkMap->cBlocksAllocData = BlkMap.cBlocksAllocData; 607 688 608 pBlkMap->pBlkBitmap = (VciBlkMapEnt *)RTMemAllocZ(pBlkMap->cBlocks / 8); 609 if (pBlkMap->pBlkBitmap) 689 /* Load the bitmap and construct the range list. */ 690 uint32_t cBlocksFree = 0; 691 uint32_t cBlocksAllocated = 0; 692 PVCIBLKRANGEDESC pRangeCur = (PVCIBLKRANGEDESC)RTMemAllocZ(sizeof(VCIBLKRANGEDESC)); 693 694 if (pRangeCur) 610 695 { 611 rc = vciFileReadSync(pStorage, offBlkMap, pBlkMap->pBlkBitmap, cBlkMap); 696 uint8_t abBitmapBuffer[16 * _1K]; 697 uint32_t cBlocksRead = 0; 698 int iBit = 0; 699 uint64_t cBlocksLeft = pBlkMap->cBlocks; 700 701 cBlocksRead = RT_MIN(VCI_BYTE2BLOCK(sizeof(abBitmapBuffer)), cBlocksLeft); 702 rc = vciFileReadSync(pStorage, VCI_BLOCK2BYTE(offBlkMap), abBitmapBuffer, 703 VCI_BLOCK2BYTE(cBlocksRead)); 704 612 705 if (RT_SUCCESS(rc)) 613 706 { 614 *ppBlkMap = pBlkMap; 615 LogFlowFunc(("return success\n")); 616 return VINF_SUCCESS; 707 pRangeCur->fFree = !(abBitmapBuffer[0] & 0x01); 708 pRangeCur->offAddrStart = 0; 709 pRangeCur->cBlocks = 0; 710 pRangeCur->pNext = NULL; 711 pRangeCur->pPrev = NULL; 712 pBlkMap->pRangesHead = pRangeCur; 713 pBlkMap->pRangesTail = pRangeCur; 617 714 } 618 715 619 RTMemFree(pBlkMap->pBlkBitmap); 716 while ( RT_SUCCESS(rc) 717 && cBlocksLeft) 718 { 719 while (cBlocksRead) 720 { 721 if (pRangeCur->fFree) 722 { 723 /* Check for the first set bit. */ 724 } 725 else 726 { 727 /* Check for the first free bit. */ 728 } 729 730 if (iBit == -1) 731 { 732 /* No change. */ 733 pRangeCur->cBlocks += cBlocksRead; 734 cBlocksRead = 0; 735 } 736 else 737 { 738 /* Create a new range descriptor. */ 739 } 740 } 741 cBlocksLeft -= cBlocksRead; 742 offBlkMap += cBlocksRead; 743 744 if (cBlocksLeft) 745 { 746 /* Read next chunk. */ 747 } 748 } 620 749 } 621 750 else 622 751 rc = VERR_NO_MEMORY; 623 752 624 RTMemFree(pBlkMap); 753 if (RT_SUCCESS(rc)) 754 { 755 *ppBlkMap = pBlkMap; 756 LogFlowFunc(("return success\n")); 757 return VINF_SUCCESS; 758 } 759 else 760 RTMemFree(pBlkMap); 625 761 } 626 762 else … … 671 807 BlkMap.cBlocksAllocData = RT_H2LE_U32(pBlkMap->cBlocksAllocData); 672 808 673 rc = vciFileWriteSync(pStorage, offBlkMap, &BlkMap, VCI_BYTE2BLOCK(sizeof(VciBlkMap)));809 rc = vciFileWriteSync(pStorage, VCI_BLOCK2BYTE(offBlkMap), &BlkMap, VCI_BYTE2BLOCK(sizeof(VciBlkMap))); 674 810 if (RT_SUCCESS(rc)) 675 811 { 812 uint8_t abBitmapBuffer[16*_1K]; 813 unsigned iBit = 0; 814 PVCIBLKRANGEDESC pCur = pBlkMap->pRangesHead; 815 676 816 offBlkMap += VCI_BYTE2BLOCK(sizeof(VciBlkMap)); 677 rc = vciFileWriteSync(pStorage, offBlkMap, pBlkMap->pBlkBitmap, pBlkMap->cBlocks / 8); 817 818 /* Write the descriptor ranges. */ 819 while (pCur) 820 { 821 uint64_t cBlocks = pCur->cBlocks; 822 823 while (cBlocks) 824 { 825 uint64_t cBlocksMax = RT_MIN(cBlocks, sizeof(abBitmapBuffer) * 8 - iBit); 826 827 if (pCur->fFree) 828 ASMBitClearRange(abBitmapBuffer, iBit, iBit + cBlocksMax); 829 else 830 ASMBitSetRange(abBitmapBuffer, iBit, iBit + cBlocksMax); 831 832 iBit += cBlocksMax; 833 cBlocks -= cBlocksMax; 834 835 if (iBit == sizeof(abBitmapBuffer) * 8) 836 { 837 /* Buffer is full, write to file and reset. */ 838 rc = vciFileWriteSync(pStorage, offBlkMap, abBitmapBuffer, sizeof(abBitmapBuffer)); 839 if (RT_FAILURE(rc)) 840 break; 841 842 offBlkMap += VCI_BYTE2BLOCK(sizeof(abBitmapBuffer)); 843 iBit = 0; 844 } 845 } 846 847 pCur = pCur->pNext; 848 } 849 850 Assert(iBit % 8 == 0); 851 852 if (RT_SUCCESS(rc) && iBit) 853 rc = vciFileWriteSync(pStorage, offBlkMap, abBitmapBuffer, iBit / 8); 678 854 } 679 855 } … … 683 859 LogFlowFunc(("returns rc=%Rrc\n", rc)); 684 860 return rc; 861 } 862 863 /** 864 * Finds the range block describing the given block address. 865 * 866 * @returns Pointer to the block range descriptor or NULL if none could be found. 867 * @param pBlkMap The block bitmap to search on. 868 * @param offBlockAddr The block address to search for. 869 */ 870 static PVCIBLKRANGEDESC vciBlkMapFindByBlock(PVCIBLKMAP pBlkMap, uint64_t offBlockAddr) 871 { 872 PVCIBLKRANGEDESC pBlk = pBlkMap->pRangesHead; 873 874 while ( pBlk 875 && pBlk->offAddrStart < offBlockAddr) 876 pBlk = pBlk->pNext; 877 878 return pBlk; 685 879 } 686 880 … … 695 889 static int vciBlkMapAllocate(PVCIBLKMAP pBlkMap, uint32_t cBlocks, uint64_t *poffBlockAddr) 696 890 { 891 PVCIBLKRANGEDESC pBestFit = NULL; 892 PVCIBLKRANGEDESC pCur = NULL; 697 893 int rc = VINF_SUCCESS; 698 894 699 895 LogFlowFunc(("pBlkMap=%#p cBlocks=%u poffBlockAddr=%#p\n", 700 896 pBlkMap, cBlocks, poffBlockAddr)); 897 898 pCur = pBlkMap->pRangesHead; 899 900 while (pCur) 901 { 902 if ( pCur->fFree 903 && pCur->cBlocks >= cBlocks) 904 { 905 if ( !pBestFit 906 || pCur->cBlocks < pBestFit->cBlocks) 907 { 908 pBestFit = pCur; 909 /* Stop searching if the size is matching exactly. */ 910 if (pBestFit->cBlocks == cBlocks) 911 break; 912 } 913 } 914 pCur = pCur->pNext; 915 } 916 917 Assert(!pBestFit || pBestFit->fFree); 918 919 if (pBestFit) 920 { 921 pBestFit->fFree = false; 922 923 if (pBestFit->cBlocks > cBlocks) 924 { 925 /* Create a new free block. */ 926 PVCIBLKRANGEDESC pFree = (PVCIBLKRANGEDESC)RTMemAllocZ(sizeof(VCIBLKRANGEDESC)); 927 928 if (pFree) 929 { 930 pFree->fFree = true; 931 pFree->cBlocks = pBestFit->cBlocks - cBlocks; 932 pFree->offAddrStart = pBestFit->offAddrStart + cBlocks; 933 934 /* Link into the list. */ 935 pFree->pNext = pBestFit->pNext; 936 pBestFit->pNext = pFree; 937 pFree->pPrev = pBestFit; 938 if (!pFree->pNext) 939 pBlkMap->pRangesTail = pFree; 940 941 *poffBlockAddr = pBestFit->offAddrStart; 942 } 943 else 944 { 945 rc = VERR_NO_MEMORY; 946 pBestFit->fFree = true; 947 } 948 } 949 } 950 else 951 rc = VERR_VCI_NO_BLOCKS_FREE; 701 952 702 953 LogFlowFunc(("returns rc=%Rrc offBlockAddr=%llu\n", rc, *poffBlockAddr)); … … 721 972 pBlkMap, cBlocksNew, offBlockAddrOld, poffBlockAddr)); 722 973 974 AssertMsgFailed(("Implement\n")); 975 723 976 LogFlowFunc(("returns rc=%Rrc offBlockAddr=%llu\n", rc, *poffBlockAddr)); 724 977 return rc; … … 735 988 static void vciBlkMapFree(PVCIBLKMAP pBlkMap, uint64_t offBlockAddr, uint32_t cBlocks) 736 989 { 990 PVCIBLKRANGEDESC pBlk; 991 737 992 LogFlowFunc(("pBlkMap=%#p offBlockAddr=%llu cBlocks=%u\n", 738 993 pBlkMap, offBlockAddr, cBlocks)); 739 994 995 while (cBlocks) 996 { 997 pBlk = vciBlkMapFindByBlock(pBlkMap, offBlockAddr); 998 AssertPtr(pBlk); 999 1000 /* Easy case, the whole block is freed. */ 1001 if ( pBlk->offAddrStart == offBlockAddr 1002 && pBlk->cBlocks <= cBlocks) 1003 { 1004 pBlk->fFree = true; 1005 cBlocks -= pBlk->cBlocks; 1006 offBlockAddr += pBlk->cBlocks; 1007 1008 /* Check if it is possible to merge free blocks. */ 1009 if ( pBlk->pPrev 1010 && pBlk->pPrev->fFree) 1011 { 1012 PVCIBLKRANGEDESC pBlkPrev = pBlk->pPrev; 1013 1014 Assert(pBlkPrev->offAddrStart + pBlkPrev->cBlocks == pBlk->offAddrStart); 1015 pBlkPrev->cBlocks += pBlk->cBlocks; 1016 pBlkPrev->pNext = pBlk->pNext; 1017 if (pBlk->pNext) 1018 pBlk->pNext->pPrev = pBlkPrev; 1019 else 1020 pBlkMap->pRangesTail = pBlkPrev; 1021 1022 RTMemFree(pBlk); 1023 pBlk = pBlkPrev; 1024 } 1025 1026 /* Now the one to the right. */ 1027 if ( pBlk->pNext 1028 && pBlk->pNext->fFree) 1029 { 1030 PVCIBLKRANGEDESC pBlkNext = pBlk->pNext; 1031 1032 Assert(pBlk->offAddrStart + pBlk->cBlocks == pBlkNext->offAddrStart); 1033 pBlk->cBlocks += pBlkNext->cBlocks; 1034 pBlk->pNext = pBlkNext->pNext; 1035 if (pBlkNext->pNext) 1036 pBlkNext->pNext->pPrev = pBlk; 1037 else 1038 pBlkMap->pRangesTail = pBlk; 1039 1040 RTMemFree(pBlkNext); 1041 } 1042 } 1043 else 1044 { 1045 /* The block is intersecting. */ 1046 AssertMsgFailed(("TODO\n")); 1047 } 1048 } 1049 740 1050 LogFlowFunc(("returns\n")); 741 1051 } 742 1052 743 1053 /** 1054 * Converts a tree node from the image to the in memory structure. 1055 * 1056 * @returns Pointer to the in memory tree node. 1057 * @param offBlockAddrNode Block address of the node. 1058 * @param pNodeImage Pointer to the image representation of the node. 1059 */ 1060 static PVCITREENODE vciTreeNodeImage2Host(uint64_t offBlockAddrNode, PVciTreeNode pNodeImage) 1061 { 1062 PVCITREENODE pNode = NULL; 1063 1064 if (pNodeImage->u8Type == VCI_TREE_NODE_TYPE_LEAF) 1065 { 1066 PVCITREENODELEAF pLeaf = (PVCITREENODELEAF)RTMemAllocZ(sizeof(VCITREENODELEAF)); 1067 1068 if (pLeaf) 1069 { 1070 PVciCacheExtent pExtent = (PVciCacheExtent)&pNodeImage->au8Data[0]; 1071 1072 pLeaf->Core.u8Type = VCI_TREE_NODE_TYPE_LEAF; 1073 1074 for (unsigned idx = 0; idx < RT_ELEMENTS(pLeaf->aExtents); idx++) 1075 { 1076 pLeaf->aExtents[idx].u64BlockOffset = RT_LE2H_U64(pExtent->u64BlockOffset); 1077 pLeaf->aExtents[idx].u32Blocks = RT_LE2H_U32(pExtent->u32Blocks); 1078 pLeaf->aExtents[idx].u64BlockAddr = RT_LE2H_U64(pExtent->u64BlockAddr); 1079 pExtent++; 1080 1081 if ( pLeaf->aExtents[idx].u32Blocks 1082 && pLeaf->aExtents[idx].u64BlockAddr) 1083 pLeaf->cUsedNodes++; 1084 } 1085 1086 pNode = &pLeaf->Core; 1087 } 1088 } 1089 else if (pNodeImage->u8Type == VCI_TREE_NODE_TYPE_INTERNAL) 1090 { 1091 PVCITREENODEINT pInt = (PVCITREENODEINT)RTMemAllocZ(sizeof(VCITREENODEINT)); 1092 1093 if (pInt) 1094 { 1095 PVciTreeNodeInternal pIntImage = (PVciTreeNodeInternal)&pNodeImage->au8Data[0]; 1096 1097 pInt->Core.u8Type = VCI_TREE_NODE_TYPE_INTERNAL; 1098 1099 for (unsigned idx = 0; idx < RT_ELEMENTS(pInt->aIntNodes); idx++) 1100 { 1101 pInt->aIntNodes[idx].u64BlockOffset = RT_LE2H_U64(pIntImage->u64BlockOffset); 1102 pInt->aIntNodes[idx].u32Blocks = RT_LE2H_U32(pIntImage->u32Blocks); 1103 pInt->aIntNodes[idx].PtrChild.fInMemory = false; 1104 pInt->aIntNodes[idx].PtrChild.u.offAddrBlockNode = RT_LE2H_U64(pIntImage->u64ChildAddr); 1105 pIntImage++; 1106 1107 if ( pInt->aIntNodes[idx].u32Blocks 1108 && pInt->aIntNodes[idx].PtrChild.u.offAddrBlockNode) 1109 pInt->cUsedNodes++; 1110 } 1111 1112 pNode = &pInt->Core; 1113 } 1114 } 1115 else 1116 AssertMsgFailed(("Invalid node type %d\n", pNodeImage->u8Type)); 1117 1118 if (pNode) 1119 pNode->u64BlockAddr = offBlockAddrNode; 1120 1121 return pNode; 1122 } 1123 1124 /** 1125 * Looks up the cache extent for the given virtual block address. 1126 * 1127 * @returns Pointer to the cache extent or NULL if none could be found. 1128 * @param pCache The cache image instance. 1129 * @param offBlockOffset The block offset to search for. 1130 */ 1131 static PVCICACHEEXTENT vciCacheExtentLookup(PVCICACHE pCache, uint64_t offBlockOffset) 1132 { 1133 int rc = VINF_SUCCESS; 1134 PVCICACHEEXTENT pExtent = NULL; 1135 PVCITREENODE pNodeCur = pCache->pRoot; 1136 1137 while ( RT_SUCCESS(rc) 1138 && pNodeCur 1139 && pNodeCur->u8Type != VCI_TREE_NODE_TYPE_LEAF) 1140 { 1141 PVCITREENODEINT pNodeInt = (PVCITREENODEINT)pNodeCur; 1142 1143 Assert(pNodeCur->u8Type == VCI_TREE_NODE_TYPE_INTERNAL); 1144 1145 /* Search for the correct internal node. */ 1146 unsigned idxMin = 0; 1147 unsigned idxMax = pNodeInt->cUsedNodes; 1148 unsigned idxCur = pNodeInt->cUsedNodes / 2; 1149 1150 while (idxMin < idxMax) 1151 { 1152 PVCINODEINTERNAL pInt = &pNodeInt->aIntNodes[idxCur]; 1153 1154 /* Determine the search direction. */ 1155 if (offBlockOffset < pInt->u64BlockOffset) 1156 { 1157 /* Search left from the current extent. */ 1158 idxMax = idxCur; 1159 } 1160 else if (offBlockOffset >= pInt->u64BlockOffset + pInt->u32Blocks) 1161 { 1162 /* Search right from the current extent. */ 1163 idxMin = idxCur; 1164 } 1165 else 1166 { 1167 /* The block lies in the node, stop searching. */ 1168 if (pInt->PtrChild.fInMemory) 1169 pNodeCur = pInt->PtrChild.u.pNode; 1170 else 1171 { 1172 PVCITREENODE pNodeNew; 1173 VciTreeNode NodeTree; 1174 1175 /* Read from disk and add to the tree. */ 1176 rc = vciFileReadSync(pCache, VCI_BLOCK2BYTE(pInt->PtrChild.u.offAddrBlockNode), 1177 &NodeTree, sizeof(NodeTree)); 1178 AssertRC(rc); 1179 1180 pNodeNew = vciTreeNodeImage2Host(pInt->PtrChild.u.offAddrBlockNode, &NodeTree); 1181 if (pNodeNew) 1182 { 1183 /* Link to the parent. */ 1184 pInt->PtrChild.fInMemory = true; 1185 pInt->PtrChild.u.pNode = pNodeNew; 1186 pNodeNew->pParent = pNodeCur; 1187 pNodeCur = pNodeNew; 1188 } 1189 else 1190 rc = VERR_NO_MEMORY; 1191 } 1192 break; 1193 } 1194 1195 idxCur = idxMin + (idxMax - idxMin) / 2; 1196 } 1197 } 1198 1199 if ( RT_SUCCESS(rc) 1200 && pNodeCur) 1201 { 1202 PVCITREENODELEAF pLeaf = (PVCITREENODELEAF)pNodeCur; 1203 Assert(pNodeCur->u8Type == VCI_TREE_NODE_TYPE_LEAF); 1204 1205 /* Search the range. */ 1206 unsigned idxMin = 0; 1207 unsigned idxMax = pLeaf->cUsedNodes; 1208 unsigned idxCur = pLeaf->cUsedNodes / 2; 1209 1210 while (idxMin < idxMax) 1211 { 1212 PVCICACHEEXTENT pExtentCur = &pLeaf->aExtents[idxCur]; 1213 1214 /* Determine the search direction. */ 1215 if (offBlockOffset < pExtentCur->u64BlockOffset) 1216 { 1217 /* Search left from the current extent. */ 1218 idxMax = idxCur; 1219 } 1220 else if (offBlockOffset >= pExtentCur->u64BlockOffset + pExtentCur->u32Blocks) 1221 { 1222 /* Search right from the current extent. */ 1223 idxMin = idxCur; 1224 } 1225 else 1226 { 1227 /* We found the extent, stop searching. */ 1228 pExtent = pExtentCur; 1229 break; 1230 } 1231 1232 idxCur = idxMin + (idxMax - idxMin) / 2; 1233 } 1234 } 1235 1236 return pExtent; 1237 } 1238 1239 /** 744 1240 * Internal: Open an image, constructing all necessary data structures. 745 1241 */ 746 static int vciOpenImage(PVCICACHE pImage, unsigned uOpenFlags) 747 { 1242 static int vciOpenImage(PVCICACHE pCache, unsigned uOpenFlags) 1243 { 1244 VciHdr Hdr; 1245 uint64_t cbFile; 748 1246 int rc; 749 1247 750 p Image->uOpenFlags = uOpenFlags;751 752 p Image->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR);753 if (p Image->pInterfaceError)754 p Image->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);1248 pCache->uOpenFlags = uOpenFlags; 1249 1250 pCache->pInterfaceError = VDInterfaceGet(pCache->pVDIfsDisk, VDINTERFACETYPE_ERROR); 1251 if (pCache->pInterfaceError) 1252 pCache->pInterfaceErrorCallbacks = VDGetInterfaceError(pCache->pInterfaceError); 755 1253 756 1254 /* Get I/O interface. */ 757 p Image->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IOINT);758 AssertPtrReturn(p Image->pInterfaceIO, VERR_INVALID_PARAMETER);759 p Image->pInterfaceIOCallbacks = VDGetInterfaceIOInt(pImage->pInterfaceIO);760 AssertPtrReturn(p Image->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);1255 pCache->pInterfaceIO = VDInterfaceGet(pCache->pVDIfsImage, VDINTERFACETYPE_IOINT); 1256 AssertPtrReturn(pCache->pInterfaceIO, VERR_INVALID_PARAMETER); 1257 pCache->pInterfaceIOCallbacks = VDGetInterfaceIOInt(pCache->pInterfaceIO); 1258 AssertPtrReturn(pCache->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 761 1259 762 1260 /* 763 1261 * Open the image. 764 1262 */ 765 rc = vciFileOpen(p Image, pImage->pszFilename,1263 rc = vciFileOpen(pCache, pCache->pszFilename, 766 1264 VDOpenFlagsToFileOpenFlags(uOpenFlags, 767 1265 false /* fCreate */)); … … 773 1271 } 774 1272 775 rc = vciFileGetSize(pImage, &pImage->cbSize); 1273 rc = vciFileGetSize(pCache, &cbFile); 1274 if (RT_FAILURE(rc) || cbFile < sizeof(VciHdr)) 1275 { 1276 rc = VERR_VD_GEN_INVALID_HEADER; 1277 goto out; 1278 } 1279 1280 rc = vciFileReadSync(pCache, 0, &Hdr, sizeof(Hdr)); 776 1281 if (RT_FAILURE(rc)) 1282 { 1283 rc = VERR_VD_GEN_INVALID_HEADER; 777 1284 goto out; 778 if (pImage->cbSize % 512) 779 { 780 rc = VERR_VD_RAW_INVALID_HEADER; 781 goto out; 782 } 783 pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED; 1285 } 1286 1287 Hdr.u32Signature = RT_LE2H_U32(Hdr.u32Signature); 1288 Hdr.u32Version = RT_LE2H_U32(Hdr.u32Version); 1289 Hdr.cBlocksCache = RT_LE2H_U64(Hdr.cBlocksCache); 1290 Hdr.u32CacheType = RT_LE2H_U32(Hdr.u32CacheType); 1291 Hdr.offTreeRoot = RT_LE2H_U64(Hdr.offTreeRoot); 1292 Hdr.offBlkMap = RT_LE2H_U64(Hdr.offBlkMap); 1293 Hdr.cBlkMap = RT_LE2H_U64(Hdr.cBlkMap); 1294 1295 if ( Hdr.u32Signature == VCI_HDR_SIGNATURE 1296 && Hdr.u32Version == VCI_HDR_VERSION) 1297 { 1298 pCache->offTreeRoot = Hdr.offTreeRoot; 1299 pCache->offBlksBitmap = Hdr.offBlkMap; 1300 1301 /* Load the block map. */ 1302 rc = vciBlkMapLoad(pCache, VCI_BLOCK2BYTE(pCache->offBlksBitmap), Hdr.cBlkMap, &pCache->pBlkMap); 1303 if (RT_SUCCESS(rc)) 1304 { 1305 /* Load the first tree node. */ 1306 VciTreeNode RootNode; 1307 1308 rc = vciFileReadSync(pCache, VCI_BLOCK2BYTE(pCache->offTreeRoot), &RootNode, sizeof(VciTreeNode)); 1309 if (RT_SUCCESS(rc)) 1310 { 1311 pCache->pRoot = vciTreeNodeImage2Host(pCache->offTreeRoot, &RootNode); 1312 if (!pCache->pRoot) 1313 rc = VERR_NO_MEMORY; 1314 } 1315 } 1316 } 1317 else 1318 rc = VERR_VD_GEN_INVALID_HEADER; 784 1319 785 1320 out: 786 1321 if (RT_FAILURE(rc)) 787 vciFreeImage(p Image, false);1322 vciFreeImage(pCache, false); 788 1323 return rc; 789 1324 } … … 792 1327 * Internal: Create a vci image. 793 1328 */ 794 static int vciCreateImage(PVCICACHE p Image, uint64_t cbSize,1329 static int vciCreateImage(PVCICACHE pCache, uint64_t cbSize, 795 1330 unsigned uImageFlags, const char *pszComment, 796 1331 unsigned uOpenFlags, PFNVDPROGRESS pfnProgress, … … 805 1340 if (uImageFlags & VD_IMAGE_FLAGS_DIFF) 806 1341 { 807 rc = vciError(p Image, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("VCI: cannot create diff image '%s'"), pImage->pszFilename);1342 rc = vciError(pCache, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("VCI: cannot create diff image '%s'"), pCache->pszFilename); 808 1343 return rc; 809 1344 } 810 1345 811 p Image->uImageFlags = uImageFlags;812 813 p Image->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY;814 815 p Image->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR);816 if (p Image->pInterfaceError)817 p Image->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);818 819 p Image->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IOINT);820 AssertPtrReturn(p Image->pInterfaceIO, VERR_INVALID_PARAMETER);821 p Image->pInterfaceIOCallbacks = VDGetInterfaceIOInt(pImage->pInterfaceIO);822 AssertPtrReturn(p Image->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);1346 pCache->uImageFlags = uImageFlags; 1347 1348 pCache->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY; 1349 1350 pCache->pInterfaceError = VDInterfaceGet(pCache->pVDIfsDisk, VDINTERFACETYPE_ERROR); 1351 if (pCache->pInterfaceError) 1352 pCache->pInterfaceErrorCallbacks = VDGetInterfaceError(pCache->pInterfaceError); 1353 1354 pCache->pInterfaceIO = VDInterfaceGet(pCache->pVDIfsImage, VDINTERFACETYPE_IOINT); 1355 AssertPtrReturn(pCache->pInterfaceIO, VERR_INVALID_PARAMETER); 1356 pCache->pInterfaceIOCallbacks = VDGetInterfaceIOInt(pCache->pInterfaceIO); 1357 AssertPtrReturn(pCache->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 823 1358 824 1359 do 825 1360 { 826 1361 /* Create image file. */ 827 rc = vciFileOpen(p Image, pImage->pszFilename,1362 rc = vciFileOpen(pCache, pCache->pszFilename, 828 1363 VDOpenFlagsToFileOpenFlags(uOpenFlags & ~VD_OPEN_FLAGS_READONLY, 829 1364 true /* fCreate */)); 830 1365 if (RT_FAILURE(rc)) 831 1366 { 832 rc = vciError(p Image, rc, RT_SRC_POS, N_("VCI: cannot create image '%s'"), pImage->pszFilename);1367 rc = vciError(pCache, rc, RT_SRC_POS, N_("VCI: cannot create image '%s'"), pCache->pszFilename); 833 1368 break; 834 1369 } … … 836 1371 /* Allocate block bitmap. */ 837 1372 uint32_t cBlkMap = 0; 838 rc = vciBlkMapCreate(cBlocks, &p Image->pBlkMap, &cBlkMap);1373 rc = vciBlkMapCreate(cBlocks, &pCache->pBlkMap, &cBlkMap); 839 1374 if (RT_FAILURE(rc)) 840 1375 { 841 rc = vciError(p Image, rc, RT_SRC_POS, N_("VCI: cannot create block bitmap '%s'"), pImage->pszFilename);1376 rc = vciError(pCache, rc, RT_SRC_POS, N_("VCI: cannot create block bitmap '%s'"), pCache->pszFilename); 842 1377 break; 843 1378 } … … 848 1383 */ 849 1384 uint64_t offHdr = 0; 850 rc = vciBlkMapAllocate(p Image->pBlkMap, VCI_BYTE2BLOCK(sizeof(VciHdr)), &offHdr);1385 rc = vciBlkMapAllocate(pCache->pBlkMap, VCI_BYTE2BLOCK(sizeof(VciHdr)), &offHdr); 851 1386 if (RT_FAILURE(rc)) 852 1387 { 853 rc = vciError(p Image, rc, RT_SRC_POS, N_("VCI: cannot allocate space for header in block bitmap '%s'"), pImage->pszFilename);1388 rc = vciError(pCache, rc, RT_SRC_POS, N_("VCI: cannot allocate space for header in block bitmap '%s'"), pCache->pszFilename); 854 1389 break; 855 1390 } … … 861 1396 */ 862 1397 uint64_t offBlkMap = 0; 863 rc = vciBlkMapAllocate(p Image->pBlkMap, cBlkMap, &offBlkMap);1398 rc = vciBlkMapAllocate(pCache->pBlkMap, cBlkMap, &offBlkMap); 864 1399 if (RT_FAILURE(rc)) 865 1400 { 866 rc = vciError(p Image, rc, RT_SRC_POS, N_("VCI: cannot allocate space for block map in block map '%s'"), pImage->pszFilename);1401 rc = vciError(pCache, rc, RT_SRC_POS, N_("VCI: cannot allocate space for block map in block map '%s'"), pCache->pszFilename); 867 1402 break; 868 1403 } … … 872 1407 */ 873 1408 uint64_t offTreeRoot = 0; 874 rc = vciBlkMapAllocate(p Image->pBlkMap, VCI_BYTE2BLOCK(sizeof(VciTreeNode)), &offTreeRoot);1409 rc = vciBlkMapAllocate(pCache->pBlkMap, VCI_BYTE2BLOCK(sizeof(VciTreeNode)), &offTreeRoot); 875 1410 if (RT_FAILURE(rc)) 876 1411 { 877 rc = vciError(p Image, rc, RT_SRC_POS, N_("VCI: cannot allocate space for block map in block map '%s'"), pImage->pszFilename);1412 rc = vciError(pCache, rc, RT_SRC_POS, N_("VCI: cannot allocate space for block map in block map '%s'"), pCache->pszFilename); 878 1413 break; 879 1414 } 1415 1416 /* 1417 * Allocate the in memory root node. 1418 */ 1419 pCache->pRoot = (PVCITREENODE)RTMemAllocZ(sizeof(VCITREENODELEAF)); 1420 if (!pCache->pRoot) 1421 { 1422 rc = vciError(pCache, rc, RT_SRC_POS, N_("VCI: cannot allocate B+-Tree root pointer '%s'"), pCache->pszFilename); 1423 break; 1424 } 1425 1426 pCache->pRoot->u8Type = VCI_TREE_NODE_TYPE_LEAF; 1427 /* Rest remains 0 as the tree is still empty. */ 880 1428 881 1429 /* … … 897 1445 Hdr.cBlkMap = RT_H2LE_U64(cBlkMap); 898 1446 899 rc = vciFileWriteSync(p Image, offHdr, &Hdr, VCI_BYTE2BLOCK(sizeof(VciHdr)));1447 rc = vciFileWriteSync(pCache, offHdr, &Hdr, VCI_BYTE2BLOCK(sizeof(VciHdr))); 900 1448 if (RT_FAILURE(rc)) 901 1449 { 902 rc = vciError(p Image, rc, RT_SRC_POS, N_("VCI: cannot write header '%s'"), pImage->pszFilename);1450 rc = vciError(pCache, rc, RT_SRC_POS, N_("VCI: cannot write header '%s'"), pCache->pszFilename); 903 1451 break; 904 1452 } 905 1453 906 rc = vciBlkMapSave(p Image->pBlkMap, pImage, offBlkMap, cBlkMap);1454 rc = vciBlkMapSave(pCache->pBlkMap, pCache, offBlkMap, cBlkMap); 907 1455 if (RT_FAILURE(rc)) 908 1456 { 909 rc = vciError(p Image, rc, RT_SRC_POS, N_("VCI: cannot write block map '%s'"), pImage->pszFilename);1457 rc = vciError(pCache, rc, RT_SRC_POS, N_("VCI: cannot write block map '%s'"), pCache->pszFilename); 910 1458 break; 911 1459 } … … 913 1461 /* Setup the root tree. */ 914 1462 memset(&NodeRoot, 0, sizeof(VciTreeNode)); 915 NodeRoot.u8Type = RT_H2LE_U32(VCI_TREE_NODE_TYPE_ ROOT);916 917 rc = vciFileWriteSync(p Image, offTreeRoot, &NodeRoot, VCI_BYTE2BLOCK(sizeof(VciTreeNode)));1463 NodeRoot.u8Type = RT_H2LE_U32(VCI_TREE_NODE_TYPE_LEAF); 1464 1465 rc = vciFileWriteSync(pCache, offTreeRoot, &NodeRoot, VCI_BYTE2BLOCK(sizeof(VciTreeNode))); 918 1466 if (RT_FAILURE(rc)) 919 1467 { 920 rc = vciError(p Image, rc, RT_SRC_POS, N_("VCI: cannot write root node '%s'"), pImage->pszFilename);1468 rc = vciError(pCache, rc, RT_SRC_POS, N_("VCI: cannot write root node '%s'"), pCache->pszFilename); 921 1469 break; 922 1470 } 923 1471 924 rc = vciFlushImage(p Image);1472 rc = vciFlushImage(pCache); 925 1473 if (RT_FAILURE(rc)) 926 1474 { 927 rc = vciError(p Image, rc, RT_SRC_POS, N_("VCI: cannot flush '%s'"), pImage->pszFilename);1475 rc = vciError(pCache, rc, RT_SRC_POS, N_("VCI: cannot flush '%s'"), pCache->pszFilename); 928 1476 break; 929 1477 } 930 1478 931 p Image->cbSize = cbSize;1479 pCache->cbSize = cbSize; 932 1480 933 1481 } while (0); … … 937 1485 938 1486 if (RT_FAILURE(rc)) 939 vciFreeImage(p Image, rc != VERR_ALREADY_EXISTS);1487 vciFreeImage(pCache, rc != VERR_ALREADY_EXISTS); 940 1488 return rc; 941 1489 } … … 945 1493 PVDINTERFACE pVDIfsImage) 946 1494 { 1495 VciHdr Hdr; 1496 PVDIOSTORAGE pStorage; 1497 uint64_t cbFile; 1498 int rc = VINF_SUCCESS; 1499 947 1500 LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename)); 948 int rc = VINF_SUCCESS; 949 950 if ( !VALID_PTR(pszFilename) 951 || !*pszFilename) 952 { 953 rc = VERR_INVALID_PARAMETER; 1501 1502 /* Get I/O interface. */ 1503 PVDINTERFACE pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IOINT); 1504 AssertPtrReturn(pInterfaceIO, VERR_INVALID_PARAMETER); 1505 PVDINTERFACEIOINT pInterfaceIOCallbacks = VDGetInterfaceIOInt(pInterfaceIO); 1506 AssertPtrReturn(pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 1507 1508 rc = pInterfaceIOCallbacks->pfnOpen(pInterfaceIO->pvUser, pszFilename, 1509 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY, 1510 false /* fCreate */), 1511 &pStorage); 1512 if (RT_FAILURE(rc)) 954 1513 goto out; 955 } 1514 1515 rc = pInterfaceIOCallbacks->pfnGetSize(pInterfaceIO->pvUser, pStorage, &cbFile); 1516 if (RT_FAILURE(rc) || cbFile < sizeof(VciHdr)) 1517 { 1518 pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage); 1519 rc = VERR_VD_GEN_INVALID_HEADER; 1520 goto out; 1521 } 1522 1523 rc = pInterfaceIOCallbacks->pfnReadSync(pInterfaceIO->pvUser, pStorage, 0, &Hdr, sizeof(Hdr), NULL); 1524 if (RT_FAILURE(rc)) 1525 { 1526 pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage); 1527 rc = VERR_VD_GEN_INVALID_HEADER; 1528 goto out; 1529 } 1530 1531 Hdr.u32Signature = RT_LE2H_U32(Hdr.u32Signature); 1532 Hdr.u32Version = RT_LE2H_U32(Hdr.u32Version); 1533 Hdr.cBlocksCache = RT_LE2H_U64(Hdr.cBlocksCache); 1534 Hdr.u32CacheType = RT_LE2H_U32(Hdr.u32CacheType); 1535 Hdr.offTreeRoot = RT_LE2H_U64(Hdr.offTreeRoot); 1536 Hdr.offBlkMap = RT_LE2H_U64(Hdr.offBlkMap); 1537 Hdr.cBlkMap = RT_LE2H_U64(Hdr.cBlkMap); 1538 1539 if ( Hdr.u32Signature == VCI_HDR_SIGNATURE 1540 && Hdr.u32Version == VCI_HDR_VERSION) 1541 rc = VINF_SUCCESS; 1542 else 1543 rc = VERR_VD_GEN_INVALID_HEADER; 1544 1545 pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage); 956 1546 957 1547 out: … … 967 1557 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData)); 968 1558 int rc; 969 PVCICACHE p Image;1559 PVCICACHE pCache; 970 1560 971 1561 /* Check open flags. All valid flags are supported. */ … … 985 1575 986 1576 987 p Image = (PVCICACHE)RTMemAllocZ(sizeof(VCICACHE));988 if (!p Image)1577 pCache = (PVCICACHE)RTMemAllocZ(sizeof(VCICACHE)); 1578 if (!pCache) 989 1579 { 990 1580 rc = VERR_NO_MEMORY; 991 1581 goto out; 992 1582 } 993 p Image->pszFilename = pszFilename;994 p Image->pStorage = NULL;995 p Image->pVDIfsDisk = pVDIfsDisk;996 p Image->pVDIfsImage = pVDIfsImage;997 998 rc = vciOpenImage(p Image, uOpenFlags);1583 pCache->pszFilename = pszFilename; 1584 pCache->pStorage = NULL; 1585 pCache->pVDIfsDisk = pVDIfsDisk; 1586 pCache->pVDIfsImage = pVDIfsImage; 1587 1588 rc = vciOpenImage(pCache, uOpenFlags); 999 1589 if (RT_SUCCESS(rc)) 1000 *ppBackendData = p Image;1590 *ppBackendData = pCache; 1001 1591 else 1002 RTMemFree(p Image);1592 RTMemFree(pCache); 1003 1593 1004 1594 out: … … 1018 1608 pszFilename, cbSize, uImageFlags, pszComment, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData)); 1019 1609 int rc; 1020 PVCICACHE p Image;1610 PVCICACHE pCache; 1021 1611 1022 1612 PFNVDPROGRESS pfnProgress = NULL; … … 1048 1638 } 1049 1639 1050 p Image = (PVCICACHE)RTMemAllocZ(sizeof(VCICACHE));1051 if (!p Image)1640 pCache = (PVCICACHE)RTMemAllocZ(sizeof(VCICACHE)); 1641 if (!pCache) 1052 1642 { 1053 1643 rc = VERR_NO_MEMORY; 1054 1644 goto out; 1055 1645 } 1056 p Image->pszFilename = pszFilename;1057 p Image->pStorage = NULL;1058 p Image->pVDIfsDisk = pVDIfsDisk;1059 p Image->pVDIfsImage = pVDIfsImage;1060 1061 rc = vciCreateImage(p Image, cbSize, uImageFlags, pszComment, uOpenFlags,1646 pCache->pszFilename = pszFilename; 1647 pCache->pStorage = NULL; 1648 pCache->pVDIfsDisk = pVDIfsDisk; 1649 pCache->pVDIfsImage = pVDIfsImage; 1650 1651 rc = vciCreateImage(pCache, cbSize, uImageFlags, pszComment, uOpenFlags, 1062 1652 pfnProgress, pvUser, uPercentStart, uPercentSpan); 1063 1653 if (RT_SUCCESS(rc)) … … 1067 1657 if (uOpenFlags & VD_OPEN_FLAGS_READONLY) 1068 1658 { 1069 vciFreeImage(p Image, false);1070 rc = vciOpenImage(p Image, uOpenFlags);1659 vciFreeImage(pCache, false); 1660 rc = vciOpenImage(pCache, uOpenFlags); 1071 1661 if (RT_FAILURE(rc)) 1072 1662 { 1073 RTMemFree(p Image);1663 RTMemFree(pCache); 1074 1664 goto out; 1075 1665 } 1076 1666 } 1077 *ppBackendData = p Image;1667 *ppBackendData = pCache; 1078 1668 } 1079 1669 else 1080 RTMemFree(p Image);1670 RTMemFree(pCache); 1081 1671 1082 1672 out: … … 1089 1679 { 1090 1680 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete)); 1091 PVCICACHE p Image = (PVCICACHE)pBackendData;1681 PVCICACHE pCache = (PVCICACHE)pBackendData; 1092 1682 int rc; 1093 1683 1094 rc = vciFreeImage(p Image, fDelete);1095 RTMemFree(p Image);1684 rc = vciFreeImage(pCache, fDelete); 1685 RTMemFree(pCache); 1096 1686 1097 1687 LogFlowFunc(("returns %Rrc\n", rc)); … … 1104 1694 { 1105 1695 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead)); 1106 PVCICACHE p Image = (PVCICACHE)pBackendData;1696 PVCICACHE pCache = (PVCICACHE)pBackendData; 1107 1697 int rc = VINF_SUCCESS; 1108 1109 AssertPtr(pImage); 1698 PVCICACHEEXTENT pExtent; 1699 1700 AssertPtr(pCache); 1110 1701 Assert(uOffset % 512 == 0); 1111 1702 Assert(cbToRead % 512 == 0); 1703 1704 1705 pExtent = vciCacheExtentLookup(pCache, VCI_BYTE2BLOCK(uOffset)); 1706 if (pExtent) 1707 { 1708 uint64_t offRead = uOffset - VCI_BLOCK2BYTE(pExtent->u64BlockOffset); 1709 cbToRead = RT_MIN(cbToRead, VCI_BLOCK2BYTE(pExtent->u32Blocks) - offRead); 1710 1711 rc = vciFileReadSync(pCache, VCI_BLOCK2BYTE(pExtent->u64BlockAddr) + offRead, 1712 pvBuf, cbToRead); 1713 } 1714 else 1715 { 1716 /** @todo Best fit to check whether we have cached data later and set 1717 * pcbActuallyRead accordingly. */ 1718 rc = VERR_VD_BLOCK_FREE; 1719 } 1720 1721 if (pcbActuallyRead) 1722 *pcbActuallyRead = cbToRead; 1112 1723 1113 1724 out: … … 1122 1733 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p\n", 1123 1734 pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess)); 1124 PVCICACHE p Image = (PVCICACHE)pBackendData;1735 PVCICACHE pCache = (PVCICACHE)pBackendData; 1125 1736 int rc = VINF_SUCCESS; 1126 1737 1127 AssertPtr(p Image);1738 AssertPtr(pCache); 1128 1739 Assert(uOffset % 512 == 0); 1129 1740 Assert(cbToWrite % 512 == 0); … … 1138 1749 { 1139 1750 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1140 PVCICACHE p Image = (PVCICACHE)pBackendData;1751 PVCICACHE pCache = (PVCICACHE)pBackendData; 1141 1752 int rc = VINF_SUCCESS; 1142 1753 1143 rc = vciFlushImage(p Image);1754 rc = vciFlushImage(pCache); 1144 1755 LogFlowFunc(("returns %Rrc\n", rc)); 1145 1756 return rc; … … 1150 1761 { 1151 1762 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1152 PVCICACHE p Image = (PVCICACHE)pBackendData;1153 1154 AssertPtr(p Image);1155 1156 if (p Image)1763 PVCICACHE pCache = (PVCICACHE)pBackendData; 1764 1765 AssertPtr(pCache); 1766 1767 if (pCache) 1157 1768 return 1; 1158 1769 else … … 1164 1775 { 1165 1776 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1166 PVCICACHE p Image = (PVCICACHE)pBackendData;1777 PVCICACHE pCache = (PVCICACHE)pBackendData; 1167 1778 uint64_t cb = 0; 1168 1779 1169 AssertPtr(p Image);1170 1171 if (p Image && pImage->pStorage)1172 cb = p Image->cbSize;1780 AssertPtr(pCache); 1781 1782 if (pCache && pCache->pStorage) 1783 cb = pCache->cbSize; 1173 1784 1174 1785 LogFlowFunc(("returns %llu\n", cb)); … … 1180 1791 { 1181 1792 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1182 PVCICACHE p Image = (PVCICACHE)pBackendData;1793 PVCICACHE pCache = (PVCICACHE)pBackendData; 1183 1794 uint64_t cb = 0; 1184 1795 1185 AssertPtr(p Image);1186 1187 if (p Image)1796 AssertPtr(pCache); 1797 1798 if (pCache) 1188 1799 { 1189 1800 uint64_t cbFile; 1190 if (p Image->pStorage)1191 { 1192 int rc = vciFileGetSize(p Image, &cbFile);1801 if (pCache->pStorage) 1802 { 1803 int rc = vciFileGetSize(pCache, &cbFile); 1193 1804 if (RT_SUCCESS(rc)) 1194 1805 cb = cbFile; … … 1204 1815 { 1205 1816 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1206 PVCICACHE p Image = (PVCICACHE)pBackendData;1817 PVCICACHE pCache = (PVCICACHE)pBackendData; 1207 1818 unsigned uImageFlags; 1208 1819 1209 AssertPtr(p Image);1210 1211 if (p Image)1212 uImageFlags = p Image->uImageFlags;1820 AssertPtr(pCache); 1821 1822 if (pCache) 1823 uImageFlags = pCache->uImageFlags; 1213 1824 else 1214 1825 uImageFlags = 0; … … 1222 1833 { 1223 1834 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1224 PVCICACHE p Image = (PVCICACHE)pBackendData;1835 PVCICACHE pCache = (PVCICACHE)pBackendData; 1225 1836 unsigned uOpenFlags; 1226 1837 1227 AssertPtr(p Image);1228 1229 if (p Image)1230 uOpenFlags = p Image->uOpenFlags;1838 AssertPtr(pCache); 1839 1840 if (pCache) 1841 uOpenFlags = pCache->uOpenFlags; 1231 1842 else 1232 1843 uOpenFlags = 0; … … 1240 1851 { 1241 1852 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 1242 PVCICACHE p Image = (PVCICACHE)pBackendData;1853 PVCICACHE pCache = (PVCICACHE)pBackendData; 1243 1854 int rc; 1244 1855 1245 1856 /* Image must be opened and the new flags must be valid. Just readonly and 1246 1857 * info flags are supported. */ 1247 if (!p Image || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO)))1858 if (!pCache || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO))) 1248 1859 { 1249 1860 rc = VERR_INVALID_PARAMETER; … … 1252 1863 1253 1864 /* Implement this operation via reopening the image. */ 1254 rc = vciFreeImage(p Image, false);1865 rc = vciFreeImage(pCache, false); 1255 1866 if (RT_FAILURE(rc)) 1256 1867 goto out; 1257 rc = vciOpenImage(p Image, uOpenFlags);1868 rc = vciOpenImage(pCache, uOpenFlags); 1258 1869 1259 1870 out: … … 1267 1878 { 1268 1879 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 1269 PVCICACHE p Image = (PVCICACHE)pBackendData;1880 PVCICACHE pCache = (PVCICACHE)pBackendData; 1270 1881 int rc; 1271 1882 1272 AssertPtr(p Image);1273 1274 if (p Image)1883 AssertPtr(pCache); 1884 1885 if (pCache) 1275 1886 rc = VERR_NOT_SUPPORTED; 1276 1887 else … … 1285 1896 { 1286 1897 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 1287 PVCICACHE p Image = (PVCICACHE)pBackendData;1898 PVCICACHE pCache = (PVCICACHE)pBackendData; 1288 1899 int rc; 1289 1900 1290 AssertPtr(p Image);1291 1292 if (p Image->uOpenFlags & VD_OPEN_FLAGS_READONLY)1901 AssertPtr(pCache); 1902 1903 if (pCache->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1293 1904 { 1294 1905 rc = VERR_VD_IMAGE_READ_ONLY; … … 1296 1907 } 1297 1908 1298 if (p Image)1909 if (pCache) 1299 1910 rc = VERR_NOT_SUPPORTED; 1300 1911 else … … 1310 1921 { 1311 1922 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 1312 PVCICACHE p Image = (PVCICACHE)pBackendData;1923 PVCICACHE pCache = (PVCICACHE)pBackendData; 1313 1924 int rc; 1314 1925 1315 AssertPtr(p Image);1316 1317 if (p Image)1926 AssertPtr(pCache); 1927 1928 if (pCache) 1318 1929 rc = VERR_NOT_SUPPORTED; 1319 1930 else … … 1328 1939 { 1329 1940 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 1330 PVCICACHE p Image = (PVCICACHE)pBackendData;1941 PVCICACHE pCache = (PVCICACHE)pBackendData; 1331 1942 int rc; 1332 1943 1333 1944 LogFlowFunc(("%RTuuid\n", pUuid)); 1334 AssertPtr(p Image);1335 1336 if (p Image)1337 { 1338 if (!(p Image->uOpenFlags & VD_OPEN_FLAGS_READONLY))1945 AssertPtr(pCache); 1946 1947 if (pCache) 1948 { 1949 if (!(pCache->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1339 1950 rc = VERR_NOT_SUPPORTED; 1340 1951 else … … 1352 1963 { 1353 1964 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 1354 PVCICACHE p Image = (PVCICACHE)pBackendData;1965 PVCICACHE pCache = (PVCICACHE)pBackendData; 1355 1966 int rc; 1356 1967 1357 AssertPtr(p Image);1358 1359 if (p Image)1968 AssertPtr(pCache); 1969 1970 if (pCache) 1360 1971 rc = VERR_NOT_SUPPORTED; 1361 1972 else … … 1370 1981 { 1371 1982 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 1372 PVCICACHE p Image = (PVCICACHE)pBackendData;1983 PVCICACHE pCache = (PVCICACHE)pBackendData; 1373 1984 int rc; 1374 1985 1375 AssertPtr(p Image);1376 1377 if (p Image)1378 { 1379 if (!(p Image->uOpenFlags & VD_OPEN_FLAGS_READONLY))1986 AssertPtr(pCache); 1987 1988 if (pCache) 1989 { 1990 if (!(pCache->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1380 1991 rc = VERR_NOT_SUPPORTED; 1381 1992 else … … 1399 2010 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 1400 2011 { 1401 int rc = VINF_SUCCESS; 1402 PVCICACHE pImage = (PVCICACHE)pBackendData; 1403 1404 rc = vciFileReadUserAsync(pImage, uOffset, pIoCtx, cbRead); 1405 if (RT_SUCCESS(rc)) 1406 *pcbActuallyRead = cbRead; 2012 int rc = VERR_NOT_SUPPORTED; 2013 PVCICACHE pCache = (PVCICACHE)pBackendData; 1407 2014 1408 2015 return rc; … … 1413 2020 PVDIOCTX pIoCtx, size_t *pcbWriteProcess) 1414 2021 { 1415 int rc = VINF_SUCCESS; 1416 PVCICACHE pImage = (PVCICACHE)pBackendData; 1417 1418 rc = vciFileWriteUserAsync(pImage, uOffset, pIoCtx, cbWrite, NULL, NULL); 1419 if (RT_SUCCESS(rc)) 1420 *pcbWriteProcess = cbWrite; 2022 int rc = VERR_NOT_SUPPORTED; 2023 PVCICACHE pCache = (PVCICACHE)pBackendData; 1421 2024 1422 2025 return rc; … … 1426 2029 static int vciAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx) 1427 2030 { 1428 int rc = VINF_SUCCESS; 1429 PVCICACHE pImage = (PVCICACHE)pBackendData; 1430 1431 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1432 rc = vciFileFlushAsync(pImage, pIoCtx, NULL, NULL); 2031 int rc = VERR_NOT_SUPPORTED; 2032 PVCICACHE pCache = (PVCICACHE)pBackendData; 1433 2033 1434 2034 return rc; … … 1443 2043 sizeof(VDCACHEBACKEND), 1444 2044 /* uBackendCaps */ 1445 VD_CAP_CREATE_FIXED | VD_CAP_CREATE_DYNAMIC | VD_CAP_FILE | VD_CAP_ ASYNC,2045 VD_CAP_CREATE_FIXED | VD_CAP_CREATE_DYNAMIC | VD_CAP_FILE | VD_CAP_VFS, 1446 2046 /* papszFileExtensions */ 1447 2047 s_apszVciFileExtensions,
Note:
See TracChangeset
for help on using the changeset viewer.