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

Linux 6.18.37 · Filesystems

Squashfs 4.0 Filesystem

Squashfs 압축, mount option, on-disk layout와 lookup cache의 전문 번역입니다.

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

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

1. 요약·해설

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

요약·해설

squashfs.rst:1-323

Squashfs 4.0은 file data, inode, directory, xattr를 압축하는 read-only 파일 시스템이다. 8KB metadata block, type별 compact inode, fragment tail packing, 2단계 lookup table로 작은 image와 빠른 lookup을 함께 달성한다.

image는 superblock부터 xattr까지 최대 아홉 영역으로 구성된다. directory index는 lookup당 metadata block 하나만 decompress하도록 하고, 대형 file index cache는 공간 효율적인 block list로 최대 1.75TiB file을 지원한다.

Squashfs 읽기 경로
superblock·table offset작은 2차 index memory cache압축 metadata 또는 data blockdecompress와 `<block, offset>` 적용inode·directory·fragment·xattr 반환

on-disk index에서 압축 block과 객체로 이동한다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 =======================
4 Squashfs 4.0 Filesystem
5 =======================
6
7 Squashfs is a compressed read-only filesystem for Linux.
8
9 It uses zlib, lz4, lzo, xz or zstd compression to compress files, inodes and
10 directories. Inodes in the system are very small and all blocks are packed to
11 minimise data overhead. Block sizes greater than 4K are supported up to a
12 maximum of 1Mbytes (default block size 128K).
13
14 Squashfs is intended for general read-only filesystem use, for archival
15 use (i.e. in cases where a .tar.gz file may be used), and in constrained
16 block device/memory systems (e.g. embedded systems) where low overhead is
17 needed.
18
19 Mailing list (kernel code): linux-fsdevel@vger.kernel.org
20 Web site: github.com/plougher/squashfs-tools
21
22 1. Filesystem Features
23 ----------------------
24
25 Squashfs filesystem features versus Cramfs:
26
27 ============================== ========= ==========
28 Squashfs Cramfs
29 ============================== ========= ==========
30 Max filesystem size 2^64 256 MiB
31 Max file size ~ 2 TiB 16 MiB
32 Max files unlimited unlimited
33 Max directories unlimited unlimited
34 Max entries per directory unlimited unlimited
35 Max block size 1 MiB 4 KiB
36 Metadata compression yes no
37 Directory indexes yes no
38 Sparse file support yes no
39 Tail-end packing (fragments) yes no
40 Exportable (NFS etc.) yes no
41 Hard link support yes no
42 "." and ".." in readdir yes no
43 Real inode numbers yes no
44 32-bit uids/gids yes no
45 File creation time yes no
46 Xattr support yes no
47 ACL support no no
48 ============================== ========= ==========
49
50 Squashfs compresses data, inodes and directories. In addition, inode and
51 directory data are highly compacted, and packed on byte boundaries. Each
52 compressed inode is on average 8 bytes in length (the exact length varies on
53 file type, i.e. regular file, directory, symbolic link, and block/char device
54 inodes have different sizes).
55
56 2. Using Squashfs
57 -----------------
58
59 As squashfs is a read-only filesystem, the mksquashfs program must be used to
60 create populated squashfs filesystems. This and other squashfs utilities
61 are very likely packaged by your linux distribution (called squashfs-tools).
62 The source code can be obtained from github.com/plougher/squashfs-tools.
63 Usage instructions can also be obtained from this site.
64
65 2.1 Mount options
66 -----------------
67 =================== =========================================================
68 errors=%s Specify whether squashfs errors trigger a kernel panic
69 or not
70
71 ========== =============================================
72 continue errors don't trigger a panic (default)
73 panic trigger a panic when errors are encountered,
74 similar to several other filesystems (e.g.
75 btrfs, ext4, f2fs, GFS2, jfs, ntfs, ubifs)
76
77 This allows a kernel dump to be saved,
78 useful for analyzing and debugging the
79 corruption.
80 ========== =============================================
81 threads=%s Select the decompression mode or the number of threads
82
83 If SQUASHFS_CHOICE_DECOMP_BY_MOUNT is set:
84
85 ========== =============================================
86 single use single-threaded decompression (default)
87
88 Only one block (data or metadata) can be
89 decompressed at any one time. This limits
90 CPU and memory usage to a minimum, but it
91 also gives poor performance on parallel I/O
92 workloads when using multiple CPU machines
93 due to waiting on decompressor availability.
94 multi use up to two parallel decompressors per core
95
96 If you have a parallel I/O workload and your
97 system has enough memory, using this option
98 may improve overall I/O performance. It
99 dynamically allocates decompressors on a
100 demand basis.
101 percpu use a maximum of one decompressor per core
102
103 It uses percpu variables to ensure
104 decompression is load-balanced across the
105 cores.
106 1|2|3|... configure the number of threads used for
107 decompression
108
109 The upper limit is num_online_cpus() * 2.
110 ========== =============================================
111
112 If SQUASHFS_CHOICE_DECOMP_BY_MOUNT is **not** set and
113 SQUASHFS_DECOMP_MULTI, SQUASHFS_MOUNT_DECOMP_THREADS are
114 both set:
115
116 ========== =============================================
117 2|3|... configure the number of threads used for
118 decompression
119
120 The upper limit is num_online_cpus() * 2.
121 ========== =============================================
122
123 =================== =========================================================
124
125 3. Squashfs Filesystem Design
126 -----------------------------
127
128 A squashfs filesystem consists of a maximum of nine parts, packed together on a
129 byte alignment::
130
131 ---------------
132 | superblock |
133 |---------------|
134 | compression |
135 | options |
136 |---------------|
137 | datablocks |
138 | & fragments |
139 |---------------|
140 | inode table |
141 |---------------|
142 | directory |
143 | table |
144 |---------------|
145 | fragment |
146 | table |
147 |---------------|
148 | export |
149 | table |
150 |---------------|
151 | uid/gid |
152 | lookup table |
153 |---------------|
154 | xattr |
155 | table |
156 ---------------
157
158 Compressed data blocks are written to the filesystem as files are read from
159 the source directory, and checked for duplicates. Once all file data has been
160 written the completed inode, directory, fragment, export, uid/gid lookup and
161 xattr tables are written.
162
163 3.1 Compression options
164 -----------------------
165
166 Compressors can optionally support compression specific options (e.g.
167 dictionary size). If non-default compression options have been used, then
168 these are stored here.
169
170 3.2 Inodes
171 ----------
172
173 Metadata (inodes and directories) are compressed in 8Kbyte blocks. Each
174 compressed block is prefixed by a two byte length, the top bit is set if the
175 block is uncompressed. A block will be uncompressed if the -noI option is set,
176 or if the compressed block was larger than the uncompressed block.
177
178 Inodes are packed into the metadata blocks, and are not aligned to block
179 boundaries, therefore inodes overlap compressed blocks. Inodes are identified
180 by a 48-bit number which encodes the location of the compressed metadata block
181 containing the inode, and the byte offset into that block where the inode is
182 placed (<block, offset>).
183
184 To maximise compression there are different inodes for each file type
185 (regular file, directory, device, etc.), the inode contents and length
186 varying with the type.
187
188 To further maximise compression, two types of regular file inode and
189 directory inode are defined: inodes optimised for frequently occurring
190 regular files and directories, and extended types where extra
191 information has to be stored.
192
193 3.3 Directories
194 ---------------
195
196 Like inodes, directories are packed into compressed metadata blocks, stored
197 in a directory table. Directories are accessed using the start address of
198 the metablock containing the directory and the offset into the
199 decompressed block (<block, offset>).
200
201 Directories are organised in a slightly complex way, and are not simply
202 a list of file names. The organisation takes advantage of the
203 fact that (in most cases) the inodes of the files will be in the same
204 compressed metadata block, and therefore, can share the start block.
205 Directories are therefore organised in a two level list, a directory
206 header containing the shared start block value, and a sequence of directory
207 entries, each of which share the shared start block. A new directory header
208 is written once/if the inode start block changes. The directory
209 header/directory entry list is repeated as many times as necessary.
210
211 Directories are sorted, and can contain a directory index to speed up
212 file lookup. Directory indexes store one entry per metablock, each entry
213 storing the index/filename mapping to the first directory header
214 in each metadata block. Directories are sorted in alphabetical order,
215 and at lookup the index is scanned linearly looking for the first filename
216 alphabetically larger than the filename being looked up. At this point the
217 location of the metadata block the filename is in has been found.
218 The general idea of the index is to ensure only one metadata block needs to be
219 decompressed to do a lookup irrespective of the length of the directory.
220 This scheme has the advantage that it doesn't require extra memory overhead
221 and doesn't require much extra storage on disk.
222
223 3.4 File data
224 -------------
225
226 Regular files consist of a sequence of contiguous compressed blocks, and/or a
227 compressed fragment block (tail-end packed block). The compressed size
228 of each datablock is stored in a block list contained within the
229 file inode.
230
231 To speed up access to datablocks when reading 'large' files (256 Mbytes or
232 larger), the code implements an index cache that caches the mapping from
233 block index to datablock location on disk.
234
235 The index cache allows Squashfs to handle large files (up to 1.75 TiB) while
236 retaining a simple and space-efficient block list on disk. The cache
237 is split into slots, caching up to eight 224 GiB files (128 KiB blocks).
238 Larger files use multiple slots, with 1.75 TiB files using all 8 slots.
239 The index cache is designed to be memory efficient, and by default uses
240 16 KiB.
241
242 3.5 Fragment lookup table
243 -------------------------
244
245 Regular files can contain a fragment index which is mapped to a fragment
246 location on disk and compressed size using a fragment lookup table. This
247 fragment lookup table is itself stored compressed into metadata blocks.
248 A second index table is used to locate these. This second index table for
249 speed of access (and because it is small) is read at mount time and cached
250 in memory.
251
252 3.6 Uid/gid lookup table
253 ------------------------
254
255 For space efficiency regular files store uid and gid indexes, which are
256 converted to 32-bit uids/gids using an id look up table. This table is
257 stored compressed into metadata blocks. A second index table is used to
258 locate these. This second index table for speed of access (and because it
259 is small) is read at mount time and cached in memory.
260
261 3.7 Export table
262 ----------------
263
264 To enable Squashfs filesystems to be exportable (via NFS etc.) filesystems
265 can optionally (disabled with the -no-exports Mksquashfs option) contain
266 an inode number to inode disk location lookup table. This is required to
267 enable Squashfs to map inode numbers passed in filehandles to the inode
268 location on disk, which is necessary when the export code reinstantiates
269 expired/flushed inodes.
270
271 This table is stored compressed into metadata blocks. A second index table is
272 used to locate these. This second index table for speed of access (and because
273 it is small) is read at mount time and cached in memory.
274
275 3.8 Xattr table
276 ---------------
277
278 The xattr table contains extended attributes for each inode. The xattrs
279 for each inode are stored in a list, each list entry containing a type,
280 name and value field. The type field encodes the xattr prefix
281 ("user.", "trusted." etc) and it also encodes how the name/value fields
282 should be interpreted. Currently the type indicates whether the value
283 is stored inline (in which case the value field contains the xattr value),
284 or if it is stored out of line (in which case the value field stores a
285 reference to where the actual value is stored). This allows large values
286 to be stored out of line improving scanning and lookup performance and it
287 also allows values to be de-duplicated, the value being stored once, and
288 all other occurrences holding an out of line reference to that value.
289
290 The xattr lists are packed into compressed 8K metadata blocks.
291 To reduce overhead in inodes, rather than storing the on-disk
292 location of the xattr list inside each inode, a 32-bit xattr id
293 is stored. This xattr id is mapped into the location of the xattr
294 list using a second xattr id lookup table.
295
296 4. TODOs and Outstanding Issues
297 -------------------------------
298
299 4.1 TODO list
300 -------------
301
302 Implement ACL support.
303
304 4.2 Squashfs Internal Cache
305 ---------------------------
306
307 Blocks in Squashfs are compressed. To avoid repeatedly decompressing
308 recently accessed data Squashfs uses two small metadata and fragment caches.
309
310 The cache is not used for file datablocks, these are decompressed and cached in
311 the page-cache in the normal way. The cache is used to temporarily cache
312 fragment and metadata blocks which have been read as a result of a metadata
313 (i.e. inode or directory) or fragment access. Because metadata and fragments
314 are packed together into blocks (to gain greater compression) the read of a
315 particular piece of metadata or fragment will retrieve other metadata/fragments
316 which have been packed with it, these because of locality-of-reference may be
317 read in the near future. Temporarily caching them ensures they are available
318 for near future access without requiring an additional read and decompress.
319
320 In the future this internal cache may be replaced with an implementation which
321 uses the kernel page cache. Because the page cache operates on page sized
322 units this may introduce additional complexity in terms of locking and
323 associated race conditions.
324

