← Documents Documentation/filesystems/qnx6.rst GitHub 원문 ↗

Linux 6.18.37 · Filesystems

The QNX6 Filesystem

QNX6의 듀얼 슈퍼블록 스냅샷, inode·긴 이름·bitmap 트리를 설명하는 전문 번역입니다.

Source pathDocumentation/filesystems/qnx6.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

qnx6.rst:1-196

QNX6는 임베디드 QNX 시스템에서 사용하는 양방향 endian 파일시스템이다. 두 슈퍼블록과 두 시스템 영역 절반을 번갈아 사용해 수정 블록으로 새 트리를 만든 뒤 64비트 일련번호를 원자적으로 갱신하는 스냅샷 구조가 핵심이다.

Linux 드라이버나 복구 도구를 작성할 때는 슈퍼블록 위치, `~0` 미사용 포인터, level별 간접 주소 계산, inode 번호 시작값, `0xff` 긴 이름 레코드, bitmap의 block 0 기준을 함께 지켜야 한다.

QNX6 온디스크 탐색
두 슈퍼블록의 64비트 일련번호 비교active 슈퍼블록 선택inode·bitmap·long filename 루트 선택level과 직접·간접 포인터 해석최하위 leaf에서 실제 데이터 읽기

active 슈퍼블록에서 각 전용 트리와 데이터 leaf로 내려간다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ===================
4 The QNX6 Filesystem
5 ===================
6
7 The qnx6fs is used by newer QNX operating system versions. (e.g. Neutrino)
8 It got introduced in QNX 6.4.0 and is used default since 6.4.1.
9
10 Option
11 ======
12
13 mmi_fs Mount filesystem as used for example by Audi MMI 3G system
14
15 Specification
16 =============
17
18 qnx6fs shares many properties with traditional Unix filesystems. It has the
19 concepts of blocks, inodes and directories.
20
21 On QNX it is possible to create little endian and big endian qnx6 filesystems.
22 This feature makes it possible to create and use a different endianness fs
23 for the target (QNX is used on quite a range of embedded systems) platform
24 running on a different endianness.
25
26 The Linux driver handles endianness transparently. (LE and BE)
27
28 Blocks
29 ------
30
31 The space in the device or file is split up into blocks. These are a fixed
32 size of 512, 1024, 2048 or 4096, which is decided when the filesystem is
33 created.
34
35 Blockpointers are 32bit, so the maximum space that can be addressed is
36 2^32 * 4096 bytes or 16TB
37
38 The superblocks
39 ---------------
40
41 The superblock contains all global information about the filesystem.
42 Each qnx6fs got two superblocks, each one having a 64bit serial number.
43 That serial number is used to identify the "active" superblock.
44 In write mode with reach new snapshot (after each synchronous write), the
45 serial of the new master superblock is increased (old superblock serial + 1)
46
47 So basically the snapshot functionality is realized by an atomic final
48 update of the serial number. Before updating that serial, all modifications
49 are done by copying all modified blocks during that specific write request
50 (or period) and building up a new (stable) filesystem structure under the
51 inactive superblock.
52
53 Each superblock holds a set of root inodes for the different filesystem
54 parts. (Inode, Bitmap and Longfilenames)
55 Each of these root nodes holds information like total size of the stored
56 data and the addressing levels in that specific tree.
57 If the level value is 0, up to 16 direct blocks can be addressed by each
58 node.
59
60 Level 1 adds an additional indirect addressing level where each indirect
61 addressing block holds up to blocksize / 4 bytes pointers to data blocks.
62 Level 2 adds an additional indirect addressing block level (so, already up
63 to 16 * 256 * 256 = 1048576 blocks that can be addressed by such a tree).
64
65 Unused block pointers are always set to ~0 - regardless of root node,
66 indirect addressing blocks or inodes.
67
68 Data leaves are always on the lowest level. So no data is stored on upper
69 tree levels.
70
71 The first Superblock is located at 0x2000. (0x2000 is the bootblock size)
72 The Audi MMI 3G first superblock directly starts at byte 0.
73
74 Second superblock position can either be calculated from the superblock
75 information (total number of filesystem blocks) or by taking the highest
76 device address, zeroing the last 3 bytes and then subtracting 0x1000 from
77 that address.
78
79 0x1000 is the size reserved for each superblock - regardless of the
80 blocksize of the filesystem.
81
82 Inodes
83 ------
84
85 Each object in the filesystem is represented by an inode. (index node)
86 The inode structure contains pointers to the filesystem blocks which contain
87 the data held in the object and all of the metadata about an object except
88 its longname. (filenames longer than 27 characters)
89 The metadata about an object includes the permissions, owner, group, flags,
90 size, number of blocks used, access time, change time and modification time.
91
92 Object mode field is POSIX format. (which makes things easier)
93
94 There are also pointers to the first 16 blocks, if the object data can be
95 addressed with 16 direct blocks.
96
97 For more than 16 blocks an indirect addressing in form of another tree is
98 used. (scheme is the same as the one used for the superblock root nodes)
99
100 The filesize is stored 64bit. Inode counting starts with 1. (while long
101 filename inodes start with 0)
102
103 Directories
104 -----------
105
106 A directory is a filesystem object and has an inode just like a file.
107 It is a specially formatted file containing records which associate each
108 name with an inode number.
109
110 '.' inode number points to the directory inode
111
112 '..' inode number points to the parent directory inode
113
114 Eeach filename record additionally got a filename length field.
115
116 One special case are long filenames or subdirectory names.
117
118 These got set a filename length field of 0xff in the corresponding directory
119 record plus the longfile inode number also stored in that record.
120
121 With that longfilename inode number, the longfilename tree can be walked
122 starting with the superblock longfilename root node pointers.
123
124 Special files
125 -------------
126
127 Symbolic links are also filesystem objects with inodes. They got a specific
128 bit in the inode mode field identifying them as symbolic link.
129
130 The directory entry file inode pointer points to the target file inode.
131
132 Hard links got an inode, a directory entry, but a specific mode bit set,
133 no block pointers and the directory file record pointing to the target file
134 inode.
135
136 Character and block special devices do not exist in QNX as those files
137 are handled by the QNX kernel/drivers and created in /dev independent of the
138 underlying filesystem.
139
140 Long filenames
141 --------------
142
143 Long filenames are stored in a separate addressing tree. The staring point
144 is the longfilename root node in the active superblock.
145
146 Each data block (tree leaves) holds one long filename. That filename is
147 limited to 510 bytes. The first two starting bytes are used as length field
148 for the actual filename.
149
150 If that structure shall fit for all allowed blocksizes, it is clear why there
151 is a limit of 510 bytes for the actual filename stored.
152
153 Bitmap
154 ------
155
156 The qnx6fs filesystem allocation bitmap is stored in a tree under bitmap
157 root node in the superblock and each bit in the bitmap represents one
158 filesystem block.
159
160 The first block is block 0, which starts 0x1000 after superblock start.
161 So for a normal qnx6fs 0x3000 (bootblock + superblock) is the physical
162 address at which block 0 is located.
163
164 Bits at the end of the last bitmap block are set to 1, if the device is
165 smaller than addressing space in the bitmap.
166
167 Bitmap system area
168 ------------------
169
170 The bitmap itself is divided into three parts.
171
172 First the system area, that is split into two halves.
173
174 Then userspace.
175
176 The requirement for a static, fixed preallocated system area comes from how
177 qnx6fs deals with writes.
178
179 Each superblock got its own half of the system area. So superblock #1
180 always uses blocks from the lower half while superblock #2 just writes to
181 blocks represented by the upper half bitmap system area bits.
182
183 Bitmap blocks, Inode blocks and indirect addressing blocks for those two
184 tree structures are treated as system blocks.
185
186 The rational behind that is that a write request can work on a new snapshot
187 (system area of the inactive - resp. lower serial numbered superblock) while
188 at the same time there is still a complete stable filesystem structure in the
189 other half of the system area.
190
191 When finished with writing (a sync write is completed, the maximum sync leap
192 time or a filesystem sync is requested), serial of the previously inactive
193 superblock atomically is increased and the fs switches over to that - then
194 stable declared - superblock.
195
196 For all data outside the system area, blocks are just copied while writing.
197

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

