/[lkdp]/lkdp/mm/swapping.tex
ViewVC logotype

Diff of /lkdp/mm/swapping.tex

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.9 by rcastro, Tue Jul 2 13:31:20 2002 UTC revision 1.10 by rcastro, Tue Jul 2 20:42:47 2002 UTC
# Line 12  functions are started in \texttt{do\_ini Line 12  functions are started in \texttt{do\_ini
12  \subsection{Function kswapd\_init()}  \subsection{Function kswapd\_init()}
13       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
14       \textit{Prototype: }       \textit{Prototype: }
15          \begin{verbatim}   \begin{verbatim}
16          static int __init kswapd_init(void)   static int __init kswapd_init(void)
17          \end{verbatim}   \end{verbatim}
18            
19       This initialization function simply performs any necessary swap       This initialization function simply performs any necessary swap
20       setup and starts \texttt{kswapd()} function as a kernel thread.       setup and starts \texttt{kswapd()} function as a kernel thread.
21    
22          \begin{verbatim}   \begin{verbatim}
23          printk("Starting kswapd\n");   printk("Starting kswapd\n");
24          swap_setup();   swap_setup();
25          kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);   kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
26          return 0;   return 0;
27          \end{verbatim}   \end{verbatim}
28    
29  \subsection{Function kswapd()}  \subsection{Function kswapd()}
30       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
31       \textit{Prototype: }       \textit{Prototype: }
32          \begin{verbatim}   \begin{verbatim}
33          int kswapd(void *unused)  int kswapd(void *unused)
34          \end{verbatim}  \end{verbatim}
35            
36       The \texttt{kswap()} function is run as a kernel thread. Its main       The \texttt{kswap()} function is run as a kernel thread. Its main
37       role in the virtual memory system is to perform the pageout       role in the virtual memory system is to perform the pageout
# Line 40  functions are started in \texttt{do\_ini Line 40  functions are started in \texttt{do\_ini
40       for allocation.  This process is done on a per-zone basis for       for allocation.  This process is done on a per-zone basis for
41       each node (if it is a NUMA system).       each node (if it is a NUMA system).
42    
43          \begin{verbatim}  \begin{verbatim}
44          struct task_struct *tsk = current;  struct task_struct *tsk = current;
45          DECLARE_WAITQUEUE(wait, tsk);  DECLARE_WAITQUEUE(wait, tsk);
46          \end{verbatim}  \end{verbatim}
47            
48       A waitqueue is declared to be added to the \texttt{kswapd\_wait}       A waitqueue is declared to be added to the \texttt{kswapd\_wait}
49       waitqueue header below. It will be used by       waitqueue header below. It will be used by
50       \texttt{\_\_alloc\_pages()} to know if it can wake up and to       \texttt{\_\_alloc\_pages()} to know if it can wake up and to
51       actually wake up kswapd process.       actually wake up kswapd process.
52    
53          \begin{verbatim}  \begin{verbatim}
54          daemonize();  daemonize();
55          strcpy(tsk->comm, "kswapd");  strcpy(tsk->comm, "kswapd");
56          sigfillset(&tsk->blocked);  sigfillset(&tsk->blocked);
57          \end{verbatim}  
58    /*
59          \begin{verbatim}           * Tell the memory management that we're a "memory allocator",
60          /*   * and that if we need more memory we should get access to it
61           * Tell the memory management that we're a "memory allocator",   * regardless (see "__alloc_pages()"). "kswapd" should
62           * and that if we need more memory we should get access to it   * never get caught in the normal page freeing logic.
63           * regardless (see "__alloc_pages()"). "kswapd" should   *
64           * never get caught in the normal page freeing logic.   * (Kswapd normally doesn't need memory anyway, but sometimes
65           *   * you need a small amount of memory in order to be able to
66           * (Kswapd normally doesn't need memory anyway, but sometimes   * page out something else, and this flag essentially protects
67           * you need a small amount of memory in order to be able to   * us from recursively trying to free more memory as we're
68           * page out something else, and this flag essentially protects   * trying to free the first piece of memory in the first place).
69           * us from recursively trying to free more memory as we're   */
70           * trying to free the first piece of memory in the first place).  tsk->flags |= PF_MEMALLOC;
71           */  
72          tsk->flags |= PF_MEMALLOC;  /*
73     * Kswapd main loop.
74          /*   */
75           * Kswapd main loop.  for (;;) {
76           */      __set_current_state(TASK_INTERRUPTIBLE);
77          for (;;) {  \end{verbatim}
             __set_current_state(TASK_INTERRUPTIBLE);  
         \end{verbatim}  
78    
79       That sets the task flag to be interruptible if \texttt{kswap}       That sets the task flag to be interruptible if \texttt{kswap}
80       sleeps below.       sleeps below.
81    
82          \begin{verbatim}  \begin{verbatim}
83              add_wait_queue(&kswapd_wait, &wait);      add_wait_queue(&kswapd_wait, &wait);
84          \end{verbatim}  \end{verbatim}
85            
86       Adding \texttt{wait} to the \texttt{kswapd\_wait} waitqueue header       Adding \texttt{wait} to the \texttt{kswapd\_wait} waitqueue header
87       turns \texttt{kswapd\_wait} into an \textbf{active} wait queue. In       turns \texttt{kswapd\_wait} into an \textbf{active} wait queue. In
# Line 91  functions are started in \texttt{do\_ini Line 89  functions are started in \texttt{do\_ini
89       free pages in any zone is under the minimum limit, \texttt{kswap}       free pages in any zone is under the minimum limit, \texttt{kswap}
90       will be able to be awaken (if it is sleeping).       will be able to be awaken (if it is sleeping).
91    
92          \begin{verbatim}  \begin{verbatim}
93              mb();      mb();
94          \end{verbatim}  \end{verbatim}
95            
96       This stands for \emph{memory barrier} and ensures that memory       This stands for \emph{memory barrier} and ensures that memory
97       ordering will happen, ie, that on a SMP system each CPU have the       ordering will happen, ie, that on a SMP system each CPU have the
98       same view of the memory.       same view of the memory.
99    
100          \begin{verbatim}  \begin{verbatim}
101              if (kswapd_can_sleep())      if (kswapd_can_sleep())
102                  schedule();          schedule();
103          \end{verbatim}  \end{verbatim}
104            
105       Here \texttt{kswapd} checks if any zone in any node needs to be       Here \texttt{kswapd} checks if any zone in any node needs to be
106       balanced. A zone will be marked ``to be balanced'' (actually       balanced. A zone will be marked ``to be balanced'' (actually
# Line 112  functions are started in \texttt{do\_ini Line 110  functions are started in \texttt{do\_ini
110       has to be balanced, \texttt{kswapd} sleeps by calling       has to be balanced, \texttt{kswapd} sleeps by calling
111       \texttt{schedule()}.       \texttt{schedule()}.
112    
113          \begin{verbatim}  \begin{verbatim}
114              __set_current_state(TASK_RUNNING);      __set_current_state(TASK_RUNNING);
115              remove_wait_queue(&kswapd_wait, &wait);      remove_wait_queue(&kswapd_wait, &wait);
116          \end{verbatim}  \end{verbatim}
117            
118       After \texttt{kswapd} is waken up, its current task state is set       After \texttt{kswapd} is waken up, its current task state is set
119       to \texttt{RUNNING} and \texttt{wait} is removed from       to \texttt{RUNNING} and \texttt{wait} is removed from
# Line 124  functions are started in \texttt{do\_ini Line 122  functions are started in \texttt{do\_ini
122       any longer, since that \texttt{kswapd} will be already running       any longer, since that \texttt{kswapd} will be already running
123       trying to balance all zones under memory shortage.       trying to balance all zones under memory shortage.
124    
125          \begin{verbatim}  \begin{verbatim}
126             /*     /*
127              * If we actually get into a low-memory situation,      * If we actually get into a low-memory situation,
128              * the processes needing more memory will wake us      * the processes needing more memory will wake us
129              * up on a more timely basis.      * up on a more timely basis.
130              */      */
131              kswapd_balance();      kswapd_balance();
132          \end{verbatim}  \end{verbatim}
133            
134       That's the part of \texttt{kswapd} where it actually does it       That's the part of \texttt{kswapd} where it actually does it
135       work. The \texttt{kswapd\_balance()} tries to free enough pages       work. The \texttt{kswapd\_balance()} tries to free enough pages
# Line 139  functions are started in \texttt{do\_ini Line 137  functions are started in \texttt{do\_ini
137       freeing a number of pages to make the zone to end up having more       freeing a number of pages to make the zone to end up having more
138       free pages than its minimum watermark.       free pages than its minimum watermark.
139    
140          \begin{verbatim}  \begin{verbatim}
141              run_task_queue(&tq_disk);      run_task_queue(&tq_disk);
142          }  }
143          \end{verbatim}  \end{verbatim}
144            
145       Now it runs the task queue tq\_disk to perform disk related bottom       Now it runs the task queue tq\_disk to perform disk related bottom
146       half activities. Since \texttt{kswapd} might have written some       half activities. Since \texttt{kswapd} might have written some
# Line 152  functions are started in \texttt{do\_ini Line 150  functions are started in \texttt{do\_ini
150  \subsection{Function try\_to\_swap\_out()}  \subsection{Function try\_to\_swap\_out()}
151       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
152       \textit{Prototype: }       \textit{Prototype: }
153          \begin{verbatim}  \begin{verbatim}
154          int try_to_swap_out(struct mm_struct * mm,  int try_to_swap_out(struct mm_struct * mm,
155                              struct vm_area_struct* vma,              struct vm_area_struct* vma,
156                              unsigned long address,                      unsigned long address,
157                              pte_t * page_table,                      pte_t * page_table,
158                              struct page *page,                      struct page *page,
159                              zone_t * classzone)                      zone_t * classzone)
160          \end{verbatim}  \end{verbatim}
161            
162       The role of the \texttt{try\_to\_swap\_out()} function is to try       The role of the \texttt{try\_to\_swap\_out()} function is to try
163       to unmap pages from processes mapping them. This is the first       to unmap pages from processes mapping them. This is the first
# Line 179  functions are started in \texttt{do\_ini Line 177  functions are started in \texttt{do\_ini
177       last process (no process is mapping it at the moment this       last process (no process is mapping it at the moment this
178       function exits).       function exits).
179    
180          \begin{verbatim}  \begin{verbatim}
181          pte_t pte;  pte_t pte;
182          swp_entry_t entry;  swp_entry_t entry;
183    
184          /* Don't look at this pte if it's been accessed recently. */  /* Don't look at this pte if it's been accessed recently. */
185          if ((vma->vm_flags & VM_LOCKED)  if ((vma->vm_flags & VM_LOCKED)
186              || ptep_test_and_clear_young(page_table)) {      || ptep_test_and_clear_young(page_table)) {
187              mark_page_accessed(page);      mark_page_accessed(page);
188              return 0;      return 0;
189          }  }
190          \end{verbatim}  \end{verbatim}
191            
192       That is part of VM aging process. Here, based on the young bit       That is part of VM aging process. Here, based on the young bit
193       from page table entries (pte), \texttt{try\_to\_swap\_out()} sets       from page table entries (pte), \texttt{try\_to\_swap\_out()} sets
# Line 198  functions are started in \texttt{do\_ini Line 196  functions are started in \texttt{do\_ini
196       \texttt{mark\_page\_accessed()} will move this page to the active       \texttt{mark\_page\_accessed()} will move this page to the active
197       list.       list.
198    
199          \begin{verbatim}  \begin{verbatim}
200          /* Don't bother unmapping pages that are active */  /* Don't bother unmapping pages that are active */
201          if (PageActive(page))  if (PageActive(page))
202              return 0;      return 0;
203          \end{verbatim}  \end{verbatim}
204            
205       Active pages are supposed to have been accessed often, so it is       Active pages are supposed to have been accessed often, so it is
206       worthless to unmap them since it is likely they will be mapped       worthless to unmap them since it is likely they will be mapped
207       back soon.       back soon.
208    
209          \begin{verbatim}  \begin{verbatim}
210          /* Don't bother replenishing zones not under pressure.. */  /* Don't bother replenishing zones not under pressure.. */
211          if (!memclass(page_zone(page), classzone))  if (!memclass(page_zone(page), classzone))
212              return 0;      return 0;
213          \end{verbatim}  \end{verbatim}
214            
215       Neither it is sensible to free pages from zones other that the       Neither it is sensible to free pages from zones other that the
216       ones that are under memory shortage.       ones that are under memory shortage.
217    
218          \begin{verbatim}  \begin{verbatim}
219          if (TryLockPage(page))  if (TryLockPage(page))
220              return 0;      return 0;
221          \end{verbatim}  \end{verbatim}
222            
223       The page is tried to lock at once given that the unmapping       The page is tried to lock at once given that the unmapping
224       process is not dependant on an specific page and it is not worth       process is not dependant on an specific page and it is not worth
225       to sleep to try to unmap any page.       to sleep to try to unmap any page.
226            
227          \begin{verbatim}  \begin{verbatim}
228          /* From this point on, the odds are that we're going to  /* From this point on, the odds are that we're going to
229           * nuke this pte, so read and clear the pte.  This hook   * nuke this pte, so read and clear the pte.  This hook
230           * is needed on CPUs which update the accessed and dirty   * is needed on CPUs which update the accessed and dirty
231           * bits in hardware.   * bits in hardware.
232           */   */
233          flush_cache_page(vma, address);  flush_cache_page(vma, address);
234          pte = ptep_get_and_clear(page_table);  pte = ptep_get_and_clear(page_table);
235          flush_tlb_page(vma, address);  flush_tlb_page(vma, address);
236          \end{verbatim}  \end{verbatim}
237    
238       Research.       Research.
239    
240          \begin{verbatim}  \begin{verbatim}
241          if (pte_dirty(pte))  if (pte_dirty(pte))
242              set_page_dirty(page);      set_page_dirty(page);
243          \end{verbatim}  \end{verbatim}
244    
245          \begin{verbatim}  \begin{verbatim}
246          /*  /*
247           * Is the page already in the swap cache? If so, then   * Is the page already in the swap cache? If so, then
248           * we can just drop our reference to it without doing   * we can just drop our reference to it without doing
249           * any IO - it's already up-to-date on disk.   * any IO - it's already up-to-date on disk.
250           */   */
251          if (PageSwapCache(page)) {  if (PageSwapCache(page)) {
252              entry.val = page->index;      entry.val = page->index;
253              swap_duplicate(entry);      swap_duplicate(entry);
254          set_swap_pte:  set_swap_pte:
255              set_pte(page_table, swp_entry_to_pte(entry));      set_pte(page_table, swp_entry_to_pte(entry));
256          \end{verbatim}  \end{verbatim}
257            
258       In the case this page has already been added to the swap cache,       In the case this page has already been added to the swap cache,
259       there is only the need to increase the swap counter (by       there is only the need to increase the swap counter (by
# Line 263  functions are started in \texttt{do\_ini Line 261  functions are started in \texttt{do\_ini
261       address. The swap address is stored in the \texttt{index} field       address. The swap address is stored in the \texttt{index} field
262       of the \texttt{struct page}.       of the \texttt{struct page}.
263    
264          \begin{verbatim}  \begin{verbatim}
265          drop_pte:  drop_pte:
266              mm->rss--;      mm->rss--;
267              UnlockPage(page);      UnlockPage(page);
268              {      {
269                  int freeable = page_count(page) - !!page->buffers <= 2;          int freeable = page_count(page) - !!page->buffers <= 2;
270                  page_cache_release(page);          page_cache_release(page);
271                  return freeable;          return freeable;
272              }      }
273          }  }
274          \end{verbatim}  \end{verbatim}
275            
276       If any process is no longer mapped to this page, the return value       If any process is no longer mapped to this page, the return value
277       is 1, since this page is completely unmapped from the processes       is 1, since this page is completely unmapped from the processes
278       and can be freed.       and can be freed.
279            
280          \begin{verbatim}  \begin{verbatim}
281          /*  /*
282           * Is it a clean page? Then it must be recoverable  * Is it a clean page? Then it must be recoverable
283           * by just paging it in again, and we can just drop   * by just paging it in again, and we can just drop
284           * it..  or if it's dirty but has backing store,   * it..  or if it's dirty but has backing store,
285           * just mark the page dirty and drop it.   * just mark the page dirty and drop it.
286           *   *
287           * However, this won't actually free any real   * However, this won't actually free any real
288           * memory, as the page will just be in the page cache   * memory, as the page will just be in the page cache
289           * somewhere, and as such we should just continue   * somewhere, and as such we should just continue
290           * our scan.   * our scan.
291           *   *
292           * Basically, this just makes it possible for us to do   * Basically, this just makes it possible for us to do
293           * some real work in the future in "refill_inactive()".   * some real work in the future in "refill_inactive()".
294           */   */
295          if (page->mapping)  if (page->mapping)
296              goto drop_pte;      goto drop_pte;
297          if (!PageDirty(page))  if (!PageDirty(page))
298              goto drop_pte;      goto drop_pte;
299    
300          /*  /*
301           * Anonymous buffercache pages can be left behind by   * Anonymous buffercache pages can be left behind by
302           * concurrent truncate and pagefault.   * concurrent truncate and pagefault.
303           */   */
304          if (page->buffers)  if (page->buffers)
305              goto preserve;      goto preserve;
306          \end{verbatim}  \end{verbatim}
307            
308       Anonymous pages are pages without backing store, ie. not mapped       Anonymous pages are pages without backing store, ie. not mapped
309       to any address space. Anonymous buffer cache pages are anonymous       to any address space. Anonymous buffer cache pages are anonymous
310       pages with buffers. In particular, these pages have already been       pages with buffers. In particular, these pages have already been
311       mapped to an address space, but aren't any longer.       mapped to an address space, but aren't any longer.
312    
313          \begin{verbatim}  \begin{verbatim}
314          /*  /*
315           * This is a dirty, swappable page.  First of all,   * This is a dirty, swappable page.  First of all,
316           * get a suitable swap entry for it, and make sure   * get a suitable swap entry for it, and make sure
317           * we have the swap cache set up to associate the   * we have the swap cache set up to associate the
318           * page with that swap entry.   * page with that swap entry.
319           */   */
320          for (;;) {  for (;;) {
321              entry = get_swap_page();      entry = get_swap_page();
322              if (!entry.val)      if (!entry.val)
323                  break;         break;
324              /* Add it to the swap cache and mark it dirty      /* Add it to the swap cache and mark it dirty
325              * (adding to the page cache will clear the dirty       * (adding to the page cache will clear the dirty
326              * and uptodate bits, so we need to do it again)       * and uptodate bits, so we need to do it again)
327              */       */
328              if (add_to_swap_cache(page, entry) == 0) {      if (add_to_swap_cache(page, entry) == 0) {
329                  SetPageUptodate(page);          SetPageUptodate(page);
330                  set_page_dirty(page);          set_page_dirty(page);
331                  goto set_swap_pte;          goto set_swap_pte;
332              }      }
333          \end{verbatim}  \end{verbatim}
334            
335       That is a dirty and anonymous page, so let's get a swap entry for       That is a dirty and anonymous page, so let's get a swap entry for
336       it in order to remap its \emph{pte} to this new address. Later       it in order to remap its \emph{pte} to this new address. Later
# Line 344  functions are started in \texttt{do\_ini Line 342  functions are started in \texttt{do\_ini
342       anonymous page), this page needs to be set as dirty in order to       anonymous page), this page needs to be set as dirty in order to
343       be written.       be written.
344    
345          \begin{verbatim}  \begin{verbatim}
346              /* Raced with "speculative" read_swap_cache_async */      /* Raced with "speculative" read_swap_cache_async */
347              swap_free(entry);      swap_free(entry);
348          }  }
349          \end{verbatim}  \end{verbatim}
350            
351       When servicing a page fault for a swap address, some pages are       When servicing a page fault for a swap address, some pages are
352       read ahead if the page is not present in the swap cache. In this       read ahead if the page is not present in the swap cache. In this
# Line 362  functions are started in \texttt{do\_ini Line 360  functions are started in \texttt{do\_ini
360       necessary to drop the counter of this swap entry and get a new       necessary to drop the counter of this swap entry and get a new
361       one.       one.
362    
363          \begin{verbatim}  \begin{verbatim}
364          /* No swap space left */  /* No swap space left */
365       preserve:       preserve:
366          set_pte(page_table, pte);          set_pte(page_table, pte);
367          UnlockPage(page);          UnlockPage(page);
368          return 0;          return 0;
369          \end{verbatim}  \end{verbatim}
370            
371       No swap space is left, what \texttt{try\_to\_swap\_out()} is       No swap space is left, what \texttt{try\_to\_swap\_out()} is
372       unable to unmap this anonymous page. Let's set the page table       unable to unmap this anonymous page. Let's set the page table
# Line 378  functions are started in \texttt{do\_ini Line 376  functions are started in \texttt{do\_ini
376  \subsection{Function swap\_out\_pmd()}  \subsection{Function swap\_out\_pmd()}
377       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
378       \textit{Prototype: }       \textit{Prototype: }
379          \begin{verbatim}  \begin{verbatim}
380          int swap_out_pmd(struct mm_struct * mm,  int swap_out_pmd(struct mm_struct * mm,
381                           struct vm_area_struct * vma,                   struct vm_area_struct * vma,
382                           pmd_t *dir, unsigned long address,                   pmd_t *dir, unsigned long address,
383                           unsigned long end, int count,                   unsigned long end, int count,
384                           zone_t * classzone)                   zone_t * classzone)
385          \end{verbatim}  \end{verbatim}
386        
387         For the page middle directory passed as parameter (\texttt{dir}),
388          \begin{verbatim}       this function scan all the page table entries of it. It returns
389          pte_t * pte;       the number of pages missed to reach the requested number of
390          unsigned long pmd_end;       completely unmapped pages (\texttt{count} parameter).
391    
392          if (pmd_none(*dir))  \begin{verbatim}
393              return count;  pte_t * pte;
394          if (pmd_bad(*dir)) {  unsigned long pmd_end;
395              pmd_ERROR(*dir);  
396              pmd_clear(dir);  if (pmd_none(*dir))
397              return count;      return count;
398          }  \end{verbatim}
399                
400          pte = pte_offset(dir, address);       Does this page middle directory offset point to no page table?
401                 There is nothing to do, so just return.
402          pmd_end = (address + PMD_SIZE) & PMD_MASK;  
403          if (end > pmd_end)  \begin{verbatim}
404              end = pmd_end;  if (pmd_bad(*dir)) {
405        pmd_ERROR(*dir);
406          do {      pmd_clear(dir);
407              if (pte_present(*pte)) {      return count;
408                  struct page *page = pte_page(*pte);  }
409    \end{verbatim}
410                  if (VALID_PAGE(page) && !PageReserved(page)) {      
411                      count -= try_to_swap_out(mm, vma, address, pte, page, classzone);       Check if the contents of this memory address points to a valid
412                      if (!count) {       page table. If it does not, print an error message
413                          address += PAGE_SIZE;       (\texttt{pmd\_ERROR}), clear this entry and return.
414                          break;  
415                      }  \begin{verbatim}
416                  }  pte = pte_offset(dir, address);
417    \end{verbatim}
418        
419         From the page middle directory pointer and the address, get the
420         pointer to a page table.
421    
422    \begin{verbatim}
423    pmd_end = (address + PMD_SIZE) & PMD_MASK;
424    if (end > pmd_end)
425        end = pmd_end;
426    \end{verbatim}
427        
428         Computes the end of the page table pointed by this page middle
429         directory entry. If the end of the VM area is beyond the end of
430         this page table, set this variable (\texttt{end}) to this value.
431    
432    \begin{verbatim}
433    do {
434        if (pte_present(*pte)) {
435    \end{verbatim}
436        
437         Only page table entries that are mapped to pages in memory can be
438         unmapped. That way, page table entries set to no page or set to
439         swap addresses are not scanned by \texttt{try\_to\_swap\_out()}.
440    
441    \begin{verbatim}
442            struct page *page = pte_page(*pte);
443    
444            if (VALID_PAGE(page) && !PageReserved(page)) {
445            \end{verbatim}
446        
447         Given the page table entry (pte), get the page to which this page
448         table entry is mapped and check if it is a valid address as well
449         as if it not reserved. Reserved pages cannot be unmapped from
450         their processes.
451    
452    \begin{verbatim}
453                count -= try_to_swap_out(mm, vma, address,
454                                         pte, page, classzone);
455    \end{verbatim}
456        
457         Call \texttt{try\_to\_swap\_out()} function that will try to
458         unmap this page (\texttt{page} variable) from the page table
459         entry which is mapped to it. It will return 1 if it has unmapped
460         and this page is freeable. The return value of 0 does not mean
461         that the page is still mapped, but simply that it is not
462         freeable (ie, it is mapped to other processes).
463    
464    \begin{verbatim}
465                if (!count) {
466                    address += PAGE_SIZE;
467                    break;
468              }              }
469              address += PAGE_SIZE;  \end{verbatim}
470              pte++;      
471          } while (address && (address < end));       If the initial requested number of completely unmapped pages have
472          mm->swap_address = address;       been reached, return. Since the \texttt{swap\_address} (the last
473          return count;       address scanned to be swapped out) of the \texttt{mm\_struct} is
474          \end{verbatim}       updated here, add the page size to the address variable, since
475         this address has been scanned and the scan should be resumed from
476         the next address.
477    
478    \begin{verbatim}
479            }
480        }
481        address += PAGE_SIZE;
482        pte++;
483    } while (address && (address < end));
484    \end{verbatim}
485    
486         Update the \texttt{address} variable to the next address and the
487         \texttt{pte} pointer to the next offset to be scanned. In the
488         case this address is beyond the VM area end, stop the loop.
489    
490    \begin{verbatim}
491    mm->swap_address = address;
492    return count;
493    \end{verbatim}
494        
495         Update the \texttt{mm\_struct} last address scanned in order to
496         swap out and return the \texttt{count} variable, which informs
497         the number of pages missed to reach the inital requested number
498         of completely unmapped pages.
499    
           
500  \subsection{Function swap\_out\_pgd()}  \subsection{Function swap\_out\_pgd()}
501       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
502       \textit{Prototype: }       \textit{Prototype: }
503          \begin{verbatim}  \begin{verbatim}
504          int swap_out_pgd(struct mm_struct * mm,  int swap_out_pgd(struct mm_struct * mm,
505                           struct vm_area_struct * vma,                   struct vm_area_struct * vma,
506                           pgd_t *dir, unsigned long address,                   pgd_t *dir, unsigned long address,
507                           unsigned long end, int count,                   unsigned long end, int count,
508                           zone_t * classzone)                   zone_t * classzone)
509          \end{verbatim}  \end{verbatim}
510        
511          \begin{verbatim}       For a given page global directory offset, this function scan all
512          pmd_t * pmd;       the page middle directories of it. It returns an int value, which
513          unsigned long pgd_end;       means how many pages are missing to the requested number of
514         completely unmapped pages (\texttt{count} parameter).
515          if (pgd_none(*dir))  
516              return count;  \begin{verbatim}
517          if (pgd_bad(*dir)) {  pmd_t * pmd;
518              pgd_ERROR(*dir);  unsigned long pgd_end;
519              pgd_clear(dir);  
520              return count;  if (pgd_none(*dir))
521          }      return count;
522    \end{verbatim}
523          pmd = pmd_offset(dir, address);      
524         If this page global directory does not have a page middle
525         directory, return.
526    
527    \begin{verbatim}
528    if (pgd_bad(*dir)) {
529        pgd_ERROR(*dir);
530        pgd_clear(dir);
531        return count;
532    }
533    \end{verbatim}
534        
535         Checks if the entry points to a bad page table. In this case,
536         prints that there is an error (\texttt{pgd\_ERROR()}) and clear
537         this entry.
538    
539    \begin{verbatim}
540    pmd = pmd_offset(dir, address);
541    \end{verbatim}
542    
543         From the page global directory entry and the address, get the
544         offset in the page middle directory.
545    
546    \begin{verbatim}
547    pgd_end = (address + PGDIR_SIZE) & PGDIR_MASK;  
548    if (pgd_end && (end > pgd_end))
549        end = pgd_end;
550    \end{verbatim}
551        
552         Obtain the end of the space addressable by this page global
553         directory. If the end of the VM area is greater than the end of
554         this page global directory, the new \texttt{end} will be the pgd
555         boundary.
556    
557    \begin{verbatim}
558    do {
559        count = swap_out_pmd(mm, vma, pmd, address, end, count,
560                             classzone);
561    \end{verbatim}
562        
563         For every page middle directory, scan all its page tables in
564         \texttt{swap\_out\_pmd()} function.
565    
566    \begin{verbatim}
567        if (!count)
568            break;
569    \end{verbatim}
570    
571         The return value of \texttt{swap\_out\_pmd()} function tells how
572         many pages still need to be unmapped to reach the initial
573         requested number. If all the needed pages have been unmapped, it
574         is time to return.
575    
576    \begin{verbatim}
577        address = (address + PMD_SIZE) & PMD_MASK;
578        pmd++;
579    } while (address && (address < end));
580    return count;
581    \end{verbatim}
582    
583         Now go to the next page middle directory, updating the start
584         address of it (\texttt{address} variable) and the offset
585         (\texttt{pmd} variable).
586    
         pgd_end = (address + PGDIR_SIZE) & PGDIR_MASK;    
         if (pgd_end && (end > pgd_end))  
             end = pgd_end;  
           
         do {  
             count = swap_out_pmd(mm, vma, pmd, address, end, count, classzone);  
             if (!count)  
                 break;  
             address = (address + PMD_SIZE) & PMD_MASK;  
             pmd++;  
         } while (address && (address < end));  
         return count;  
         \end{verbatim}  
   
   
   
           
587  \subsection{Function swap\_out\_vma()}  \subsection{Function swap\_out\_vma()}
588       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
589       \textit{Prototype: }       \textit{Prototype: }
590          \begin{verbatim}  \begin{verbatim}
591          int swap_out_vma(struct mm_struct * mm,  int swap_out_vma(struct mm_struct * mm,
592                           struct vm_area_struct * vma,                   struct vm_area_struct * vma,
593                           unsigned long address,                   unsigned long address,
594                           int count, zone_t * classzone)                   int count, zone_t * classzone)
595          \end{verbatim}  \end{verbatim}
596        
597          \begin{verbatim}       This function scans a VM area (\texttt{vma} parameter), returning
598          pgd_t *pgdir;       the number of pages missed to reach the requested number of
599          unsigned long end;       completely unmapped pages (\texttt{count} parameter).
600    
601          /* Don't swap out areas which are reserved */  \begin{verbatim}
602          if (vma->vm_flags & VM_RESERVED)  pgd_t *pgdir;
603              return count;  unsigned long end;
604    
605          pgdir = pgd_offset(mm, address);  /* Don't swap out areas which are reserved */
606    if (vma->vm_flags & VM_RESERVED)
607          end = vma->vm_end;      return count;
608          BUG_ON(address >= end);  \end{verbatim}
609          do {      
610              count = swap_out_pgd(mm, vma, pgdir, address, end, count, classzone);       Some special cases define the VM area as reserved
611              if (!count)       (\texttt{VM\_RESERVED} flag) to avoid this VM area to have its
612                  break;       entries unmapped.
613              address = (address + PGDIR_SIZE) & PGDIR_MASK;  
614              pgdir++;  \begin{verbatim}
615          } while (address && (address < end));  pgdir = pgd_offset(mm, address);
616          return count;  \end{verbatim}
617          \end{verbatim}      
618         Now, based on the \texttt{mm\_struct} and the \texttt{address},
619         get the offset in the process page global directory to scan.
620        
621    \begin{verbatim}
622    end = vma->vm_end;
623    BUG_ON(address >= end);
624    do {
625        count = swap_out_pgd(mm, vma, pgdir, address, end, count,
626                             classzone);
627    \end{verbatim}
628        
629         Call \texttt{swap\_out\_pgd()} to swap out this part of the page
630         global directory. The \texttt{address} and \texttt{end}
631         parameters tells the beginning and end of the memory address to
632         be scanned.
633    
634    \begin{verbatim}
635        if (!count)
636            break;
637    \end{verbatim}
638        
639         Could unmap the requested number of pages? In this case, leave
640         the loop and return.
641    
642    \begin{verbatim}
643        address = (address + PGDIR_SIZE) & PGDIR_MASK;
644        pgdir++;
645    } while (address && (address < end));
646    return count;
647    \end{verbatim}
648        
649         Updates the \texttt{address} variable to the next page global
650         directory offset and \texttt{pgdir} variable to the next offset.
651         If it did not reach the end of this VM area address space, scan
652         the next page global directory offset.
653    
654  \subsection{Function swap\_out\_mm()}  \subsection{Function swap\_out\_mm()}
655       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
656       \textit{Prototype: }       \textit{Prototype: }
657          \begin{verbatim}  \begin{verbatim}
658          int swap_out_mm(struct mm_struct * mm,  int swap_out_mm(struct mm_struct * mm,
659                          int count, int * mmcounter,                  int count, int * mmcounter,
660                          zone_t * classzone)                  zone_t * classzone)
661          \end{verbatim}  \end{verbatim}
662        
663          \begin{verbatim}       Given a \texttt{mm\_struct} (\texttt{mm} parameter), this
664          unsigned long address;       function scans all its VM areas. It returns how many pages were
665          struct vm_area_struct* vma;       missing to get to the initial request amount (\texttt{count}
666         parameter). If return value is zero, it means that all the
667          /*       requested pages were completely unmapped.
668           * Find the proper vm-area after freezing the vma chain  
669           * and ptes.  \begin{verbatim}
670           */  unsigned long address;
671          spin_lock(&mm->page_table_lock);  struct vm_area_struct* vma;
672          address = mm->swap_address;  
673          if (address == TASK_SIZE || swap_mm != mm) {  /*
674              /* We raced: don't count this mm but try again */   * Find the proper vm-area after freezing the vma chain
675              ++*mmcounter;   * and ptes.
676     */
677    spin_lock(&mm->page_table_lock);
678    address = mm->swap_address;
679    if (address == TASK_SIZE || swap_mm != mm) {
680        /* We raced: don't count this mm but try again */
681        ++*mmcounter;
682        goto out_unlock;
683    }
684    \end{verbatim}
685        
686         Check for a race condition. Before getting to this point, another
687         code path might have been faster than the current one and scanned
688         all the address space of this task. Besides that, it could even
689         have been completely scanned and another \texttt{mm\_struct} is
690         the current one to be scanned. In either case, increment the
691         \texttt{mmcounter} variable in order to make the caller function
692         to try it again (if unable to unmap the necessary pages first).
693    
694    \begin{verbatim}
695    vma = find_vma(mm, address);
696    \end{verbatim}
697        
698         Find the first VM area that ends after this \texttt{address}.
699    
700    \begin{verbatim}
701    if (vma) {
702        if (address < vma->vm_start)
703            address = vma->vm_start;
704    \end{verbatim}
705        
706         Set \texttt{address} variable which will be passed as the start
707         of VM area that \texttt{swap\_out\_vma()} function will scan.
708         This is needed for the first call.
709    
710    \begin{verbatim}
711        for (;;) {
712            count = swap_out_vma(mm, vma, address, count,
713                                 classzone);
714    \end{verbatim}
715        
716         Call \texttt{swap\_out\_vma()} to scan all the VM area address
717         space.
718    
719    \begin{verbatim}
720            vma = vma->vm_next;
721            if (!vma)
722                break;
723            if (!count)
724              goto out_unlock;              goto out_unlock;
725          }          address = vma->vm_start;
726          vma = find_vma(mm, address);      }
727          if (vma) {  }
728              if (address < vma->vm_start)  \end{verbatim}
729                  address = vma->vm_start;      
730         Set \texttt{vma} variable to the next VM area. If there are no VM
731              for (;;) {       areas to be scanned, leave the while loop. If the number of pages
732                  count = swap_out_vma(mm, vma, address, count, classzone);       to be unmapped has been reached, leave the function since this VM
733                  vma = vma->vm_next;       area scan can be continued. Otherwise, set \texttt{address} to
734                  if (!vma)       the beginning of the next VM area and go on.
735                      break;  
736                  if (!count)  \begin{verbatim}
737                      goto out_unlock;  /* Indicate that we reached the end of address space */
738                  address = vma->vm_start;  mm->swap_address = TASK_SIZE;
739              }  \end{verbatim}
740          }      
741          /* Indicate that we reached the end of address space */       If all VM areas have been scanned, set the \texttt{swap\_address}
742          mm->swap_address = TASK_SIZE;       of \texttt{mm\_struct} to \texttt{TASK\_SIZE} to mark it as
743         having been completely scanned.
744          out_unlock:  
745          spin_unlock(&mm->page_table_lock);  \begin{verbatim}
746          return count;       out_unlock:
747          \end{verbatim}  spin_unlock(&mm->page_table_lock);
748    return count;
749    \end{verbatim}
750        
751         Here simply returns the number of pages missing to the initial
752         amount of pages to be completely unmapped.
753    
754  \subsection{Function swap\_out()}  \subsection{Function swap\_out()}
755       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
756       \textit{Prototype: }       \textit{Prototype: }
757          \begin{verbatim}  \begin{verbatim}
758          int swap_out(unsigned int priority,  int swap_out(unsigned int priority,
759                       unsigned int gfp_mask,               unsigned int gfp_mask,
760                       zone_t * classzone)               zone_t * classzone)
761          \end{verbatim}  \end{verbatim}
762        
763          \begin{verbatim}       This function picks a task which will have its page table
764          int counter, nr_pages = SWAP_CLUSTER_MAX;       scanned. To be more specific, a \texttt{mm\_struct} -- which is
765          struct mm_struct *mm;       one per task -- is chosen.
766        
767          counter = mmlist_nr;       It returns if all the active tasks have been scanned or the
768          do {       requested number of pages unmapped completely from the processes
769              if (unlikely(current->need_resched)) {       (defined below) has been achieved. The return value is an int
770                  __set_current_state(TASK_RUNNING);       which means that the number of requested pages has been achieved
771                  schedule();       (return value: 1) or not (return value: 0)
772              }      
773    \begin{verbatim}
774    int counter, nr_pages = SWAP_CLUSTER_MAX;
775    \end{verbatim}
776        
777         The goal is to unmap \texttt{nr\_pages} pages from the process to
778         be selected.
779    
780    \begin{verbatim}
781    struct mm_struct *mm;
782    
783    counter = mmlist_nr;
784    do {
785        if (unlikely(current->need_resched)) {
786            __set_current_state(TASK_RUNNING);
787            schedule();
788        }
789    \end{verbatim}
790    
791         Improve fairness by rescheduling the current task.
792    
793    \begin{verbatim}
794        spin_lock(&mmlist_lock);
795        mm = swap_mm;
796    \end{verbatim}
797        
798         Set \texttt{mm} variable to the latest \texttt{mm\_struct} which
799         has been scanned (or is being scanned).
800    
801    \begin{verbatim}
802        while (mm->swap_address == TASK_SIZE || mm == &init_mm) {
803    \end{verbatim}
804        
805         If no task has ever been scanned (second condition) or all the
806         address space of this task has been scanned (first condition),
807         try to get a new \texttt{mm\_struct} to scan.
808    
809    \begin{verbatim}
810            mm->swap_address = 0;
811    \end{verbatim}
812        
813         Zeroing \texttt{swap\_address} makes this \texttt{mm\_struct}
814         available again to be scanned.
815    
816    \begin{verbatim}
817            mm = list_entry(mm->mmlist.next, struct mm_struct, mmlist);
818    \end{verbatim}
819        
820         Pick the next \texttt{mm\_struct} in the \texttt{mmlist}, which
821         is the list of all active \texttt{mm\_struct}s.
822    
823    \begin{verbatim}
824            if (mm == swap_mm)
825                goto empty;
826    \end{verbatim}
827    
828         In the case the list is empty, return.
829        
830    \begin{verbatim}
831            swap_mm = mm;
832        }
833    \end{verbatim}
834        
835         Now check (in the while condition) if this \texttt{mm\_struct}
836         can be scanned. Otherwise, try to get a new one.
837    
838    \begin{verbatim}
839        /* Make sure the mm doesn't disappear
840           when we drop the lock.. */
841        atomic_inc(&mm->mm_users);
842        spin_unlock(&mmlist_lock);
843    
844        nr_pages = swap_out_mm(mm, nr_pages, &counter, classzone);
845    \end{verbatim}
846        
847         Chosen an \texttt{mm\_struct()}, call \texttt{swap\_out\_mm()}
848         function, which will ``swap out'' the VM areas of this
849         \texttt{mm\_struct}.
850    
851    \begin{verbatim}
852        mmput(mm);
853    \end{verbatim}
854        
855         Once all the VM areas have been scanned, decrement the
856         \texttt{mm\_struct} counter, deleting if it is the last
857         reference.
858    
859              spin_lock(&mmlist_lock);  \begin{verbatim}
860              mm = swap_mm;      if (!nr_pages)
861              while (mm->swap_address == TASK_SIZE || mm == &init_mm) {          return 1;
862                  mm->swap_address = 0;  \end{verbatim}
                 mm = list_entry(mm->mmlist.next, struct mm_struct, mmlist);  
                 if (mm == swap_mm)  
                     goto empty;  
                 swap_mm = mm;  
             }  
   
         /* Make sure the mm doesn't disappear when we drop the lock.. */  
             atomic_inc(&mm->mm_users);  
             spin_unlock(&mmlist_lock);  
863    
864              nr_pages = swap_out_mm(mm, nr_pages, &counter, classzone);       No remaining pages to be unmapped? This function is sucessful, so
865         it is time to return.
866    
867              mmput(mm);  \begin{verbatim}
868    } while (--counter >= 0);
869    
870              if (!nr_pages)  return 0;
                 return 1;  
         } while (--counter >= 0);  
871    
872          return 0;       empty:
873    spin_unlock(&mmlist_lock);
874          empty:  return 0;
875          spin_unlock(&mmlist_lock);  \end{verbatim}
876          return 0;      
877          \end{verbatim}       Unsuccesful since either the \texttt{mmlist} does not have other
878         \texttt{mm\_struct}s or even after scanning all \texttt{mmlist},
879         it was unable to unmap the requested number of pages.
880    
881  \subsection{Function shrink\_cache()}  \subsection{Function shrink\_cache()}
882       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
883       \textit{Prototype: }       \textit{Prototype: }
884          \begin{verbatim}  \begin{verbatim}
885          int shrink_cache(int nr_pages,  int shrink_cache(int nr_pages,
886                           zone_t * classzone,                   zone_t * classzone,
887                           unsigned int gfp_mask,                   unsigned int gfp_mask,
888                           int priority)                   int priority)
889          \end{verbatim}  \end{verbatim}
890            
891       This function shrinks the page and swap cache, checking the       This function shrinks the page and swap cache, checking the
892       inactive list and trying to free pages from it. It may be needed       inactive list and trying to free pages from it. It may be needed
# Line 624  functions are started in \texttt{do\_ini Line 900  functions are started in \texttt{do\_ini
900     number of pages. For example, a return value of 3 means that this     number of pages. For example, a return value of 3 means that this
901     function was able of free (\texttt{nr\_pages} - 3) pages.     function was able of free (\texttt{nr\_pages} - 3) pages.
902    
903          \begin{verbatim}  \begin{verbatim}
904          struct list_head * entry;  struct list_head * entry;
905          int max_scan = nr_inactive_pages / priority;  int max_scan = nr_inactive_pages / priority;
906          int max_mapped = min((nr_pages <\< (10 - priority)), max_scan / 10);  int max_mapped = min((nr_pages < < (10 - priority)),
907          \end{verbatim}                       max_scan / 10);
908    \end{verbatim}
909        
910     Here it is calculated how many pages at most will be scanned by     Here it is calculated how many pages at most will be scanned by
911     this function (if it can't return first). This value is based on     this function (if it can't return first). This value is based on
# Line 643  functions are started in \texttt{do\_ini Line 920  functions are started in \texttt{do\_ini
920     (\texttt{max\_scan} and \texttt{max\_mapped}) are known as     (\texttt{max\_scan} and \texttt{max\_mapped}) are known as
921     \emph{magic values}.     \emph{magic values}.
922    
923          \begin{verbatim}  \begin{verbatim}
924          spin_lock(&pagemap_lru_lock);  spin_lock(&pagemap_lru_lock);
925          while (--max_scan >= 0 && (entry = inactive_list.prev) != &inactive_list) {  while (--max_scan >= 0 &&
926          \end{verbatim}         (entry = inactive_list.prev) != &inactive_list) {
927    \end{verbatim}
928        
929     The while is very clear. It is scanned the minimum value between     The while is very clear. It is scanned the minimum value between
930     \texttt{max\_scan} number of pages and the whole inactive list.     \texttt{max\_scan} number of pages and the whole inactive list.
# Line 655  functions are started in \texttt{do\_ini Line 933  functions are started in \texttt{do\_ini
933     number of mapped pages is reached or the requested number of pages     number of mapped pages is reached or the requested number of pages
934     has been freed, this function will return too.     has been freed, this function will return too.
935    
936          \begin{verbatim}  \begin{verbatim}
937              struct page * page;      struct page * page;
938    
939              if (unlikely(current->need_resched)) {      if (unlikely(current->need_resched)) {
940                  spin_unlock(&pagemap_lru_lock);          spin_unlock(&pagemap_lru_lock);
941                  __set_current_state(TASK_RUNNING);          __set_current_state(TASK_RUNNING);
942                  schedule();          schedule();
943                  spin_lock(&pagemap_lru_lock);          spin_lock(&pagemap_lru_lock);
944                  continue;          continue;
945              }      }
946          \end{verbatim}  \end{verbatim}
947        
948     Improve fairness among process by rescheduling the process if it     Improve fairness among process by rescheduling the process if it
949     has been for a long time using CPU resources.     has been for a long time using CPU resources.
950    
951          \begin{verbatim}  \begin{verbatim}
952              page = list_entry(entry, struct page, lru);      page = list_entry(entry, struct page, lru);
953    
954              BUG_ON(!PageLRU(page));      BUG_ON(!PageLRU(page));
955              BUG_ON(PageActive(page));      BUG_ON(PageActive(page));
956    
957              list_del(entry);      list_del(entry);
958              list_add(entry, &inactive_list);      list_add(entry, &inactive_list);
959          \end{verbatim}  \end{verbatim}
960        
961     Obtain the page from \texttt{struct list\_head} pointer, and move     Obtain the page from \texttt{struct list\_head} pointer, and move
962     it to the back of the inactive list.     it to the back of the inactive list.
963    
964          \begin{verbatim}  \begin{verbatim}
965              /*      /*
966               * Zero page counts can happen because we unlink the pages       * Zero page counts can happen because we unlink the pages
967               * _after_ decrementing the usage count..       * _after_ decrementing the usage count..
968               */       */
969              if (unlikely(!page_count(page)))      if (unlikely(!page_count(page)))
970                  continue;          continue;
971          \end{verbatim}  \end{verbatim}
972        
973     Since the page may be removed from lru lists after having its     Since the page may be removed from lru lists after having its
974     counter decremented, a race condition may happen: this page gets     counter decremented, a race condition may happen: this page gets
# Line 698  functions are started in \texttt{do\_ini Line 976  functions are started in \texttt{do\_ini
976     unlinked from the lru lists. The above \texttt{if} handles this     unlinked from the lru lists. The above \texttt{if} handles this
977     case.     case.
978    
979          \begin{verbatim}  \begin{verbatim}
980              if (!memclass(page_zone(page), classzone))      if (!memclass(page_zone(page), classzone))
981                  continue;          continue;
982          \end{verbatim}  \end{verbatim}
983        
984     Only check pages that are from the zone which is under pressure.     Only check pages that are from the zone which is under pressure.
985    
986          \begin{verbatim}  \begin{verbatim}
987              /* Racy check to avoid trylocking when not worthwhile */      /* Racy check to avoid trylocking when not worthwhile */
988              if (!page->buffers && (page_count(page) != 1 || !page->mapping))      if (!page->buffers && (page_count(page) != 1 || !page->mapping))
989                  goto page_mapped;          goto page_mapped;
990          \end{verbatim}  \end{verbatim}
991        
992     Before trying to lock the page, first check if it is mapped or     Before trying to lock the page, first check if it is mapped or
993     anonymous and does not have buffers to be freed. If that is true,     anonymous and does not have buffers to be freed. If that is true,
# Line 717  functions are started in \texttt{do\_ini Line 995  functions are started in \texttt{do\_ini
995     even if mapped to processes, go on to try to free them (what may     even if mapped to processes, go on to try to free them (what may
996     imply to synchronize them if busy).     imply to synchronize them if busy).
997    
998          \begin{verbatim}  \begin{verbatim}
999          /*  /*
1000           * The page is locked. IO in progress?   * The page is locked. IO in progress?
1001           * Move it to the back of the list.   * Move it to the back of the list.
1002           */   */
1003              if (unlikely(TryLockPage(page))) {      if (unlikely(TryLockPage(page))) {
1004                  if (PageLaunder(page) && (gfp_mask & __GFP_FS)) {          if (PageLaunder(page) && (gfp_mask & __GFP_FS)) {
1005                      page_cache_get(page);              page_cache_get(page);
1006                      spin_unlock(&pagemap_lru_lock);              spin_unlock(&pagemap_lru_lock);
1007                      wait_on_page(page);              wait_on_page(page);
1008                      page_cache_release(page);              page_cache_release(page);
1009                      spin_lock(&pagemap_lru_lock);              spin_lock(&pagemap_lru_lock);
1010                  }          }
1011                  continue;          continue;
1012              }      }
1013          \end{verbatim}  \end{verbatim}
1014        
1015     Try to lock the page at once. If it is locked and PageLaunder bit     Try to lock the page at once. If it is locked and PageLaunder bit
1016     is true, wait until it gets unlocked. PageLaunder will be only set     is true, wait until it gets unlocked. PageLaunder will be only set
# Line 747  functions are started in \texttt{do\_ini Line 1025  functions are started in \texttt{do\_ini
1025       the list}). It does not make sense since the page has already       the list}). It does not make sense since the page has already
1026     been moved to the back of the list.     been moved to the back of the list.
1027    
1028          \begin{verbatim}  \begin{verbatim}
1029              if (PageDirty(page) && is_page_cache_freeable(page) && page->mapping) {      if (PageDirty(page) && is_page_cache_freeable(page) &&
1030          \end{verbatim}          page->mapping) {
1031    \end{verbatim}
1032        
1033     Dirty pages, completely unmapped by processes and that are in the     Dirty pages, completely unmapped by processes and that are in the
1034     page cache (swap cache is only a part of it) are eligible to be     page cache (swap cache is only a part of it) are eligible to be
# Line 757  functions are started in \texttt{do\_ini Line 1036  functions are started in \texttt{do\_ini
1036     accesses this page, it will be only remapped after the IO is     accesses this page, it will be only remapped after the IO is
1037     complete, ie, the faultin path is able lock this page.     complete, ie, the faultin path is able lock this page.
1038    
1039          \begin{verbatim}  \begin{verbatim}
1040                  /*          /*
1041                   * It is not critical here to write it only if           * It is not critical here to write it only if
1042                   * the page is unmapped beause any direct writer           * the page is unmapped beause any direct writer
1043                   * like O_DIRECT would set the PG_dirty bitflag           * like O_DIRECT would set the PG_dirty bitflag
1044                   * on the phisical page after having successfully           * on the phisical page after having successfully
1045                   * pinned it and after the I/O to the page is finished,           * pinned it and after the I/O to the page is finished,
1046                   * so the direct writes to the page cannot get lost.           * so the direct writes to the page cannot get lost.
1047                   */           */
1048                  int (*writepage)(struct page *);          int (*writepage)(struct page *);
1049    
1050                  writepage = page->mapping->a_ops->writepage;          writepage = page->mapping->a_ops->writepage;
1051                  if ((gfp_mask & __GFP_FS) && writepage) {          if ((gfp_mask & __GFP_FS) && writepage) {
1052                      ClearPageDirty(page);              ClearPageDirty(page);
1053                      SetPageLaunder(page);              SetPageLaunder(page);
1054                      page_cache_get(page);              page_cache_get(page);
1055                      spin_unlock(&pagemap_lru_lock);              spin_unlock(&pagemap_lru_lock);
1056    
1057                      writepage(page);              writepage(page);
1058                      page_cache_release(page);              page_cache_release(page);
1059    
1060                      spin_lock(&pagemap_lru_lock);              spin_lock(&pagemap_lru_lock);
1061                      continue;              continue;
1062                  }          }
1063               }       }
1064          \end{verbatim}  \end{verbatim}
1065        
1066     Only pages from page cache which have the \texttt{writepage()}     Only pages from page cache which have the \texttt{writepage()}
1067     function defined can be cleaned. Actually, the \texttt{gfp\_mask}     function defined can be cleaned. Actually, the \texttt{gfp\_mask}
# Line 792  functions are started in \texttt{do\_ini Line 1071  functions are started in \texttt{do\_ini
1071     is called.  Here a reference to the page is got in order to avoid     is called.  Here a reference to the page is got in order to avoid
1072     it to be ocasionally freed in the meanwhile.     it to be ocasionally freed in the meanwhile.
1073    
1074          \begin{verbatim}  \begin{verbatim}
1075              /*      /*
1076               * If the page has buffers, try to free the buffer mappings       * If the page has buffers, try to free the buffer mappings
1077               * associated with this page. If we succeed we try to free       * associated with this page. If we succeed we try to free
1078               * the page as well.       * the page as well.
1079               */       */
1080              if (page->buffers) {      if (page->buffers) {
1081                  spin_unlock(&pagemap_lru_lock);          spin_unlock(&pagemap_lru_lock);
1082    
1083                  /* avoid to free a locked page */          /* avoid to free a locked page */
1084                  page_cache_get(page);          page_cache_get(page);
1085    
1086                  if (try_to_release_page(page, gfp_mask)) {          if (try_to_release_page(page, gfp_mask)) {
1087          \end{verbatim}  \end{verbatim}
1088        
1089     Does the page have buffers? No matter if is completely unmapped     Does the page have buffers? No matter if is completely unmapped
1090     from its processes, try to free them by calling     from its processes, try to free them by calling
# Line 814  functions are started in \texttt{do\_ini Line 1093  functions are started in \texttt{do\_ini
1093     free the buffers if they are clean, otherwise will synchronize them     free the buffers if they are clean, otherwise will synchronize them
1094     (\texttt{gfp\_mask} must allow that).     (\texttt{gfp\_mask} must allow that).
1095    
1096          \begin{verbatim}  \begin{verbatim}
1097                      if (!page->mapping) {              if (!page->mapping) {
1098                          /*                  /*
1099                           * We must not allow an anon page                   * We must not allow an anon page
1100                           * with no buffers to be visible on                   * with no buffers to be visible on
1101                           * the LRU, so we unlock the page after                   * the LRU, so we unlock the page after
1102                           * taking the lru lock                   * taking the lru lock
1103                           */                   */
1104                          spin_lock(&pagemap_lru_lock);                  spin_lock(&pagemap_lru_lock);
1105                          UnlockPage(page);                  UnlockPage(page);
1106                          __lru_cache_del(page);                  __lru_cache_del(page);
1107    
1108                          /* effectively free the page here */                  /* effectively free the page here */
1109                          page_cache_release(page);                  page_cache_release(page);
1110    
1111                          if (--nr_pages)                  if (--nr_pages)
1112                              continue;                      continue;
1113                          break;                  break;
1114          \end{verbatim}  \end{verbatim}
1115        
1116     The page has had its buffers freed. Is it an anonymous page? In     The page has had its buffers freed. Is it an anonymous page? In
1117     order to be an anonymous page with buffers, it must have already     order to be an anonymous page with buffers, it must have already
# Line 841  functions are started in \texttt{do\_ini Line 1120  functions are started in \texttt{do\_ini
1120     invalidate/truncate its pages. In this case, simply remove the page     invalidate/truncate its pages. In this case, simply remove the page
1121     from the inactive list and release it.     from the inactive list and release it.
1122    
1123          \begin{verbatim}  \begin{verbatim}
1124                      } else {              } else {
1125                          /*                  /*
1126                           * The page is still in pagecache so undo the stuff                   * The page is still in pagecache so undo
1127                           * before the try_to_release_page since we've not                   * the stuff before the try_to_release_page
1128                           * finished and we can now try the next step.                   * since we've not finished and we can now
1129                           */                   * try the next step.
1130                          page_cache_release(page);                   */
1131                    page_cache_release(page);
1132    
1133                          spin_lock(&pagemap_lru_lock);                  spin_lock(&pagemap_lru_lock);
1134                      }              }
1135          \end{verbatim}  \end{verbatim}
1136        
1137     The pages's buffers are gone, so go on to the next step since the     The pages's buffers are gone, so go on to the next step since the
1138     page is still in the page cache. It needs to be removed from the     page is still in the page cache. It needs to be removed from the
# Line 860  functions are started in \texttt{do\_ini Line 1140  functions are started in \texttt{do\_ini
1140     give up on i since it is still to be unmapped and it is not     give up on i since it is still to be unmapped and it is not
1141     freeable at this moment.     freeable at this moment.
1142    
1143          \begin{verbatim}  \begin{verbatim}
1144                  } else {          } else {
1145                      /* failed to drop the buffers so stop here */              /* failed to drop the buffers so stop here */
1146                      UnlockPage(page);              UnlockPage(page);
1147                      page_cache_release(page);              page_cache_release(page);
1148    
1149                      spin_lock(&pagemap_lru_lock);              spin_lock(&pagemap_lru_lock);
1150                      continue;              continue;
1151                  }          }
1152              }      }
1153          \end{verbatim}  \end{verbatim}
1154        
1155     The buffers could not be freed, so give up on this page. It is time     The buffers could not be freed, so give up on this page. It is time
1156     to try another page from the inactive list.     to try another page from the inactive list.
1157    
1158          \begin{verbatim}  \begin{verbatim}
1159              spin_lock(&pagecache_lock);      spin_lock(&pagecache_lock);
1160    
1161              /*      /*
1162               * this is the non-racy check for busy page.       * this is the non-racy check for busy page.
1163               */       */
1164              if (!page->mapping || !is_page_cache_freeable(page)) {      if (!page->mapping || !is_page_cache_freeable(page)) {
1165                  spin_unlock(&pagecache_lock);          spin_unlock(&pagecache_lock);
1166                  UnlockPage(page);          UnlockPage(page);
1167          page_mapped:  page_mapped:
1168                  if (--max_mapped >= 0)          if (--max_mapped >= 0)
1169                      continue;              continue;
1170          \end{verbatim}  \end{verbatim}
1171        
1172     For anonymous pages without buffers, that is a race check since     For anonymous pages without buffers, that is a race check since
1173     they probably have been removed from the page cache in the     they probably have been removed from the page cache in the
# Line 895  functions are started in \texttt{do\_ini Line 1175  functions are started in \texttt{do\_ini
1175     and are still mapped by processes, it is time to account them to     and are still mapped by processes, it is time to account them to
1176     \texttt{max\_mapped} variable.     \texttt{max\_mapped} variable.
1177    
1178          \begin{verbatim}  \begin{verbatim}
1179                  /*          /*
1180                   * Alert! We've found too many mapped pages on the           * Alert! We've found too many mapped pages on the
1181                   * inactive list, so we start swapping out now!           * inactive list, so we start swapping out now!
1182                   */           */
1183                  spin_unlock(&pagemap_lru_lock);          spin_unlock(&pagemap_lru_lock);
1184                  swap_out(priority, gfp_mask, classzone);          swap_out(priority, gfp_mask, classzone);
1185                  return nr_pages;          return nr_pages;
1186              }      }
1187          \end{verbatim}  \end{verbatim}
1188        
1189     When a \texttt{max\_mapped} number of pages have been observed to     When a \texttt{max\_mapped} number of pages have been observed to
1190     be mapped to processes, it is time to start unmapping pages that     be mapped to processes, it is time to start unmapping pages that
# Line 913  functions are started in \texttt{do\_ini Line 1193  functions are started in \texttt{do\_ini
1193     reaching a \texttt{max\_mapped} number of mapped pages is one of     reaching a \texttt{max\_mapped} number of mapped pages is one of
1194     the conditions to stop the scan process.     the conditions to stop the scan process.
1195    
1196          \begin{verbatim}  \begin{verbatim}
1197              /*      /*
1198               * It is critical to check PageDirty _after_ we made sure       * It is critical to check PageDirty _after_ we made sure
1199               * the page is freeable* so not in use by anybody.       * the page is freeable* so not in use by anybody.
1200               */       */
1201              if (PageDirty(page)) {      if (PageDirty(page)) {
1202                  spin_unlock(&pagecache_lock);          spin_unlock(&pagecache_lock);
1203                  UnlockPage(page);          UnlockPage(page);
1204                  continue;          continue;
1205              }      }
1206          \end{verbatim}  \end{verbatim}
1207    
1208     To do     To do
1209    
1210          \begin{verbatim}  \begin{verbatim}
1211              /* point of no return */      /* point of no return */
1212              if (likely(!PageSwapCache(page))) {      if (likely(!PageSwapCache(page))) {
1213                  __remove_inode_page(page);          __remove_inode_page(page);
1214                  spin_unlock(&pagecache_lock);          spin_unlock(&pagecache_lock);
1215              } else {      } else {
1216                  swp_entry_t swap;          swp_entry_t swap;
1217                  swap.val = page->index;          swap.val = page->index;
1218                  __delete_from_swap_cache(page);          __delete_from_swap_cache(page);
1219                  spin_unlock(&pagecache_lock);          spin_unlock(&pagecache_lock);
1220                  swap_free(swap);          swap_free(swap);
1221              }      }
1222    
1223              __lru_cache_del(page);      __lru_cache_del(page);
1224              UnlockPage(page);      UnlockPage(page);
1225    
1226              /* effectively free the page here */      /* effectively free the page here */
1227              page_cache_release(page);      page_cache_release(page);
1228    
1229        if (--nr_pages)
1230            continue;
1231        break;
1232    }
1233    spin_unlock(&pagemap_lru_lock);
1234    
1235              if (--nr_pages)  return nr_pages;
1236                  continue;  \end{verbatim}
             break;  
         }  
         spin_unlock(&pagemap_lru_lock);  
   
         return nr_pages;  
         \end{verbatim}  
