]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - mm/swapfile.c
[SCSI] lpfc 8.1.2: Explicitly initialize the skip_post argument to lpfc_sli_send_reset
[linux-2.6-omap-h63xx.git] / mm / swapfile.c
index d8a5afc8b2a3a417ade826173ce96a55f2ac0000..1f9cf0d073b84caad71234ddfb091618906d3047 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/rmap.h>
 #include <linux/security.h>
 #include <linux/backing-dev.h>
+#include <linux/mutex.h>
+#include <linux/capability.h>
 #include <linux/syscalls.h>
 
 #include <asm/pgtable.h>
@@ -45,12 +47,12 @@ struct swap_list_t swap_list = {-1, -1};
 
 struct swap_info_struct swap_info[MAX_SWAPFILES];
 
-static DECLARE_MUTEX(swapon_sem);
+static DEFINE_MUTEX(swapon_mutex);
 
 /*
  * We need this because the bdev->unplug_fn can sleep and we cannot
  * hold swap_lock while calling the unplug_fn. And swap_lock
- * cannot be turned into a semaphore.
+ * cannot be turned into a mutex.
  */
 static DECLARE_RWSEM(swap_unplug_sem);
 
@@ -552,6 +554,15 @@ static int unuse_mm(struct mm_struct *mm,
        return 0;
 }
 
+#ifdef CONFIG_MIGRATION
+int remove_vma_swap(struct vm_area_struct *vma, struct page *page)
+{
+       swp_entry_t entry = { .val = page_private(page) };
+
+       return unuse_vma(vma, entry, page);
+}
+#endif
+
 /*
  * Scan swap_map from current position to next entry still in use.
  * Recycle to start on reaching the end, returning 0 when empty.
@@ -644,6 +655,7 @@ static int try_to_unuse(unsigned int type)
                 */
                swap_map = &si->swap_map[i];
                entry = swp_entry(type, i);
+again:
                page = read_swap_cache_async(entry, NULL, 0);
                if (!page) {
                        /*
@@ -678,6 +690,12 @@ static int try_to_unuse(unsigned int type)
                wait_on_page_locked(page);
                wait_on_page_writeback(page);
                lock_page(page);
+               if (!PageSwapCache(page)) {
+                       /* Page migration has occured */
+                       unlock_page(page);
+                       page_cache_release(page);
+                       goto again;
+               }
                wait_on_page_writeback(page);
 
                /*
@@ -1160,7 +1178,7 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
        up_write(&swap_unplug_sem);
 
        destroy_swap_extents(p);
-       down(&swapon_sem);
+       mutex_lock(&swapon_mutex);
        spin_lock(&swap_lock);
        drain_mmlist();
 
@@ -1179,7 +1197,7 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
        p->swap_map = NULL;
        p->flags = 0;
        spin_unlock(&swap_lock);
-       up(&swapon_sem);
+       mutex_unlock(&swapon_mutex);
        vfree(swap_map);
        inode = mapping->host;
        if (S_ISBLK(inode->i_mode)) {
@@ -1208,7 +1226,7 @@ static void *swap_start(struct seq_file *swap, loff_t *pos)
        int i;
        loff_t l = *pos;
 
-       down(&swapon_sem);
+       mutex_lock(&swapon_mutex);
 
        for (i = 0; i < nr_swapfiles; i++, ptr++) {
                if (!(ptr->flags & SWP_USED) || !ptr->swap_map)
@@ -1237,7 +1255,7 @@ static void *swap_next(struct seq_file *swap, void *v, loff_t *pos)
 
 static void swap_stop(struct seq_file *swap, void *v)
 {
-       up(&swapon_sem);
+       mutex_unlock(&swapon_mutex);
 }
 
 static int swap_show(struct seq_file *swap, void *v)
@@ -1539,7 +1557,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
                goto bad_swap;
        }
 
-       down(&swapon_sem);
+       mutex_lock(&swapon_mutex);
        spin_lock(&swap_lock);
        p->flags = SWP_ACTIVE;
        nr_swap_pages += nr_good_pages;
@@ -1565,7 +1583,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
                swap_info[prev].next = p - swap_info;
        }
        spin_unlock(&swap_lock);
-       up(&swapon_sem);
+       mutex_unlock(&swapon_mutex);
        error = 0;
        goto out;
 bad_swap: