Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d6f5b0aa authored by Frederic Weisbecker's avatar Frederic Weisbecker
Browse files

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: default avatarFrederic Weisbecker <fweisbec@gmail.com>
parent 09eb47a7
Loading
Loading
Loading
Loading
+15 −10
Original line number Original line Diff line number Diff line
@@ -2681,6 +2681,8 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
	int update_sd = 0;
	int update_sd = 0;
	struct reiserfs_transaction_handle *th;
	struct reiserfs_transaction_handle *th;
	unsigned start;
	unsigned start;
	int lock_depth = 0;
	bool locked = false;


	if ((unsigned long)fsdata & AOP_FLAG_CONT_EXPAND)
	if ((unsigned long)fsdata & AOP_FLAG_CONT_EXPAND)
		pos ++;
		pos ++;
@@ -2707,9 +2709,11 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
	 ** to do the i_size updates here.
	 ** to do the i_size updates here.
	 */
	 */
	pos += copied;
	pos += copied;

	if (pos > inode->i_size) {
	if (pos > inode->i_size) {
		struct reiserfs_transaction_handle myth;
		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
		/* If the file have grown beyond the border where it
		   can have a tail, unmark it as needing a tail
		   can have a tail, unmark it as needing a tail
		   packing */
		   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;
			REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;


		ret = journal_begin(&myth, inode->i_sb, 1);
		ret = journal_begin(&myth, inode->i_sb, 1);
		if (ret) {
		if (ret)
			reiserfs_write_unlock(inode->i_sb);
			goto journal_error;
			goto journal_error;
		}

		reiserfs_update_inode_transaction(inode);
		reiserfs_update_inode_transaction(inode);
		inode->i_size = pos;
		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);
		reiserfs_update_sd(&myth, inode);
		update_sd = 1;
		update_sd = 1;
		ret = journal_end(&myth, inode->i_sb, 1);
		ret = journal_end(&myth, inode->i_sb, 1);
		reiserfs_write_unlock(inode->i_sb);
		if (ret)
		if (ret)
			goto journal_error;
			goto journal_error;
	}
	}
	if (th) {
	if (th) {
		reiserfs_write_lock(inode->i_sb);
		if (!locked) {
			lock_depth = reiserfs_write_lock_once(inode->i_sb);
			locked = true;
		}
		if (!update_sd)
		if (!update_sd)
			mark_inode_dirty(inode);
			mark_inode_dirty(inode);
		ret = reiserfs_end_persistent_transaction(th);
		ret = reiserfs_end_persistent_transaction(th);
		reiserfs_write_unlock(inode->i_sb);
		if (ret)
		if (ret)
			goto out;
			goto out;
	}
	}


      out:
      out:
	if (locked)
		reiserfs_write_unlock_once(inode->i_sb, lock_depth);
	unlock_page(page);
	unlock_page(page);
	page_cache_release(page);
	page_cache_release(page);
	return ret == 0 ? copied : ret;
	return ret == 0 ? copied : ret;


      journal_error:
      journal_error:
	reiserfs_write_unlock_once(inode->i_sb, lock_depth);
	locked = false;
	if (th) {
	if (th) {
		reiserfs_write_lock(inode->i_sb);
		if (!update_sd)
		if (!update_sd)
			reiserfs_update_sd(th, inode);
			reiserfs_update_sd(th, inode);
		ret = reiserfs_end_persistent_transaction(th);
		ret = reiserfs_end_persistent_transaction(th);
		reiserfs_write_unlock(inode->i_sb);
	}
	}

	goto out;
	goto out;
}
}