diff options
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 74 |
1 files changed, 61 insertions, 13 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 3e8023efaff7..9c9fb46ccd08 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -606,6 +606,7 @@ next_slot: | |||
606 | btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); | 606 | btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); |
607 | 607 | ||
608 | btrfs_release_path(root, path); | 608 | btrfs_release_path(root, path); |
609 | path->leave_spinning = 1; | ||
609 | ret = btrfs_insert_empty_item(trans, root, path, &ins, | 610 | ret = btrfs_insert_empty_item(trans, root, path, &ins, |
610 | sizeof(*extent)); | 611 | sizeof(*extent)); |
611 | BUG_ON(ret); | 612 | BUG_ON(ret); |
@@ -639,17 +640,22 @@ next_slot: | |||
639 | ram_bytes); | 640 | ram_bytes); |
640 | btrfs_set_file_extent_type(leaf, extent, found_type); | 641 | btrfs_set_file_extent_type(leaf, extent, found_type); |
641 | 642 | ||
643 | btrfs_unlock_up_safe(path, 1); | ||
642 | btrfs_mark_buffer_dirty(path->nodes[0]); | 644 | btrfs_mark_buffer_dirty(path->nodes[0]); |
645 | btrfs_set_lock_blocking(path->nodes[0]); | ||
643 | 646 | ||
644 | if (disk_bytenr != 0) { | 647 | if (disk_bytenr != 0) { |
645 | ret = btrfs_update_extent_ref(trans, root, | 648 | ret = btrfs_update_extent_ref(trans, root, |
646 | disk_bytenr, orig_parent, | 649 | disk_bytenr, |
650 | le64_to_cpu(old.disk_num_bytes), | ||
651 | orig_parent, | ||
647 | leaf->start, | 652 | leaf->start, |
648 | root->root_key.objectid, | 653 | root->root_key.objectid, |
649 | trans->transid, ins.objectid); | 654 | trans->transid, ins.objectid); |
650 | 655 | ||
651 | BUG_ON(ret); | 656 | BUG_ON(ret); |
652 | } | 657 | } |
658 | path->leave_spinning = 0; | ||
653 | btrfs_release_path(root, path); | 659 | btrfs_release_path(root, path); |
654 | if (disk_bytenr != 0) | 660 | if (disk_bytenr != 0) |
655 | inode_add_bytes(inode, extent_end - end); | 661 | inode_add_bytes(inode, extent_end - end); |
@@ -912,7 +918,7 @@ again: | |||
912 | btrfs_set_file_extent_other_encoding(leaf, fi, 0); | 918 | btrfs_set_file_extent_other_encoding(leaf, fi, 0); |
913 | 919 | ||
914 | if (orig_parent != leaf->start) { | 920 | if (orig_parent != leaf->start) { |
915 | ret = btrfs_update_extent_ref(trans, root, bytenr, | 921 | ret = btrfs_update_extent_ref(trans, root, bytenr, num_bytes, |
916 | orig_parent, leaf->start, | 922 | orig_parent, leaf->start, |
917 | root->root_key.objectid, | 923 | root->root_key.objectid, |
918 | trans->transid, inode->i_ino); | 924 | trans->transid, inode->i_ino); |
@@ -1091,19 +1097,24 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1091 | WARN_ON(num_pages > nrptrs); | 1097 | WARN_ON(num_pages > nrptrs); |
1092 | memset(pages, 0, sizeof(struct page *) * nrptrs); | 1098 | memset(pages, 0, sizeof(struct page *) * nrptrs); |
1093 | 1099 | ||
1094 | ret = btrfs_check_free_space(root, write_bytes, 0); | 1100 | ret = btrfs_check_data_free_space(root, inode, write_bytes); |
1095 | if (ret) | 1101 | if (ret) |
1096 | goto out; | 1102 | goto out; |
1097 | 1103 | ||
1098 | ret = prepare_pages(root, file, pages, num_pages, | 1104 | ret = prepare_pages(root, file, pages, num_pages, |
1099 | pos, first_index, last_index, | 1105 | pos, first_index, last_index, |
1100 | write_bytes); | 1106 | write_bytes); |
1101 | if (ret) | 1107 | if (ret) { |
1108 | btrfs_free_reserved_data_space(root, inode, | ||
1109 | write_bytes); | ||
1102 | goto out; | 1110 | goto out; |
1111 | } | ||
1103 | 1112 | ||
1104 | ret = btrfs_copy_from_user(pos, num_pages, | 1113 | ret = btrfs_copy_from_user(pos, num_pages, |
1105 | write_bytes, pages, buf); | 1114 | write_bytes, pages, buf); |
1106 | if (ret) { | 1115 | if (ret) { |
1116 | btrfs_free_reserved_data_space(root, inode, | ||
1117 | write_bytes); | ||
1107 | btrfs_drop_pages(pages, num_pages); | 1118 | btrfs_drop_pages(pages, num_pages); |
1108 | goto out; | 1119 | goto out; |
1109 | } | 1120 | } |
@@ -1111,8 +1122,11 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1111 | ret = dirty_and_release_pages(NULL, root, file, pages, | 1122 | ret = dirty_and_release_pages(NULL, root, file, pages, |
1112 | num_pages, pos, write_bytes); | 1123 | num_pages, pos, write_bytes); |
1113 | btrfs_drop_pages(pages, num_pages); | 1124 | btrfs_drop_pages(pages, num_pages); |
1114 | if (ret) | 1125 | if (ret) { |
1126 | btrfs_free_reserved_data_space(root, inode, | ||
1127 | write_bytes); | ||
1115 | goto out; | 1128 | goto out; |
1129 | } | ||
1116 | 1130 | ||
1117 | if (will_write) { | 1131 | if (will_write) { |
1118 | btrfs_fdatawrite_range(inode->i_mapping, pos, | 1132 | btrfs_fdatawrite_range(inode->i_mapping, pos, |
@@ -1136,6 +1150,8 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1136 | } | 1150 | } |
1137 | out: | 1151 | out: |
1138 | mutex_unlock(&inode->i_mutex); | 1152 | mutex_unlock(&inode->i_mutex); |
1153 | if (ret) | ||
1154 | err = ret; | ||
1139 | 1155 | ||
1140 | out_nolock: | 1156 | out_nolock: |
1141 | kfree(pages); | 1157 | kfree(pages); |
@@ -1145,6 +1161,20 @@ out_nolock: | |||
1145 | page_cache_release(pinned[1]); | 1161 | page_cache_release(pinned[1]); |
1146 | *ppos = pos; | 1162 | *ppos = pos; |
1147 | 1163 | ||
1164 | /* | ||
1165 | * we want to make sure fsync finds this change | ||
1166 | * but we haven't joined a transaction running right now. | ||
1167 | * | ||
1168 | * Later on, someone is sure to update the inode and get the | ||
1169 | * real transid recorded. | ||
1170 | * | ||
1171 | * We set last_trans now to the fs_info generation + 1, | ||
1172 | * this will either be one more than the running transaction | ||
1173 | * or the generation used for the next transaction if there isn't | ||
1174 | * one running right now. | ||
1175 | */ | ||
1176 | BTRFS_I(inode)->last_trans = root->fs_info->generation + 1; | ||
1177 | |||
1148 | if (num_written > 0 && will_write) { | 1178 | if (num_written > 0 && will_write) { |
1149 | struct btrfs_trans_handle *trans; | 1179 | struct btrfs_trans_handle *trans; |
1150 | 1180 | ||
@@ -1157,8 +1187,11 @@ out_nolock: | |||
1157 | ret = btrfs_log_dentry_safe(trans, root, | 1187 | ret = btrfs_log_dentry_safe(trans, root, |
1158 | file->f_dentry); | 1188 | file->f_dentry); |
1159 | if (ret == 0) { | 1189 | if (ret == 0) { |
1160 | btrfs_sync_log(trans, root); | 1190 | ret = btrfs_sync_log(trans, root); |
1161 | btrfs_end_transaction(trans, root); | 1191 | if (ret == 0) |
1192 | btrfs_end_transaction(trans, root); | ||
1193 | else | ||
1194 | btrfs_commit_transaction(trans, root); | ||
1162 | } else { | 1195 | } else { |
1163 | btrfs_commit_transaction(trans, root); | 1196 | btrfs_commit_transaction(trans, root); |
1164 | } | 1197 | } |
@@ -1175,6 +1208,18 @@ out_nolock: | |||
1175 | 1208 | ||
1176 | int btrfs_release_file(struct inode *inode, struct file *filp) | 1209 | int btrfs_release_file(struct inode *inode, struct file *filp) |
1177 | { | 1210 | { |
1211 | /* | ||
1212 | * ordered_data_close is set by settattr when we are about to truncate | ||
1213 | * a file from a non-zero size to a zero size. This tries to | ||
1214 | * flush down new bytes that may have been written if the | ||
1215 | * application were using truncate to replace a file in place. | ||
1216 | */ | ||
1217 | if (BTRFS_I(inode)->ordered_data_close) { | ||
1218 | BTRFS_I(inode)->ordered_data_close = 0; | ||
1219 | btrfs_add_ordered_operation(NULL, BTRFS_I(inode)->root, inode); | ||
1220 | if (inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) | ||
1221 | filemap_flush(inode->i_mapping); | ||
1222 | } | ||
1178 | if (filp->private_data) | 1223 | if (filp->private_data) |
1179 | btrfs_ioctl_trans_end(filp); | 1224 | btrfs_ioctl_trans_end(filp); |
1180 | return 0; | 1225 | return 0; |
@@ -1222,7 +1267,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1222 | /* | 1267 | /* |
1223 | * ok we haven't committed the transaction yet, lets do a commit | 1268 | * ok we haven't committed the transaction yet, lets do a commit |
1224 | */ | 1269 | */ |
1225 | if (file->private_data) | 1270 | if (file && file->private_data) |
1226 | btrfs_ioctl_trans_end(file); | 1271 | btrfs_ioctl_trans_end(file); |
1227 | 1272 | ||
1228 | trans = btrfs_start_transaction(root, 1); | 1273 | trans = btrfs_start_transaction(root, 1); |
@@ -1231,7 +1276,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1231 | goto out; | 1276 | goto out; |
1232 | } | 1277 | } |
1233 | 1278 | ||
1234 | ret = btrfs_log_dentry_safe(trans, root, file->f_dentry); | 1279 | ret = btrfs_log_dentry_safe(trans, root, dentry); |
1235 | if (ret < 0) | 1280 | if (ret < 0) |
1236 | goto out; | 1281 | goto out; |
1237 | 1282 | ||
@@ -1245,15 +1290,18 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1245 | * file again, but that will end up using the synchronization | 1290 | * file again, but that will end up using the synchronization |
1246 | * inside btrfs_sync_log to keep things safe. | 1291 | * inside btrfs_sync_log to keep things safe. |
1247 | */ | 1292 | */ |
1248 | mutex_unlock(&file->f_dentry->d_inode->i_mutex); | 1293 | mutex_unlock(&dentry->d_inode->i_mutex); |
1249 | 1294 | ||
1250 | if (ret > 0) { | 1295 | if (ret > 0) { |
1251 | ret = btrfs_commit_transaction(trans, root); | 1296 | ret = btrfs_commit_transaction(trans, root); |
1252 | } else { | 1297 | } else { |
1253 | btrfs_sync_log(trans, root); | 1298 | ret = btrfs_sync_log(trans, root); |
1254 | ret = btrfs_end_transaction(trans, root); | 1299 | if (ret == 0) |
1300 | ret = btrfs_end_transaction(trans, root); | ||
1301 | else | ||
1302 | ret = btrfs_commit_transaction(trans, root); | ||
1255 | } | 1303 | } |
1256 | mutex_lock(&file->f_dentry->d_inode->i_mutex); | 1304 | mutex_lock(&dentry->d_inode->i_mutex); |
1257 | out: | 1305 | out: |
1258 | return ret > 0 ? EIO : ret; | 1306 | return ret > 0 ? EIO : ret; |
1259 | } | 1307 | } |