Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

swap_state.c

Go to the documentation of this file.
00001 /*
00002  *  linux/mm/swap_state.c
00003  *
00004  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
00005  *  Swap reorganised 29.12.95, Stephen Tweedie
00006  *
00007  *  Rewritten to use page cache, (C) 1998 Stephen Tweedie
00008  */
00009 
00010 #include <linux/mm.h>
00011 #include <linux/kernel_stat.h>
00012 #include <linux/swap.h>
00013 #include <linux/swapctl.h>
00014 #include <linux/init.h>
00015 #include <linux/pagemap.h>
00016 
00017 #include <asm/pgtable.h>
00018 
00019 /* 
00020  * Keep a reserved false inode which we will use to mark pages in the
00021  * page cache are acting as swap cache instead of file cache. 
00022  *
00023  * We only need a unique pointer to satisfy the page cache, but we'll
00024  * reserve an entire zeroed inode structure for the purpose just to
00025  * ensure that any mistaken dereferences of this structure cause a
00026  * kernel oops.
00027  */
00028 struct inode swapper_inode;
00029 
00030 #ifdef SWAP_CACHE_INFO
00031 unsigned long swap_cache_add_total = 0;
00032 unsigned long swap_cache_del_total = 0;
00033 unsigned long swap_cache_find_total = 0;
00034 unsigned long swap_cache_find_success = 0;
00035 
00036 void show_swap_cache_info(void)
00037 {
00038         printk("Swap cache: add %ld, delete %ld, find %ld/%ld\n",
00039                 swap_cache_add_total, 
00040                 swap_cache_del_total,
00041                 swap_cache_find_success, swap_cache_find_total);
00042 }
00043 #endif
00044 
00045 int add_to_swap_cache(struct page *page, unsigned long entry)
00046 {
00047 #ifdef SWAP_CACHE_INFO
00048         swap_cache_add_total++;
00049 #endif
00050 #ifdef DEBUG_SWAP
00051         printk("DebugVM: add_to_swap_cache(%08lx count %d, entry %08lx)\n",
00052                page_address(page), atomic_read(&page->count), entry);
00053 #endif
00054         if (PageTestandSetSwapCache(page)) {
00055                 printk(KERN_ERR "swap_cache: replacing non-empty entry %08lx "
00056                        "on page %08lx\n",
00057                        page->offset, page_address(page));
00058                 return 0;
00059         }
00060         if (page->inode) {
00061                 printk(KERN_ERR "swap_cache: replacing page-cached entry "
00062                        "on page %08lx\n", page_address(page));
00063                 return 0;
00064         }
00065         atomic_inc(&page->count);
00066         page->flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_referenced));
00067         page->inode = &swapper_inode;
00068         page->offset = entry;
00069         add_page_to_hash_queue(page, &swapper_inode, entry);
00070         add_page_to_inode_queue(&swapper_inode, page);
00071         return 1;
00072 }
00073 
00074 /*
00075  * Verify that a swap entry is valid and increment its swap map count.
00076  *
00077  * Note: if swap_map[] reaches SWAP_MAP_MAX the entries are treated as
00078  * "permanent", but will be reclaimed by the next swapoff.
00079  */
00080 int swap_duplicate(unsigned long entry)
00081 {
00082         struct swap_info_struct * p;
00083         unsigned long offset, type;
00084         int result = 0;
00085 
00086         if (!entry)
00087                 goto out;
00088         type = SWP_TYPE(entry);
00089         if (type & SHM_SWP_TYPE)
00090                 goto out;
00091         if (type >= nr_swapfiles)
00092                 goto bad_file;
00093         p = type + swap_info;
00094         offset = SWP_OFFSET(entry);
00095         if (offset >= p->max)
00096                 goto bad_offset;
00097         if (!p->swap_map[offset])
00098                 goto bad_unused;
00099         /*
00100          * Entry is valid, so increment the map count.
00101          */
00102         if (p->swap_map[offset] < SWAP_MAP_MAX)
00103                 p->swap_map[offset]++;
00104         else {
00105                 static int overflow = 0;
00106                 if (overflow++ < 5)
00107                         printk(KERN_WARNING
00108                                 "swap_duplicate: entry %08lx map count=%d\n",
00109                                 entry, p->swap_map[offset]);
00110                 p->swap_map[offset] = SWAP_MAP_MAX;
00111         }
00112         result = 1;
00113 #ifdef DEBUG_SWAP
00114         printk("DebugVM: swap_duplicate(entry %08lx, count now %d)\n",
00115                entry, p->swap_map[offset]);
00116 #endif
00117 out:
00118         return result;
00119 
00120 bad_file:
00121         printk(KERN_ERR
00122                 "swap_duplicate: entry %08lx, nonexistent swap file\n", entry);
00123         goto out;
00124 bad_offset:
00125         printk(KERN_ERR
00126                 "swap_duplicate: entry %08lx, offset exceeds max\n", entry);
00127         goto out;
00128 bad_unused:
00129         printk(KERN_ERR
00130                 "swap_duplicate at %8p: entry %08lx, unused page\n", 
00131                __builtin_return_address(0), entry);
00132         goto out;
00133 }
00134 
00135 int swap_count(unsigned long entry)
00136 {
00137         struct swap_info_struct * p;
00138         unsigned long offset, type;
00139         int retval = 0;
00140 
00141         if (!entry)
00142                 goto bad_entry;
00143         type = SWP_TYPE(entry);
00144         if (type & SHM_SWP_TYPE)
00145                 goto out;
00146         if (type >= nr_swapfiles)
00147                 goto bad_file;
00148         p = type + swap_info;
00149         offset = SWP_OFFSET(entry);
00150         if (offset >= p->max)
00151                 goto bad_offset;
00152         if (!p->swap_map[offset])
00153                 goto bad_unused;
00154         retval = p->swap_map[offset];
00155 #ifdef DEBUG_SWAP
00156         printk("DebugVM: swap_count(entry %08lx, count %d)\n",
00157                entry, retval);
00158 #endif
00159 out:
00160         return retval;
00161 
00162 bad_entry:
00163         printk(KERN_ERR "swap_count: null entry!\n");
00164         goto out;
00165 bad_file:
00166         printk(KERN_ERR
00167                "swap_count: entry %08lx, nonexistent swap file!\n", entry);
00168         goto out;
00169 bad_offset:
00170         printk(KERN_ERR
00171                "swap_count: entry %08lx, offset exceeds max!\n", entry);
00172         goto out;
00173 bad_unused:
00174         printk(KERN_ERR
00175                "swap_count at %8p: entry %08lx, unused page!\n", 
00176                __builtin_return_address(0), entry);
00177         goto out;
00178 }
00179 
00180 static inline void remove_from_swap_cache(struct page *page)
00181 {
00182         if (!page->inode) {
00183                 printk ("VM: Removing swap cache page with zero inode hash "
00184                         "on page %08lx\n", page_address(page));
00185                 return;
00186         }
00187         if (page->inode != &swapper_inode) {
00188                 printk ("VM: Removing swap cache page with wrong inode hash "
00189                         "on page %08lx\n", page_address(page));
00190         }
00191 
00192 #ifdef DEBUG_SWAP
00193         printk("DebugVM: remove_from_swap_cache(%08lx count %d)\n",
00194                page_address(page), atomic_read(&page->count));
00195 #endif
00196         PageClearSwapCache (page);
00197         remove_inode_page(page);
00198 }
00199 
00200 
00201 /*
00202  * This must be called only on pages that have
00203  * been verified to be in the swap cache.
00204  */
00205 void delete_from_swap_cache(struct page *page)
00206 {
00207         long entry = page->offset;
00208 
00209 #ifdef SWAP_CACHE_INFO
00210         swap_cache_del_total++;
00211 #endif
00212 #ifdef DEBUG_SWAP
00213         printk("DebugVM: delete_from_swap_cache(%08lx count %d, "
00214                "entry %08lx)\n",
00215                page_address(page), atomic_read(&page->count), entry);
00216 #endif
00217         remove_from_swap_cache (page);
00218         swap_free (entry);
00219 }
00220 
00221 /* 
00222  * Perform a free_page(), also freeing any swap cache associated with
00223  * this page if it is the last user of the page. 
00224  */
00225 
00226 void free_page_and_swap_cache(unsigned long addr)
00227 {
00228         struct page *page = mem_map + MAP_NR(addr);
00229 
00230         /* 
00231          * If we are the only user, then free up the swap cache. 
00232          */
00233         if (PageSwapCache(page) && !is_page_shared(page)) {
00234                 delete_from_swap_cache(page);
00235         }
00236         
00237         __free_page(page);
00238 }
00239 
00240 
00241 /*
00242  * Lookup a swap entry in the swap cache.  We need to be careful about
00243  * locked pages.  A found page will be returned with its refcount
00244  * incremented.
00245  */
00246 
00247 struct page * lookup_swap_cache(unsigned long entry)
00248 {
00249         struct page *found;
00250 
00251 #ifdef SWAP_CACHE_INFO
00252         swap_cache_find_total++;
00253 #endif
00254         while (1) {
00255                 found = find_page(&swapper_inode, entry);
00256                 if (!found)
00257                         return 0;
00258                 if (found->inode != &swapper_inode || !PageSwapCache(found))
00259                         goto out_bad;
00260                 if (!PageLocked(found)) {
00261 #ifdef SWAP_CACHE_INFO
00262                         swap_cache_find_success++;
00263 #endif
00264                         return found;
00265                 }
00266                 __free_page(found);
00267                 __wait_on_page(found);
00268         }
00269 
00270 out_bad:
00271         printk (KERN_ERR "VM: Found a non-swapper swap page!\n");
00272         __free_page(found);
00273         return 0;
00274 }
00275 
00276 /* 
00277  * Locate a page of swap in physical memory, reserving swap cache space
00278  * and reading the disk if it is not already cached.  If wait==0, we are
00279  * only doing readahead, so don't worry if the page is already locked.
00280  *
00281  * A failure return means that either the page allocation failed or that
00282  * the swap entry is no longer in use.
00283  */
00284 
00285 struct page * read_swap_cache_async(unsigned long entry, int wait)
00286 {
00287         struct page *found_page = 0, *new_page;
00288         unsigned long new_page_addr;
00289         
00290 #ifdef DEBUG_SWAP
00291         printk("DebugVM: read_swap_cache_async entry %08lx%s\n",
00292                entry, wait ? ", wait" : "");
00293 #endif
00294         /*
00295          * Make sure the swap entry is still in use.
00296          */
00297         if (!swap_duplicate(entry))     /* Account for the swap cache */
00298                 goto out;
00299         /*
00300          * Look for the page in the swap cache.
00301          */
00302         found_page = lookup_swap_cache(entry);
00303         if (found_page)
00304                 goto out_free_swap;
00305 
00306         new_page_addr = __get_free_page(GFP_USER);
00307         if (!new_page_addr)
00308                 goto out_free_swap;     /* Out of memory */
00309         new_page = mem_map + MAP_NR(new_page_addr);
00310 
00311         /*
00312          * Check the swap cache again, in case we stalled above.
00313          */
00314         found_page = lookup_swap_cache(entry);
00315         if (found_page)
00316                 goto out_free_page;
00317         /* 
00318          * Add it to the swap cache and read its contents.
00319          */
00320         if (!add_to_swap_cache(new_page, entry))
00321                 goto out_free_page;
00322 
00323         set_bit(PG_locked, &new_page->flags);
00324         rw_swap_page(READ, entry, (char *) new_page_addr, wait);
00325 #ifdef DEBUG_SWAP
00326         printk("DebugVM: read_swap_cache_async created "
00327                "entry %08lx at %p\n",
00328                entry, (char *) page_address(new_page));
00329 #endif
00330         return new_page;
00331 
00332 out_free_page:
00333         __free_page(new_page);
00334 out_free_swap:
00335         swap_free(entry);
00336 out:
00337         return found_page;
00338 }