Worked examples — Journaling — why, how it works
4.2.36 · D3· Coding › Operating Systems › Journaling — why, how it works
Yeh page Journaling ka case-by-case drill room hai. Parent note ne tumhe bataya tha kyun journaling exist karti hai aur kaise commit block kaam karta hai. Yahan hum ek simple operation lete hain — ek file mein ek block append karna — aur usse har possible crash timing aur configuration ke saath hit karte hain. Iske baad tum koi bhi crash scenario nahi dekhoge jo tumne pehle solve hote na dekha ho.
Shuru karne se pehle, thodi si shared vocabulary (sab parent note se):
Recall Ek transaction ke paanch steps (parent se)
- Descriptor — ek record jo naam leta hai ki kaunse blocks change honge.
- Journal data — naye block contents ki copies journal mein likhi jaati hain.
- COMMIT — aakhri, chhota, single write; "go" switch.
- Checkpoint — journal blocks ko unke real in-place homes mein copy karo.
- Free — circular log ko aage badhao, space reclaim karo. Crash in steps ke beech kisi bhi gap mein aa sakta hai. Yahi hum enumerate karte hain.
Scenario matrix
Har crash ki kahani is table ka ek cell hai. Do axes hain: crash kab hua aur kaunsa journaling mode chala (teen modes ke liye parent dekho). Hum degenerate, non-commit-blocks ke corruption, aur word-problem rows bhi add karte hain. Cell column mein letters hain taaki "Example N" numbering se clash na ho.
| Cell | Case class | Crash timing | Mode | Committed? | Recovery action |
|---|---|---|---|---|---|
| A | Happy path | koi crash nahi | ordered | haan | kuch nahi chahiye |
| B | Crash mid-logging | step 2 ke baad, COMMIT se pehle | any | nahi | discard |
| C | Crash mid-checkpoint | step 4 ke dauran | any | haan | replay (idempotent) |
| D | Crash after free | step 5 ke baad | any | (gone) | kuch nahi karna |
| E | Torn COMMIT block | commit half-written | any | nahi (bad checksum) | discard |
| F1 | Ordered mode exposure | metadata commit ke baad crash, data nahi landa | ordered | haan | data guaranteed present |
| F2 | Writeback mode exposure | metadata commit ke baad crash, data nahi landa | writeback | haan | garbage expose ho sakta hai |
| G | Degenerate: empty transaction | zero blocks changed | any | trivially | no-op |
| H | Durability trap (word problem) | commit ke baad crash lekin app ne fsync call nahi ki | ordered | haan jo log hua uske liye | consistent, lekin recent write lost |
| I | Exam twist: do transactions, doosra uncommitted | TX7 commit ke baad crash, TX8 ke beech mein | ordered | TX7 haan, TX8 nahi | TX7 replay karo, TX8 discard karo |
| J | Full journal (data) mode | data journaling ke dauran / commit ke baad crash | journal | commit ke hisaab se | data journal se hi recoverable |
| K | Torn descriptor / torn journal-data | mid-descriptor ya mid-journal-data crash | any | nahi (us record ka bad checksum) | discard |
Neeche ke nau worked examples barahon cells cover karte hain (Example 6 dono F-cells cover karta hai, aur Example 8 cells G aur H cover karta hai).
Worked Example 1 — Cell A: happy path (koi crash nahi)
Forecast: pehle guess karo — sab kuch khatam hone ke baad, naye inode ki disk par kitni copies hain, aur kahan?
- Pehle data block ko uske real home par force karo. Yeh step kyun? Ordered mode mein rule hai data-before-metadata-commit, isliye real file bytes metadata commit se pehle hi neeche aa jaate hain. Yahi cheez inode ko kabhi garbage point karne se rokti hai.
- Descriptor likho "TX#7 touches inode 9, bitmap, block 50" journal mein. Kyun? Recovery ko scope pata hona chahiye — kaunse blocks is transaction ke hain.
- Naya inode + naya bitmap journal mein likho. Kyun? Yeh real copies ko touch karne se pehle intended final metadata ko durably capture karta hai.
- TX#7 ka COMMIT block likho. Kyun? Yeh single small write transaction ko "mujhe ignore karo" se "mujhe replay karo" mein flip karti hai. Isse pehle kuch bhi trusted nahi hai.
- Checkpoint: journalled inode + bitmap ko unke real in-place locations par copy karo. Kyun? Ab hi hum real filesystem edit karte hain; is point tak woh untouched tha.
- Free karo TX#7 ka journal space. Kyun? Circular log chhota hota hai; agale transaction ke liye reclaim karo.
Verify: Copies gino. Transaction ke dauran inode do jagah tha (journal copy + real copy). Step 6 ke baad, journal copy free ho gayi, exactly 1 real inode raha. Data block: ek baar likha gaya (step 1). Koi contradiction nahi, koi leaked block nahi — bitmap aur inode agree karte hain. ✅
Worked Example 2 — Cell B: logging ke baad, COMMIT se pehle crash
Forecast: kya append survive karta hai, partially survive karta hai, ya gayab ho jaata hai?

