]>
Commit | Line | Data |
---|---|---|
830613f8 HJ |
1 | /* SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0 */ |
2 | /* | |
3 | * EROFS (Enhanced ROM File System) on-disk format definition | |
4 | * | |
5 | * Copyright (C) 2017-2018 HUAWEI, Inc. | |
3a21e92f | 6 | * https://www.huawei.com/ |
830613f8 HJ |
7 | * Copyright (C) 2021, Alibaba Cloud |
8 | */ | |
9 | #ifndef __EROFS_FS_H | |
10 | #define __EROFS_FS_H | |
11 | ||
12 | #include <asm/unaligned.h> | |
13 | #include <fs.h> | |
14 | #include <part.h> | |
15 | #include <stdint.h> | |
16 | #include <compiler.h> | |
17 | ||
18 | #define EROFS_SUPER_MAGIC_V1 0xE0F5E1E2 | |
19 | #define EROFS_SUPER_OFFSET 1024 | |
20 | ||
3a21e92f YZ |
21 | #define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001 |
22 | #define EROFS_FEATURE_COMPAT_MTIME 0x00000002 | |
830613f8 HJ |
23 | |
24 | /* | |
25 | * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should | |
26 | * be incompatible with this kernel version. | |
27 | */ | |
3a21e92f | 28 | #define EROFS_FEATURE_INCOMPAT_ZERO_PADDING 0x00000001 |
830613f8 HJ |
29 | #define EROFS_FEATURE_INCOMPAT_COMPR_CFGS 0x00000002 |
30 | #define EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER 0x00000002 | |
31 | #define EROFS_FEATURE_INCOMPAT_CHUNKED_FILE 0x00000004 | |
32 | #define EROFS_FEATURE_INCOMPAT_DEVICE_TABLE 0x00000008 | |
3a21e92f YZ |
33 | #define EROFS_FEATURE_INCOMPAT_COMPR_HEAD2 0x00000008 |
34 | #define EROFS_FEATURE_INCOMPAT_ZTAILPACKING 0x00000010 | |
35 | #define EROFS_FEATURE_INCOMPAT_FRAGMENTS 0x00000020 | |
36 | #define EROFS_FEATURE_INCOMPAT_DEDUPE 0x00000020 | |
37 | #define EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES 0x00000040 | |
830613f8 | 38 | #define EROFS_ALL_FEATURE_INCOMPAT \ |
3a21e92f | 39 | (EROFS_FEATURE_INCOMPAT_ZERO_PADDING | \ |
830613f8 HJ |
40 | EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \ |
41 | EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER | \ | |
42 | EROFS_FEATURE_INCOMPAT_CHUNKED_FILE | \ | |
3a21e92f YZ |
43 | EROFS_FEATURE_INCOMPAT_DEVICE_TABLE | \ |
44 | EROFS_FEATURE_INCOMPAT_COMPR_HEAD2 | \ | |
45 | EROFS_FEATURE_INCOMPAT_ZTAILPACKING | \ | |
46 | EROFS_FEATURE_INCOMPAT_FRAGMENTS | \ | |
47 | EROFS_FEATURE_INCOMPAT_DEDUPE | \ | |
48 | EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES) | |
830613f8 HJ |
49 | |
50 | #define EROFS_SB_EXTSLOT_SIZE 16 | |
51 | ||
52 | struct erofs_deviceslot { | |
3a21e92f YZ |
53 | u8 tag[64]; /* digest(sha256), etc. */ |
54 | __le32 blocks; /* total fs blocks of this device */ | |
55 | __le32 mapped_blkaddr; /* map starting at mapped_blkaddr */ | |
830613f8 HJ |
56 | u8 reserved[56]; |
57 | }; | |
58 | ||
59 | #define EROFS_DEVT_SLOT_SIZE sizeof(struct erofs_deviceslot) | |
60 | ||
61 | /* erofs on-disk super block (currently 128 bytes) */ | |
62 | struct erofs_super_block { | |
63 | __le32 magic; /* file system magic number */ | |
64 | __le32 checksum; /* crc32c(super_block) */ | |
65 | __le32 feature_compat; | |
3a21e92f | 66 | __u8 blkszbits; /* filesystem block size in bit shift */ |
830613f8 HJ |
67 | __u8 sb_extslots; /* superblock size = 128 + sb_extslots * 16 */ |
68 | ||
69 | __le16 root_nid; /* nid of root directory */ | |
70 | __le64 inos; /* total valid ino # (== f_files - f_favail) */ | |
71 | ||
3a21e92f YZ |
72 | __le64 build_time; /* compact inode time derivation */ |
73 | __le32 build_time_nsec; /* compact inode time derivation in ns scale */ | |
830613f8 HJ |
74 | __le32 blocks; /* used for statfs */ |
75 | __le32 meta_blkaddr; /* start block address of metadata area */ | |
76 | __le32 xattr_blkaddr; /* start block address of shared xattr area */ | |
77 | __u8 uuid[16]; /* 128-bit uuid for volume */ | |
78 | __u8 volume_name[16]; /* volume name */ | |
79 | __le32 feature_incompat; | |
80 | union { | |
81 | /* bitmap for available compression algorithms */ | |
82 | __le16 available_compr_algs; | |
83 | /* customized sliding window size instead of 64k by default */ | |
84 | __le16 lz4_max_distance; | |
85 | } __packed u1; | |
86 | __le16 extra_devices; /* # of devices besides the primary device */ | |
87 | __le16 devt_slotoff; /* startoff = devt_slotoff * devt_slotsize */ | |
3a21e92f YZ |
88 | __u8 dirblkbits; /* directory block size in bit shift */ |
89 | __u8 xattr_prefix_count; /* # of long xattr name prefixes */ | |
90 | __le32 xattr_prefix_start; /* start of long xattr prefixes */ | |
91 | __le64 packed_nid; /* nid of the special packed inode */ | |
92 | __u8 reserved2[24]; | |
830613f8 HJ |
93 | }; |
94 | ||
95 | /* | |
3a21e92f YZ |
96 | * EROFS inode datalayout (i_format in on-disk inode): |
97 | * 0 - uncompressed flat inode without tail-packing inline data: | |
98 | * 1 - compressed inode with non-compact indexes: | |
99 | * 2 - uncompressed flat inode with tail-packing inline data: | |
100 | * 3 - compressed inode with compact indexes: | |
101 | * 4 - chunk-based inode with (optional) multi-device support: | |
830613f8 HJ |
102 | * 5~7 - reserved |
103 | */ | |
104 | enum { | |
105 | EROFS_INODE_FLAT_PLAIN = 0, | |
3a21e92f | 106 | EROFS_INODE_COMPRESSED_FULL = 1, |
830613f8 | 107 | EROFS_INODE_FLAT_INLINE = 2, |
3a21e92f | 108 | EROFS_INODE_COMPRESSED_COMPACT = 3, |
830613f8 HJ |
109 | EROFS_INODE_CHUNK_BASED = 4, |
110 | EROFS_INODE_DATALAYOUT_MAX | |
111 | }; | |
112 | ||
113 | static inline bool erofs_inode_is_data_compressed(unsigned int datamode) | |
114 | { | |
3a21e92f YZ |
115 | return datamode == EROFS_INODE_COMPRESSED_COMPACT || |
116 | datamode == EROFS_INODE_COMPRESSED_FULL; | |
830613f8 HJ |
117 | } |
118 | ||
3a21e92f | 119 | /* bit definitions of inode i_format */ |
830613f8 HJ |
120 | #define EROFS_I_VERSION_BITS 1 |
121 | #define EROFS_I_DATALAYOUT_BITS 3 | |
122 | ||
123 | #define EROFS_I_VERSION_BIT 0 | |
124 | #define EROFS_I_DATALAYOUT_BIT 1 | |
125 | ||
126 | #define EROFS_I_ALL \ | |
127 | ((1 << (EROFS_I_DATALAYOUT_BIT + EROFS_I_DATALAYOUT_BITS)) - 1) | |
128 | ||
129 | /* indicate chunk blkbits, thus 'chunksize = blocksize << chunk blkbits' */ | |
130 | #define EROFS_CHUNK_FORMAT_BLKBITS_MASK 0x001F | |
131 | /* with chunk indexes or just a 4-byte blkaddr array */ | |
132 | #define EROFS_CHUNK_FORMAT_INDEXES 0x0020 | |
133 | ||
134 | #define EROFS_CHUNK_FORMAT_ALL \ | |
135 | (EROFS_CHUNK_FORMAT_BLKBITS_MASK | EROFS_CHUNK_FORMAT_INDEXES) | |
136 | ||
3a21e92f YZ |
137 | /* 32-byte on-disk inode */ |
138 | #define EROFS_INODE_LAYOUT_COMPACT 0 | |
139 | /* 64-byte on-disk inode */ | |
140 | #define EROFS_INODE_LAYOUT_EXTENDED 1 | |
141 | ||
830613f8 HJ |
142 | struct erofs_inode_chunk_info { |
143 | __le16 format; /* chunk blkbits, etc. */ | |
144 | __le16 reserved; | |
145 | }; | |
146 | ||
3a21e92f YZ |
147 | union erofs_inode_i_u { |
148 | /* total compressed blocks for compressed inodes */ | |
149 | __le32 compressed_blocks; | |
150 | ||
151 | /* block address for uncompressed flat inodes */ | |
152 | __le32 raw_blkaddr; | |
153 | ||
154 | /* for device files, used to indicate old/new device # */ | |
155 | __le32 rdev; | |
156 | ||
157 | /* for chunk-based files, it contains the summary info */ | |
158 | struct erofs_inode_chunk_info c; | |
159 | }; | |
160 | ||
830613f8 HJ |
161 | /* 32-byte reduced form of an ondisk inode */ |
162 | struct erofs_inode_compact { | |
163 | __le16 i_format; /* inode format hints */ | |
164 | ||
165 | /* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ | |
166 | __le16 i_xattr_icount; | |
167 | __le16 i_mode; | |
168 | __le16 i_nlink; | |
169 | __le32 i_size; | |
170 | __le32 i_reserved; | |
3a21e92f | 171 | union erofs_inode_i_u i_u; |
830613f8 | 172 | |
3a21e92f | 173 | __le32 i_ino; /* only used for 32-bit stat compatibility */ |
830613f8 HJ |
174 | __le16 i_uid; |
175 | __le16 i_gid; | |
176 | __le32 i_reserved2; | |
177 | }; | |
178 | ||
830613f8 HJ |
179 | /* 64-byte complete form of an ondisk inode */ |
180 | struct erofs_inode_extended { | |
181 | __le16 i_format; /* inode format hints */ | |
182 | ||
183 | /* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ | |
184 | __le16 i_xattr_icount; | |
185 | __le16 i_mode; | |
186 | __le16 i_reserved; | |
187 | __le64 i_size; | |
3a21e92f | 188 | union erofs_inode_i_u i_u; |
830613f8 | 189 | |
3a21e92f | 190 | __le32 i_ino; /* only used for 32-bit stat compatibility */ |
830613f8 HJ |
191 | __le32 i_uid; |
192 | __le32 i_gid; | |
3a21e92f YZ |
193 | __le64 i_mtime; |
194 | __le32 i_mtime_nsec; | |
830613f8 HJ |
195 | __le32 i_nlink; |
196 | __u8 i_reserved2[16]; | |
197 | }; | |
198 | ||
830613f8 HJ |
199 | /* |
200 | * inline xattrs (n == i_xattr_icount): | |
201 | * erofs_xattr_ibody_header(1) + (n - 1) * 4 bytes | |
202 | * 12 bytes / \ | |
203 | * / \ | |
204 | * /-----------------------\ | |
205 | * | erofs_xattr_entries+ | | |
206 | * +-----------------------+ | |
207 | * inline xattrs must starts in erofs_xattr_ibody_header, | |
208 | * for read-only fs, no need to introduce h_refcount | |
209 | */ | |
210 | struct erofs_xattr_ibody_header { | |
211 | __le32 h_reserved; | |
212 | __u8 h_shared_count; | |
213 | __u8 h_reserved2[7]; | |
214 | __le32 h_shared_xattrs[0]; /* shared xattr id array */ | |
215 | }; | |
216 | ||
217 | /* Name indexes */ | |
218 | #define EROFS_XATTR_INDEX_USER 1 | |
219 | #define EROFS_XATTR_INDEX_POSIX_ACL_ACCESS 2 | |
220 | #define EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT 3 | |
221 | #define EROFS_XATTR_INDEX_TRUSTED 4 | |
222 | #define EROFS_XATTR_INDEX_LUSTRE 5 | |
223 | #define EROFS_XATTR_INDEX_SECURITY 6 | |
224 | ||
3a21e92f YZ |
225 | /* |
226 | * bit 7 of e_name_index is set when it refers to a long xattr name prefix, | |
227 | * while the remained lower bits represent the index of the prefix. | |
228 | */ | |
229 | #define EROFS_XATTR_LONG_PREFIX 0x80 | |
230 | #define EROFS_XATTR_LONG_PREFIX_MASK 0x7f | |
231 | ||
830613f8 HJ |
232 | /* xattr entry (for both inline & shared xattrs) */ |
233 | struct erofs_xattr_entry { | |
234 | __u8 e_name_len; /* length of name */ | |
235 | __u8 e_name_index; /* attribute name index */ | |
236 | __le16 e_value_size; /* size of attribute value */ | |
237 | /* followed by e_name and e_value */ | |
238 | char e_name[0]; /* attribute name */ | |
239 | }; | |
240 | ||
3a21e92f YZ |
241 | /* long xattr name prefix */ |
242 | struct erofs_xattr_long_prefix { | |
243 | __u8 base_index; /* short xattr name prefix index */ | |
244 | char infix[0]; /* infix apart from short prefix */ | |
245 | }; | |
246 | ||
830613f8 HJ |
247 | static inline unsigned int erofs_xattr_ibody_size(__le16 i_xattr_icount) |
248 | { | |
249 | if (!i_xattr_icount) | |
250 | return 0; | |
251 | ||
252 | return sizeof(struct erofs_xattr_ibody_header) + | |
253 | sizeof(__u32) * (le16_to_cpu(i_xattr_icount) - 1); | |
254 | } | |
255 | ||
256 | #define EROFS_XATTR_ALIGN(size) round_up(size, sizeof(struct erofs_xattr_entry)) | |
257 | ||
258 | static inline unsigned int erofs_xattr_entry_size(struct erofs_xattr_entry *e) | |
259 | { | |
260 | return EROFS_XATTR_ALIGN(sizeof(struct erofs_xattr_entry) + | |
261 | e->e_name_len + le16_to_cpu(e->e_value_size)); | |
262 | } | |
263 | ||
264 | /* represent a zeroed chunk (hole) */ | |
265 | #define EROFS_NULL_ADDR -1 | |
266 | ||
267 | /* 4-byte block address array */ | |
268 | #define EROFS_BLOCK_MAP_ENTRY_SIZE sizeof(__le32) | |
269 | ||
270 | /* 8-byte inode chunk indexes */ | |
271 | struct erofs_inode_chunk_index { | |
272 | __le16 advise; /* always 0, don't care for now */ | |
273 | __le16 device_id; /* back-end storage id (with bits masked) */ | |
274 | __le32 blkaddr; /* start block address of this inode chunk */ | |
275 | }; | |
276 | ||
3a21e92f YZ |
277 | /* dirent sorts in alphabet order, thus we can do binary search */ |
278 | struct erofs_dirent { | |
279 | __le64 nid; /* node number */ | |
280 | __le16 nameoff; /* start offset of file name */ | |
281 | __u8 file_type; /* file type */ | |
282 | __u8 reserved; /* reserved */ | |
283 | } __packed; | |
284 | ||
285 | /* file types used in inode_info->flags */ | |
286 | enum { | |
287 | EROFS_FT_UNKNOWN, | |
288 | EROFS_FT_REG_FILE, | |
289 | EROFS_FT_DIR, | |
290 | EROFS_FT_CHRDEV, | |
291 | EROFS_FT_BLKDEV, | |
292 | EROFS_FT_FIFO, | |
293 | EROFS_FT_SOCK, | |
294 | EROFS_FT_SYMLINK, | |
295 | EROFS_FT_MAX | |
296 | }; | |
297 | ||
298 | #define EROFS_NAME_LEN 255 | |
299 | ||
830613f8 HJ |
300 | /* maximum supported size of a physical compression cluster */ |
301 | #define Z_EROFS_PCLUSTER_MAX_SIZE (1024 * 1024) | |
302 | ||
303 | /* available compression algorithm types (for h_algorithmtype) */ | |
304 | enum { | |
305 | Z_EROFS_COMPRESSION_LZ4 = 0, | |
306 | Z_EROFS_COMPRESSION_LZMA = 1, | |
307 | Z_EROFS_COMPRESSION_MAX | |
308 | }; | |
309 | ||
3a21e92f | 310 | #define Z_EROFS_ALL_COMPR_ALGS ((1 << Z_EROFS_COMPRESSION_MAX) - 1) |
830613f8 HJ |
311 | |
312 | /* 14 bytes (+ length field = 16 bytes) */ | |
313 | struct z_erofs_lz4_cfgs { | |
314 | __le16 max_distance; | |
315 | __le16 max_pclusterblks; | |
316 | u8 reserved[10]; | |
317 | } __packed; | |
318 | ||
319 | /* 14 bytes (+ length field = 16 bytes) */ | |
320 | struct z_erofs_lzma_cfgs { | |
321 | __le32 dict_size; | |
322 | __le16 format; | |
323 | u8 reserved[8]; | |
324 | } __packed; | |
3a21e92f | 325 | |
830613f8 HJ |
326 | #define Z_EROFS_LZMA_MAX_DICT_SIZE (8 * Z_EROFS_PCLUSTER_MAX_SIZE) |
327 | ||
328 | /* | |
329 | * bit 0 : COMPACTED_2B indexes (0 - off; 1 - on) | |
330 | * e.g. for 4k logical cluster size, 4B if compacted 2B is off; | |
331 | * (4B) + 2B + (4B) if compacted 2B is on. | |
332 | * bit 1 : HEAD1 big pcluster (0 - off; 1 - on) | |
333 | * bit 2 : HEAD2 big pcluster (0 - off; 1 - on) | |
3a21e92f YZ |
334 | * bit 3 : tailpacking inline pcluster (0 - off; 1 - on) |
335 | * bit 4 : interlaced plain pcluster (0 - off; 1 - on) | |
336 | * bit 5 : fragment pcluster (0 - off; 1 - on) | |
830613f8 HJ |
337 | */ |
338 | #define Z_EROFS_ADVISE_COMPACTED_2B 0x0001 | |
339 | #define Z_EROFS_ADVISE_BIG_PCLUSTER_1 0x0002 | |
340 | #define Z_EROFS_ADVISE_BIG_PCLUSTER_2 0x0004 | |
3a21e92f YZ |
341 | #define Z_EROFS_ADVISE_INLINE_PCLUSTER 0x0008 |
342 | #define Z_EROFS_ADVISE_INTERLACED_PCLUSTER 0x0010 | |
343 | #define Z_EROFS_ADVISE_FRAGMENT_PCLUSTER 0x0020 | |
830613f8 | 344 | |
3a21e92f | 345 | #define Z_EROFS_FRAGMENT_INODE_BIT 7 |
830613f8 | 346 | struct z_erofs_map_header { |
3a21e92f YZ |
347 | union { |
348 | /* fragment data offset in the packed inode */ | |
349 | __le32 h_fragmentoff; | |
350 | struct { | |
351 | __le16 h_reserved1; | |
352 | /* indicates the encoded size of tailpacking data */ | |
353 | __le16 h_idata_size; | |
354 | }; | |
355 | }; | |
830613f8 HJ |
356 | __le16 h_advise; |
357 | /* | |
358 | * bit 0-3 : algorithm type of head 1 (logical cluster type 01); | |
359 | * bit 4-7 : algorithm type of head 2 (logical cluster type 11). | |
360 | */ | |
361 | __u8 h_algorithmtype; | |
362 | /* | |
363 | * bit 0-2 : logical cluster bits - 12, e.g. 0 for 4096; | |
3a21e92f YZ |
364 | * bit 3-6 : reserved; |
365 | * bit 7 : move the whole file into packed inode or not. | |
830613f8 HJ |
366 | */ |
367 | __u8 h_clusterbits; | |
368 | }; | |
369 | ||
830613f8 | 370 | /* |
3a21e92f YZ |
371 | * On-disk logical cluster type: |
372 | * 0 - literal (uncompressed) lcluster | |
373 | * 1,3 - compressed lcluster (for HEAD lclusters) | |
374 | * 2 - compressed lcluster (for NONHEAD lclusters) | |
830613f8 HJ |
375 | * |
376 | * In detail, | |
3a21e92f | 377 | * 0 - literal (uncompressed) lcluster, |
830613f8 | 378 | * di_advise = 0 |
3a21e92f YZ |
379 | * di_clusterofs = the literal data offset of the lcluster |
380 | * di_blkaddr = the blkaddr of the literal pcluster | |
830613f8 | 381 | * |
3a21e92f YZ |
382 | * 1,3 - compressed lcluster (for HEAD lclusters) |
383 | * di_advise = 1 or 3 | |
384 | * di_clusterofs = the decompressed data offset of the lcluster | |
385 | * di_blkaddr = the blkaddr of the compressed pcluster | |
830613f8 | 386 | * |
3a21e92f | 387 | * 2 - compressed lcluster (for NONHEAD lclusters) |
830613f8 HJ |
388 | * di_advise = 2 |
389 | * di_clusterofs = | |
3a21e92f YZ |
390 | * the decompressed data offset in its own HEAD lcluster |
391 | * di_u.delta[0] = distance to this HEAD lcluster | |
392 | * di_u.delta[1] = distance to the next HEAD lcluster | |
830613f8 HJ |
393 | */ |
394 | enum { | |
3a21e92f YZ |
395 | Z_EROFS_LCLUSTER_TYPE_PLAIN = 0, |
396 | Z_EROFS_LCLUSTER_TYPE_HEAD1 = 1, | |
397 | Z_EROFS_LCLUSTER_TYPE_NONHEAD = 2, | |
398 | Z_EROFS_LCLUSTER_TYPE_HEAD2 = 3, | |
399 | Z_EROFS_LCLUSTER_TYPE_MAX | |
830613f8 HJ |
400 | }; |
401 | ||
3a21e92f YZ |
402 | #define Z_EROFS_LI_LCLUSTER_TYPE_BITS 2 |
403 | #define Z_EROFS_LI_LCLUSTER_TYPE_BIT 0 | |
404 | ||
405 | /* (noncompact only, HEAD) This pcluster refers to partial decompressed data */ | |
406 | #define Z_EROFS_LI_PARTIAL_REF (1 << 15) | |
830613f8 HJ |
407 | |
408 | /* | |
409 | * D0_CBLKCNT will be marked _only_ at the 1st non-head lcluster to store the | |
410 | * compressed block count of a compressed extent (in logical clusters, aka. | |
411 | * block count of a pcluster). | |
412 | */ | |
3a21e92f | 413 | #define Z_EROFS_LI_D0_CBLKCNT (1 << 11) |
830613f8 | 414 | |
3a21e92f | 415 | struct z_erofs_lcluster_index { |
830613f8 | 416 | __le16 di_advise; |
3a21e92f | 417 | /* where to decompress in the head lcluster */ |
830613f8 HJ |
418 | __le16 di_clusterofs; |
419 | ||
420 | union { | |
3a21e92f | 421 | /* for the HEAD lclusters */ |
830613f8 HJ |
422 | __le32 blkaddr; |
423 | /* | |
3a21e92f YZ |
424 | * for the NONHEAD lclusters |
425 | * [0] - distance to its HEAD lcluster | |
426 | * [1] - distance to the next HEAD lcluster | |
830613f8 HJ |
427 | */ |
428 | __le16 delta[2]; | |
429 | } di_u; | |
430 | }; | |
431 | ||
3a21e92f YZ |
432 | #define Z_EROFS_FULL_INDEX_ALIGN(end) \ |
433 | (round_up(end, 8) + sizeof(struct z_erofs_map_header) + 8) | |
830613f8 HJ |
434 | |
435 | /* check the EROFS on-disk layout strictly at compile time */ | |
436 | static inline void erofs_check_ondisk_layout_definitions(void) | |
437 | { | |
3a21e92f YZ |
438 | const __le64 fmh __maybe_unused = |
439 | *(__le64 *)&(struct z_erofs_map_header) { | |
440 | .h_clusterbits = 1 << Z_EROFS_FRAGMENT_INODE_BIT | |
441 | }; | |
442 | ||
830613f8 HJ |
443 | BUILD_BUG_ON(sizeof(struct erofs_super_block) != 128); |
444 | BUILD_BUG_ON(sizeof(struct erofs_inode_compact) != 32); | |
445 | BUILD_BUG_ON(sizeof(struct erofs_inode_extended) != 64); | |
446 | BUILD_BUG_ON(sizeof(struct erofs_xattr_ibody_header) != 12); | |
447 | BUILD_BUG_ON(sizeof(struct erofs_xattr_entry) != 4); | |
448 | BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_info) != 4); | |
449 | BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != 8); | |
450 | BUILD_BUG_ON(sizeof(struct z_erofs_map_header) != 8); | |
3a21e92f | 451 | BUILD_BUG_ON(sizeof(struct z_erofs_lcluster_index) != 8); |
830613f8 HJ |
452 | BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12); |
453 | /* keep in sync between 2 index structures for better extendibility */ | |
454 | BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != | |
3a21e92f | 455 | sizeof(struct z_erofs_lcluster_index)); |
830613f8 HJ |
456 | BUILD_BUG_ON(sizeof(struct erofs_deviceslot) != 128); |
457 | ||
3a21e92f YZ |
458 | BUILD_BUG_ON(BIT(Z_EROFS_LI_LCLUSTER_TYPE_BITS) < |
459 | Z_EROFS_LCLUSTER_TYPE_MAX - 1); | |
460 | /* exclude old compiler versions like gcc 7.5.0 */ | |
461 | BUILD_BUG_ON(__builtin_constant_p(fmh) ? | |
462 | fmh != cpu_to_le64(1ULL << 63) : 0); | |
830613f8 HJ |
463 | } |
464 | ||
465 | #endif |