diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-05-05 16:52:15 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-05-05 16:52:15 -0700 |
commit | fe27d189e3f42e31d3c8223d5daed7285e334c5e (patch) | |
tree | 766fa93ae394a9d1bc922d97e8e30fca6ef22312 /include | |
parent | f47c960e9395743a8aa3bd939d4d3a0f582f565e (diff) | |
parent | b9ff43dd27434dbd850b908e2e0e1f6e794efd9b (diff) | |
download | lwn-fe27d189e3f42e31d3c8223d5daed7285e334c5e.tar.gz lwn-fe27d189e3f42e31d3c8223d5daed7285e334c5e.zip |
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
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/bio.h | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/include/linux/bio.h b/include/linux/bio.h index 278cc81cc1e7..00450fd86bb4 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -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 { |