btrfs: change error handling for btrfs_delete_*_in_log
Currently we will abort the transaction if we get a random error (like -EIO) while trying to remove the directory entries from the root log during rename. However since these are simply log tree related errors, we can mark the trans as needing a full commit. Then if the error was truly catastrophic we'll hit it during the normal commit and abort as appropriate. Reviewed-by: Nikolay Borisov <nborisov@suse.com> Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
committed by
David Sterba
parent
ba51e2a11e
commit
9a35fc9542
@@ -4120,19 +4120,9 @@ skip_backref:
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len, inode,
|
btrfs_del_inode_ref_in_log(trans, root, name, name_len, inode,
|
||||||
dir_ino);
|
dir_ino);
|
||||||
if (ret != 0 && ret != -ENOENT) {
|
btrfs_del_dir_entries_in_log(trans, root, name, name_len, dir, index);
|
||||||
btrfs_abort_transaction(trans, ret);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = btrfs_del_dir_entries_in_log(trans, root, name, name_len, dir,
|
|
||||||
index);
|
|
||||||
if (ret == -ENOENT)
|
|
||||||
ret = 0;
|
|
||||||
else if (ret)
|
|
||||||
btrfs_abort_transaction(trans, ret);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have a pending delayed iput we could end up with the final iput
|
* If we have a pending delayed iput we could end up with the final iput
|
||||||
|
|||||||
@@ -3518,10 +3518,10 @@ static bool inode_logged(struct btrfs_trans_handle *trans,
|
|||||||
* This optimizations allows us to avoid relogging the entire inode
|
* This optimizations allows us to avoid relogging the entire inode
|
||||||
* or the entire directory.
|
* or the entire directory.
|
||||||
*/
|
*/
|
||||||
int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
|
void btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_root *root,
|
struct btrfs_root *root,
|
||||||
const char *name, int name_len,
|
const char *name, int name_len,
|
||||||
struct btrfs_inode *dir, u64 index)
|
struct btrfs_inode *dir, u64 index)
|
||||||
{
|
{
|
||||||
struct btrfs_root *log;
|
struct btrfs_root *log;
|
||||||
struct btrfs_dir_item *di;
|
struct btrfs_dir_item *di;
|
||||||
@@ -3531,11 +3531,11 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
|
|||||||
u64 dir_ino = btrfs_ino(dir);
|
u64 dir_ino = btrfs_ino(dir);
|
||||||
|
|
||||||
if (!inode_logged(trans, dir))
|
if (!inode_logged(trans, dir))
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
ret = join_running_log_trans(root);
|
ret = join_running_log_trans(root);
|
||||||
if (ret)
|
if (ret)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
mutex_lock(&dir->log_mutex);
|
mutex_lock(&dir->log_mutex);
|
||||||
|
|
||||||
@@ -3583,48 +3583,36 @@ fail:
|
|||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
out_unlock:
|
out_unlock:
|
||||||
mutex_unlock(&dir->log_mutex);
|
mutex_unlock(&dir->log_mutex);
|
||||||
if (err == -ENOSPC) {
|
if (err < 0)
|
||||||
btrfs_set_log_full_commit(trans);
|
btrfs_set_log_full_commit(trans);
|
||||||
err = 0;
|
|
||||||
} else if (err < 0) {
|
|
||||||
btrfs_abort_transaction(trans, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
btrfs_end_log_trans(root);
|
btrfs_end_log_trans(root);
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* see comments for btrfs_del_dir_entries_in_log */
|
/* see comments for btrfs_del_dir_entries_in_log */
|
||||||
int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans,
|
void btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_root *root,
|
struct btrfs_root *root,
|
||||||
const char *name, int name_len,
|
const char *name, int name_len,
|
||||||
struct btrfs_inode *inode, u64 dirid)
|
struct btrfs_inode *inode, u64 dirid)
|
||||||
{
|
{
|
||||||
struct btrfs_root *log;
|
struct btrfs_root *log;
|
||||||
u64 index;
|
u64 index;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!inode_logged(trans, inode))
|
if (!inode_logged(trans, inode))
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
ret = join_running_log_trans(root);
|
ret = join_running_log_trans(root);
|
||||||
if (ret)
|
if (ret)
|
||||||
return 0;
|
return;
|
||||||
log = root->log_root;
|
log = root->log_root;
|
||||||
mutex_lock(&inode->log_mutex);
|
mutex_lock(&inode->log_mutex);
|
||||||
|
|
||||||
ret = btrfs_del_inode_ref(trans, log, name, name_len, btrfs_ino(inode),
|
ret = btrfs_del_inode_ref(trans, log, name, name_len, btrfs_ino(inode),
|
||||||
dirid, &index);
|
dirid, &index);
|
||||||
mutex_unlock(&inode->log_mutex);
|
mutex_unlock(&inode->log_mutex);
|
||||||
if (ret == -ENOSPC) {
|
if (ret < 0 && ret != -ENOENT)
|
||||||
btrfs_set_log_full_commit(trans);
|
btrfs_set_log_full_commit(trans);
|
||||||
ret = 0;
|
|
||||||
} else if (ret < 0 && ret != -ENOENT)
|
|
||||||
btrfs_abort_transaction(trans, ret);
|
|
||||||
btrfs_end_log_trans(root);
|
btrfs_end_log_trans(root);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -70,14 +70,14 @@ int btrfs_recover_log_trees(struct btrfs_root *tree_root);
|
|||||||
int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans,
|
int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans,
|
||||||
struct dentry *dentry,
|
struct dentry *dentry,
|
||||||
struct btrfs_log_ctx *ctx);
|
struct btrfs_log_ctx *ctx);
|
||||||
int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
|
void btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_root *root,
|
struct btrfs_root *root,
|
||||||
const char *name, int name_len,
|
const char *name, int name_len,
|
||||||
struct btrfs_inode *dir, u64 index);
|
struct btrfs_inode *dir, u64 index);
|
||||||
int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans,
|
void btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_root *root,
|
struct btrfs_root *root,
|
||||||
const char *name, int name_len,
|
const char *name, int name_len,
|
||||||
struct btrfs_inode *inode, u64 dirid);
|
struct btrfs_inode *inode, u64 dirid);
|
||||||
void btrfs_end_log_trans(struct btrfs_root *root);
|
void btrfs_end_log_trans(struct btrfs_root *root);
|
||||||
void btrfs_pin_log_trans(struct btrfs_root *root);
|
void btrfs_pin_log_trans(struct btrfs_root *root);
|
||||||
void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans,
|
void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans,
|
||||||
|
|||||||
Reference in New Issue
Block a user