QNX6 파일시스템 개요와 블록

1-27

`qnx6fs`는 Neutrino 같은 비교적 최신 QNX 운영체제에서 사용하는 파일시스템이다. QNX 6.4.0에서 도입됐고 6.4.1부터 기본 파일시스템으로 사용됐다.

마운트 옵션 `mmi_fs`는 Audi MMI 3G 시스템과 같은 변형 레이아웃으로 파일시스템을 마운트한다.

QNX6는 블록·inode·디렉터리라는 전통적인 Unix 파일시스템 개념을 공유한다. QNX에서는 little-endian과 big-endian QNX6 파일시스템을 모두 만들 수 있으므로, 다양한 임베디드 대상의 바이트 순서와 다른 파일시스템도 생성하고 사용할 수 있다. Linux 드라이버는 LE와 BE를 투명하게 처리한다.

장치나 파일의 공간은 생성 시 결정되는 512, 1024, 2048, 4096바이트 고정 크기 블록으로 나뉜다. 블록 포인터는 32비트이므로 최대 주소 공간은 `2^32 * 4096`바이트, 즉 16TB다.

QNX6 기본 형식
항목
도입QNX 6.4.0, 6.4.1부터 기본
변형 옵션`mmi_fs`
바이트 순서little-endian과 big-endian, Linux에서 자동 처리
블록 크기512 / 1024 / 2048 / 4096바이트
블록 포인터32비트
최대 주소 공간`2^32 * 4096` = 16TB

