빙응의 공부 블로그

[OSTEP 영속성(persistence)]크래시 일관성: FSCK와 저널링 본문

CS/운영체제

[OSTEP 영속성(persistence)]크래시 일관성: FSCK와 저널링

빙응이 2025. 7. 15. 20:51

📝서론 

이번 장에서는  파일 시스템이 자료 구조를 안전하게 저장하는 방법에 대해 알아보자

 

파일 시스템이 직면한 가장 큰 어려움 중 하나는 전력 손실이나 시스템 크래시와 같은 장애 상황 이다.
이러한 상황에서도 디스크의 데이터가 어떻게 안전하게 갱신되는가는 중요한 문제다.

 

 

이 과정을 살펴보면서, 우리는 데이터베이스에서 사용하는 트랜잭션 처리 원리와 유사한 개념을 파일 시스템에서도 체험할 수 있을 것이다.

 

📝크래시 시나리오

  • 데이터 블록만 디스크에 기록됨
    • 이 경우 데이터는 디스크에 있지만 아이노드가 없고 할당 여부를 나타내는 비트맵도 없다.
    • 파일 시스템에서 접근이 불가능해 크래시 일관성에서 문제가 없다.
  • 갱신된 아이노드만 디스크에 기록됨
    • 데이터블록이 기록되지 않아서, 의미없는 데이터를 얻게된다.
    • 일관성 손상이라는 문제가 발생한다.
  • 갱신된 비트맵만 디스크에 기록됨
    • 비트맵은 기록되었다고 표시하지만, 아이노드는 그렇지 않다.
    • 데이터블록을 파일시스템에서 사용이 불가능하다.

 

📝크래시 일관성 문제

크래시 때문에 파일 시스템 디스크 상의 자료 구조는 많은 문제가 발생한다.

  • 파일 시스템 자료 구조 간의 불일치
  • 공간 누수
  • 사용자에게 의미없는 데이터 전달 

이러한 문제를 우리는 크래시 일관성 문제라고 부른다.

그렇기 때문에 파일 시스템의 일관성이 항상 유지되도록 만들어야한다. 

 

📝해법 1: 파일 시스템 검사기 

초기 파일 시스템은 크래시 일관성을 해결하기 위해 간단한 방법을 사용하였다.

기본적으로 파일 시스템이 일관성이 없더라도 그대로 두었다가 리부팅 시에 일관성 문제를 해결하였다.

fsck : 일관성 불일치를 발견하고 수정하는 Unix의 도구
  • 슈퍼블럭: 슈퍼블럭 내용에 오류가 없는지를 검사한다.
  • 프리블럭: 아이노드와 간접 블럭, 이중 간접 블럭 등을 살펴보고 파일 시스템에 현재 어떤 블럭들이 할당되었는지에 대한 정보를 생성한다.
  • 아이노드 상태: 각 아이노드가 손상되었는지 다른 문제는 없는지 검사한다.
  • 아이노드 링크: 각 할당된 아이노드의 링크 개수를 확인한다.
  • 중복: 중복된 포인터가 있는지도 검사한다.
  • 배드블럭: 모든 포인터 목록을 검사하면서 배드블럭 포인터들도 함께 검사한다.
  • 디렉터리 검사: 파일의 내용을 파악하는 것은 불가능하나, 디렉터리 내용에 대해서는 모든 내용이 제대로 저장되어 있는지의 검사를 수행한다.

 

그러나 fsck를 만드는 것은 보통일이 아니다. 파일 시스템 전반에 대한 이해가 필요하다. 

또한 근본적으로 매우 느리다. 모든 파일을 검사하기 때문이며 만약 디스크 용량이 매우 커지면 큰일이다.

📝해법 2: 저널링 (또는 Write-Ahead Logging)

디스크 내용을 갱신할 때,해당 자료구조를 갱신하기 전에, 먼저 수행하고자 하는 작업을 요약해서 기록해두는 해법이다.

대표적인 저널링 파일 시스템은 Linux ext3 파일 시스템이 있다.

데이터 저널링
  • 물리 로깅 : 갱신해야할 물리적 내용을 저널에 기록
  • 논리 로깅 : 갱신 명령어 자체를 저널에 기록 

이러한 저널링을 진행하고 트랜잭션이 종료된다면 트랜잭션 종료 로그를 기록하게 된다. 이것을 커밋이라고 부른다.

 

체크포인팅

체크 포인팅은 트랜잭션이 디스크에 안전히 기록된 후, 파일 시스템 상의 자료 구조들은 이제 갱신될 수 있다.

저널에 기록된 내용을 실제 위치에 반영하는 것을 체크포인팅이라고 부른다.

 

데이터 갱신 과정
  1. 저널 쓰기 : 트랜잭션의 내용(물리 로그, 논리 로그)를 로그에 쓴다.
  2. 저널 커밋 : 트랜잭션이 완료되면 트랜잭션 커밋 블록을 로그에 쓴다.
  3. 체크포인팅 : 갱신한 내용을 디스크 최종 위치에 쓴다.

 

복구

파일 시스템의 복구 프로세스는 시스템이 부팅할 때 로그를 탐색해서 디스크에 커밋된 트랜잭션이 있는지 파악한다.

커밋된 트랜잭션 블럭들을 디스크 상의 원래 위치에 쓴다. 이 과정을 재생(replayed)이라고 한다.

가장 간단한 로그 방식이며 redo logging이라고 한다.

 

로그 기록을 일괄 처리 방식으로

지금까지의 데이터 저널링 방식은 디스크에 엄청난 트래픽을 유발한다. 그래서 리눅스는 여러 개의 저널 로그를 모아서 한 번에 디스크에 커밋하는 방법을 사용한다. 

 

📝메타데이터 저널링

복구 시간 단축은 어느정도 성공했지만 파일 시스템이 로깅으로 인해 느려졌다.

디스크는 모든 작업에서 저널을 기록하기 때문이다.

 

이러한 문제를 개선하기 위해 메타데이터 저널링을 사용하게 되었다.

메타데이터 저널링
  • 기존의 문제점 : 파일 시스템이 로깅으로 인해 현저히 느려짐(데이터 블록이 특히 오래걸림)
  • 메타데이터 저널링 : 기존 저널링과 동일하나 데이터 블록은 저널링하지 않는 기법

이렇게 메타데이터 저널링은 크래시 복구의 최소한의 재료만 저널링하는 기법이다. 

그러나 메타데이터 저널링은 기록 순서에 예민한 단점이 존재한다. (유실 가능성)

 

메타데이터 저널링 순서
  1. 데이터 쓰기: 데이터를 최종 위치에 쓴다.완료될 때까지 대기한다(사실 꼭 대기할 필요는 다.상세 설명은 아래를 참고하기 바란다).
  2. 저널 메타데이터 쓰기: 시작 블럭과 메타데이터를 로그에 쓴다. 완료될 때까지 기다린다.
  3. 저널 커밋: 트랜젝션 커밋 블럭을 로그에 쓴다(TxE를 포함).쓰기가 완료될 때까지 기다린다. 트랜젝션은 이제 (데이터를 포함하여)커밋된 상태이다.
  4. 체크포인트 메타데이터: 갱신된 메타데이터의 내용을 파일 시스템 상에 있어야 할 최종 위치에 갱신한다.
  5. 해제: 저널 슈퍼블럭에 해당 트랜젝션이 해제되다고 표기한다.

데이터가 먼저 기록되는 것을 강제하여 아이노드 포인트가 쓰레딕 데이터를 가리키지 않는 것을 보장한다.