Commit 9567413c authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: bch2_readahead() large folio conversion

Readahead now uses the new filemap_get_contig_folios_d() helper.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 40022c01
...@@ -35,6 +35,49 @@ ...@@ -35,6 +35,49 @@
#include <trace/events/writeback.h> #include <trace/events/writeback.h>
struct folio_vec {
struct folio *fv_folio;
size_t fv_offset;
size_t fv_len;
};
static inline struct folio_vec biovec_to_foliovec(struct bio_vec bv)
{
struct folio *folio = page_folio(bv.bv_page);
size_t offset = (folio_page_idx(folio, bv.bv_page) << PAGE_SHIFT) +
bv.bv_offset;
size_t len = min_t(size_t, folio_size(folio) - offset, bv.bv_len);
return (struct folio_vec) {
.fv_folio = folio,
.fv_offset = offset,
.fv_len = len,
};
}
static inline struct folio_vec bio_iter_iovec_folio(struct bio *bio,
struct bvec_iter iter)
{
return biovec_to_foliovec(bio_iter_iovec(bio, iter));
}
#define __bio_for_each_folio(bvl, bio, iter, start) \
for (iter = (start); \
(iter).bi_size && \
((bvl = bio_iter_iovec_folio((bio), (iter))), 1); \
bio_advance_iter_single((bio), &(iter), (bvl).fv_len))
/**
* bio_for_each_folio - iterate over folios within a bio
*
* Like other non-_all versions, this iterates over what bio->bi_iter currently
* points to. This version is for drivers, where the bio may have previously
* been split or cloned.
*/
#define bio_for_each_folio(bvl, bio, iter) \
__bio_for_each_folio(bvl, bio, iter, (bio)->bi_iter)
static inline loff_t folio_end_pos(struct folio *folio) static inline loff_t folio_end_pos(struct folio *folio)
{ {
return folio_pos(folio) + folio_size(folio); return folio_pos(folio) + folio_size(folio);
...@@ -622,14 +665,16 @@ static int bch2_folio_set(struct bch_fs *c, subvol_inum inum, ...@@ -622,14 +665,16 @@ static int bch2_folio_set(struct bch_fs *c, subvol_inum inum,
static void bch2_bio_page_state_set(struct bio *bio, struct bkey_s_c k) static void bch2_bio_page_state_set(struct bio *bio, struct bkey_s_c k)
{ {
struct bvec_iter iter; struct bvec_iter iter;
struct bio_vec bv; struct folio_vec fv;
unsigned nr_ptrs = k.k->type == KEY_TYPE_reflink_v unsigned nr_ptrs = k.k->type == KEY_TYPE_reflink_v
? 0 : bch2_bkey_nr_ptrs_fully_allocated(k); ? 0 : bch2_bkey_nr_ptrs_fully_allocated(k);
unsigned state = bkey_to_sector_state(k); unsigned state = bkey_to_sector_state(k);
bio_for_each_segment(bv, bio, iter) bio_for_each_folio(fv, bio, iter)
__bch2_folio_set(page_folio(bv.bv_page), bv.bv_offset >> 9, __bch2_folio_set(fv.fv_folio,
bv.bv_len >> 9, nr_ptrs, state); fv.fv_offset >> 9,
fv.fv_len >> 9,
nr_ptrs, state);
} }
static void mark_pagecache_unallocated(struct bch_inode_info *inode, static void mark_pagecache_unallocated(struct bch_inode_info *inode,
...@@ -1049,44 +1094,48 @@ static void bch2_readpages_end_io(struct bio *bio) ...@@ -1049,44 +1094,48 @@ static void bch2_readpages_end_io(struct bio *bio)
struct readpages_iter { struct readpages_iter {
struct address_space *mapping; struct address_space *mapping;
struct page **pages;
unsigned nr_pages;
unsigned idx; unsigned idx;
pgoff_t offset; folios folios;
}; };
static int readpages_iter_init(struct readpages_iter *iter, static int readpages_iter_init(struct readpages_iter *iter,
struct readahead_control *ractl) struct readahead_control *ractl)
{ {
unsigned i, nr_pages = readahead_count(ractl); struct folio **fi;
int ret;
memset(iter, 0, sizeof(*iter)); memset(iter, 0, sizeof(*iter));
iter->mapping = ractl->mapping; iter->mapping = ractl->mapping;
iter->offset = readahead_index(ractl);
iter->nr_pages = nr_pages;
iter->pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_NOFS); ret = filemap_get_contig_folios_d(iter->mapping,
if (!iter->pages) ractl->_index << PAGE_SHIFT,
return -ENOMEM; (ractl->_index + ractl->_nr_pages) << PAGE_SHIFT,
0, mapping_gfp_mask(iter->mapping),
&iter->folios);
if (ret)
return ret;
nr_pages = __readahead_batch(ractl, iter->pages, nr_pages); darray_for_each(iter->folios, fi) {
for (i = 0; i < nr_pages; i++) { ractl->_nr_pages -= 1U << folio_order(*fi);
__bch2_folio_create(page_folio(iter->pages[i]), __GFP_NOFAIL); __bch2_folio_create(*fi, __GFP_NOFAIL);
put_page(iter->pages[i]); folio_put(*fi);
folio_put(*fi);
} }
return 0; return 0;
} }
static inline struct folio *readpage_iter_next(struct readpages_iter *iter) static inline struct folio *readpage_iter_peek(struct readpages_iter *iter)
{ {
if (iter->idx >= iter->nr_pages) if (iter->idx >= iter->folios.nr)
return NULL; return NULL;
return iter->folios.data[iter->idx];
}
EBUG_ON(iter->pages[iter->idx]->index != iter->offset + iter->idx); static inline void readpage_iter_advance(struct readpages_iter *iter)
{
return page_folio(iter->pages[iter->idx]); iter->idx++;
} }
static bool extent_partial_reads_expensive(struct bkey_s_c k) static bool extent_partial_reads_expensive(struct bkey_s_c k)
...@@ -1108,16 +1157,14 @@ static void readpage_bio_extend(struct readpages_iter *iter, ...@@ -1108,16 +1157,14 @@ static void readpage_bio_extend(struct readpages_iter *iter,
{ {
while (bio_sectors(bio) < sectors_this_extent && while (bio_sectors(bio) < sectors_this_extent &&
bio->bi_vcnt < bio->bi_max_vecs) { bio->bi_vcnt < bio->bi_max_vecs) {
pgoff_t folio_offset = bio_end_sector(bio) >> PAGE_SECTORS_SHIFT; struct folio *folio = readpage_iter_peek(iter);
struct folio *folio = readpage_iter_next(iter);
int ret; int ret;
if (folio) { if (folio) {
if (iter->offset + iter->idx != folio_offset) readpage_iter_advance(iter);
break;
iter->idx++;
} else { } else {
pgoff_t folio_offset = bio_end_sector(bio) >> PAGE_SECTORS_SHIFT;
if (!get_more) if (!get_more)
break; break;
...@@ -1144,6 +1191,8 @@ static void readpage_bio_extend(struct readpages_iter *iter, ...@@ -1144,6 +1191,8 @@ static void readpage_bio_extend(struct readpages_iter *iter,
folio_put(folio); folio_put(folio);
} }
BUG_ON(folio_sector(folio) != bio_end_sector(bio));
BUG_ON(!bio_add_folio(bio, folio, folio_size(folio), 0)); BUG_ON(!bio_add_folio(bio, folio, folio_size(folio), 0));
} }
} }
...@@ -1275,10 +1324,9 @@ void bch2_readahead(struct readahead_control *ractl) ...@@ -1275,10 +1324,9 @@ void bch2_readahead(struct readahead_control *ractl)
bch2_pagecache_add_get(inode); bch2_pagecache_add_get(inode);
while ((folio = readpage_iter_next(&readpages_iter))) { while ((folio = readpage_iter_peek(&readpages_iter))) {
pgoff_t index = readpages_iter.offset + readpages_iter.idx;
unsigned n = min_t(unsigned, unsigned n = min_t(unsigned,
readpages_iter.nr_pages - readpages_iter.folios.nr -
readpages_iter.idx, readpages_iter.idx,
BIO_MAX_VECS); BIO_MAX_VECS);
struct bch_read_bio *rbio = struct bch_read_bio *rbio =
...@@ -1286,9 +1334,9 @@ void bch2_readahead(struct readahead_control *ractl) ...@@ -1286,9 +1334,9 @@ void bch2_readahead(struct readahead_control *ractl)
GFP_NOFS, &c->bio_read), GFP_NOFS, &c->bio_read),
opts); opts);
readpages_iter.idx++; readpage_iter_advance(&readpages_iter);
rbio->bio.bi_iter.bi_sector = (sector_t) index << PAGE_SECTORS_SHIFT; rbio->bio.bi_iter.bi_sector = folio_sector(folio);
rbio->bio.bi_end_io = bch2_readpages_end_io; rbio->bio.bi_end_io = bch2_readpages_end_io;
BUG_ON(!bio_add_folio(&rbio->bio, folio, folio_size(folio), 0)); BUG_ON(!bio_add_folio(&rbio->bio, folio, folio_size(folio), 0));
...@@ -1299,7 +1347,7 @@ void bch2_readahead(struct readahead_control *ractl) ...@@ -1299,7 +1347,7 @@ void bch2_readahead(struct readahead_control *ractl)
bch2_pagecache_add_put(inode); bch2_pagecache_add_put(inode);
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
kfree(readpages_iter.pages); darray_exit(&readpages_iter.folios);
} }
static void __bchfs_readfolio(struct bch_fs *c, struct bch_read_bio *rbio, static void __bchfs_readfolio(struct bch_fs *c, struct bch_read_bio *rbio,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment