aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-10-13 13:21:08 -0400
committerChris Mason <chris.mason@oracle.com>2009-10-13 13:35:12 -0400
commit257c62e1bce03e5b9f3f069fd52ad73a56de71fd (patch)
treead047fe5796156aa88e3f3600111bf2b8d12759f /fs/btrfs/tree-log.c
parent4722607db6a78bd7748c51fa4c8d7371da797254 (diff)
Btrfs: avoid tree log commit when there are no changes
rpm has a habit of running fdatasync when the file hasn't changed. We already detect if a file hasn't been changed in the current transaction but it might have been sent to the tree-log in this transaction and not changed since the last call to fsync. In this case, we want to avoid a tree log sync, which includes a number of synchronous writes and barriers. This commit extends the existing tracking of the last transaction to change a file to also track the last sub-transaction. The end result is that rpm -ivh and -Uvh are roughly twice as fast, and on par with ext3. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 6d9ec285644d..0a1bde268963 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -1980,6 +1980,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
1980 int ret; 1980 int ret;
1981 struct btrfs_root *log = root->log_root; 1981 struct btrfs_root *log = root->log_root;
1982 struct btrfs_root *log_root_tree = root->fs_info->log_root_tree; 1982 struct btrfs_root *log_root_tree = root->fs_info->log_root_tree;
1983 u64 log_transid = 0;
1983 1984
1984 mutex_lock(&root->log_mutex); 1985 mutex_lock(&root->log_mutex);
1985 index1 = root->log_transid % 2; 1986 index1 = root->log_transid % 2;
@@ -2018,6 +2019,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2018 btrfs_set_root_node(&log->root_item, log->node); 2019 btrfs_set_root_node(&log->root_item, log->node);
2019 2020
2020 root->log_batch = 0; 2021 root->log_batch = 0;
2022 log_transid = root->log_transid;
2021 root->log_transid++; 2023 root->log_transid++;
2022 log->log_transid = root->log_transid; 2024 log->log_transid = root->log_transid;
2023 root->log_start_pid = 0; 2025 root->log_start_pid = 0;
@@ -2095,6 +2097,11 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2095 write_ctree_super(trans, root->fs_info->tree_root, 1); 2097 write_ctree_super(trans, root->fs_info->tree_root, 1);
2096 ret = 0; 2098 ret = 0;
2097 2099
2100 mutex_lock(&root->log_mutex);
2101 if (root->last_log_commit < log_transid)
2102 root->last_log_commit = log_transid;
2103 mutex_unlock(&root->log_mutex);
2104
2098out_wake_log_root: 2105out_wake_log_root:
2099 atomic_set(&log_root_tree->log_commit[index2], 0); 2106 atomic_set(&log_root_tree->log_commit[index2], 0);
2100 smp_mb(); 2107 smp_mb();
@@ -2862,6 +2869,21 @@ out:
2862 return ret; 2869 return ret;
2863} 2870}
2864 2871
2872static int inode_in_log(struct btrfs_trans_handle *trans,
2873 struct inode *inode)
2874{
2875 struct btrfs_root *root = BTRFS_I(inode)->root;
2876 int ret = 0;
2877
2878 mutex_lock(&root->log_mutex);
2879 if (BTRFS_I(inode)->logged_trans == trans->transid &&
2880 BTRFS_I(inode)->last_sub_trans <= root->last_log_commit)
2881 ret = 1;
2882 mutex_unlock(&root->log_mutex);
2883 return ret;
2884}
2885
2886
2865/* 2887/*
2866 * helper function around btrfs_log_inode to make sure newly created 2888 * helper function around btrfs_log_inode to make sure newly created
2867 * parent directories also end up in the log. A minimal inode and backref 2889 * parent directories also end up in the log. A minimal inode and backref
@@ -2901,6 +2923,11 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
2901 if (ret) 2923 if (ret)
2902 goto end_no_trans; 2924 goto end_no_trans;
2903 2925
2926 if (inode_in_log(trans, inode)) {
2927 ret = BTRFS_NO_LOG_SYNC;
2928 goto end_no_trans;
2929 }
2930
2904 start_log_trans(trans, root); 2931 start_log_trans(trans, root);
2905 2932
2906 ret = btrfs_log_inode(trans, root, inode, inode_only); 2933 ret = btrfs_log_inode(trans, root, inode, inode_only);