/* * Trying to stop swapping from a file is fraught with races, so * we repeat quite a bit here when we have to pause. swapoff() * isn't exactly timing-critical, so who cares (but this is /really/ * inefficient, ugh). * * We return 1 after having slept, which makes the process start over * from the beginning for this process.. */ static inline int unuse_pte(struct vm_area_struct * vma, unsigned long address, pte_t *dir, unsigned int type, unsigned long page) { pte_t pte = *dir; if (pte_none(pte)) return 0; if (pte_present(pte)) { unsigned long page_nr = MAP_NR(pte_page(pte)); if (page_nr >= MAP_NR(high_memory)) return 0; if (!in_swap_cache(page_nr)) return 0; if (SWP_TYPE(in_swap_cache(page_nr)) != type) return 0; delete_from_swap_cache(page_nr); set_pte(dir, pte_mkdirty(pte)); return 0; } if (SWP_TYPE(pte_val(pte)) != type) return 0; read_swap_page(pte_val(pte), (char *) page); #if 0 /* Is this really needed here, hasn't it been solved elsewhere? */ flush_page_to_ram(page); #endif if (pte_val(*dir) != pte_val(pte)) { free_page(page); return 1; } set_pte(dir, pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)))); flush_tlb_page(vma, address); ++vma->vm_mm->rss; swap_free(pte_val(pte)); return 1; }
void swap_in(unsigned long *table_ptr) { int swap_nr; unsigned long page; if (!swap_bitmap) { printk("Trying to swap in without swap bit-map"); return; } if (1 & *table_ptr) { printk("trying to swap in present page\n\r"); return; } swap_nr = *table_ptr >> 1; if (!swap_nr) { printk("No swap page in swap_in\n\r"); return; } if (!(page = get_free_page())) oom(); read_swap_page(swap_nr, (char *) page); if (setbit(swap_bitmap,swap_nr)) printk("swapping in multiply from same page\n\r"); *table_ptr = page | (PAGE_DIRTY | 7); }
int sys_swapon(const char * specialfile) { struct inode * swap_inode; int i,j; if (!suser()) return -EPERM; if (!(swap_inode = namei(specialfile))) return -ENOENT; if (swap_file || swap_device || swap_bitmap) { iput(swap_inode); return -EBUSY; } if (S_ISBLK(swap_inode->i_mode)) { swap_device = swap_inode->i_rdev; iput(swap_inode); } else if (S_ISREG(swap_inode->i_mode)) swap_file = swap_inode; else { iput(swap_inode); return -EINVAL; } swap_bitmap = (char *) get_free_page(); if (!swap_bitmap) { iput(swap_file); swap_device = 0; swap_file = NULL; printk("Unable to start swapping: out of memory :-)\n"); return -ENOMEM; } read_swap_page(0,swap_bitmap); if (strncmp("SWAP-SPACE",swap_bitmap+4086,10)) { printk("Unable to find swap-space signature\n\r"); free_page((long) swap_bitmap); iput(swap_file); swap_device = 0; swap_file = NULL; swap_bitmap = NULL; return -EINVAL; } memset(swap_bitmap+4086,0,10); j = 0; for (i = 1 ; i < SWAP_BITS ; i++) if (bit(swap_bitmap,i)) j++; if (!j) { printk("Empty swap-file\n"); free_page((long) swap_bitmap); iput(swap_file); swap_device = 0; swap_file = NULL; swap_bitmap = NULL; return -EINVAL; } printk("Adding Swap: %d pages (%d bytes) swap-space\n\r",j,j*4096); return 0; }
void swap_in(struct vm_area_struct * vma, pte_t * page_table, swap_entry_t entry, int write_access) { unsigned long page; if(pte_val(*page_table) != entry.val) { return; } page = get_free_page(GFP_KERNEL); if(!page) { pte_val(*page_table) = PAGE_BAD; swap_free(entry); oom(); } read_swap_page(entry,(char *)page); if(pte_val(*page_table) != entry.val) { return; } return ; }