Figure mein kya dekhna hai: chhe coloured boxes hain six steps ke, left se right. Magenta dashed line COMMIT mark karti hai. Mota orange bar woh hai jahan power gayi. Notice karo yeh commit line ke left mein hai — yeh single visual fact ("crash before commit") poora jawaab hai.
- Journal scan karo. Recovery circular log walk karti hai transactions dhundhne ke liye. Kyun? Recovery time journal par depend karta hai, poori disk par nahi (journaling ka yahi point hai Write-Ahead Logging).
- TX#7 milo descriptor + data ke saath lekin koi COMMIT block nahi. Yeh kyun matter karta hai? COMMIT nahi matlab hum nahi jaante ki TX#7 ke saare journal blocks successfully likhe gaye ya nahi — crash mid-write cut off kar sakta tha.
- TX#7 discard karo. Usse drop karo, aage badho. Yeh safe kyun hai? Figure mein orange bar dekho: crash commit line ke left mein pada, isliye step 5 (checkpoint) kabhi nahi chala — real inode, bitmap, aur directory byte-for-byte wahi hain jo append shuru hone se pehle the.
- Filesystem consistent hai. Append simply "hua hi nahi."
Verify: Invariant "in-place structures untouched" sanity check karo. Jo steps in-place likhte hain woh hain step 1 (data, ordered mode mein) aur step 5 (metadata). Step 5 kabhi nahi chala, isliye metadata purana hai. Step 1 ne data block zaroor likha — lekin koi inode uski taraf point nahi karta aur koi bitmap bit set nahi hai, isliye woh sirf ek unreferenced sector hai, free space se alag nahi. Zero corruption. ✅
Worked Example 3 — Cell C: checkpoint ke dauran crash (idempotency)
Forecast: inode naya hai, bitmap purana hai — kya disk abhi corrupt hai, aur kya fix karti hai?

