Two folio fixes for 5.18:
- Fix a race when we were calling folio_next() in the BIO folio iter without holding a reference, meaning the folio could be split or freed, and we'd jump to the next page instead of the intended next folio. - Fix readahead creating single-page folios instead of the intended large folios when doing reads that are not a power of two in size. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEejHryeLBw/spnjHrDpNsjXcpgj4FAmJ0Xu4ACgkQDpNsjXcp gj4rTAf/Rp2P9jwnOCN9X78YBiydkHq9dtIYbEz1jhOr2pnbz/ZWOeWvVvTBgG5I GSIeaK3dhCBqi6G28QrQR1j1+gOWOJOs/rmJtkkOgBfoGsCL8HLFzcbXR10zeF2K 8bhivsq5tshn2DiVu8WK1W2n25mg4k7ORrBVcuUtW4Am8EPsyJpzoSWBTlZJvClt Re9mIkbWNWktEyRiMl8wA4WRKqysaIWBuf9jugaOrv0Y0Db2TqiqYiAG6xm3VSZy ABf8ZSOyNuxF6ZrW2tUjwdnJ6oDXjVB3Dykw4EQMFQ6uINJPBArj8AkDUe4FJa2w 9FmDLDxR1T4k9+8cEC6ZkkVb6KyvdQ== =KKsJ -----END PGP SIGNATURE----- Merge tag 'folio-5.18f' of git://git.infradead.org/users/willy/pagecache Pull folio fixes from Matthew Wilcox: "Two folio fixes for 5.18. Darrick and Brian have done amazing work debugging the race I created in the folio BIO iterator. The readahead problem was deterministic, so easy to fix. - Fix a race when we were calling folio_next() in the BIO folio iter without holding a reference, meaning the folio could be split or freed, and we'd jump to the next page instead of the intended next folio. - Fix readahead creating single-page folios instead of the intended large folios when doing reads that are not a power of two in size" * tag 'folio-5.18f' of git://git.infradead.org/users/willy/pagecache: mm/readahead: Fix readahead with large folios block: Do not call folio_next() on an unreferenced folio
This commit is contained in:
commit
fe27d189e3
|
@ -269,6 +269,7 @@ struct folio_iter {
|
|||
size_t offset;
|
||||
size_t length;
|
||||
/* private: for use by the iterator */
|
||||
struct folio *_next;
|
||||
size_t _seg_count;
|
||||
int _i;
|
||||
};
|
||||
|
@ -283,6 +284,7 @@ static inline void bio_first_folio(struct folio_iter *fi, struct bio *bio,
|
|||
PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
|
||||
fi->_seg_count = bvec->bv_len;
|
||||
fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
|
||||
fi->_next = folio_next(fi->folio);
|
||||
fi->_i = i;
|
||||
}
|
||||
|
||||
|
@ -290,9 +292,10 @@ static inline void bio_next_folio(struct folio_iter *fi, struct bio *bio)
|
|||
{
|
||||
fi->_seg_count -= fi->length;
|
||||
if (fi->_seg_count) {
|
||||
fi->folio = folio_next(fi->folio);
|
||||
fi->folio = fi->_next;
|
||||
fi->offset = 0;
|
||||
fi->length = min(folio_size(fi->folio), fi->_seg_count);
|
||||
fi->_next = folio_next(fi->folio);
|
||||
} else if (fi->_i + 1 < bio->bi_vcnt) {
|
||||
bio_first_folio(fi, bio, fi->_i + 1);
|
||||
} else {
|
||||
|
|
|
@ -474,7 +474,8 @@ static inline int ra_alloc_folio(struct readahead_control *ractl, pgoff_t index,
|
|||
|
||||
if (!folio)
|
||||
return -ENOMEM;
|
||||
if (mark - index < (1UL << order))
|
||||
mark = round_up(mark, 1UL << order);
|
||||
if (index == mark)
|
||||
folio_set_readahead(folio);
|
||||
err = filemap_add_folio(ractl->mapping, folio, index, gfp);
|
||||
if (err)
|
||||
|
@ -555,8 +556,9 @@ static void ondemand_readahead(struct readahead_control *ractl,
|
|||
struct file_ra_state *ra = ractl->ra;
|
||||
unsigned long max_pages = ra->ra_pages;
|
||||
unsigned long add_pages;
|
||||
unsigned long index = readahead_index(ractl);
|
||||
pgoff_t prev_index;
|
||||
pgoff_t index = readahead_index(ractl);
|
||||
pgoff_t expected, prev_index;
|
||||
unsigned int order = folio ? folio_order(folio) : 0;
|
||||
|
||||
/*
|
||||
* If the request exceeds the readahead window, allow the read to
|
||||
|
@ -575,8 +577,9 @@ static void ondemand_readahead(struct readahead_control *ractl,
|
|||
* It's the expected callback index, assume sequential access.
|
||||
* Ramp up sizes, and push forward the readahead window.
|
||||
*/
|
||||
if ((index == (ra->start + ra->size - ra->async_size) ||
|
||||
index == (ra->start + ra->size))) {
|
||||
expected = round_up(ra->start + ra->size - ra->async_size,
|
||||
1UL << order);
|
||||
if (index == expected || index == (ra->start + ra->size)) {
|
||||
ra->start += ra->size;
|
||||
ra->size = get_next_ra_size(ra, max_pages);
|
||||
ra->async_size = ra->size;
|
||||
|
@ -662,7 +665,7 @@ readit:
|
|||
}
|
||||
|
||||
ractl->_index = ra->start;
|
||||
page_cache_ra_order(ractl, ra, folio ? folio_order(folio) : 0);
|
||||
page_cache_ra_order(ractl, ra, order);
|
||||
}
|
||||
|
||||
void page_cache_sync_ra(struct readahead_control *ractl,
|
||||
|
|
Loading…
Reference in New Issue