reduce lock contention in try_to_free_buffers()

reduce lock contention in try_to_free_buffers()

Post by Andrew Morto » Sat, 06 Jul 2002 09:30:09



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

                (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);

                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;

 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)) {
                /*

                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

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

1. reduce lock contention in do_pagecache_readahead

Anton Blanchard has a workload (the SDET benchmark) which is showing some
moderate lock contention in do_pagecache_readahead().

Seems that SDET has many threads performing seeky reads against a
cached file.  The average number of pagecache probes in a single
do_pagecache_readahead() is six, which seems reasonable.

The patch (from Anton) flips the locking around to optimise for the
fast case (page was present).  So the kernel takes the lock less often,
and does more work once it has been acquired.

=====================================

--- 2.5.16/mm/readahead.c~anton-readahead-locking       Sun May 19 11:49:45 2002

        /*
         * Preallocate as many pages as we will need.
         */
+       read_lock(&mapping->page_lock);
        for (page_idx = 0; page_idx < nr_to_read; page_idx++) {
                unsigned long page_offset = offset + page_idx;

                if (page_offset > end_index)
                        break;

-               read_lock(&mapping->page_lock);
                page = radix_tree_lookup(&mapping->page_tree, page_offset);
-               read_unlock(&mapping->page_lock);
                if (page)
                        continue;

+               read_unlock(&mapping->page_lock);
                page = page_cache_alloc(mapping);
+               read_lock(&mapping->page_lock);
                if (!page)
                        break;
                page->index = page_offset;
                list_add(&page->list, &page_pool);
                nr_to_really_read++;
        }
+       read_unlock(&mapping->page_lock);

        /*
         * Now start the IO.  We ignore I/O errors - if the page is not

-
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

2. User write privilege on /dos partition

3. Lock contention problems

4. Books.. Programming with Threads, Threads Primer.

5. kernel lock contention and scalability

6. automatic signature on email

7. Enhanced profiling support (was Re: vm lock contention reduction)

8. More dealer's bigotry, and the MS secret handshake

9. scalable kmap (was Re: vm lock contention reduction) (fwd)

10. Lock contention data for 2.5.8-pre1

11. reduced locking in buffer.c

12. Yacc: reduce/reduce-conflict

13. Reduce gif without reducing resolution?