[OS] Ext4 Structure : Superblock
linux kernel sourse tree의 깃허브 코드를 참조해 Ext4의 주요 구조체를 정리한 글입니다.
Ext4 주요 구조체 정리
Superblock, inode, dentry, Block Group, extent, orphan, Journal
📌 Ext4 Superblock
🫧 Superblock
Superblock은 전체적인 파일 시스템의 정보를 담고 있다.
슈퍼 블록이 손상되면 파일 시스템 전체의 데이터가 날아가는 것이므로 이를 방지하기 위해 여러 개의 블록 그룹에 모두 동일한 값으로 저장한다.
- 총 inode 개수
- 총 블록 수
- 사용 가능한 블록 수
- 사용 중인 블록 수
- 블록 크기
다음은 /fs/ext4/ext4.h, $1304에 위치한 superblock 구조체이다.
편의를 위해 일부 생략하였으므로 전문을 보고 싶으신 분들은 Linux 오픈소스를 참고해 주세요.
🫧 Cluster
: 여러 개의 연속된 블록을 묶은 단위
ext4에서는 클러스터가 블록보다 큰 단위로 사용될 수 있으며, 기본적으로 블록의 크기는 4KB, 클러스터는 이 블록의 묶음으로 정의된다.
클러스터는 큰 저장 공간의 효율적 관리를 위해 사용하며, 한 클러스터의 크기를 블록 크기보다 크게 잡음으로써 보다 적은 메타데이터를 관리할 수 있고, 디스크 입출력을 최적화할 수 있다.
extents와 cluster의 차이점은 여기에서..
🫧 코드
- /fs/ext4/ext4/h, $1304
struct ext4_super_block {
/*00*/ __le32 s_inodes_count; // 전체 inode 수
__le32 s_blocks_count_lo; // 전체 블록 수
__le32 s_free_blocks_count_lo; // 사용 가능한 블록 수
/*10*/ __le32 s_free_inodes_count; // 사용 가능한 inode 수
// 실제 데이터가 저장될 수 있는 첫 블록 번호 (0 or 1)
// 0인 경우 슈퍼 블록은 블록 그룹 0의 블록 1에 위치, 그 이후부터 가용 블록
// 1인 경우 슈퍼 블록이 블록 그룹 0의 블록 0에 위치, 블록 1부터 가용 블록
__le32 s_first_data_block;
__le32 s_log_block_size; // 블록 크기
__le32 s_log_cluster_size; // 클러스터 크기 (로그 단위로 표현)
/*20*/ __le32 s_blocks_per_group; // 한 블록 그룹에 포함된 블록 개수
__le32 s_clusters_per_group; // 한 블록 그룹에 포함된 클러스터 개수
__le32 s_inodes_per_group; // 한 블록 그룹에 포함된 inode 개수
__le32 s_mtime; // 마운트된 시각
// 마지막으로 파일 시스템이 수정된 시간 (파일 수정 시 이 값도 수정됨)
/*30*/ __le32 s_wtime; // 마지막 쓰기 시간
__le16 s_magic; // 매직 넘버 (ext 계열인지 확인)
__le32 s_first_ino; // 사용 가능한 첫 inode 번호 (보통 11부터 시작)
__le16 s_inode_size; // inode 구조체 바이트 크기
/*68*/ __u8 s_uuid[16]; // 파일 시스템을 고유하게 식별하기 위한 UUID
/*88*/ char s_last_mounted[64] __nonstring; // 마지막 마운트 경로
__u8 s_prealloc_blocks; // 일반 파일에 대해 미리 할당할 블록 수 (보통 8 블록 할당)
__u8 s_prealloc_dir_blocks; // 디렉터리에 대해 미리 할당할 블록 수
/*E0*/ __le32 s_journal_inum; // 저널의 inode 번호 (일반적으로 8번에 위치 -> 이 부분을 읽어서 저널을 찾아감)
__le32 s_last_orphan; // 삭제 예정이지만 아직 닫히지 않은 orphan inode 리스트 시작점
__le16 s_desc_size; // 그룹 디스크립터 단위
__le32 s_first_meta_bg; // Meta_bg 기능 활성화 경우에 메타 블록 그룹 시작 번호 (그룹 디스크립터 등이 포함된 특수 블록 그룹)
/*150*/
__le32 s_lpf_ino; // lost+found 디렉터리의 inode 번호
__le32 s_orphan_file_inum; // orphan inode 관리를 위한 orphan file의 inode number
};
✨ orphan file
dentry에는 연결되어있지 않지만 아직 살아있는 inode
: 삭제된 파일이지만 파일 시스템에는 여전히 파일 메타데이터가 남아있고, 루트 디렉터리에서 접근할 수 없는 파일
🌙 발생 이유
- open() 시스템 콜 호출
- unlink() 시스템 콜 호출
- 디렉터리 엔트리 삭제
- close() 시스템 콜 호출 X?
그러나 close() 시스템 콜(파일 디스크립터 정리)을 호출하지 않았기 때문에 데이터는 지워지지 않고 디스크 상에 남아 있다.
🌙 접근 방법
- 슈퍼 블록의 s_last_orphan 필드는 linked list 형태로 연결되어 있는 orphan inode들의 시작점을 가리킨다.
- 즉, 이 필드가 0이 아니라면, orphan inode가 존재한다는 뜻이고, 그 inode 안의 i_next_orphan을 따라가면서 다음 orphan inode들을 찾는 방식이다.
=> inode와 관련된 설명은 여기에서..
🌙 파일 복구
만일 다음 조건들이 충족된다면 orphan inode를 통해 파일 복구가 가능할 것이다.
- 해당 inode가 삭제되지 않은 상태
- 파일 삭제 직후 시스템의 이유로 아직 완전히 정리되지 않은 상태
(sync X, mount X)
=> 파일 시스템의 일관성 보장을 위해, mount 시 s_last_orphan이 가리키는 inode들을 순회하며 truncate 실행 후 inode 삭제
✨ s_last_orphan vs s_orphan_file_inum
두 가지 방식 모두 orphan file을 처리하는 방식이지만, 저마다 차이점이 조금씩 존재한다.
🌙 s_last_orphan
- 전통적인 복구 방식을 위한 필드
- linked list의 마지막 inode 번호를 저장
- linked list 형태로 inode를 추적하는 방식
- 각 orphan_inode 구조체에 i_next_orphan 필드를 통해 다음 inode 번호를 찾아감으로써 파일 복구가 가능
🌙 s_orphan_file_inum
- ext4에 새로 도입된 디렉터리 기반 방식을 위한 필드
- orphan file을 모아두는 디렉터리의 inode 번호 (ext4에서는 디렉터리도 파일로 취급)
- dentry는 사라졌지만 inode와 블록은 여전히 존재하기 때문에, 커널이 자동으로 할당한 dentry 이름과 inode 번호를 연결하여 새로운 dentry를 만들어 저장
- orphan 전용 디렉터리를 탐색하며 복구 파일을 찾아냄
✨ magic number