Figure mein kya dekhna hai: wahi chhe step boxes, lekin ab orange crash bar magenta commit line ke right mein hai, checkpoint step ke andar landa. "Crash right of commit" replay ka visual signature hai, pichle figure ka mirror image.
- Journal scan karo, TX#7 ke saath COMMIT block milta hai. COMMIT sab kuch kaise badal deta hai? Iska presence prove karta hai ki TX#7 ke saare journal blocks safely log hain, isliye hum unhe sab in place force kar sakte hain.
- Replay: TX#7 ke har journal block ko uske real home par re-copy karo — inode aur bitmap. Woh inode kyun re-copy karein jo pehle se sahi hai? Recovery nahi bata sakti step 5 kitni door gayi thi; cheapest correct move hai sab dobara likhna.
- Same inode value dobara likhna harmless hai. Value likhna phir dobara likhna equals ek baar likhna. Yeh idempotency hai.
Verify: Replay ke baad, inode = naya (dobara likha gaya), bitmap = naya (finally likha gaya). Dono agree karte hain: file ek block longer hai aur woh block used mark hai. ko apne dimag mein ek teesri baar apply karo — same result. Consistent. ✅
Worked Example 4 — Cell D: journal free hone ke baad crash
Forecast: kya journal mein replay karne ke liye kuch hai?
- Journal scan karo. Kyun? Hamesha pehla kadam.
- Append ke liye koi live transaction nahi milta. Kyun? Step 6 ne circular log ko TX#7 se aage advance kar diya, isliye uske records ab "live" nahi hain.
- Kuch nahi karo. Real filesystem pehle se finished append hold karta hai.
Verify: Change crash se pehle in place fully apply ho chuka tha. Koi half-state fix karna nahi hai aur kuch replay nahi karna. Recovery no-op hai — jo ideal outcome hai. ✅
Worked Example 5 — Cells E & K: torn COMMIT, aur torn descriptor / journal-data
Forecast: commit block physically present lekin garbled hai — replay ya discard?
- Commit record padho aur transaction ke blocks par checksum recompute karo. Checksum kyun? Kyunki "commit block present hai" kaafi nahi — humhe jaanna hai ki woh completely likha gaya tha. Checksum "poora likha?" ko yes/no test mein badal deta hai.
- Checksum mismatch → transaction ko NOT committed treat karo. Kyun? Torn commit matlab wahi khatara hai jaise koi commit nahi: hum trust nahi kar sakte ki har block landa.
- TX#7 discard karo, bilkul Cell B ki tarah.
Verify: Yeh Cell B outcome par collapse ho jaata hai. In-place structures kabhi checkpoint nahi hue (step 5 commit ke baad aata hai), isliye discard karna pre-append filesystem intact chhod deta hai. Consistent. Checksum guarantee karta hai ki partial commit kabhi real ke liye mistake na ho. ✅
Forecast: agar descriptor garbled hai, kya recovery bata bhi sakti hai ki transaction ne kaun se blocks touch karne ka claim kiya tha?
- Har journal record apna checksum carry karta hai, sirf commit nahi. Kyun? Torn descriptor otherwise recovery ko transaction ke scope ke baare mein mislead karega, aur torn journal-data block real filesystem mein galat bytes replay karega.
- Descriptor aur har journal-data block ka checksum recompute karo. Kyun? Yeh wahi "poora likha?" test hai jaise Cell E mein, har record type par apply.
- Agar kisi bhi record ka checksum fail ho, transaction ko NOT committed treat karo aur discard karo. Yeh hamesha safe kyun hai? Torn descriptor ya torn journal-data sirf COMMIT se pehle ho sakta hai (commit aakhir mein likha jaata hai), isliye koi checkpoint nahi chali — in-place filesystem abhi bhi pre-transaction hai.
Verify: Dono E aur K same rule pe reduce ho jaate hain: kisi bhi record par koi bhi failed checksum ⇒ committed nahi ⇒ discard ⇒ pre-transaction state preserved. Har case mein crash step 5 se pehle tha, isliye consistency holds. ✅
Worked Example 6 — Cells F1 & F2: same crash par ordered vs writeback
Forecast: kaunse mode mein user reboot ke baad is file se kisi aur ki purani deleted data padh sakta hai?
Steps se pehle, notation ka ek piece. Hum likhenge do writes kab finish hote hain compare karne ke liye:

