요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
=======================
ROMFS - ROM File System
=======================
This is a quite dumb, read only filesystem, mainly for initial RAM
disks of installation disks. It has grown up by the need of having
modules linked at boot time. Using this filesystem, you get a very
similar feature, and even the possibility of a small kernel, with a
file system which doesn't take up useful memory from the router
functions in the basement of your office.
For comparison, both the older minix and xiafs (the latter is now
defunct) filesystems, compiled as module need more than 20000 bytes,
while romfs is less than a page, about 4000 bytes (assuming i586
code). Under the same conditions, the msdos filesystem would need
about 30K (and does not support device nodes or symlinks), while the
nfs module with nfsroot is about 57K. Furthermore, as a bit unfair
comparison, an actual rescue disk used up 3202 blocks with ext2, while
with romfs, it needed 3079 blocks.
To create such a file system, you'll need a user program named
genromfs. It is available on http://romfs.sourceforge.net/
As the name suggests, romfs could be also used (space-efficiently) on
various read-only media, like (E)EPROM disks if someone will have the
motivation.. :)
However, the main purpose of romfs is to have a very small kernel,
which has only this filesystem linked in, and then can load any module
later, with the current module utilities. It can also be used to run
some program to decide if you need SCSI devices, and even IDE or
floppy drives can be loaded later if you use the "initrd"--initial
RAM disk--feature of the kernel. This would not be really news
flash, but with romfs, you can even spare off your ext2 or minix or
maybe even affs filesystem until you really know that you need it.
For example, a distribution boot disk can contain only the cd disk
drivers (and possibly the SCSI drivers), and the ISO 9660 filesystem
module. The kernel can be small enough, since it doesn't have other
filesystems, like the quite large ext2fs module, which can then be
loaded off the CD at a later stage of the installation. Another use
would be for a recovery disk, when you are reinstalling a workstation
from the network, and you will have all the tools/modules available
from a nearby server, so you don't want to carry two disks for this
purpose, just because it won't fit into ext2.
romfs operates on block devices as you can expect, and the underlying
structure is very simple. Every accessible structure begins on 16
byte boundaries for fast access. The minimum space a file will take
is 32 bytes (this is an empty file, with a less than 16 character
name). The maximum overhead for any non-empty file is the header, and
the 16 byte padding for the name and the contents, also 16+14+15 = 45
bytes. This is quite rare however, since most file names are longer
than 3 bytes, and shorter than 15 bytes.
The layout of the filesystem is the following::
offset content
+---+---+---+---+
0 | - | r | o | m | \
+---+---+---+---+ The ASCII representation of those bytes
4 | 1 | f | s | - | / (i.e. "-rom1fs-")
+---+---+---+---+
8 | full size | The number of accessible bytes in this fs.
+---+---+---+---+
12 | checksum | The checksum of the FIRST 512 BYTES.
+---+---+---+---+
16 | volume name | The zero terminated name of the volume,
: : padded to 16 byte boundary.
+---+---+---+---+
xx | file |
: headers :
Every multi byte value (32 bit words, I'll use the longwords term from
now on) must be in big endian order.
The first eight bytes identify the filesystem, even for the casual
inspector. After that, in the 3rd longword, it contains the number of
bytes accessible from the start of this filesystem. The 4th longword
is the checksum of the first 512 bytes (or the number of bytes
accessible, whichever is smaller). The applied algorithm is the same
as in the AFFS filesystem, namely a simple sum of the longwords
(assuming bigendian quantities again). For details, please consult
the source. This algorithm was chosen because although it's not quite
reliable, it does not require any tables, and it is very simple.
The following bytes are now part of the file system; each file header
must begin on a 16 byte boundary::
offset content
+---+---+---+---+
0 | next filehdr|X| The offset of the next file header
+---+---+---+---+ (zero if no more files)
4 | spec.info | Info for directories/hard links/devices
+---+---+---+---+
8 | size | The size of this file in bytes
+---+---+---+---+
12 | checksum | Covering the meta data, including the file
+---+---+---+---+ name, and padding
16 | file name | The zero terminated name of the file,
: : padded to 16 byte boundary
+---+---+---+---+
xx | file data |
: :
Since the file headers begin always at a 16 byte boundary, the lowest
4 bits would be always zero in the next filehdr pointer. These four
bits are used for the mode information. Bits 0..2 specify the type of
the file; while bit 4 shows if the file is executable or not. The
permissions are assumed to be world readable, if this bit is not set,
and world executable if it is; except the character and block devices,
they are never accessible for other than owner. The owner of every
file is user and group 0, this should never be a problem for the
intended use. The mapping of the 8 possible values to file types is
the following:
== =============== ============================================
mapping spec.info means
== =============== ============================================
0 hard link link destination [file header]
1 directory first file's header
2 regular file unused, must be zero [MBZ]
3 symbolic link unused, MBZ (file data is the link content)
4 block device 16/16 bits major/minor number
5 char device - " -
6 socket unused, MBZ
7 fifo unused, MBZ
== =============== ============================================
Note that hard links are specifically marked in this filesystem, but
they will behave as you can expect (i.e. share the inode number).
Note also that it is your responsibility to not create hard link
loops, and creating all the . and .. links for directories. This is
normally done correctly by the genromfs program. Please refrain from
using the executable bits for special purposes on the socket and fifo
special files, they may have other uses in the future. Additionally,
please remember that only regular files, and symlinks are supposed to
have a nonzero size field; they contain the number of bytes available
directly after the (padded) file name.
Another thing to note is that romfs works on file headers and data
aligned to 16 byte boundaries, but most hardware devices and the block
device drivers are unable to cope with smaller than block-sized data.
To overcome this limitation, the whole size of the file system must be
padded to an 1024 byte boundary.
If you have any problems or suggestions concerning this file system,
please contact me. However, think twice before wanting me to add
features and code, because the primary and most important advantage of
this file system is the small code. On the other hand, don't be
alarmed, I'm not getting that much romfs related mail. Now I can
understand why Avery wrote poems in the ARCnet docs to get some more
feedback. :)
romfs has also a mailing list, and to date, it hasn't received any
traffic, so you are welcome to join it to discuss your ideas. :)
It's run by ezmlm, so you can subscribe to it by sending a message
to romfs-subscribe@shadow.banki.hu, the content is irrelevant.
Pending issues:
- Permissions and owner information are pretty essential features of a
Un*x like system, but romfs does not provide the full possibilities.
I have never found this limiting, but others might.
- The file system is read only, so it can be very small, but in case
one would want to write _anything_ to a file system, he still needs
a writable file system, thus negating the size advantages. Possible
solutions: implement write access as a compile-time option, or a new,
similarly small writable filesystem for RAM disks.
- Since the files are only required to have alignment on a 16 byte
boundary, it is currently possibly suboptimal to read or execute files
from the filesystem. It might be resolved by reordering file data to
have most of it (i.e. except the start and the end) laying at "natural"
boundaries, thus it would be possible to directly map a big portion of
the file contents to the mm subsystem.
- Compression might be an useful feature, but memory is quite a
limiting factor in my eyes.
- Where it is used?
- Does it work on other architectures than intel and motorola?
Have fun,
Janos Farkas <chexum@shadow.banki.hu>
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
ROMFS의 목적과 크기
1-56ROMFS는 주로 설치 디스크의 초기 RAM disk를 위한 매우 단순한 read-only 파일시스템이다. Boot 때 module을 연결해야 한다는 요구에서 만들어졌으며, 작은 kernel이 처음에는 ROMFS만 내장하고 나중에 필요한 module을 올릴 수 있게 한다.
i586 코드를 가정하면 module로 빌드한 minix와 xiafs는 20,000바이트보다 크지만 ROMFS는 page 하나보다 작은 약 4,000바이트다. 같은 조건의 msdos는 약 30KB이면서 device node와 symlink를 지원하지 않고, nfsroot를 포함한 NFS module은 약 57KB다. 실제 rescue disk 예시는 ext2 3202 block, ROMFS 3079 block을 사용했다.
파일시스템 이미지는 `genromfs` userspace 도구로 만들며 원문은 `http://romfs.sourceforge.net/`을 제공한다. 이름처럼 EEPROM 같은 read-only media에서도 공간 효율적으로 쓸 수 있다.
핵심 용도는 작은 kernel이 boot한 뒤 현재 module utility로 SCSI·IDE·floppy·일반 filesystem driver를 필요할 때만 올리는 것이다. 배포판 boot disk는 CD·SCSI driver와 ISO 9660 module만 포함하고 큰 ext2fs는 설치 후 CD에서 읽을 수 있다. Network recovery에서도 모든 tool과 module을 server에서 받으므로 별도 disk를 줄일 수 있다.
ROMFS는 block device에서 동작하며 접근 가능한 모든 구조가 빠른 접근을 위해 16-byte boundary에서 시작한다. 16자보다 짧은 이름의 빈 파일 최소 크기는 32바이트다. Non-empty 파일의 최대 overhead는 header 16, 이름 관련 14, 이름과 content padding 15를 합친 45바이트지만 일반 이름 길이에서는 드물다.
작은 read-only driver로 나머지 storage stack을 늦게 적재한다.
.. SPDX-License-Identifier: GPL-2.0
=======================
ROMFS - ROM File System
=======================
This is a quite dumb, read only filesystem, mainly for initial RAM
disks of installation disks. It has grown up by the need of having
modules linked at boot time. Using this filesystem, you get a very
similar feature, and even the possibility of a small kernel, with a
file system which doesn't take up useful memory from the router
functions in the basement of your office.
For comparison, both the older minix and xiafs (the latter is now
defunct) filesystems, compiled as module need more than 20000 bytes,
while romfs is less than a page, about 4000 bytes (assuming i586
code). Under the same conditions, the msdos filesystem would need
about 30K (and does not support device nodes or symlinks), while the
nfs module with nfsroot is about 57K. Furthermore, as a bit unfair
comparison, an actual rescue disk used up 3202 blocks with ext2, while
with romfs, it needed 3079 blocks.
To create such a file system, you'll need a user program named
genromfs. It is available on http://romfs.sourceforge.net/
As the name suggests, romfs could be also used (space-efficiently) on
various read-only media, like (E)EPROM disks if someone will have the
motivation.. :)
However, the main purpose of romfs is to have a very small kernel,
which has only this filesystem linked in, and then can load any module
later, with the current module utilities. It can also be used to run
some program to decide if you need SCSI devices, and even IDE or
floppy drives can be loaded later if you use the "initrd"--initial
RAM disk--feature of the kernel. This would not be really news
flash, but with romfs, you can even spare off your ext2 or minix or
maybe even affs filesystem until you really know that you need it.
For example, a distribution boot disk can contain only the cd disk
drivers (and possibly the SCSI drivers), and the ISO 9660 filesystem
module. The kernel can be small enough, since it doesn't have other
filesystems, like the quite large ext2fs module, which can then be
loaded off the CD at a later stage of the installation. Another use
would be for a recovery disk, when you are reinstalling a workstation
from the network, and you will have all the tools/modules available
from a nearby server, so you don't want to carry two disks for this
purpose, just because it won't fit into ext2.
romfs operates on block devices as you can expect, and the underlying
structure is very simple. Every accessible structure begins on 16
byte boundaries for fast access. The minimum space a file will take
is 32 bytes (this is an empty file, with a less than 16 character
name). The maximum overhead for any non-empty file is the header, and
the 16 byte padding for the name and the contents, also 16+14+15 = 45
bytes. This is quite rare however, since most file names are longer
than 3 bytes, and shorter than 15 bytes.
Filesystem header와 checksum
57-111원문의 ASCII layout을 offset별 구조로 옮겼다.
모든 multi-byte 값, 즉 32-bit longword는 big-endian 순서다. 첫 8바이트는 사람이 보아도 파일시스템을 식별할 magic이다. 셋째 longword가 접근 가능 byte 수, 넷째가 checksum이다.
Checksum은 AFFS와 같은 방식으로 big-endian longword를 단순 합산한다. 신뢰성이 높지는 않지만 table이 필요 없고 구현이 매우 단순해 선택됐다. 자세한 알고리즘은 source를 참고한다.
Magic과 길이·checksum을 검증한 뒤 정렬된 첫 file header로 이동한다.
The layout of the filesystem is the following::
offset content
+---+---+---+---+
0 | - | r | o | m | \
+---+---+---+---+ The ASCII representation of those bytes
4 | 1 | f | s | - | / (i.e. "-rom1fs-")
+---+---+---+---+
8 | full size | The number of accessible bytes in this fs.
+---+---+---+---+
12 | checksum | The checksum of the FIRST 512 BYTES.
+---+---+---+---+
16 | volume name | The zero terminated name of the volume,
: : padded to 16 byte boundary.
+---+---+---+---+
xx | file |
: headers :
Every multi byte value (32 bit words, I'll use the longwords term from
now on) must be in big endian order.
The first eight bytes identify the filesystem, even for the casual
inspector. After that, in the 3rd longword, it contains the number of
bytes accessible from the start of this filesystem. The 4th longword
is the checksum of the first 512 bytes (or the number of bytes
accessible, whichever is smaller). The applied algorithm is the same
as in the AFFS filesystem, namely a simple sum of the longwords
(assuming bigendian quantities again). For details, please consult
the source. This algorithm was chosen because although it's not quite
reliable, it does not require any tables, and it is very simple.
The following bytes are now part of the file system; each file header
must begin on a 16 byte boundary::
offset content
+---+---+---+---+
0 | next filehdr|X| The offset of the next file header
+---+---+---+---+ (zero if no more files)
4 | spec.info | Info for directories/hard links/devices
+---+---+---+---+
8 | size | The size of this file in bytes
+---+---+---+---+
12 | checksum | Covering the meta data, including the file
+---+---+---+---+ name, and padding
16 | file name | The zero terminated name of the file,
: : padded to 16 byte boundary
+---+---+---+---+
xx | file data |
: :
Since the file headers begin always at a 16 byte boundary, the lowest
4 bits would be always zero in the next filehdr pointer. These four
File header·type·spec.info
112-162모든 file header와 data는 16-byte boundary에 맞춘다.
File header가 항상 16-byte boundary에 있으므로 next pointer의 하위 4 bit는 원래 0이다. 이 bit를 mode 정보로 재사용한다. Bit 0..2는 file type, 원문이 말하는 bit 4는 executable 여부를 나타낸다.
기본 permission은 world-readable이고 executable bit가 있으면 world-executable이다. Character와 block device는 owner 외 접근할 수 없다. 모든 파일의 owner와 group은 0이다.
3-bit type 값과 `spec.info`의 전체 의미다.
Hard link는 명시적으로 표시되지만 예상대로 inode 번호를 공유한다. Hard link loop를 만들지 않고 directory의 `.`와 `..` link를 모두 만드는 책임은 image 생성자에게 있으며 `genromfs`가 보통 정확히 처리한다.
Socket과 fifo의 executable bit는 미래 용도가 있을 수 있으므로 특별한 의미로 재사용하면 안 된다. Regular file과 symlink만 nonzero size를 가져야 하며, padded file name 직후의 실제 byte 수를 뜻한다.
bits are used for the mode information. Bits 0..2 specify the type of
the file; while bit 4 shows if the file is executable or not. The
permissions are assumed to be world readable, if this bit is not set,
and world executable if it is; except the character and block devices,
they are never accessible for other than owner. The owner of every
file is user and group 0, this should never be a problem for the
intended use. The mapping of the 8 possible values to file types is
the following:
== =============== ============================================
mapping spec.info means
== =============== ============================================
0 hard link link destination [file header]
1 directory first file's header
2 regular file unused, must be zero [MBZ]
3 symbolic link unused, MBZ (file data is the link content)
4 block device 16/16 bits major/minor number
5 char device - " -
6 socket unused, MBZ
7 fifo unused, MBZ
== =============== ============================================
Note that hard links are specifically marked in this filesystem, but
they will behave as you can expect (i.e. share the inode number).
Note also that it is your responsibility to not create hard link
loops, and creating all the . and .. links for directories. This is
normally done correctly by the genromfs program. Please refrain from
using the executable bits for special purposes on the socket and fifo
special files, they may have other uses in the future. Additionally,
please remember that only regular files, and symlinks are supposed to
have a nonzero size field; they contain the number of bytes available
directly after the (padded) file name.
Another thing to note is that romfs works on file headers and data
aligned to 16 byte boundaries, but most hardware devices and the block
device drivers are unable to cope with smaller than block-sized data.
To overcome this limitation, the whole size of the file system must be
padded to an 1024 byte boundary.
If you have any problems or suggestions concerning this file system,
please contact me. However, think twice before wanting me to add
features and code, because the primary and most important advantage of
this file system is the small code. On the other hand, don't be
alarmed, I'm not getting that much romfs related mail. Now I can
understand why Avery wrote poems in the ARCnet docs to get some more
feedback. :)
romfs has also a mailing list, and to date, it hasn't received any
traffic, so you are welcome to join it to discuss your ideas. :)
It's run by ezmlm, so you can subscribe to it by sending a message
Image padding과 남은 과제
163-194ROMFS 내부 header와 data는 16-byte 정렬이지만 많은 hardware device와 block driver는 block보다 작은 I/O를 처리하지 못한다. 이를 보완하려면 전체 filesystem 크기를 1024-byte boundary까지 padding해야 한다.
기능 추가를 제안할 때는 ROMFS의 가장 중요한 장점이 작은 코드라는 점을 고려해야 한다. 원문은 ROMFS mailing list 가입 주소로 `romfs-subscribe@shadow.banki.hu`를 기록한다.
원문이 남긴 기능·성능·이식성 질문이다.
쓰기 해법으로 compile-time 옵션이나 RAM disk용의 비슷하게 작은 writable filesystem을 제안한다. 읽기·실행 성능은 file data 대부분을 자연 정렬 경계에 재배치해 mm subsystem에 직접 mapping하는 방식으로 개선할 수 있다.
to romfs-subscribe@shadow.banki.hu, the content is irrelevant.
Pending issues:
- Permissions and owner information are pretty essential features of a
Un*x like system, but romfs does not provide the full possibilities.
I have never found this limiting, but others might.
- The file system is read only, so it can be very small, but in case
one would want to write _anything_ to a file system, he still needs
a writable file system, thus negating the size advantages. Possible
solutions: implement write access as a compile-time option, or a new,
similarly small writable filesystem for RAM disks.
- Since the files are only required to have alignment on a 16 byte
boundary, it is currently possibly suboptimal to read or execute files
from the filesystem. It might be resolved by reordering file data to
have most of it (i.e. except the start and the end) laying at "natural"
boundaries, thus it would be possible to directly map a big portion of
the file contents to the mm subsystem.
- Compression might be an useful feature, but memory is quite a
limiting factor in my eyes.
- Where it is used?
- Does it work on other architectures than intel and motorola?
Have fun,
Janos Farkas <chexum@shadow.banki.hu>
요약·해설
romfs.rst:1-194ROMFS는 초기 RAM disk와 read-only media를 위한 약 4KB 규모의 단순 파일시스템이다. 모든 구조를 16-byte boundary에 놓고 big-endian longword와 단순 checksum을 사용해 작은 kernel이 나머지 module을 늦게 적재하게 한다.
Parser는 `-rom1fs-` magic, full size, 첫 512바이트 checksum, volume name을 검증한 뒤 정렬된 file header를 따라가야 한다. Next pointer의 하위 bit에는 type과 executable 정보가 들어가며 `spec.info` 의미는 type마다 다르다.
Filesystem header에서 정렬된 file chain과 data로 이동한다.