]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - mm/truncate.c
[POWERPC] modify PCI code for a merged kernel
[karo-tx-linux.git] / mm / truncate.c
index 6cb3fff25f670948d1ef519d7609793b54bfdca3..c6ab55ec6883378cb46367e54c7568f1f2b3983d 100644 (file)
@@ -68,10 +68,10 @@ invalidate_complete_page(struct address_space *mapping, struct page *page)
                return 0;
 
        write_lock_irq(&mapping->tree_lock);
-       if (PageDirty(page)) {
-               write_unlock_irq(&mapping->tree_lock);
-               return 0;
-       }
+       if (PageDirty(page))
+               goto failed;
+       if (page_count(page) != 2)      /* caller's ref + pagecache ref */
+               goto failed;
 
        BUG_ON(PagePrivate(page));
        __remove_from_page_cache(page);
@@ -79,6 +79,9 @@ invalidate_complete_page(struct address_space *mapping, struct page *page)
        ClearPageUptodate(page);
        page_cache_release(page);       /* pagecache ref */
        return 1;
+failed:
+       write_unlock_irq(&mapping->tree_lock);
+       return 0;
 }
 
 /**
@@ -230,14 +233,24 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
                        pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
                for (i = 0; i < pagevec_count(&pvec); i++) {
                        struct page *page = pvec.pages[i];
+                       pgoff_t index;
+                       int lock_failed;
 
-                       if (TestSetPageLocked(page)) {
-                               next++;
-                               continue;
-                       }
-                       if (page->index > next)
-                               next = page->index;
+                       lock_failed = TestSetPageLocked(page);
+
+                       /*
+                        * We really shouldn't be looking at the ->index of an
+                        * unlocked page.  But we're not allowed to lock these
+                        * pages.  So we rely upon nobody altering the ->index
+                        * of this (pinned-by-us) page.
+                        */
+                       index = page->index;
+                       if (index > next)
+                               next = index;
                        next++;
+                       if (lock_failed)
+                               continue;
+
                        if (PageDirty(page) || PageWriteback(page))
                                goto unlock;
                        if (page_mapped(page))