diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2009-05-08 08:53:52 -0400 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2009-09-14 01:18:20 -0400 |
commit | d6f5b0aa08078c3dabe377d5b1a6077e9c9352d3 (patch) | |
tree | b5d6bd99e007c57a6cd4953368202d99a41141cd | |
parent | 09eb47a7c52ad535aafca889e0b936c445c375ce (diff) |
kill-the-bkl/reiserfs: factorize the locking in reiserfs_write_end()
reiserfs_write_end() is a hot path in reiserfs.
We have two wasteful write lock lock/release inside that can be gathered
without changing the code logic.
This patch factorizes them out in a single protected section, reducing the
number of contentions inside.
[ Impact: reduce lock contention in a reiserfs hotpath ]
Cc: Jeff Mahoney <jeffm@suse.com>
Cc: Chris Mason <chris.mason@oracle.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Alexander Beregalov <a.beregalov@gmail.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
-rw-r--r-- | fs/reiserfs/inode.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 6114050f342e..853f4f6fe920 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -2681,6 +2681,8 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, | |||
2681 | int update_sd = 0; | 2681 | int update_sd = 0; |
2682 | struct reiserfs_transaction_handle *th; | 2682 | struct reiserfs_transaction_handle *th; |
2683 | unsigned start; | 2683 | unsigned start; |
2684 | int lock_depth = 0; | ||
2685 | bool locked = false; | ||
2684 | 2686 | ||
2685 | if ((unsigned long)fsdata & AOP_FLAG_CONT_EXPAND) | 2687 | if ((unsigned long)fsdata & AOP_FLAG_CONT_EXPAND) |
2686 | pos ++; | 2688 | pos ++; |
@@ -2707,9 +2709,11 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, | |||
2707 | ** to do the i_size updates here. | 2709 | ** to do the i_size updates here. |
2708 | */ | 2710 | */ |
2709 | pos += copied; | 2711 | pos += copied; |
2712 | |||
2710 | if (pos > inode->i_size) { | 2713 | if (pos > inode->i_size) { |
2711 | struct reiserfs_transaction_handle myth; | 2714 | struct reiserfs_transaction_handle myth; |
2712 | reiserfs_write_lock(inode->i_sb); | 2715 | lock_depth = reiserfs_write_lock_once(inode->i_sb); |
2716 | locked = true; | ||
2713 | /* If the file have grown beyond the border where it | 2717 | /* If the file have grown beyond the border where it |
2714 | can have a tail, unmark it as needing a tail | 2718 | can have a tail, unmark it as needing a tail |
2715 | packing */ | 2719 | packing */ |
@@ -2720,10 +2724,9 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, | |||
2720 | REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; | 2724 | REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; |
2721 | 2725 | ||
2722 | ret = journal_begin(&myth, inode->i_sb, 1); | 2726 | ret = journal_begin(&myth, inode->i_sb, 1); |
2723 | if (ret) { | 2727 | if (ret) |
2724 | reiserfs_write_unlock(inode->i_sb); | ||
2725 | goto journal_error; | 2728 | goto journal_error; |
2726 | } | 2729 | |
2727 | reiserfs_update_inode_transaction(inode); | 2730 | reiserfs_update_inode_transaction(inode); |
2728 | inode->i_size = pos; | 2731 | inode->i_size = pos; |
2729 | /* | 2732 | /* |
@@ -2735,34 +2738,36 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, | |||
2735 | reiserfs_update_sd(&myth, inode); | 2738 | reiserfs_update_sd(&myth, inode); |
2736 | update_sd = 1; | 2739 | update_sd = 1; |
2737 | ret = journal_end(&myth, inode->i_sb, 1); | 2740 | ret = journal_end(&myth, inode->i_sb, 1); |
2738 | reiserfs_write_unlock(inode->i_sb); | ||
2739 | if (ret) | 2741 | if (ret) |
2740 | goto journal_error; | 2742 | goto journal_error; |
2741 | } | 2743 | } |
2742 | if (th) { | 2744 | if (th) { |
2743 | reiserfs_write_lock(inode->i_sb); | 2745 | if (!locked) { |
2746 | lock_depth = reiserfs_write_lock_once(inode->i_sb); | ||
2747 | locked = true; | ||
2748 | } | ||
2744 | if (!update_sd) | 2749 | if (!update_sd) |
2745 | mark_inode_dirty(inode); | 2750 | mark_inode_dirty(inode); |
2746 | ret = reiserfs_end_persistent_transaction(th); | 2751 | ret = reiserfs_end_persistent_transaction(th); |
2747 | reiserfs_write_unlock(inode->i_sb); | ||
2748 | if (ret) | 2752 | if (ret) |
2749 | goto out; | 2753 | goto out; |
2750 | } | 2754 | } |
2751 | 2755 | ||
2752 | out: | 2756 | out: |
2757 | if (locked) | ||
2758 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); | ||
2753 | unlock_page(page); | 2759 | unlock_page(page); |
2754 | page_cache_release(page); | 2760 | page_cache_release(page); |
2755 | return ret == 0 ? copied : ret; | 2761 | return ret == 0 ? copied : ret; |
2756 | 2762 | ||
2757 | journal_error: | 2763 | journal_error: |
2764 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); | ||
2765 | locked = false; | ||
2758 | if (th) { | 2766 | if (th) { |
2759 | reiserfs_write_lock(inode->i_sb); | ||
2760 | if (!update_sd) | 2767 | if (!update_sd) |
2761 | reiserfs_update_sd(th, inode); | 2768 | reiserfs_update_sd(th, inode); |
2762 | ret = reiserfs_end_persistent_transaction(th); | 2769 | ret = reiserfs_end_persistent_transaction(th); |
2763 | reiserfs_write_unlock(inode->i_sb); | ||
2764 | } | 2770 | } |
2765 | |||
2766 | goto out; | 2771 | goto out; |
2767 | } | 2772 | } |
2768 | 2773 | ||