Add option to skip more sectors than tried to read when a bad sector is found.

This commit is contained in:
2018-02-02 18:44:28 +00:00
parent 2a26a22e21
commit efcf1720e2
10 changed files with 91 additions and 61 deletions

View File

@@ -81,7 +81,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DumpLog dumpLog, Encoding encoding, string outputPrefix,
string outputPath,
Dictionary<string, string>
formatOptions, CICMMetadataType preSidecar)
formatOptions, CICMMetadataType preSidecar, uint skip)
{
bool aborted;
@@ -232,6 +232,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(ataReader.IsLba)
{
DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead);
if(skip < blocksToRead) skip = blocksToRead;
mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
ibgLog = new IbgLog(outputPrefix + ".ibg", ATA_PROFILE);
@@ -270,15 +271,16 @@ namespace DiscImageChef.Core.Devices.Dumping
}
else
{
for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b);
mhddLog.Write(i, duration < 500 ? 65535 : duration);
ibgLog.Write(i, 0);
DateTime writeStart = DateTime.Now;
outputPlugin.WriteSectors(new byte[blockSize * blocksToRead], i, blocksToRead);
outputPlugin.WriteSectors(new byte[blockSize * skip], i, skip);
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead;
}
double newSpeed =
@@ -428,7 +430,8 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1024 / (imageWriteDuration / 1000));
(double)blockSize * (double)(blocks + 1) / 1024 /
(imageWriteDuration / 1000));
}
foreach(ulong bad in resume.BadBlocks) dumpLog.WriteLine("Sector {0} could not be read.", bad);
@@ -594,8 +597,10 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.WriteLine();
DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming, {3:F3} writing, {4:F3} closing).",
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000, imageWriteDuration, (closeEnd -closeStart).TotalSeconds);
DicConsole
.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming, {3:F3} writing, {4:F3} closing).",
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000,
imageWriteDuration, (closeEnd - closeStart).TotalSeconds);
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000));
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);

View File

@@ -91,7 +91,7 @@ namespace DiscImageChef.Core.Devices.Dumping
string
outputPrefix, string outputPath, Dictionary<string, string> formatOptions,
CICMMetadataType
preSidecar)
preSidecar, uint skip)
{
uint subSize;
DateTime start;
@@ -662,6 +662,8 @@ namespace DiscImageChef.Core.Devices.Dumping
double imageWriteDuration = 0;
if(skip < blocksToRead) skip = blocksToRead;
// Start reading
start = DateTime.UtcNow;
for(int t = 0; t < tracks.Length; t++)
@@ -733,20 +735,22 @@ namespace DiscImageChef.Core.Devices.Dumping
DateTime writeStart = DateTime.Now;
if(supportedSubchannel != MmcSubchannel.None)
{
outputPlugin.WriteSectorsLong(new byte[SECTOR_SIZE * blocksToRead], i, blocksToRead);
outputPlugin.WriteSectorsTag(new byte[subSize * blocksToRead], i, blocksToRead,
outputPlugin.WriteSectorsLong(new byte[SECTOR_SIZE * skip], i, skip);
outputPlugin.WriteSectorsTag(new byte[subSize * skip], i, skip,
SectorTagType.CdSectorSubchannel);
}
else outputPlugin.WriteSectorsLong(new byte[blockSize * blocksToRead], i, blocksToRead);
else outputPlugin.WriteSectorsLong(new byte[blockSize * skip], i, skip);
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b);
DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}", Sense.PrettifySense(senseBuf));
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
ibgLog.Write(i, 0);
dumpLog.WriteLine("Error reading {0} sectors from sector {1}.", blocksToRead, i);
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead;
}
double newSpeed =
@@ -963,7 +967,9 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.WriteLine();
DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming, {3:F3} writing, {4:F3} closing).",
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000, imageWriteDuration, (closeEnd-closeStart).TotalSeconds);
(end - start).TotalSeconds, totalDuration / 1000,
totalChkDuration / 1000,
imageWriteDuration, (closeEnd - closeStart).TotalSeconds);
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000));
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);

View File

@@ -84,7 +84,7 @@ namespace DiscImageChef.Core.Devices.Dumping
string
outputPrefix, string outputPath, Dictionary<string, string> formatOptions,
CICMMetadataType
preSidecar)
preSidecar, uint skip)
{
bool sense;
ulong blocks;
@@ -200,7 +200,7 @@ namespace DiscImageChef.Core.Devices.Dumping
{
CompactDisc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError,
ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath,
formatOptions, preSidecar);
formatOptions, preSidecar, skip);
return;
}
@@ -602,13 +602,13 @@ namespace DiscImageChef.Core.Devices.Dumping
{
Xgd.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags,
ref dskType, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions,
preSidecar);
preSidecar, skip);
return;
}
Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags,
ref dskType, true, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions,
preSidecar);
preSidecar, skip);
}
internal static void AddMediaTagToSidecar(string outputPath,

View File

@@ -50,7 +50,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DumpLog dumpLog, Encoding encoding, string outputPrefix,
string outputPath,
Dictionary<string, string>
formatOptions, CICMMetadataType preSidecar)
formatOptions, CICMMetadataType preSidecar, uint skip)
{
throw new NotImplementedException("NVMe devices not yet supported.");
}

View File

@@ -86,7 +86,8 @@ namespace DiscImageChef.Core.Devices.Dumping
ref DumpLog dumpLog, Encoding encoding, string outputPrefix,
string outputPath,
Dictionary<string, string> formatOptions,
CICMMetadataType preSidecar)
CICMMetadataType preSidecar,
uint skip)
{
bool sense;
ulong blocks;
@@ -387,15 +388,16 @@ namespace DiscImageChef.Core.Devices.Dumping
// Write empty data
DateTime writeStart = DateTime.Now;
outputPlugin.WriteSectors(new byte[blockSize * blocksToRead], i, blocksToRead);
outputPlugin.WriteSectors(new byte[blockSize * skip], i, skip);
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b);
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
ibgLog.Write(i, 0);
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead;
}
double newSpeed =
@@ -883,7 +885,9 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.WriteLine();
DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming, {3:F3} writing, {4:F3} closing).",
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000, imageWriteDuration, (closeEnd -closeStart).TotalSeconds);
(end - start).TotalSeconds, totalDuration / 1000,
totalChkDuration / 1000,
imageWriteDuration, (closeEnd - closeStart).TotalSeconds);
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000));
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);

View File

@@ -79,7 +79,7 @@ namespace DiscImageChef.Core.Devices.Dumping
string
outputPath, Dictionary<string, string> formatOptions,
CICMMetadataType
preSidecar)
preSidecar, uint skip)
{
MediaType dskType = MediaType.Unknown;
int resets = 0;
@@ -212,12 +212,12 @@ namespace DiscImageChef.Core.Devices.Dumping
case PeripheralDeviceTypes.MultiMediaDevice:
Mmc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError,
ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath,
formatOptions, preSidecar);
formatOptions, preSidecar, skip);
return;
default:
Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, null,
ref dskType, false, ref resume, ref dumpLog, encoding, outputPrefix, outputPath,
formatOptions, preSidecar);
formatOptions, preSidecar, skip);
break;
}
}

View File

@@ -79,7 +79,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DumpLog dumpLog, Encoding encoding, string outputPrefix,
string outputPath,
Dictionary<string, string>
formatOptions, CICMMetadataType preSidecar)
formatOptions, CICMMetadataType preSidecar, uint skip)
{
bool aborted;
@@ -234,6 +234,8 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
if(skip < blocksToRead) skip = blocksToRead;
DumpHardwareType currentTry = null;
ExtentsULong extents = null;
ResumeSupport.Process(true, false, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformId,
@@ -316,15 +318,16 @@ namespace DiscImageChef.Core.Devices.Dumping
}
else
{
for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b);
mhddLog.Write(i, duration < 500 ? 65535 : duration);
ibgLog.Write(i, 0);
DateTime writeStart = DateTime.Now;
outputPlugin.WriteSectors(new byte[blockSize * blocksToRead], i, blocksToRead);
outputPlugin.WriteSectors(new byte[blockSize * skip], i, skip);
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead;
}
double newSpeed =
@@ -598,7 +601,9 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.WriteLine();
DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming, {3:F3} writing, {4:F3} closing).",
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000, imageWriteDuration, (closeEnd -closeStart).TotalSeconds);
(end - start).TotalSeconds, totalDuration / 1000,
totalChkDuration / 1000,
imageWriteDuration, (closeEnd - closeStart).TotalSeconds);
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000));
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);

View File

