diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
commit | d6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch) | |
tree | e2be02f33984c48ec019c654051d27964e42c441 /mm/swapfile.c | |
parent | 609d1e803baf519487233b765eb487f9ec227a18 (diff) |
Merge with 2.3.19.
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r-- | mm/swapfile.c | 98 |
1 files changed, 77 insertions, 21 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index ce18f34f5..c4ce5377d 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -46,16 +46,36 @@ static inline int scan_swap_map(struct swap_info_struct *si) } } si->cluster_nr = SWAPFILE_CLUSTER; + + /* try to find an empty (even not aligned) cluster. */ + offset = si->lowest_bit; + check_next_cluster: + if (offset+SWAPFILE_CLUSTER-1 <= si->highest_bit) + { + int nr; + for (nr = offset; nr < offset+SWAPFILE_CLUSTER; nr++) + if (si->swap_map[nr]) + { + offset = nr+1; + goto check_next_cluster; + } + /* We found a completly empty cluster, so start + * using it. + */ + goto got_page; + } + /* No luck, so now go finegrined as usual. -Andrea */ for (offset = si->lowest_bit; offset <= si->highest_bit ; offset++) { if (si->swap_map[offset]) continue; - si->lowest_bit = offset; -got_page: - si->swap_map[offset] = 1; - nr_swap_pages--; + got_page: + if (offset == si->lowest_bit) + si->lowest_bit++; if (offset == si->highest_bit) si->highest_bit--; - si->cluster_next = offset; + si->swap_map[offset] = 1; + nr_swap_pages--; + si->cluster_next = offset+1; return offset; } return 0; @@ -81,12 +101,9 @@ unsigned long get_swap_page(void) entry = SWP_ENTRY(type,offset); type = swap_info[type].next; if (type < 0 || - p->prio != swap_info[type].prio) - { + p->prio != swap_info[type].prio) { swap_list.next = swap_list.head; - } - else - { + } else { swap_list.next = type; } return entry; @@ -126,15 +143,16 @@ void swap_free(unsigned long entry) offset = SWP_OFFSET(entry); if (offset >= p->max) goto bad_offset; - if (offset < p->lowest_bit) - p->lowest_bit = offset; - if (offset > p->highest_bit) - p->highest_bit = offset; if (!p->swap_map[offset]) goto bad_free; if (p->swap_map[offset] < SWAP_MAP_MAX) { - if (!--p->swap_map[offset]) + if (!--p->swap_map[offset]) { + if (offset < p->lowest_bit) + p->lowest_bit = offset; + if (offset > p->highest_bit) + p->highest_bit = offset; nr_swap_pages++; + } } #ifdef DEBUG_SWAP printk("DebugVM: swap_free(entry %08lx, count now %d)\n", @@ -157,6 +175,44 @@ bad_free: goto out; } +/* needs the big kernel lock */ +unsigned long acquire_swap_entry(struct page *page) +{ + struct swap_info_struct * p; + unsigned long offset, type; + unsigned long entry; + + if (!test_bit(PG_swap_entry, &page->flags)) + goto new_swap_entry; + + /* We have the old entry in the page offset still */ + entry = page->offset; + if (!entry) + goto new_swap_entry; + type = SWP_TYPE(entry); + if (type & SHM_SWP_TYPE) + goto new_swap_entry; + if (type >= nr_swapfiles) + goto new_swap_entry; + p = type + swap_info; + if ((p->flags & SWP_WRITEOK) != SWP_WRITEOK) + goto new_swap_entry; + offset = SWP_OFFSET(entry); + if (offset >= p->max) + goto new_swap_entry; + /* Has it been re-used for something else? */ + if (p->swap_map[offset]) + goto new_swap_entry; + + /* We're cool, we can just use the old one */ + p->swap_map[offset] = 1; + nr_swap_pages--; + return entry; + +new_swap_entry: + return get_swap_page(); +} + /* * The swap entry has been read in advance, and we return 1 to indicate * that the page has been used or is no longer needed. @@ -266,7 +322,7 @@ static void unuse_process(struct mm_struct * mm, unsigned long entry, /* * Go through process' page directory. */ - if (!mm || mm == &init_mm) + if (!mm) return; for (vma = mm->mmap; vma; vma = vma->vm_next) { pgd_t * pgd = pgd_offset(mm, vma->vm_start); @@ -340,7 +396,7 @@ static int try_to_unuse(unsigned int type) return 0; } -asmlinkage int sys_swapoff(const char * specialfile) +asmlinkage long sys_swapoff(const char * specialfile) { struct swap_info_struct * p = NULL; struct dentry * dentry; @@ -484,7 +540,7 @@ int is_swap_partition(kdev_t dev) { * * The swapon system call */ -asmlinkage int sys_swapon(const char * specialfile, int swap_flags) +asmlinkage long sys_swapon(const char * specialfile, int swap_flags) { struct swap_info_struct * p; struct dentry * swap_dentry; @@ -495,7 +551,6 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags) static int least_priority = 0; union swap_header *swap_header = 0; int swap_header_version; - int lock_map_size = PAGE_SIZE; int nr_good_pages = 0; unsigned long maxpages; int swapfilesize; @@ -661,8 +716,9 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags) else p->swap_map[page] = SWAP_MAP_BAD; } - nr_good_pages = swap_header->info.last_page - i; - lock_map_size = (p->max + 7) / 8; + nr_good_pages = swap_header->info.last_page - + swap_header->info.nr_badpages - + 1 /* header page */; if (error) goto bad_swap; } |