Commit 9a35fc95 authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba
Browse files

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: default avatarNikolay Borisov <nborisov@suse.com>
Reviewed-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent ba51e2a1
Loading
Loading
Loading
Loading
+3 −13
Original line number Diff line number Diff line
@@ -4120,19 +4120,9 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans,
		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);
	if (ret != 0 && ret != -ENOENT) {
		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);
	btrfs_del_dir_entries_in_log(trans, root, name, name_len, dir, index);

	/*
	 * If we have a pending delayed iput we could end up with the final iput
+14 −26
Original line number Diff line number Diff line
@@ -3518,7 +3518,7 @@ static bool inode_logged(struct btrfs_trans_handle *trans,
 * This optimizations allows us to avoid relogging the entire inode
 * 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,
				  const char *name, int name_len,
				  struct btrfs_inode *dir, u64 index)
@@ -3531,11 +3531,11 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
	u64 dir_ino = btrfs_ino(dir);

	if (!inode_logged(trans, dir))
		return 0;
		return;

	ret = join_running_log_trans(root);
	if (ret)
		return 0;
		return;

	mutex_lock(&dir->log_mutex);

@@ -3583,20 +3583,13 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
	btrfs_free_path(path);
out_unlock:
	mutex_unlock(&dir->log_mutex);
	if (err == -ENOSPC) {
	if (err < 0)
		btrfs_set_log_full_commit(trans);
		err = 0;
	} else if (err < 0) {
		btrfs_abort_transaction(trans, err);
	}

	btrfs_end_log_trans(root);

	return err;
}

/* 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,
				const char *name, int name_len,
				struct btrfs_inode *inode, u64 dirid)
@@ -3606,25 +3599,20 @@ int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans,
	int ret;

	if (!inode_logged(trans, inode))
		return 0;
		return;

	ret = join_running_log_trans(root);
	if (ret)
		return 0;
		return;
	log = root->log_root;
	mutex_lock(&inode->log_mutex);

	ret = btrfs_del_inode_ref(trans, log, name, name_len, btrfs_ino(inode),
				  dirid, &index);
	mutex_unlock(&inode->log_mutex);
	if (ret == -ENOSPC) {
	if (ret < 0 && ret != -ENOENT)
		btrfs_set_log_full_commit(trans);
		ret = 0;
	} else if (ret < 0 && ret != -ENOENT)
		btrfs_abort_transaction(trans, ret);
	btrfs_end_log_trans(root);

	return ret;
}

/*
+8 −8
Original line number Diff line number Diff line
@@ -70,11 +70,11 @@ int btrfs_recover_log_trees(struct btrfs_root *tree_root);
int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans,
			  struct dentry *dentry,
			  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,
				  const char *name, int name_len,
				  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,
				const char *name, int name_len,
				struct btrfs_inode *inode, u64 dirid);