마운트 변형, 바이트 순서, 주소 크기의 핵심 제약이다.

.. SPDX-License-Identifier: GPL-2.0

===================
The QNX6 Filesystem
===================

The qnx6fs is used by newer QNX operating system versions. (e.g. Neutrino)
It got introduced in QNX 6.4.0 and is used default since 6.4.1.

Option
======

mmi_fs                Mount filesystem as used for example by Audi MMI 3G system

Specification
=============

qnx6fs shares many properties with traditional Unix filesystems. It has the
concepts of blocks, inodes and directories.

On QNX it is possible to create little endian and big endian qnx6 filesystems.
This feature makes it possible to create and use a different endianness fs
for the target (QNX is used on quite a range of embedded systems) platform
running on a different endianness.

The Linux driver handles endianness transparently. (LE and BE)

듀얼 슈퍼블록과 스냅샷 트리

28-81

슈퍼블록은 파일시스템의 전역 정보를 담는다. 각 QNX6 파일시스템에는 64비트 일련번호를 가진 슈퍼블록이 두 개 있으며, 이 번호로 active 슈퍼블록을 식별한다. 쓰기 모드에서 동기 쓰기로 새 스냅샷에 도달할 때 새 master 슈퍼블록의 일련번호는 이전 값보다 1 증가한다.

스냅샷은 마지막 일련번호 갱신을 원자적으로 수행하는 방식으로 완성된다. 일련번호를 바꾸기 전에는 해당 쓰기 요청 또는 기간에 수정된 블록을 모두 복사하고, inactive 슈퍼블록 아래에 새롭고 안정적인 파일시스템 구조를 구축한다.

각 슈퍼블록에는 inode, bitmap, long filename 영역을 위한 루트 inode 집합이 있다. 각 루트 노드는 저장 데이터의 전체 크기와 트리의 주소 지정 level을 기록한다. level 0에서는 노드마다 직접 블록을 최대 16개 가리킨다.

level 1은 간접 주소 블록 하나를 추가하며 각 간접 블록은 `blocksize / 4`개의 데이터 블록 포인터를 담는다. level 2는 간접 단계 하나를 더 추가하므로, 1024바이트 블록을 예로 들면 `16 * 256 * 256 = 1048576`개 블록을 가리킬 수 있다. 데이터 leaf는 항상 최하위 level에 있고 상위 트리 level에는 데이터를 저장하지 않는다.

사용하지 않는 블록 포인터는 루트 노드·간접 주소 블록·inode를 가리지 않고 항상 `~0`으로 설정한다.

