1 // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2 /*
3 * (a large amount of code was adapted from Linux kernel. )
4 *
5 * Copyright (C) 2018-2019 HUAWEI, Inc.
6 * https://www.huawei.com/
7 * Created by Gao Xiang <gaoxiang25@huawei.com>
8 * Modified by Huang Jianan <huangjianan@oppo.com>
9 */
10 #include "erofs/io.h"
11 #include "erofs/print.h"
12
13 static int z_erofs_do_map_blocks(struct erofs_inode *vi,
14 struct erofs_map_blocks *map,
15 int flags);
16
z_erofs_fill_inode(struct erofs_inode * vi)17 int z_erofs_fill_inode(struct erofs_inode *vi)
18 {
19 if (!erofs_sb_has_big_pcluster() &&
20 !erofs_sb_has_ztailpacking() &&
21 vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) {
22 vi->z_advise = 0;
23 vi->z_algorithmtype[0] = 0;
24 vi->z_algorithmtype[1] = 0;
25 vi->z_logical_clusterbits = LOG_BLOCK_SIZE;
26
27 vi->flags |= EROFS_I_Z_INITED;
28 }
29 return 0;
30 }
31
z_erofs_fill_inode_lazy(struct erofs_inode * vi)32 static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
33 {
34 int ret;
35 erofs_off_t pos;
36 struct z_erofs_map_header *h;
37 char buf[sizeof(struct z_erofs_map_header)];
38
39 if (vi->flags & EROFS_I_Z_INITED)
40 return 0;
41
42 DBG_BUGON(!erofs_sb_has_big_pcluster() &&
43 !erofs_sb_has_ztailpacking() &&
44 vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY);
45 pos = round_up(iloc(vi->nid) + vi->inode_isize + vi->xattr_isize, 8);
46
47 ret = dev_read(0, buf, pos, sizeof(buf));
48 if (ret < 0)
49 return -EIO;
50
51 h = (struct z_erofs_map_header *)buf;
52 vi->z_advise = le16_to_cpu(h->h_advise);
53 vi->z_algorithmtype[0] = h->h_algorithmtype & 15;
54 vi->z_algorithmtype[1] = h->h_algorithmtype >> 4;
55
56 if (vi->z_algorithmtype[0] >= Z_EROFS_COMPRESSION_MAX) {
57 erofs_err("unknown compression format %u for nid %llu",
58 vi->z_algorithmtype[0], (unsigned long long)vi->nid);
59 return -EOPNOTSUPP;
60 }
61
62 vi->z_logical_clusterbits = LOG_BLOCK_SIZE + (h->h_clusterbits & 7);
63 if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION &&
64 !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1) ^
65 !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_2)) {
66 erofs_err("big pcluster head1/2 of compact indexes should be consistent for nid %llu",
67 vi->nid * 1ULL);
68 return -EFSCORRUPTED;
69 }
70
71 if (vi->z_advise & Z_EROFS_ADVISE_INLINE_PCLUSTER) {
72 struct erofs_map_blocks map = { .index = UINT_MAX };
73
74 vi->idata_size = le16_to_cpu(h->h_idata_size);
75 ret = z_erofs_do_map_blocks(vi, &map,
76 EROFS_GET_BLOCKS_FINDTAIL);
77 if (!map.m_plen ||
78 erofs_blkoff(map.m_pa) + map.m_plen > EROFS_BLKSIZ) {
79 erofs_err("invalid tail-packing pclustersize %llu",
80 map.m_plen | 0ULL);
81 return -EFSCORRUPTED;
82 }
83 if (ret < 0)
84 return ret;
85 }
86 vi->flags |= EROFS_I_Z_INITED;
87 return 0;
88 }
89
90 struct z_erofs_maprecorder {
91 struct erofs_inode *inode;
92 struct erofs_map_blocks *map;
93 void *kaddr;
94
95 unsigned long lcn;
96 /* compression extent information gathered */
97 u8 type, headtype;
98 u16 clusterofs;
99 u16 delta[2];
100 erofs_blk_t pblk, compressedlcs;
101 erofs_off_t nextpackoff;
102 };
103
z_erofs_reload_indexes(struct z_erofs_maprecorder * m,erofs_blk_t eblk)104 static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m,
105 erofs_blk_t eblk)
106 {
107 int ret;
108 struct erofs_map_blocks *const map = m->map;
109 char *mpage = map->mpage;
110
111 if (map->index == eblk)
112 return 0;
113
114 ret = blk_read(0, mpage, eblk, 1);
115 if (ret < 0)
116 return -EIO;
117
118 map->index = eblk;
119
120 return 0;
121 }
122
legacy_load_cluster_from_disk(struct z_erofs_maprecorder * m,unsigned long lcn)123 static int legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m,
124 unsigned long lcn)
125 {
126 struct erofs_inode *const vi = m->inode;
127 const erofs_off_t ibase = iloc(vi->nid);
128 const erofs_off_t pos =
129 Z_EROFS_VLE_LEGACY_INDEX_ALIGN(ibase + vi->inode_isize +
130 vi->xattr_isize) +
131 lcn * sizeof(struct z_erofs_vle_decompressed_index);
132 struct z_erofs_vle_decompressed_index *di;
133 unsigned int advise, type;
134 int err;
135
136 err = z_erofs_reload_indexes(m, erofs_blknr(pos));
137 if (err)
138 return err;
139
140 m->nextpackoff = pos + sizeof(struct z_erofs_vle_decompressed_index);
141 m->lcn = lcn;
142 di = m->kaddr + erofs_blkoff(pos);
143
144 advise = le16_to_cpu(di->di_advise);
145 type = (advise >> Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT) &
146 ((1 << Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) - 1);
147 switch (type) {
148 case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
149 m->clusterofs = 1 << vi->z_logical_clusterbits;
150 m->delta[0] = le16_to_cpu(di->di_u.delta[0]);
151 if (m->delta[0] & Z_EROFS_VLE_DI_D0_CBLKCNT) {
152 if (!(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) {
153 DBG_BUGON(1);
154 return -EFSCORRUPTED;
155 }
156 m->compressedlcs = m->delta[0] &
157 ~Z_EROFS_VLE_DI_D0_CBLKCNT;
158 m->delta[0] = 1;
159 }
160 m->delta[1] = le16_to_cpu(di->di_u.delta[1]);
161 break;
162 case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
163 case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
164 m->clusterofs = le16_to_cpu(di->di_clusterofs);
165 m->pblk = le32_to_cpu(di->di_u.blkaddr);
166 break;
167 default:
168 DBG_BUGON(1);
169 return -EOPNOTSUPP;
170 }
171 m->type = type;
172 return 0;
173 }
174
decode_compactedbits(unsigned int lobits,unsigned int lomask,u8 * in,unsigned int pos,u8 * type)175 static unsigned int decode_compactedbits(unsigned int lobits,
176 unsigned int lomask,
177 u8 *in, unsigned int pos, u8 *type)
178 {
179 const unsigned int v = get_unaligned_le32(in + pos / 8) >> (pos & 7);
180 const unsigned int lo = v & lomask;
181
182 *type = (v >> lobits) & 3;
183 return lo;
184 }
185
get_compacted_la_distance(unsigned int lclusterbits,unsigned int encodebits,unsigned int vcnt,u8 * in,int i)186 static int get_compacted_la_distance(unsigned int lclusterbits,
187 unsigned int encodebits,
188 unsigned int vcnt, u8 *in, int i)
189 {
190 const unsigned int lomask = (1 << lclusterbits) - 1;
191 unsigned int lo, d1 = 0;
192 u8 type;
193
194 DBG_BUGON(i >= vcnt);
195
196 do {
197 lo = decode_compactedbits(lclusterbits, lomask,
198 in, encodebits * i, &type);
199
200 if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
201 return d1;
202 ++d1;
203 } while (++i < vcnt);
204
205 /* vcnt - 1 (Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) item */
206 if (!(lo & Z_EROFS_VLE_DI_D0_CBLKCNT))
207 d1 += lo - 1;
208 return d1;
209 }
210
unpack_compacted_index(struct z_erofs_maprecorder * m,unsigned int amortizedshift,erofs_off_t pos,bool lookahead)211 static int unpack_compacted_index(struct z_erofs_maprecorder *m,
212 unsigned int amortizedshift,
213 erofs_off_t pos, bool lookahead)
214 {
215 struct erofs_inode *const vi = m->inode;
216 const unsigned int lclusterbits = vi->z_logical_clusterbits;
217 const unsigned int lomask = (1 << lclusterbits) - 1;
218 unsigned int vcnt, base, lo, encodebits, nblk, eofs;
219 int i;
220 u8 *in, type;
221 bool big_pcluster;
222
223 if (1 << amortizedshift == 4)
224 vcnt = 2;
225 else if (1 << amortizedshift == 2 && lclusterbits == 12)
226 vcnt = 16;
227 else
228 return -EOPNOTSUPP;
229
230 /* it doesn't equal to round_up(..) */
231 m->nextpackoff = round_down(pos, vcnt << amortizedshift) +
232 (vcnt << amortizedshift);
233 big_pcluster = vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1;
234 encodebits = ((vcnt << amortizedshift) - sizeof(__le32)) * 8 / vcnt;
235 eofs = erofs_blkoff(pos);
236 base = round_down(eofs, vcnt << amortizedshift);
237 in = m->kaddr + base;
238
239 i = (eofs - base) >> amortizedshift;
240
241 lo = decode_compactedbits(lclusterbits, lomask,
242 in, encodebits * i, &type);
243 m->type = type;
244 if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
245 m->clusterofs = 1 << lclusterbits;
246
247 /* figure out lookahead_distance: delta[1] if needed */
248 if (lookahead)
249 m->delta[1] = get_compacted_la_distance(lclusterbits,
250 encodebits, vcnt, in, i);
251 if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) {
252 if (!big_pcluster) {
253 DBG_BUGON(1);
254 return -EFSCORRUPTED;
255 }
256 m->compressedlcs = lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT;
257 m->delta[0] = 1;
258 return 0;
259 } else if (i + 1 != (int)vcnt) {
260 m->delta[0] = lo;
261 return 0;
262 }
263 /*
264 * since the last lcluster in the pack is special,
265 * of which lo saves delta[1] rather than delta[0].
266 * Hence, get delta[0] by the previous lcluster indirectly.
267 */
268 lo = decode_compactedbits(lclusterbits, lomask,
269 in, encodebits * (i - 1), &type);
270 if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
271 lo = 0;
272 else if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT)
273 lo = 1;
274 m->delta[0] = lo + 1;
275 return 0;
276 }
277 m->clusterofs = lo;
278 m->delta[0] = 0;
279 /* figout out blkaddr (pblk) for HEAD lclusters */
280 if (!big_pcluster) {
281 nblk = 1;
282 while (i > 0) {
283 --i;
284 lo = decode_compactedbits(lclusterbits, lomask,
285 in, encodebits * i, &type);
286 if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
287 i -= lo;
288
289 if (i >= 0)
290 ++nblk;
291 }
292 } else {
293 nblk = 0;
294 while (i > 0) {
295 --i;
296 lo = decode_compactedbits(lclusterbits, lomask,
297 in, encodebits * i, &type);
298 if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
299 if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) {
300 --i;
301 nblk += lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT;
302 continue;
303 }
304 if (lo == 1) {
305 DBG_BUGON(1);
306 /* --i; ++nblk; continue; */
307 return -EFSCORRUPTED;
308 }
309 i -= lo - 2;
310 continue;
311 }
312 ++nblk;
313 }
314 }
315 in += (vcnt << amortizedshift) - sizeof(__le32);
316 m->pblk = le32_to_cpu(*(__le32 *)in) + nblk;
317 return 0;
318 }
319
compacted_load_cluster_from_disk(struct z_erofs_maprecorder * m,unsigned long lcn,bool lookahead)320 static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m,
321 unsigned long lcn, bool lookahead)
322 {
323 struct erofs_inode *const vi = m->inode;
324 const unsigned int lclusterbits = vi->z_logical_clusterbits;
325 const erofs_off_t ebase = round_up(iloc(vi->nid) + vi->inode_isize +
326 vi->xattr_isize, 8) +
327 sizeof(struct z_erofs_map_header);
328 const unsigned int totalidx = DIV_ROUND_UP(vi->i_size, EROFS_BLKSIZ);
329 unsigned int compacted_4b_initial, compacted_2b;
330 unsigned int amortizedshift;
331 erofs_off_t pos;
332 int err;
333
334 if (lclusterbits != 12)
335 return -EOPNOTSUPP;
336
337 if (lcn >= totalidx)
338 return -EINVAL;
339
340 m->lcn = lcn;
341 /* used to align to 32-byte (compacted_2b) alignment */
342 compacted_4b_initial = (32 - ebase % 32) / 4;
343 if (compacted_4b_initial == 32 / 4)
344 compacted_4b_initial = 0;
345
346 if ((vi->z_advise & Z_EROFS_ADVISE_COMPACTED_2B) &&
347 compacted_4b_initial < totalidx)
348 compacted_2b = rounddown(totalidx - compacted_4b_initial, 16);
349 else
350 compacted_2b = 0;
351
352 pos = ebase;
353 if (lcn < compacted_4b_initial) {
354 amortizedshift = 2;
355 goto out;
356 }
357 pos += compacted_4b_initial * 4;
358 lcn -= compacted_4b_initial;
359
360 if (lcn < compacted_2b) {
361 amortizedshift = 1;
362 goto out;
363 }
364 pos += compacted_2b * 2;
365 lcn -= compacted_2b;
366 amortizedshift = 2;
367 out:
368 pos += lcn * (1 << amortizedshift);
369 err = z_erofs_reload_indexes(m, erofs_blknr(pos));
370 if (err)
371 return err;
372 return unpack_compacted_index(m, amortizedshift, pos, lookahead);
373 }
374
z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder * m,unsigned int lcn,bool lookahead)375 static int z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder *m,
376 unsigned int lcn, bool lookahead)
377 {
378 const unsigned int datamode = m->inode->datalayout;
379
380 if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY)
381 return legacy_load_cluster_from_disk(m, lcn);
382
383 if (datamode == EROFS_INODE_FLAT_COMPRESSION)
384 return compacted_load_cluster_from_disk(m, lcn, lookahead);
385
386 return -EINVAL;
387 }
388
z_erofs_extent_lookback(struct z_erofs_maprecorder * m,unsigned int lookback_distance)389 static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
390 unsigned int lookback_distance)
391 {
392 struct erofs_inode *const vi = m->inode;
393 struct erofs_map_blocks *const map = m->map;
394 const unsigned int lclusterbits = vi->z_logical_clusterbits;
395 unsigned long lcn = m->lcn;
396 int err;
397
398 if (lcn < lookback_distance) {
399 erofs_err("bogus lookback distance @ nid %llu",
400 (unsigned long long)vi->nid);
401 DBG_BUGON(1);
402 return -EFSCORRUPTED;
403 }
404
405 /* load extent head logical cluster if needed */
406 lcn -= lookback_distance;
407 err = z_erofs_load_cluster_from_disk(m, lcn, false);
408 if (err)
409 return err;
410
411 switch (m->type) {
412 case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
413 if (!m->delta[0]) {
414 erofs_err("invalid lookback distance 0 @ nid %llu",
415 (unsigned long long)vi->nid);
416 DBG_BUGON(1);
417 return -EFSCORRUPTED;
418 }
419 return z_erofs_extent_lookback(m, m->delta[0]);
420 case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
421 case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
422 m->headtype = m->type;
423 map->m_la = (lcn << lclusterbits) | m->clusterofs;
424 break;
425 default:
426 erofs_err("unknown type %u @ lcn %lu of nid %llu",
427 m->type, lcn, (unsigned long long)vi->nid);
428 DBG_BUGON(1);
429 return -EOPNOTSUPP;
430 }
431 return 0;
432 }
433
z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder * m,unsigned int initial_lcn)434 static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
435 unsigned int initial_lcn)
436 {
437 struct erofs_inode *const vi = m->inode;
438 struct erofs_map_blocks *const map = m->map;
439 const unsigned int lclusterbits = vi->z_logical_clusterbits;
440 unsigned long lcn;
441 int err;
442
443 DBG_BUGON(m->type != Z_EROFS_VLE_CLUSTER_TYPE_PLAIN &&
444 m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD);
445
446 if (m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN ||
447 !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) {
448 map->m_plen = 1 << lclusterbits;
449 return 0;
450 }
451
452 lcn = m->lcn + 1;
453 if (m->compressedlcs)
454 goto out;
455
456 err = z_erofs_load_cluster_from_disk(m, lcn, false);
457 if (err)
458 return err;
459
460 /*
461 * If the 1st NONHEAD lcluster has already been handled initially w/o
462 * valid compressedlcs, which means at least it mustn't be CBLKCNT, or
463 * an internal implemenatation error is detected.
464 *
465 * The following code can also handle it properly anyway, but let's
466 * BUG_ON in the debugging mode only for developers to notice that.
467 */
468 DBG_BUGON(lcn == initial_lcn &&
469 m->type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD);
470
471 switch (m->type) {
472 case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
473 case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
474 /*
475 * if the 1st NONHEAD lcluster is actually PLAIN or HEAD type
476 * rather than CBLKCNT, it's a 1 lcluster-sized pcluster.
477 */
478 m->compressedlcs = 1;
479 break;
480 case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
481 if (m->delta[0] != 1)
482 goto err_bonus_cblkcnt;
483 if (m->compressedlcs)
484 break;
485 /* fallthrough */
486 default:
487 erofs_err("cannot found CBLKCNT @ lcn %lu of nid %llu",
488 lcn, vi->nid | 0ULL);
489 DBG_BUGON(1);
490 return -EFSCORRUPTED;
491 }
492 out:
493 map->m_plen = m->compressedlcs << lclusterbits;
494 return 0;
495 err_bonus_cblkcnt:
496 erofs_err("bogus CBLKCNT @ lcn %lu of nid %llu",
497 lcn, vi->nid | 0ULL);
498 DBG_BUGON(1);
499 return -EFSCORRUPTED;
500 }
501
z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder * m)502 static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
503 {
504 struct erofs_inode *const vi = m->inode;
505 struct erofs_map_blocks *map = m->map;
506 unsigned int lclusterbits = vi->z_logical_clusterbits;
507 u64 lcn = m->lcn, headlcn = map->m_la >> lclusterbits;
508 int err;
509
510 do {
511 /* handle the last EOF pcluster (no next HEAD lcluster) */
512 if ((lcn << lclusterbits) >= vi->i_size) {
513 map->m_llen = vi->i_size - map->m_la;
514 return 0;
515 }
516
517 err = z_erofs_load_cluster_from_disk(m, lcn, true);
518 if (err)
519 return err;
520
521 if (m->type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
522 DBG_BUGON(!m->delta[1] &&
523 m->clusterofs != 1 << lclusterbits);
524 } else if (m->type == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN ||
525 m->type == Z_EROFS_VLE_CLUSTER_TYPE_HEAD) {
526 /* go on until the next HEAD lcluster */
527 if (lcn != headlcn)
528 break;
529 m->delta[1] = 1;
530 } else {
531 erofs_err("unknown type %u @ lcn %llu of nid %llu",
532 m->type, lcn | 0ULL,
533 (unsigned long long)vi->nid);
534 DBG_BUGON(1);
535 return -EOPNOTSUPP;
536 }
537 lcn += m->delta[1];
538 } while (m->delta[1]);
539
540 map->m_llen = (lcn << lclusterbits) + m->clusterofs - map->m_la;
541 return 0;
542 }
543
z_erofs_do_map_blocks(struct erofs_inode * vi,struct erofs_map_blocks * map,int flags)544 static int z_erofs_do_map_blocks(struct erofs_inode *vi,
545 struct erofs_map_blocks *map,
546 int flags)
547 {
548 bool ztailpacking = vi->z_advise & Z_EROFS_ADVISE_INLINE_PCLUSTER;
549 struct z_erofs_maprecorder m = {
550 .inode = vi,
551 .map = map,
552 .kaddr = map->mpage,
553 };
554 int err = 0;
555 unsigned int lclusterbits, endoff;
556 unsigned long initial_lcn;
557 unsigned long long ofs, end;
558
559 lclusterbits = vi->z_logical_clusterbits;
560 ofs = flags & EROFS_GET_BLOCKS_FINDTAIL ? vi->i_size - 1 : map->m_la;
561 initial_lcn = ofs >> lclusterbits;
562 endoff = ofs & ((1 << lclusterbits) - 1);
563
564 err = z_erofs_load_cluster_from_disk(&m, initial_lcn, false);
565 if (err)
566 goto out;
567
568 if (ztailpacking && (flags & EROFS_GET_BLOCKS_FINDTAIL))
569 vi->z_idataoff = m.nextpackoff;
570
571 map->m_flags = EROFS_MAP_MAPPED | EROFS_MAP_ENCODED;
572 end = (m.lcn + 1ULL) << lclusterbits;
573 switch (m.type) {
574 case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
575 case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
576 if (endoff >= m.clusterofs) {
577 m.headtype = m.type;
578 map->m_la = (m.lcn << lclusterbits) | m.clusterofs;
579 break;
580 }
581 /* m.lcn should be >= 1 if endoff < m.clusterofs */
582 if (!m.lcn) {
583 erofs_err("invalid logical cluster 0 at nid %llu",
584 (unsigned long long)vi->nid);
585 err = -EFSCORRUPTED;
586 goto out;
587 }
588 end = (m.lcn << lclusterbits) | m.clusterofs;
589 map->m_flags |= EROFS_MAP_FULL_MAPPED;
590 m.delta[0] = 1;
591 /* fallthrough */
592 case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
593 /* get the correspoinding first chunk */
594 err = z_erofs_extent_lookback(&m, m.delta[0]);
595 if (err)
596 goto out;
597 break;
598 default:
599 erofs_err("unknown type %u @ offset %llu of nid %llu",
600 m.type, ofs, (unsigned long long)vi->nid);
601 err = -EOPNOTSUPP;
602 goto out;
603 }
604
605 map->m_llen = end - map->m_la;
606 if (flags & EROFS_GET_BLOCKS_FINDTAIL)
607 vi->z_tailextent_headlcn = m.lcn;
608 if (ztailpacking && m.lcn == vi->z_tailextent_headlcn) {
609 map->m_flags |= EROFS_MAP_META;
610 map->m_pa = vi->z_idataoff;
611 map->m_plen = vi->z_idata_size;
612 } else {
613 map->m_pa = blknr_to_addr(m.pblk);
614 err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
615 if (err)
616 goto out;
617 }
618
619 if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN)
620 map->m_algorithmformat = Z_EROFS_COMPRESSION_SHIFTED;
621 else
622 map->m_algorithmformat = vi->z_algorithmtype[0];
623
624 if (flags & EROFS_GET_BLOCKS_FIEMAP) {
625 err = z_erofs_get_extent_decompressedlen(&m);
626 if (!err)
627 map->m_flags |= EROFS_MAP_FULL_MAPPED;
628 }
629
630 out:
631 erofs_dbg("m_la %" PRIu64 " m_pa %" PRIu64 " m_llen %" PRIu64 " m_plen %" PRIu64 " m_flags 0%o",
632 map->m_la, map->m_pa,
633 map->m_llen, map->m_plen, map->m_flags);
634 return err;
635 }
636
z_erofs_map_blocks_iter(struct erofs_inode * vi,struct erofs_map_blocks * map,int flags)637 int z_erofs_map_blocks_iter(struct erofs_inode *vi,
638 struct erofs_map_blocks *map,
639 int flags)
640 {
641 int err = 0;
642
643 /* when trying to read beyond EOF, leave it unmapped */
644 if (map->m_la >= vi->i_size) {
645 map->m_llen = map->m_la + 1 - vi->i_size;
646 map->m_la = vi->i_size;
647 map->m_flags = 0;
648 goto out;
649 }
650
651 err = z_erofs_fill_inode_lazy(vi);
652 if (err)
653 goto out;
654
655 err = z_erofs_do_map_blocks(vi, map, flags);
656 out:
657 DBG_BUGON(err < 0 && err != -ENOMEM);
658 return err;
659 }
660