@@ -563,21 +563,19 @@ static void z_erofs_bind_cache(struct z_erofs_decompress_frontend *fe)
563
563
__GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN ;
564
564
unsigned int i ;
565
565
566
- if (i_blocksize (fe -> inode ) != PAGE_SIZE )
567
- return ;
568
- if (fe -> mode < Z_EROFS_PCLUSTER_FOLLOWED )
566
+ if (i_blocksize (fe -> inode ) != PAGE_SIZE ||
567
+ fe -> mode < Z_EROFS_PCLUSTER_FOLLOWED )
569
568
return ;
570
569
571
570
for (i = 0 ; i < pclusterpages ; ++ i ) {
572
571
struct page * page , * newpage ;
573
572
void * t ; /* mark pages just found for debugging */
574
573
575
- /* the compressed page was loaded before */
574
+ /* Inaccurate check w/o locking to avoid unneeded lookups */
576
575
if (READ_ONCE (pcl -> compressed_bvecs [i ].page ))
577
576
continue ;
578
577
579
578
page = find_get_page (mc , pcl -> obj .index + i );
580
-
581
579
if (page ) {
582
580
t = (void * )((unsigned long )page | 1 );
583
581
newpage = NULL ;
@@ -597,9 +595,13 @@ static void z_erofs_bind_cache(struct z_erofs_decompress_frontend *fe)
597
595
set_page_private (newpage , Z_EROFS_PREALLOCATED_PAGE );
598
596
t = (void * )((unsigned long )newpage | 1 );
599
597
}
600
-
601
- if (!cmpxchg_relaxed (& pcl -> compressed_bvecs [i ].page , NULL , t ))
598
+ spin_lock (& pcl -> obj .lockref .lock );
599
+ if (!pcl -> compressed_bvecs [i ].page ) {
600
+ pcl -> compressed_bvecs [i ].page = t ;
601
+ spin_unlock (& pcl -> obj .lockref .lock );
602
602
continue ;
603
+ }
604
+ spin_unlock (& pcl -> obj .lockref .lock );
603
605
604
606
if (page )
605
607
put_page (page );
@@ -718,31 +720,25 @@ int erofs_init_managed_cache(struct super_block *sb)
718
720
return 0 ;
719
721
}
720
722
721
- static bool z_erofs_try_inplace_io (struct z_erofs_decompress_frontend * fe ,
722
- struct z_erofs_bvec * bvec )
723
- {
724
- struct z_erofs_pcluster * const pcl = fe -> pcl ;
725
-
726
- while (fe -> icur > 0 ) {
727
- if (!cmpxchg (& pcl -> compressed_bvecs [-- fe -> icur ].page ,
728
- NULL , bvec -> page )) {
729
- pcl -> compressed_bvecs [fe -> icur ] = * bvec ;
730
- return true;
731
- }
732
- }
733
- return false;
734
- }
735
-
736
723
/* callers must be with pcluster lock held */
737
724
static int z_erofs_attach_page (struct z_erofs_decompress_frontend * fe ,
738
725
struct z_erofs_bvec * bvec , bool exclusive )
739
726
{
727
+ struct z_erofs_pcluster * pcl = fe -> pcl ;
740
728
int ret ;
741
729
742
730
if (exclusive ) {
743
731
/* give priority for inplaceio to use file pages first */
744
- if (z_erofs_try_inplace_io (fe , bvec ))
732
+ spin_lock (& pcl -> obj .lockref .lock );
733
+ while (fe -> icur > 0 ) {
734
+ if (pcl -> compressed_bvecs [-- fe -> icur ].page )
735
+ continue ;
736
+ pcl -> compressed_bvecs [fe -> icur ] = * bvec ;
737
+ spin_unlock (& pcl -> obj .lockref .lock );
745
738
return 0 ;
739
+ }
740
+ spin_unlock (& pcl -> obj .lockref .lock );
741
+
746
742
/* otherwise, check if it can be used as a bvpage */
747
743
if (fe -> mode >= Z_EROFS_PCLUSTER_FOLLOWED &&
748
744
!fe -> candidate_bvpage )
@@ -1423,23 +1419,26 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec,
1423
1419
{
1424
1420
gfp_t gfp = mapping_gfp_mask (mc );
1425
1421
bool tocache = false;
1426
- struct z_erofs_bvec * zbv = pcl -> compressed_bvecs + nr ;
1422
+ struct z_erofs_bvec zbv ;
1427
1423
struct address_space * mapping ;
1428
- struct page * page , * oldpage ;
1424
+ struct page * page ;
1429
1425
int justfound , bs = i_blocksize (f -> inode );
1430
1426
1431
1427
/* Except for inplace pages, the entire page can be used for I/Os */
1432
1428
bvec -> bv_offset = 0 ;
1433
1429
bvec -> bv_len = PAGE_SIZE ;
1434
1430
repeat :
1435
- oldpage = READ_ONCE (zbv -> page );
1436
- if (!oldpage )
1431
+ spin_lock (& pcl -> obj .lockref .lock );
1432
+ zbv = pcl -> compressed_bvecs [nr ];
1433
+ page = zbv .page ;
1434
+ justfound = (unsigned long )page & 1UL ;
1435
+ page = (struct page * )((unsigned long )page & ~1UL );
1436
+ pcl -> compressed_bvecs [nr ].page = page ;
1437
+ spin_unlock (& pcl -> obj .lockref .lock );
1438
+ if (!page )
1437
1439
goto out_allocpage ;
1438
1440
1439
- justfound = (unsigned long )oldpage & 1UL ;
1440
- page = (struct page * )((unsigned long )oldpage & ~1UL );
1441
1441
bvec -> bv_page = page ;
1442
-
1443
1442
DBG_BUGON (z_erofs_is_shortlived_page (page ));
1444
1443
/*
1445
1444
* Handle preallocated cached pages. We tried to allocate such pages
@@ -1448,7 +1447,6 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec,
1448
1447
*/
1449
1448
if (page -> private == Z_EROFS_PREALLOCATED_PAGE ) {
1450
1449
set_page_private (page , 0 );
1451
- WRITE_ONCE (zbv -> page , page );
1452
1450
tocache = true;
1453
1451
goto out_tocache ;
1454
1452
}
@@ -1459,9 +1457,9 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec,
1459
1457
* therefore it is impossible for `mapping` to be NULL.
1460
1458
*/
1461
1459
if (mapping && mapping != mc ) {
1462
- if (zbv -> offset < 0 )
1463
- bvec -> bv_offset = round_up (- zbv -> offset , bs );
1464
- bvec -> bv_len = round_up (zbv -> end , bs ) - bvec -> bv_offset ;
1460
+ if (zbv . offset < 0 )
1461
+ bvec -> bv_offset = round_up (- zbv . offset , bs );
1462
+ bvec -> bv_len = round_up (zbv . end , bs ) - bvec -> bv_offset ;
1465
1463
return ;
1466
1464
}
1467
1465
@@ -1471,7 +1469,6 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec,
1471
1469
1472
1470
/* the cached page is still in managed cache */
1473
1471
if (page -> mapping == mc ) {
1474
- WRITE_ONCE (zbv -> page , page );
1475
1472
/*
1476
1473
* The cached page is still available but without a valid
1477
1474
* `->private` pcluster hint. Let's reconnect them.
@@ -1503,11 +1500,15 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec,
1503
1500
put_page (page );
1504
1501
out_allocpage :
1505
1502
page = erofs_allocpage (& f -> pagepool , gfp | __GFP_NOFAIL );
1506
- if (oldpage != cmpxchg (& zbv -> page , oldpage , page )) {
1503
+ spin_lock (& pcl -> obj .lockref .lock );
1504
+ if (pcl -> compressed_bvecs [nr ].page ) {
1507
1505
erofs_pagepool_add (& f -> pagepool , page );
1506
+ spin_unlock (& pcl -> obj .lockref .lock );
1508
1507
cond_resched ();
1509
1508
goto repeat ;
1510
1509
}
1510
+ pcl -> compressed_bvecs [nr ].page = page ;
1511
+ spin_unlock (& pcl -> obj .lockref .lock );
1511
1512
bvec -> bv_page = page ;
1512
1513
out_tocache :
1513
1514
if (!tocache || bs != PAGE_SIZE ||
@@ -1685,6 +1686,7 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f,
1685
1686
1686
1687
if (cur + bvec .bv_len > end )
1687
1688
bvec .bv_len = end - cur ;
1689
+ DBG_BUGON (bvec .bv_len < sb -> s_blocksize );
1688
1690
if (!bio_add_page (bio , bvec .bv_page , bvec .bv_len ,
1689
1691
bvec .bv_offset ))
1690
1692
goto submit_bio_retry ;
0 commit comments