patch-2.3.13 linux/mm/vmscan.c
Next file: linux/net/ax25/Config.in
Previous file: linux/mm/swapfile.c
Back to the patch index
Back to the overall index
- Lines: 300
- Date:
Mon Aug 9 11:37:05 1999
- Orig file:
v2.3.12/linux/mm/vmscan.c
- Orig date:
Wed Jul 21 15:46:48 1999
diff -u --recursive --new-file v2.3.12/linux/mm/vmscan.c linux/mm/vmscan.c
@@ -31,8 +31,7 @@
* using a process that no longer actually exists (it might
* have died while we slept).
*/
-static int try_to_swap_out(struct task_struct * tsk, struct vm_area_struct* vma,
- unsigned long address, pte_t * page_table, int gfp_mask)
+static int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pte_t * page_table, int gfp_mask)
{
pte_t pte;
unsigned long entry;
@@ -47,7 +46,7 @@
goto out_failed;
page = mem_map + MAP_NR(page_addr);
- spin_lock(&tsk->mm->page_table_lock);
+ spin_lock(&vma->vm_mm->page_table_lock);
if (pte_val(pte) != pte_val(*page_table))
goto out_failed_unlock;
@@ -55,7 +54,7 @@
* Dont be too eager to get aging right if
* memory is dangerously low.
*/
- if (!low_on_memory && pte_young(pte)) {
+ if (pte_young(pte)) {
/*
* Transfer the "accessed" bit from the page
* tables to the global page map.
@@ -136,15 +135,16 @@
*/
flush_cache_page(vma, address);
if (vma->vm_ops && vma->vm_ops->swapout) {
- pid_t pid = tsk->pid;
+ int error;
pte_clear(page_table);
- spin_unlock(&tsk->mm->page_table_lock);
+ spin_unlock(&vma->vm_mm->page_table_lock);
flush_tlb_page(vma, address);
vma->vm_mm->rss--;
-
- if (vma->vm_ops->swapout(vma, page))
- kill_proc(pid, SIGBUS, 1);
- goto out_free_success;
+ error = vma->vm_ops->swapout(vma, page);
+ if (!error)
+ goto out_free_success;
+ __free_page(page);
+ return error;
}
/*
@@ -153,14 +153,13 @@
* we have the swap cache set up to associate the
* page with that swap entry.
*/
- entry = get_swap_page();
+ entry = acquire_swap_entry(page);
if (!entry)
- goto out_failed; /* No swap space left */
+ goto out_failed_unlock; /* No swap space left */
vma->vm_mm->rss--;
- tsk->nswap++;
set_pte(page_table, __pte(entry));
- spin_unlock(&tsk->mm->page_table_lock);
+ spin_unlock(&vma->vm_mm->page_table_lock);
flush_tlb_page(vma, address);
swap_duplicate(entry); /* One for the process, one for the swap cache */
@@ -175,7 +174,7 @@
__free_page(page);
return 1;
out_failed_unlock:
- spin_unlock(&tsk->mm->page_table_lock);
+ spin_unlock(&vma->vm_mm->page_table_lock);
out_failed:
return 0;
}
@@ -194,8 +193,7 @@
* (C) 1993 Kai Petzke, wpp@marie.physik.tu-berlin.de
*/
-static inline int swap_out_pmd(struct task_struct * tsk, struct vm_area_struct * vma,
- pmd_t *dir, unsigned long address, unsigned long end, int gfp_mask)
+static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long end, int gfp_mask)
{
pte_t * pte;
unsigned long pmd_end;
@@ -216,8 +214,8 @@
do {
int result;
- tsk->mm->swap_address = address + PAGE_SIZE;
- result = try_to_swap_out(tsk, vma, address, pte, gfp_mask);
+ vma->vm_mm->swap_address = address + PAGE_SIZE;
+ result = try_to_swap_out(vma, address, pte, gfp_mask);
if (result)
return result;
address += PAGE_SIZE;
@@ -226,8 +224,7 @@
return 0;
}
-static inline int swap_out_pgd(struct task_struct * tsk, struct vm_area_struct * vma,
- pgd_t *dir, unsigned long address, unsigned long end, int gfp_mask)
+static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir, unsigned long address, unsigned long end, int gfp_mask)
{
pmd_t * pmd;
unsigned long pgd_end;
@@ -247,7 +244,7 @@
end = pgd_end;
do {
- int result = swap_out_pmd(tsk, vma, pmd, address, end, gfp_mask);
+ int result = swap_out_pmd(vma, pmd, address, end, gfp_mask);
if (result)
return result;
address = (address + PMD_SIZE) & PMD_MASK;
@@ -256,8 +253,7 @@
return 0;
}
-static int swap_out_vma(struct task_struct * tsk, struct vm_area_struct * vma,
- unsigned long address, int gfp_mask)
+static int swap_out_vma(struct vm_area_struct * vma, unsigned long address, int gfp_mask)
{
pgd_t *pgdir;
unsigned long end;
@@ -266,11 +262,11 @@
if (vma->vm_flags & VM_LOCKED)
return 0;
- pgdir = pgd_offset(tsk->mm, address);
+ pgdir = pgd_offset(vma->vm_mm, address);
end = vma->vm_end;
while (address < end) {
- int result = swap_out_pgd(tsk, vma, pgdir, address, end, gfp_mask);
+ int result = swap_out_pgd(vma, pgdir, address, end, gfp_mask);
if (result)
return result;
address = (address + PGDIR_SIZE) & PGDIR_MASK;
@@ -279,7 +275,7 @@
return 0;
}
-static int swap_out_process(struct task_struct * p, int gfp_mask)
+static int swap_out_mm(struct mm_struct * mm, int gfp_mask)
{
unsigned long address;
struct vm_area_struct* vma;
@@ -287,18 +283,18 @@
/*
* Go through process' page directory.
*/
- address = p->mm->swap_address;
+ address = mm->swap_address;
/*
* Find the proper vm-area
*/
- vma = find_vma(p->mm, address);
+ vma = find_vma(mm, address);
if (vma) {
if (address < vma->vm_start)
address = vma->vm_start;
for (;;) {
- int result = swap_out_vma(p, vma, address, gfp_mask);
+ int result = swap_out_vma(vma, address, gfp_mask);
if (result)
return result;
vma = vma->vm_next;
@@ -309,8 +305,8 @@
}
/* We didn't find anything for the process */
- p->mm->swap_cnt = 0;
- p->mm->swap_address = 0;
+ mm->swap_cnt = 0;
+ mm->swap_address = 0;
return 0;
}
@@ -321,8 +317,8 @@
*/
static int swap_out(unsigned int priority, int gfp_mask)
{
- struct task_struct * p, * pbest;
- int counter, assign, max_cnt;
+ struct task_struct * p;
+ int counter;
/*
* We make one or two passes through the task list, indexed by
@@ -345,36 +341,49 @@
counter = nr_threads;
for (; counter >= 0; counter--) {
- assign = 0;
- max_cnt = 0;
- pbest = NULL;
+ int assign = 0;
+ int max_cnt = 0;
+ struct mm_struct *best = NULL;
+ int pid = 0;
select:
read_lock(&tasklist_lock);
p = init_task.next_task;
for (; p != &init_task; p = p->next_task) {
- if (!p->swappable || !p->mm)
+ struct mm_struct *mm = p->mm;
+ if (!p->swappable || !mm)
continue;
- if (p->mm->rss <= 0)
+ if (mm->rss <= 0)
continue;
/* Refresh swap_cnt? */
if (assign)
- p->mm->swap_cnt = p->mm->rss;
- if (p->mm->swap_cnt > max_cnt) {
- max_cnt = p->mm->swap_cnt;
- pbest = p;
+ mm->swap_cnt = mm->rss;
+ if (mm->swap_cnt > max_cnt) {
+ max_cnt = mm->swap_cnt;
+ best = mm;
+ pid = p->pid;
}
}
read_unlock(&tasklist_lock);
- if (!pbest) {
+ if (!best) {
if (!assign) {
assign = 1;
goto select;
}
goto out;
- }
+ } else {
+ int ret;
+
+ atomic_inc(&best->mm_count);
+ ret = swap_out_mm(best, gfp_mask);
+ mmdrop(best);
+
+ if (!ret)
+ continue;
- if (swap_out_process(pbest, gfp_mask))
+ if (ret < 0)
+ kill_proc(pid, SIGBUS, 1);
return 1;
+ }
}
out:
return 0;
@@ -428,27 +437,6 @@
return priority >= 0;
}
-/*
- * Before we start the kernel thread, print out the
- * kswapd initialization message (otherwise the init message
- * may be printed in the middle of another driver's init
- * message). It looks very bad when that happens.
- */
-void __init kswapd_setup(void)
-{
- int i;
- char *revision="$Revision: 1.5 $", *s, *e;
-
- swap_setup();
-
- if ((s = strchr(revision, ':')) &&
- (e = strchr(s, '$')))
- s++, i = e - s;
- else
- s = revision, i = -1;
- printk ("Starting kswapd v%.*s\n", i, s);
-}
-
static struct task_struct *kswapd_process;
/*
@@ -535,4 +523,13 @@
retval = do_try_to_free_pages(gfp_mask);
return retval;
}
-
+
+static int __init kswapd_init(void)
+{
+ printk("Starting kswapd v1.6\n");
+ swap_setup();
+ kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ return 0;
+}
+
+module_init(kswapd_init)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)