kill-the-bkl/reiserfs: factorize the locking in reiserfs_write_end()
authorFrederic Weisbecker <fweisbec@gmail.com>
Fri, 8 May 2009 12:53:52 +0000 (14:53 +0200)
committerFrederic Weisbecker <fweisbec@gmail.com>
Mon, 14 Sep 2009 05:18:20 +0000 (07:18 +0200)
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>
fs/reiserfs/inode.c

index 6114050..853f4f6 100644 (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;
 }