aboutsummaryrefslogtreecommitdiffstats
path: root/fs/reiserfs/stree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/reiserfs/stree.c')
-rw-r--r--fs/reiserfs/stree.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index 960c9114f6d3..6b025a42d510 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -519,12 +519,22 @@ static int is_tree_node(struct buffer_head *bh, int level)
519 519
520#define SEARCH_BY_KEY_READA 16 520#define SEARCH_BY_KEY_READA 16
521 521
522/* The function is NOT SCHEDULE-SAFE! */ 522/*
523static void search_by_key_reada(struct super_block *s, 523 * The function is NOT SCHEDULE-SAFE!
524 * It might unlock the write lock if we needed to wait for a block
525 * to be read. Note that in this case it won't recover the lock to avoid
526 * high contention resulting from too much lock requests, especially
527 * the caller (search_by_key) will perform other schedule-unsafe
528 * operations just after calling this function.
529 *
530 * @return true if we have unlocked
531 */
532static bool search_by_key_reada(struct super_block *s,
524 struct buffer_head **bh, 533 struct buffer_head **bh,
525 b_blocknr_t *b, int num) 534 b_blocknr_t *b, int num)
526{ 535{
527 int i, j; 536 int i, j;
537 bool unlocked = false;
528 538
529 for (i = 0; i < num; i++) { 539 for (i = 0; i < num; i++) {
530 bh[i] = sb_getblk(s, b[i]); 540 bh[i] = sb_getblk(s, b[i]);
@@ -536,16 +546,21 @@ static void search_by_key_reada(struct super_block *s,
536 * the lock. But it's still fine because we check later 546 * the lock. But it's still fine because we check later
537 * if the tree changed 547 * if the tree changed
538 */ 548 */
539 reiserfs_write_unlock(s);
540 for (j = 0; j < i; j++) { 549 for (j = 0; j < i; j++) {
541 /* 550 /*
542 * note, this needs attention if we are getting rid of the BKL 551 * note, this needs attention if we are getting rid of the BKL
543 * you have to make sure the prepared bit isn't set on this buffer 552 * you have to make sure the prepared bit isn't set on this buffer
544 */ 553 */
545 if (!buffer_uptodate(bh[j])) 554 if (!buffer_uptodate(bh[j])) {
555 if (!unlocked) {
556 reiserfs_write_unlock(s);
557 unlocked = true;
558 }
546 ll_rw_block(READA, 1, bh + j); 559 ll_rw_block(READA, 1, bh + j);
560 }
547 brelse(bh[j]); 561 brelse(bh[j]);
548 } 562 }
563 return unlocked;
549} 564}
550 565
551/************************************************************************** 566/**************************************************************************
@@ -633,15 +648,26 @@ int search_by_key(struct super_block *sb, const struct cpu_key *key, /* Key to s
633 have a pointer to it. */ 648 have a pointer to it. */
634 if ((bh = last_element->pe_buffer = 649 if ((bh = last_element->pe_buffer =
635 sb_getblk(sb, block_number))) { 650 sb_getblk(sb, block_number))) {
651 bool unlocked = false;
652
636 if (!buffer_uptodate(bh) && reada_count > 1) 653 if (!buffer_uptodate(bh) && reada_count > 1)
637 /* will unlock the write lock */ 654 /* may unlock the write lock */
638 search_by_key_reada(sb, reada_bh, 655 unlocked = search_by_key_reada(sb, reada_bh,
639 reada_blocks, reada_count); 656 reada_blocks, reada_count);
640 else 657 /*
658 * If we haven't already unlocked the write lock,
659 * then we need to do that here before reading
660 * the current block
661 */
662 if (!buffer_uptodate(bh) && !unlocked) {
641 reiserfs_write_unlock(sb); 663 reiserfs_write_unlock(sb);
664 unlocked = true;
665 }
642 ll_rw_block(READ, 1, &bh); 666 ll_rw_block(READ, 1, &bh);
643 wait_on_buffer(bh); 667 wait_on_buffer(bh);
644 reiserfs_write_lock(sb); 668
669 if (unlocked)
670 reiserfs_write_lock(sb);
645 if (!buffer_uptodate(bh)) 671 if (!buffer_uptodate(bh))
646 goto io_error; 672 goto io_error;
647 } else { 673 } else {