aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs')
-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 */