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));
43 pos = le16_to_cpu(dsb->devt_slotoff) * EROFS_DEVT_SLOT_SIZE;
44 for (i = 0; i < ondisk_extradevs; ++i) {
45 struct erofs_deviceslot dis;
48 ret = erofs_dev_read(0, &dis, pos, sizeof(dis));
52 sbi->devs[i].mapped_blkaddr = dis.mapped_blkaddr;
53 sbi->total_blocks += dis.blocks;
54 pos += EROFS_DEVT_SLOT_SIZE;
59 int erofs_read_superblock(void)
61 char data[EROFS_BLKSIZ];
62 struct erofs_super_block *dsb;
63 unsigned int blkszbits;
66 ret = erofs_blk_read(data, 0, 1);
68 erofs_err("cannot read erofs superblock: %d", ret);
71 dsb = (struct erofs_super_block *)(data + EROFS_SUPER_OFFSET);
74 if (le32_to_cpu(dsb->magic) != EROFS_SUPER_MAGIC_V1) {
75 erofs_err("cannot find valid erofs superblock");
79 sbi.feature_compat = le32_to_cpu(dsb->feature_compat);
81 blkszbits = dsb->blkszbits;
82 /* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */
83 if (blkszbits != LOG_BLOCK_SIZE) {
84 erofs_err("blksize %u isn't supported on this platform",
89 if (!check_layout_compatibility(&sbi, dsb))
92 sbi.primarydevice_blocks = le32_to_cpu(dsb->blocks);
93 sbi.meta_blkaddr = le32_to_cpu(dsb->meta_blkaddr);
94 sbi.xattr_blkaddr = le32_to_cpu(dsb->xattr_blkaddr);
95 sbi.islotbits = EROFS_ISLOTBITS;
96 sbi.root_nid = le16_to_cpu(dsb->root_nid);
97 sbi.inos = le64_to_cpu(dsb->inos);
98 sbi.checksum = le32_to_cpu(dsb->checksum);
100 sbi.build_time = le64_to_cpu(dsb->build_time);
101 sbi.build_time_nsec = le32_to_cpu(dsb->build_time_nsec);
103 memcpy(&sbi.uuid, dsb->uuid, sizeof(dsb->uuid));
104 return erofs_init_devices(&sbi, dsb);