3. 한국어 전문 번역

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

Squashfs 4.0 개요와 기능

1-55

Squashfs는 Linux용 압축 read-only 파일 시스템이다. zlib, lz4, lzo, xz, zstd로 file data뿐 아니라 inode와 directory도 압축한다. inode는 매우 작고 모든 block을 촘촘히 pack해 overhead를 줄인다. 4KB보다 큰 block을 최대 1MB까지 지원하며 기본 block 크기는 128KB다.

일반 read-only 배포, `.tar.gz`를 쓸 법한 archive, 낮은 overhead가 중요한 embedded block device·memory 시스템을 목표로 한다. kernel code 문의는 `linux-fsdevel@vger.kernel.org`, 도구 source는 `github.com/plougher/squashfs-tools`에 있다.

Squashfs와 Cramfs 기능 비교
기능SquashfsCramfs
최대 파일 시스템2^64256 MiB
최대 파일약 2 TiB16 MiB
최대 파일 수무제한무제한
최대 directory 수무제한무제한
directory당 최대 entry무제한무제한
최대 block1 MiB4 KiB
Metadata compressionyesno
Directory indexyesno
Sparse fileyesno
Tail-end packing(fragment)yesno
NFS exportyesno
Hard linkyesno
readdir의 `.`·`..`yesno
실제 inode numberyesno
32-bit uid/gidyesno
File creation timeyesno
Xattryesno
ACLnono

