ब्लॉग पर वापस जाएं
7 अक्टूबर 2026Sergei Solod24 मिनट पढ़ें

GNU ddrescue द्वारा 4 TB ड्राइव का 99.999654% कॉपी किए जाने के बाद मैंने करप्ट APFS क्लोन से फ़ाइलें कैसे रिकवर कीं

GNU ddrescue ने फेल हो रही 4 TB HDD का 99.999654% कॉपी कर लिया, लेकिन APFS क्लोन फिर भी फ़ाइल सिस्टम जाँच में फेल हुआ और The Sleuth Kit पाथ्स सूचीबद्ध कर सकता था, जबकि ज़ीरो-बाइट फ़ाइलें लौट रही थीं। मैंने रीड-ओनली मास्टर क्लोन को सुरक्षित रखकर, libfsapfs पर स्विच करके और रिज़्यूमेबल एक्सट्रैक्शन पाइपलाइन बनाकर चुने हुए डायरेक्टरी ट्री रिकवर किए।

APFSGNU ddrescueडेटा रिकवरीlibfsapfsmacOS

GNU ddrescue ने 100.00% दिखाया। मेरी पहली संरचित फ़ाइल-रिकवरी पास का नतीजा 0 useful recovered user files था।

ये दोनों नतीजे उसी 4 TB हार्ड-ड्राइव फेल्यर से आए थे, और यही विरोधाभास इस रिकवरी को “खराब डिस्क को क्लोन करो और फ़ाइल्स कॉपी कर लो” से कहीं ज्यादा दिलचस्प बना गया। ddrescue ने अपना काम असाधारण रूप से अच्छी तरह किया था: उसने फ़िज़िकल सोर्स का लगभग 99.999654% कॉपी कर लिया था। क्लोन स्वस्थ हार्डवेयर पर था। फिर भी APFS करप्ट था, macOS फ़ाइल सिस्टम को सामान्य तरीके से उपलब्ध नहीं करा रहा था, और पहला APFS रिकवरी स्टैक डायरेक्टरी ट्री के बड़े हिस्सों को एन्यूमरेट कर सकता था, लेकिन सामान्य फ़ाइल्स का कंटेंट पढ़ने में विफल हो रहा था।

आखिरकार मैंने वे सभी चुने हुए, एन्यूमरेट किए जा सकने वाले फ़ोल्डर ट्रीज़ रिकवर कर लिए जिनकी मुझे जरूरत थी, लेकिन यह तभी संभव हुआ जब मैंने घटना को तीन अलग समस्याओं की तरह लिया: फ़िज़िकल ब्लॉक रिकवरी, डैमेज्ड फ़ाइल सिस्टम की इंटरप्रिटेशन, और वैलिडेशन व रिज़्यूम सपोर्ट के साथ लार्ज-स्केल फ़ाइल एक्सट्रैक्शन।

फेल्यर सबसे पहले फ़ाइल सिस्टम की समस्या रहना बंद हुआ

मूल 4 TB Toshiba उस स्थिति में पहुँच चुका था जहाँ मैं सामान्य फ़ाइल सिस्टम एक्टिविटी के लिए उस पर भरोसा नहीं कर सकता था। कुछ रीड्स में 60–75 सेकंड लग रहे थे। ऑपरेशन्स हैंग हो सकती थीं। ड्राइव कभी-कभी macOS से गायब हो जाती थी, साफ सुनाई देने वाली क्लिकिंग करती थी और कभी-कभी पावर डाउन भी हो जाती थी।

फेल्यर से कुछ समय पहले मैंने लगभग 300 GB अतिरिक्त डेटा लिखा था और करीब 500,000 फ़ाइल्स व डायरेक्टरीज़ को प्रभावित करने वाला मास रीनेम किया था। टाइमिंग की वजह से मेटाडेटा-हेवी वर्कलोड संदिग्ध लगा, लेकिन मैं यह साबित नहीं कर सकता कि उसी ने हार्डवेयर फेल्यर पैदा किया। यह भी हो सकता है कि उसने पहले से अस्वस्थ ड्राइव पर इतना स्ट्रेस डाला हो कि समस्या सामने आ गई।

मैं जो निश्चित रूप से स्थापित कर सकता था, वह ड्राइव का व्यवहार था। जब मैकेनिकल स्टोरेज स्टॉल करने लगे, गायब होने लगे और क्लिक करे, तब बार-बार डायरेक्टरीज़ ब्राउज़ करना गलत एब्स्ट्रैक्शन है। डायरेक्टरी ट्रैवर्सल और रीड्स व सीक्स ट्रिगर कर सकता है। फ़ाइल सिस्टम माउंट करना मेटाडेटा वर्क ट्रिगर कर सकता है। हर एक्सपेरिमेंट उसी एक कम्पोनेंट का समय खर्च करता है जिसकी बाकी उपयोगी लाइफ़ अज्ञात है।

इसलिए मैंने लक्ष्य को इससे:

recover my files

बदलकर यह कर दिया:

recover as many readable sectors as possible

मैंने पर्सिस्टेंट mapfile के साथ GNU ddrescue 1.30 इस्तेमाल किया। सोर्स ड्राइव का एग्ज़ैक्ट फ़िज़िकल साइज़ था:

4,000,787,027,968 bytes

mapfile जरूरी था, क्योंकि सोर्स वन-शॉट कॉपी के लिए पर्याप्त स्टेबल नहीं था। इसकी वजह से रिकवरी स्टॉल्स, डिस्कनेक्ट्स, रीस्टार्ट्स और बाद की पासेस से बच सकी, बिना यह भूले कि कौन-से रीजन पहले ही रिकवर हो चुके थे।

रॉ macOS डिवाइस पाथ के साथ एक प्रैक्टिकल इश्यू भी आया: दिखाई देने वाला रेस्क्यू एक्स्टेंट वास्तविक डिवाइस बाउंड्री पर खत्म होने के बजाय बेतुका हो सकता था। इसलिए मैंने रेस्क्यू डोमेन को ऊपर दिए नोन फ़िज़िकल साइज़ तक सीमित किया। इस मामले में इनपुट को स्पष्ट रूप से बाउंड करना स्पीड ऑप्टिमाइज़ेशन नहीं, करेक्टनेस उपाय था।

ddrescue का 100.00% दिखाना यह नहीं बताता था कि फ़ाइल्स सुरक्षित थीं

फ़िज़िकल रेस्क्यू के अंत के पास ddrescue ने लगभग यह रिपोर्ट किया:

domain size:  4000 GB
rescued:      4000 GB
non-tried:   13481 kB
non-trimmed: 327680 B
non-scraped:      0 B
bad-sector:   27136 B