Figure mein kya dekhna hai: top row (ordered) orange "data → disk" box ko magenta COMMIT box se pehle finish hone ke liye force karta hai, isliye reader green "read → REAL bytes" par landa. Bottom row (writeback) pehle COMMIT hai aur grey "data NOT landed" box uske baad; orange crash line data land hone se pehle pad jaati hai, isliye reader orange "read → GARBAGE" par landa. Same crash column, opposite ending.
- Writeback mode path (Cell F2). Metadata journal kiya jaata hai, lekin data commit se pehle ordered nahi hota — yaani writeback enforce nahi karta. Yeh khatarnaak kyun hai? Inode (size 8 KB, pointer → block 50) commit hota hai aur replay hota hai, lekin block 50 kabhi actually nahi likha gaya — woh abhi bhi stale/garbage bytes hold karta hai jo pehle use karta tha. File padhne se woh garbage return hoti hai: ek integrity/security leak.
- Ordered mode path (Cell F1). Rule enforce karta hai: data block disk par pehle pahuncha metadata commit se (Example 1 ka step 1). Yeh hole kaise band karta hai? Agar data neeche nahi hai, commit likhne ki permission nahi; isliye committed inode ka matlab guaranteed hai ki real naye bytes hain.
- Same crash, opposite safety. Identical timing, alag mode → writeback garbage expose karta hai, ordered nahi karta. Yahi wajah hai ki ordered default hai.
Verify: Ordering constraint symbolically trace karo. Ordered mode enforce karta hai, jo ek logical implication hai : agar crash ne commit chhod diya, data guaranteed present hai. Writeback constraint drop kar deta hai, isliye hamare ko ke baare mein kuch nahi batata — state " true, false" possible hai, exactly garbage case. Logic check out hoti hai. ✅
Worked Example 7 — Cell J: full journal (data) mode
Forecast: data-before-commit flush ke bina, reboot par sahi data bytes kahan se aate hain?
- Journal mode mein, step 3 ne naya data block bhi journal mein likha, sirf metadata nahi. Kyun? Yahi mode ka poora point hai — journal sab kuch ki complete, durable copy hold karta hai, isliye woh self-sufficient hai. Recovery ko block rebuild karne ke liye journal ke alawa kahan aur dekhna hi nahi padta.
- Recovery TX#7 ko valid COMMIT ke saath dhundhti hai → saare journalled blocks replay karo, including data block, unke real homes par. Data safe kyun hai? Kyunki woh commit se pehle durably log hua tha; commit certify karta hai ki journal mein data copy complete hai (Cell E jaisi hi checksum guarantee).
- Koi garbage window exist nahi karta. Kyun? Writeback (jahan data missing ho sakta hai) aur even ordered (jahan sirf ordering guarantee hai) se alag, yahan data khud journal mein rehta hai, isliye committed transaction hamesha fully reconstruct ho sakta hai — har data block ko do baar likhne ki cost par.
Verify: Bytes reconstruct karo. Journal mode mein final data journal copy se aata hai, jise commit complete certify karta hai → real block replay par sahi naye bytes pata hai, chahe kabhi separately flush nahi hua. Cost check: har data block journal mein likha jaata hai (ek baar) aur phir in place checkpoint hota hai (ek baar) = data block per 2 writes, parent ke "har cheez do baar likhi jaati hai" se match karta hai. ✅
Worked Example 8 — Cell G (degenerate empty transaction) + Cell H (durability trap)
Forecast: kya woh phir bhi descriptor aur commit likhta hai?
- Transaction koi blocks touch nahi karta, isliye descriptor empty block set naam karta hai. Transaction kyun kholna bhi? Code path consistency ke liye — lekin ek smart implementation notice karti hai ki log karne ke liye kuch nahi hai.
- Koi journal writes nahi, koi checkpoint nahi. Safe kyun? (identity): "no change" apply karna kitni bhi baar state ko fixed rakhta hai. Crash pehle ya baad same hai.
Verify: Zero blocks changed ⇒ inode, bitmap, data sab crash se pehle aur baad identical ⇒ trivially consistent. Idempotent for free (identity idempotent hai: ). ✅
Forecast: filesystem corrupt? data present? user ko honest jawaab kya hai?
- Filesystem consistent hai. Kyun? Jo bhi commit hua tha woh cleanly replay hota hai; kuch bhi half-broken nahi hai. Yahi journaling ki actual guarantee hai.
- Lekin un-synced writes gone ho sakte hain. Kyun? Journaling consistency deta hai, un-flushed writes ka durability nahi. Buffered bytes jo kabhi disk tak nahi pahunche, lost hain — fsync and Durability dekho.
- User ke liye fix: critical writes ke baad
fsync()call karo durability force karne ke liye. Journaling aur durability alag guarantees hain.
Verify: Do properties alag karo. Consistency = "koi contradictory on-disk state nahi" → holds. Durability = "ek acknowledged write crash survive karta hai" → sirf flushed data ke liye holds. User ne unhe confuse kiya; sahi statement hai "corrupt nahi, lekin recent unsynced kaam lost ho sakta hai." ✅ (Yeh parent ke pehle [!mistake] ka exact trap hai.)
Worked Example 9 — Cell I (exam twist): do transactions, doosra uncommitted
Forecast: kya TX#8 par missing commit TX#7 ko bhi poison karta hai, ya dono independent hain?