원문의 비교표 18개 항목을 그대로 구조화했다.

inode와 directory data는 byte boundary에 맞춰 강하게 compact된다. 압축 inode 하나는 평균 약 8 byte지만 regular file, directory, symbolic link, block·character device 등 file type마다 구조와 길이가 다르다.

.. SPDX-License-Identifier: GPL-2.0

=======================
Squashfs 4.0 Filesystem
=======================

Squashfs is a compressed read-only filesystem for Linux.

It uses zlib, lz4, lzo, xz or zstd compression to compress files, inodes and
directories.  Inodes in the system are very small and all blocks are packed to
minimise data overhead. Block sizes greater than 4K are supported up to a
maximum of 1Mbytes (default block size 128K).

Squashfs is intended for general read-only filesystem use, for archival
use (i.e. in cases where a .tar.gz file may be used), and in constrained
block device/memory systems (e.g. embedded systems) where low overhead is
needed.

Mailing list (kernel code): linux-fsdevel@vger.kernel.org
Web site: github.com/plougher/squashfs-tools

1. Filesystem Features
----------------------

Squashfs filesystem features versus Cramfs:

==============================         =========                ==========
                                Squashfs                Cramfs
==============================         =========                ==========
Max filesystem size                2^64                        256 MiB
Max file size                        ~ 2 TiB                        16 MiB
Max files                        unlimited                unlimited
Max directories                        unlimited                unlimited
Max entries per directory        unlimited                unlimited
Max block size                        1 MiB                        4 KiB
Metadata compression                yes                        no
Directory indexes                yes                        no
Sparse file support                yes                        no
Tail-end packing (fragments)        yes                        no
Exportable (NFS etc.)                yes                        no
Hard link support                yes                        no
"." and ".." in readdir                yes                        no
Real inode numbers                yes                        no
32-bit uids/gids                yes                        no
File creation time                yes                        no
Xattr support                        yes                        no
ACL support                        no                        no
==============================         =========                ==========

