VHD Performance enhancementsDaa:

optimize BAT updates when writing to previously unwritten data blocks
  data block alignment for optimal behavior on Advance Format host disks (4096 sectors)
This commit is contained in:
Mark Pizzolato 2012-07-10 13:18:03 -07:00
parent 321b05c705
commit 2a9ac8a830

View file

@ -2902,11 +2902,11 @@ if (!hVHD) {
} }
LocatorPosition = NtoHll (hVHD->Dynamic.TableOffset)+BytesPerSector*((NtoHl (hVHD->Dynamic.MaxTableEntries)*sizeof(*hVHD->BAT)+BytesPerSector-1)/BytesPerSector); LocatorPosition = NtoHll (hVHD->Dynamic.TableOffset)+BytesPerSector*((NtoHl (hVHD->Dynamic.MaxTableEntries)*sizeof(*hVHD->BAT)+BytesPerSector-1)/BytesPerSector);
hVHD->Dynamic.Checksum = 0; hVHD->Dynamic.Checksum = 0;
RelativeParentVHDPath = calloc (1, BytesPerSector+1); RelativeParentVHDPath = calloc (1, BytesPerSector+2);
FullParentVHDPath = calloc (1, BytesPerSector+1); FullParentVHDPath = calloc (1, BytesPerSector+2);
RelativeParentVHDPathBuffer = calloc (1, BytesPerSector); RelativeParentVHDPathBuffer = calloc (1, BytesPerSector+2);
FullParentVHDPathBuffer = calloc (1, BytesPerSector); FullParentVHDPathBuffer = calloc (1, BytesPerSector+2);
FullVHDPath = calloc (1, BytesPerSector+1); FullVHDPath = calloc (1, BytesPerSector+2);
ExpandToFullPath (szParentVHDPath, FullParentVHDPath, BytesPerSector); ExpandToFullPath (szParentVHDPath, FullParentVHDPath, BytesPerSector);
for (i=0; i < strlen (FullParentVHDPath); i++) for (i=0; i < strlen (FullParentVHDPath); i++)
hVHD->Dynamic.ParentUnicodeName[i*2+1] = FullParentVHDPath[i]; hVHD->Dynamic.ParentUnicodeName[i*2+1] = FullParentVHDPath[i];
@ -3240,8 +3240,13 @@ while (sects) {
} }
SectorsInWrite = 1; SectorsInWrite = 1;
if (hVHD->BAT[BlockNumber] == VHD_BAT_FREE_ENTRY) { if (hVHD->BAT[BlockNumber] == VHD_BAT_FREE_ENTRY) {
void *BitMap = NULL; uint8 *BitMap = NULL;
uint32 BitMapBufferSize = VHD_DATA_BLOCK_ALIGNMENT;
uint8 *BitMapBuffer = NULL;
void *BlockData = NULL; void *BlockData = NULL;
uint8 *BATUpdateBufferAddress;
uint32 BATUpdateBufferSize;
uint64 BATUpdateStorageAddress;
if (!hVHD->Parent && BufferIsZeros(buf, SectorSize)) if (!hVHD->Parent && BufferIsZeros(buf, SectorSize))
goto IO_Done; goto IO_Done;
@ -3249,28 +3254,51 @@ while (sects) {
BlockOffset = sim_fsize_ex (hVHD->File); BlockOffset = sim_fsize_ex (hVHD->File);
if (((int64)BlockOffset) == -1) if (((int64)BlockOffset) == -1)
return SCPE_IOERR; return SCPE_IOERR;
BitMap = malloc(BitMapSectors*SectorSize); if (BitMapSectors*SectorSize > BitMapBufferSize)
BitMapBufferSize = BitMapSectors*SectorSize;
BitMapBuffer = calloc(1, BitMapBufferSize + SectorSize*SectorsPerBlock);
if (BitMapBufferSize > BitMapSectors*SectorSize)
BitMap = BitMapBuffer + BitMapBufferSize-BitMapBytes;
else
BitMap = BitMapBuffer;
memset(BitMap, 0xFF, BitMapBytes); memset(BitMap, 0xFF, BitMapBytes);
BlockOffset -= sizeof(hVHD->Footer); BlockOffset -= sizeof(hVHD->Footer);
/* align the data portion of the block to the desired alignment */ if (0 == (BlockOffset & ~(VHD_DATA_BLOCK_ALIGNMENT-1)))
/* compute the address of the data portion of the block */ { // Already aligned, so use padded BitMapBuffer
BlockOffset += BitMapSectors*SectorSize; if (WriteFilePosition(hVHD->File,
/* round up this address to the desired alignment */ BitMapBuffer,
BlockOffset += VHD_DATA_BLOCK_ALIGNMENT-1; BitMapBufferSize + SectorSize*SectorsPerBlock,
BlockOffset &= ~(VHD_DATA_BLOCK_ALIGNMENT-1); NULL,
/* the actual block address is the beginning of the block bitmap */ BlockOffset)) {
free (BitMapBuffer);
return SCPE_IOERR;
}
BlockOffset += BitMapBufferSize;
}
else
{
// align the data portion of the block to the desired alignment
// compute the address of the data portion of the block
BlockOffset += BitMapSectors*SectorSize;
// round up this address to the desired alignment
BlockOffset += VHD_DATA_BLOCK_ALIGNMENT-1;
BlockOffset &= ~(VHD_DATA_BLOCK_ALIGNMENT-1);
BlockOffset -= BitMapSectors*SectorSize;
if (WriteFilePosition(hVHD->File,
BitMap,
SectorSize * (BitMapSectors + SectorsPerBlock),
NULL,
BlockOffset)) {
free (BitMapBuffer);
return SCPE_IOERR;
}
BlockOffset += BitMapSectors*SectorSize;
}
free(BitMapBuffer);
BitMapBuffer = BitMap = NULL;
/* the BAT block address is the beginning of the block bitmap */
BlockOffset -= BitMapSectors*SectorSize; BlockOffset -= BitMapSectors*SectorSize;
hVHD->BAT[BlockNumber] = NtoHl((uint32)(BlockOffset/SectorSize)); hVHD->BAT[BlockNumber] = NtoHl((uint32)(BlockOffset/SectorSize));
if (WriteFilePosition(hVHD->File,
BitMap,
BitMapSectors*SectorSize,
NULL,
BlockOffset)) {
free (BitMap);
return SCPE_IOERR;
}
free(BitMap);
BitMap = NULL;
BlockOffset += SectorSize * (SectorsPerBlock + BitMapSectors); BlockOffset += SectorSize * (SectorsPerBlock + BitMapSectors);
if (WriteFilePosition(hVHD->File, if (WriteFilePosition(hVHD->File,
&hVHD->Footer, &hVHD->Footer,
@ -3278,11 +3306,17 @@ while (sects) {
NULL, NULL,
BlockOffset)) BlockOffset))
goto Fatal_IO_Error; goto Fatal_IO_Error;
BATUpdateBufferAddress = ((uint8 *)hVHD->BAT) +
(((((size_t)&hVHD->BAT[BlockNumber]) - ((size_t)hVHD->BAT) + VHD_DATA_BLOCK_ALIGNMENT - 1)/VHD_DATA_BLOCK_ALIGNMENT)*VHD_DATA_BLOCK_ALIGNMENT);
BATUpdateBufferSize = SectorSize*((sizeof(*hVHD->BAT)*NtoHl(hVHD->Dynamic.MaxTableEntries)+511)/512);
if (BATUpdateBufferSize > VHD_DATA_BLOCK_ALIGNMENT)
BATUpdateBufferSize = VHD_DATA_BLOCK_ALIGNMENT;
BATUpdateStorageAddress = NtoHll(hVHD->Dynamic.TableOffset) + BATUpdateBufferAddress - ((uint8 *)hVHD->BAT);
if (WriteFilePosition(hVHD->File, if (WriteFilePosition(hVHD->File,
hVHD->BAT, BATUpdateBufferAddress,
SectorSize*((sizeof(*hVHD->BAT)*NtoHl(hVHD->Dynamic.MaxTableEntries)+511)/512), BATUpdateBufferSize,
NULL, NULL,
NtoHll(hVHD->Dynamic.TableOffset))) BATUpdateStorageAddress))
goto Fatal_IO_Error; goto Fatal_IO_Error;
if (hVHD->Parent) if (hVHD->Parent)
{ /* Need to populate data block contents from parent VHD */ { /* Need to populate data block contents from parent VHD */