Department of Computer Science
University of São Paulo
São Paulo, Brazil
Linux 2.4 Virtual Memory Overview
vmscan.c
On this page you can find some of our studies of Linux 2.4 VM
system. This page was created to help us out to visualize VM system
better. WARNING: this material is still very raw and some ideas may
have not been correctly understood. If you have any
suggestion or correction, please send an e-mail to us at [email protected].
description
In vmscan.c we have most of the important functions related to
the Linux's VM subsystem. Including two very important kernel daemons,
the traditional kswapd and the new kreclaimd. It is the
group of functions that is directly linked to swap out process.
functions
- static int
try_to_swap_out(struct mm_struct * mm, struct vm_area_struct*
vma, unsigned long address, pte_t * page_table, int gfp_mask)
description
Mainly, try to swap_out the given page. Here is a description of
a rough algorithm:
- If the page has been accessed recently, age_up this page
and fail
- If the page is in active use (page_age > 0), then fail
- Clear it's pte on page_table and flush the tlb for this
page
- If the page is in swap_cache, drop our reference to it,
since it's already synched with swap, and return 0 since no
real memory was freed (???)
- If the page is clean, then also drop the reference to it,
since it's also synched with swap. Here, again, we don't free
any real memory as the page is still in the page cache, so we
return 0 (to continue the scan). This will leave work for
future call of refill_inactive()
- Finally, we have a dirty page and it's swappable, get a
swap_entry for it and dirty this page.
parameters
- mm - mm struct from the process chosen to have a
page swapped out (swap_out())
- vma - virtual memory area chosen to have a page
swapped out (swap_out_vma())
- address - linear address of the page (swap_out_pmd())
- page_table - address in the page table of the page
which we're trying to swap_out (swap_out_pmd())
- gfp_mask - what operations are we allowed to do
(currently not used!!!)
return value
- 0: returns 0 always.
- 1: unless the mm struct chosen has no page in swap
area.
- static inline int swap_out_pmd(struct mm_struct *
mm, struct vm_area_struct * vma, pmd_t *dir, unsigned long address,
unsigned long end, int gfp_mask)
- static inline int swap_out_pgd(struct mm_struct *
mm, struct vm_area_struct * vma, pgd_t *dir, unsigned long address,
unsigned long end, int gfp_mask)
- static int swap_out_vma(struct mm_struct * mm, struct
vm_area_struct * vma, unsigned long address, int gfp_mask)
- static int swap_out_mm(struct mm_struct * mm, int
gfp_mask)
- static int swap_out(unsigned int priority, int
gfp_mask)
- struct page * reclaim_page(zone_t * zone)
description
- It basically reclaims one page from the inactive_clean_list
- It's a per-zone basis
- If the page is or was in use, it is returned to active_list
- If it is dirty or locked, it will be moved to
inactive_dirty_list
- Other - the above description is the main idea to
this function, but it also does the following while scanning for
the page
- Send referenced and aged (page->age > 0) from
inactive_clean_list to active_list.
- Send dirty or locked pages from inactive_clean_list to
inactive_dirty_list.
parameters
- zone - reclaim a page from this zone
return value
- returns the page just reclaimed
- int page_launder(int gfp_mask, int sync)
description
It cleans dirty inactive pages and moves them to
inactive_clean_list
- If the page is or was in use, it is returned to active_list
- If it's locked, it will be moved to the end of the list
- Dirty swap-cache page? Swap it out if last copy. This will
be only done if, after the first time through, we still are out
of free pages (see launder_loop variable).
- If it has buffers, try to free them and free the page or
move it to inactive_clean_list.
- Even if we couldn't free enough pages, wait synchronously on
the writeout of pages (if user process). And then wakes up
bdflush.
parameters
- gfp_mask - what operations we are allowed to do
- sync - should we wait synchronously for the cleaning of pages?
return value
- returns the number of pages moved to inactive_clean_list.
- int
refill_inactive_scan(unsigned int priority, int oneshot)
description
It scans the active list and find pages to deactivate,
- If the page was referenced, clear referenced bit and up its
age.
- Otherwise, down its age and deactivate it if (page->age == 0
&& page_count(age) <= (page->buffers ? 2 : 1)
- In the case it was not deactivated, move it to the end of
the list
parameters
- priority - the priority at which to scan
- oneshot - exit after deactivating _one_ page
return value
- 0 - the page was not deactivated
- 1 - the page was sucessfully deactivated
- int inactive_shortage(void)
description
- Check how many inactive pages we are short
parameters
return value
- returns the number of pages we are short
- int free_shortage(void)
description
- Check if there are zones with a severe shortage of free
pages, or if all zones have a minor shortage.
parameters
return value
- returns the number of pages we are short
- int inactive_shortage(void)
description
- Check how many inactive pages we are short
parameters
return value
- returns the number of pages we are short
- static int refill_inactive(unsigned int gfp_mask,
int user)
description
- Always trim slab caches
- Calls refill_inactive_scan() to
refill inactive_dirty list with pages from active_list.
- Shrink dcache and icache
- Try to swap pages out to add new pages to active list
- And end with refill_inactive_scan()
- If it is a user process, we do care about latency, so we
won't try to free too many pages
parameters
- gfp_mask - specifies the type of page the process
expects to get
- user - if it is a user process
return value
- 0 - nothing was moved to inactive_dirty
- 1 - something was moved to inactive_dirty
- static int
do_try_to_free_pages(unsigned int gfp_mask, int user)
description
- If we are low on free pages, move pages from inactive_dirty
list to the inactive_clean list. This is done calling page_launder()
- Then if needed, we move pages from active_list to
inactive_list (to balance). This is done calling refill_inactive(). Whenever this is
done, icache and dcache are shrunk.
- If last step was not needed, unused slab cache memory is
reclaimed.
parameters
- gfp_mask - specifies the kind of page we are trying
to free
- user - if it is user process. This parameter is not
used here, but it is passed as parameter to page_launder() and refill_inactive()
return value
- int kswapd(void *unused)
description
The background pageout daemon, started as a kernel thread from the
init process
- If needed (i.e. inactive_shortage() || free_shortage()), try to free some
pages with do_try_to_free_pages()
- Call refill_inactive_scan() to do
some background scanning. Once a minute, all pages on the active
list will be scanned.
- Wake up everybody waiting for some memory
- We go to sleep if the free page shortage is gone. We go
sleep for one second, but if it's needed we'll be woken up
earlier
- But if we couldn't free enough memory, we will kill a
process calling oom_kill()
parameters
return value
- void wakeup_kswapd(int block)
- int
try_to_free_pages(unsigned int gfp_mask)
description
- Called by non-kswapd processes when they want more memory
but are unable to sleep on kswapd because they might be holding
some IO locks
- What is mainly does, if gfp_mask & __GFP_WAIT is
true, is, besides setting some flags, to call do_try_to_free_pages()
parameters
- gfp_mask - specifies the kind of page the process
expects to get
return value
- int kreclaimd(void
*unused)
description
- Sleep until someone wake us up from __aloc_pages()
- If needed (this is per zone), call reclaim_page()
parameters
return value
- static int __init kswapd_init(void)
description
- Set up page_cluster size (with swap_setup())
- Start kswapd kernel thread
- Start kreclaimd kernel thread
parameters
return value
Page last updated on "Mon Apr 30 08:43:27 2001"
Send feedback to
Rodrigo S. de Castro<[email protected]>