Squashfs compresses data, inodes and directories.  In addition, inode and
directory data are highly compacted, and packed on byte boundaries.  Each
compressed inode is on average 8 bytes in length (the exact length varies on
file type, i.e. regular file, directory, symbolic link, and block/char device
inodes have different sizes).

생성 도구와 mount option

56-124

read-only 파일 시스템이므로 내용이 채워진 image는 `mksquashfs`로 만든다. 배포판은 대개 이 프로그램과 유틸리티를 `squashfs-tools` package로 제공하며 source와 사용법도 프로젝트 site에서 얻을 수 있다.

`errors=continue`는 오류가 발생해도 panic하지 않는 기본값이다. `errors=panic`은 corruption을 만났을 때 ext4·btrfs 등과 비슷하게 kernel panic을 일으켜 분석용 kernel dump를 저장할 수 있게 한다.

`threads=`는 decompression mode 또는 thread 수를 정한다. `SQUASHFS_CHOICE_DECOMP_BY_MOUNT`가 켜지면 `single`, `multi`, `percpu`, 숫자를 선택할 수 있다. single은 동시 block 하나라 CPU·memory가 최소지만 parallel I/O가 느리다. multi는 core당 최대 두 decompressor를 수요에 따라 동적 할당한다. percpu는 core당 최대 하나를 두고 percpu variable로 load balance한다. 숫자 지정 상한은 `num_online_cpus() * 2`다.

mount 선택 기능은 없지만 `SQUASHFS_DECOMP_MULTI`와 `SQUASHFS_MOUNT_DECOMP_THREADS`가 모두 켜진 구성에서는 `threads=2|3|...`로 수를 지정하며 같은 상한을 적용한다.

