Btrfs: Dir fsync optimizations

Drop i_mutex during the commit

Don't bother doing the fsync at all unless the dir is marked as dirtied
and needing fsync in this transaction.  For directories, this means
that someone has unlinked a file from the dir without fsyncing the
file.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 3f4b139..5d49a70 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -1973,10 +1973,10 @@
 	atomic_set(&log->fs_info->tree_log_commit, 1);
 
 	while(1) {
+		batch = log->fs_info->tree_log_batch;
 		mutex_unlock(&log->fs_info->tree_log_mutex);
 		schedule_timeout_uninterruptible(1);
 		mutex_lock(&log->fs_info->tree_log_mutex);
-		batch = log->fs_info->tree_log_batch;
 
 		while(atomic_read(&log->fs_info->tree_log_writers)) {
 			DEFINE_WAIT(wait);
@@ -2189,8 +2189,6 @@
 	mutex_unlock(&BTRFS_I(inode)->log_mutex);
 	end_log_trans(root);
 
-	if (ret == 0 || ret == -ENOENT)
-		return 0;
 	return ret;
 }
 
@@ -2620,9 +2618,11 @@
 		else
 			break;
 	}
-	if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) {
+	if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode) &&
+	    BTRFS_I(inode)->log_dirty_trans >= trans->transid) {
 		btrfs_release_path(root, path);
 		btrfs_release_path(log, dst_path);
+		BTRFS_I(inode)->log_dirty_trans = 0;
 		ret = log_directory_changes(trans, root, inode, path, dst_path);
 		BUG_ON(ret);
 	}