Ядро Linux в комментариях

Mm/swap_state.c


37479 /* 37480 * linux/mm/swap_state.c 37481 * 37482 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds 37483 * Swap reorganised 29.12.95, Stephen Tweedie 37484 * 37485 * Rewritten to use page cache, (C) 1998 Stephen Tweedie 37486 */ 37487 37488 #include <linux/mm.h> 37489 #include <linux/kernel_stat.h> 37490 #include <linux/swap.h> 37491 #include <linux/swapctl.h> 37492 #include <linux/init.h> 37493 #include <linux/pagemap.h> 37494 37495 #include <asm/pgtable.h> 37496 37497 /* Keep a reserved false inode which we will use to mark 37498 * pages in the page cache are acting as swap cache 37499 * instead of file cache. 37500 * 37501 * We only need a unique pointer to satisfy the page 37502 * cache, but we'll reserve an entire zeroed inode 37503 * structure for the purpose just to ensure that any 37504 * mistaken dereferences of this structure cause a kernel 37505 * oops. */ 37506 struct inode swapper_inode; 37507 37508 #ifdef SWAP_CACHE_INFO 37509 unsigned long swap_cache_add_total = 0; 37510 unsigned long swap_cache_del_total = 0; 37511 unsigned long swap_cache_find_total = 0; 37512 unsigned long swap_cache_find_success = 0; 37513 37514 void show_swap_cache_info(void) 37515 { 37516 printk("Swap cache: add %ld, delete %ld, " 37517 "find %ld/%ld\n", 37518 swap_cache_add_total, 37519 swap_cache_del_total, 37520 swap_cache_find_success, swap_cache_find_total); 37521 } 37522 #endif 37523 37524 int add_to_swap_cache(struct page *page, 37525 unsigned long entry) 37526 { 37527 #ifdef SWAP_CACHE_INFO 37528 swap_cache_add_total++; 37529 #endif 37530 #ifdef DEBUG_SWAP 37531 printk("DebugVM: add_to_swap_cache(%08lx count %d, " 37532 "entry %08lx)\n", page_address(page), 37533 atomic_read(&page->count), entry); 37534 #endif 37535 if (PageTestandSetSwapCache(page)) { 37536 printk(KERN_ERR 37537 "swap_cache: replacing non-empty entry %08lx " 37538 "on page %08lx\n", 37539 page->offset, page_address(page)); 37540 return 0; 37541 } 37542 if (page->inode) { 37543 printk(KERN_ERR 37544 "swap_cache: replacing page-cached entry " 37545 "on page %08lx\n", page_address(page)); 37546 return 0; 37547 } 37548 atomic_inc(&page->count); 37549 page->inode = &swapper_inode; 37550 page->offset = entry; 37551 add_page_to_hash_queue(page, &swapper_inode, entry); 37552 add_page_to_inode_queue(&swapper_inode, page); 37553 return 1; 37554 } 37555 37556 /* Verify that a swap entry is valid and increment its 37557 * swap map count. 37558 * 37559 * Note: if swap_map[] reaches SWAP_MAP_MAX the entries 37560 * are treated as "permanent", but will be reclaimed by 37561 * the next swapoff. */ 37562 int swap_duplicate(unsigned long entry) 37563 { 37564 struct swap_info_struct * p; 37565 unsigned long offset, type; 37566 int result = 0; 37567 37568 if (!entry) 37569 goto out; 37570 type = SWP_TYPE(entry); 37571 if (type & SHM_SWP_TYPE) 37572 goto out; 37573 if (type >= nr_swapfiles) 37574 goto bad_file; 37575 p = type + swap_info; 37576 offset = SWP_OFFSET(entry); 37577 if (offset >= p->max) 37578 goto bad_offset; 37579 if (!p->swap_map[offset]) 37580 goto bad_unused; 37581 /* Entry is valid, so increment the map count. */ 37582 if (p->swap_map[offset] < SWAP_MAP_MAX) 37583 p->swap_map[offset]++; 37584 else { 37585 static int overflow = 0; 37586 if (overflow++ < 5) 37587 printk(KERN_WARNING 37588 "swap_duplicate: entry %08lx map count=%d\n", 37589 entry, p->swap_map[offset]); 37590 p->swap_map[offset] = SWAP_MAP_MAX; 37591 } 37592 result = 1; 37593 #ifdef DEBUG_SWAP 37594 printk("DebugVM: swap_duplicate(entry %08lx, " 37595 "count now %d)\n", entry, p->swap_map[offset]); 37596 #endif 37597 out: 37598 return result; 37599 37600 bad_file: 37601 printk(KERN_ERR "swap_duplicate: entry %08lx, " 37602 "nonexistent swap file\n", entry); 37603 goto out; 37604 bad_offset: 37605 printk(KERN_ERR "swap_duplicate: entry %08lx, " 37606 "offset exceeds max\n", entry); 37607 goto out; 37608 bad_unused: 37609 printk(KERN_ERR "swap_duplicate at %8p: " 37610 "entry %08lx, unused page\n", 37611 __builtin_return_address(0), entry); 37612 goto out; 37613 } 37614 37615 int swap_count(unsigned long entry) 37616 { 37617 struct swap_info_struct * p; 37618 unsigned long offset, type; 37619 int retval = 0; 37620 37621 if (!entry) 37622 goto bad_entry; 37623 type = SWP_TYPE(entry); 37624 if (type & SHM_SWP_TYPE) 37625 goto out; 37626 if (type >= nr_swapfiles) 37627 goto bad_file; 37628 p = type + swap_info; 37629 offset = SWP_OFFSET(entry); 37630 if (offset >= p->max) 37631 goto bad_offset; 37632 if (!p->swap_map[offset]) 37633 goto bad_unused; 37634 retval = p->swap_map[offset]; 37635 #ifdef DEBUG_SWAP 37636 printk("DebugVM: swap_count(entry %08lx, count %d)\n", 37637 entry, retval); 37638 #endif 37639 out: 37640 return retval; 37641 37642 bad_entry: 37643 printk(KERN_ERR "swap_count: null entry!\n"); 37644 goto out; 37645 bad_file: 37646 printk(KERN_ERR "swap_count: entry %08lx, " 37647 "nonexistent swap file!\n", entry); 37648 goto out; 37649 bad_offset: 37650 printk(KERN_ERR "swap_count: entry %08lx, offset " 37651 "exceeds max!\n", entry); 37652 goto out; 37653 bad_unused: 37654 printk(KERN_ERR "swap_count at %8p: entry %08lx, " 37655 "unused page!\n", __builtin_return_address(0), 37656 entry); 37657 goto out; 37658 } 37659 37660 static inline void remove_from_swap_cache( 37661 struct page *page) 37662 { 37663 if (!page->inode) { 37664 printk("VM: Removing swap cache page with zero inode" 37665 " hash on page %08lx\n", page_address(page)); 37666 return; 37667 } 37668 if (page->inode != &swapper_inode) { 37669 printk("VM: Removing swap cache page with wrong " 37670 "inode hash on page %08lx\n", 37671 page_address(page)); 37672 } 37673 37674 #ifdef DEBUG_SWAP 37675 printk("DebugVM: remove_from_swap_cache(%08lx " 37676 "count %d)\n", 37677 page_address(page), atomic_read(&page->count)); 37678 #endif 37679 PageClearSwapCache (page); 37680 remove_inode_page(page); 37681 } 37682 37683 37684 /* This must be called only on pages that have been 37685 * verified to be in the swap cache. */ 37686 void delete_from_swap_cache(struct page *page) 37687 { 37688 long entry = page->offset; 37689 37690 #ifdef SWAP_CACHE_INFO 37691 swap_cache_del_total++; 37692 #endif 37693 #ifdef DEBUG_SWAP 37694 printk("DebugVM: delete_from_swap_cache(%08lx " 37695 "count %d, entry %08lx)\n", 37696 page_address(page), atomic_read(&page->count), 37697 entry); 37698 #endif 37699 remove_from_swap_cache (page); 37700 swap_free (entry); 37701 } 37702 37703 /* Perform a free_page(), also freeing any swap cache 37704 * associated with this page if it is the last user of 37705 * the page. */ 37706 37707 void free_page_and_swap_cache(unsigned long addr) 37708 { 37709 struct page *page = mem_map + MAP_NR(addr); 37710 37711 /* If we are the only user, then free up the swap 37712 * cache. */ 37713 if (PageSwapCache(page) && !is_page_shared(page)) { 37714 delete_from_swap_cache(page); 37715 } 37716 37717 __free_page(page); 37718 } 37719 37720 /* Lookup a swap entry in the swap cache. We need to be 37721 * careful about locked pages. A found page will be 37722 * returned with its refcount incremented. */ 37723 struct page * lookup_swap_cache(unsigned long entry) 37724 { 37725 struct page *found; 37726 37727 #ifdef SWAP_CACHE_INFO 37728 swap_cache_find_total++; 37729 #endif 37730 while (1) { 37731 found = find_page(&swapper_inode, entry); 37732 if (!found) 37733 return 0; 37734 if (found->inode != &swapper_inode 37735 !PageSwapCache(found)) 37736 goto out_bad; 37737 if (!PageLocked(found)) { 37738 #ifdef SWAP_CACHE_INFO 37739 swap_cache_find_success++; 37740 #endif 37741 return found; 37742 } 37743 __free_page(found); 37744 __wait_on_page(found); 37745 } 37746 37747 out_bad: 37748 printk(KERN_ERR 37749 "VM: Found a non-swapper swap page!\n"); 37750 __free_page(found); 37751 return 0; 37752 } 37753 37754 /* Locate a page of swap in physical memory, reserving 37755 * swap cache space and reading the disk if it is not 37756 * already cached. If wait==0, we are only doing 37757 * readahead, so don't worry if the page is already 37758 * locked. 37759 * 37760 * A failure return means that either the page allocation 37761 * failed or that the swap entry is no longer in use. */ 37762 struct page * read_swap_cache_async(unsigned long entry, 37763 int wait) 37764 { 37765 struct page *found_page = 0, *new_page; 37766 unsigned long new_page_addr; 37767 37768 #ifdef DEBUG_SWAP 37769 printk("DebugVM: read_swap_cache_async entry %08lx%s\n" 37770 , entry, wait ? ", wait" : ""); 37771 #endif 37772 /* Make sure the swap entry is still in use. */ 37773 /* Account for the swap cache */ 37774 if (!swap_duplicate(entry)) 37775 goto out; 37776 /* Look for the page in the swap cache. */ 37777 found_page = lookup_swap_cache(entry); 37778 if (found_page) 37779 goto out_free_swap; 37780 37781 new_page_addr = __get_free_page(GFP_USER); 37782 if (!new_page_addr) 37783 goto out_free_swap; /* Out of memory */ 37784 new_page = mem_map + MAP_NR(new_page_addr); 37785 37786 /* Check the swap cache again, in case we stalled 37787 * above. */ 37788 found_page = lookup_swap_cache(entry); 37789 if (found_page) 37790 goto out_free_page; 37791 /* Add it to the swap cache and read its contents. */ 37792 if (!add_to_swap_cache(new_page, entry)) 37793 goto out_free_page; 37794 37795 set_bit(PG_locked, &new_page->flags); 37796 rw_swap_page(READ, entry, (char *)new_page_addr, wait); 37797 #ifdef DEBUG_SWAP 37798 printk("DebugVM: read_swap_cache_async created " 37799 "entry %08lx at %p\n", 37800 entry, (char *) page_address(new_page)); 37801 #endif 37802 return new_page; 37803 37804 out_free_page: 37805 __free_page(new_page); 37806 out_free_swap: 37807 swap_free(entry); 37808 out: 37809 return found_page; 37810 }



Содержание раздела