서울대학교 컴퓨터공학과 김진수 교수님의 "고급 운영체제" 강의를 필기한 내용입니다.
다소 잘못된 내용과 구어적 표현 이 포함되어 있을 수 있습니다.
Ext4
- Minix FS 에서 진화한 Ext FS 가 계속 발전해 지금의 Ext4 까지 왔다.
- FS 전체 용량은 최대 1EB 까지 늘릴 수 있고
- 파일 하나당의 크기는 16TB 까지 늘릴 수 있다고 한다.
Direct, indirect blocks (~Ext3)
- 뭐 기본적으로 생긴 것은 똑같다.
- Inode 하나는 256byte 크기이고,
- Direct 에는 data block 이 연결되고 Single-indirect/Double-indirect 에는 indirect block 이 연결되는
- Ext4 이전 상황은 아래와 같다고 하더라
- 4Ki 사이즈 block 를 기준으로 했을 때, Inode 하나에는
- Direct block: 파일 사이즈 까지 감당 가능
- Single indirect block: 1 개의 블럭이 indirect block 으로 사용됨
- Indirect block (4Ki) 하나에는 (32bit address 기준) 1024 개의 entry 를 저장할 수 있음
- 따라서 single indirect 에는 파일 사이즈 까지 감당 가능
- Double indirect block: indirect block 계층이 하나 더 추가되므로, 파일 사이즈 까지 감당 가능
- 보다시피 파일 최대 크기가 4Gi 좀 넘기 때문에 아주 작다
- 그리고, 1GB 파일을 4Ki block 들에 저장하려면 2^20 / 4 = 262,144 개의 block 을 연결해야 했기에 아주 번거롭다.
- 4Ki 사이즈 block 를 기준으로 했을 때, Inode 하나에는
- 이 문제를 지금은 뒤에 나올 Extent 로 해결한다.
Block Group
- Block Group 은 FFS 에서의 cylinder group 과 유사하다.
- 128MB 고정크기를 가진다고 한다.
- Superblock 은 FS 전체에 대한 메타데이터, Group Descriptor 는 block group 에 대한 메타데이터인 것 같음
- 얘네들은 모든 block group 에 동일하게 복제된다? FS init 시에만 그렇다는건지 아니면 항상 sync 되어 있다는 것인지는 모르겠음
- 각 Block group 이 하나의 disk 인 양 여기에 superblock, IB, DB 등이 들어가 있음
- DB 와 IB 를 1 block 으로 한정
Ext4 extent
- 기존에는 inode 에 각 block 마다 mapping 이 되어 있었지만, Ext4 로 오면서 연속된 공간은 하나의 mapping 으로 처리하는 Extent 개념이 도입된다.
- Extent 는 연속된 LBA 주소공간이 PBA 주소공간에도 동일하게 저장되어 있을 때 이 연속된 공간을 대표하는 하나의 descriptor 이다.
- Extent 자료구조는
offset
,length
,physical_length
세 필드를 가진다.offset
: LBA 시작점length
: 연속된 갯수physical_length
: 는 뭔지 잘 모르겠음
- 이제 이 Extent 를 사용했을 때에 최대 사이즈에 대해 계산해보자.
length
는 15bit 이다: 따라서 개의 연속된 block 을 나타낼 수 있다.- 결과적으로 하나의 extent 는 최대 의 공간을 대표할 수 있다.
- #draft 저 16TB file, 1EB filesystem 을 이걸로 어떻게 계산할 수 있을 것 같은데 일단 패스
- 이렇게 하면 당연히 차지하는 공간이 작기 때문에 좋지만, random access 를 위해서는 각각의 extent 를 다 꺼내 계산을 해야 하기 때문에 시간이 오래 걸리게 되는 문제점이 생긴다.
- 따라서 이러한 선형 연산을 하지 않기 위해 extent 가 4개 이상으로 많아지면 tree 형태로 관리된다고 한다.
- Multi-block allocator: Block 을 할당할 때도 이 Extent 단위로 한다.
- Ext3 까지는 블럭을 한번에 하나씩만 allocate 했다면
- Ext4 부터는 이 Extent 단위로 연속된 block 들을 한번에 쭉 할당한다.
- 이렇게 하면 fragmentation 도 줄어들고 allocate call 도 적게 하게 되므로 CPU utilization 을 줄일 수 있다더라.
Flex Block Group
- 기존의 block group 이 128Mb 인데 여기 앞에는 전부 metadata 가 들어가서
- large sequential write 을 하려고 할 때 자꾸 이 metadata 때문에 중간중간 건너뛰어야 한다.
- 따라서 위처럼 block group 의 각 부분을 모아서 저장하는 방법을 Flex Block Group 이라고 한댄다.
#draft Record:
1h 11m
Delayed Allocation
Record:
1h 15m
- Block allocation 을 매
write()
syscall 마다 하는 것이 아닌 메모리에 일단 모아놨다가 나중에flush()
할 때 수행하는 것.- 단점은 flush 를 하기 위해서는 os 의 허락을 받아야 하는데 이게 쉽지 않다?
여기부터는
2024-04-04
강의
- 이짓을 왜하느냐,,
- Filesystem fragmentation: 오랜 기간 동안 파일들이 썻다 지웠다 하다 보니 파일의 각 block 이 여기저기 흩어지게 되는 문제가 있었음
- 예를 들면 프로세스 세개가 각각 A, B, C 세 파일을 4KB 씩 계속 쓰면 ABCABC 이런식으로 할당되고 C 가 지워지면 AB-AB- 이렇게 돼서 external fragmentation 이 발생하게 되는 것
- 이것을 Ext4 에서는 write 시에 allocation 을 하지 않고 flush 시에 수행해서 방지한다.
Directory indexing: H-tree (Hash Tree)
#draft Record
15m
- Ext4 에서는 H-tree 를 사용하여 directory 내의 filename 을 찾는다고 한다.
- “찾기 (indexing)” 에 사용되는 data structure 는 거의 무조건 tree 아니면 hash 이다.
- Hash 는 빠르지만 worst case 가 존재하고
- 아마 worst case 가 collision 을 의미하는 것 같다: collision 이 없게 하자니 메모리 사용량이 너무 많아지고, collision 을 어느정도 허용하자니 linear search 를 해야되고
- Tree 는 비교적 느리지만 안정적
- Hash 는 빠르지만 worst case 가 존재하고
- H-tree 는 이 둘을 섞은 것이다.
- 우선 file name 을 hash 한다 - digest 비교는 integer 비교이기 때문에 string 보다 훨씬 빠름
- 그리고 hash collision 에 대해서는 digest 당 tree 를 구성한다.
- Collision string 비교를 선형적으로 하는 것보다 트리를 사용하는 것이 훨씬 빠르기 때문
- 즉, file name 이 주어지면 일단 hash 해서 digest 를 구하고 해당 digest 에 해당하는 tree 로 가서 file name 을 찾는 것.
Journaling
- ext2 까지는
fsck
로 부팅시에 디스크를 full scan 해 망가진 데이터를 복구 - ext3 부터 journaling 이 도입
- 다음의 세 mode 로 작동한다:
- Data mode 는 다음처럼 수행
- journal 영역에 inode 와 data 를 적고
sync()
해서 버퍼공간이 아닌 media 에 journal 이 반영되게 하고, 완료되면 commit 표시- 이후 실제 data flush 는 천천히
- Writeback mode 는 data mode 와 다르게 metadata 에 대한 journaling 과정을 따로 하는 것이다.
- Metadata sync 가 안맞으면 다음과 같은 상황이 발생할 수 있다:
- Block bitmap 에서는 없다고 하는데 inode direct/indirect 에는 pointer 가 있는 경우
- Inode bitmap 에서는 있다고 하는데 연결된 directory entry 는 없는 경우
- 이때에는 inode 의 reference counter 와 이놈을 참조하고 있는 directory entry 의 갯수를 추적해서 비교하고, directory entry 가 없으면 inode 를 삭제한다.
- 따라서 Metadata (Bitmap-Directory-Inode) 셋 간의 sync 를 맞추는게 중허다.
- 이를 위해 metadata write 전에 metadata journaling 먼저 하고, data block write 는 아무때나 수행하는 방법을 Writeback mode 라고 한다.
- 하지만 이 모드는 단점이 있다.
- Block 이 할당되었음을 block bitmap 이랑 inode 에 모두 명시해줘서 metadata sync 는 맞췄는데
- 이 상황에서 data 가 commit 되기 전에 crash 가 나면
- 이후에 해당 파일에 이 block 에 대한 이전의 data 가 보임
- 근데 이전 data 가 내가 쓴 것이 아닐 수 있기 때문에 privacy 문제가 있다.
- Metadata sync 가 안맞으면 다음과 같은 상황이 발생할 수 있다:
- 그래서 나온 것이 Ordering mode 이다. (기본)
- 여기서는 data commit 를 먼저 한 이후에 metadata journaling + commit 를 수행한다.