QNX6 스냅샷 전환
현재 active 슈퍼블록과 안정된 트리 유지inactive 슈퍼블록 쪽에 수정 블록 복사inode·bitmap·long filename 새 트리 완성동기화 시 inactive 슈퍼블록 일련번호를 원자적으로 증가더 큰 일련번호의 슈퍼블록이 새 active master

inactive 절반에 완전한 새 구조를 만든 뒤 일련번호 하나로 active 상태를 바꾼다.

슈퍼블록 위치
항목위치 또는 계산
첫 슈퍼블록`0x2000` (bootblock 크기 뒤)
Audi MMI 3G 첫 슈퍼블록byte 0
둘째 슈퍼블록전체 파일시스템 블록 수로 계산
대체 계산최고 장치 주소의 마지막 3바이트를 0으로 만든 뒤 `0x1000` 차감
슈퍼블록 예약 크기파일시스템 블록 크기와 무관하게 각각 `0x1000`

일반 QNX6와 Audi MMI 변형의 시작 위치 및 두 번째 슈퍼블록 계산법이다.

Blocks
------

The space in the device or file is split up into blocks. These are a fixed
size of 512, 1024, 2048 or 4096, which is decided when the filesystem is
created.

Blockpointers are 32bit, so the maximum space that can be addressed is
2^32 * 4096 bytes or 16TB

The superblocks
---------------

The superblock contains all global information about the filesystem.
Each qnx6fs got two superblocks, each one having a 64bit serial number.
That serial number is used to identify the "active" superblock.
In write mode with reach new snapshot (after each synchronous write), the
serial of the new master superblock is increased (old superblock serial + 1)

So basically the snapshot functionality is realized by an atomic final
update of the serial number. Before updating that serial, all modifications
are done by copying all modified blocks during that specific write request
(or period) and building up a new (stable) filesystem structure under the
inactive superblock.

Each superblock holds a set of root inodes for the different filesystem
parts. (Inode, Bitmap and Longfilenames)
Each of these root nodes holds information like total size of the stored
data and the addressing levels in that specific tree.
If the level value is 0, up to 16 direct blocks can be addressed by each
node.

Level 1 adds an additional indirect addressing level where each indirect
addressing block holds up to blocksize / 4 bytes pointers to data blocks.
Level 2 adds an additional indirect addressing block level (so, already up
to 16 * 256 * 256 = 1048576 blocks that can be addressed by such a tree).

Unused block pointers are always set to ~0 - regardless of root node,
indirect addressing blocks or inodes.

Data leaves are always on the lowest level. So no data is stored on upper
tree levels.

The first Superblock is located at 0x2000. (0x2000 is the bootblock size)
The Audi MMI 3G first superblock directly starts at byte 0.

Second superblock position can either be calculated from the superblock
information (total number of filesystem blocks) or by taking the highest
device address, zeroing the last 3 bytes and then subtracting 0x1000 from
that address.

0x1000 is the size reserved for each superblock - regardless of the
blocksize of the filesystem.

Inode와 디렉터리 레코드

82-123

파일시스템의 각 객체는 inode(index node)로 표현한다. inode에는 객체 데이터가 있는 블록 포인터와 긴 이름을 제외한 메타데이터가 들어간다. 긴 이름은 27자를 넘는 파일명이다. 메타데이터에는 권한, 소유자, 그룹, 플래그, 크기, 사용 블록 수, 접근·변경·수정 시간이 포함된다.

객체 mode 필드는 POSIX 형식이다. 데이터가 직접 블록 16개로 표현되면 inode에 있는 첫 16개 포인터를 사용하고, 그보다 많으면 슈퍼블록 루트 노드와 같은 방식의 별도 간접 주소 트리를 사용한다. 파일 크기는 64비트로 저장한다. 일반 inode 번호는 1부터 세지만 long filename inode는 0부터 센다.

디렉터리도 파일과 같은 inode를 가진 파일시스템 객체다. 이름과 inode 번호를 연결하는 특별한 형식의 레코드 파일이다. `.`의 inode 번호는 디렉터리 자신을, `..`의 inode 번호는 부모 디렉터리를 가리키며 각 파일명 레코드에는 이름 길이 필드가 있다.