मुख्य परसेंटेज था:

100.00%

लेकिन अनरिज़ॉल्व्ड स्टेट्स का कुल योग अभी भी था:

13,835,816 bytes

या लगभग:

13.84 MB

4,000,787,027,968-बाइट सोर्स की तुलना में रिकवर्ड शेयर लगभग था:

99.999654%

यह ब्लॉक रिकवरी के लिए बेहतरीन रिज़ल्ट है। यह फ़ाइल इंटेग्रिटी का रिज़ल्ट नहीं है।

मिसिंग बाइट्स कहाँ हैं, यह मुख्य आँकड़ा से ज्यादा महत्वपूर्ण है। अनयूज़्ड स्पेस से गायब हुए कई मेगाबाइट्स शायद कुछ भी दिखाई देने लायक प्रभावित न करें। वीडियो के अंदर छोटा अनरीडेबल रीजन एक फ़ाइल को नुकसान पहुँचा सकता है। फ़ाइल सिस्टम मेटाडेटा में उससे कहीं छोटा लॉस कई अन्यथा इंटैक्ट डेटा एक्स्टेंट्स को लोकेट करना मुश्किल बना सकता है।

रिकवरी के बाकी हिस्से के लिए यही मेरा केंद्रीय मानसिक मॉडल बन गया:

लेयरयह किस सवाल का जवाब देता हैसक्सेस क्या साबित नहीं करता
ब्लॉक रिकवरीक्या फ़िज़िकल सेक्टर्स कॉपी हुए?कि APFS हर फ़ाइल रिकंस्ट्रक्ट कर सकता है
फ़ाइल सिस्टम रिकवरीक्या पाथ्स, मेटाडेटा और एक्स्टेंट्स रिज़ॉल्व किए जा सकते हैं?कि निकाला गया हर बाइट वैलिड है
फ़ाइल वैलिडेशनक्या फ़ाइल एक्सपेक्टेड साइज़ या हैश के साथ मिली?कि कोई अनडिस्कवरेबल फ़ाइल कभी मौजूद ही नहीं थी

मैंने बाकी अनरीड रीजन पर कुछ अंतिम अटेम्प्ट्स किए। Toshiba के जोर से क्लिक करने के दौरान वे आखिरकार कोई उपयोगी नई रीड्स देना बंद कर गए। वहीं मैंने ओरिजिनल ड्राइव को एक्टिव रिकवरी सोर्स की तरह इस्तेमाल करना बंद कर दिया।

एक 4 TB डिस्क रिकवर करने के लिए मैंने दो 5 TB ड्राइव्स क्यों खरीदीं

पहली नई ड्राइव 5 TB Seagate Expansion थी, जिसकी एग्ज़ैक्ट फ़िज़िकल कैपेसिटी थी:

5,000,981,077,504 bytes

मैंने Toshiba का ब्लॉक-लेवल क्लोन उस पर लिखा। सोर्स लेआउट लगभग शुरुआती 4 TB तक फैला था, जिससे कॉपीड लेआउट के बाद करीब 1 TB अतिरिक्त जगह बची। मैंने जानबूझकर उस अतिरिक्त कैपेसिटी को नहीं छुआ।

मैंने APFS कंटेनर को बड़ा नहीं किया। सुविधा के लिए क्लोन को रीपार्टिशन नहीं किया। उस पर फ़ाइल सिस्टम रिपेयर नहीं चलाया। वह डिस्क मास्टर क्लोन बन गई।

फिर मैंने दूसरी 5 TB ड्राइव खरीदी। वह फ्रेशली फ़ॉर्मैटेड, राइटेबल, इंडिपेंडेंटली टेस्टेड थी और सिर्फ रिकवर्ड आउटपुट के लिए इस्तेमाल हुई।

failing 4 TB HDD
        │
        │ GNU ddrescue
        ▼
5 TB drive #1
master block-level clone
READ-ONLY
        │
        │ APFS parsing and extraction
        ▼
5 TB drive #2
recovered files
WRITABLE

इसका मतलब लगभग 3.26 TB यूज़्ड डेटा वाले वॉल्यूम को रिकवर करने के लिए नॉमिनल तौर पर करीब 10 TB नया स्टोरेज खरीदना था। एक्स्ट्रा डिस्क कैपेसिटी के लिए नहीं थी। उसका उद्देश्य एक इनवेरिएंट बनाए रखना था:

If an experiment is wrong, I can return to the same untouched master clone.

मास्टर पर रिपेयर, रीसाइज़, रीपार्टिशन या रिकवर्ड आउटपुट लिखने से प्रिज़र्वेशन और एक्सपेरिमेंटेशन मिल जाते। सोर्स और डेस्टिनेशन को अलग फ़िज़िकल ड्राइव्स पर रखने से गलतियाँ रिकवरेबल रहीं।

डेस्टिनेशन पर भरोसा करने से पहले मैंने लगभग 10 GB राइट/रीड टेस्ट चलाया। उस टेस्ट में दोनों दिशाओं में लगभग 144.4 MB/s सस्टेन्ड थ्रूपुट मिला। मास्टर क्लोन से सैंपल रॉ रीड्स लगभग 28–49 MB/s थीं और उन चेक्स के दौरान ओरिजिनल ड्राइव वाला फ़िज़िकल I/O फेल्यर पैटर्न रीप्रोड्यूस नहीं हुआ।

उस बिंदु पर समस्या बदल चुकी थी। अब मैं फेलिंग हार्डवेयर डीबग नहीं कर रहा था। मैं ऐसे हार्डवेयर पर प्रिज़र्व्ड डैमेज्ड APFS मेटाडेटा डीबग कर रहा था जो मेरे टेस्ट्स में सामान्य व्यवहार कर रहा था।

APFS क्लोन डिवाइस के रूप में रीडेबल था, लेकिन फ़ाइल सिस्टम के रूप में इनवैलिड

क्लोन्ड APFS फ़िज़िकल स्टोर था:

4,000,650,887,168 bytes

रिलिवेंट पार्टिशन इस सेक्टर से शुरू हुआ:

264192

512-बाइट सेक्टर्स के साथ इसका बाइट ऑफ़सेट है:

135,266,304 bytes

APFS वॉल्यूम ने लगभग इतना कंज़्यूम्ड दिखाया:

3,260,976,717,824 bytes

।

रीड-ओनली APFS चेक आखिरकार fsroot ट्री तक पहुँचा और यह रिपोर्ट किया:

