aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c74
1 files changed, 27 insertions, 47 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index e692eea87af6..8aaca5c6af94 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -4141,6 +4141,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
4141 4141
4142 INIT_LIST_HEAD(&extents); 4142 INIT_LIST_HEAD(&extents);
4143 4143
4144 down_write(&BTRFS_I(inode)->dio_sem);
4144 write_lock(&tree->lock); 4145 write_lock(&tree->lock);
4145 test_gen = root->fs_info->last_trans_committed; 4146 test_gen = root->fs_info->last_trans_committed;
4146 4147
@@ -4169,13 +4170,20 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
4169 } 4170 }
4170 4171
4171 list_sort(NULL, &extents, extent_cmp); 4172 list_sort(NULL, &extents, extent_cmp);
4173 btrfs_get_logged_extents(inode, logged_list, start, end);
4172 /* 4174 /*
4173 * Collect any new ordered extents within the range. This is to 4175 * Some ordered extents started by fsync might have completed
4174 * prevent logging file extent items without waiting for the disk 4176 * before we could collect them into the list logged_list, which
4175 * location they point to being written. We do this only to deal 4177 * means they're gone, not in our logged_list nor in the inode's
4176 * with races against concurrent lockless direct IO writes. 4178 * ordered tree. We want the application/user space to know an
4179 * error happened while attempting to persist file data so that
4180 * it can take proper action. If such error happened, we leave
4181 * without writing to the log tree and the fsync must report the
4182 * file data write error and not commit the current transaction.
4177 */ 4183 */
4178 btrfs_get_logged_extents(inode, logged_list, start, end); 4184 ret = btrfs_inode_check_errors(inode);
4185 if (ret)
4186 ctx->io_err = ret;
4179process: 4187process:
4180 while (!list_empty(&extents)) { 4188 while (!list_empty(&extents)) {
4181 em = list_entry(extents.next, struct extent_map, list); 4189 em = list_entry(extents.next, struct extent_map, list);
@@ -4202,6 +4210,7 @@ process:
4202 } 4210 }
4203 WARN_ON(!list_empty(&extents)); 4211 WARN_ON(!list_empty(&extents));
4204 write_unlock(&tree->lock); 4212 write_unlock(&tree->lock);
4213 up_write(&BTRFS_I(inode)->dio_sem);
4205 4214
4206 btrfs_release_path(path); 4215 btrfs_release_path(path);
4207 return ret; 4216 return ret;
@@ -4623,23 +4632,6 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
4623 mutex_lock(&BTRFS_I(inode)->log_mutex); 4632 mutex_lock(&BTRFS_I(inode)->log_mutex);
4624 4633
4625 /* 4634 /*
4626 * Collect ordered extents only if we are logging data. This is to
4627 * ensure a subsequent request to log this inode in LOG_INODE_ALL mode
4628 * will process the ordered extents if they still exists at the time,
4629 * because when we collect them we test and set for the flag
4630 * BTRFS_ORDERED_LOGGED to prevent multiple log requests to process the
4631 * same ordered extents. The consequence for the LOG_INODE_ALL log mode
4632 * not processing the ordered extents is that we end up logging the
4633 * corresponding file extent items, based on the extent maps in the
4634 * inode's extent_map_tree's modified_list, without logging the
4635 * respective checksums (since the may still be only attached to the
4636 * ordered extents and have not been inserted in the csum tree by
4637 * btrfs_finish_ordered_io() yet).
4638 */
4639 if (inode_only == LOG_INODE_ALL)
4640 btrfs_get_logged_extents(inode, &logged_list, start, end);
4641
4642 /*
4643 * a brute force approach to making sure we get the most uptodate 4635 * a brute force approach to making sure we get the most uptodate
4644 * copies of everything. 4636 * copies of everything.
4645 */ 4637 */
@@ -4846,21 +4838,6 @@ log_extents:
4846 goto out_unlock; 4838 goto out_unlock;
4847 } 4839 }
4848 if (fast_search) { 4840 if (fast_search) {
4849 /*
4850 * Some ordered extents started by fsync might have completed
4851 * before we collected the ordered extents in logged_list, which
4852 * means they're gone, not in our logged_list nor in the inode's
4853 * ordered tree. We want the application/user space to know an
4854 * error happened while attempting to persist file data so that
4855 * it can take proper action. If such error happened, we leave
4856 * without writing to the log tree and the fsync must report the
4857 * file data write error and not commit the current transaction.
4858 */
4859 err = btrfs_inode_check_errors(inode);
4860 if (err) {
4861 ctx->io_err = err;
4862 goto out_unlock;
4863 }
4864 ret = btrfs_log_changed_extents(trans, root, inode, dst_path, 4841 ret = btrfs_log_changed_extents(trans, root, inode, dst_path,
4865 &logged_list, ctx, start, end); 4842 &logged_list, ctx, start, end);
4866 if (ret) { 4843 if (ret) {
@@ -5158,7 +5135,7 @@ process_leaf:
5158 } 5135 }
5159 5136
5160 ctx->log_new_dentries = false; 5137 ctx->log_new_dentries = false;
5161 if (type == BTRFS_FT_DIR) 5138 if (type == BTRFS_FT_DIR || type == BTRFS_FT_SYMLINK)
5162 log_mode = LOG_INODE_ALL; 5139 log_mode = LOG_INODE_ALL;
5163 btrfs_release_path(path); 5140 btrfs_release_path(path);
5164 ret = btrfs_log_inode(trans, root, di_inode, 5141 ret = btrfs_log_inode(trans, root, di_inode,
@@ -5278,11 +5255,16 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans,
5278 if (IS_ERR(dir_inode)) 5255 if (IS_ERR(dir_inode))
5279 continue; 5256 continue;
5280 5257
5258 if (ctx)
5259 ctx->log_new_dentries = false;
5281 ret = btrfs_log_inode(trans, root, dir_inode, 5260 ret = btrfs_log_inode(trans, root, dir_inode,
5282 LOG_INODE_ALL, 0, LLONG_MAX, ctx); 5261 LOG_INODE_ALL, 0, LLONG_MAX, ctx);
5283 if (!ret && 5262 if (!ret &&
5284 btrfs_must_commit_transaction(trans, dir_inode)) 5263 btrfs_must_commit_transaction(trans, dir_inode))
5285 ret = 1; 5264 ret = 1;
5265 if (!ret && ctx && ctx->log_new_dentries)
5266 ret = log_new_dir_dentries(trans, root,
5267 dir_inode, ctx);
5286 iput(dir_inode); 5268 iput(dir_inode);
5287 if (ret) 5269 if (ret)
5288 goto out; 5270 goto out;
@@ -5519,7 +5501,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
5519 5501
5520 ret = walk_log_tree(trans, log_root_tree, &wc); 5502 ret = walk_log_tree(trans, log_root_tree, &wc);
5521 if (ret) { 5503 if (ret) {
5522 btrfs_std_error(fs_info, ret, "Failed to pin buffers while " 5504 btrfs_handle_fs_error(fs_info, ret, "Failed to pin buffers while "
5523 "recovering log root tree."); 5505 "recovering log root tree.");
5524 goto error; 5506 goto error;
5525 } 5507 }
@@ -5533,7 +5515,7 @@ again:
5533 ret = btrfs_search_slot(NULL, log_root_tree, &key, path, 0, 0); 5515 ret = btrfs_search_slot(NULL, log_root_tree, &key, path, 0, 0);
5534 5516
5535 if (ret < 0) { 5517 if (ret < 0) {
5536 btrfs_std_error(fs_info, ret, 5518 btrfs_handle_fs_error(fs_info, ret,
5537 "Couldn't find tree log root."); 5519 "Couldn't find tree log root.");
5538 goto error; 5520 goto error;
5539 } 5521 }
@@ -5551,7 +5533,7 @@ again:
5551 log = btrfs_read_fs_root(log_root_tree, &found_key); 5533 log = btrfs_read_fs_root(log_root_tree, &found_key);
5552 if (IS_ERR(log)) { 5534 if (IS_ERR(log)) {
5553 ret = PTR_ERR(log); 5535 ret = PTR_ERR(log);
5554 btrfs_std_error(fs_info, ret, 5536 btrfs_handle_fs_error(fs_info, ret,
5555 "Couldn't read tree log root."); 5537 "Couldn't read tree log root.");
5556 goto error; 5538 goto error;
5557 } 5539 }
@@ -5566,7 +5548,7 @@ again:
5566 free_extent_buffer(log->node); 5548 free_extent_buffer(log->node);
5567 free_extent_buffer(log->commit_root); 5549 free_extent_buffer(log->commit_root);
5568 kfree(log); 5550 kfree(log);
5569 btrfs_std_error(fs_info, ret, "Couldn't read target root " 5551 btrfs_handle_fs_error(fs_info, ret, "Couldn't read target root "
5570 "for tree log recovery."); 5552 "for tree log recovery.");
5571 goto error; 5553 goto error;
5572 } 5554 }
@@ -5652,11 +5634,9 @@ void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans,
5652 * into the file. When the file is logged we check it and 5634 * into the file. When the file is logged we check it and
5653 * don't log the parents if the file is fully on disk. 5635 * don't log the parents if the file is fully on disk.
5654 */ 5636 */
5655 if (S_ISREG(inode->i_mode)) { 5637 mutex_lock(&BTRFS_I(inode)->log_mutex);
5656 mutex_lock(&BTRFS_I(inode)->log_mutex); 5638 BTRFS_I(inode)->last_unlink_trans = trans->transid;
5657 BTRFS_I(inode)->last_unlink_trans = trans->transid; 5639 mutex_unlock(&BTRFS_I(inode)->log_mutex);
5658 mutex_unlock(&BTRFS_I(inode)->log_mutex);
5659 }
5660 5640
5661 /* 5641 /*
5662 * if this directory was already logged any new 5642 * if this directory was already logged any new