1237        
1238     That is the part of the code where the page is not mapped by any     That is the part of the code where the page is not mapped by any
1239     process, it is not dirty and does not have buffers, so it can     process, it is not dirty and does not have buffers, so it can
# Line 964  functions are started in \texttt{do\_ini Line 1244  functions are started in \texttt{do\_ini
1244  \subsection{Function refill\_inactive()}  \subsection{Function refill\_inactive()}
1245       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
1246       \textit{Prototype: }       \textit{Prototype: }
1247          \begin{verbatim}  \begin{verbatim}
1248          void refill_inactive(int nr_pages)  void refill_inactive(int nr_pages)
1249          \end{verbatim}  \end{verbatim}
1250          This function moves pages from the active list to the inactive list.  This function moves pages from the active list to the inactive list.
1251          \begin{verbatim}  \begin{verbatim}
1252          struct list_head * entry;  struct list_head * entry;
1253    
1254          spin_lock(&pagemap_lru_lock);  spin_lock(&pagemap_lru_lock);
1255          entry = active_list.prev;  entry = active_list.prev;
1256          while (nr_pages && entry != &active_list) {  while (nr_pages && entry != &active_list) {
1257              struct page * page;      struct page * page;
1258    
1259              page = list_entry(entry, struct page, lru);      page = list_entry(entry, struct page, lru);
1260              entry = entry->prev;      entry = entry->prev;
1261              if (PageTestandClearReferenced(page)) {      if (PageTestandClearReferenced(page)) {
1262                  list_del(&page->lru);          list_del(&page->lru);
1263                  list_add(&page->lru, &active_list);          list_add(&page->lru, &active_list);
1264                  continue;          continue;
1265              }      }
1266    
1267              nr_pages--;      nr_pages--;
1268    
1269              del_page_from_active_list(page);      del_page_from_active_list(page);
1270              add_page_to_inactive_list(page);      add_page_to_inactive_list(page);
1271              SetPageReferenced(page);      SetPageReferenced(page);
1272          }  }
1273          spin_unlock(&pagemap_lru_lock);  spin_unlock(&pagemap_lru_lock);
1274          \end{verbatim}  \end{verbatim}
1275    
1276    
1277    
# Line 999  functions are started in \texttt{do\_ini Line 1279  functions are started in \texttt{do\_ini
1279  \subsection{Function shrink\_caches()}  \subsection{Function shrink\_caches()}
1280       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
1281       \textit{Prototype: }       \textit{Prototype: }
1282          \begin{verbatim}  \begin{verbatim}
1283          int shrink_caches(zone_t * classzone,  int shrink_caches(zone_t * classzone,
1284                            int priority,                    int priority,
1285                            unsigned int gfp_mask,                    unsigned int gfp_mask,
1286                            int nr_pages)                    int nr_pages)
1287          \end{verbatim}  \end{verbatim}
1288    
1289          \begin{verbatim}  \begin{verbatim}
1290          int chunk_size = nr_pages;  int chunk_size = nr_pages;
1291          unsigned long ratio;  unsigned long ratio;
1292    
1293          nr_pages -= kmem_cache_reap(gfp_mask);  nr_pages -= kmem_cache_reap(gfp_mask);
1294          if (nr_pages <= 0)  if (nr_pages <= 0)
1295              return 0;      return 0;
1296    
1297          nr_pages = chunk_size;  nr_pages = chunk_size;
1298          /* try to keep the active list 2/3 of the size of the cache */  /* try to keep the active list 2/3 of the size of the cache */
1299          ratio = (unsigned long) nr_pages *  ratio = (unsigned long) nr_pages *
1300                        nr_active_pages / ((nr_inactive_pages + 1) * 2);          nr_active_pages / ((nr_inactive_pages + 1) * 2);
1301          refill_inactive(ratio);  refill_inactive(ratio);
1302    
1303          nr_pages = shrink_cache(nr_pages, classzone, gfp_mask, priority);  nr_pages = shrink_cache(nr_pages, classzone, gfp_mask,
1304          if (nr_pages <= 0)                          priority);
1305              return 0;  if (nr_pages <= 0)
1306        return 0;
1307          shrink_dcache_memory(priority, gfp_mask);  
1308          shrink_icache_memory(priority, gfp_mask);  shrink_dcache_memory(priority, gfp_mask);
1309          #ifdef CONFIG_QUOTA  shrink_icache_memory(priority, gfp_mask);
1310          shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);  #ifdef CONFIG_QUOTA
1311          #endif  shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
1312    #endif
1313    
1314          return nr_pages;  return nr_pages;
1315          \end{verbatim}  \end{verbatim}
1316    
1317    
1318    
# Line 1039  functions are started in \texttt{do\_ini Line 1320  functions are started in \texttt{do\_ini
1320    
1321  \subsection{Function try\_to\_free\_pages()}\label{fun:ttfp}  \subsection{Function try\_to\_free\_pages()}\label{fun:ttfp}
1322       \textit{Prototype: }       \textit{Prototype: }
1323          \begin{verbatim}  \begin{verbatim}
1324          int try_to_free_pages(zone_t *classzone,  int try_to_free_pages(zone_t *classzone,
1325                                unsigned int gfp_mask,                        unsigned int gfp_mask,
1326                                unsigned int order)                        unsigned int order)
1327          \end{verbatim}  \end{verbatim}
1328    
1329    \begin{verbatim}
1330    int priority = DEF_PRIORITY;
1331    int nr_pages = SWAP_CLUSTER_MAX;
1332    
1333    gfp_mask = pf_gfp_mask(gfp_mask);
1334    do {
1335        nr_pages = shrink_caches(classzone, priority, gfp_mask,
1336                                 nr_pages);
1337        if (nr_pages <= 0)
1338            return 1;
1339    } while (--priority);
1340    
1341          \begin{verbatim}  /*
1342          int priority = DEF_PRIORITY;   * Hmm.. Cache shrink failed - time to kill something?
1343          int nr_pages = SWAP_CLUSTER_MAX;   * Mhwahahhaha! This is the part I really like. Giggle.
1344     */
1345          gfp_mask = pf_gfp_mask(gfp_mask);  out_of_memory();
1346          do {  return 0;
1347              nr_pages = shrink_caches(classzone, priority, gfp_mask, nr_pages);  \end{verbatim}
             if (nr_pages <= 0)  
                 return 1;  
         } while (--priority);  
   
         /*  
          * Hmm.. Cache shrink failed - time to kill something?  
          * Mhwahahhaha! This is the part I really like. Giggle.  
          */  
         out_of_memory();  
         return 0;  
         \end{verbatim}  
