When dumping media if device returns "corrected error", consider it as a good read.

This commit is contained in:
2020-10-17 20:46:43 +01:00
parent ba8b98e6ec
commit 2d3720a9f5
8 changed files with 90 additions and 51 deletions

View File

@@ -3,6 +3,9 @@
<component name="ContentModelStore">
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/extResources" t="IncludeRecursive" />
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/resharper-host/local/Transient/Rider/v202/SolutionCaches/_Aaru.232757112.00" t="ExcludeRecursive" />
<e p="$APPLICATION_CONFIG_DIR$/consoles/db" t="IncludeRecursive" />
<e p="$APPLICATION_CONFIG_DIR$/extensions" t="IncludeRecursive" />
<e p="$APPLICATION_CONFIG_DIR$/scratches" t="IncludeRecursive" />
<e p="$USER_HOME$/.config/git/ignore" t="IncludeRecursive" />
<e p="$APPLICATION_PLUGINS_DIR$/puppet/lib/stubs" t="IncludeRecursive" />
<e p="$USER_HOME$/.nuget/packages/microsoft.net.test.sdk/16.4.0/build/netcoreapp2.1" t="Include">
@@ -13,6 +16,16 @@
<e p="$USER_HOME$/.nuget/packages/nunit3testadapter/3.15.1/build/netcoreapp2.0/nunit.engine.api.dll" t="Include" />
<e p="$USER_HOME$/.nuget/packages/nunit3testadapter/3.15.1/build/netcoreapp2.0/nunit.engine.dll" t="Include" />
<e p="$PROJECT_DIR$" t="IncludeFlat">
<e p=".git/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/Aaru.Checksums/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/Aaru.CommonTypes/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/Aaru.Console/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/Aaru.Decoders/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/Aaru.Dto/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/Aaru.Helpers/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/CICMMetadata/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/cuetools.net/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/cuetoolsnet/info/exclude" t="IncludeRecursive" />
<e p=".github/CODE_OF_CONDUCT.md" t="Include" />
<e p=".github/ISSUE_TEMPLATE.md" t="Include" />
<e p=".github/PULL_REQUEST_TEMPLATE.md" t="Include" />

View File