Checking fsroot tree.
error: (oid 0xe36cb) apfs_root:
btn: dev_read_finish(3828538, 1): Input/output error
fsroot tree is invalid.

यहीं “ddrescue ने लगभग पूरी डिस्क कॉपी कर ली” पूर्ण डायग्नोसिस के रूप में उपयोगी रहना बंद कर दिया। रॉ क्लोन मौजूद था। उसके अंदर की फ़ाइल सिस्टम स्ट्रक्चर अभी भी इनकंसिस्टेंट थी।

मैंने जानबूझकर फ़ाइल सिस्टम चेकिंग को नॉन-मॉडिफ़ाइंग रखा। मेरे पास मौजूद एकमात्र हाई-क्वालिटी मास्टर क्लोन पर fsck_apfs -n को रिपेयर ऑपरेशन में नहीं बदला। सामान्य स्टोरेज पर रिपेयर उचित हो सकता है, लेकिन यहाँ वह उस एविडेंस को बदल देता जिसे मैं अभी समझने की कोशिश कर रहा था।

The Sleuth Kit APFS नेमस्पेस सूचीबद्ध कर सकता था, लेकिन फ़ाइल कंटेंट्स पर विफल हुआ

The Sleuth Kit 4.15.0 पहला रिकवरी स्टैक था जिसने क्लोन को आशाजनक दिखाया। पूरे क्लोन्ड डिवाइस, नोन पार्टिशन ऑफ़सेट और मेरे पहचाने APFS सुपरब्लॉक का उपयोग करके मैं fls से वास्तविक डायरेक्टरी नेम्स एन्यूमरेट कर सकता था:

fls \\
  -o 264192 \\
  -B 4594668 \\
  -p \\
  /dev/rdiskN

मैं जानबूझकर N इस्तेमाल करता हूँ। macOS डिस्क नंबर्स रीकनेक्ट्स और रीबूट्स के बाद बदलते थे, इसलिए मैंने पुराने /dev/disk6 असाइनमेंट को आइडेंटिटी नहीं माना।

fls नेमस्पेस के बड़े हिस्सों में ट्रैवर्स कर सकता था। सिर्फ एक बड़े ट्री ने लगभग 8,900 डायरेक्टरीज़ दिखाईं। कुछ समय के लिए लगा कि कठिन हिस्सा हल हो गया है।

फिर मैंने फ़ाइल कंटेंट्स रिट्रीव करने की कोशिश की।

एक रिप्रेज़ेंटेटिव फेल्यर था:

libc++abi: terminating due to uncaught exception
of type std::runtime_error:
could not read APFSBlock

tsk_recover एक्सट्रैक्शन शुरू कर सकता था और फिर किसी APFS ब्लॉक पर फेल हो सकता था। अलग-अलग icat अटेम्प्ट्स ने भी इसी तरह की समस्या दिखाई।

महत्वपूर्ण अंतर यह था:

directory traversal works

इसका मतलब यह नहीं था:

file content retrieval works

किसी पार्सर के पास पाथनेम खोजने लायक सर्वाइविंग मेटाडेटा हो सकता है, लेकिन बाद में फ़ाइल ऑब्जेक्ट, एक्स्टेंट मेटाडेटा या बाइट स्ट्रीम लौटाने के लिए जरूरी कंटेंट ब्लॉक्स रिज़ॉल्व करते समय वह फिर भी फेल कर सकता है।

मैंने पहला बल्क रिकवरी इंजन फॉल्ट-टॉलरेंट बनाया, लेकिन पार्सर इस डैमेज के लिए फिर भी गलत था

मेरी पहली प्रतिक्रिया पार्सर तुरंत बदलने के बजाय TSK एक्सट्रैक्शन को ज्यादा रेज़िलिएंट बनाना थी।

मैंने fls और icat के आसपास Python रिकवरी रैपर बनाया। वह ड्यूरेबल स्टेट SQLite में रखता था, फेल्यर्स लॉग करता था, रिज़्यूम सपोर्ट करता था, पार्शियल आउटपुट अलग लिखता था और पहली पास में लो-वैल्यू macOS हाउसकीपिंग डेटा को डी-प्रायोरिटाइज़ करता था।

मैंने “हॉटस्पॉट” रूल भी जोड़ा: अगर एक डायरेक्टरी में लगातार चार फ़ाइल्स एक ही ज़ीरो-बाइट APFSBlock पैटर्न के साथ फेल हों, तो स्क्रिप्ट उस ब्रांच के बाकी हिस्से पर समय खर्च करना बंद कर देता, उसे डिफ़र करता और कहीं और आगे बढ़ जाता। वर्किंग हाइपोथेसिस यह थी कि एक जैसे फेल्यर्स का क्लस्टर सैकड़ों स्वतंत्र रूप से डेस्ट्रॉयड पेलोड्स की बजाय एक डैमेज्ड मेटाडेटा डिपेंडेंसी शेयर कर सकता है।

ऑर्केस्ट्रेशन उपयोगी थी। अंडरलाइंग APFS रीडर नहीं था।

एक कैप्चर्ड पॉइंट पर रिकवरी डेटाबेस में था:

DEFERRED_HOTSPOT: 30,356 files
FAILED:              486 files

486 फेल्यर्स का ब्रेकडाउन था:

409  APFSBlock crashes
75   rc=0 but output-size mismatch
2    other rc=1 failures

और स्ट्रक्चर्ड पास ने यह प्रोड्यूस किया था:

0 useful recovered user files

75 साइज़ मिसमैचेज़ ने मेरे अपने रैपर में बग दिखाया: कुछ सिस्टम मेटाडेटा फ़ाइल्स ने डेटा लौटाया था, लेकिन मेरे पार्सर ने एक्सपेक्टेड साइज़ ज़ीरो रिकॉर्ड किया था। उस इंटरप्रिटेशन को ठीक करना महत्वपूर्ण था, लेकिन डॉमिनेंट रिज़ल्ट नहीं बदला। सामान्य यूज़र फ़ाइल्स अभी भी could not read APFSBlock के साथ ज़ीरो बाइट्स पर खत्म हो रही थीं।

मैंने रीप्रोड्यूसिबल टेस्ट केस के रूप में एक छोटी AVIF फ़ाइल चुनी। TSK को उसका एक्सपेक्टेड साइज़ पता था:

expected size: 56,309 bytes
recovered:             0 bytes

यह फ़ाइल एक और कई घंटे चलने वाली बल्क पास से कहीं ज्यादा वैल्यूएबल बन गई। अगर नया अप्रोच एक 56 KB टेस्ट फ़ाइल रिकवर नहीं कर सकता था जो लगातार फेल होती थी, तो उसे बाकी टेराबाइट्स तक एक्सेस नहीं मिलना चाहिए था।

