~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/mm/swap.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/mm/swap.c
  3  *
  4  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  5  */
  6 
  7 /*
  8  * This file contains the default values for the opereation of the
  9  * Linux VM subsystem. Fine-tuning documentation can be found in
 10  * linux/Documentation/sysctl/vm.txt.
 11  * Started 18.12.91
 12  * Swap aging added 23.2.95, Stephen Tweedie.
 13  * Buffermem limits added 12.3.98, Rik van Riel.
 14  */
 15 
 16 #include <linux/mm.h>
 17 #include <linux/kernel_stat.h>
 18 #include <linux/swap.h>
 19 #include <linux/swapctl.h>
 20 #include <linux/pagemap.h>
 21 #include <linux/init.h>
 22 
 23 #include <asm/dma.h>
 24 #include <asm/uaccess.h> /* for copy_to/from_user */
 25 #include <asm/pgtable.h>
 26 
 27 /*
 28  * We identify three levels of free memory.  We never let free mem
 29  * fall below the freepages.min except for atomic allocations.  We
 30  * start background swapping if we fall below freepages.high free
 31  * pages, and we begin intensive swapping below freepages.low.
 32  *
 33  * Actual initialization is done in mm/page_alloc.c or 
 34  * arch/sparc(64)/mm/init.c.
 35  */
 36 freepages_t freepages = {
 37         0,      /* freepages.min */
 38         0,      /* freepages.low */
 39         0       /* freepages.high */
 40 };
 41 
 42 /* How many pages do we try to swap or page in/out together? */
 43 int page_cluster;
 44 
 45 /*
 46  * This variable contains the amount of page steals the system
 47  * is doing, averaged over a minute. We use this to determine how
 48  * many inactive pages we should have.
 49  *
 50  * In reclaim_page and __alloc_pages: memory_pressure++
 51  * In __free_pages_ok: memory_pressure--
 52  * In recalculate_vm_stats the value is decayed (once a second)
 53  */
 54 int memory_pressure;
 55 
 56 /* We track the number of pages currently being asynchronously swapped
 57    out, so that we don't try to swap TOO many pages out at once */
 58 atomic_t nr_async_pages = ATOMIC_INIT(0);
 59 
 60 buffer_mem_t buffer_mem = {
 61         2,      /* minimum percent buffer */
 62         10,     /* borrow percent buffer */
 63         60      /* maximum percent buffer */
 64 };
 65 
 66 buffer_mem_t page_cache = {
 67         2,      /* minimum percent page cache */
 68         15,     /* borrow percent page cache */
 69         75      /* maximum */
 70 };
 71 
 72 pager_daemon_t pager_daemon = {
 73         512,    /* base number for calculating the number of tries */
 74         SWAP_CLUSTER_MAX,       /* minimum number of tries */
 75         8,      /* do swap I/O in clusters of this size */
 76 };
 77 
 78 /**
 79  * age_page_{up,down} - page aging helper functions
 80  * @page - the page we want to age
 81  * @nolock - are we already holding the pagelist_lru_lock?
 82  *
 83  * If the page is on one of the lists (active, inactive_dirty or
 84  * inactive_clean), we will grab the pagelist_lru_lock as needed.
 85  * If you're already holding the lock, call this function with the
 86  * nolock argument non-zero.
 87  */
 88 void age_page_up_nolock(struct page * page)
 89 {
 90         /*
 91          * We're dealing with an inactive page, move the page
 92          * to the active list.
 93          */
 94         if (!page->age)
 95                 activate_page_nolock(page);
 96 
 97         /* The actual page aging bit */
 98         page->age += PAGE_AGE_ADV;
 99         if (page->age > PAGE_AGE_MAX)
100                 page->age = PAGE_AGE_MAX;
101 }
102 
103 /*
104  * We use this (minimal) function in the case where we
105  * know we can't deactivate the page (yet).
106  */
107 void age_page_down_ageonly(struct page * page)
108 {
109         page->age /= 2;
110 }
111 
112 void age_page_down_nolock(struct page * page)
113 {
114         /* The actual page aging bit */
115         page->age /= 2;
116 
117         /*
118          * The page is now an old page. Move to the inactive
119          * list (if possible ... see below).
120          */
121         if (!page->age)
122                deactivate_page_nolock(page);
123 }
124 
125 void age_page_up(struct page * page)
126 {
127         /*
128          * We're dealing with an inactive page, move the page
129          * to the active list.
130          */
131         if (!page->age)
132                 activate_page(page);
133 
134         /* The actual page aging bit */
135         page->age += PAGE_AGE_ADV;
136         if (page->age > PAGE_AGE_MAX)
137                 page->age = PAGE_AGE_MAX;
138 }
139 
140 void age_page_down(struct page * page)
141 {
142         /* The actual page aging bit */
143         page->age /= 2;
144 
145         /*
146          * The page is now an old page. Move to the inactive
147          * list (if possible ... see below).
148          */
149         if (!page->age)
150                deactivate_page(page);
151 }
152 
153 
154 /**
155  * (de)activate_page - move pages from/to active and inactive lists
156  * @page: the page we want to move
157  * @nolock - are we already holding the pagemap_lru_lock?
158  *
159  * Deactivate_page will move an active page to the right
160  * inactive list, while activate_page will move a page back
161  * from one of the inactive lists to the active list. If
162  * called on a page which is not on any of the lists, the
163  * page is left alone.
164  */
165 void deactivate_page_nolock(struct page * page)
166 {
167         /*
168          * One for the cache, one for the extra reference the
169          * caller has and (maybe) one for the buffers.
170          *
171          * This isn't perfect, but works for just about everything.
172          * Besides, as long as we don't move unfreeable pages to the
173          * inactive_clean list it doesn't need to be perfect...
174          */
175         int maxcount = (page->buffers ? 3 : 2);
176         page->age = 0;
177         ClearPageReferenced(page);
178 
179         /*
180          * Don't touch it if it's not on the active list.
181          * (some pages aren't on any list at all)
182          */
183         if (PageActive(page) && page_count(page) <= maxcount && !page_ramdisk(page)) {
184                 del_page_from_active_list(page);
185                 add_page_to_inactive_dirty_list(page);
186         }
187 }       
188 
189 void deactivate_page(struct page * page)
190 {
191         spin_lock(&pagemap_lru_lock);
192         deactivate_page_nolock(page);
193         spin_unlock(&pagemap_lru_lock);
194 }
195 
196 /*
197  * Move an inactive page to the active list.
198  */
199 void activate_page_nolock(struct page * page)
200 {
201         if (PageInactiveDirty(page)) {
202                 del_page_from_inactive_dirty_list(page);
203                 add_page_to_active_list(page);
204         } else if (PageInactiveClean(page)) {
205                 del_page_from_inactive_clean_list(page);
206                 add_page_to_active_list(page);
207         } else {
208                 /*
209                  * The page was not on any list, so we take care
210                  * not to do anything.
211                  */
212         }
213 
214         /* Make sure the page gets a fair chance at staying active. */
215         if (page->age < PAGE_AGE_START)
216                 page->age = PAGE_AGE_START;
217 }
218 
219 void activate_page(struct page * page)
220 {
221         spin_lock(&pagemap_lru_lock);
222         activate_page_nolock(page);
223         spin_unlock(&pagemap_lru_lock);
224 }
225 
226 /**
227  * lru_cache_add: add a page to the page lists
228  * @page: the page to add
229  */
230 void lru_cache_add(struct page * page)
231 {
232         spin_lock(&pagemap_lru_lock);
233         if (!PageLocked(page))
234                 BUG();
235         DEBUG_ADD_PAGE
236         add_page_to_active_list(page);
237         /* This should be relatively rare */
238         if (!page->age)
239                 deactivate_page_nolock(page);
240         spin_unlock(&pagemap_lru_lock);
241 }
242 
243 /**
244  * __lru_cache_del: remove a page from the page lists
245  * @page: the page to add
246  *
247  * This function is for when the caller already holds
248  * the pagemap_lru_lock.
249  */
250 void __lru_cache_del(struct page * page)
251 {
252         if (PageActive(page)) {
253                 del_page_from_active_list(page);
254         } else if (PageInactiveDirty(page)) {
255                 del_page_from_inactive_dirty_list(page);
256         } else if (PageInactiveClean(page)) {
257                 del_page_from_inactive_clean_list(page);
258         } else {
259                 printk("VM: __lru_cache_del, found unknown page ?!\n");
260         }
261         DEBUG_ADD_PAGE
262 }
263 
264 /**
265  * lru_cache_del: remove a page from the page lists
266  * @page: the page to remove
267  */
268 void lru_cache_del(struct page * page)
269 {
270         if (!PageLocked(page))
271                 BUG();
272         spin_lock(&pagemap_lru_lock);
273         __lru_cache_del(page);
274         spin_unlock(&pagemap_lru_lock);
275 }
276 
277 /**
278  * recalculate_vm_stats - recalculate VM statistics
279  *
280  * This function should be called once a second to recalculate
281  * some useful statistics the VM subsystem uses to determine
282  * its behaviour.
283  */
284 void recalculate_vm_stats(void)
285 {
286         /*
287          * Substract one second worth of memory_pressure from
288          * memory_pressure.
289          */
290         memory_pressure -= (memory_pressure >> INACTIVE_SHIFT);
291 }
292 
293 /*
294  * Perform any setup for the swap system
295  */
296 void __init swap_setup(void)
297 {
298         /* Use a smaller cluster for memory <16MB or <32MB */
299         if (num_physpages < ((16 * 1024 * 1024) >> PAGE_SHIFT))
300                 page_cluster = 2;
301         else if (num_physpages < ((32 * 1024 * 1024) >> PAGE_SHIFT))
302                 page_cluster = 3;
303         else
304                 page_cluster = 4;
305 }
306 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.