From 448ee4ad3cee795997d28126f18ceb787c9f5c8d Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Mon, 11 Feb 2013 09:48:36 -0800 Subject: [PATCH] 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. --- sim_disk.c | 50 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/sim_disk.c b/sim_disk.c index abf50e78..4f0a17d5 100644 --- a/sim_disk.c +++ b/sim_disk.c @@ -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,