डिस्क ब्लॉक्स और APFS मेटाडेटा पाथ अलग फेल्यर डोमेन्स थे

इस बिंदु तक मेरे पास तीन ऑब्ज़र्वेशन्स थीं:

GNU ddrescue:
almost the entire physical source was copied

TSK fls:
many real paths were discoverable

TSK icat:
many ordinary file contents still failed

लुकअप चेन को कॉन्सेप्चुअल रूप से अलग करने पर ये ऑब्ज़र्वेशन्स एक-दूसरे के साथ कम्पैटिबल हैं:

pathname
   ↓
directory record
   ↓
file object / inode metadata
   ↓
extent mapping
   ↓
physical data blocks

नीचे के डेटा ब्लॉक्स बच सकते हैं जबकि मेटाडेटा चेन में ऊपर की कोई लिंक डैमेज्ड हो। दूसरी संभावना यह है कि दो APFS इम्प्लीमेंटेशन्स एक ही डैमेज्ड स्ट्रक्चर्स को अलग तरीके से ट्रैवर्स करें।

मैंने ऐसा कोई एक करप्ट APFS ऑब्जेक्ट आइसोलेट नहीं किया जो हर फेल्यर को एक्सप्लेन करे, इसलिए मैं उसे कन्फर्म्ड रूट कॉज़ नहीं कहूँगा। एविडेंस ने जिस चीज का समर्थन किया, वह ज्यादा उपयोगी एक्सपेरिमेंट था: क्लोन्ड बाइट्स को अनचेंज्ड रखो और पार्सर बदलो।

142 APFS चेकपॉइंट्स तुरंत रोलबैक पाथ नहीं बने

APFS चेकपॉइंट डिस्क्रिप्टर एरिया की रॉ, रीड-ओनली स्कैन में 142 कैंडिडेट NXSB चेकपॉइंट सुपरब्लॉक्स मिले, जिनके ट्रांज़ैक्शन IDs इस वैल्यू से:

223133

नीचे इस वैल्यू तक थे:

222992

स्पष्ट सवाल था कि क्या कोई पुराना चेकपॉइंट ज्यादा हेल्दी मेटाडेटा ट्री को रेफ़रेंस करता है।

मैंने apfs-fuse बिल्ड किया और fuse-t के जरिए अलग-अलग चेकपॉइंट ट्रांज़ैक्शन IDs आजमाए। सबसे नया चेकपॉइंट स्टॉल हो गया। पुराने XIDs ने भी वही किया। मैंने हर चेकपॉइंट के लिए हार्ड टाइमआउट्स जोड़े, और लगातार 50 से ज्यादा अटेम्प्ट्स यूज़ेबल माउंट नहीं दे सके। मैंने NFS और SMB दोनों fuse-t बैकएंड्स भी आजमाए।

इससे यह साबित नहीं हुआ कि सभी चेकपॉइंट्स करप्ट थे। एक्सपेरिमेंट चेकपॉइंट, apfs-fuse, fuse-t, macOS डिवाइस बिहेवियर और माउंट बैकएंड पर निर्भर था। उस स्टैक में कहीं भी फेल्यर होने पर वही विज़िबल आउटकम आ सकता था।

बाद के पार्सर ने ज़ीरो APFS स्नैपशॉट्स रिपोर्ट किए, जिससे एक डिस्टिंक्शन और साफ हुई जिसे मुझे अलग रखना था: वे चेकपॉइंट ट्रांज़ैक्शन स्टेट्स यूज़र-विज़िबल APFS स्नैपशॉट्स जैसी चीज नहीं थीं।

--help पर हैंग होने वाला पार्सर मेरी डिस्क डायग्नोज़ नहीं कर सकता

मैंने go-apfs-v2 भी बिल्ड किया। बिल्ड पूरा हुआ, लेकिन यहाँ तक कि:

apfs --help

भी हैंग हो गया और टाइमआउट से kill करना पड़ा।

रॉ और बफ़र्ड दोनों डिवाइस पाथ्स पर मिनिमल ब्लॉक इंस्पेक्शन भी हैंग हुआ। मैंने apfsutil के साथ भी उसी तरह बाउंडेड टेस्ट किया; दोनों डिवाइस फ़ॉर्म्स लगभग 15 सेकंड बाद टाइम आउट हो गए।

ये यूज़फुल फेल्यर्स थे क्योंकि उन्होंने मुझे गलत कन्क्लूज़न निकालने से रोका। जो टूल अपना help पाथ भी भरोसेमंद ढंग से पूरा नहीं कर सकता, वह इस बात के लिए कमजोर एविडेंस है कि डैमेज्ड फ़ाइल रिकवरेबल है या नहीं।

मेरा रूल बन गया:

रिकवरी टूल की फेल्यर को डेटा के बारे में एविडेंस मानने से पहले रिकवरी टूल को वैलिडेट करो।

macOS को क्लोन ऑटो-माउंट करने से रोकने पर एक और रिस्क सोर्स खत्म हुआ

macOS खुद भी एक मूविंग पार्ट था। मैं हेल्दी डेस्टिनेशन को सामान्य तरीके से माउंटेड रखना चाहता था, लेकिन स्टोरेज रीकनेक्ट करते समय Disk Arbitration को डैमेज्ड APFS क्लोन ऑटोमैटिकली माउंट करने की कोशिश नहीं करने देना चाहता था।

आखिर में मैंने यह सेफ़ क्रम इस्तेमाल किया:

  1. हेल्दी रिकवरी डेस्टिनेशन कनेक्ट और माउंट करो।
  2. उसकी वॉल्यूम आइडेंटिटी और फ़्री स्पेस वेरिफ़ाई करो।
  3. diskarbitrationd फ़्रीज़ करो।
  4. वेरिफ़ाई करो कि कोई एक्टिव mount_apfs प्रोसेस नहीं है।
  5. मास्टर क्लोन अटैच करो।
  6. नोन फ़िज़िकल साइज़ और APFS आइडेंटिटी से मास्टर को डायनैमिकली आइडेंटिफ़ाई करो।
  7. वेरिफ़ाई करो कि मास्टर माउंटेड नहीं है।
  8. रीड-ओनली रिकवरी वर्क करो।
  9. रोकते समय स्टेट सेव करो, Disk Arbitration रिज़्यूम करो और फिर सामान्य तरीके से शट डाउन या इजेक्ट करो।

Disk Arbitration फ़्रीज़ करने के लिए मैंने वास्तव में यह कमांड इस्तेमाल किया:

