Skip to content

Commit 649932f

Browse files
committed
erofs: fix managed cache race for unaligned extents
After unaligned compressed extents were introduced, the following race could occur: [Thread 1] [Thread 2] (z_erofs_fill_bio_vec) <handle a Z_EROFS_PREALLOCATED_FOLIO folio> ... filemap_add_folio (1) (z_erofs_bind_cache) <the same folio is found..> .. .. folio_attach_private (2) filemap_add_folio (3) again Since (1) is executed but (2) hasn't been executed yet, it's possible that another thread finds the same managed folio in z_erofs_bind_cache() for a different pcluster and calls filemap_add_folio() again since folio->private is still Z_EROFS_PREALLOCATED_FOLIO. Fix this by explicitly clearing folio->private before making the folio visible in the managed cache so that another pcluster can simply wait on the locked managed folio as what we did for other shared cases [1]. This only impacts unaligned data compression (`-E48bit` with zstd, for example). [1] Commit 9e2f9d3 ("erofs: handle overlapped pclusters out of crafted images properly") was originally introduced to handle crafted overlapped extents, but it addresses unaligned extents as well. Fixes: 7361d1e ("erofs: support unaligned encoded data") Reported-by: Arseniy Krasnov <avkrasnov@salutedevices.com> Closes: https://lore.kernel.org/r/4a2f3801-fac1-42fe-ae75-da315822e088@salutedevices.com Tested-by: Arseniy Krasnov <avkrasnov@salutedevices.com> Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
1 parent 254f496 commit 649932f

1 file changed

Lines changed: 8 additions & 7 deletions

File tree

fs/erofs/zdata.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,8 +1509,15 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec,
15091509
DBG_BUGON(z_erofs_is_shortlived_page(bvec->bv_page));
15101510

15111511
folio = page_folio(zbv.page);
1512-
/* For preallocated managed folios, add them to page cache here */
1512+
/*
1513+
* Preallocated folios are added to the managed cache here rather than
1514+
* in z_erofs_bind_cache() in order to keep these folios locked in
1515+
* increasing (physical) address order.
1516+
* Clear folio->private before these folios become visible to others in
1517+
* the managed cache to avoid duplicate additions for unaligned extents.
1518+
*/
15131519
if (folio->private == Z_EROFS_PREALLOCATED_FOLIO) {
1520+
folio->private = NULL;
15141521
tocache = true;
15151522
goto out_tocache;
15161523
}
@@ -1546,14 +1553,8 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec,
15461553
}
15471554
return;
15481555
}
1549-
/*
1550-
* Already linked with another pcluster, which only appears in
1551-
* crafted images by fuzzers for now. But handle this anyway.
1552-
*/
1553-
tocache = false; /* use temporary short-lived pages */
15541556
} else {
15551557
DBG_BUGON(1); /* referenced managed folios can't be truncated */
1556-
tocache = true;
15571558
}
15581559
folio_unlock(folio);
15591560
folio_put(folio);

0 commit comments

Comments
 (0)