ext4 filesystem

ext filesystem

ext는 기본적으로 Linux os 에서 많이 사용된다. Windows os에서는 NTFS, Mac OS에서는 APFS를 사용하는 것과 같은 개념으로 이해하면 된다.

안드로이드와 같은 새로운 OS의 경우, 리눅스 시스템을 기초로 하기 때문에 ext는 생각보다 널리 쓰이고 있으며, 다른 filesystem을 이해하기 위한 기초 개념이라고 볼 수 있다.

ext2, 3, 4로 조금씩 발전 했기 때문에 차례대로 이해하는 게 좋을 꺼 같다.

ext2

하나의 파일은 하나의 inode 값을 가지고 위와 같이 데이터가 있는 block과 매핑하는 Block Mapping을 사용하는 것이 ext2의 특징이다.
각 inode 내 Info 하나 당 하나의 block과 매핑 될 할 수 있지만, 그렇게 되면 너무 적은 block 매핑이 이루어져서 감당할 수 있는 용량에 제한에 걸리기 때문에 보다 많은 block과 매핑하기 위해서 간접(Indirect)적으로 매핑 할 수 있도록 만들어져 있다.

DISK 내에서는 아래와 같이 ext2 filesystem 이 구성되어 있다.

1. boot block

Disk의 첫 1024 bytes는 boot block으로 boot sector 파티션을 위해서 할당된 공간으로 ext2 filesystem에서는 사용하지 않는 공간이다.

2. Super Block