sudo kill -STOP "$(pgrep -x diskarbitrationd)"

मैंने वेरिफ़ाई किया कि प्रोसेस स्टेट में T था, और आगे बढ़ने से पहले स्ट्रे mount_apfs प्रोसेसेज़ भी चेक किए।

महत्वपूर्ण सेफ़्टी लेसन कोई खास डिस्क नंबर नहीं था। उल्टा था: कल के डिस्क नंबर पर कभी भरोसा मत करो। रीबूट के बाद पुराना /dev/disk6 किसी अलग फ़िज़िकल डिवाइस को रेफ़र कर सकता है। मैंने APFS UUID और नोन फ़िज़िकल साइज़ को आइडेंटिटी माना, फिर उनसे करंट डिवाइस पाथ डिराइव किया।

libfsapfs ने वही फ़ाइल रिकवर की जिसे TSK ने ज़ीरो बाइट्स लौटाया था

ब्रेकथ्रू एक अलग APFS इम्प्लीमेंटेशन, libfsapfs, से आया।

मैंने इसे macOS पर सोर्स से बिल्ड किया। रिज़ल्टिंग fsapfsinfo बाइनरी ने खुद को इस तरह आइडेंटिफ़ाई किया:

fsapfsinfo 20260923

फिर macOS डिवाइस इंटरफ़ेस का एक महत्वपूर्ण डिफ़रेंस सामने आया।

रॉ कैरेक्टर-डिवाइस पार्टिशन:

/dev/rdiskNs2

ऑफ़सेट 4096 के पास इनवैलिड-आर्ग्युमेंट रीड के साथ जल्दी फेल हुआ।

बफ़र्ड ब्लॉक-डिवाइस फ़ॉर्म:

/dev/diskNs2

काम किया।

वही फ़िज़िकल क्लोन। वही APFS पार्टिशन। अलग macOS डिवाइस इंटरफ़ेस।

fsapfsinfo ने कंटेनर खोला और एक वॉल्यूम पाया। फिर मैंने वही एग्ज़ैक्ट 56,309-बाइट फ़ाइल टेस्ट की जिसे TSK एक्सट्रैक्ट करने में फेल हुआ था।

TSK ने दिया था:

expected:  56,309
recovered:      0
APFSBlock failure

libfsapfs के जरिए फ़ाइल एंट्री ने दिया:

size: 56,309
MD5:  c6f56db33eafc1de0f52a035bc255dc7
RC:   0

यह पहला रिज़ल्ट था जिसने डायग्नोसिस को वास्तव में बदल दिया। क्लोन्ड बाइट्स नहीं बदले थे। टेस्ट फ़ाइल नहीं बदली थी। डैमेज्ड APFS रिपेयर नहीं हुआ था।

APFS इम्प्लीमेंटेशन बदला था।

कम से कम अब मुझे पता था कि TSK के जरिए अनरिकवरेबल दिखने वाली वास्तविक यूज़र फ़ाइल libfsapfs के जरिए इतनी गहराई तक रीचेबल थी कि उसका पूरा कंटेंट पढ़ा जा सके और डाइजेस्ट कैलकुलेट किया जा सके।

libfsapfs पर टेराबाइट्स का भरोसा करने से पहले मैंने एक नोन-बैड फ़ाइल एक्सट्रैक्ट की

सक्सेसफुल डाइजेस्ट मेरे लिए मल्टी-टेराबाइट रिकवरी शुरू करने के लिए पर्याप्त नहीं था। मैं डेस्टिनेशन डिस्क पर एक्चुअल बाइट्स चाहता था।

libfsapfs C API का अंदाजा लगाने के बजाय मैंने लाइब्रेरी सोर्स इंस्पेक्ट किया और डाइजेस्ट कैलकुलेट करते समय fsapfsinfo द्वारा पहले से इस्तेमाल रीड पाथ को फ़ॉलो किया। फिर मैंने नोन टेस्ट फ़ाइल के लिए छोटा रीड-ओनली एक्सट्रैक्टर बनाया।

एक्सट्रैक्टर ने एग्ज़ैक्ट लिखा:

56,309 bytes

अलग रिकवरी डिस्क पर। एक्सट्रैक्टेड फ़ाइल का MD5 था:

c6f56db33eafc1de0f52a035bc255dc7

यह पहले वाले डाइजेस्ट से मैच करता था।

उसके बाद ही मैंने अप्रोच स्केल किया। वन-फ़ाइल टेस्ट ने तीन अलग चीजें साबित की थीं: पाथनेम रिज़ॉल्व हो सकता था, पूरा एक्सपेक्टेड बाइट काउंट एक्सट्रैक्ट हो सकता था, और एक्सट्रैक्टेड बाइट्स पहले के फुल-कंटेंट रीड जैसा ही डाइजेस्ट प्रोड्यूस करते थे।

बल्क रिकवरी प्रॉब्लम मुख्य रूप से फॉल्ट कंटेनमेंट और रिज़्यूम की थी

जब libfsapfs उस फ़ाइल को रिकवर कर सका जिसे TSK नहीं कर सका, कठिन प्रॉब्लम फिर बदल गई। मुझे ऐसी सिस्टम चाहिए थी जो बहुत बड़े डायरेक्टरी ट्री को प्रोसेस कर सके और एक डैमेज्ड ब्रांच, एक रीबूट या एक Ctrl+C पूरे जॉब को ज़ीरो से रीस्टार्ट न कर दे।

इसलिए बल्क रिकवरी पाइपलाइन ने कुछ स्ट्रिक्ट इनवेरिएंट्स इस्तेमाल किए:

  • मास्टर क्लोन रीड-ओनली खोला गया।
  • रिकवर्ड आउटपुट सिर्फ दूसरी 5 TB डिस्क पर लिखा गया।
  • डायरेक्टरी और फ़ाइल नेम्स प्रिज़र्व किए गए।
  • प्रोग्रेस SQLite में रखा गया ताकि प्रोसेस एग्ज़िट्स और रीबूट्स के बाद भी बचा रहे।
  • हर फ़ाइल पहले टेम्पररी पाथ पर लिखी गई।
  • टेम्पररी फ़ाइल को फ़ाइनल पाथ पर तभी रीनेम किया गया जब पूरा एक्सपेक्टेड साइज़ लिखा जा चुका था।
  • एक्सपेक्टेड साइज़ वाली एग्ज़िस्टिंग फ़ाइल्स को रिज़्यूम के दौरान पहचान लिया जाता था।
  • फेल्ड या प्रॉब्लमैटिक वर्क को कम्प्लीटेड वर्क से अलग रखा गया।
  • फ़्री स्पेस चेक किया गया और सेफ़्टी रिज़र्व बनाए रखा गया।
  • रीजेनेरेटेबल डेवलपमेंट आर्टिफ़ैक्ट्स और लो-वैल्यू सिस्टम मेटाडेटा स्किप या डी-प्रायोरिटाइज़ किए जा सकते थे।