긴 파일명이나 긴 하위 디렉터리 이름은 예외다. 해당 디렉터리 레코드의 파일명 길이를 `0xff`로 설정하고 longfile inode 번호를 함께 저장한다. 이 번호로 active 슈퍼블록의 long filename 루트 노드 포인터에서 시작해 long filename 트리를 순회한다.

객체 주소 지정
대상주소 지정
객체 데이터 ≤ 16블록inode의 직접 포인터 16개
객체 데이터 > 16블록간접 주소 트리
일반 inode 번호1부터 시작
long filename inode 번호0부터 시작
긴 이름 디렉터리 레코드길이 `0xff` + longfile inode 번호

inode의 직접 포인터와 별도 트리로 일반 데이터와 긴 이름을 찾는다.

Inodes
------

Each object in the filesystem is represented by an inode. (index node)
The inode structure contains pointers to the filesystem blocks which contain
the data held in the object and all of the metadata about an object except
its longname. (filenames longer than 27 characters)
The metadata about an object includes the permissions, owner, group, flags,
size, number of blocks used, access time, change time and modification time.

Object mode field is POSIX format. (which makes things easier)

There are also pointers to the first 16 blocks, if the object data can be
addressed with 16 direct blocks.

For more than 16 blocks an indirect addressing in form of another tree is
used. (scheme is the same as the one used for the superblock root nodes)

The filesize is stored 64bit. Inode counting starts with 1. (while long
filename inodes start with 0)

Directories
-----------

A directory is a filesystem object and has an inode just like a file.
It is a specially formatted file containing records which associate each
name with an inode number.

'.' inode number points to the directory inode

'..' inode number points to the parent directory inode

Eeach filename record additionally got a filename length field.

One special case are long filenames or subdirectory names.

These got set a filename length field of 0xff in the corresponding directory
record plus the longfile inode number also stored in that record.

With that longfilename inode number, the longfilename tree can be walked
starting with the superblock longfilename root node pointers.

특수 파일과 긴 파일명 저장

124-152

심볼릭 링크도 inode를 가진 파일시스템 객체이며 inode mode 필드의 전용 비트로 식별한다. 디렉터리 엔트리의 file inode 포인터는 대상 파일 inode를 가리킨다.

하드 링크는 inode와 디렉터리 엔트리를 가지지만 전용 mode 비트가 설정되고 블록 포인터는 없으며, 디렉터리 파일 레코드가 대상 파일 inode를 가리킨다.

QNX의 문자·블록 특수 장치는 기반 파일시스템에 존재하지 않는다. QNX 커널과 드라이버가 처리하고 `/dev`에 독립적으로 생성하기 때문이다.

긴 파일명은 별도 주소 트리에 저장하며 시작점은 active 슈퍼블록의 long filename 루트 노드다. 각 데이터 블록인 트리 leaf는 긴 파일명 하나를 담는다. 이름의 실제 최대 길이는 510바이트이며 첫 2바이트는 길이 필드로 사용한다. 이 구조가 허용되는 모든 블록 크기에 맞아야 하므로 510바이트 제한이 생긴다.

긴 파일명 조회
디렉터리 레코드의 길이 필드가 `0xff`레코드에서 longfile inode 번호 읽기active 슈퍼블록의 long filename 루트에서 시작주소 트리를 leaf까지 순회첫 2바이트 길이 + 최대 510바이트 이름 해석

디렉터리 레코드에는 이름 대신 별도 트리의 참조를 둔다.

Special files
-------------

Symbolic links are also filesystem objects with inodes. They got a specific
bit in the inode mode field identifying them as symbolic link.

The directory entry file inode pointer points to the target file inode.

Hard links got an inode, a directory entry, but a specific mode bit set,
no block pointers and the directory file record pointing to the target file
inode.

Character and block special devices do not exist in QNX as those files
are handled by the QNX kernel/drivers and created in /dev independent of the
underlying filesystem.

Long filenames
--------------

