[patch 26/27] reduce lock contention in try_to_free_buffers()

From: Andrew Morton (akpm@zip.com.au)
Date: Thu Jul 04 2002 - 18:55:25 EST


The blockdev mapping's private_lock is fairly contended. The buffer
LRU cache fixed a lot of that, but under page replacement load,
try_to_free_buffers is still showing up.

Moving the freeing of buffer_heads outside the lock reduces contention
in there by 30%.

 buffer.c | 24 +++++++++++++++++++-----
 1 files changed, 19 insertions(+), 5 deletions(-)

--- 2.5.24/fs/buffer.c~ttfb_contention Thu Jul 4 16:17:34 2002
+++ 2.5.24-akpm/fs/buffer.c Thu Jul 4 16:17:34 2002
@@ -2472,7 +2472,8 @@ static inline int buffer_busy(struct buf
                 (bh->b_state & ((1 << BH_Dirty) | (1 << BH_Lock)));
 }
 
-static /*inline*/ int drop_buffers(struct page *page)
+static inline int
+drop_buffers(struct page *page, struct buffer_head **buffers_to_free)
 {
         struct buffer_head *head = page_buffers(page);
         struct buffer_head *bh;
@@ -2496,9 +2497,9 @@ static /*inline*/ int drop_buffers(struc
 
                 if (!list_empty(&bh->b_assoc_buffers))
                         __remove_assoc_queue(bh);
- free_buffer_head(bh);
                 bh = next;
         } while (bh != head);
+ *buffers_to_free = head;
         __clear_page_buffers(page);
         return 1;
 failed:
@@ -2508,17 +2509,20 @@ failed:
 int try_to_free_buffers(struct page *page)
 {
         struct address_space * const mapping = page->mapping;
+ struct buffer_head *buffers_to_free = NULL;
         int ret = 0;
 
         BUG_ON(!PageLocked(page));
         if (PageWriteback(page))
                 return 0;
 
- if (mapping == NULL) /* swapped-in anon page */
- return drop_buffers(page);
+ if (mapping == NULL) { /* swapped-in anon page */
+ ret = drop_buffers(page, &buffers_to_free);
+ goto out;
+ }
 
         spin_lock(&mapping->private_lock);
- ret = drop_buffers(page);
+ ret = drop_buffers(page, &buffers_to_free);
         if (ret && !PageSwapCache(page)) {
                 /*
                  * If the filesystem writes its buffers by hand (eg ext3)
@@ -2531,6 +2535,16 @@ int try_to_free_buffers(struct page *pag
                 ClearPageDirty(page);
         }
         spin_unlock(&mapping->private_lock);
+out:
+ if (buffers_to_free) {
+ struct buffer_head *bh = buffers_to_free;
+
+ do {
+ struct buffer_head *next = bh->b_this_page;
+ free_buffer_head(bh);
+ bh = next;
+ } while (bh != buffers_to_free);
+ }
         return ret;
 }
 EXPORT_SYMBOL(try_to_free_buffers);

-
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Jul 07 2002 - 22:00:14 EST