एक परफ़ॉर्मेंस चेंज का तुरंत असर पड़ा: मैंने हर फ़ाइल के लिए APFS कंटेनर को अलग से रीओपन करना बंद कर दिया।

फास्ट पाथ एक समय में एक डायरेक्टरी प्रोसेस करता था। वर्कर सोर्स खोलता, उस डायरेक्टरी को एन्यूमरेट करता, उसकी इमीडिएट रेगुलर फ़ाइल्स रिकवर करता और चाइल्ड डायरेक्टरीज़ को क्यू में वापस डाल देता। अगर डायरेक्टरी फेल होती या टाइमआउट करती, कंट्रोलर उसे DEFERRED मार्क कर देता और ग्लोबल पास ब्लॉक करने के बजाय आगे बढ़ जाता।

जब कोई नॉर्मल पेंडिंग वर्क नहीं बचता, डिफ़र्ड डायरेक्टरीज़ को स्लोअर फॉलबैक पाथ से फिर देखा जाता जिसमें पर-फ़ाइल वर्क ज्यादा आइसोलेटेड था। बाकी फेल्यर्स को फिर इंडिपेंडेंटली रीट्राई किया जा सकता था।

discover directory
    ↓
recover immediate files
    ↓
verify expected sizes
    ↓
commit durable state
    ↓
queue child directories
    ↓
defer local failures
    ↓
continue globally
    ↓
fallback and retry later

यह आर्किटेक्चर एक्चुअल फेल्यर पैटर्न से एक विशाल रिकर्सिव कमांड की तुलना में कहीं बेहतर मैच करता था। डैमेज यूनिफ़ॉर्म नहीं था, इसलिए रिकवरी सिस्टम को प्रोग्रेस भी यूनिफ़ॉर्म नहीं बनानी चाहिए थी।

लाखों फ़ाइल्स हैश करने के बजाय मैंने एक्सपेक्टेड-साइज़ चेक्स और एटॉमिक रीनेम क्यों इस्तेमाल किए

MD5 सिंगल-फ़ाइल प्रूफ़ के दौरान उपयोगी था क्योंकि मुझे मजबूत एविडेंस चाहिए था कि पार्सर उस फ़ाइल का पूरा कंटेंट पढ़ रहा है जिसे TSK नहीं पढ़ सका।

सिर्फ लाखों फ़ाइल्स हैश करने के लिए हर रिकवर्ड बाइट को दूसरी बार पूरा पढ़ना बहुत ज्यादा I/O जोड़ देता। मेन एक्सट्रैक्शन पास के लिए मैंने अलग इनवेरिएंट इस्तेमाल किया।

हर रेगुलर फ़ाइल के लिए APFS मेटाडेटा एक्सपेक्टेड साइज़ देता था। वर्कर टेम्पररी फ़ाइल में लिखता और उसे फ़ाइनल पाथनेम पर तभी प्रमोट करता जब कम्प्लीट रीड उस एक्सपेक्टेड साइज़ से मैच करती।

इसका मतलब इंटरप्शन के बाद फ़ाइनल नेम के नीचे कोई शॉर्ट फ़ाइल पूरी फ़ाइल बनकर नहीं रहनी चाहिए।

साइज़ मैच क्रिप्टोग्राफ़िक इंटेग्रिटी प्रूफ़ नहीं है। मैं इसे वैसा नहीं मानता। लेकिन एक्सपेक्टेड-साइज़ वेरिफ़िकेशन और एटॉमिक रीनेम हाई-वॉल्यूम पास के लिए प्रैक्टिकल करेक्टनेस बाउंड्री थी, जबकि टार्गेटेड हैशेज़ सैंपल्स और नोन फेल्यर केसेज़ के लिए उपयोगी बने रहे।

SQLite ने रीबूट को कैटास्ट्रॉफिक की बजाय बोरिंग बना दिया

रिकवरी इतनी लंबी चली कि मुझे कंप्यूटर रोककर बाद में रिज़्यूम करना पड़ा। उस रिक्वायरमेंट ने डिज़ाइन को “स्क्रिप्ट” से “रिकवरेबल वर्कफ़्लो” में बदल दिया।

Ctrl+C एक्टिव चाइल्ड प्रोसेस को बस छोड़ नहीं देता था। कंट्रोलर इंटरप्शन ट्रैप करता, वर्कर रोकता, एक्टिव डायरेक्टरी को रिकवरेबल स्टेट में लौटाता, SQLite कमिट करता और एग्ज़िट करता।

क्लीन स्टॉप कॉन्सेप्चुअल रूप से ऐसा दिखता था:

CURRENT DIRECTORY -> PENDING

CTRL+C: RECOVERY STOPPED SAFELY
STATE SAVED. RUN THE SAME COMMAND TO RESUME.

रीबूट के बाद मैंने डिस्क-आइडेंटिटी चेक्स दोहराए और वही रिकवरी कमांड शुरू किया। स्टेट डेटाबेस ने एग्ज़िस्टिंग क्यू रिज़्यूम की।

बाद की एक रीस्टार्ट इस तरह शुरू हुई:

DEFERRED:     1
DONE:     73,015
PENDING:   7,254

यह जेनेरिक प्रोग्रेस बार से कहीं ज्यादा मीनिंगफुल था। इससे दिखा कि दसियों हज़ार कम्प्लीटेड डायरेक्टरी यूनिट्स रीबूट के बाद भी बचे थे और रिमेनिंग क्यू स्पष्ट थी।

एक पुराने रिज़्यूम में पिछले सेशन में इंटरप्टेड डायरेक्टरी फिर उठाई गई। एक्सपेक्टेड साइज़ पर पहले से मौजूद फ़ाइल्स पहचान ली गईं और सिर्फ मिसिंग वर्क लिखना पड़ा। यही बिहेवियर मैं चाहता था: रिकवरी रीस्टार्ट करना रूटीन होना चाहिए, डरावना नहीं।

326,799 फ़ाइल्स पहला प्रमाण थीं कि तरीका स्केल कर सकता है

नए एक्सट्रैक्टर को सभी सेलेक्टेड डेटा पर फैलाने से पहले मैंने एक बड़े प्रायोरिटी ट्री को बल्क वैलिडेशन टार्गेट बनाया।

