aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/btrfs_inode.h3
-rw-r--r--fs/btrfs/file.c19
-rw-r--r--fs/btrfs/inode.c5
-rw-r--r--fs/btrfs/tree-log.c8
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);
1087out: 1104out:
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 }