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>
This commit is contained in:
Frederic Weisbecker 2009-05-08 14:53:52 +02:00
parent 09eb47a7c5
commit d6f5b0aa08

View File

@ -2681,6 +2681,8 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
int update_sd = 0;
struct reiserfs_transaction_handle *th;
unsigned start;
int lock_depth = 0;
bool locked = false;
if ((unsigned long)fsdata & AOP_FLAG_CONT_EXPAND)
pos ++;
@ -2707,9 +2709,11 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
** to do the i_size updates here.
*/
pos += copied;
if (pos > inode->i_size) {
struct reiserfs_transaction_handle myth;
reiserfs_write_lock(inode->i_sb);
lock_depth = reiserfs_write_lock_once(inode->i_sb);
locked = true;
/* If the file have grown beyond the border where it
can have a tail, unmark it as needing a tail
packing */
@ -2720,10 +2724,9 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
ret = journal_begin(&myth, inode->i_sb, 1);
if (ret) {
reiserfs_write_unlock(inode->i_sb);
if (ret)
goto journal_error;
}
reiserfs_update_inode_transaction(inode);
inode->i_size = pos;
/*
@ -2735,34 +2738,36 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
reiserfs_update_sd(&myth, inode);
update_sd = 1;
ret = journal_end(&myth, inode->i_sb, 1);
reiserfs_write_unlock(inode->i_sb);
if (ret)
goto journal_error;
}
if (th) {
reiserfs_write_lock(inode->i_sb);
if (!locked) {
lock_depth = reiserfs_write_lock_once(inode->i_sb);
locked = true;
}
if (!update_sd)
mark_inode_dirty(inode);
ret = reiserfs_end_persistent_transaction(th);
reiserfs_write_unlock(inode->i_sb);
if (ret)
goto out;
}
out:
if (locked)
reiserfs_write_unlock_once(inode->i_sb, lock_depth);
unlock_page(page);
page_cache_release(page);
return ret == 0 ? copied : ret;
journal_error:
reiserfs_write_unlock_once(inode->i_sb, lock_depth);
locked = false;
if (th) {
reiserfs_write_lock(inode->i_sb);
if (!update_sd)
reiserfs_update_sd(th, inode);
ret = reiserfs_end_persistent_transaction(th);
reiserfs_write_unlock(inode->i_sb);
}
goto out;
}