From 8dd8701e8d35e2253918c26fba8282cb262c1e7a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 25 Mar 2022 18:45:28 -0600 Subject: [PATCH] Split read phase into two parts Addresses issue #184 The first read phase will skip a lot more to try to recover more data from the whole source. Then the second read phase will fill in like the previous configuration. --- scripts/wk/cfg/ddrescue.py | 12 ++++++++--- scripts/wk/hw/ddrescue.py | 41 ++++++++++++++++++-------------------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/scripts/wk/cfg/ddrescue.py b/scripts/wk/cfg/ddrescue.py index 02b7de36..15f5f46d 100644 --- a/scripts/wk/cfg/ddrescue.py +++ b/scripts/wk/cfg/ddrescue.py @@ -16,9 +16,10 @@ TMUX_LAYOUT = OrderedDict({ # ddrescue AUTO_PASS_THRESHOLDS = { # NOTE: The scrape key is set to infinity to force a break - 'read': 95, - 'trim': 98, - 'scrape': float('inf'), + 'read-skip': 50, + 'read-full': 95, + 'trim': 98, + 'scrape': float('inf'), } DDRESCUE_MAP_TEMPLATE = '''# Mapfile. Created by {name} 0x0 ? 1 @@ -54,6 +55,11 @@ DDRESCUE_SETTINGS = { '--timeout': {'Selected': False, 'Value': '30m', }, }, } +DDRESCUE_SPECIFIC_PASS_SETTINGS = { + 'read-skip': ['--no-scrape', '--no-trim', '--cpass=1,2'], + 'read-full': ['--no-scrape', '--no-trim'], + 'trim': ['--no-scrape'], + } DRIVE_POWEROFF_TIMEOUT = 90 PARTITION_TYPES = { 'GPT': { diff --git a/scripts/wk/hw/ddrescue.py b/scripts/wk/hw/ddrescue.py index fc3724dc..e457dfe2 100644 --- a/scripts/wk/hw/ddrescue.py +++ b/scripts/wk/hw/ddrescue.py @@ -22,7 +22,11 @@ import psutil import pytz from wk import cfg, debug, exe, io, log, net, std, tmux -from wk.cfg.ddrescue import DDRESCUE_MAP_TEMPLATE, DDRESCUE_SETTINGS +from wk.cfg.ddrescue import ( + DDRESCUE_MAP_TEMPLATE, + DDRESCUE_SETTINGS, + DDRESCUE_SPECIFIC_PASS_SETTINGS, + ) from wk.hw import obj as hw_obj @@ -105,11 +109,11 @@ SETTING_PRESETS = ( 'Safe', ) STATUS_COLORS = { - 'Passed': 'GREEN', - 'Aborted': 'YELLOW', - 'Skipped': 'YELLOW', - 'Working': 'YELLOW', - 'ERROR': 'RED', + 'Passed': 'GREEN', + 'Aborted': 'YELLOW', + 'Skipped': 'YELLOW', + 'Working': 'YELLOW', + 'ERROR': 'RED', } TIMEZONE = pytz.timezone(cfg.main.LINUX_TIME_ZONE) @@ -131,9 +135,10 @@ class BlockPair(): self.map_path = None self.size = source.details['size'] self.status = OrderedDict({ - 'read': 'Pending', - 'trim': 'Pending', - 'scrape': 'Pending', + 'read-skip': 'Pending', + 'read-full': 'Pending', + 'trim': 'Pending', + 'scrape': 'Pending', }) self.view_map = 'DISPLAY' in os.environ or 'WAYLAND_DISPLAY' in os.environ @@ -305,10 +310,9 @@ class BlockPair(): # Mark future passes as skipped if applicable if percent == 100: - if pass_name == 'read': - self.status['trim'] = 'Skipped' - if pass_name in ('read', 'trim'): - self.status['scrape'] = 'Skipped' + status_keys = list(self.status.keys()) + for i in status_keys[status_keys.index(pass_name)+1:]: + self.status[status_keys[i]] = 'Skipped' class State(): @@ -1217,14 +1221,7 @@ def build_ddrescue_cmd(block_pair, pass_name, settings_menu): if (block_pair.destination.is_block_device() or block_pair.destination.is_char_device()): cmd.append('--force') - if pass_name == 'read': - cmd.extend(['--no-trim', '--no-scrape']) - elif pass_name == 'trim': - # Allow trimming - cmd.append('--no-scrape') - elif pass_name == 'scrape': - # Allow trimming and scraping - pass + cmd.extend(DDRESCUE_SPECIFIC_PASS_SETTINGS.get(pass_name, [])) # Fix domain size based on starting position domain_size = block_pair.size @@ -2172,7 +2169,7 @@ def run_recovery(state, main_menu, settings_menu, dry_run=True): ) # Run pass(es) - for pass_name in ('read', 'trim', 'scrape'): + for pass_name in ('read-skip', 'read-full', 'trim', 'scrape'): abort = False # Skip to next pass