@@ -56,6 +56,8 @@ namespace Aaru.Core.Devices.Dumping
/// <summary>Dumps an ATA device</summary>
void Ata()
{
bool recoveredError;
if(_dumpRaw)
{
if(_force)
@@ -288,7 +290,7 @@ namespace Aaru.Core.Devices.Dumping
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)",
(long)i, (long)blocks);
bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration);
bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration, out _);
if(!error)
{
@@ -380,11 +382,12 @@ namespace Aaru.Core.Devices.Dumping
PulseProgress?.Invoke($"Trimming sector {badSector}");
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration);
bool error =
ataReader.ReadBlock(out cmdBuf, badSector, out duration, out recoveredError);
totalDuration += duration;
if(error)
if(error && !recoveredError)
continue;
_resume.BadBlocks.Remove(badSector);
@@ -426,11 +429,12 @@ namespace Aaru.Core.Devices.Dumping
pass, forward ? "forward" : "reverse",
_persistent ? "recovering partial data, " : ""));
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration);
bool error =
ataReader.ReadBlock(out cmdBuf, badSector, out duration, out recoveredError);
totalDuration += duration;
if(!error)
if(!error || recoveredError)
{
_resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
@@ -502,11 +506,12 @@ namespace Aaru.Core.Devices.Dumping
PulseProgress?.
Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)");
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration);
bool error =
ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration, out recoveredError);
totalDuration += duration;
if(!error)
if(!error || recoveredError)
{
mhddLog.Write(currentBlock, duration);
ibgLog.Write(currentBlock, currentSpeed * 1024);

View File

@@ -81,6 +81,7 @@ namespace Aaru.Core.Devices.Dumping
byte[] readBuffer;
Modes.DecodedMode? decMode = null;
bool ret;
bool recoveredError;
if(opticalDisc)
switch(dskType)
@@ -621,7 +622,7 @@ namespace Aaru.Core.Devices.Dumping
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", (long)i,
(long)blocks);
sense = scsiReader.ReadBlocks(out readBuffer, i, blocksToRead, out double cmdDuration);
sense = scsiReader.ReadBlocks(out readBuffer, i, blocksToRead, out double cmdDuration, out _);
totalDuration += cmdDuration;
if(!sense &&
@@ -736,9 +737,10 @@ namespace Aaru.Core.Devices.Dumping
PulseProgress?.Invoke($"Trimming sector {badSector}");
sense = scsiReader.ReadBlock(out readBuffer, badSector, out double _);
sense = scsiReader.ReadBlock(out readBuffer, badSector, out double _, out recoveredError);
if(sense || _dev.Error)
if((sense || _dev.Error) &&
!recoveredError)
continue;
_resume.BadBlocks.Remove(badSector);
@@ -785,9 +787,7 @@ namespace Aaru.Core.Devices.Dumping
if(dcMode10?.Pages != null)
foreach(Modes.ModePage modePage in dcMode10.Value.Pages.Where(modePage =>
modePage.Page ==
0x01 && modePage.
Subpage == 0x00))
modePage.Page == 0x01 && modePage.Subpage == 0x00))
currentModePage = modePage;
}
}
@@ -796,8 +796,8 @@ namespace Aaru.Core.Devices.Dumping
Modes.DecodedMode? dcMode6 = Modes.DecodeMode6(readBuffer, _dev.ScsiType);
if(dcMode6?.Pages != null)
foreach(var modePage in dcMode6.Value.Pages.Where(modePage => modePage.Page == 0x01 &&
modePage.Subpage == 0x00))
foreach(Modes.ModePage modePage in dcMode6.Value.Pages.Where(modePage =>
modePage.Page == 0x01 && modePage.Subpage == 0x00))
currentModePage = modePage;
}
@@ -946,11 +946,10 @@ namespace Aaru.Core.Devices.Dumping
forward ? "forward" : "reverse",
runningPersistent ? "recovering partial data, " : ""));
sense = scsiReader.ReadBlock(out readBuffer, badSector, out double cmdDuration);
sense = scsiReader.ReadBlock(out readBuffer, badSector, out double cmdDuration, out recoveredError);
totalDuration += cmdDuration;
if(!sense &&
!_dev.Error)
if((!sense && !_dev.Error) || recoveredError)
{
_resume.BadBlocks.Remove(badSector);
extents.Add(badSector);

View File

@@ -132,35 +132,40 @@ namespace Aaru.Core.Devices
}
}
internal bool ReadBlock(out byte[] buffer, ulong block, out double duration) =>
ReadBlocks(out buffer, block, 1, out duration);
internal bool ReadBlock(out byte[] buffer, ulong block, out double duration, out bool recoveredError) =>
ReadBlocks(out buffer, block, 1, out duration, out recoveredError);
internal bool ReadBlocks(out byte[] buffer, ulong block, out double duration) =>
ReadBlocks(out buffer, block, BlocksToRead, out duration);
internal bool ReadBlocks(out byte[] buffer, ulong block, out double duration, out bool recoveredError) =>
ReadBlocks(out buffer, block, BlocksToRead, out duration, out recoveredError);
internal bool ReadBlocks(out byte[] buffer, ulong block, uint count, out double duration)
internal bool ReadBlocks(out byte[] buffer, ulong block, uint count, out double duration,
out bool recoveredError)
{
switch(_dev.Type)
{
case DeviceType.ATA: return AtaReadBlocks(out buffer, block, count, out duration);
case DeviceType.ATA: return AtaReadBlocks(out buffer, block, count, out duration, out recoveredError);
case DeviceType.ATAPI:
case DeviceType.SCSI: return ScsiReadBlocks(out buffer, block, count, out duration);
case DeviceType.SCSI: return ScsiReadBlocks(out buffer, block, count, out duration, out recoveredError);
default:
buffer = null;
duration = 0d;
recoveredError = false;
return true;
}
}
internal bool ReadChs(out byte[] buffer, ushort cylinder, byte head, byte sector, out double duration)
internal bool ReadChs(out byte[] buffer, ushort cylinder, byte head, byte sector, out double duration,
out bool recoveredError)
{
switch(_dev.Type)
{
case DeviceType.ATA: return AtaReadChs(out buffer, cylinder, head, sector, out duration);
case DeviceType.ATA:
return AtaReadChs(out buffer, cylinder, head, sector, out duration, out recoveredError);
default:
buffer = null;
duration = 0d;
recoveredError = false;
return true;
}

View File

@@ -343,7 +343,7 @@ namespace Aaru.Core.Devices
return true;
}
bool AtaReadBlocks(out byte[] buffer, ulong block, uint count, out double duration)
bool AtaReadBlocks(out byte[] buffer, ulong block, uint count, out double duration, out bool recoveredError)
{
bool error = true;
bool sense;
@@ -352,6 +352,7 @@ namespace Aaru.Core.Devices
byte status = 0, errorByte = 0;
buffer = null;
duration = 0;
recoveredError = false;
if(_ataReadDmaLba48)
{
@@ -416,13 +417,19 @@ namespace Aaru.Core.Devices
_errorLog?.WriteLine(block, _dev.Error, _dev.LastError, errorLba);
}
if(error)
if(!error)
return false;
if((status & 0x04) == 0x04)
recoveredError = true;
AaruConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
return error;
return true;
}
bool AtaReadChs(out byte[] buffer, ushort cylinder, byte head, byte sector, out double duration)
bool AtaReadChs(out byte[] buffer, ushort cylinder, byte head, byte sector, out double duration,
out bool recoveredError)
{
bool error = true;
bool sense;
@@ -430,6 +437,7 @@ namespace Aaru.Core.Devices
byte status = 0, errorByte = 0;
buffer = null;
duration = 0;
recoveredError = false;
if(_ataReadDmaRetry)
{
@@ -475,10 +483,15 @@ namespace Aaru.Core.Devices
_errorLog?.WriteLine(cylinder, head, sector, _dev.Error, _dev.LastError, errorChs);
}
if(error)
if(!error)
return false;
if((status & 0x04) == 0x04)
recoveredError = true;
AaruConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
return error;
return true;
}
bool AtaSeek(ulong block, out double duration)