Squashfs mount option
Option의미
errorscontinue오류가 panic을 일으키지 않음, 기본값
errorspaniccorruption 때 panic과 dump 저장 가능
threadssingle동시 1 block, 최소 CPU·memory
threadsmulticore당 최대 2개, 수요 기반 동적 할당
threadspercpucore당 최대 1개, percpu load balance
threads1|2|3|...명시적 thread 수, 상한 CPU 수의 2배

오류 정책과 decompressor 병렬성의 선택지다.

2. Using Squashfs
-----------------

As squashfs is a read-only filesystem, the mksquashfs program must be used to
create populated squashfs filesystems.  This and other squashfs utilities
are very likely packaged by your linux distribution (called squashfs-tools).
The source code can be obtained from github.com/plougher/squashfs-tools.
Usage instructions can also be obtained from this site.

2.1 Mount options
-----------------
===================    =========================================================
errors=%s              Specify whether squashfs errors trigger a kernel panic
                       or not

                       ==========  =============================================
                         continue  errors don't trigger a panic (default)
                            panic  trigger a panic when errors are encountered,
                                   similar to several other filesystems (e.g.
                                   btrfs, ext4, f2fs, GFS2, jfs, ntfs, ubifs)

                                   This allows a kernel dump to be saved,
                                   useful for analyzing and debugging the
                                   corruption.
                       ==========  =============================================
threads=%s             Select the decompression mode or the number of threads

                       If SQUASHFS_CHOICE_DECOMP_BY_MOUNT is set:

                       ==========  =============================================
                           single  use single-threaded decompression (default)

                                   Only one block (data or metadata) can be
                                   decompressed at any one time. This limits
                                   CPU and memory usage to a minimum, but it
                                   also gives poor performance on parallel I/O
                                   workloads when using multiple CPU machines
                                   due to waiting on decompressor availability.
                            multi  use up to two parallel decompressors per core

                                   If you have a parallel I/O workload and your
                                   system has enough memory, using this option
                                   may improve overall I/O performance. It
                                   dynamically allocates decompressors on a
                                   demand basis.
                           percpu  use a maximum of one decompressor per core

                                   It uses percpu variables to ensure
                                   decompression is load-balanced across the
                                   cores.
                        1|2|3|...  configure the number of threads used for
                                   decompression

                                   The upper limit is num_online_cpus() * 2.
                       ==========  =============================================

                       If SQUASHFS_CHOICE_DECOMP_BY_MOUNT is **not** set and
                       SQUASHFS_DECOMP_MULTI, SQUASHFS_MOUNT_DECOMP_THREADS are
                       both set:

                       ==========  =============================================
                          2|3|...  configure the number of threads used for
                                   decompression

                                   The upper limit is num_online_cpus() * 2.
                       ==========  =============================================

===================    =========================================================

파일 시스템의 최대 아홉 영역

125-162

Squashfs image는 byte alignment로 연속 배치되는 최대 아홉 부분으로 구성된다. compression option은 non-default compressor 설정이 있을 때만 존재하고, export·xattr 같은 optional table도 설정에 따라 생략될 수 있다.

Squashfs on-disk layout
순서영역역할
1superblock전역 형식·offset 정보
2compression optionsnon-default dictionary 등 compressor option
3datablocks & fragmentsfile data와 tail-end packed block
4inode table압축 metadata inode
5directory table압축 directory header·entry
6fragment tablefragment 위치·압축 크기 lookup
7export tableinode number에서 disk inode 위치 lookup
8uid/gid lookup tableid index에서 32-bit uid/gid 변환
9xattr tableinode별 extended attribute

원문의 세로 ASCII 구조를 순서가 있는 표로 다시 그렸다.

source directory에서 file을 읽는 동안 압축 data block을 image에 쓰고 duplicate를 검사한다. 모든 file data가 끝난 다음 완성된 inode, directory, fragment, export, uid/gid lookup, xattr table을 기록한다.

Image 생성 순서
source file 읽기data block 압축duplicate block 검사·기록모든 file data 완료inode·directory·lookup·xattr table 기록

streaming data 기록 뒤 metadata table을 마감한다.

3. Squashfs Filesystem Design
-----------------------------

A squashfs filesystem consists of a maximum of nine parts, packed together on a
byte alignment::

         ---------------
        |  superblock         |
        |---------------|
        |  compression  |
        |    options    |
        |---------------|
        |  datablocks   |
        |  & fragments  |
        |---------------|
        |  inode table        |
        |---------------|
        |   directory        |
        |     table     |
        |---------------|
        |   fragment        |
        |    table      |
        |---------------|
        |    export     |
        |    table      |
        |---------------|
        |    uid/gid        |
        |  lookup table        |
        |---------------|
        |     xattr     |
        |     table        |
         ---------------

