From 2d3720a9f5bbfe37f865d41f63f5c7b654e4ddae Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 17 Oct 2020 20:46:43 +0100 Subject: [PATCH] When dumping media if device returns "corrected error", consider it as a good read. --- .idea/.idea.Aaru/.idea/contentModel.xml | 13 +++++++++ Aaru.Core/Devices/Dumping/ATA.cs | 19 ++++++++----- Aaru.Core/Devices/Dumping/SBC.cs | 21 +++++++------- Aaru.Core/Devices/Reader.cs | 33 ++++++++++++---------- Aaru.Core/Devices/ReaderATA.cs | 37 +++++++++++++++++-------- Aaru.Core/Devices/ReaderSCSI.cs | 10 +++++-- Aaru.Core/Devices/Scanning/ATA.cs | 4 +-- Aaru.Core/Devices/Scanning/SCSI.cs | 4 +-- 8 files changed, 90 insertions(+), 51 deletions(-) diff --git a/.idea/.idea.Aaru/.idea/contentModel.xml b/.idea/.idea.Aaru/.idea/contentModel.xml index d3d390d86..f24091712 100644 --- a/.idea/.idea.Aaru/.idea/contentModel.xml +++ b/.idea/.idea.Aaru/.idea/contentModel.xml @@ -3,6 +3,9 @@ + + + @@ -13,6 +16,16 @@ + + + + + + + + + + diff --git a/Aaru.Core/Devices/Dumping/ATA.cs b/Aaru.Core/Devices/Dumping/ATA.cs index 772f41db7..bc22ab3db 100644 --- a/Aaru.Core/Devices/Dumping/ATA.cs +++ b/Aaru.Core/Devices/Dumping/ATA.cs @@ -56,6 +56,8 @@ namespace Aaru.Core.Devices.Dumping /// Dumps an ATA device 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); diff --git a/Aaru.Core/Devices/Dumping/SBC.cs b/Aaru.Core/Devices/Dumping/SBC.cs index af3eb6b15..4bf48adad 100644 --- a/Aaru.Core/Devices/Dumping/SBC.cs +++ b/Aaru.Core/Devices/Dumping/SBC.cs @@ -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); diff --git a/Aaru.Core/Devices/Reader.cs b/Aaru.Core/Devices/Reader.cs index 5e8833140..a06d79c45 100644 --- a/Aaru.Core/Devices/Reader.cs +++ b/Aaru.Core/Devices/Reader.cs @@ -73,7 +73,7 @@ namespace Aaru.Core.Devices internal uint PhysicalBlockSize { get; private set; } internal uint LongBlockSize { get; private set; } internal bool CanReadRaw { get; private set; } - internal bool CanSeek => _ataSeek || _seek6 || _seek10; + internal bool CanSeek => _ataSeek || _seek6 || _seek10; internal bool CanSeekLba => _ataSeekLba || _seek6 || _seek10; internal ulong GetDeviceBlocks() @@ -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; + 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; + buffer = null; + duration = 0d; + recoveredError = false; return true; } diff --git a/Aaru.Core/Devices/ReaderATA.cs b/Aaru.Core/Devices/ReaderATA.cs index 57adf9ad2..1e5423d7d 100644 --- a/Aaru.Core/Devices/ReaderATA.cs +++ b/Aaru.Core/Devices/ReaderATA.cs @@ -343,15 +343,16 @@ 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; AtaErrorRegistersLba28 errorLba; AtaErrorRegistersLba48 errorLba48; byte status = 0, errorByte = 0; - buffer = null; - duration = 0; + buffer = null; + duration = 0; + recoveredError = false; if(_ataReadDmaLba48) { @@ -416,20 +417,27 @@ namespace Aaru.Core.Devices _errorLog?.WriteLine(block, _dev.Error, _dev.LastError, errorLba); } - if(error) - AaruConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status); + if(!error) + return false; - return error; + if((status & 0x04) == 0x04) + recoveredError = true; + + AaruConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status); + + 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; AtaErrorRegistersChs errorChs; byte status = 0, errorByte = 0; - buffer = null; - duration = 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) - AaruConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status); + if(!error) + return false; - return error; + if((status & 0x04) == 0x04) + recoveredError = true; + + AaruConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status); + + return true; } bool AtaSeek(ulong block, out double duration) diff --git a/Aaru.Core/Devices/ReaderSCSI.cs b/Aaru.Core/Devices/ReaderSCSI.cs index 74c9a8484..59227fcd8 100644 --- a/Aaru.Core/Devices/ReaderSCSI.cs +++ b/Aaru.Core/Devices/ReaderSCSI.cs @@ -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; + 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; diff --git a/Aaru.Core/Devices/Scanning/ATA.cs b/Aaru.Core/Devices/Scanning/ATA.cs index a4c3277dd..48b9f0ed0 100644 --- a/Aaru.Core/Devices/Scanning/ATA.cs +++ b/Aaru.Core/Devices/Scanning/ATA.cs @@ -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) { diff --git a/Aaru.Core/Devices/Scanning/SCSI.cs b/Aaru.Core/Devices/Scanning/SCSI.cs index aef10d059..c13ebd52a 100644 --- a/Aaru.Core/Devices/Scanning/SCSI.cs +++ b/Aaru.Core/Devices/Scanning/SCSI.cs @@ -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)