]> err.no Git - linux-2.6/blobdiff - fs/buffer.c
[PATCH] ext4: refuse ro to rw remount of fs with orphan inodes
[linux-2.6] / fs / buffer.c
index 3b116078b4c399211875623092de6eec139d4c15..763c5b59492d9f6c003e5d39377c2f7a4445f7f1 100644 (file)
@@ -345,7 +345,7 @@ void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers)
         * We really want to use invalidate_inode_pages2() for
         * that, but not until that's cleaned up.
         */
-       invalidate_inode_pages(mapping);
+       invalidate_mapping_pages(mapping, 0, -1);
 }
 
 /*
@@ -2834,7 +2834,7 @@ int try_to_free_buffers(struct page *page)
        int ret = 0;
 
        BUG_ON(!PageLocked(page));
-       if (PageDirty(page) || PageWriteback(page))
+       if (PageWriteback(page))
                return 0;
 
        if (mapping == NULL) {          /* can this still happen? */
@@ -2844,6 +2844,23 @@ int try_to_free_buffers(struct page *page)
 
        spin_lock(&mapping->private_lock);
        ret = drop_buffers(page, &buffers_to_free);
+
+       /*
+        * If the filesystem writes its buffers by hand (eg ext3)
+        * then we can have clean buffers against a dirty page.  We
+        * clean the page here; otherwise the VM will never notice
+        * that the filesystem did any IO at all.
+        *
+        * Also, during truncate, discard_buffer will have marked all
+        * the page's buffers clean.  We discover that here and clean
+        * the page also.
+        *
+        * private_lock must be held over this entire operation in order
+        * to synchronise against __set_page_dirty_buffers and prevent the
+        * dirty bit from being lost.
+        */
+       if (ret)
+               cancel_dirty_page(page, PAGE_CACHE_SIZE);
        spin_unlock(&mapping->private_lock);
 out:
        if (buffers_to_free) {