Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=fba2591bf4e418b6c3f9f8794c9dd8fe40ae7bd9
Commit:     fba2591bf4e418b6c3f9f8794c9dd8fe40ae7bd9
Parent:     46d2277c796f9f4937bfa668c40b2e3f43e93dd0
Author:     Linus Torvalds <[EMAIL PROTECTED]>
AuthorDate: Wed Dec 20 13:46:42 2006 -0800
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Thu Dec 21 09:19:57 2006 -0800

    VM: Remove "clear_page_dirty()" and "test_clear_page_dirty()" functions
    
    They were horribly easy to mis-use because of their tempting naming, and
    they also did way more than any users of them generally wanted them to
    do.
    
    A dirty page can become clean under two circumstances:
    
     (a) when we write it out.  We have "clear_page_dirty_for_io()" for
         this, and that function remains unchanged.
    
         In the "for IO" case it is not sufficient to just clear the dirty
         bit, you also have to mark the page as being under writeback etc.
    
     (b) when we actually remove a page due to it becoming inaccessible to
         users, notably because it was truncate()'d away or the file (or
         metadata) no longer exists, and we thus want to cancel any
         outstanding dirty state.
    
    For the (b) case, we now introduce "cancel_dirty_page()", which only
    touches the page state itself, and verifies that the page is not mapped
    (since cancelling writes on a mapped page would be actively wrong as it
    is still accessible to users).
    
    Some filesystems need to be fixed up for this: CIFS, FUSE, JFS,
    ReiserFS, XFS all use the old confusing functions, and will be fixed
    separately in subsequent commits (with some of them just removing the
    offending logic, and others using clear_page_dirty_for_io()).
    
    This was confirmed by Martin Michlmayr to fix the apt database
    corruption on ARM.
    
    Cc: Martin Michlmayr <[EMAIL PROTECTED]>
    Cc: Peter Zijlstra <[EMAIL PROTECTED]>
    Cc: Hugh Dickins <[EMAIL PROTECTED]>
    Cc: Nick Piggin <[EMAIL PROTECTED]>
    Cc: Arjan van de Ven <[EMAIL PROTECTED]>
    Cc: Andrei Popa <[EMAIL PROTECTED]>
    Cc: Andrew Morton <[EMAIL PROTECTED]>
    Cc: Dave Kleikamp <[EMAIL PROTECTED]>
    Cc: Gordon Farquharson <[EMAIL PROTECTED]>
    Cc: Martin Schwidefsky <[EMAIL PROTECTED]>
    Cc: Trond Myklebust <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/hugetlbfs/inode.c       |    2 +-
 include/linux/page-flags.h |    8 ++------
 mm/page-writeback.c        |   32 --------------------------------
 mm/truncate.c              |   25 +++++++++++++++++--------
 4 files changed, 20 insertions(+), 47 deletions(-)

diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index ed2c223..4f4cd13 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -176,7 +176,7 @@ static int hugetlbfs_commit_write(struct file *file,
 
 static void truncate_huge_page(struct page *page)
 {
-       clear_page_dirty(page);
+       cancel_dirty_page(page, /* No IO accounting for huge pages? */0);
        ClearPageUptodate(page);
        remove_from_page_cache(page);
        put_page(page);
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 4830a3b..350878a 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -253,15 +253,11 @@ static inline void SetPageUptodate(struct page *page)
 
 struct page;   /* forward declaration */
 
-int test_clear_page_dirty(struct page *page);
+extern void cancel_dirty_page(struct page *page, unsigned int account_size);
+
 int test_clear_page_writeback(struct page *page);
 int test_set_page_writeback(struct page *page);
 
-static inline void clear_page_dirty(struct page *page)
-{
-       test_clear_page_dirty(page);
-}
-
 static inline void set_page_writeback(struct page *page)
 {
        test_set_page_writeback(page);
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 237107c..b3a198c 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -845,38 +845,6 @@ int set_page_dirty_lock(struct page *page)
 EXPORT_SYMBOL(set_page_dirty_lock);
 
 /*
- * Clear a page's dirty flag, while caring for dirty memory accounting. 
- * Returns true if the page was previously dirty.
- */
-int test_clear_page_dirty(struct page *page)
-{
-       struct address_space *mapping = page_mapping(page);
-       unsigned long flags;
-
-       if (!mapping)
-               return TestClearPageDirty(page);
-
-       write_lock_irqsave(&mapping->tree_lock, flags);
-       if (TestClearPageDirty(page)) {
-               radix_tree_tag_clear(&mapping->page_tree,
-                               page_index(page), PAGECACHE_TAG_DIRTY);
-               write_unlock_irqrestore(&mapping->tree_lock, flags);
-               /*
-                * We can continue to use `mapping' here because the
-                * page is locked, which pins the address_space
-                */
-               if (mapping_cap_account_dirty(mapping)) {
-                       page_mkclean(page);
-                       dec_zone_page_state(page, NR_FILE_DIRTY);
-               }
-               return 1;
-       }
-       write_unlock_irqrestore(&mapping->tree_lock, flags);
-       return 0;
-}
-EXPORT_SYMBOL(test_clear_page_dirty);
-
-/*
  * Clear a page's dirty flag, while caring for dirty memory accounting.
  * Returns true if the page was previously dirty.
  *
diff --git a/mm/truncate.c b/mm/truncate.c
index 9bfb8e8..bf9e296 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -51,6 +51,20 @@ static inline void truncate_partial_page(struct page *page, 
unsigned partial)
                do_invalidatepage(page, partial);
 }
 
+void cancel_dirty_page(struct page *page, unsigned int account_size)
+{
+       /* If we're cancelling the page, it had better not be mapped any more */
+       if (page_mapped(page)) {
+               static unsigned int warncount;
+
+               WARN_ON(++warncount < 5);
+       }
+               
+       if (TestClearPageDirty(page) && account_size)
+               task_io_account_cancelled_write(account_size);
+}
+
+
 /*
  * If truncate cannot remove the fs-private metadata from the page, the page
  * becomes anonymous.  It will be left on the LRU and may even be mapped into
@@ -70,8 +84,8 @@ truncate_complete_page(struct address_space *mapping, struct 
page *page)
        if (PagePrivate(page))
                do_invalidatepage(page, 0);
 
-       if (test_clear_page_dirty(page))
-               task_io_account_cancelled_write(PAGE_CACHE_SIZE);
+       cancel_dirty_page(page, PAGE_CACHE_SIZE);
+
        ClearPageUptodate(page);
        ClearPageMappedToDisk(page);
        remove_from_page_cache(page);
@@ -350,7 +364,6 @@ int invalidate_inode_pages2_range(struct address_space 
*mapping,
                for (i = 0; !ret && i < pagevec_count(&pvec); i++) {
                        struct page *page = pvec.pages[i];
                        pgoff_t page_index;
-                       int was_dirty;
 
                        lock_page(page);
                        if (page->mapping != mapping) {
@@ -386,12 +399,8 @@ int invalidate_inode_pages2_range(struct address_space 
*mapping,
                                          PAGE_CACHE_SIZE, 0);
                                }
                        }
-                       was_dirty = test_clear_page_dirty(page);
-                       if (!invalidate_complete_page2(mapping, page)) {
-                               if (was_dirty)
-                                       set_page_dirty(page);
+                       if (!invalidate_complete_page2(mapping, page))
                                ret = -EIO;
-                       }
                        unlock_page(page);
                }
                pagevec_release(&pvec);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to