Compressed data blocks are written to the filesystem as files are read from
the source directory, and checked for duplicates.  Once all file data has been
written the completed inode, directory, fragment, export, uid/gid lookup and
xattr tables are written.

압축 option과 inode 주소

163-192

compressor는 dictionary size 같은 고유 option을 선택적으로 지원한다. 기본값이 아닌 option을 썼을 때 image의 compression options 영역에 저장한다.

inode와 directory metadata는 8KB block으로 압축된다. 각 block 앞에는 2-byte 길이가 있고 최상위 bit는 block이 uncompressed임을 뜻한다. `-noI`를 사용했거나 압축 결과가 원본보다 커졌으면 uncompressed로 저장한다.

inode는 metadata block 안에 block boundary alignment 없이 이어 붙기 때문에 압축 block 경계를 가로지를 수 있다. inode의 48-bit 번호는 inode를 포함하는 압축 metadata block 위치와 decompressed block 내부 byte offset을 `<block, offset>`으로 encoding한다.

압축률을 높이기 위해 regular file, directory, device 등 file type별 inode 구조와 길이가 다르다. 자주 나타나는 regular file·directory용 compact type과 추가 정보가 필요한 extended type도 별도로 정의한다.

48-bit inode 위치 해석
48-bit inode identifier압축 metadata block 위치 추출해당 8KB block 읽기·decompressblock 내부 byte offset 적용file type별 inode 구조 decode

inode number를 metadata block과 내부 offset으로 나눈다.

3.1 Compression options
-----------------------

Compressors can optionally support compression specific options (e.g.
dictionary size).  If non-default compression options have been used, then
these are stored here.

3.2 Inodes
----------

Metadata (inodes and directories) are compressed in 8Kbyte blocks.  Each
compressed block is prefixed by a two byte length, the top bit is set if the
block is uncompressed.  A block will be uncompressed if the -noI option is set,
or if the compressed block was larger than the uncompressed block.

Inodes are packed into the metadata blocks, and are not aligned to block
boundaries, therefore inodes overlap compressed blocks.  Inodes are identified
by a 48-bit number which encodes the location of the compressed metadata block
containing the inode, and the byte offset into that block where the inode is
placed (<block, offset>).

To maximise compression there are different inodes for each file type
(regular file, directory, device, etc.), the inode contents and length
varying with the type.

To further maximise compression, two types of regular file inode and
directory inode are defined: inodes optimised for frequently occurring
regular files and directories, and extended types where extra
information has to be stored.

Directory의 2단계 list와 index

193-222

directory도 압축 metadata block에 pack되어 directory table에 저장된다. 접근 주소는 directory를 포함한 metablock의 시작 주소와 decompressed block 내부 offset인 `<block, offset>`이다.

단순 filename list가 아니라 inode가 대개 같은 압축 metadata block에 있다는 점을 이용한 2단계 list다. directory header가 공유 inode start block을 한 번 저장하고, 뒤의 여러 directory entry가 그 값을 공유한다. inode start block이 바뀔 때 새 header를 쓰며 필요한 만큼 header·entry 묶음을 반복한다.

directory는 alphabetic order로 정렬되고 lookup을 빠르게 할 index를 가질 수 있다. index는 metablock마다 entry 하나를 두어 그 block의 첫 directory header에 해당하는 index·filename mapping을 저장한다. 찾는 이름보다 사전순으로 처음 큰 filename을 만날 때까지 선형 scan하면 대상 metadata block을 알 수 있다.

이 방식은 directory 길이와 상관없이 lookup마다 metadata block 하나만 decompress하게 하면서 추가 memory와 disk 공간을 거의 요구하지 않는다.

Directory lookup
정렬된 directory index 선형 scan찾는 이름보다 처음 큰 index filename 발견직전 mapping으로 metadata block 위치 결정해당 block 하나 decompress공유 start block header와 entry sequence 검색

index에서 block을 고른 뒤 2단계 list를 해석한다.

3.3 Directories
---------------

Like inodes, directories are packed into compressed metadata blocks, stored
in a directory table.  Directories are accessed using the start address of
the metablock containing the directory and the offset into the
decompressed block (<block, offset>).

Directories are organised in a slightly complex way, and are not simply
a list of file names.  The organisation takes advantage of the
fact that (in most cases) the inodes of the files will be in the same
compressed metadata block, and therefore, can share the start block.
Directories are therefore organised in a two level list, a directory
header containing the shared start block value, and a sequence of directory
entries, each of which share the shared start block.  A new directory header
is written once/if the inode start block changes.  The directory
header/directory entry list is repeated as many times as necessary.

