요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
The Contents of inode.i_block
------------------------------
Depending on the type of file an inode describes, the 60 bytes of
storage in ``inode.i_block`` can be used in different ways. In general,
regular files and directories will use it for file block indexing
information, and special files will use it for special purposes.
Symbolic Links
~~~~~~~~~~~~~~
The target of a symbolic link will be stored in this field if the target
string is less than 60 bytes long. Otherwise, either extents or block
maps will be used to allocate data blocks to store the link target.
Direct/Indirect Block Addressing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In ext2/3, file block numbers were mapped to logical block numbers by
means of an (up to) three level 1-1 block map. To find the logical block
that stores a particular file block, the code would navigate through
this increasingly complicated structure. Notice that there is neither a
magic number nor a checksum to provide any level of confidence that the
block isn't full of garbage.
.. ifconfig:: builder != 'latex'
.. include:: blockmap.rst
.. ifconfig:: builder == 'latex'
[Table omitted because LaTeX doesn't support nested tables.]
Note that with this block mapping scheme, it is necessary to fill out a
lot of mapping data even for a large contiguous file! This inefficiency
led to the creation of the extent mapping scheme, discussed below.
Notice also that a file using this mapping scheme cannot be placed
higher than 2^32 blocks.
Extent Tree
~~~~~~~~~~~
In ext4, the file to logical block map has been replaced with an extent
tree. Under the old scheme, allocating a contiguous run of 1,000 blocks
requires an indirect block to map all 1,000 entries; with extents, the
mapping is reduced to a single ``struct ext4_extent`` with
``ee_len = 1000``. If flex_bg is enabled, it is possible to allocate
very large files with a single extent, at a considerable reduction in
metadata block use, and some improvement in disk efficiency. The inode
must have the extents flag (0x80000) flag set for this feature to be in
use.
Extents are arranged as a tree. Each node of the tree begins with a
``struct ext4_extent_header``. If the node is an interior node
(``eh.eh_depth`` > 0), the header is followed by ``eh.eh_entries``
instances of ``struct ext4_extent_idx``; each of these index entries
points to a block containing more nodes in the extent tree. If the node
is a leaf node (``eh.eh_depth == 0``), then the header is followed by
``eh.eh_entries`` instances of ``struct ext4_extent``; these instances
point to the file's data blocks. The root node of the extent tree is
stored in ``inode.i_block``, which allows for the first four extents to
be recorded without the use of extra metadata blocks.
The extent tree header is recorded in ``struct ext4_extent_header``,
which is 12 bytes long:
.. list-table::
:widths: 8 8 24 40
:header-rows: 1
* - Offset
- Size
- Name
- Description
* - 0x0
- __le16
- eh_magic
- Magic number, 0xF30A.
* - 0x2
- __le16
- eh_entries
- Number of valid entries following the header.
* - 0x4
- __le16
- eh_max
- Maximum number of entries that could follow the header.
* - 0x6
- __le16
- eh_depth
- Depth of this extent node in the extent tree. 0 = this extent node
points to data blocks; otherwise, this extent node points to other
extent nodes. The extent tree can be at most 5 levels deep: a logical
block number can be at most ``2^32``, and the smallest ``n`` that
satisfies ``4*(((blocksize - 12)/12)^n) >= 2^32`` is 5.
* - 0x8
- __le32
- eh_generation
- Generation of the tree. (Used by Lustre, but not standard ext4).
Internal nodes of the extent tree, also known as index nodes, are
recorded as ``struct ext4_extent_idx``, and are 12 bytes long:
.. list-table::
:widths: 8 8 24 40
:header-rows: 1
* - Offset
- Size
- Name
- Description
* - 0x0
- __le32
- ei_block
- This index node covers file blocks from 'block' onward.
* - 0x4
- __le32
- ei_leaf_lo
- Lower 32-bits of the block number of the extent node that is the next
level lower in the tree. The tree node pointed to can be either another
internal node or a leaf node, described below.
* - 0x8
- __le16
- ei_leaf_hi
- Upper 16-bits of the previous field.
* - 0xA
- __u16
- ei_unused
-
Leaf nodes of the extent tree are recorded as ``struct ext4_extent``,
and are also 12 bytes long:
.. list-table::
:widths: 8 8 24 40
:header-rows: 1
* - Offset
- Size
- Name
- Description
* - 0x0
- __le32
- ee_block
- First file block number that this extent covers.
* - 0x4
- __le16
- ee_len
- Number of blocks covered by extent. If the value of this field is <=
32768, the extent is initialized. If the value of the field is > 32768,
the extent is uninitialized and the actual extent length is ``ee_len`` -
32768. Therefore, the maximum length of a initialized extent is 32768
blocks, and the maximum length of an uninitialized extent is 32767.
* - 0x6
- __le16
- ee_start_hi
- Upper 16-bits of the block number to which this extent points.
* - 0x8
- __le32
- ee_start_lo
- Lower 32-bits of the block number to which this extent points.
Prior to the introduction of metadata checksums, the extent header +
extent entries always left at least 4 bytes of unallocated space at the
end of each extent tree data block (because (2^x % 12) >= 4). Therefore,
the 32-bit checksum is inserted into this space. The 4 extents in the
inode do not need checksumming, since the inode is already checksummed.
The checksum is calculated against the FS UUID, the inode number, the
inode generation, and the entire extent block leading up to (but not
including) the checksum itself.
``struct ext4_extent_tail`` is 4 bytes long:
.. list-table::
:widths: 8 8 24 40
:header-rows: 1
* - Offset
- Size
- Name
- Description
* - 0x0
- __le32
- eb_checksum
- Checksum of the extent block, crc32c(uuid+inum+igeneration+extentblock)
Inline Data
~~~~~~~~~~~
If the inline data feature is enabled for the filesystem and the flag is
set for the inode, it is possible that the first 60 bytes of the file
data are stored here.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
`inode.i_block`의 내용과 심볼릭 링크
1-16inode가 나타내는 파일 종류에 따라 `inode.i_block`의 60바이트 저장 공간은 서로 다른 방식으로 사용됩니다. 일반 파일과 디렉터리는 대체로 파일 블록 인덱싱 정보를 저장하고, 특수 파일은 종류별 특수 목적에 사용합니다.
심볼릭 링크 대상 문자열이 60바이트보다 짧으면 이 필드에 직접 저장합니다. 더 길면 extent 또는 block map으로 데이터 블록을 할당하여 링크 대상을 저장합니다.
파일 종류와 크기에 따라 같은 60바이트 영역의 의미가 달라집니다.
.. SPDX-License-Identifier: GPL-2.0
The Contents of inode.i_block
------------------------------
Depending on the type of file an inode describes, the 60 bytes of
storage in ``inode.i_block`` can be used in different ways. In general,
regular files and directories will use it for file block indexing
information, and special files will use it for special purposes.
Symbolic Links
~~~~~~~~~~~~~~
The target of a symbolic link will be stored in this field if the target
string is less than 60 bytes long. Otherwise, either extents or block
maps will be used to allocate data blocks to store the link target.
직접·간접 블록 주소 지정
17-42ext2/3에서는 최대 3단계의 1대1 block map으로 파일 블록 번호를 논리 블록 번호에 매핑했습니다. 특정 파일 블록을 저장하는 논리 블록을 찾으려면 단계가 깊어질수록 복잡해지는 구조를 따라가야 합니다.
이 block map에는 magic number도 checksum도 없으므로 읽은 블록이 손상된 쓰레기 데이터가 아니라는 확신을 제공하지 못합니다. 비 LaTeX 빌드에서는 `blockmap.rst`의 표를 포함하고, LaTeX 빌드에서는 중첩 표 미지원으로 해당 표를 생략합니다.
큰 파일이 연속된 블록을 사용해도 많은 매핑 엔트리를 채워야 하는 비효율 때문에 아래의 extent mapping scheme이 만들어졌습니다.
또한 이 매핑 방식을 쓰는 파일은 `2^32` 블록보다 높은 위치에 배치할 수 없습니다.
파일 블록에서 데이터 블록까지 직접·간접 포인터를 따라가는 개념적 경로입니다.
Direct/Indirect Block Addressing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In ext2/3, file block numbers were mapped to logical block numbers by
means of an (up to) three level 1-1 block map. To find the logical block
that stores a particular file block, the code would navigate through
this increasingly complicated structure. Notice that there is neither a
magic number nor a checksum to provide any level of confidence that the
block isn't full of garbage.
.. ifconfig:: builder != 'latex'
.. include:: blockmap.rst
.. ifconfig:: builder == 'latex'
[Table omitted because LaTeX doesn't support nested tables.]
Note that with this block mapping scheme, it is necessary to fill out a
lot of mapping data even for a large contiguous file! This inefficiency
led to the creation of the extent mapping scheme, discussed below.
Notice also that a file using this mapping scheme cannot be placed
higher than 2^32 blocks.
extent tree와 header
43-102ext4에서는 파일 블록에서 논리 블록으로 가는 매핑을 extent tree로 대체했습니다. 이전 방식은 연속된 1,000블록을 할당해도 1,000개 매핑 엔트리를 담은 indirect block이 필요했지만, extent에서는 `ee_len = 1000`인 `struct ext4_extent` 하나로 줄어듭니다.
`flex_bg`를 켜면 매우 큰 파일도 하나의 extent로 할당할 수 있어 메타데이터 블록 사용량을 크게 줄이고 디스크 효율도 개선할 수 있습니다. 이 기능을 사용하려면 inode의 extents flag `0x80000`이 설정되어 있어야 합니다.
extent는 tree로 배열됩니다. 각 node는 `struct ext4_extent_header`로 시작합니다. `eh.eh_depth > 0`인 interior node에는 header 다음에 `eh.eh_entries`개의 `struct ext4_extent_idx`가 오고, 각 index entry는 더 아래의 extent tree node가 든 블록을 가리킵니다.
`eh.eh_depth == 0`인 leaf node에는 header 다음에 `eh.eh_entries`개의 `struct ext4_extent`가 오며 파일의 data block을 가리킵니다. extent tree의 root node는 `inode.i_block`에 저장되므로 추가 메타데이터 블록 없이 처음 네 extent를 기록할 수 있습니다.
12바이트 `struct ext4_extent_header`는 magic, 현재 entry 수, 최대 entry 수, node depth, tree generation을 기록합니다. tree depth는 최대 5단계입니다. 논리 블록 번호의 최댓값이 `2^32`이고 `4*(((blocksize - 12)/12)^n) >= 2^32`를 만족하는 가장 작은 `n`이 5이기 때문입니다.
`inode.i_block`의 root에서 파일 데이터 extent까지 내려가는 경로입니다.
모든 extent tree node 앞에 놓이는 12바이트 header입니다.
Extent Tree
~~~~~~~~~~~
In ext4, the file to logical block map has been replaced with an extent
tree. Under the old scheme, allocating a contiguous run of 1,000 blocks
requires an indirect block to map all 1,000 entries; with extents, the
mapping is reduced to a single ``struct ext4_extent`` with
``ee_len = 1000``. If flex_bg is enabled, it is possible to allocate
very large files with a single extent, at a considerable reduction in
metadata block use, and some improvement in disk efficiency. The inode
must have the extents flag (0x80000) flag set for this feature to be in
use.
Extents are arranged as a tree. Each node of the tree begins with a
``struct ext4_extent_header``. If the node is an interior node
(``eh.eh_depth`` > 0), the header is followed by ``eh.eh_entries``
instances of ``struct ext4_extent_idx``; each of these index entries
points to a block containing more nodes in the extent tree. If the node
is a leaf node (``eh.eh_depth == 0``), then the header is followed by
``eh.eh_entries`` instances of ``struct ext4_extent``; these instances
point to the file's data blocks. The root node of the extent tree is
stored in ``inode.i_block``, which allows for the first four extents to
be recorded without the use of extra metadata blocks.
The extent tree header is recorded in ``struct ext4_extent_header``,
which is 12 bytes long:
.. list-table::
:widths: 8 8 24 40
:header-rows: 1
* - Offset
- Size
- Name
- Description
* - 0x0
- __le16
- eh_magic
- Magic number, 0xF30A.
* - 0x2
- __le16
- eh_entries
- Number of valid entries following the header.
* - 0x4
- __le16
- eh_max
- Maximum number of entries that could follow the header.
* - 0x6
- __le16
- eh_depth
- Depth of this extent node in the extent tree. 0 = this extent node
points to data blocks; otherwise, this extent node points to other
extent nodes. The extent tree can be at most 5 levels deep: a logical
block number can be at most ``2^32``, and the smallest ``n`` that
satisfies ``4*(((blocksize - 12)/12)^n) >= 2^32`` is 5.
* - 0x8
- __le32
- eh_generation
- Generation of the tree. (Used by Lustre, but not standard ext4).
extent tree 내부 index node
103-132extent tree의 내부 node, 즉 index node는 12바이트 `struct ext4_extent_idx`로 기록됩니다.
`ei_block`은 이 index node가 담당하기 시작하는 파일 블록을 나타냅니다. `ei_leaf_hi`와 `ei_leaf_lo`를 결합한 48비트 블록 번호는 tree의 다음 낮은 단계에 있는 node를 가리킵니다. 대상은 또 다른 내부 node일 수도 있고 leaf node일 수도 있습니다.
extent tree 내부 node의 12바이트 index entry입니다.
Internal nodes of the extent tree, also known as index nodes, are
recorded as ``struct ext4_extent_idx``, and are 12 bytes long:
.. list-table::
:widths: 8 8 24 40
:header-rows: 1
* - Offset
- Size
- Name
- Description
* - 0x0
- __le32
- ei_block
- This index node covers file blocks from 'block' onward.
* - 0x4
- __le32
- ei_leaf_lo
- Lower 32-bits of the block number of the extent node that is the next
level lower in the tree. The tree node pointed to can be either another
internal node or a leaf node, described below.
* - 0x8
- __le16
- ei_leaf_hi
- Upper 16-bits of the previous field.
* - 0xA
- __u16
- ei_unused
-
extent tree leaf entry
133-164extent tree의 leaf node는 역시 12바이트인 `struct ext4_extent`로 기록되며 파일의 연속된 data block 구간을 설명합니다.
`ee_block`은 extent가 담당하는 첫 파일 블록 번호입니다. `ee_start_hi`와 `ee_start_lo`는 extent가 가리키는 실제 블록 번호의 상·하위 비트입니다.
`ee_len <= 32768`이면 초기화된 extent이며 값 자체가 블록 수입니다. `ee_len > 32768`이면 초기화되지 않은 extent이고 실제 길이는 `ee_len - 32768`입니다. 따라서 초기화된 extent의 최대 길이는 32,768블록, 초기화되지 않은 extent는 32,767블록입니다.
leaf node에서 연속된 파일 데이터 구간을 설명하는 12바이트 entry입니다.
Leaf nodes of the extent tree are recorded as ``struct ext4_extent``,
and are also 12 bytes long:
.. list-table::
:widths: 8 8 24 40
:header-rows: 1
* - Offset
- Size
- Name
- Description
* - 0x0
- __le32
- ee_block
- First file block number that this extent covers.
* - 0x4
- __le16
- ee_len
- Number of blocks covered by extent. If the value of this field is <=
32768, the extent is initialized. If the value of the field is > 32768,
the extent is uninitialized and the actual extent length is ``ee_len`` -
32768. Therefore, the maximum length of a initialized extent is 32768
blocks, and the maximum length of an uninitialized extent is 32767.
* - 0x6
- __le16
- ee_start_hi
- Upper 16-bits of the block number to which this extent points.
* - 0x8
- __le32
- ee_start_lo
- Lower 32-bits of the block number to which this extent points.
extent block checksum tail
165-188metadata checksum이 도입되기 전부터 extent header와 entry를 배치하면 모든 extent tree data block 끝에 최소 4바이트의 빈 공간이 남았습니다. 이는 `(2^x % 12) >= 4`이기 때문이며, 이 공간에 32비트 checksum을 넣습니다.
inode 안에 직접 들어 있는 네 extent는 inode 자체의 checksum으로 보호되므로 별도 checksum이 필요하지 않습니다.
extent block checksum은 FS UUID, inode number, inode generation, checksum 필드 직전까지의 extent block 전체를 입력으로 계산합니다.
`struct ext4_extent_tail`은 4바이트이며 offset `0x0`의 `__le32 eb_checksum` 하나만 담습니다. 값은 `crc32c(uuid+inum+igeneration+extentblock)`입니다.
extent tree data block의 마지막 4바이트 checksum입니다.
Prior to the introduction of metadata checksums, the extent header +
extent entries always left at least 4 bytes of unallocated space at the
end of each extent tree data block (because (2^x % 12) >= 4). Therefore,
the 32-bit checksum is inserted into this space. The 4 extents in the
inode do not need checksumming, since the inode is already checksummed.
The checksum is calculated against the FS UUID, the inode number, the
inode generation, and the entire extent block leading up to (but not
including) the checksum itself.
``struct ext4_extent_tail`` is 4 bytes long:
.. list-table::
:widths: 8 8 24 40
:header-rows: 1
* - Offset
- Size
- Name
- Description
* - 0x0
- __le32
- eb_checksum
- Checksum of the extent block, crc32c(uuid+inum+igeneration+extentblock)
`i_block`의 inline data
189-194파일시스템에서 inline data 기능을 켜고 해당 inode에도 플래그가 설정되어 있으면 파일 데이터의 처음 60바이트를 `inode.i_block`에 직접 저장할 수 있습니다.
작은 파일의 첫 데이터를 inode 내부에 저장하는 조건입니다.
Inline Data
~~~~~~~~~~~
If the inline data feature is enabled for the filesystem and the flag is
set for the inode, it is possible that the first 60 bytes of the file
data are stored here.
요약·해설
ifork.rst:1-194`inode.i_block`의 60바이트는 파일 종류에 따라 짧은 링크, block map, extent tree root 또는 inline data가 됩니다.
ext4 extent tree는 연속 블록을 하나의 entry로 압축하고 외부 tree block은 CRC32C tail로 보호합니다.
문서의 주요 관계를 짧게 정리합니다.