1 // SPDX-License-Identifier: GPL-2.0+
4 static bool check_layout_compatibility(struct erofs_sb_info
*sbi
,
5 struct erofs_super_block
*dsb
)
7 const unsigned int feature
= le32_to_cpu(dsb
->feature_incompat
);
9 sbi
->feature_incompat
= feature
;
11 /* check if current kernel meets all mandatory requirements */
12 if (feature
& ~EROFS_ALL_FEATURE_INCOMPAT
) {
13 erofs_err("unidentified incompatible feature %x, please upgrade kernel version",
14 feature
& ~EROFS_ALL_FEATURE_INCOMPAT
);
20 static int erofs_init_devices(struct erofs_sb_info
*sbi
,
21 struct erofs_super_block
*dsb
)
23 unsigned int ondisk_extradevs
, i
;
26 sbi
->total_blocks
= sbi
->primarydevice_blocks
;
28 if (!erofs_sb_has_device_table())
31 ondisk_extradevs
= le16_to_cpu(dsb
->extra_devices
);
33 if (ondisk_extradevs
!= sbi
->extra_devices
) {
34 erofs_err("extra devices don't match (ondisk %u, given %u)",
35 ondisk_extradevs
, sbi
->extra_devices
);
38 if (!ondisk_extradevs
)
41 sbi
->device_id_mask
= roundup_pow_of_two(ondisk_extradevs
+ 1) - 1;
42 sbi
->devs
= calloc(ondisk_extradevs
, sizeof(*sbi
->devs
));
45 pos
= le16_to_cpu(dsb
->devt_slotoff
) * EROFS_DEVT_SLOT_SIZE
;
46 for (i
= 0; i
< ondisk_extradevs
; ++i
) {
47 struct erofs_deviceslot dis
;
50 ret
= erofs_dev_read(0, &dis
, pos
, sizeof(dis
));
56 sbi
->devs
[i
].mapped_blkaddr
= dis
.mapped_blkaddr
;
57 sbi
->total_blocks
+= dis
.blocks
;
58 pos
+= EROFS_DEVT_SLOT_SIZE
;
63 int erofs_read_superblock(void)
65 u8 data
[EROFS_MAX_BLOCK_SIZE
];
66 struct erofs_super_block
*dsb
;
69 ret
= erofs_blk_read(data
, 0, erofs_blknr(sizeof(data
)));
71 erofs_dbg("cannot read erofs superblock: %d", ret
);
74 dsb
= (struct erofs_super_block
*)(data
+ EROFS_SUPER_OFFSET
);
77 if (le32_to_cpu(dsb
->magic
) != EROFS_SUPER_MAGIC_V1
) {
78 erofs_dbg("cannot find valid erofs superblock");
82 sbi
.feature_compat
= le32_to_cpu(dsb
->feature_compat
);
84 sbi
.blkszbits
= dsb
->blkszbits
;
85 if (sbi
.blkszbits
< 9 ||
86 sbi
.blkszbits
> ilog2(EROFS_MAX_BLOCK_SIZE
)) {
87 erofs_err("blksize %llu isn't supported on this platform",
88 erofs_blksiz() | 0ULL);
90 } else if (!check_layout_compatibility(&sbi
, dsb
)) {
94 sbi
.primarydevice_blocks
= le32_to_cpu(dsb
->blocks
);
95 sbi
.meta_blkaddr
= le32_to_cpu(dsb
->meta_blkaddr
);
96 sbi
.xattr_blkaddr
= le32_to_cpu(dsb
->xattr_blkaddr
);
97 sbi
.islotbits
= EROFS_ISLOTBITS
;
98 sbi
.root_nid
= le16_to_cpu(dsb
->root_nid
);
99 sbi
.packed_nid
= le64_to_cpu(dsb
->packed_nid
);
100 sbi
.inos
= le64_to_cpu(dsb
->inos
);
101 sbi
.checksum
= le32_to_cpu(dsb
->checksum
);
103 sbi
.build_time
= le64_to_cpu(dsb
->build_time
);
104 sbi
.build_time_nsec
= le32_to_cpu(dsb
->build_time_nsec
);
106 memcpy(&sbi
.uuid
, dsb
->uuid
, sizeof(dsb
->uuid
));
107 return erofs_init_devices(&sbi
, dsb
);