내용

1. 저널링 기법(Journaling) 도입

- 의도치 않게 시스템이 멈추거나 정전으로 컴퓨터가 꺼지게 되는 경우가 종종 존재할  있게 되는데, 이때 파일시스템을 업데이트 하고 있었다면 파일시스템의 일관성 문제를 초래할  있게  것이다.

- 파일을 생성하고 데이터를 쓰는 도중에 시스템이 갑자기 멈춘다면 해당 파일은 신뢰할  없는 상태가  것인데  때문에 파일시스템의 일관성 체크를 위해 e2fsck 등의 유틸이 존재하게 되었다.

- e2fsck 경우 파일시스템을 마운트 하는 시점에 기존의 파일시스템이 정상적으로 Unmount 되지 않았다면 검사를 수행하게 되는데, 저장장치 내에 있는 모든 Inode 비트맵 데이터 등의 메타 데이터를 검사하여 일관성 문제를 해결한다. 그러나 요즘 하드디스크 용량은 엄청나게 늘어났기 때문에 모두 검사를 하게 되면 시간이 오래 걸리게  것이고 이런 문제로 인해 저널링 기술이 파일시스템에서도 사용하게 되었다.

 

2. 저널링 파일 시스템과 Ext3

- 저널링 기법은 데이터베이스의 기본적 특징을 구현하기 위한 방법의 하나로 일종의 로깅(Logging) 기법을 이용한 데이터 백업 체계라고   있을 것이다.

- 데이터베이스에서 트랜잭션 단위로 커밋과 롤백이 가능한게 데이터 업데이트  원본 데이터 영역에 바로 쓰는 것이 아니라 로그를 기록한  최종적용을 하거나 취소를 하기 때문인데 이를 파일시스템에 적용한 것이다.

- 파일을 쓰는 작업  파일시스템의 특정 영역 저널(Journal)이라 불리는 로그를 기록한  작업이 정상 완료  커밋(commit) 하면 실제 사용되는 영역에 기록 하는 것이다.

- 이렇게 되면 시스템이 갑자기 종료되더라도  위치가 어디인지 파악할  있고, 파일 시스템 전체를 검사할 필요가 없어지게  것이다. 따라서 파일시스템을 마운트 하는 시점에 일관성 검사  소요되는 시간이 굉장히 줄어들 것이다.

- 이런 기법은 다른 파일시스템에도 많이 사용되고, Ext3 장점은 Ext2 완벽한 호환을 가지게 된다. 따라서 저널링 기능을 사용하기 위해 파일시스템을 교체할 필요가 없으며, 일체의 손상 없이 저널링 기능만을 추가  삭제하는 것은 매우 쉽다.

- 어느 정도 검증된 Ext2 파일시스템에 저널링 기능만 부가한 파일시스템인 Ext3 리눅스의 기본 파일 시스템으로 자리잡게  것이다.

 

3. Ext3 파일시스템의 저널링 기법

- Ext3 저널링 방식에 로그 기록 옵션이 크게 3가지가 있는데 이를 알아보자.

 

 

1) Wirteback 모드

- 파일 시스템의 데이터 저널링을 사용하지 않고, 메타 데이터의 변경 이력만 로그로 남긴다. 변경 이력만 저장하고, 실제 메타 데이터는 저장하지 않아 파일이 쓰여지는 시점에서 시스템 Crash 발생 하면 해당 파일이 비교적 쉽게 손상된다. 그러나 파일시스템의 일관성을 유지하는 것은 충실하며, 저장 데이터가 적기 때문에 다른 모드에 비애 속도가 뛰어난 장점이 있어 다른 여러 저널링 파일시스템에서 유사하게 사용되는 방식이다.

 

2) Ordered 모드

- 파일시스템의 메타 데이터 저널링을 구현하는 방식으로 실제 로깅되는 데이터는 메타 데이터뿐 아니라 관련 데이터 블록을 함께 포함하여 트랜잭션 단위로 그룹화 한다. 따라서 전체 데이터 블록을 저널링하지 않더라도 파일시스템 손상  효과적으로 복구하며  속도 또한 빠르다. 효율과 안전성을 절충한 방식이기 때문에 가장 널리 사용되는 모드이기도 하다.

 

3) Journal 모드

- 메타데이터  아니라 데이터 블록에 대한 모든 변경 로그를 남긴다. 따라서 안전성을 보장 받지만 파일 I/O 2배로 일어나 가장 느린 모드이다.

- 모든 데이터가 쓰여질 때는 저널링 영역에 먼저 쓰여진  최종적으로 원래 쓰고자 했던 위치에 파일을 쓰게 된다.