1348    
1349    
1350    
# Line 1070  functions are started in \texttt{do\_ini Line 1352  functions are started in \texttt{do\_ini
1352  \subsection{Function check\_classzone\_need\_balance()}  \subsection{Function check\_classzone\_need\_balance()}
1353       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
1354       \textit{Prototype: }       \textit{Prototype: }
1355          \begin{verbatim}  \begin{verbatim}
1356          int check_classzone_need_balance(zone_t * classzone)  int check_classzone_need_balance(zone_t * classzone)
1357          \end{verbatim}  \end{verbatim}
1358    
1359    
1360          \begin{verbatim}  \begin{verbatim}
1361          zone_t * first_classzone;  zone_t * first_classzone;
1362    
1363          first_classzone = classzone->zone_pgdat->node_zones;  first_classzone = classzone->zone_pgdat->node_zones;
1364          while (classzone >= first_classzone) {  while (classzone >= first_classzone) {
1365              if (classzone->free_pages > classzone->pages_high)      if (classzone->free_pages > classzone->pages_high)
1366                  return 0;          return 0;
1367              classzone--;      classzone--;
1368          }  }
1369          return 1;  return 1;
1370          \end{verbatim}  \end{verbatim}
1371    
1372    
1373    
# Line 1094  functions are started in \texttt{do\_ini Line 1376  functions are started in \texttt{do\_ini
1376  \subsection{Function kswapd\_balance\_pgdat()}  \subsection{Function kswapd\_balance\_pgdat()}
1377       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
1378       \textit{Prototype: }       \textit{Prototype: }
1379          \begin{verbatim}  \begin{verbatim}
1380          int kswapd_balance_pgdat(pg_data_t * pgdat)  int kswapd_balance_pgdat(pg_data_t * pgdat)
1381          \end{verbatim}  \end{verbatim}
1382    
1383          \begin{verbatim}  \begin{verbatim}
1384          int need_more_balance = 0, i;  int need_more_balance = 0, i;
1385          zone_t * zone;  zone_t * zone;
1386    
1387          for (i = pgdat->nr_zones-1; i >= 0; i--) {  for (i = pgdat->nr_zones-1; i >= 0; i--) {
1388              zone = pgdat->node_zones + i;      zone = pgdat->node_zones + i;
1389              if (unlikely(current->need_resched))      if (unlikely(current->need_resched))
1390                 schedule();         schedule();
1391              if (!zone->need_balance)      if (!zone->need_balance)
1392                  continue;          continue;
1393              if (!try_to_free_pages(zone, GFP_KSWAPD, 0)) {      if (!try_to_free_pages(zone, GFP_KSWAPD, 0)) {
1394                  zone->need_balance = 0;          zone->need_balance = 0;
1395                  __set_current_state(TASK_INTERRUPTIBLE);          __set_current_state(TASK_INTERRUPTIBLE);
1396                  schedule_timeout(HZ);          schedule_timeout(HZ);
1397                  continue;          continue;
1398              }      }
1399              if (check_classzone_need_balance(zone))      if (check_classzone_need_balance(zone))
1400                  need_more_balance = 1;          need_more_balance = 1;
1401              else      else
1402                  zone->need_balance = 0;                  zone->need_balance = 0;
1403          }  }
1404    
1405          return need_more_balance;  return need_more_balance;
1406          \end{verbatim}  \end{verbatim}
1407    
1408    
1409    
# Line 1129  functions are started in \texttt{do\_ini Line 1411  functions are started in \texttt{do\_ini
1411  \subsection{Function kswapd\_balance()}  \subsection{Function kswapd\_balance()}
1412       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
1413       \textit{Prototype: }       \textit{Prototype: }
1414          \begin{verbatim}  \begin{verbatim}
1415          void kswapd_balance(void)  void kswapd_balance(void)
1416          \end{verbatim}  \end{verbatim}
1417    
1418          \begin{verbatim}  \begin{verbatim}
1419          int need_more_balance;  int need_more_balance;
1420          pg_data_t * pgdat;  pg_data_t * pgdat;
1421    
1422          do {  do {
1423              need_more_balance = 0;      need_more_balance = 0;
1424              pgdat = pgdat_list;      pgdat = pgdat_list;
1425              do      do
1426                  need_more_balance |= kswapd_balance_pgdat(pgdat);          need_more_balance |= kswapd_balance_pgdat(pgdat);
1427              while ((pgdat = pgdat->node_next));      while ((pgdat = pgdat->node_next));
1428          } while (need_more_balance);  } while (need_more_balance);
1429          \end{verbatim}  \end{verbatim}
1430    
1431    
1432    
# Line 1153  functions are started in \texttt{do\_ini Line 1435  functions are started in \texttt{do\_ini
1435  \subsection{Function kswapd\_can\_sleep\_pgdat()}  \subsection{Function kswapd\_can\_sleep\_pgdat()}
1436       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
1437       \textit{Prototype: }       \textit{Prototype: }
1438          \begin{verbatim}  \begin{verbatim}
1439          int kswapd_can_sleep_pgdat(pg_data_t * pgdat)  int kswapd_can_sleep_pgdat(pg_data_t * pgdat)
1440          \end{verbatim}  \end{verbatim}
1441    
1442    
1443    \begin{verbatim}
1444    zone_t * zone;
1445    int i;
1446    
1447    for (i = pgdat->nr_zones-1; i >= 0; i--) {
1448        zone = pgdat->node_zones + i;
1449        if (!zone->need_balance)
1450            continue;
1451        return 0;
1452    }
1453    
1454          \begin{verbatim}  return 1;
1455          zone_t * zone;  \end{verbatim}
         int i;  
   
         for (i = pgdat->nr_zones-1; i >= 0; i--) {  
             zone = pgdat->node_zones + i;  
             if (!zone->need_balance)  
                 continue;  
             return 0;  
         }  
   
         return 1;  
         \end{verbatim}  