슈퍼 블록의 크기는 1024 Bytes이며, 파일 시스템의 전반적인 정보를 저장한다.

특히, 시작 지점에서 0x38만큼 앞으로 가면 슈퍼 블록의 매직 넘버를 확인할 수 있다. (0xEF53)
파일의 매직 넘버는 일종의 파일 시그니처로, 이 값으로 파일 시스템을 파악하거나 어떤 포맷인지 식별이 가능하다.
특히, 사진에서 본 것과 같이 슈퍼 블록에서의 매직 넘버 (0xEF53)은 ext 계열 파일 시스템 매직 넘버로, 이를 통해 해당 파일 시스템이 ext 시리즈인 것을 인식할 수 있다.
✨ meta block group
일반적인 경우 Group Descriptor Table?은 보통 Block Group 0에 포함되어 있지만, meta_bg 포맷 사용 시 Group Descriptor Table이 각 블록 그룹의 메타 블록 그룹 내 분산 배치된다.
이 경우 몇 번째 블록 그룹부터가 메타 블록 그룹인지 알아야 하는데, 이때 메타 블록 그룹 시작 번호를 포함하는 s_first_meta_bg 이 쓰이게 된다.
🫧 주의 깊게 보아야 할 점
- 저널도 파일로써 취급되며, 대개 inode 8번에 위치한다.
s_journal_inum을 읽어 저널을 찾아간다. 만일 이 숫자가 손상된다면 시스템에서는 저널에 접근할 수 없다.- 스냅샷도 inode처럼 관리된다.