저널링 기능이 파일시스템의 일관성  시스템 Crash 상황의 데이터 복구 기능까지 좋은 성능을 보이지만 이는 시스템  차원의 문제이다.  커널이 동작하고 상위 레벨 시스템 콜을 이용한 로깅 기법이기 때문에 파일시스템 입장에서 보면 일종의 유틸리티라고   있기 때문에 파일시스템을 직접 구현하고자 한다면 설계 시점부터 저널링 기능을 구현할 것인지 염두 하여야  것이다.

 

 

4. 저널 데이터 구조

- 저널 로그 기록 영역은 저널링을 위한 영역에 따로 저장되는데  영역을 찾기 위해서는 Super Block Journal Inode Number 항목을 읽어 들여 찾아갈  있게 된다.

- 일반적으로 저널링을 위한 Inode 8번으로 예약 되어 있다.

- Super Block 저널링 항목들은 저널링 기능을 지원하는 경우에만 관련 항목들을 사용하게 되며, 그렇지 않으면 Padding 위해 예약된 영역으로 비워두고 사용하면  것이다.

- 저널링  파일시스템의 동작에 있어 필수적인 요소는 아니라는 점이다.

- 저널링 기능을 사용할  없는 저장장치가 있음으로 저널링을 설치하였음에도 동작하지 않으면 Super Block incompatible feature flags 항목에 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV(0x0008) 플래그가 ON되어 있는지 확인 해보자. 이때 Ext3 아닌 Ext2 인식할  파일시스템의 동작에 아무런 문제가 없다.

 

- Ext3 파일시스템의 저널링 기능으로 4가지 구조체를 사용한다.  데이터들은 다른 저널 데이터들과 구분할  있도록 Signature 가지며, Ext2 데이터가 저장되는 방식과 달리 Big Endian 방식을 사용하므로 데이터를 읽을  유의해야 한다.

 

1) Journal Header(12Byte)

 

이름

Signature

위치

(Offset)

0

크기

(Size)

4 Byte

일반적인 

(Value)

0xc03b3998U

설명

저널 헤더의 Signature 값으로 리눅스 커널 소스의 linux/include/linux/jdb.h 경로에 정의 되어 있다.

 

#define JFS_MAGIC_NUMBER 0xc03b3998U

 

이름

Block Type

위치

(Offset)

4

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

앞서 언급한 4가지 구조체(Journal Super Block, Descriptor, Commit, Revoke Block)들을 구분하기 위한 Block 타입의 고유 값이 기록되며 값들은 아래표를 확인 하자

 

[저널링 Descriptor Block 타입]

Block 타입

설명

JFS_DESCRIPTOR_BLOCK

1

Descriptor Block

JFS_COMMIT_BLOCK

2

Commit Block

JFS_SUPERBLOCK_V1

3

Journal Super Block version 1

JFS_SUPERBLOCK_V2

4

Journal Super Block version 2

JFS_REVOKE_BLOCK

5

Revoke Bolck

 

이름

Sequence Number

위치

(Offset)

8

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

트랜잭션(transaction) 관리를 위한 시퀀스 번호로  번호를 이용하여 트랜잭션이 시작되고 Commit 된다.

 

2) Journal Super Block

 

이름

Journal Header

위치

(Offset)

0

크기

(Size)

12 Byte

일반적인 

(Value)

가변적

설명

위에서 Journal Header 구조체

 

이름

Journal block size

위치

(Offset)

12

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

저널링에 사용되는 Block 크기로 고정되어 있진 않으나 일반적으로 0x400(1024) Byte 사용 된다.

 

이름

Number of journal blocks

위치

(Offset)

16

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

저널링에 사용되는 최대 Block 

 

이름

Journal start block

위치

(Offset)

20

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

저널 데이터가 기록된 최초 블록

 

이름

Sequence number of transaction

위치

(Offset)

24

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

 트랜잭션이 일어난 시퀀스 번호

 

이름

Journal block of first transaction

위치

(Offset)

28

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

 트랜잭션이 일어난 블록의 번호

 

이름

Error Number

위치

(Offset)

32

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

에러 코드로  값은 리눅스 커널 소스의 journal_abort( ) 함수에 의해 쓰여진다.

 

- 아래 항목들은 Journal Super Block Version 2, Version 1 이어서 추가로 기록되는 영역이다. 따라서 앞의 구조체의 뒤를 이어 추가하여야 한다.

 

이름

Compatible Teatures

위치

(Offset)

36

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

저널링 시스템과 호환 가능한 특징

 

이름

Incompatible Feature

위치

(Offset)

40

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