Long filenames are stored in a separate addressing tree. The staring point
is the longfilename root node in the active superblock.

Each data block (tree leaves) holds one long filename. That filename is
limited to 510 bytes. The first two starting bytes are used as length field
for the actual filename.

If that structure shall fit for all allowed blocksizes, it is clear why there
is a limit of 510 bytes for the actual filename stored.

할당 bitmap과 이중 시스템 영역

153-196

QNX6 할당 bitmap은 슈퍼블록의 bitmap 루트 노드 아래 트리에 저장되며 각 bit가 파일시스템 블록 하나를 나타낸다. block 0은 슈퍼블록 시작에서 `0x1000` 뒤에 있다. 일반 QNX6에서는 bootblock과 슈퍼블록 뒤인 물리 주소 `0x3000`이 block 0이다.

장치가 bitmap의 주소 공간보다 작으면 마지막 bitmap 블록 끝의 초과 bit를 1로 설정해 할당할 수 없게 한다.

bitmap은 먼저 시스템 영역, 그 뒤 userspace의 세 부분으로 나뉜다. 시스템 영역 자체가 두 절반으로 나뉘므로 전체 구조는 하위 시스템 절반, 상위 시스템 절반, userspace다. 고정 크기로 미리 할당한 시스템 영역이 필요한 이유는 QNX6의 copy-on-write식 쓰기 처리다.

각 슈퍼블록은 시스템 영역의 자기 절반을 사용한다. 슈퍼블록 #1은 항상 하위 절반의 블록을 사용하고 슈퍼블록 #2는 상위 절반 bitmap bit가 나타내는 블록에만 쓴다. bitmap 블록, inode 블록, 두 트리의 간접 주소 블록은 시스템 블록으로 취급한다.

inactive, 즉 일련번호가 더 작은 슈퍼블록의 시스템 영역에 새 스냅샷을 쓰는 동안 다른 절반에는 완전하고 안정적인 파일시스템 구조가 그대로 남는다. 동기 쓰기 완료, 최대 sync leap 시간 도달, 또는 파일시스템 sync 요청 시 이전 inactive 슈퍼블록의 일련번호를 원자적으로 증가시키고 그 슈퍼블록을 안정된 active 상태로 전환한다.

시스템 영역 밖의 모든 데이터 블록은 쓰는 동안 단순히 복사한다.

Bitmap 시스템 영역
영역사용자내용
시스템 하위 절반슈퍼블록 #1bitmap·inode·간접 주소 블록
시스템 상위 절반슈퍼블록 #2bitmap·inode·간접 주소 블록
userspace두 스냅샷의 데이터쓰기 시 블록 복사

두 슈퍼블록이 서로 다른 시스템 블록 절반을 사용해 안정된 스냅샷을 유지한다.

Bitmap
------

The qnx6fs filesystem allocation bitmap is stored in a tree under bitmap
root node in the superblock and each bit in the bitmap represents one
filesystem block.

The first block is block 0, which starts 0x1000 after superblock start.
So for a normal qnx6fs 0x3000 (bootblock + superblock) is the physical
address at which block 0 is located.

Bits at the end of the last bitmap block are set to 1, if the device is
smaller than addressing space in the bitmap.

Bitmap system area
------------------

The bitmap itself is divided into three parts.

First the system area, that is split into two halves.

Then userspace.

The requirement for a static, fixed preallocated system area comes from how
qnx6fs deals with writes.

Each superblock got its own half of the system area. So superblock #1
always uses blocks from the lower half while superblock #2 just writes to
blocks represented by the upper half bitmap system area bits.

Bitmap blocks, Inode blocks and indirect addressing blocks for those two
tree structures are treated as system blocks.

The rational behind that is that a write request can work on a new snapshot
(system area of the inactive - resp. lower serial numbered superblock) while
at the same time there is still a complete stable filesystem structure in the
other half of the system area.

When finished with writing (a sync write is completed, the maximum sync leap
time or a filesystem sync is requested), serial of the previously inactive
superblock atomically is increased and the fs switches over to that - then
stable declared - superblock.

For all data outside the system area, blocks are just copied while writing.