diff options
Diffstat (limited to 'fs/btrfs/file.c')
| -rw-r--r-- | fs/btrfs/file.c | 48 |
1 files changed, 30 insertions, 18 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index f19e1259a971..77f759302e12 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -878,7 +878,8 @@ again: | |||
| 878 | btrfs_put_ordered_extent(ordered); | 878 | btrfs_put_ordered_extent(ordered); |
| 879 | 879 | ||
| 880 | clear_extent_bits(&BTRFS_I(inode)->io_tree, start_pos, | 880 | clear_extent_bits(&BTRFS_I(inode)->io_tree, start_pos, |
| 881 | last_pos - 1, EXTENT_DIRTY | EXTENT_DELALLOC, | 881 | last_pos - 1, EXTENT_DIRTY | EXTENT_DELALLOC | |
| 882 | EXTENT_DO_ACCOUNTING, | ||
| 882 | GFP_NOFS); | 883 | GFP_NOFS); |
| 883 | unlock_extent(&BTRFS_I(inode)->io_tree, | 884 | unlock_extent(&BTRFS_I(inode)->io_tree, |
| 884 | start_pos, last_pos - 1, GFP_NOFS); | 885 | start_pos, last_pos - 1, GFP_NOFS); |
| @@ -908,7 +909,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
| 908 | unsigned long last_index; | 909 | unsigned long last_index; |
| 909 | int will_write; | 910 | int will_write; |
| 910 | 911 | ||
| 911 | will_write = ((file->f_flags & O_SYNC) || IS_SYNC(inode) || | 912 | will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || |
| 912 | (file->f_flags & O_DIRECT)); | 913 | (file->f_flags & O_DIRECT)); |
| 913 | 914 | ||
| 914 | nrptrs = min((count + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE, | 915 | nrptrs = min((count + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE, |
| @@ -1075,7 +1076,7 @@ out_nolock: | |||
| 1075 | if (err) | 1076 | if (err) |
| 1076 | num_written = err; | 1077 | num_written = err; |
| 1077 | 1078 | ||
| 1078 | if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { | 1079 | if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { |
| 1079 | trans = btrfs_start_transaction(root, 1); | 1080 | trans = btrfs_start_transaction(root, 1); |
| 1080 | ret = btrfs_log_dentry_safe(trans, root, | 1081 | ret = btrfs_log_dentry_safe(trans, root, |
| 1081 | file->f_dentry); | 1082 | file->f_dentry); |
| @@ -1085,8 +1086,10 @@ out_nolock: | |||
| 1085 | btrfs_end_transaction(trans, root); | 1086 | btrfs_end_transaction(trans, root); |
| 1086 | else | 1087 | else |
| 1087 | btrfs_commit_transaction(trans, root); | 1088 | btrfs_commit_transaction(trans, root); |
| 1088 | } else { | 1089 | } else if (ret != BTRFS_NO_LOG_SYNC) { |
| 1089 | btrfs_commit_transaction(trans, root); | 1090 | btrfs_commit_transaction(trans, root); |
| 1091 | } else { | ||
| 1092 | btrfs_end_transaction(trans, root); | ||
| 1090 | } | 1093 | } |
| 1091 | } | 1094 | } |
| 1092 | if (file->f_flags & O_DIRECT) { | 1095 | if (file->f_flags & O_DIRECT) { |
| @@ -1136,6 +1139,13 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
| 1136 | int ret = 0; | 1139 | int ret = 0; |
| 1137 | struct btrfs_trans_handle *trans; | 1140 | struct btrfs_trans_handle *trans; |
| 1138 | 1141 | ||
| 1142 | |||
| 1143 | /* we wait first, since the writeback may change the inode */ | ||
| 1144 | root->log_batch++; | ||
| 1145 | /* the VFS called filemap_fdatawrite for us */ | ||
| 1146 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | ||
| 1147 | root->log_batch++; | ||
| 1148 | |||
| 1139 | /* | 1149 | /* |
| 1140 | * check the transaction that last modified this inode | 1150 | * check the transaction that last modified this inode |
| 1141 | * and see if its already been committed | 1151 | * and see if its already been committed |
| @@ -1143,6 +1153,11 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
| 1143 | if (!BTRFS_I(inode)->last_trans) | 1153 | if (!BTRFS_I(inode)->last_trans) |
| 1144 | goto out; | 1154 | goto out; |
| 1145 | 1155 | ||
| 1156 | /* | ||
| 1157 | * if the last transaction that changed this file was before | ||
| 1158 | * the current transaction, we can bail out now without any | ||
| 1159 | * syncing | ||
| 1160 | */ | ||
| 1146 | mutex_lock(&root->fs_info->trans_mutex); | 1161 | mutex_lock(&root->fs_info->trans_mutex); |
| 1147 | if (BTRFS_I(inode)->last_trans <= | 1162 | if (BTRFS_I(inode)->last_trans <= |
| 1148 | root->fs_info->last_trans_committed) { | 1163 | root->fs_info->last_trans_committed) { |
| @@ -1152,13 +1167,6 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
| 1152 | } | 1167 | } |
| 1153 | mutex_unlock(&root->fs_info->trans_mutex); | 1168 | mutex_unlock(&root->fs_info->trans_mutex); |
| 1154 | 1169 | ||
| 1155 | root->log_batch++; | ||
| 1156 | filemap_fdatawrite(inode->i_mapping); | ||
| 1157 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | ||
| 1158 | root->log_batch++; | ||
| 1159 | |||
| 1160 | if (datasync && !(inode->i_state & I_DIRTY_PAGES)) | ||
| 1161 | goto out; | ||
| 1162 | /* | 1170 | /* |
| 1163 | * ok we haven't committed the transaction yet, lets do a commit | 1171 | * ok we haven't committed the transaction yet, lets do a commit |
| 1164 | */ | 1172 | */ |
| @@ -1187,14 +1195,18 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
| 1187 | */ | 1195 | */ |
| 1188 | mutex_unlock(&dentry->d_inode->i_mutex); | 1196 | mutex_unlock(&dentry->d_inode->i_mutex); |
| 1189 | 1197 | ||
| 1190 | if (ret > 0) { | 1198 | if (ret != BTRFS_NO_LOG_SYNC) { |
| 1191 | ret = btrfs_commit_transaction(trans, root); | 1199 | if (ret > 0) { |
| 1192 | } else { | ||
| 1193 | ret = btrfs_sync_log(trans, root); | ||
| 1194 | if (ret == 0) | ||
| 1195 | ret = btrfs_end_transaction(trans, root); | ||
| 1196 | else | ||
| 1197 | ret = btrfs_commit_transaction(trans, root); | 1200 | ret = btrfs_commit_transaction(trans, root); |
| 1201 | } else { | ||
| 1202 | ret = btrfs_sync_log(trans, root); | ||
| 1203 | if (ret == 0) | ||
| 1204 | ret = btrfs_end_transaction(trans, root); | ||
| 1205 | else | ||
| 1206 | ret = btrfs_commit_transaction(trans, root); | ||
| 1207 | } | ||
| 1208 | } else { | ||
| 1209 | ret = btrfs_end_transaction(trans, root); | ||
| 1198 | } | 1210 | } |
| 1199 | mutex_lock(&dentry->d_inode->i_mutex); | 1211 | mutex_lock(&dentry->d_inode->i_mutex); |
| 1200 | out: | 1212 | out: |
