diff options
author | Nick Piggin <nickpiggin@yahoo.com.au> | 2005-07-07 20:56:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-07 21:23:45 -0400 |
commit | a39722034ae37f80a1803bf781fe3fe1b03e20bc (patch) | |
tree | fb7ef719d745e28678d73f884108f4cb2ef79171 /fs | |
parent | d6afe27bfff30fbec2cca6ad5626c22f4094d770 (diff) |
[PATCH] page_uptodate locking scalability
Use a bit spin lock in the first buffer of the page to synchronise asynch
IO buffer completions, instead of the global page_uptodate_lock, which is
showing some scalabilty problems.
Signed-off-by: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/buffer.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 561e63a14966..6a25d7df89b1 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -513,8 +513,8 @@ static void free_more_memory(void) | |||
513 | */ | 513 | */ |
514 | static void end_buffer_async_read(struct buffer_head *bh, int uptodate) | 514 | static void end_buffer_async_read(struct buffer_head *bh, int uptodate) |
515 | { | 515 | { |
516 | static DEFINE_SPINLOCK(page_uptodate_lock); | ||
517 | unsigned long flags; | 516 | unsigned long flags; |
517 | struct buffer_head *first; | ||
518 | struct buffer_head *tmp; | 518 | struct buffer_head *tmp; |
519 | struct page *page; | 519 | struct page *page; |
520 | int page_uptodate = 1; | 520 | int page_uptodate = 1; |
@@ -536,7 +536,9 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate) | |||
536 | * two buffer heads end IO at almost the same time and both | 536 | * two buffer heads end IO at almost the same time and both |
537 | * decide that the page is now completely done. | 537 | * decide that the page is now completely done. |
538 | */ | 538 | */ |
539 | spin_lock_irqsave(&page_uptodate_lock, flags); | 539 | first = page_buffers(page); |
540 | local_irq_save(flags); | ||
541 | bit_spin_lock(BH_Uptodate_Lock, &first->b_state); | ||
540 | clear_buffer_async_read(bh); | 542 | clear_buffer_async_read(bh); |
541 | unlock_buffer(bh); | 543 | unlock_buffer(bh); |
542 | tmp = bh; | 544 | tmp = bh; |
@@ -549,7 +551,8 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate) | |||
549 | } | 551 | } |
550 | tmp = tmp->b_this_page; | 552 | tmp = tmp->b_this_page; |
551 | } while (tmp != bh); | 553 | } while (tmp != bh); |
552 | spin_unlock_irqrestore(&page_uptodate_lock, flags); | 554 | bit_spin_unlock(BH_Uptodate_Lock, &first->b_state); |
555 | local_irq_restore(flags); | ||
553 | 556 | ||
554 | /* | 557 | /* |
555 | * If none of the buffers had errors and they are all | 558 | * If none of the buffers had errors and they are all |
@@ -561,7 +564,8 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate) | |||
561 | return; | 564 | return; |
562 | 565 | ||
563 | still_busy: | 566 | still_busy: |
564 | spin_unlock_irqrestore(&page_uptodate_lock, flags); | 567 | bit_spin_unlock(BH_Uptodate_Lock, &first->b_state); |
568 | local_irq_restore(flags); | ||
565 | return; | 569 | return; |
566 | } | 570 | } |
567 | 571 | ||
@@ -572,8 +576,8 @@ still_busy: | |||
572 | void end_buffer_async_write(struct buffer_head *bh, int uptodate) | 576 | void end_buffer_async_write(struct buffer_head *bh, int uptodate) |
573 | { | 577 | { |
574 | char b[BDEVNAME_SIZE]; | 578 | char b[BDEVNAME_SIZE]; |
575 | static DEFINE_SPINLOCK(page_uptodate_lock); | ||
576 | unsigned long flags; | 579 | unsigned long flags; |
580 | struct buffer_head *first; | ||
577 | struct buffer_head *tmp; | 581 | struct buffer_head *tmp; |
578 | struct page *page; | 582 | struct page *page; |
579 | 583 | ||
@@ -594,7 +598,10 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate) | |||
594 | SetPageError(page); | 598 | SetPageError(page); |
595 | } | 599 | } |
596 | 600 | ||
597 | spin_lock_irqsave(&page_uptodate_lock, flags); | 601 | first = page_buffers(page); |
602 | local_irq_save(flags); | ||
603 | bit_spin_lock(BH_Uptodate_Lock, &first->b_state); | ||
604 | |||
598 | clear_buffer_async_write(bh); | 605 | clear_buffer_async_write(bh); |
599 | unlock_buffer(bh); | 606 | unlock_buffer(bh); |
600 | tmp = bh->b_this_page; | 607 | tmp = bh->b_this_page; |
@@ -605,12 +612,14 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate) | |||
605 | } | 612 | } |
606 | tmp = tmp->b_this_page; | 613 | tmp = tmp->b_this_page; |
607 | } | 614 | } |
608 | spin_unlock_irqrestore(&page_uptodate_lock, flags); | 615 | bit_spin_unlock(BH_Uptodate_Lock, &first->b_state); |
616 | local_irq_restore(flags); | ||
609 | end_page_writeback(page); | 617 | end_page_writeback(page); |
610 | return; | 618 | return; |
611 | 619 | ||
612 | still_busy: | 620 | still_busy: |
613 | spin_unlock_irqrestore(&page_uptodate_lock, flags); | 621 | bit_spin_unlock(BH_Uptodate_Lock, &first->b_state); |
622 | local_irq_restore(flags); | ||
614 | return; | 623 | return; |
615 | } | 624 | } |
616 | 625 | ||