저널링 시스템과 호환 불가능한 특징으로 현재 정의된 플래그는 아래 항목 하나 뿐이다.

 

#define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001

 

이름

Read only Compatible Features

위치

(Offset)

44

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

저널링 시스템에서 읽기 전용인 특징

 

- 위의 3 항목들은 현재까지 정의된 특징들이  가지밖에 없기 때문에 크게 신경 쓰지 않아도 되지만 앞으로 추가될 여지를 두고 있으니 필요시 그때그때 가장 최근 소스를 참고하길 바란다.

 

이름

Journal UUID

위치

(Offset)

48

크기

(Size)

16 Byte

일반적인 

(Value)

가변적

설명

저널링에 사용되는 128bit UUID

 

이름

Number of filesystems using jornal

위치

(Offset)

64

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

파일시스템에서 사용하는 저널의 개수

 

이름

Location of super block copy

위치

(Offset)

68

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

Super Block 복사본이 있는 블록 번호

 

이름

Max journal blocks per transaction

위치

(Offset)

72

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

트랜잭션당 저널 블록의 최대 개수

 

이름

Max filesystem blocks per transaction

위치

(Offset)

76

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

트랜잭션당 파일시스템 블록의 최대 개수

 

이름

Padding

위치

(Offset)

80

크기

(Size)

176 Byte

일반적인 

(Value)

가변적

설명

패딩 용도의 사용되지 않는 영역

 

이름

16-byte IDs

위치

(Offset)

256

크기

(Size)

768 Byte

일반적인 

(Value)

가변적

설명

파일시스템에서 사용하는 저널의 UUID(128bit) 기록하며, UUID 16Byte이므로 48개를 연속 기록   있다.

 

3) Journal Descriptor Block Entry(journal_block_tag_t)

- Block Tag 부르기도 하는 Journal Descriptor Ext2 파일시스템의 블록 위치와 상태  등을 나타내기 위한 작은 영역이다. 그러나  영역을 나타내기 위해 Journal Super Block 같이 Signature 필요하다.

- 아래 항목(실제 구조체)에는 생략되었지만  항목들에 앞서 Journal Header 위치하여 Descriptor 나타내고 있다. 모든 구조체 들은 Journal Header 포함해야 하는걸 잊지 말아야 한다.

 

이름

Block Number

위치

(Offset)

0

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

파일 시스템 내의 블록 번호

 

이름

Descriptor Entry Flags

위치

(Offset)

4

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

Descriptor Entry 상태 플래그. 아래  참조

 

[Descriptor Entry 타입]

Entry 타입

플래그

설명

JFS_FLAG_ESCAPE

0x01

저널 블록이 잘못된 경우

JFS_FLAG_SAME_UUID

0x02

앞선 Entry UUID 같은 경우

JFS_FLAG_DELETED

0x04

현재의 트랜잭션으로 인해 블록이 지워진 경우

JFS_FLAG_LAST_TAG

0x08

현재의 Entry 저널의 마지막 Entry  경우

 

- JFS_FLAG_ESCAPE 플래그가 사용되는 시점은 다음 읽어 들이는 파일시스템 블록에서 Journal Header Signature 읽혀진 경우로  경우 Journal 의해 해당 데이터가 초기화 된다.

 

4) Revoke Block

이름

Journal Header

위치

(Offset)

0

크기

(Size)

12 Byte

일반적인 

(Value)

가변적

설명

앞에서 나온 Journal Header

 

이름

Block Size

위치

(Offset)

12

크기

(Size)

4 Byte

일반적인 

(Value)

가변적

설명

저널 로그를 기록한 블록의 크기(Byte 단위)

 

이름

Revoked Data Block

위치

(Offset)

16

크기

(Size)

x Byte

일반적인 

(Value)

가변적

설명

 영역은 Block Size 만큼의 크기를 가지며, 로깅이 취소된 데이터 블록의 포인터를 가리키는 배열로 이루어져 있다. 따라서 4Byte 단위로 데이터를 읽어 들인다.

 

- 모든 저널 로그들은 트랜잭션 단위로 그룹화되며, 각각의 트랜잭션들은 시퀀스 번호를 부여 받게 되며, 저널 데이터는  트랜잭션을 관리할  있는 정보와 파일시스템의 변경 내역에 대한 데이터를 가지고 있어 이를 이용하여 비정상적으로 시스템이 정지한 상황에 수행했던 작업을 마무리 한다.

- commit  저널 데이터는 e2fsck에서 정상 데이터로 분류하여 파일시스템에 기록

- commit 되지 않은 경우 완료되지 않은 데이터로 무시하고 넘어감.

+ Recent posts