Figure mein kya dekhna hai: do block groups. Left group (TX7) ek magenta COMMIT box par khatam hota hai aur green mein "→ REPLAY" label hai. Right group (TX8) ek grey "no COMMIT" box par khatam hota hai aur orange mein "→ DISCARD" label hai, crash line uske commit se thodi der pehle pad rahi hai. Groups ke beech ka gap visual reminder hai ki har ek apne aap judged hota hai.
- Log order mein scan karo; har transaction ko uske apne COMMIT se independently evaluate karo. Independent kyun? Har transaction apna all-or-nothing unit hai; commit boundary per-transaction hai (yeh Atomicity hai).
- TX#7 ka valid COMMIT hai → usse replay karo (uske blocks ko unke in-place homes par re-copy karo). Kyun? Committed ⇒ saare blocks safely logged ⇒ idempotently apply karna safe hai.
- TX#8 ka koi COMMIT nahi → discard karo aur wahan scanning band karo. Wahan kyun rokein? Jab valid commit ke bina transaction milta hai, uske baad kuch bhi trust nahi kiya ja sakta — yeh log ka high-water mark hai.
- Final on-disk state:
a.txtek block longer hai (TX#7 applied);b.txtbilkul waisa hai jaise pehle tha (TX#8 discarded, uske in-place blocks kabhi checkpoint nahi hue).
Verify: Do logically separate operations, do independent outcomes: TX#7 applied = True, TX#8 applied = False. a.txt appended, b.txt unchanged, koi cross-contamination nahi — exactly woh jo per-transaction atomicity promise karta hai. ✅
Recall
Recovery journalled har transaction ke liye kaunsa single fact check karta hai? ::: Kya uska COMMIT block present hai aur checksum pass karta hai.
Cell C mein (crash mid-checkpoint) pehle se update ho chuke inode ko dobara likhna safe kyun hai? ::: Checkpointing ek fixed final value se overwrite karta hai, isliye — idempotent, jahan pre-apply state hai.
Cells E aur K mein, torn commit / descriptor / journal-data blocks kaise detect hote hain? ::: Har journal record ek checksum carry karta hai; koi bhi mismatch ⇒ transaction ko not committed treat karo ⇒ discard.
Cell F mein, ordered mode kabhi garbage expose kyun nahi karta jabki writeback kar sakta hai? ::: Ordered data-before-commit () enforce karta hai, isliye committed inode guaranteed real bytes point karta hai.
Cell J (full journal mode) mein, replay par sahi data bytes kahan se aate hain? ::: Journal se hi — data block commit se pehle journal mein copy kiya gaya tha, data do baar likhne ki cost par.
Cell H mein, kya crash ke baad filesystem corrupt tha? ::: Nahi — sirf consistency guarantee hai; unsynced buffered writes phir bhi lost ho sakte hain. fsync() use karo.
Cell I mein, TX#8 ka missing commit TX#7 ko kyun affect nahi karta? ::: Har transaction ek independent atomic unit hai jo apne commit block se judge hoti hai.
Prerequisite / neighbour links: File Systems · Write-Ahead Logging · Databases · Atomicity · fsync and Durability · Copy-on-Write Filesystems · fsck