>>>>> "juan" == Juan J Quintela <[EMAIL PROTECTED]> writes:

Hi Linus
   I am resending to you this patch, it works here, and nobody has
   complained about it the previous times that I post it here.
    
Later, Juan.

juan>         I have reworte the function truncate_inode_pages.  The version
juan>         in vanilla pre9-3 does busy waiting in the partial page, with
juan>         this version the locking for the partial page and from the
juan>         rest of the pages is the same.  This make that we have less
juan>         special cases.  For the rest of pages the function works the
juan>         same.  The only difference is that version is cleaner IMHO.
juan>         Or there are some corner case that I have failed to see?

juan>         Comments?

juan>         Later, Juan.

juan>         I have CC: the linux-fsdevel people, they are the users of
juan>         that function, could somebody give me some feedback against
juan>         the change?



diff -urN --exclude-from=/home/lfcia/quintela/work/kernel/exclude work/mm/filemap.c 
testing/mm/filemap.c
--- work/mm/filemap.c   Fri May 12 23:46:46 2000
+++ testing/mm/filemap.c        Sun May 14 22:08:45 2000
@@ -146,9 +146,39 @@
        spin_unlock(&pagecache_lock);
 }
 
-/*
+static inline void truncate_partial_page(struct page *page, unsigned partial)
+{
+       memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
+                               
+       if (page->buffers)
+               block_flushpage(page, partial);
+
+}
+
+static inline void truncate_complete_page(struct page *page)
+{
+       if (!page->buffers || block_flushpage(page, 0))
+               lru_cache_del(page);
+       
+       /*
+        * We remove the page from the page cache _after_ we have
+        * destroyed all buffer-cache references to it. Otherwise some
+        * other process might think this inode page is not in the
+        * page cache and creates a buffer-cache alias to it causing
+        * all sorts of fun problems ...  
+        */
+       remove_inode_page(page);
+       page_cache_release(page);
+}
+
+/**
+ * truncate_inode_pages - truncate *all* the pages from an offset
+ * @mapping: mapping to truncate
+ * @lstart: offset from with to truncate
+ *
  * Truncate the page cache at a set offset, removing the pages
  * that are beyond that offset (and zeroing out partial pages).
+ * If any page is locked we wait for it to become unlocked.
  */
 void truncate_inode_pages(struct address_space * mapping, loff_t lstart)
 {
@@ -168,11 +198,10 @@
 
                page = list_entry(curr, struct page, list);
                curr = curr->next;
-
                offset = page->index;
 
-               /* page wholly truncated - free it */
-               if (offset >= start) {
+               /* Is one of the pages to truncate? */
+               if ((offset >= start) || (partial && (offset + 1) == start)) {
                        if (TryLockPage(page)) {
                                page_cache_get(page);
                                spin_unlock(&pagecache_lock);
@@ -183,22 +212,14 @@
                        page_cache_get(page);
                        spin_unlock(&pagecache_lock);
 
-                       if (!page->buffers || block_flushpage(page, 0))
-                               lru_cache_del(page);
-
-                       /*
-                        * We remove the page from the page cache
-                        * _after_ we have destroyed all buffer-cache
-                        * references to it. Otherwise some other process
-                        * might think this inode page is not in the
-                        * page cache and creates a buffer-cache alias
-                        * to it causing all sorts of fun problems ...
-                        */
-                       remove_inode_page(page);
+                       if (partial && (offset + 1) == start) {
+                               truncate_partial_page(page, partial);
+                               partial = 0;
+                       } else 
+                               truncate_complete_page(page);
 
                        UnlockPage(page);
                        page_cache_release(page);
-                       page_cache_release(page);
 
                        /*
                         * We have done things without the pagecache lock,
@@ -209,37 +230,6 @@
                         */
                        goto repeat;
                }
-               /*
-                * there is only one partial page possible.
-                */
-               if (!partial)
-                       continue;
-
-               /* and it's the one preceeding the first wholly truncated page */
-               if ((offset + 1) != start)
-                       continue;
-
-               /* partial truncate, clear end of page */
-               if (TryLockPage(page)) {
-                       spin_unlock(&pagecache_lock);
-                       goto repeat;
-               }
-               page_cache_get(page);
-               spin_unlock(&pagecache_lock);
-
-               memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
-               if (page->buffers)
-                       block_flushpage(page, partial);
-
-               partial = 0;
-
-               /*
-                * we have dropped the spinlock so we have to
-                * restart.
-                */
-               UnlockPage(page);
-               page_cache_release(page);
-               goto repeat;
        }
        spin_unlock(&pagecache_lock);
 }

-- 
In theory, practice and theory are the same, but in practice they 
are different -- Larry McVoy

Reply via email to