कम्प्लीटेड स्टेट ने रिपोर्ट किया:

directories completed:     8,940
new files written:       302,541
existing/resumed files:   24,258
recorded failed files:         0

डेस्टिनेशन में था:

326,799 files
145,039,215,948 bytes

या लगभग:

135.08 GiB

फ़ाइल काउंट्स एग्ज़ैक्ट रिकॉन्साइल हुए:

302,541 + 24,258 = 326,799

उस कम्प्लीटेड ट्री में कोई लेफ़्टओवर .partial.* फ़ाइल्स नहीं थीं।

56,309-बाइट टेस्ट फ़ाइल ने साबित किया था कि पार्सर वहाँ सफल हो सकता है जहाँ TSK फेल हुआ। 326,799-फ़ाइल रिकवरी ने साबित किया कि वही अप्रोच रिज़्यूम लॉजिक, एग्ज़िस्टिंग-फ़ाइल डिटेक्शन और उस कम्प्लीटेड पास में ज़ीरो रिकॉर्डेड फ़ाइल फेल्यर्स के साथ सब्स्टैंशल रियल हाइरार्की संभाल सकता है।

बड़ी रिकवरी कम्प्लीशन से पहले 1.6 मिलियन नई फ़ाइल्स पार कर गई

प्रायोरिटी ट्री क्लीनली कम्प्लीट होने के बाद मैंने रिकवरी को बाकी सेलेक्टेड टॉप-लेवल डेटा तक एक्सपैंड किया।

एक इंटेंशनल सेफ़ स्टॉप पर SQLite ने रिपोर्ट किया:

DONE directories:       39,015
PENDING directories:    17,017
DEFERRED directories:        1

new files written:   1,636,305
new bytes written: 902,715,716,335

यह लगभग था:

840.72 GiB

उस समय डायरेक्टरी पासेस द्वारा रिकॉर्डेड न्यूली लिखा हुआ डेटा।

एकमात्र DEFERRED डायरेक्टरी का मतलब लॉस्ट डेटा नहीं था। इसका मतलब फास्ट पाथ ने जानबूझकर उस लोकल प्रॉब्लम को अनरिलेटेड वर्क डिले करने से रोक दिया था। फॉलबैक फ़ेज़ खास तौर पर ऐसे केसेज़ पर बाद में लौटने के लिए था।

बाद के सेशन्स उसी डेटाबेस से रिज़्यूम हुए। कम्प्लीटेड काउंट बढ़ा और पेंडिंग क्यू घटती गई। अंत में मैंने वे सभी सेलेक्टेड, एन्यूमरेटेड फ़ोल्डर ट्रीज़ रिकवर कर लिए जिनकी मुझे जरूरत थी।

फ़ाइनल रिकवरी के बारे में मैं ईमानदारी से क्या दावा कर सकता हूँ

मैं आउटकम को “हर बाइट रिकवर हो गया” नहीं कहूँगा। एविडेंस इसका समर्थन नहीं करता।

ओरिजिनल ddrescue मैप में अभी भी लगभग 13.84 MB ऐसा था जिसके सफलतापूर्वक कॉपीड होने की पुष्टि नहीं हुई थी। मैं यह भी साबित नहीं कर सकता कि कोई फ़ाइल सिस्टम ऑब्जेक्ट पूरी तरह अनडिस्कवरेबल नहीं हो गया, क्योंकि उसे एन्यूमरेट करने के लिए जरूरी मेटाडेटा डैमेज्ड रीजन में हो सकता था।

ये लिमिटेशन्स महत्वपूर्ण हैं, क्योंकि स्ट्रक्चर्ड रिकवरी यह साबित कर सकती है कि एन्यूमरेटेड ऑब्जेक्ट एक्सट्रैक्ट हुआ; वह किसी ऐसे ऑब्जेक्ट के हिस्टोरिकल गैर-मौजूदगी को साबित नहीं कर सकती जिसे डैमेज्ड नेमस्पेस अब रिवील नहीं कर सकता।

सबसे मजबूत फ़ाइनल कथन इससे संकरा है:

जिन सेलेक्टेड, एन्यूमरेटेड फ़ोल्डर ट्रीज़ की मुझे जरूरत थी, वे सभी स्ट्रक्चर्ड रिकवरी प्रोसेस के जरिए सफलतापूर्वक रिकवर हुए।

मुझे मास्टर क्लोन को इन-प्लेस रिपेयर नहीं करना पड़ा। बल्क एक्सट्रैक्शन के लिए ओरिजिनल क्लिकिंग Toshiba दोबारा इस्तेमाल नहीं करना पड़ा। मुझे ऐसा होल-डिस्क PhotoRec-स्टाइल कार्विंग पास भी नहीं करना पड़ा जो डायरेक्टरी स्ट्रक्चर और फ़ाइलनेम्स खो देता।

फेल्ड टूल्स फिर भी यूज़फुल एविडेंस थे

पीछे मुड़कर देखने पर सक्सेसफुल पाथ सरल लगता है:

ddrescue clone
    ↓
libfsapfs
    ↓
resumable extractor
    ↓
recovered files

इन्वेस्टिगेशन के दौरान ऐसा महसूस नहीं हुआ था, और फेल्ड अप्रोचेज़ हटाने से उपयोगी इंजीनियरिंग लेसन का बड़ा हिस्सा भी हट जाता।

TSK ने मुझे सिखाया कि APFS नेमस्पेस ट्रैवर्सल और कंटेंट रिट्रीवल अलग फेल्यर मोड्स थे।

मेरे पहले रैपर बग ने सिखाया कि रिकवरी स्क्रिप्ट की अपनी एरर क्लासिफ़िकेशन ग्राउंड ट्रुथ नहीं होती।

हॉटस्पॉट मैकेनिज़्म ने सिखाया कि लोकल फेल्यर को ग्लोबल प्रोग्रेस स्टॉल करने देने के बजाय आइसोलेट करना चाहिए।

चेकपॉइंट एक्सपेरिमेंट ने सिखाया कि APFS ट्रांज़ैक्शन चेकपॉइंट्स को स्नैपशॉट्स समझना गलत है।

FUSE अटेम्प्ट्स ने सिखाया कि फेल्ड माउंट फ़ाइल सिस्टम डेटा के अलावा कई दूसरी लेयर्स को भी इम्प्लिकेट कर सकता है।

--help पर हैंग होने वाले APFS रीडर ने सिखाया कि डायग्नॉस्टिक्स इंटरप्रेट करने से पहले टूल वैलिडेट करना चाहिए।

