aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-03-24 10:24:31 -0400
committerChris Mason <chris.mason@oracle.com>2009-03-24 16:14:52 -0400
commitaf4176b49c5ee15a9c9b10720c92456b28e7aac7 (patch)
treea8f763a172e6fc19ef6ac24f04d6b88337c8a1b6
parent12fcfd22fe5bf4fe74710232098bc101af497995 (diff)
Btrfs: optimize fsyncs on old files
The fsync log has code to make sure all of the parents of a file are in the log along with the file. It uses a minimal log of the parent directory inodes, just enough to get the parent directory on disk. If the transaction that originally created a file is fully on disk, and the file hasn't been renamed or linked into other directories, we can safely skip the parent directory walk. We know the file is on disk somewhere and we can go ahead and just log that single file. This is more important now because unrelated unlinks in the parent directory might make us force a commit if we try to log the parent. Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/tree-log.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 1b7f04a8f168..fc9b87a7975b 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2835,6 +2835,17 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
2835 int ret = 0; 2835 int ret = 0;
2836 struct btrfs_root *root; 2836 struct btrfs_root *root;
2837 2837
2838 /*
2839 * for regular files, if its inode is already on disk, we don't
2840 * have to worry about the parents at all. This is because
2841 * we can use the last_unlink_trans field to record renames
2842 * and other fun in this file.
2843 */
2844 if (S_ISREG(inode->i_mode) &&
2845 BTRFS_I(inode)->generation <= last_committed &&
2846 BTRFS_I(inode)->last_unlink_trans <= last_committed)
2847 goto out;
2848
2838 if (!S_ISDIR(inode->i_mode)) { 2849 if (!S_ISDIR(inode->i_mode)) {
2839 if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb) 2850 if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb)
2840 goto out; 2851 goto out;
@@ -2904,8 +2915,19 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
2904 2915
2905 ret = btrfs_log_inode(trans, root, inode, inode_only); 2916 ret = btrfs_log_inode(trans, root, inode, inode_only);
2906 BUG_ON(ret); 2917 BUG_ON(ret);
2907 inode_only = LOG_INODE_EXISTS;
2908 2918
2919 /*
2920 * for regular files, if its inode is already on disk, we don't
2921 * have to worry about the parents at all. This is because
2922 * we can use the last_unlink_trans field to record renames
2923 * and other fun in this file.
2924 */
2925 if (S_ISREG(inode->i_mode) &&
2926 BTRFS_I(inode)->generation <= last_committed &&
2927 BTRFS_I(inode)->last_unlink_trans <= last_committed)
2928 goto no_parent;
2929
2930 inode_only = LOG_INODE_EXISTS;
2909 while (1) { 2931 while (1) {
2910 if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb) 2932 if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb)
2911 break; 2933 break;
@@ -2921,6 +2943,7 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
2921 2943
2922 parent = parent->d_parent; 2944 parent = parent->d_parent;
2923 } 2945 }
2946no_parent:
2924 ret = 0; 2947 ret = 0;
2925 btrfs_end_log_trans(root); 2948 btrfs_end_log_trans(root);
2926end_no_trans: 2949end_no_trans:
@@ -3070,6 +3093,19 @@ void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans,
3070 int for_rename) 3093 int for_rename)
3071{ 3094{
3072 /* 3095 /*
3096 * when we're logging a file, if it hasn't been renamed
3097 * or unlinked, and its inode is fully committed on disk,
3098 * we don't have to worry about walking up the directory chain
3099 * to log its parents.
3100 *
3101 * So, we use the last_unlink_trans field to put this transid
3102 * into the file. When the file is logged we check it and
3103 * don't log the parents if the file is fully on disk.
3104 */
3105 if (S_ISREG(inode->i_mode))
3106 BTRFS_I(inode)->last_unlink_trans = trans->transid;
3107
3108 /*
3073 * if this directory was already logged any new 3109 * if this directory was already logged any new
3074 * names for this file/dir will get recorded 3110 * names for this file/dir will get recorded
3075 */ 3111 */
@@ -3115,6 +3151,13 @@ int btrfs_log_new_name(struct btrfs_trans_handle *trans,
3115 struct btrfs_root * root = BTRFS_I(inode)->root; 3151 struct btrfs_root * root = BTRFS_I(inode)->root;
3116 3152
3117 /* 3153 /*
3154 * this will force the logging code to walk the dentry chain
3155 * up for the file
3156 */
3157 if (S_ISREG(inode->i_mode))
3158 BTRFS_I(inode)->last_unlink_trans = trans->transid;
3159
3160 /*
3118 * if this inode hasn't been logged and directory we're renaming it 3161 * if this inode hasn't been logged and directory we're renaming it
3119 * from hasn't been logged, we don't need to log it 3162 * from hasn't been logged, we don't need to log it
3120 */ 3163 */