Directories are sorted, and can contain a directory index to speed up
file lookup.  Directory indexes store one entry per metablock, each entry
storing the index/filename mapping to the first directory header
in each metadata block.  Directories are sorted in alphabetical order,
and at lookup the index is scanned linearly looking for the first filename
alphabetically larger than the filename being looked up.  At this point the
location of the metadata block the filename is in has been found.
The general idea of the index is to ensure only one metadata block needs to be
decompressed to do a lookup irrespective of the length of the directory.
This scheme has the advantage that it doesn't require extra memory overhead
and doesn't require much extra storage on disk.

File block list와 대형 파일 index cache

223-241

regular file은 연속된 압축 block sequence와 선택적 압축 fragment block(tail-end packed block)으로 구성된다. 각 data block의 압축 크기는 file inode 안의 block list에 저장된다.

256MB 이상 큰 file을 읽을 때 block index에서 on-disk data block 위치를 빨리 찾도록 index cache를 사용한다. 단순하고 공간 효율적인 on-disk block list를 유지하면서 최대 1.75TiB file을 처리한다.

cache는 slot으로 나뉘며 128KB block 기준 최대 224GiB file 여덟 개를 cache할 수 있다. 더 큰 file은 여러 slot을 쓰고 1.75TiB file 하나는 8 slot 전부를 사용한다. 기본 memory 사용량은 16KiB다.

대형 파일 index cache
항목
적용 기준256 MiB 이상 file
최대 file1.75 TiB
slot 수8
slot당 범위128 KiB block 기준 224 GiB
기본 memory16 KiB

block list의 공간 효율과 lookup 속도를 보완한다.

3.4 File data
-------------

Regular files consist of a sequence of contiguous compressed blocks, and/or a
compressed fragment block (tail-end packed block).   The compressed size
of each datablock is stored in a block list contained within the
file inode.

To speed up access to datablocks when reading 'large' files (256 Mbytes or
larger), the code implements an index cache that caches the mapping from
block index to datablock location on disk.

The index cache allows Squashfs to handle large files (up to 1.75 TiB) while
retaining a simple and space-efficient block list on disk.  The cache
is split into slots, caching up to eight 224 GiB files (128 KiB blocks).
Larger files use multiple slots, with 1.75 TiB files using all 8 slots.
The index cache is designed to be memory efficient, and by default uses
16 KiB.

Fragment·uid/gid·export lookup

242-274

regular file의 fragment index는 fragment lookup table을 통해 on-disk 위치와 압축 크기로 변환된다. 이 table 자체가 metadata block으로 압축되고, 그 block들을 찾는 두 번째 index table이 있다. 작고 접근 빈도가 높으므로 두 번째 table은 mount 때 읽어 memory에 cache한다.

공간 절약을 위해 regular file은 uid·gid 실제 값 대신 index를 저장한다. id lookup table이 이를 32-bit uid/gid로 변환한다. 이 table도 압축 metadata block과 mount 때 cache되는 두 번째 index table 구조를 사용한다.

NFS 등으로 export하려면 filehandle의 inode number에서 on-disk inode 위치를 찾을 table이 선택적으로 필요하다. export code가 만료·flush된 inode를 재생성할 때 이 mapping을 사용한다. `mksquashfs -no-exports`로 비활성화할 수 있으며, 역시 압축 table과 memory-cached 2차 index로 구성된다.

Squashfs lookup table
Table입력출력2차 index
Fragmentfragment indexdisk 위치·압축 크기mount 때 memory cache
uid/gidid index32-bit uid/gidmount 때 memory cache
Exportinode numberinode disk 위치mount 때 memory cache

세 table이 같은 2단계 압축·index 패턴을 공유한다.

3.5 Fragment lookup table
-------------------------

Regular files can contain a fragment index which is mapped to a fragment
location on disk and compressed size using a fragment lookup table.  This
fragment lookup table is itself stored compressed into metadata blocks.
A second index table is used to locate these.  This second index table for
speed of access (and because it is small) is read at mount time and cached
in memory.

3.6 Uid/gid lookup table
------------------------

For space efficiency regular files store uid and gid indexes, which are
converted to 32-bit uids/gids using an id look up table.  This table is
stored compressed into metadata blocks.  A second index table is used to
locate these.  This second index table for speed of access (and because it
is small) is read at mount time and cached in memory.

3.7 Export table
----------------

To enable Squashfs filesystems to be exportable (via NFS etc.) filesystems
can optionally (disabled with the -no-exports Mksquashfs option) contain
an inode number to inode disk location lookup table.  This is required to
enable Squashfs to map inode numbers passed in filehandles to the inode
location on disk, which is necessary when the export code reinstantiates
expired/flushed inodes.

