xref: /kernel/linux/linux-6.6/fs/cramfs/README (revision 62306a36)
162306a36Sopenharmony_ciNotes on Filesystem Layout
262306a36Sopenharmony_ci--------------------------
362306a36Sopenharmony_ci
462306a36Sopenharmony_ciThese notes describe what mkcramfs generates.  Kernel requirements are
562306a36Sopenharmony_cia bit looser, e.g. it doesn't care if the <file_data> items are
662306a36Sopenharmony_ciswapped around (though it does care that directory entries (inodes) in
762306a36Sopenharmony_cia given directory are contiguous, as this is used by readdir).
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciAll data is currently in host-endian format; neither mkcramfs nor the
1062306a36Sopenharmony_cikernel ever do swabbing.  (See section `Block Size' below.)
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci<filesystem>:
1362306a36Sopenharmony_ci	<superblock>
1462306a36Sopenharmony_ci	<directory_structure>
1562306a36Sopenharmony_ci	<data>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci<superblock>: struct cramfs_super (see cramfs_fs.h).
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci<directory_structure>:
2062306a36Sopenharmony_ci	For each file:
2162306a36Sopenharmony_ci		struct cramfs_inode (see cramfs_fs.h).
2262306a36Sopenharmony_ci		Filename.  Not generally null-terminated, but it is
2362306a36Sopenharmony_ci		 null-padded to a multiple of 4 bytes.
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ciThe order of inode traversal is described as "width-first" (not to be
2662306a36Sopenharmony_ciconfused with breadth-first); i.e. like depth-first but listing all of
2762306a36Sopenharmony_cia directory's entries before recursing down its subdirectories: the
2862306a36Sopenharmony_cisame order as `ls -AUR' (but without the /^\..*:$/ directory header
2962306a36Sopenharmony_cilines); put another way, the same order as `find -type d -exec
3062306a36Sopenharmony_cils -AU1 {} \;'.
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ciBeginning in 2.4.7, directory entries are sorted.  This optimization
3362306a36Sopenharmony_ciallows cramfs_lookup to return more quickly when a filename does not
3462306a36Sopenharmony_ciexist, speeds up user-space directory sorts, etc.
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci<data>:
3762306a36Sopenharmony_ci	One <file_data> for each file that's either a symlink or a
3862306a36Sopenharmony_ci	 regular file of non-zero st_size.
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci<file_data>:
4162306a36Sopenharmony_ci	nblocks * <block_pointer>
4262306a36Sopenharmony_ci	 (where nblocks = (st_size - 1) / blksize + 1)
4362306a36Sopenharmony_ci	nblocks * <block>
4462306a36Sopenharmony_ci	padding to multiple of 4 bytes
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ciThe i'th <block_pointer> for a file stores the byte offset of the
4762306a36Sopenharmony_ci*end* of the i'th <block> (i.e. one past the last byte, which is the
4862306a36Sopenharmony_cisame as the start of the (i+1)'th <block> if there is one).  The first
4962306a36Sopenharmony_ci<block> immediately follows the last <block_pointer> for the file.
5062306a36Sopenharmony_ci<block_pointer>s are each 32 bits long.
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ciWhen the CRAMFS_FLAG_EXT_BLOCK_POINTERS capability bit is set, each
5362306a36Sopenharmony_ci<block_pointer>'s top bits may contain special flags as follows:
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ciCRAMFS_BLK_FLAG_UNCOMPRESSED (bit 31):
5662306a36Sopenharmony_ci	The block data is not compressed and should be copied verbatim.
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ciCRAMFS_BLK_FLAG_DIRECT_PTR (bit 30):
5962306a36Sopenharmony_ci	The <block_pointer> stores the actual block start offset and not
6062306a36Sopenharmony_ci	its end, shifted right by 2 bits. The block must therefore be
6162306a36Sopenharmony_ci	aligned to a 4-byte boundary. The block size is either blksize
6262306a36Sopenharmony_ci	if CRAMFS_BLK_FLAG_UNCOMPRESSED is also specified, otherwise
6362306a36Sopenharmony_ci	the compressed data length is included in the first 2 bytes of
6462306a36Sopenharmony_ci	the block data. This is used to allow discontiguous data layout
6562306a36Sopenharmony_ci	and specific data block alignments e.g. for XIP applications.
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ciThe order of <file_data>'s is a depth-first descent of the directory
6962306a36Sopenharmony_citree, i.e. the same order as `find -size +0 \( -type f -o -type l \)
7062306a36Sopenharmony_ci-print'.
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci<block>: The i'th <block> is the output of zlib's compress function
7462306a36Sopenharmony_ciapplied to the i'th blksize-sized chunk of the input data if the
7562306a36Sopenharmony_cicorresponding CRAMFS_BLK_FLAG_UNCOMPRESSED <block_ptr> bit is not set,
7662306a36Sopenharmony_ciotherwise it is the input data directly.
7762306a36Sopenharmony_ci(For the last <block> of the file, the input may of course be smaller.)
7862306a36Sopenharmony_ciEach <block> may be a different size.  (See <block_pointer> above.)
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci<block>s are merely byte-aligned, not generally u32-aligned.
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ciWhen CRAMFS_BLK_FLAG_DIRECT_PTR is specified then the corresponding
8362306a36Sopenharmony_ci<block> may be located anywhere and not necessarily contiguous with
8462306a36Sopenharmony_cithe previous/next blocks. In that case it is minimally u32-aligned.
8562306a36Sopenharmony_ciIf CRAMFS_BLK_FLAG_UNCOMPRESSED is also specified then the size is always
8662306a36Sopenharmony_ciblksize except for the last block which is limited by the file length.
8762306a36Sopenharmony_ciIf CRAMFS_BLK_FLAG_DIRECT_PTR is set and CRAMFS_BLK_FLAG_UNCOMPRESSED
8862306a36Sopenharmony_ciis not set then the first 2 bytes of the block contains the size of the
8962306a36Sopenharmony_ciremaining block data as this cannot be determined from the placement of
9062306a36Sopenharmony_cilogically adjacent blocks.
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ciHoles
9462306a36Sopenharmony_ci-----
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ciThis kernel supports cramfs holes (i.e. [efficient representation of]
9762306a36Sopenharmony_ciblocks in uncompressed data consisting entirely of NUL bytes), but by
9862306a36Sopenharmony_cidefault mkcramfs doesn't test for & create holes, since cramfs in
9962306a36Sopenharmony_cikernels up to at least 2.3.39 didn't support holes.  Run mkcramfs
10062306a36Sopenharmony_ciwith -z if you want it to create files that can have holes in them.
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ciTools
10462306a36Sopenharmony_ci-----
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ciThe cramfs user-space tools, including mkcramfs and cramfsck, are
10762306a36Sopenharmony_cilocated at <http://sourceforge.net/projects/cramfs/>.
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ciFuture Development
11162306a36Sopenharmony_ci==================
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ciBlock Size
11462306a36Sopenharmony_ci----------
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci(Block size in cramfs refers to the size of input data that is
11762306a36Sopenharmony_cicompressed at a time.  It's intended to be somewhere around
11862306a36Sopenharmony_ciPAGE_SIZE for cramfs_read_folio's convenience.)
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ciThe superblock ought to indicate the block size that the fs was
12162306a36Sopenharmony_ciwritten for, since comments in <linux/pagemap.h> indicate that
12262306a36Sopenharmony_ciPAGE_SIZE may grow in future (if I interpret the comment
12362306a36Sopenharmony_cicorrectly).
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ciCurrently, mkcramfs #define's PAGE_SIZE as 4096 and uses that
12662306a36Sopenharmony_cifor blksize, whereas Linux-2.3.39 uses its PAGE_SIZE, which in
12762306a36Sopenharmony_citurn is defined as PAGE_SIZE (which can be as large as 32KB on arm).
12862306a36Sopenharmony_ciThis discrepancy is a bug, though it's not clear which should be
12962306a36Sopenharmony_cichanged.
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ciOne option is to change mkcramfs to take its PAGE_SIZE from
13262306a36Sopenharmony_ci<asm/page.h>.  Personally I don't like this option, but it does
13362306a36Sopenharmony_cirequire the least amount of change: just change `#define
13462306a36Sopenharmony_ciPAGE_SIZE (4096)' to `#include <asm/page.h>'.  The disadvantage
13562306a36Sopenharmony_ciis that the generated cramfs cannot always be shared between different
13662306a36Sopenharmony_cikernels, not even necessarily kernels of the same architecture if
13762306a36Sopenharmony_ciPAGE_SIZE is subject to change between kernel versions
13862306a36Sopenharmony_ci(currently possible with arm and ia64).
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ciThe remaining options try to make cramfs more sharable.
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ciOne part of that is addressing endianness.  The two options here are
14362306a36Sopenharmony_ci`always use little-endian' (like ext2fs) or `writer chooses
14462306a36Sopenharmony_ciendianness; kernel adapts at runtime'.  Little-endian wins because of
14562306a36Sopenharmony_cicode simplicity and little CPU overhead even on big-endian machines.
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ciThe cost of swabbing is changing the code to use the le32_to_cpu
14862306a36Sopenharmony_cietc. macros as used by ext2fs.  We don't need to swab the compressed
14962306a36Sopenharmony_cidata, only the superblock, inodes and block pointers.
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ciThe other part of making cramfs more sharable is choosing a block
15362306a36Sopenharmony_cisize.  The options are:
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci  1. Always 4096 bytes.
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci  2. Writer chooses blocksize; kernel adapts but rejects blocksize >
15862306a36Sopenharmony_ci     PAGE_SIZE.
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci  3. Writer chooses blocksize; kernel adapts even to blocksize >
16162306a36Sopenharmony_ci     PAGE_SIZE.
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ciIt's easy enough to change the kernel to use a smaller value than
16462306a36Sopenharmony_ciPAGE_SIZE: just make cramfs_read_folio read multiple blocks.
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ciThe cost of option 1 is that kernels with a larger PAGE_SIZE
16762306a36Sopenharmony_civalue don't get as good compression as they can.
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ciThe cost of option 2 relative to option 1 is that the code uses
17062306a36Sopenharmony_civariables instead of #define'd constants.  The gain is that people
17162306a36Sopenharmony_ciwith kernels having larger PAGE_SIZE can make use of that if
17262306a36Sopenharmony_cithey don't mind their cramfs being inaccessible to kernels with
17362306a36Sopenharmony_cismaller PAGE_SIZE values.
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ciOption 3 is easy to implement if we don't mind being CPU-inefficient:
17662306a36Sopenharmony_cie.g. get read_folio to decompress to a buffer of size MAX_BLKSIZE (which
17762306a36Sopenharmony_cimust be no larger than 32KB) and discard what it doesn't need.
17862306a36Sopenharmony_ciGetting read_folio to read into all the covered pages is harder.
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ciThe main advantage of option 3 over 1, 2, is better compression.  The
18162306a36Sopenharmony_cicost is greater complexity.  Probably not worth it, but I hope someone
18262306a36Sopenharmony_ciwill disagree.  (If it is implemented, then I'll re-use that code in
18362306a36Sopenharmony_cie2compr.)
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ciAnother cost of 2 and 3 over 1 is making mkcramfs use a different
18762306a36Sopenharmony_ciblock size, but that just means adding and parsing a -b option.
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ciInode Size
19162306a36Sopenharmony_ci----------
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ciGiven that cramfs will probably be used for CDs etc. as well as just
19462306a36Sopenharmony_cisilicon ROMs, it might make sense to expand the inode a little from
19562306a36Sopenharmony_ciits current 12 bytes.  Inodes other than the root inode are followed
19662306a36Sopenharmony_ciby filename, so the expansion doesn't even have to be a multiple of 4
19762306a36Sopenharmony_cibytes.
198