1456    
1457  \subsection{Function kswapd\_can\_sleep()}  \subsection{Function kswapd\_can\_sleep()}
1458       \textit{File: }\url{mm/vmscan.c}\\       \textit{File: }\url{mm/vmscan.c}\\
1459       \textit{Prototype: }       \textit{Prototype: }
1460          \begin{verbatim}  \begin{verbatim}
1461          int kswapd_can_sleep(void)  int kswapd_can_sleep(void)
1462          \end{verbatim}  \end{verbatim}
1463    
1464    
1465          \begin{verbatim}  \begin{verbatim}
1466          pg_data_t * pgdat;  pg_data_t * pgdat;
1467    
1468    pgdat = pgdat_list;
1469    do {
1470        if (kswapd_can_sleep_pgdat(pgdat))
1471            continue;
1472        return 0;
1473    } while ((pgdat = pgdat->node_next));
1474    
1475          pgdat = pgdat_list;  return 1;
1476          do {  \end{verbatim}
             if (kswapd_can_sleep_pgdat(pgdat))  
                 continue;  
             return 0;  
         } while ((pgdat = pgdat->node_next));  
   
         return 1;  
         \end{verbatim}  
1477    
1478  \section{Mechanism}  \section{Mechanism}
1479  swapfile.c  swapfile.c

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.10

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26