diff options
-rw-r--r-- | fs/btrfs/btrfs_inode.h | 3 | ||||
-rw-r--r-- | fs/btrfs/file.c | 19 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 5 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 8 |
4 files changed, 29 insertions, 6 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index fcc8cf27e906..0577fda2168a 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
@@ -56,6 +56,9 @@ struct btrfs_inode { | |||
56 | * transid that last logged this inode | 56 | * transid that last logged this inode |
57 | */ | 57 | */ |
58 | u64 logged_trans; | 58 | u64 logged_trans; |
59 | |||
60 | /* trans that last made a change that should be fully fsync'd */ | ||
61 | u64 log_dirty_trans; | ||
59 | u64 delalloc_bytes; | 62 | u64 delalloc_bytes; |
60 | u64 disk_i_size; | 63 | u64 disk_i_size; |
61 | u32 flags; | 64 | u32 flags; |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 84ecf3ab8511..58b329ddb426 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1061,7 +1061,9 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1061 | } | 1061 | } |
1062 | mutex_unlock(&root->fs_info->trans_mutex); | 1062 | mutex_unlock(&root->fs_info->trans_mutex); |
1063 | 1063 | ||
1064 | root->fs_info->tree_log_batch++; | ||
1064 | filemap_fdatawait(inode->i_mapping); | 1065 | filemap_fdatawait(inode->i_mapping); |
1066 | root->fs_info->tree_log_batch++; | ||
1065 | 1067 | ||
1066 | /* | 1068 | /* |
1067 | * ok we haven't committed the transaction yet, lets do a commit | 1069 | * ok we haven't committed the transaction yet, lets do a commit |
@@ -1076,14 +1078,29 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1076 | } | 1078 | } |
1077 | 1079 | ||
1078 | ret = btrfs_log_dentry_safe(trans, root, file->f_dentry); | 1080 | ret = btrfs_log_dentry_safe(trans, root, file->f_dentry); |
1079 | if (ret < 0) | 1081 | if (ret < 0) { |
1080 | goto out; | 1082 | goto out; |
1083 | } | ||
1084 | |||
1085 | /* we've logged all the items and now have a consistent | ||
1086 | * version of the file in the log. It is possible that | ||
1087 | * someone will come in and modify the file, but that's | ||
1088 | * fine because the log is consistent on disk, and we | ||
1089 | * have references to all of the file's extents | ||
1090 | * | ||
1091 | * It is possible that someone will come in and log the | ||
1092 | * file again, but that will end up using the synchronization | ||
1093 | * inside btrfs_sync_log to keep things safe. | ||
1094 | */ | ||
1095 | mutex_unlock(&file->f_dentry->d_inode->i_mutex); | ||
1096 | |||
1081 | if (ret > 0) { | 1097 | if (ret > 0) { |
1082 | ret = btrfs_commit_transaction(trans, root); | 1098 | ret = btrfs_commit_transaction(trans, root); |
1083 | } else { | 1099 | } else { |
1084 | btrfs_sync_log(trans, root); | 1100 | btrfs_sync_log(trans, root); |
1085 | ret = btrfs_end_transaction(trans, root); | 1101 | ret = btrfs_end_transaction(trans, root); |
1086 | } | 1102 | } |
1103 | mutex_lock(&file->f_dentry->d_inode->i_mutex); | ||
1087 | out: | 1104 | out: |
1088 | return ret > 0 ? EIO : ret; | 1105 | return ret > 0 ? EIO : ret; |
1089 | } | 1106 | } |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 24b7e97fccb9..12c1c0530f3d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1187,7 +1187,9 @@ int btrfs_unlink_inode(struct btrfs_trans_handle *trans, | |||
1187 | 1187 | ||
1188 | ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len, | 1188 | ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len, |
1189 | inode, dir->i_ino); | 1189 | inode, dir->i_ino); |
1190 | BUG_ON(ret); | 1190 | BUG_ON(ret != 0 && ret != -ENOENT); |
1191 | if (ret != -ENOENT) | ||
1192 | BTRFS_I(dir)->log_dirty_trans = trans->transid; | ||
1191 | 1193 | ||
1192 | ret = btrfs_del_dir_entries_in_log(trans, root, name, name_len, | 1194 | ret = btrfs_del_dir_entries_in_log(trans, root, name, name_len, |
1193 | dir, index); | 1195 | dir, index); |
@@ -1790,6 +1792,7 @@ static noinline void init_btrfs_i(struct inode *inode) | |||
1790 | bi->disk_i_size = 0; | 1792 | bi->disk_i_size = 0; |
1791 | bi->flags = 0; | 1793 | bi->flags = 0; |
1792 | bi->index_cnt = (u64)-1; | 1794 | bi->index_cnt = (u64)-1; |
1795 | bi->log_dirty_trans = 0; | ||
1793 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); | 1796 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); |
1794 | extent_io_tree_init(&BTRFS_I(inode)->io_tree, | 1797 | extent_io_tree_init(&BTRFS_I(inode)->io_tree, |
1795 | inode->i_mapping, GFP_NOFS); | 1798 | inode->i_mapping, GFP_NOFS); |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 3f4b139b27ed..5d49a701bdcd 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -1973,10 +1973,10 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
1973 | atomic_set(&log->fs_info->tree_log_commit, 1); | 1973 | atomic_set(&log->fs_info->tree_log_commit, 1); |
1974 | 1974 | ||
1975 | while(1) { | 1975 | while(1) { |
1976 | batch = log->fs_info->tree_log_batch; | ||
1976 | mutex_unlock(&log->fs_info->tree_log_mutex); | 1977 | mutex_unlock(&log->fs_info->tree_log_mutex); |
1977 | schedule_timeout_uninterruptible(1); | 1978 | schedule_timeout_uninterruptible(1); |
1978 | mutex_lock(&log->fs_info->tree_log_mutex); | 1979 | mutex_lock(&log->fs_info->tree_log_mutex); |
1979 | batch = log->fs_info->tree_log_batch; | ||
1980 | 1980 | ||
1981 | while(atomic_read(&log->fs_info->tree_log_writers)) { | 1981 | while(atomic_read(&log->fs_info->tree_log_writers)) { |
1982 | DEFINE_WAIT(wait); | 1982 | DEFINE_WAIT(wait); |
@@ -2189,8 +2189,6 @@ int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans, | |||
2189 | mutex_unlock(&BTRFS_I(inode)->log_mutex); | 2189 | mutex_unlock(&BTRFS_I(inode)->log_mutex); |
2190 | end_log_trans(root); | 2190 | end_log_trans(root); |
2191 | 2191 | ||
2192 | if (ret == 0 || ret == -ENOENT) | ||
2193 | return 0; | ||
2194 | return ret; | 2192 | return ret; |
2195 | } | 2193 | } |
2196 | 2194 | ||
@@ -2620,9 +2618,11 @@ static int __btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
2620 | else | 2618 | else |
2621 | break; | 2619 | break; |
2622 | } | 2620 | } |
2623 | if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) { | 2621 | if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode) && |
2622 | BTRFS_I(inode)->log_dirty_trans >= trans->transid) { | ||
2624 | btrfs_release_path(root, path); | 2623 | btrfs_release_path(root, path); |
2625 | btrfs_release_path(log, dst_path); | 2624 | btrfs_release_path(log, dst_path); |
2625 | BTRFS_I(inode)->log_dirty_trans = 0; | ||
2626 | ret = log_directory_changes(trans, root, inode, path, dst_path); | 2626 | ret = log_directory_changes(trans, root, inode, path, dst_path); |
2627 | BUG_ON(ret); | 2627 | BUG_ON(ret); |
2628 | } | 2628 | } |