aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/fs.h64
-rw-r--r--mm/readahead.c19
2 files changed, 83 insertions, 0 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 75dd16efc9b6..9a5f562abc77 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -695,6 +695,10 @@ struct fown_struct {
695 695
696/* 696/*
697 * Track a single file's readahead state 697 * Track a single file's readahead state
698 *
699 * ================#============|==================#==================|
700 * ^ ^ ^ ^
701 * file_ra_state.la_index .ra_index .lookahead_index .readahead_index
698 */ 702 */
699struct file_ra_state { 703struct file_ra_state {
700 unsigned long start; /* Current window */ 704 unsigned long start; /* Current window */
@@ -704,6 +708,12 @@ struct file_ra_state {
704 unsigned long prev_index; /* Cache last read() position */ 708 unsigned long prev_index; /* Cache last read() position */
705 unsigned long ahead_start; /* Ahead window */ 709 unsigned long ahead_start; /* Ahead window */
706 unsigned long ahead_size; 710 unsigned long ahead_size;
711
712 pgoff_t la_index; /* enqueue time */
713 pgoff_t ra_index; /* begin offset */
714 pgoff_t lookahead_index; /* time to do next readahead */
715 pgoff_t readahead_index; /* end offset */
716
707 unsigned long ra_pages; /* Maximum readahead window */ 717 unsigned long ra_pages; /* Maximum readahead window */
708 unsigned long mmap_hit; /* Cache hit stat for mmap accesses */ 718 unsigned long mmap_hit; /* Cache hit stat for mmap accesses */
709 unsigned long mmap_miss; /* Cache miss stat for mmap accesses */ 719 unsigned long mmap_miss; /* Cache miss stat for mmap accesses */
@@ -712,6 +722,60 @@ struct file_ra_state {
712#define RA_FLAG_MISS 0x01 /* a cache miss occured against this file */ 722#define RA_FLAG_MISS 0x01 /* a cache miss occured against this file */
713#define RA_FLAG_INCACHE 0x02 /* file is already in cache */ 723#define RA_FLAG_INCACHE 0x02 /* file is already in cache */
714 724
725/*
726 * Measuring read-ahead sizes.
727 *
728 * |----------- readahead size ------------>|
729 * ===#============|==================#=====================|
730 * |------- invoke interval ------>|-- lookahead size -->|
731 */
732static inline unsigned long ra_readahead_size(struct file_ra_state *ra)
733{
734 return ra->readahead_index - ra->ra_index;
735}
736
737static inline unsigned long ra_lookahead_size(struct file_ra_state *ra)
738{
739 return ra->readahead_index - ra->lookahead_index;
740}
741
742static inline unsigned long ra_invoke_interval(struct file_ra_state *ra)
743{
744 return ra->lookahead_index - ra->la_index;
745}
746
747/*
748 * Check if @index falls in the readahead windows.
749 */
750static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index)
751{
752 return (index >= ra->la_index &&
753 index < ra->readahead_index);
754}
755
756/*
757 * Where is the old read-ahead and look-ahead?
758 */
759static inline void ra_set_index(struct file_ra_state *ra,
760 pgoff_t la_index, pgoff_t ra_index)
761{
762 ra->la_index = la_index;
763 ra->ra_index = ra_index;
764}
765
766/*
767 * Where is the new read-ahead and look-ahead?
768 */
769static inline void ra_set_size(struct file_ra_state *ra,
770 unsigned long ra_size, unsigned long la_size)
771{
772 ra->readahead_index = ra->ra_index + ra_size;
773 ra->lookahead_index = ra->ra_index + ra_size - la_size;
774}
775
776unsigned long ra_submit(struct file_ra_state *ra,
777 struct address_space *mapping, struct file *filp);
778
715struct file { 779struct file {
716 /* 780 /*
717 * fu_list becomes invalid after file_free is called and queued via 781 * fu_list becomes invalid after file_free is called and queued via
diff --git a/mm/readahead.c b/mm/readahead.c
index 7f9bf588c936..072ce8f8357d 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -592,3 +592,22 @@ unsigned long max_sane_readahead(unsigned long nr)
592 return min(nr, (node_page_state(numa_node_id(), NR_INACTIVE) 592 return min(nr, (node_page_state(numa_node_id(), NR_INACTIVE)
593 + node_page_state(numa_node_id(), NR_FREE_PAGES)) / 2); 593 + node_page_state(numa_node_id(), NR_FREE_PAGES)) / 2);
594} 594}
595
596/*
597 * Submit IO for the read-ahead request in file_ra_state.
598 */
599unsigned long ra_submit(struct file_ra_state *ra,
600 struct address_space *mapping, struct file *filp)
601{
602 unsigned long ra_size;
603 unsigned long la_size;
604 int actual;
605
606 ra_size = ra_readahead_size(ra);
607 la_size = ra_lookahead_size(ra);
608 actual = __do_page_cache_readahead(mapping, filp,
609 ra->ra_index, ra_size, la_size);
610
611 return actual;
612}
613EXPORT_SYMBOL_GPL(ra_submit);