struct ext2_super_block {

__u32 s_inodes_count; /* Inodes count */ __u32 s_blocks_count; /* Blocks count */ ... __u32 s_free_blocks_count; /* Free blocks count */ __u32 s_free_inodes_count; /* Free inodes count */ __u32 s_first_data_block; /* First Data Block */ __u32 s_log_block_size; /* Block size */ ... __u32 s_blocks_per_group; /* # Blocks per group */ ... __u16 s_magic; /* Magic signature */

(여기서 __u32는 32-bit integer number 라는 의미이다.)

Super Block은 디스크의 총 블록 수, 블록 크기(일반적으로 1024바이트), 사용 가능한 블록 수 등의 정보가 포함됩니다.

3. Group Descriptors

struct ext2_group_desc
{
__u32 bg_block_bitmap; /* Blocks bitmap block */
__u32 bg_inode_bitmap; /* Inodes bitmap block */
__u32 bg_inode_table; /* Inodes table block */
__u16 bg_free_blocks_count; /* Free blocks count */
__u16 bg_free_inodes_count; /* Free inodes count */
__u16 bg_used_dirs_count; /* Directories count */
__u16 bg_pad;
__u32 bg_reserved[3];
};

Group Descriptor는 bg_block_bitmap, bg_inode_bitmap 및 bg_inode_table 필드를 통해 블록/inode 비트맵과 inode 테이블(나중에 설명)의 위치를 나타낸다. 이러한 값은 비트맵과 테이블이 있는 블록을 가리킨다. 

4. Blocks and inodes bitmaps


Bitmap은 bit의 sequence이다. 각 bit는 Block Group의 특정 Block(Block bitmap) 또는 inode(inode bitmap)를 나타낸다. bit 값 0은 block/inode가 비어 있음을 나타내고, 값 1은 블록/inode가 사용 중임을 나타낸다. bitmap은 항상 자신이 속한 Block Group을 참조하며, 크기는 한 블록 크기여야 한다.

5. inode table

inode table은 일련의 연속된 block으로 구성되어 있다. 각 연속된 block에는 미리 정의된 수의 inode가 들어 있다. inode table의 first block의 block 번호는 Group Descriptor의 bg_inode_table 필드에 저장된다. inode table이 차지하는 block 수를 파악하려면 그룹의 총 inode 수(super block의 s_inodes_per_group 필드에 저장됨)를 block당 inode 수로 나눈다.

/* number of inodes per block */
unsigned int inodes_per_block = block_size / sizeof(struct ext2_inode);

/* size in blocks of the inode table */
unsigned int itable_blocks = super.s_inodes_per_group / inodes_per_block;

6. Directory entries in the inode table


Directory entries 의 경우 i_block[]이 가리키는 데이터 블록에는 디렉토리에 있는 파일 목록과 해당 inode 번호가 포함되어 있다.

struct ext2_dir_entry_2 {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[EXT2_NAME_LEN]; /* File name */
};


각 항목은 파일 이름의 길이에 따라 가변적인 크기를 갖는다. 파일 이름의 최대 길이는 EXT2_NAME_LEN이며, 일반적으로 255입니다. name_len 필드는 파일 이름의 길이를 저장하는 반면 rec_len은 항목의 총 크기를 저장하며 목록에서 다음 항목을 찾는 데 사용된다.

7. Locating a file

파일에 속하는 inode를 찾으려면 먼저 루트 디렉토리에서 시작하여 파일의 부모 디렉토리에 도달할 때까지 경로를 따라 내려가야 한다. 이 지점에서 hello.txt에 해당하는 ext2_dir_entry_2 엔트리와 그 inode 번호를 찾을 수 있다.

ext3

ext2에서 journaling 기능을 제공한다. 여기서 journaling 이란 데이터의 일부를 임시 저장함으로써 갑작스런 장애에서 파일이 손상되는 일을 최소화 하는 기능이다.
CentOS 6.x 버전에서 사용되었었다.

journaling

저널링은 write-ahead 로깅이라고도 하며 데이터베이스에서 유래한다. 저널링을 사용하면 변경 사항에 대한 트랜잭션 중심 저널을 보관합니다. 트랜잭션 시작, 해당 트랜잭션에 관련된 작업(작업과 함께 제공되는 데이터와 함께), 트랜잭션 종료를 기록하고 모든 것을 디스크에 커밋한다. 
예를 들어:
  • Transaction-begin
  • New inode 779 [inode contents]
  • New block bitmap, group 4 [bitmap block contents ]
  • New data block 24120 [data block contents ]
  • Transaction-end
이 저널이 디스크에 기록되면 동일한 작업을 실제 파일 시스템으로 다시 보낸다. 모든 것이 잘 진행되고 시스템이 비정상적으로 종료되지 않으면 이 트랜잭션 항목이 더 이상 필요하지 않다. 그러나 로그가 저널에 커밋된 후 언제든지 충돌(또는 파일 시스템의 자발적인 제거)이 발생하면 충돌 복구 프로세스는 파일 시스템을 마운트하기 전에 로그를 재생한다. 이를 redo-logging이라고 한다. 로그에는 필요한 모든 데이터가 포함되어 있으므로 정보 손실이 없고 데이터를 재구성할 수 있다. 

또한 로그는 영향을 받았을 수 있는 디스크 블록(수정되었는지 여부)을 알려주므로 불일치를 찾기 위해 전체 파일 시스템을 검색할 필요가 없다. 저널 트랜잭션이 기록되기 전에 시스템이 중단된 경우 복구 프로세스는 로그에 기록된 "트랜잭션 종료" 마커가 없음을 확인하고 부분 트랜잭션을 무시한다. 트랜잭션이 완전히 로깅되지 않았으므로 아직 파일 시스템에 수정이 발생하지 않았으므로 파일 시스템은 여전히 ​​일관된 상태다.

ext4

ext3에서 성능이 향상되었고 보다 큰 용량을 지원한다. 또한 삭제 파일을 복구하는 기능과 파일 점검 속도가 크게 향상 되었다.

Large file system support.

파일 시스템은 이제 최대 1엑사바이트(1018바이트)의 디스크를 지원할 수 있으며, 파일 크기는 최대 16TB이다. 반면 ext3는 최대 32TB의 파일 시스템과 최대 2TB의 파일을 지원한다.

Extents

block map 대신 extent가 사용된다. inode의 block 번호 대신 ext4는 extent를 사용한다. 
extent는 연속된 block의 수와 함께 시작 block 번호이다. extent의 큰 장점은 많은 block이 연속적으로 할당되고(특히 새 디스크나 가득 차지 않은 디스크에서) block 번호보다 적은 양의 extent로 표현할 수 있다는 것이다. 
물론 block 번호는 할당된 block당 block 번호 항목이 필요하다. 하나의 extent는 4KB block 크기를 사용하여 최대 12MB의 공간을 매핑할 수 있다. inode는 inode당 4개의 extent를 포함한다. 간접 및 이중 indirect block 대신 추가 extent는 Htree(B-트리와 유사한 상수 깊이 트리)에 저장된다. inode에서 block(클러스터) 번호로 선형 목록 대신 Htree를 사용하는 이유는 파일을 무작위로 검색할 때 block 번호를 빠르게 검색할 수 있도록 하기 위해서 이다. block 번호는 고정된 양의 파일 공간을 나타내므로 바이트 n에 대한 바이트 offset을 찾는 것은 [n/(cluster_size)]번째 block 번호를 찾는 것을 의미하는 반면 각 extent는 다양한 수의 block을 나타낸다.

Reference

https://www.science.smith.edu/~nhowe/262/oldlabs/ext2.html
https://people.cs.rutgers.edu/~pxk/416/notes/13-fs-studies.html

댓글

가장 많이 본 글