diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/tree-log.c | 45 |
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 | } |
2946 | no_parent: | ||
2924 | ret = 0; | 2947 | ret = 0; |
2925 | btrfs_end_log_trans(root); | 2948 | btrfs_end_log_trans(root); |
2926 | end_no_trans: | 2949 | end_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 | */ |