CS/운영체제

[운영체제] 27. FSCK and Journaling

공영재 2023. 12. 10. 22:50

Reference - Operating Systems: Three Easy Pieces

 

 

https://pages.cs.wisc.edu/~remzi/OSTEP/

 

Operating Systems: Three Easy Pieces

Blog: Why Textbooks Should Be Free Quick: Free Book Chapters - Hardcover - Softcover (Lulu) - Softcover (Amazon) - Buy PDF - EU (Lulu) - Buy in India - Buy Stuff - Donate - For Teachers - Homework - Projects - News - Acknowledgements - Other Books Welcome

pages.cs.wisc.edu

 

 

FSCK and Journaling

 

디스크는 저장한 데이터가 소실되길 원하지 않는다. write할 때, 눈에 보이는 것과 달리 실제 컴퓨터에선 write가 세번 일어난다. (one each of inode, data bitmap, data block) 이 중에 1, 2번 과정에서 fail(컴퓨터 꺼짐)이 발생하면 inode는 작성되어서 파일은 있지만 bitmap이 없어서 막상 까보면 없는 경우의 문제를 crash consistency라 한다. 즉, 파일의 상태를 있으면 있고, 없으면 없도록 일관성있게 유지하도록 하는것이다.

 

Crash consistency problem

 

storage는 항상 persistent해야하는데, crash가 일어났을 때 이를 유지하지 못하는 문제

 

update시 일어나는 3개의 변경점

- data block 쓰기 - data bitmap 업데이트 - inode 업데이트 (순서는 상관없이 업데이트된다.)

이 3개 순서에 따른 scenario를 살펴볼것이다.

 

crash scenario

1

data block만 쓰고 inode/bitmap 못쓰면 -> 이는 inode가 없어 쓰기가 없었던 것과 같다. -> consistency 문제는 아님

inode만 쓰고 bitmap / datablock 못쓰면 -> inode에 data가 없어서 garbage data를 읽을 것 -> file system inconsistency

bitmap만 쓰면 - bitmap이 특정 block이 사용중이라 판단하므로 마찬가지로 inconsistent

 

inode / bitmap o - datablock x -> 메타데이터는 consistent하지만 block이 garbage일 것.

inode / datablock o - bitmap x -> inode와 bitmap 사이의 inconsistent

bitmap / datablock o - inode x -> 마찬가지 inconsistent, 공간 낭비 발생

 

결론적으로 atomically하게 연산을 수행하게끔 해야한다. 이를 journaling이라 한다.

그전에 FSCK를 살펴보겠다.

 

- FSCK (file system checker)

FSCK는 리눅스 툴로, 디바이스를 제거할 때 os가 레코딩을 하는데, 오류를 체킹하고 알려준다.

inconsistencies가 있다면 이를 복구해준다. (다른 os도 이름은 다르지만 존재한다.)

파일시스템이 마운트(=물리 장치와 디렉토리 연결)되기 전에 돌아간다.

하지만 모든 문제를 fix해주진 못한다 - inode와 bitmap이 있지만 datablock이 없는 경우, 즉 consistent한 경우는 고칠 수 없다. 이때는 무시하거나, 확률적으로 더 높은 부분을 선택하거나, 사용자에게 체크를 요청하는 방법을 쓴다. FSCK는 데이터를 복구하는게 아닌, 메타데이터 consistent하게 만들어서 추후 문제가 발생하지 않도록 하는게 목표다.

 

- FSCK가 하는 일

inode state - inode의 기록에 문제가 있다면 inode를 삭제하고 bitmap은 free시킨다.

free block - bitmap과 inode 사이의 inconsistency만 해결할 수 있다. (1c. 2b)

directory checks - 자식은 있는데 부모는 없는 등 디렉토리에 문제가 있는지 확인한다.

 

FSCK의 문제는 너무 느리고 완전한 복구가 불가능하다는 것이다.

 

이를 해결하기 위해 journaling이 나왔다.

우리가 쓰는 대부분의 파일 시스템은 journaling을 쓴다.

 

- Journaling (Write-Ahead Logging)

 

파일 시스템 변화가 있을 때 바로 적용하는게 아니라, 디스크의 다른 영역에 log를 미리 기록을 해놓는다.

만약 crash가 일어나면 log를 먼저 보고 문제가 있는지 없는지 확인하고 main 영역에 적용시키게 된다.

ext = 리눅스 파일시스템

ext2 = fast file system

ext3 = +journaling 지원, Journal만 디스크에 할당

final location에 할당하기 전에, TxB(transaction Block) I, B, Db, TxE(Transaction End block)를 모두 기록한다.

begin은 있는데 end가 없거나 하면 트랜잭션이 완료가 안되었다는 뜻이므로 버린다. 이를 통해 check할 수 있다.

TxB와 TxE가 모두 있다면 main영역에 이동시키고 journal을 삭제한다. 이렇게 5개가 있는걸 확인한 뒤 journal에서 disk로 옮기는 과정을 checkpoint라 한다.

이러한 추가적인 과정은 퍼포먼스를 느리게 만든다. 이를 개선시키기 위해 메모리 buffer에 넣어뒀다가 5개를 한번에 flush한다. 하지만 이는 unsafe하다. 디스크가 저 5개를 순서에 맞춰 쓰게끔 할거란 보장이 없다.

예를 들면, TxB, I, B를 쓰고 디스크가 TxE가 더 빠를 것이라 생각하고 TxE를 Db보다 먼저 쓸 수 있다는 것이다.

각각을 순서대로 기다렸다가 배치하는 것은 너무 느리다.

그래서 TxE를 제외한 나머지를 먼저 쓰게 하고 그 뒤에 TxE 블록을 써서 트랜잭션을 완성한다. 이러한 과정을 Journal commit이라 한다.

즉, journal write(journal에 TxE 후 3개의 데이터를 다쓸때까지 기다리는 과정) -> journal commit -> checkpoint 순서로 진행된다. 이러한 방법을 통해 원자성을 보장할 수 있게 된다.

recovery의 경우 transaction이 log에 쓰여지기 전이라면 skip하고, log엔 쓰여졌지만 checkpoint가 완료되기 전이면 journal의 log를 scan해서 transaction을 다시 시도한다.

 

업데이트가 끝나면 journal에서 해당 transaction을 제거해줘야 한다. 이 과정은 checkpoint가 끝나면 수행된다.

어떤 트랜잭션을 제거할지에 대한 정보는 journal superblock에 저장되며, 완료된 transaction을 free시킨다.

 

교재 외의 얘기로, 모든 datablock을 하면 사이즈가 너무 커서 performance가 매우 안좋아지기 때문에, 교과서엔 없지만 실제로는 메타데이터만 저널링한다고 한다.