Make readahead store folio count in readahead_control so that the
filesystem can know in advance how many folios it needs to keep track of.

This is cleared by read_pages() in case it is called from a loop.

The count is accessed by the filesystem with readahead_folio_count().

Signed-off-by: David Howells <[email protected]>
cc: Paulo Alcantara (Red Hat) <[email protected]>
cc: Matthew Wilcox <[email protected]>
cc: [email protected]
cc: [email protected]
cc: [email protected]
---
 include/linux/pagemap.h | 10 ++++++++++
 mm/readahead.c          |  5 +++++
 2 files changed, 15 insertions(+)

diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 31a848485ad9..1de60ecfd6e3 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -1350,6 +1350,7 @@ struct readahead_control {
        struct file_ra_state *ra;
 /* private: use the readahead_* accessors instead */
        pgoff_t _index;
+       unsigned int _nr_folios;
        unsigned int _nr_pages;
        unsigned int _batch_count;
        bool dropbehind;
@@ -1529,6 +1530,15 @@ static inline size_t readahead_batch_length(const struct 
readahead_control *rac)
        return rac->_batch_count * PAGE_SIZE;
 }
 
+/**
+ * readahead_folio_count - Get the number of folios in this readahead request.
+ * @rac: The readahead request.
+ */
+static inline unsigned int readahead_folio_count(const struct 
readahead_control *rac)
+{
+       return rac->_nr_folios;
+}
+
 static inline unsigned long dir_pages(const struct inode *inode)
 {
        return (unsigned long)(inode->i_size + PAGE_SIZE - 1) >>
diff --git a/mm/readahead.c b/mm/readahead.c
index 7b05082c89ea..eba194f4635f 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -177,6 +177,7 @@ static void read_pages(struct readahead_control *rac)
        if (unlikely(rac->_workingset))
                psi_memstall_leave(&rac->_pflags);
        rac->_workingset = false;
+       rac->_nr_folios = 0;
 
        BUG_ON(readahead_count(rac));
 }
@@ -292,6 +293,7 @@ void page_cache_ra_unbounded(struct readahead_control 
*ractl,
                if (i == mark)
                        folio_set_readahead(folio);
                ractl->_workingset |= folio_test_workingset(folio);
+               ractl->_nr_folios++;
                ractl->_nr_pages += min_nrpages;
                i += min_nrpages;
        }
@@ -459,6 +461,7 @@ static inline int ra_alloc_folio(struct readahead_control 
*ractl, pgoff_t index,
                return err;
        }
 
+       ractl->_nr_folios++;
        ractl->_nr_pages += 1UL << order;
        ractl->_workingset |= folio_test_workingset(folio);
        return 0;
@@ -802,6 +805,7 @@ void readahead_expand(struct readahead_control *ractl,
                        ractl->_workingset = true;
                        psi_memstall_enter(&ractl->_pflags);
                }
+               ractl->_nr_folios++;
                ractl->_nr_pages += min_nrpages;
                ractl->_index = folio->index;
        }
@@ -831,6 +835,7 @@ void readahead_expand(struct readahead_control *ractl,
                        ractl->_workingset = true;
                        psi_memstall_enter(&ractl->_pflags);
                }
+               ractl->_nr_folios++;
                ractl->_nr_pages += min_nrpages;
                if (ra) {
                        ra->size += min_nrpages;


Reply via email to