View File

@@ -571,12 +571,13 @@ namespace Aaru.Core.Devices
return true;
}
bool ScsiReadBlocks(out byte[] buffer, ulong block, uint count, out double duration)
bool ScsiReadBlocks(out byte[] buffer, ulong block, uint count, out double duration, out bool recoveredError)
{
bool sense;
byte[] senseBuf;
buffer = null;
duration = 0;
recoveredError = false;
if(CanReadRaw)
if(_readLong16)
@@ -624,6 +625,9 @@ namespace Aaru.Core.Devices
!_dev.Error)
return false;
recoveredError = Sense.DecodeFixed(senseBuf)?.SenseKey == SenseKeys.RecoveredError ||
Sense.DecodeDescriptor(senseBuf)?.SenseKey == SenseKeys.RecoveredError;
AaruConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}", Sense.PrettifySense(senseBuf));
return sense;

View File

@@ -152,7 +152,7 @@ namespace Aaru.Core.Devices.Scanning
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
(long)i, (long)results.Blocks);
bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration);
bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration, out _);
if(!error)
{
@@ -268,7 +268,7 @@ namespace Aaru.Core.Devices.Scanning
PulseProgress?.
Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)");
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration);
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration, out _);
if(!error)
{

View File

@@ -481,7 +481,7 @@ namespace Aaru.Core.Devices.Scanning
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
(long)i, (long)results.Blocks);
sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out double cmdDuration);
sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out double cmdDuration, out _);
results.ProcessingTime += cmdDuration;
if(!sense &&
@@ -563,7 +563,7 @@ namespace Aaru.Core.Devices.Scanning
if(scsiReader.CanSeek)
scsiReader.Seek(seekPos, out seekCur);
else
scsiReader.ReadBlock(out _, seekPos, out seekCur);
scsiReader.ReadBlock(out _, seekPos, out seekCur, out _);
if(seekCur > results.SeekMax &&
seekCur > 0)