/dev/rdiskNs2 और /dev/diskNs2 के बिहेवियर ने सिखाया कि अंडरलाइंग डिस्क आइडेंटिकल होने पर भी ऑपरेटिंग-सिस्टम I/O पाथ पार्सर बिहेवियर बदल सकता है।

और टू-ड्राइव आर्किटेक्चर ने मुझे मास्टर क्लोन अनचेंज्ड रखते हुए बाकी जगह गलतियाँ करने की स्वतंत्रता दी।

वह रिकवरी वर्कफ़्लो जिसे मैं फिर इस्तेमाल करूँगा

  1. मैकेनिकली फेलिंग स्टोरेज पर सामान्य फ़ाइल सिस्टम एक्टिविटी रोक दो। अगर रीड्स स्टॉल हो रही हों, डिवाइस गायब हो या क्लिक करे, तो मैं Finder एक्सप्लोरेशन के बजाय रिज़्यूमेबल ब्लॉक-लेवल क्लोन को प्रायोरिटी दूँगा।
  2. पर्सिस्टेंट mapfile और वेरिफ़ाइड रेस्क्यू डोमेन के साथ GNU ddrescue इस्तेमाल करो। mapfile प्रोग्रेस बचाता है; नोन सोर्स साइज़ डिवाइस-साइज़ कन्फ्यूज़न को रिकवरी का हिस्सा बनने से रोकता है।
  3. एक मास्टर क्लोन रीड-ओनली रखो। उसे रिपेयर, रीसाइज़, रीपार्टिशन मत करो और रिकवर्ड-फ़ाइल स्टोरेज की तरह इस्तेमाल मत करो।
  4. रिकवर्ड फ़ाइल्स दूसरी फ़िज़िकल डिस्क पर लिखो। सोर्स प्रिज़र्वेशन और आउटपुट स्टोरेज अलग काम हैं।
  5. क्लोन्ड फ़ाइल सिस्टम को पहले रीड-ओनली डायग्नोज़ करो। करप्ट APFS मेटाडेटा वाला हेल्दी फ़िज़िकल क्लोन लॉजिकल रिकवरी प्रॉब्लम है; यह क्लिकिंग सोर्स डिस्क जैसी समस्या नहीं है।
  6. पार्सर टेस्ट के लिए एक रीप्रोड्यूसिबल फेल्ड फ़ाइल चुनो। 56 KB नोन-बैड फ़ाइल ने अल्टरनेटिव पार्सर्स के बारे में ब्लाइंड बल्क एक्सट्रैक्शन के घंटों से ज्यादा बताया।
  7. पार्सर को खुद वैलिडेट करो। अगर टूल सोर्स को अर्थपूर्ण ढंग से पढ़ने से पहले हैंग हो जाए, तो इसे डेटा गॉन होने का प्रूफ़ मत मानो।
  8. यह मत मानो कि एक APFS इम्प्लीमेंटेशन रिकवरेबिलिटी तय करता है। TSK और libfsapfs ने उन्हीं क्लोन्ड बाइट्स पर बहुत अलग बिहेवियर दिखाया।
  9. डिस्क्स को टेम्पररी डिवाइस नंबर्स से नहीं, स्टेबल प्रॉपर्टीज़ से आइडेंटिफ़ाई करो। फ़ाइल सिस्टम UUID और नोन फ़िज़िकल साइज़ कल के /dev/diskN से ज्यादा सुरक्षित हैं।
  10. लॉन्ग-रनिंग एक्सट्रैक्शन को शुरुआत से रिज़्यूमेबल बनाओ। ड्यूरेबल स्टेट, टेम्पररी फ़ाइल्स, एटॉमिक रीनेम, डिफ़र्ड वर्क, बाउंडेड रीट्राइज़ और क्लीन शटडाउन हैंडलिंग इस स्केल पर करेक्टनेस का हिस्सा हैं।
  11. वैलिडेशन लेवल्स अलग रखो। ddrescue परसेंटेज, विज़िबल पाथनेम, एक्सपेक्टेड-साइज़ मैच और कंटेंट हैश अलग-अलग चीजें साबित करते हैं।

जो संख्या फ़िनिश लाइन जैसी लगी, वह सिर्फ स्टेज वन का अंत थी

पूरी रिकवरी में सबसे भ्रामक नंबर अभी भी था:

100.00%

यह “क्या मैंने डिस्क बचा ली?” का जवाब लगता था।

असल में उसने बहुत संकरे सवाल का जवाब दिया:

How much of the physical rescue domain did ddrescue successfully copy?

उसने यह नहीं बताया कि APFS नेमस्पेस रिकंस्ट्रक्ट कर सकता है या नहीं। उसने यह नहीं बताया कि एक पार्सर उस डैमेज्ड मेटाडेटा को ट्रैवर्स कर सकता है जिसे दूसरा पार्सर रिजेक्ट करता है। उसने यह नहीं बताया कि रिकवर्ड फ़ाइल की एक्सपेक्टेड लेंथ है या नहीं। और उसने यह भी नहीं बताया कि मल्टी-मिलियन-फ़ाइल एक्सट्रैक्शन एरर्स और रीबूट्स से अपने स्टेट को करप्ट किए बिना बच सकती है या नहीं।

हर लेयर के लिए मुझे अलग एविडेंस चाहिए था।

फ़िज़िकल रिकवरी पहले सफल हुई। फ़ाइल सिस्टम अभी भी डैमेज्ड था। पहला पार्सर नेम्स दिखा सकता था लेकिन कई फ़ाइल कंटेंट्स पर फेल होता था। अलग APFS इम्प्लीमेंटेशन ने वही टेस्ट फ़ाइल सफलतापूर्वक पढ़ी। वह प्रूफ़ वन-फ़ाइल एक्सट्रैक्टर बना, एक्सट्रैक्टर रिज़्यूमेबल रिकवरी इंजन बना, और आखिरकार इंजन ने मास्टर क्लोन अनटच्ड रखते हुए जरूरी सेलेक्टेड फ़ोल्डर ट्रीज़ को दूसरी डिस्क पर रिकवर कर दिया।

ओरिजिनल हार्ड ड्राइव कभी हेल्दी नहीं हुई। APFS ने जादुई तरीके से खुद को रिपेयर नहीं किया। जो बदला वह रिकवरी मॉडल था।

ब्लॉक रिकवरी, फ़ाइल सिस्टम रिकवरी और फ़ाइल वैलिडेशन अलग इंजीनियरिंग स्टेजेज़ हैं। उन्हें एक ही प्रॉब्लम मानने से स्थिति लगभग होपलेस लगी। उन्हें अलग करने से समस्या मैनेजेबल हो गई।