1*33b1fccfSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2*33b1fccfSAndroid Build Coastguard Worker /*
3*33b1fccfSAndroid Build Coastguard Worker * Created by Li Guifu <[email protected]>
4*33b1fccfSAndroid Build Coastguard Worker */
5*33b1fccfSAndroid Build Coastguard Worker #include <string.h>
6*33b1fccfSAndroid Build Coastguard Worker #include <stdlib.h>
7*33b1fccfSAndroid Build Coastguard Worker #include "erofs/print.h"
8*33b1fccfSAndroid Build Coastguard Worker #include "erofs/xattr.h"
9*33b1fccfSAndroid Build Coastguard Worker #include "erofs/cache.h"
10*33b1fccfSAndroid Build Coastguard Worker
check_layout_compatibility(struct erofs_sb_info * sbi,struct erofs_super_block * dsb)11*33b1fccfSAndroid Build Coastguard Worker static bool check_layout_compatibility(struct erofs_sb_info *sbi,
12*33b1fccfSAndroid Build Coastguard Worker struct erofs_super_block *dsb)
13*33b1fccfSAndroid Build Coastguard Worker {
14*33b1fccfSAndroid Build Coastguard Worker const unsigned int feature = le32_to_cpu(dsb->feature_incompat);
15*33b1fccfSAndroid Build Coastguard Worker
16*33b1fccfSAndroid Build Coastguard Worker sbi->feature_incompat = feature;
17*33b1fccfSAndroid Build Coastguard Worker
18*33b1fccfSAndroid Build Coastguard Worker /* check if current kernel meets all mandatory requirements */
19*33b1fccfSAndroid Build Coastguard Worker if (feature & ~EROFS_ALL_FEATURE_INCOMPAT) {
20*33b1fccfSAndroid Build Coastguard Worker erofs_err("unidentified incompatible feature %x, please upgrade kernel version",
21*33b1fccfSAndroid Build Coastguard Worker feature & ~EROFS_ALL_FEATURE_INCOMPAT);
22*33b1fccfSAndroid Build Coastguard Worker return false;
23*33b1fccfSAndroid Build Coastguard Worker }
24*33b1fccfSAndroid Build Coastguard Worker return true;
25*33b1fccfSAndroid Build Coastguard Worker }
26*33b1fccfSAndroid Build Coastguard Worker
erofs_init_devices(struct erofs_sb_info * sbi,struct erofs_super_block * dsb)27*33b1fccfSAndroid Build Coastguard Worker static int erofs_init_devices(struct erofs_sb_info *sbi,
28*33b1fccfSAndroid Build Coastguard Worker struct erofs_super_block *dsb)
29*33b1fccfSAndroid Build Coastguard Worker {
30*33b1fccfSAndroid Build Coastguard Worker unsigned int ondisk_extradevs, i;
31*33b1fccfSAndroid Build Coastguard Worker erofs_off_t pos;
32*33b1fccfSAndroid Build Coastguard Worker
33*33b1fccfSAndroid Build Coastguard Worker sbi->total_blocks = sbi->primarydevice_blocks;
34*33b1fccfSAndroid Build Coastguard Worker
35*33b1fccfSAndroid Build Coastguard Worker if (!erofs_sb_has_device_table(sbi))
36*33b1fccfSAndroid Build Coastguard Worker ondisk_extradevs = 0;
37*33b1fccfSAndroid Build Coastguard Worker else
38*33b1fccfSAndroid Build Coastguard Worker ondisk_extradevs = le16_to_cpu(dsb->extra_devices);
39*33b1fccfSAndroid Build Coastguard Worker
40*33b1fccfSAndroid Build Coastguard Worker if (sbi->extra_devices &&
41*33b1fccfSAndroid Build Coastguard Worker ondisk_extradevs != sbi->extra_devices) {
42*33b1fccfSAndroid Build Coastguard Worker erofs_err("extra devices don't match (ondisk %u, given %u)",
43*33b1fccfSAndroid Build Coastguard Worker ondisk_extradevs, sbi->extra_devices);
44*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
45*33b1fccfSAndroid Build Coastguard Worker }
46*33b1fccfSAndroid Build Coastguard Worker if (!ondisk_extradevs)
47*33b1fccfSAndroid Build Coastguard Worker return 0;
48*33b1fccfSAndroid Build Coastguard Worker
49*33b1fccfSAndroid Build Coastguard Worker sbi->extra_devices = ondisk_extradevs;
50*33b1fccfSAndroid Build Coastguard Worker sbi->device_id_mask = roundup_pow_of_two(ondisk_extradevs + 1) - 1;
51*33b1fccfSAndroid Build Coastguard Worker sbi->devs = calloc(ondisk_extradevs, sizeof(*sbi->devs));
52*33b1fccfSAndroid Build Coastguard Worker if (!sbi->devs)
53*33b1fccfSAndroid Build Coastguard Worker return -ENOMEM;
54*33b1fccfSAndroid Build Coastguard Worker pos = le16_to_cpu(dsb->devt_slotoff) * EROFS_DEVT_SLOT_SIZE;
55*33b1fccfSAndroid Build Coastguard Worker for (i = 0; i < ondisk_extradevs; ++i) {
56*33b1fccfSAndroid Build Coastguard Worker struct erofs_deviceslot dis;
57*33b1fccfSAndroid Build Coastguard Worker int ret;
58*33b1fccfSAndroid Build Coastguard Worker
59*33b1fccfSAndroid Build Coastguard Worker ret = erofs_dev_read(sbi, 0, &dis, pos, sizeof(dis));
60*33b1fccfSAndroid Build Coastguard Worker if (ret < 0) {
61*33b1fccfSAndroid Build Coastguard Worker free(sbi->devs);
62*33b1fccfSAndroid Build Coastguard Worker sbi->devs = NULL;
63*33b1fccfSAndroid Build Coastguard Worker return ret;
64*33b1fccfSAndroid Build Coastguard Worker }
65*33b1fccfSAndroid Build Coastguard Worker
66*33b1fccfSAndroid Build Coastguard Worker sbi->devs[i].mapped_blkaddr = le32_to_cpu(dis.mapped_blkaddr);
67*33b1fccfSAndroid Build Coastguard Worker sbi->devs[i].blocks = le32_to_cpu(dis.blocks);
68*33b1fccfSAndroid Build Coastguard Worker memcpy(sbi->devs[i].tag, dis.tag, sizeof(dis.tag));
69*33b1fccfSAndroid Build Coastguard Worker sbi->total_blocks += sbi->devs[i].blocks;
70*33b1fccfSAndroid Build Coastguard Worker pos += EROFS_DEVT_SLOT_SIZE;
71*33b1fccfSAndroid Build Coastguard Worker }
72*33b1fccfSAndroid Build Coastguard Worker return 0;
73*33b1fccfSAndroid Build Coastguard Worker }
74*33b1fccfSAndroid Build Coastguard Worker
erofs_read_superblock(struct erofs_sb_info * sbi)75*33b1fccfSAndroid Build Coastguard Worker int erofs_read_superblock(struct erofs_sb_info *sbi)
76*33b1fccfSAndroid Build Coastguard Worker {
77*33b1fccfSAndroid Build Coastguard Worker u8 data[EROFS_MAX_BLOCK_SIZE];
78*33b1fccfSAndroid Build Coastguard Worker struct erofs_super_block *dsb;
79*33b1fccfSAndroid Build Coastguard Worker int ret;
80*33b1fccfSAndroid Build Coastguard Worker
81*33b1fccfSAndroid Build Coastguard Worker sbi->blkszbits = ilog2(EROFS_MAX_BLOCK_SIZE);
82*33b1fccfSAndroid Build Coastguard Worker ret = erofs_blk_read(sbi, 0, data, 0, erofs_blknr(sbi, sizeof(data)));
83*33b1fccfSAndroid Build Coastguard Worker if (ret < 0) {
84*33b1fccfSAndroid Build Coastguard Worker erofs_err("cannot read erofs superblock: %d", ret);
85*33b1fccfSAndroid Build Coastguard Worker return -EIO;
86*33b1fccfSAndroid Build Coastguard Worker }
87*33b1fccfSAndroid Build Coastguard Worker dsb = (struct erofs_super_block *)(data + EROFS_SUPER_OFFSET);
88*33b1fccfSAndroid Build Coastguard Worker
89*33b1fccfSAndroid Build Coastguard Worker ret = -EINVAL;
90*33b1fccfSAndroid Build Coastguard Worker if (le32_to_cpu(dsb->magic) != EROFS_SUPER_MAGIC_V1) {
91*33b1fccfSAndroid Build Coastguard Worker erofs_err("cannot find valid erofs superblock");
92*33b1fccfSAndroid Build Coastguard Worker return ret;
93*33b1fccfSAndroid Build Coastguard Worker }
94*33b1fccfSAndroid Build Coastguard Worker
95*33b1fccfSAndroid Build Coastguard Worker sbi->feature_compat = le32_to_cpu(dsb->feature_compat);
96*33b1fccfSAndroid Build Coastguard Worker
97*33b1fccfSAndroid Build Coastguard Worker sbi->blkszbits = dsb->blkszbits;
98*33b1fccfSAndroid Build Coastguard Worker if (sbi->blkszbits < 9 ||
99*33b1fccfSAndroid Build Coastguard Worker sbi->blkszbits > ilog2(EROFS_MAX_BLOCK_SIZE)) {
100*33b1fccfSAndroid Build Coastguard Worker erofs_err("blksize %llu isn't supported on this platform",
101*33b1fccfSAndroid Build Coastguard Worker erofs_blksiz(sbi) | 0ULL);
102*33b1fccfSAndroid Build Coastguard Worker return ret;
103*33b1fccfSAndroid Build Coastguard Worker } else if (!check_layout_compatibility(sbi, dsb)) {
104*33b1fccfSAndroid Build Coastguard Worker return ret;
105*33b1fccfSAndroid Build Coastguard Worker }
106*33b1fccfSAndroid Build Coastguard Worker
107*33b1fccfSAndroid Build Coastguard Worker sbi->sb_size = 128 + dsb->sb_extslots * EROFS_SB_EXTSLOT_SIZE;
108*33b1fccfSAndroid Build Coastguard Worker if (sbi->sb_size > (1 << sbi->blkszbits) - EROFS_SUPER_OFFSET) {
109*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid sb_extslots %u (more than a fs block)",
110*33b1fccfSAndroid Build Coastguard Worker dsb->sb_extslots);
111*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
112*33b1fccfSAndroid Build Coastguard Worker }
113*33b1fccfSAndroid Build Coastguard Worker sbi->primarydevice_blocks = le32_to_cpu(dsb->blocks);
114*33b1fccfSAndroid Build Coastguard Worker sbi->meta_blkaddr = le32_to_cpu(dsb->meta_blkaddr);
115*33b1fccfSAndroid Build Coastguard Worker sbi->xattr_blkaddr = le32_to_cpu(dsb->xattr_blkaddr);
116*33b1fccfSAndroid Build Coastguard Worker sbi->xattr_prefix_start = le32_to_cpu(dsb->xattr_prefix_start);
117*33b1fccfSAndroid Build Coastguard Worker sbi->xattr_prefix_count = dsb->xattr_prefix_count;
118*33b1fccfSAndroid Build Coastguard Worker sbi->islotbits = EROFS_ISLOTBITS;
119*33b1fccfSAndroid Build Coastguard Worker sbi->root_nid = le16_to_cpu(dsb->root_nid);
120*33b1fccfSAndroid Build Coastguard Worker sbi->packed_nid = le64_to_cpu(dsb->packed_nid);
121*33b1fccfSAndroid Build Coastguard Worker sbi->inos = le64_to_cpu(dsb->inos);
122*33b1fccfSAndroid Build Coastguard Worker sbi->checksum = le32_to_cpu(dsb->checksum);
123*33b1fccfSAndroid Build Coastguard Worker
124*33b1fccfSAndroid Build Coastguard Worker sbi->build_time = le64_to_cpu(dsb->build_time);
125*33b1fccfSAndroid Build Coastguard Worker sbi->build_time_nsec = le32_to_cpu(dsb->build_time_nsec);
126*33b1fccfSAndroid Build Coastguard Worker
127*33b1fccfSAndroid Build Coastguard Worker memcpy(&sbi->uuid, dsb->uuid, sizeof(dsb->uuid));
128*33b1fccfSAndroid Build Coastguard Worker
129*33b1fccfSAndroid Build Coastguard Worker ret = z_erofs_parse_cfgs(sbi, dsb);
130*33b1fccfSAndroid Build Coastguard Worker if (ret)
131*33b1fccfSAndroid Build Coastguard Worker return ret;
132*33b1fccfSAndroid Build Coastguard Worker
133*33b1fccfSAndroid Build Coastguard Worker ret = erofs_init_devices(sbi, dsb);
134*33b1fccfSAndroid Build Coastguard Worker if (ret)
135*33b1fccfSAndroid Build Coastguard Worker return ret;
136*33b1fccfSAndroid Build Coastguard Worker
137*33b1fccfSAndroid Build Coastguard Worker ret = erofs_xattr_prefixes_init(sbi);
138*33b1fccfSAndroid Build Coastguard Worker if (ret && sbi->devs) {
139*33b1fccfSAndroid Build Coastguard Worker free(sbi->devs);
140*33b1fccfSAndroid Build Coastguard Worker sbi->devs = NULL;
141*33b1fccfSAndroid Build Coastguard Worker }
142*33b1fccfSAndroid Build Coastguard Worker return ret;
143*33b1fccfSAndroid Build Coastguard Worker }
144*33b1fccfSAndroid Build Coastguard Worker
erofs_put_super(struct erofs_sb_info * sbi)145*33b1fccfSAndroid Build Coastguard Worker void erofs_put_super(struct erofs_sb_info *sbi)
146*33b1fccfSAndroid Build Coastguard Worker {
147*33b1fccfSAndroid Build Coastguard Worker if (sbi->devs) {
148*33b1fccfSAndroid Build Coastguard Worker free(sbi->devs);
149*33b1fccfSAndroid Build Coastguard Worker sbi->devs = NULL;
150*33b1fccfSAndroid Build Coastguard Worker }
151*33b1fccfSAndroid Build Coastguard Worker erofs_xattr_prefixes_cleanup(sbi);
152*33b1fccfSAndroid Build Coastguard Worker if (sbi->bmgr) {
153*33b1fccfSAndroid Build Coastguard Worker erofs_buffer_exit(sbi->bmgr);
154*33b1fccfSAndroid Build Coastguard Worker sbi->bmgr = NULL;
155*33b1fccfSAndroid Build Coastguard Worker }
156*33b1fccfSAndroid Build Coastguard Worker }
157*33b1fccfSAndroid Build Coastguard Worker
erofs_writesb(struct erofs_sb_info * sbi,struct erofs_buffer_head * sb_bh,erofs_blk_t * blocks)158*33b1fccfSAndroid Build Coastguard Worker int erofs_writesb(struct erofs_sb_info *sbi, struct erofs_buffer_head *sb_bh,
159*33b1fccfSAndroid Build Coastguard Worker erofs_blk_t *blocks)
160*33b1fccfSAndroid Build Coastguard Worker {
161*33b1fccfSAndroid Build Coastguard Worker struct erofs_super_block sb = {
162*33b1fccfSAndroid Build Coastguard Worker .magic = cpu_to_le32(EROFS_SUPER_MAGIC_V1),
163*33b1fccfSAndroid Build Coastguard Worker .blkszbits = sbi->blkszbits,
164*33b1fccfSAndroid Build Coastguard Worker .root_nid = cpu_to_le16(sbi->root_nid),
165*33b1fccfSAndroid Build Coastguard Worker .inos = cpu_to_le64(sbi->inos),
166*33b1fccfSAndroid Build Coastguard Worker .build_time = cpu_to_le64(sbi->build_time),
167*33b1fccfSAndroid Build Coastguard Worker .build_time_nsec = cpu_to_le32(sbi->build_time_nsec),
168*33b1fccfSAndroid Build Coastguard Worker .meta_blkaddr = cpu_to_le32(sbi->meta_blkaddr),
169*33b1fccfSAndroid Build Coastguard Worker .xattr_blkaddr = cpu_to_le32(sbi->xattr_blkaddr),
170*33b1fccfSAndroid Build Coastguard Worker .xattr_prefix_count = sbi->xattr_prefix_count,
171*33b1fccfSAndroid Build Coastguard Worker .xattr_prefix_start = cpu_to_le32(sbi->xattr_prefix_start),
172*33b1fccfSAndroid Build Coastguard Worker .feature_incompat = cpu_to_le32(sbi->feature_incompat),
173*33b1fccfSAndroid Build Coastguard Worker .feature_compat = cpu_to_le32(sbi->feature_compat &
174*33b1fccfSAndroid Build Coastguard Worker ~EROFS_FEATURE_COMPAT_SB_CHKSUM),
175*33b1fccfSAndroid Build Coastguard Worker .extra_devices = cpu_to_le16(sbi->extra_devices),
176*33b1fccfSAndroid Build Coastguard Worker .devt_slotoff = cpu_to_le16(sbi->devt_slotoff),
177*33b1fccfSAndroid Build Coastguard Worker .packed_nid = cpu_to_le64(sbi->packed_nid),
178*33b1fccfSAndroid Build Coastguard Worker };
179*33b1fccfSAndroid Build Coastguard Worker const u32 sb_blksize = round_up(EROFS_SUPER_END, erofs_blksiz(sbi));
180*33b1fccfSAndroid Build Coastguard Worker char *buf;
181*33b1fccfSAndroid Build Coastguard Worker int ret;
182*33b1fccfSAndroid Build Coastguard Worker
183*33b1fccfSAndroid Build Coastguard Worker *blocks = erofs_mapbh(sbi->bmgr, NULL);
184*33b1fccfSAndroid Build Coastguard Worker sb.blocks = cpu_to_le32(*blocks);
185*33b1fccfSAndroid Build Coastguard Worker memcpy(sb.uuid, sbi->uuid, sizeof(sb.uuid));
186*33b1fccfSAndroid Build Coastguard Worker memcpy(sb.volume_name, sbi->volume_name, sizeof(sb.volume_name));
187*33b1fccfSAndroid Build Coastguard Worker
188*33b1fccfSAndroid Build Coastguard Worker if (erofs_sb_has_compr_cfgs(sbi))
189*33b1fccfSAndroid Build Coastguard Worker sb.u1.available_compr_algs = cpu_to_le16(sbi->available_compr_algs);
190*33b1fccfSAndroid Build Coastguard Worker else
191*33b1fccfSAndroid Build Coastguard Worker sb.u1.lz4_max_distance = cpu_to_le16(sbi->lz4.max_distance);
192*33b1fccfSAndroid Build Coastguard Worker
193*33b1fccfSAndroid Build Coastguard Worker buf = calloc(sb_blksize, 1);
194*33b1fccfSAndroid Build Coastguard Worker if (!buf) {
195*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to allocate memory for sb: %s",
196*33b1fccfSAndroid Build Coastguard Worker erofs_strerror(-errno));
197*33b1fccfSAndroid Build Coastguard Worker return -ENOMEM;
198*33b1fccfSAndroid Build Coastguard Worker }
199*33b1fccfSAndroid Build Coastguard Worker memcpy(buf + EROFS_SUPER_OFFSET, &sb, sizeof(sb));
200*33b1fccfSAndroid Build Coastguard Worker
201*33b1fccfSAndroid Build Coastguard Worker ret = erofs_dev_write(sbi, buf, sb_bh ? erofs_btell(sb_bh, false) : 0,
202*33b1fccfSAndroid Build Coastguard Worker EROFS_SUPER_END);
203*33b1fccfSAndroid Build Coastguard Worker free(buf);
204*33b1fccfSAndroid Build Coastguard Worker if (sb_bh)
205*33b1fccfSAndroid Build Coastguard Worker erofs_bdrop(sb_bh, false);
206*33b1fccfSAndroid Build Coastguard Worker return ret;
207*33b1fccfSAndroid Build Coastguard Worker }
208*33b1fccfSAndroid Build Coastguard Worker
erofs_reserve_sb(struct erofs_bufmgr * bmgr)209*33b1fccfSAndroid Build Coastguard Worker struct erofs_buffer_head *erofs_reserve_sb(struct erofs_bufmgr *bmgr)
210*33b1fccfSAndroid Build Coastguard Worker {
211*33b1fccfSAndroid Build Coastguard Worker struct erofs_buffer_head *bh;
212*33b1fccfSAndroid Build Coastguard Worker int err;
213*33b1fccfSAndroid Build Coastguard Worker
214*33b1fccfSAndroid Build Coastguard Worker bh = erofs_balloc(bmgr, META, 0, 0, 0);
215*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(bh)) {
216*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to allocate super: %s", PTR_ERR(bh));
217*33b1fccfSAndroid Build Coastguard Worker return bh;
218*33b1fccfSAndroid Build Coastguard Worker }
219*33b1fccfSAndroid Build Coastguard Worker bh->op = &erofs_skip_write_bhops;
220*33b1fccfSAndroid Build Coastguard Worker err = erofs_bh_balloon(bh, EROFS_SUPER_END);
221*33b1fccfSAndroid Build Coastguard Worker if (err < 0) {
222*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to balloon super: %s", erofs_strerror(err));
223*33b1fccfSAndroid Build Coastguard Worker goto err_bdrop;
224*33b1fccfSAndroid Build Coastguard Worker }
225*33b1fccfSAndroid Build Coastguard Worker
226*33b1fccfSAndroid Build Coastguard Worker /* make sure that the super block should be the very first blocks */
227*33b1fccfSAndroid Build Coastguard Worker (void)erofs_mapbh(NULL, bh->block);
228*33b1fccfSAndroid Build Coastguard Worker if (erofs_btell(bh, false) != 0) {
229*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to pin super block @ 0");
230*33b1fccfSAndroid Build Coastguard Worker err = -EFAULT;
231*33b1fccfSAndroid Build Coastguard Worker goto err_bdrop;
232*33b1fccfSAndroid Build Coastguard Worker }
233*33b1fccfSAndroid Build Coastguard Worker return bh;
234*33b1fccfSAndroid Build Coastguard Worker err_bdrop:
235*33b1fccfSAndroid Build Coastguard Worker erofs_bdrop(bh, true);
236*33b1fccfSAndroid Build Coastguard Worker return ERR_PTR(err);
237*33b1fccfSAndroid Build Coastguard Worker }
238*33b1fccfSAndroid Build Coastguard Worker
erofs_enable_sb_chksum(struct erofs_sb_info * sbi,u32 * crc)239*33b1fccfSAndroid Build Coastguard Worker int erofs_enable_sb_chksum(struct erofs_sb_info *sbi, u32 *crc)
240*33b1fccfSAndroid Build Coastguard Worker {
241*33b1fccfSAndroid Build Coastguard Worker int ret;
242*33b1fccfSAndroid Build Coastguard Worker u8 buf[EROFS_MAX_BLOCK_SIZE];
243*33b1fccfSAndroid Build Coastguard Worker unsigned int len;
244*33b1fccfSAndroid Build Coastguard Worker struct erofs_super_block *sb;
245*33b1fccfSAndroid Build Coastguard Worker
246*33b1fccfSAndroid Build Coastguard Worker ret = erofs_blk_read(sbi, 0, buf, 0, erofs_blknr(sbi, EROFS_SUPER_END) + 1);
247*33b1fccfSAndroid Build Coastguard Worker if (ret) {
248*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to read superblock to set checksum: %s",
249*33b1fccfSAndroid Build Coastguard Worker erofs_strerror(ret));
250*33b1fccfSAndroid Build Coastguard Worker return ret;
251*33b1fccfSAndroid Build Coastguard Worker }
252*33b1fccfSAndroid Build Coastguard Worker
253*33b1fccfSAndroid Build Coastguard Worker /*
254*33b1fccfSAndroid Build Coastguard Worker * skip the first 1024 bytes, to allow for the installation
255*33b1fccfSAndroid Build Coastguard Worker * of x86 boot sectors and other oddities.
256*33b1fccfSAndroid Build Coastguard Worker */
257*33b1fccfSAndroid Build Coastguard Worker sb = (struct erofs_super_block *)(buf + EROFS_SUPER_OFFSET);
258*33b1fccfSAndroid Build Coastguard Worker
259*33b1fccfSAndroid Build Coastguard Worker if (le32_to_cpu(sb->magic) != EROFS_SUPER_MAGIC_V1) {
260*33b1fccfSAndroid Build Coastguard Worker erofs_err("internal error: not an erofs valid image");
261*33b1fccfSAndroid Build Coastguard Worker return -EFAULT;
262*33b1fccfSAndroid Build Coastguard Worker }
263*33b1fccfSAndroid Build Coastguard Worker
264*33b1fccfSAndroid Build Coastguard Worker /* turn on checksum feature */
265*33b1fccfSAndroid Build Coastguard Worker sb->feature_compat = cpu_to_le32(le32_to_cpu(sb->feature_compat) |
266*33b1fccfSAndroid Build Coastguard Worker EROFS_FEATURE_COMPAT_SB_CHKSUM);
267*33b1fccfSAndroid Build Coastguard Worker if (erofs_blksiz(sbi) > EROFS_SUPER_OFFSET)
268*33b1fccfSAndroid Build Coastguard Worker len = erofs_blksiz(sbi) - EROFS_SUPER_OFFSET;
269*33b1fccfSAndroid Build Coastguard Worker else
270*33b1fccfSAndroid Build Coastguard Worker len = erofs_blksiz(sbi);
271*33b1fccfSAndroid Build Coastguard Worker *crc = erofs_crc32c(~0, (u8 *)sb, len);
272*33b1fccfSAndroid Build Coastguard Worker
273*33b1fccfSAndroid Build Coastguard Worker /* set up checksum field to erofs_super_block */
274*33b1fccfSAndroid Build Coastguard Worker sb->checksum = cpu_to_le32(*crc);
275*33b1fccfSAndroid Build Coastguard Worker
276*33b1fccfSAndroid Build Coastguard Worker ret = erofs_blk_write(sbi, buf, 0, 1);
277*33b1fccfSAndroid Build Coastguard Worker if (ret) {
278*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to write checksummed superblock: %s",
279*33b1fccfSAndroid Build Coastguard Worker erofs_strerror(ret));
280*33b1fccfSAndroid Build Coastguard Worker return ret;
281*33b1fccfSAndroid Build Coastguard Worker }
282*33b1fccfSAndroid Build Coastguard Worker
283*33b1fccfSAndroid Build Coastguard Worker return 0;
284*33b1fccfSAndroid Build Coastguard Worker }
285