]> err.no Git - linux-2.6/blobdiff - mm/swapfile.c
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
[linux-2.6] / mm / swapfile.c
index 4d11f9d84666fbc0186f18729f52eb830496bcdb..e5fd5385f0cc119005a87decfb10385b67a2474f 100644 (file)
@@ -397,18 +397,24 @@ void free_swap_and_cache(swp_entry_t entry)
 
        p = swap_info_get(entry);
        if (p) {
-               if (swap_entry_free(p, swp_offset(entry)) == 1)
-                       page = find_trylock_page(&swapper_space, entry.val);
+               if (swap_entry_free(p, swp_offset(entry)) == 1) {
+                       page = find_get_page(&swapper_space, entry.val);
+                       if (page && unlikely(TestSetPageLocked(page))) {
+                               page_cache_release(page);
+                               page = NULL;
+                       }
+               }
                spin_unlock(&swap_lock);
        }
        if (page) {
                int one_user;
 
                BUG_ON(PagePrivate(page));
-               page_cache_get(page);
                one_user = (page_count(page) == 2);
                /* Only cache user (+us), or swap space full? Free it! */
-               if (!PageWriteback(page) && (one_user || vm_swap_full())) {
+               /* Also recheck PageSwapCache after page is locked (above) */
+               if (PageSwapCache(page) && !PageWriteback(page) &&
+                                       (one_user || vm_swap_full())) {
                        delete_from_swap_cache(page);
                        SetPageDirty(page);
                }
@@ -428,14 +434,16 @@ int swap_type_of(dev_t device)
 {
        int i;
 
-       if (!device)
-               return -EINVAL;
        spin_lock(&swap_lock);
        for (i = 0; i < nr_swapfiles; i++) {
                struct inode *inode;
 
                if (!(swap_info[i].flags & SWP_WRITEOK))
                        continue;
+               if (!device) {
+                       spin_unlock(&swap_lock);
+                       return i;
+               }
                inode = swap_info->swap_file->f_dentry->d_inode;
                if (S_ISBLK(inode->i_mode) &&
                    device == MKDEV(imajor(inode), iminor(inode))) {