@@ -212,9 +212,34 @@ static unsigned int decode_compactedbits(unsigned int lobits,
212
212
return lo ;
213
213
}
214
214
215
+ static int get_compacted_la_distance (unsigned int lclusterbits ,
216
+ unsigned int encodebits ,
217
+ unsigned int vcnt , u8 * in , int i )
218
+ {
219
+ const unsigned int lomask = (1 << lclusterbits ) - 1 ;
220
+ unsigned int lo , d1 = 0 ;
221
+ u8 type ;
222
+
223
+ DBG_BUGON (i >= vcnt );
224
+
225
+ do {
226
+ lo = decode_compactedbits (lclusterbits , lomask ,
227
+ in , encodebits * i , & type );
228
+
229
+ if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD )
230
+ return d1 ;
231
+ ++ d1 ;
232
+ } while (++ i < vcnt );
233
+
234
+ /* vcnt - 1 (Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) item */
235
+ if (!(lo & Z_EROFS_VLE_DI_D0_CBLKCNT ))
236
+ d1 += lo - 1 ;
237
+ return d1 ;
238
+ }
239
+
215
240
static int unpack_compacted_index (struct z_erofs_maprecorder * m ,
216
241
unsigned int amortizedshift ,
217
- unsigned int eofs )
242
+ unsigned int eofs , bool lookahead )
218
243
{
219
244
struct erofs_inode * const vi = EROFS_I (m -> inode );
220
245
const unsigned int lclusterbits = vi -> z_logical_clusterbits ;
@@ -243,6 +268,11 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
243
268
m -> type = type ;
244
269
if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD ) {
245
270
m -> clusterofs = 1 << lclusterbits ;
271
+
272
+ /* figure out lookahead_distance: delta[1] if needed */
273
+ if (lookahead )
274
+ m -> delta [1 ] = get_compacted_la_distance (lclusterbits ,
275
+ encodebits , vcnt , in , i );
246
276
if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT ) {
247
277
if (!big_pcluster ) {
248
278
DBG_BUGON (1 );
@@ -313,7 +343,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
313
343
}
314
344
315
345
static int compacted_load_cluster_from_disk (struct z_erofs_maprecorder * m ,
316
- unsigned long lcn )
346
+ unsigned long lcn , bool lookahead )
317
347
{
318
348
struct inode * const inode = m -> inode ;
319
349
struct erofs_inode * const vi = EROFS_I (inode );
@@ -364,19 +394,20 @@ static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m,
364
394
err = z_erofs_reload_indexes (m , erofs_blknr (pos ));
365
395
if (err )
366
396
return err ;
367
- return unpack_compacted_index (m , amortizedshift , erofs_blkoff (pos ));
397
+ return unpack_compacted_index (m , amortizedshift , erofs_blkoff (pos ),
398
+ lookahead );
368
399
}
369
400
370
401
static int z_erofs_load_cluster_from_disk (struct z_erofs_maprecorder * m ,
371
- unsigned int lcn )
402
+ unsigned int lcn , bool lookahead )
372
403
{
373
404
const unsigned int datamode = EROFS_I (m -> inode )-> datalayout ;
374
405
375
406
if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY )
376
407
return legacy_load_cluster_from_disk (m , lcn );
377
408
378
409
if (datamode == EROFS_INODE_FLAT_COMPRESSION )
379
- return compacted_load_cluster_from_disk (m , lcn );
410
+ return compacted_load_cluster_from_disk (m , lcn , lookahead );
380
411
381
412
return - EINVAL ;
382
413
}
@@ -399,7 +430,7 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
399
430
400
431
/* load extent head logical cluster if needed */
401
432
lcn -= lookback_distance ;
402
- err = z_erofs_load_cluster_from_disk (m , lcn );
433
+ err = z_erofs_load_cluster_from_disk (m , lcn , false );
403
434
if (err )
404
435
return err ;
405
436
@@ -450,7 +481,7 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
450
481
if (m -> compressedlcs )
451
482
goto out ;
452
483
453
- err = z_erofs_load_cluster_from_disk (m , lcn );
484
+ err = z_erofs_load_cluster_from_disk (m , lcn , false );
454
485
if (err )
455
486
return err ;
456
487
@@ -498,6 +529,48 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
498
529
return - EFSCORRUPTED ;
499
530
}
500
531
532
+ static int z_erofs_get_extent_decompressedlen (struct z_erofs_maprecorder * m )
533
+ {
534
+ struct inode * inode = m -> inode ;
535
+ struct erofs_inode * vi = EROFS_I (inode );
536
+ struct erofs_map_blocks * map = m -> map ;
537
+ unsigned int lclusterbits = vi -> z_logical_clusterbits ;
538
+ u64 lcn = m -> lcn , headlcn = map -> m_la >> lclusterbits ;
539
+ int err ;
540
+
541
+ do {
542
+ /* handle the last EOF pcluster (no next HEAD lcluster) */
543
+ if ((lcn << lclusterbits ) >= inode -> i_size ) {
544
+ map -> m_llen = inode -> i_size - map -> m_la ;
545
+ return 0 ;
546
+ }
547
+
548
+ err = z_erofs_load_cluster_from_disk (m , lcn , true);
549
+ if (err )
550
+ return err ;
551
+
552
+ if (m -> type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD ) {
553
+ DBG_BUGON (!m -> delta [1 ] &&
554
+ m -> clusterofs != 1 << lclusterbits );
555
+ } else if (m -> type == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN ||
556
+ m -> type == Z_EROFS_VLE_CLUSTER_TYPE_HEAD ) {
557
+ /* go on until the next HEAD lcluster */
558
+ if (lcn != headlcn )
559
+ break ;
560
+ m -> delta [1 ] = 1 ;
561
+ } else {
562
+ erofs_err (inode -> i_sb , "unknown type %u @ lcn %llu of nid %llu" ,
563
+ m -> type , lcn , vi -> nid );
564
+ DBG_BUGON (1 );
565
+ return - EOPNOTSUPP ;
566
+ }
567
+ lcn += m -> delta [1 ];
568
+ } while (m -> delta [1 ]);
569
+
570
+ map -> m_llen = (lcn << lclusterbits ) + m -> clusterofs - map -> m_la ;
571
+ return 0 ;
572
+ }
573
+
501
574
int z_erofs_map_blocks_iter (struct inode * inode ,
502
575
struct erofs_map_blocks * map ,
503
576
int flags )
@@ -531,7 +604,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
531
604
initial_lcn = ofs >> lclusterbits ;
532
605
endoff = ofs & ((1 << lclusterbits ) - 1 );
533
606
534
- err = z_erofs_load_cluster_from_disk (& m , initial_lcn );
607
+ err = z_erofs_load_cluster_from_disk (& m , initial_lcn , false );
535
608
if (err )
536
609
goto unmap_out ;
537
610
@@ -581,6 +654,12 @@ int z_erofs_map_blocks_iter(struct inode *inode,
581
654
err = z_erofs_get_extent_compressedlen (& m , initial_lcn );
582
655
if (err )
583
656
goto out ;
657
+
658
+ if (flags & EROFS_GET_BLOCKS_FIEMAP ) {
659
+ err = z_erofs_get_extent_decompressedlen (& m );
660
+ if (!err )
661
+ map -> m_flags |= EROFS_MAP_FULL_MAPPED ;
662
+ }
584
663
unmap_out :
585
664
if (m .kaddr )
586
665
kunmap_atomic (m .kaddr );
0 commit comments