Fixed open issues on corrupt or inconsistent differencing disks to properly return error status.

Fixed error paths to report errors when copying a differencing disk.
Fixed structure alignment issues to produce dynamic VHDs which are compatible with Windows 7's disk management.
Fixed performance optimization which attempted to optimize dynamic disk BAT updates as dynamic disks grew.
Added -O attach option for to override consistency checks for differencing disks which may have unexpected parent GUID or timestamp values.
This commit is contained in:
Mark Pizzolato 2013-02-11 09:48:36 -08:00
parent 4d187a7ada
commit 448ee4ad3c

View file

@ -911,14 +911,21 @@ if (sim_switches & SWMASK ('C')) { /* create vhd disk & cop
}
}
if (!sim_quiet)
printf ("\n%s%d: Copied %dMB. Done.\n", sim_dname (dptr), (int)(uptr-dptr->units), (int)(((t_addr)lba*sector_size)/1000000));
if (r == SCPE_OK)
printf ("\n%s%d: Copied %dMB. Done.\n", sim_dname (dptr), (int)(uptr-dptr->units), (int)(((t_addr)lba*sector_size)/1000000));
else
printf ("\n%s%d: Error copying: %s.\n", sim_dname (dptr), (int)(uptr-dptr->units), sim_error_text (r));
free (copy_buf);
created = TRUE;
sim_vhd_disk_close (vhd);
sim_disk_detach (uptr);
strcpy (cptr, gbuf);
sim_disk_set_fmt (uptr, 0, "VHD", NULL);
sim_switches = saved_sim_switches;
if (r == SCPE_OK) {
created = TRUE;
strcpy (cptr, gbuf);
sim_disk_set_fmt (uptr, 0, "VHD", NULL);
sim_switches = saved_sim_switches;
}
else
return r;
/* fall through and open/return the newly created & copied vhd */
}
}
@ -1196,7 +1203,9 @@ fprintf (st, " -X When creating a VHD, create a fixed sized VHD (vs
fprintf (st, " expanding one).\n");
fprintf (st, " -D Create a Differencing VHD (relative to an already existing VHD\n");
fprintf (st, " disk)\n");
fprintf (st, " -M Merge a Differencing VHD into its parent VHD disk\n\n");
fprintf (st, " -M Merge a Differencing VHD into its parent VHD disk\n");
fprintf (st, " -O Override consistency checks when attaching differencing disks\n");
fprintf (st, " which have unexpected parent disk GUID or timestamps\n\n");
fprintf (st, "Examples:\n");
fprintf (st, " sim> show rq\n");
fprintf (st, " RQ, address=20001468-2000146B*, no vector, 4 units\n");
@ -2667,13 +2676,17 @@ if ((sDynamic) &&
NULL,
0)) &&
(0 == memcmp (sDynamic->ParentUniqueID, sParentFooter.UniqueID, sizeof (sParentFooter.UniqueID))) &&
(sDynamic->ParentTimeStamp == ParentModificationTime)) {
((sDynamic->ParentTimeStamp == ParentModificationTime) ||
((NtoHl(sDynamic->ParentTimeStamp)-NtoHl(ParentModificationTime)) == 3600) ||
(sim_switches & SWMASK ('O')))) {
strncpy (szParentVHDPath, CheckPath, ParentVHDPathSize);
break;
}
}
if (!szParentVHDPath)
if (!*szParentVHDPath) {
Return = EINVAL; /* File Corrupt */
fprintf (stderr, "Error Invalid Parent VHD for Differencing VHD\n");
}
}
}
}
@ -3080,7 +3093,7 @@ Footer.DataOffset = NtoHll (bFixedVHD ? ((long long)-1) : (long long)(sizeof(Foo
time (&now);
Footer.TimeStamp = NtoHl ((uint32)(now-946684800));
memcpy (Footer.CreatorApplication, "simh", 4);
Footer.CreatorVersion = NtoHl (0x00010000);
Footer.CreatorVersion = NtoHl (0x00040000);
memcpy (Footer.CreatorHostOS, "Wi2k", 4);
Footer.OriginalSize = NtoHll (SizeInBytes);
Footer.CurrentSize = NtoHll (SizeInBytes);
@ -3142,9 +3155,7 @@ if (bFixedVHD) {
memset (&Dynamic, 0, sizeof(Dynamic));
memcpy (Dynamic.Cookie, "cxsparse", 8);
Dynamic.DataOffset = NtoHll (0xFFFFFFFFFFFFFFFFLL);
TableOffset = (uint64)(BytesPerSector*((sizeof(Dynamic)+sizeof(Footer)+BytesPerSector-1)/BytesPerSector));
TableOffset += VHD_DATA_BLOCK_ALIGNMENT-1;
TableOffset &= ~(VHD_DATA_BLOCK_ALIGNMENT-1);
TableOffset = NtoHll(Footer.DataOffset)+sizeof(Dynamic);
Dynamic.TableOffset = NtoHll (TableOffset);
Dynamic.HeaderVersion = NtoHl (0x00010000);
if (0 == BlockSize)
@ -3721,12 +3732,19 @@ while (sects) {
BlockOffset))
goto Fatal_IO_Error;
/* Write back just the aligned sector which contains the updated BAT entry */
BATUpdateBufferAddress = ((uint8 *)hVHD->BAT) +
(((((size_t)&hVHD->BAT[BlockNumber]) - (size_t)hVHD->BAT)/VHD_DATA_BLOCK_ALIGNMENT)*VHD_DATA_BLOCK_ALIGNMENT);
BATUpdateBufferSize = VHD_DATA_BLOCK_ALIGNMENT;
BATUpdateBufferAddress = (uint8 *)hVHD->BAT - (size_t)NtoHll(hVHD->Dynamic.TableOffset) +
(size_t)((((size_t)&hVHD->BAT[BlockNumber+1]) - (size_t)hVHD->BAT + (size_t)NtoHll(hVHD->Dynamic.TableOffset)) & ~(VHD_DATA_BLOCK_ALIGNMENT-1));
if (BATUpdateBufferAddress < (uint8 *)hVHD->BAT) {
BATUpdateBufferAddress = (uint8 *)hVHD->BAT;
BATUpdateBufferSize = (((((size_t)&hVHD->BAT[BlockNumber+1]) - (size_t)hVHD->BAT) + 511)/512)*512;
BATUpdateStorageAddress = NtoHll(hVHD->Dynamic.TableOffset);
}
else {
BATUpdateBufferSize = VHD_DATA_BLOCK_ALIGNMENT;
BATUpdateStorageAddress = NtoHll(hVHD->Dynamic.TableOffset) + BATUpdateBufferAddress - ((uint8 *)hVHD->BAT);
}
if ((size_t)(BATUpdateBufferAddress - (uint8 *)hVHD->BAT + BATUpdateBufferSize) > 512*((sizeof(*hVHD->BAT)*NtoHl(hVHD->Dynamic.MaxTableEntries) + 511)/512))
BATUpdateBufferSize = 512*((sizeof(*hVHD->BAT)*NtoHl(hVHD->Dynamic.MaxTableEntries) + 511)/512) - (BATUpdateBufferAddress - ((uint8 *)hVHD->BAT));
BATUpdateStorageAddress = NtoHll(hVHD->Dynamic.TableOffset) + BATUpdateBufferAddress - ((uint8 *)hVHD->BAT);
if (WriteFilePosition(hVHD->File,
BATUpdateBufferAddress,
BATUpdateBufferSize,