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 }
Сайт управляется системой
uCoz