@@ -88,7 +88,7 @@ namespace DiscImageChef.Core.Devices.Dumping
ref DumpLog dumpLog,
Encoding encoding, string outputPrefix, string outputPath,
Dictionary<string, string> formatOptions,
CICMMetadataType preSidecar)
CICMMetadataType preSidecar, uint skip)
{
bool sense;
ulong blocks;
@@ -311,6 +311,8 @@ namespace DiscImageChef.Core.Devices.Dumping
return;
}
if(skip < blocksToRead) skip = blocksToRead;
bool ret = true;
foreach(MediaTagType tag in mediaTags.Keys)
@@ -438,17 +440,18 @@ namespace DiscImageChef.Core.Devices.Dumping
// Write empty data
DateTime writeStart = DateTime.Now;
outputPlugin.WriteSectors(new byte[BLOCK_SIZE * blocksToRead], i, blocksToRead);
outputPlugin.WriteSectors(new byte[BLOCK_SIZE * skip], i, skip);
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b);
DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}", Sense.PrettifySense(senseBuf));
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
ibgLog.Write(i, 0);
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead;
string[] senseLines = Sense.PrettifySense(senseBuf).Split(new[] {Environment.NewLine},
StringSplitOptions
.RemoveEmptyEntries);
@@ -577,7 +580,7 @@ namespace DiscImageChef.Core.Devices.Dumping
// Write empty data
DateTime writeStart = DateTime.Now;
outputPlugin.WriteSectors(new byte[BLOCK_SIZE * blocksToRead], currentSector, blocksToRead);
outputPlugin.WriteSectors(new byte[BLOCK_SIZE * skip], currentSector, skip);
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
// TODO: Handle errors in video partition
@@ -587,7 +590,8 @@ namespace DiscImageChef.Core.Devices.Dumping
mhddLog.Write(l1, cmdDuration < 500 ? 65535 : cmdDuration);
ibgLog.Write(l1, 0);
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, l1);
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, l1);
l1 += skip - blocksToRead;
string[] senseLines = Sense.PrettifySense(senseBuf).Split(new[] {Environment.NewLine},
StringSplitOptions.RemoveEmptyEntries);
foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine);
@@ -861,7 +865,9 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.WriteLine();
DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming, {3:F3} writing, {4:F3} closing).",
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000, imageWriteDuration, (closeEnd -closeStart).TotalSeconds);
(end - start).TotalSeconds, totalDuration / 1000,
totalChkDuration / 1000,
imageWriteDuration, (closeEnd - closeStart).TotalSeconds);
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
(double)BLOCK_SIZE * (double)(blocks + 1) / 1048576 / (totalDuration / 1000));
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);

View File

@@ -76,6 +76,7 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", options.Force);
DicConsole.DebugWriteLine("Dump-Media command", "--options={0}", options.Options);
DicConsole.DebugWriteLine("Dump-Media command", "--cicm-xml={0}", options.CicmXml);
DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", options.Skip);
Dictionary<string, string> parsedOptions = Options.Parse(options.Options);
DicConsole.DebugWriteLine("Dump-Media command", "Parsed options:");
@@ -205,24 +206,24 @@ namespace DiscImageChef.Commands
case DeviceType.ATA:
Ata.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw,
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix,
options.OutputFile, parsedOptions, sidecar);
options.OutputFile, parsedOptions, sidecar, options.Skip);
break;
case DeviceType.MMC:
case DeviceType.SecureDigital:
SecureDigital.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force,
options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog,
encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar);
encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar, options.Skip);
break;
case DeviceType.NVMe:
NvMe.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw,
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix,
options.OutputFile, parsedOptions, sidecar);
options.OutputFile, parsedOptions, sidecar, options.Skip);
break;
case DeviceType.ATAPI:
case DeviceType.SCSI:
Scsi.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw,
options.Persistent, options.StopOnError, ref resume, ref dumpLog, options.LeadIn,
encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar);
encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar, options.Skip);
break;
default:
dumpLog.WriteLine("Unknown device type.");

View File

@@ -308,6 +308,9 @@ namespace DiscImageChef
[Option('x', "cicm-xml", Default = null, HelpText = "Take metadata from existing CICM XML sidecar.")]
public string CicmXml { get; set; }
[Option('k', "skip", Default = 512, HelpText = "When an unreadable sector is found skip this many sectors.")]
public uint Skip { get; set; }
}
[Verb("device-report", HelpText = "Tests the device capabilities and creates an XML report of them.")]