Magellan Linux

Contents of /trunk/kernel26-alx/patches-2.6.20-r6/0022-2.6.20-mm-filesize_dependant_lru_cache_add.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1175 - (show annotations) (download)
Thu Oct 14 12:15:46 2010 UTC (13 years, 6 months ago) by niro
File size: 6637 byte(s)
-2.6.20-alx-r6 new magellan 0.5.2 kernel
1 When reading from large files through the generic file read functions into
2 page cache we can detect when a file is so large that it is unlikely to be
3 fully cached in ram.
4
5 Add a tunable /proc/sys/vm/tail_largefiles that puts them at the tail of the
6 inactive list to minimise their harm on present mapped pages and pagecache
7 and enable it by default.
8
9 Signed-off-by: Con Kolivas <kernel@kolivas.org>
10
11 ---
12 Documentation/filesystems/proc.txt | 8 +++++
13 Documentation/sysctl/vm.txt | 2 -
14 include/linux/sysctl.h | 1
15 kernel/sysctl.c | 9 ++++++
16 mm/filemap.c | 53 +++++++++++++++++++++++++++++++++++--
17 mm/swap.c | 3 --
18 6 files changed, 71 insertions(+), 5 deletions(-)
19
20 Index: linux-2.6.20-ck1/mm/filemap.c
21 ===================================================================
22 --- linux-2.6.20-ck1.orig/mm/filemap.c 2007-02-05 22:52:04.000000000 +1100
23 +++ linux-2.6.20-ck1/mm/filemap.c 2007-02-16 19:01:34.000000000 +1100
24 @@ -466,6 +466,16 @@ int add_to_page_cache_lru(struct page *p
25 return ret;
26 }
27
28 +int add_to_page_cache_lru_tail(struct page *page,
29 + struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
30 +{
31 + int ret = add_to_page_cache(page, mapping, offset, gfp_mask);
32 +
33 + if (ret == 0)
34 + lru_cache_add_tail(page);
35 + return ret;
36 +}
37 +
38 #ifdef CONFIG_NUMA
39 struct page *__page_cache_alloc(gfp_t gfp)
40 {
41 @@ -856,6 +866,34 @@ static void shrink_readahead_size_eio(st
42 ra->ra_pages /= 4;
43 }
44
45 +/*
46 + * Sysctl which determines whether we should read from large files to the
47 + * tail of the inactive lru list.
48 + */
49 +int vm_tail_largefiles __read_mostly = 1;
50 +
51 +static inline int nr_mapped(void)
52 +{
53 + return global_page_state(NR_FILE_MAPPED) +
54 + global_page_state(NR_ANON_PAGES);
55 +}
56 +
57 +/*
58 + * This examines how large in pages a file size is and returns 1 if it is
59 + * more than half the unmapped ram. Avoid doing read_page_state which is
60 + * expensive unless we already know it is likely to be large enough.
61 + */
62 +static int large_isize(unsigned long nr_pages)
63 +{
64 + if (nr_pages * 6 > vm_total_pages) {
65 + unsigned long unmapped_ram = vm_total_pages - nr_mapped();
66 +
67 + if (nr_pages * 2 > unmapped_ram)
68 + return 1;
69 + }
70 + return 0;
71 +}
72 +
73 /**
74 * do_generic_mapping_read - generic file read routine
75 * @mapping: address_space to be read
76 @@ -1064,8 +1102,19 @@ no_cached_page:
77 goto out;
78 }
79 }
80 - error = add_to_page_cache_lru(cached_page, mapping,
81 - index, GFP_KERNEL);
82 +
83 + /*
84 + * If we know the file is large we add the pages read to the
85 + * end of the lru as we're unlikely to be able to cache the
86 + * whole file in ram so make those pages the first to be
87 + * dropped if not referenced soon.
88 + */
89 + if (vm_tail_largefiles && large_isize(end_index))
90 + error = add_to_page_cache_lru_tail(cached_page,
91 + mapping, index, GFP_KERNEL);
92 + else
93 + error = add_to_page_cache_lru(cached_page, mapping,
94 + index, GFP_KERNEL);
95 if (error) {
96 if (error == -EEXIST)
97 goto find_page;
98 Index: linux-2.6.20-ck1/mm/swap.c
99 ===================================================================
100 --- linux-2.6.20-ck1.orig/mm/swap.c 2007-02-16 19:01:33.000000000 +1100
101 +++ linux-2.6.20-ck1/mm/swap.c 2007-02-16 19:01:34.000000000 +1100
102 @@ -434,8 +434,7 @@ void __pagevec_lru_add_active(struct pag
103
104 /*
105 * Function used uniquely to put pages back to the lru at the end of the
106 - * inactive list to preserve the lru order. Currently only used by swap
107 - * prefetch.
108 + * inactive list to preserve the lru order.
109 */
110 void fastcall lru_cache_add_tail(struct page *page)
111 {
112 Index: linux-2.6.20-ck1/kernel/sysctl.c
113 ===================================================================
114 --- linux-2.6.20-ck1.orig/kernel/sysctl.c 2007-02-16 19:01:33.000000000 +1100
115 +++ linux-2.6.20-ck1/kernel/sysctl.c 2007-02-16 19:01:34.000000000 +1100
116 @@ -77,6 +77,7 @@ extern int pid_max_min, pid_max_max;
117 extern int sysctl_drop_caches;
118 extern int percpu_pagelist_fraction;
119 extern int compat_log;
120 +extern int vm_tail_largefiles;
121
122 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
123 static int maxolduid = 65535;
124 @@ -918,6 +919,14 @@ static ctl_table vm_table[] = {
125 .mode = 0644,
126 .proc_handler = &proc_dointvec,
127 },
128 + {
129 + .ctl_name = VM_TAIL_LARGEFILES,
130 + .procname = "tail_largefiles",
131 + .data = &vm_tail_largefiles,
132 + .maxlen = sizeof(int),
133 + .mode = 0644,
134 + .proc_handler = &proc_dointvec,
135 + },
136 #ifdef CONFIG_HUGETLB_PAGE
137 {
138 .ctl_name = VM_HUGETLB_PAGES,
139 Index: linux-2.6.20-ck1/Documentation/filesystems/proc.txt
140 ===================================================================
141 --- linux-2.6.20-ck1.orig/Documentation/filesystems/proc.txt 2007-02-05 22:51:59.000000000 +1100
142 +++ linux-2.6.20-ck1/Documentation/filesystems/proc.txt 2007-02-16 19:01:34.000000000 +1100
143 @@ -1324,6 +1324,14 @@ To free pagecache, dentries and inodes:
144 As this is a non-destructive operation and dirty objects are not freeable, the
145 user should run `sync' first.
146
147 +tail_largefiles
148 +---------------
149 +
150 +When enabled reads from large files to the tail end of the inactive lru list.
151 +This means that any cache from reading large files is dropped very quickly,
152 +preventing loss of mapped ram and useful pagecache when large files are read.
153 +This does, however, make caching less effective when working with large files.
154 +
155
156 2.5 /proc/sys/dev - Device specific parameters
157 ----------------------------------------------
158 Index: linux-2.6.20-ck1/Documentation/sysctl/vm.txt
159 ===================================================================
160 --- linux-2.6.20-ck1.orig/Documentation/sysctl/vm.txt 2007-02-16 19:01:33.000000000 +1100
161 +++ linux-2.6.20-ck1/Documentation/sysctl/vm.txt 2007-02-16 19:01:34.000000000 +1100
162 @@ -39,7 +39,7 @@ Currently, these files are in /proc/sys/
163
164 dirty_ratio, dirty_background_ratio, dirty_expire_centisecs,
165 dirty_writeback_centisecs, vfs_cache_pressure, laptop_mode,
166 -block_dump, swap_token_timeout, drop-caches:
167 +block_dump, swap_token_timeout, drop-caches, tail_largefiles:
168
169 See Documentation/filesystems/proc.txt
170
171 Index: linux-2.6.20-ck1/include/linux/sysctl.h
172 ===================================================================
173 --- linux-2.6.20-ck1.orig/include/linux/sysctl.h 2007-02-16 19:01:33.000000000 +1100
174 +++ linux-2.6.20-ck1/include/linux/sysctl.h 2007-02-16 19:01:34.000000000 +1100
175 @@ -204,6 +204,7 @@ enum
176 VM_MIN_SLAB=35, /* Percent pages ignored by zone reclaim */
177 VM_SWAP_PREFETCH=36, /* swap prefetch */
178 VM_HARDMAPLIMIT=37, /* Make mapped a hard limit */
179 + VM_TAIL_LARGEFILES=38, /* Read large files to lru tail */
180 };
181
182