This table is stored compressed into metadata blocks.  A second index table is
used to locate these.  This second index table for speed of access (and because
it is small) is read at mount time and cached in memory.

Xattr list와 out-of-line 값

275-295

xattr table은 inode별 extended attribute를 list로 저장한다. 각 entry는 type, name, value field를 가지며 type은 `user.`, `trusted.` 같은 prefix와 name·value 해석 방법을 encoding한다.

value는 inline이면 value field에 직접 들어가고, out-of-line이면 실제 값 위치의 reference가 들어간다. 큰 값을 별도로 두면 scan·lookup 성능이 좋아지고 동일 value를 한 번만 저장해 여러 occurrence가 같은 reference를 쓰는 de-duplication도 가능하다.

xattr list는 압축 8KB metadata block에 pack된다. inode마다 긴 on-disk 위치를 저장하는 대신 32-bit xattr id만 두고, 두 번째 xattr id lookup table이 list 위치로 mapping해 inode overhead를 줄인다.

Xattr 값 해석
inode의 32-bit xattr idxattr id lookup table압축 8KB metadata block의 listtype에서 prefix·inline 여부 decodeinline value 또는 공유 out-of-line value 참조

type과 32-bit id를 따라 실제 name·value list에 도달한다.

3.8 Xattr table
---------------

The xattr table contains extended attributes for each inode.  The xattrs
for each inode are stored in a list, each list entry containing a type,
name and value field.  The type field encodes the xattr prefix
("user.", "trusted." etc) and it also encodes how the name/value fields
should be interpreted.  Currently the type indicates whether the value
is stored inline (in which case the value field contains the xattr value),
or if it is stored out of line (in which case the value field stores a
reference to where the actual value is stored).  This allows large values
to be stored out of line improving scanning and lookup performance and it
also allows values to be de-duplicated, the value being stored once, and
all other occurrences holding an out of line reference to that value.

The xattr lists are packed into compressed 8K metadata blocks.
To reduce overhead in inodes, rather than storing the on-disk
location of the xattr list inside each inode, a 32-bit xattr id
is stored.  This xattr id is mapped into the location of the xattr
list using a second xattr id lookup table.

ACL TODO와 내부 cache

296-323

남은 TODO는 ACL 지원 구현이다.

압축 block을 최근 접근 때마다 다시 decompress하지 않도록 Squashfs는 작은 metadata cache와 fragment cache 두 개를 사용한다. 일반 file data block은 이 내부 cache 대상이 아니며 평소처럼 decompress한 뒤 kernel page cache에 저장한다.

metadata와 fragment는 압축률을 위해 한 block에 여러 항목이 함께 pack된다. 특정 항목을 읽을 때 같이 나온 이웃 항목은 locality of reference로 곧 다시 쓰일 가능성이 있으므로 잠시 cache하면 추가 read와 decompress를 피할 수 있다.

향후 내부 cache를 kernel page cache 기반 구현으로 바꿀 수 있다. 다만 page cache는 page-size 단위라 locking과 관련 race condition이 더 복잡해질 수 있다.

Squashfs cache 역할
대상Cache이유
File datablockkernel page cache일반 file I/O 경로
Inode·directory metadata작은 내부 metadata cache함께 unpack된 이웃 재사용
Fragment작은 내부 fragment cache추가 read·decompress 회피
미래 대안kernel page cache 통합page 단위 locking·race 복잡성

data block과 packed metadata의 cache 경로가 다르다.

4. TODOs and Outstanding Issues
-------------------------------

4.1 TODO list
-------------

Implement ACL support.

4.2 Squashfs Internal Cache
---------------------------

Blocks in Squashfs are compressed.  To avoid repeatedly decompressing
recently accessed data Squashfs uses two small metadata and fragment caches.

The cache is not used for file datablocks, these are decompressed and cached in
the page-cache in the normal way.  The cache is used to temporarily cache
fragment and metadata blocks which have been read as a result of a metadata
(i.e. inode or directory) or fragment access.  Because metadata and fragments
are packed together into blocks (to gain greater compression) the read of a
particular piece of metadata or fragment will retrieve other metadata/fragments
which have been packed with it, these because of locality-of-reference may be
read in the near future. Temporarily caching them ensures they are available
for near future access without requiring an additional read and decompress.

In the future this internal cache may be replaced with an implementation which
uses the kernel page cache.  Because the page cache operates on page sized
units this may introduce additional complexity in terms of locking and
associated race conditions.