Commit aa453bec authored by David Howells's avatar David Howells
Browse files

afs: Simplify error handling



Simplify error handling a bit by moving it from the afs_addr_cursor struct
to the afs_operation and afs_vl_cursor structs and using the error
prioritisation function for accumulating errors from multiple sources (AFS
tries to rotate between multiple fileservers, some of which may be
inaccessible or in some state of offlinedness).

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
parent 6f2ff7e8
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -386,26 +386,24 @@ bool afs_iterate_addresses(struct afs_addr_cursor *ac)
selected:
	ac->index = index;
	set_bit(index, &ac->tried);
	ac->responded = false;
	ac->call_responded = false;
	return true;
}

/*
 * Release an address list cursor.
 */
int afs_end_cursor(struct afs_addr_cursor *ac)
void afs_end_cursor(struct afs_addr_cursor *ac)
{
	struct afs_addr_list *alist;

	alist = ac->alist;
	if (alist) {
		if (ac->responded &&
		if (ac->call_responded &&
		    ac->index != alist->preferred &&
		    test_bit(ac->alist->preferred, &ac->tried))
			WRITE_ONCE(alist->preferred, ac->index);
		afs_put_addrlist(alist);
		ac->alist = NULL;
	}

	return ac->error;
}
+8 −6
Original line number Diff line number Diff line
@@ -693,8 +693,9 @@ static void afs_do_lookup_success(struct afs_operation *op)
			vp = &op->file[0];
			abort_code = vp->scb.status.abort_code;
			if (abort_code != 0) {
				op->ac.abort_code = abort_code;
				op->error = afs_abort_to_error(abort_code);
				op->call_abort_code = abort_code;
				afs_op_set_error(op, afs_abort_to_error(abort_code));
				op->cumul_error.abort_code = abort_code;
			}
			break;

@@ -846,13 +847,14 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
	_debug("nr_files %u", op->nr_files);

	/* Need space for examining all the selected files */
	op->error = -ENOMEM;
	if (op->nr_files > 2) {
		op->more_files = kvcalloc(op->nr_files - 2,
					  sizeof(struct afs_vnode_param),
					  GFP_KERNEL);
		if (!op->more_files)
		if (!op->more_files) {
			afs_op_nomem(op);
			goto out_op;
		}

		for (i = 2; i < op->nr_files; i++) {
			vp = &op->more_files[i - 2];
@@ -1255,7 +1257,7 @@ void afs_check_for_remote_deletion(struct afs_operation *op)
{
	struct afs_vnode *vnode = op->file[0].vnode;

	switch (op->ac.abort_code) {
	switch (afs_op_abort_code(op)) {
	case VNOVNODE:
		set_bit(AFS_VNODE_DELETED, &vnode->flags);
		afs_break_callback(vnode, afs_cb_break_for_deleted);
@@ -1280,7 +1282,7 @@ static void afs_vnode_new_inode(struct afs_operation *op)
		/* ENOMEM or EINTR at a really inconvenient time - just abandon
		 * the new directory on the server.
		 */
		op->error = PTR_ERR(inode);
		afs_op_accumulate_error(op, PTR_ERR(inode), 0);
		return;
	}

+1 −1
Original line number Diff line number Diff line
@@ -218,7 +218,7 @@ static int afs_do_silly_unlink(struct afs_vnode *dvnode, struct afs_vnode *vnode
	/* If there was a conflict with a third party, check the status of the
	 * unlinked vnode.
	 */
	if (op->error == 0 && (op->flags & AFS_OPERATION_DIR_CONFLICT)) {
	if (op->cumul_error.error == 0 && (op->flags & AFS_OPERATION_DIR_CONFLICT)) {
		op->file[1].update_ctime = false;
		op->fetch_status.which = 1;
		op->ops = &afs_fetch_status_operation;
+0 −3
Original line number Diff line number Diff line
@@ -245,10 +245,7 @@ static void afs_fetch_data_notify(struct afs_operation *op)
	struct netfs_io_subrequest *subreq = req->subreq;
	int error = afs_op_error(op);

	if (error == -ECONNABORTED)
		error = afs_abort_to_error(op->ac.abort_code);
	req->error = error;

	if (subreq) {
		__set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags);
		netfs_subreq_terminated(subreq, error ?: req->actual_len, false);
+12 −12
Original line number Diff line number Diff line
@@ -169,9 +169,6 @@ static void afs_end_vnode_operation(struct afs_operation *op)
	}

	afs_drop_io_locks(op);

	if (op->error == -ECONNABORTED)
		op->error = afs_abort_to_error(op->ac.abort_code);
}

/*
@@ -182,6 +179,8 @@ void afs_wait_for_operation(struct afs_operation *op)
	_enter("");

	while (afs_select_fileserver(op)) {
		op->call_error = 0;
		op->call_abort_code = 0;
		op->cb_s_break = op->server->cb_s_break;
		if (test_bit(AFS_SERVER_FL_IS_YFS, &op->server->flags) &&
		    op->ops->issue_yfs_rpc)
@@ -189,28 +188,29 @@ void afs_wait_for_operation(struct afs_operation *op)
		else if (op->ops->issue_afs_rpc)
			op->ops->issue_afs_rpc(op);
		else
			op->ac.error = -ENOTSUPP;
			op->call_error = -ENOTSUPP;

		if (op->call) {
			afs_wait_for_call_to_complete(op->call, &op->ac);
			op->error = op->ac.error;
			op->call_abort_code = op->call->abort_code;
			op->call_error = op->call->error;
			op->call_responded = op->call->responded;
			op->ac.call_responded = true;
			WRITE_ONCE(op->ac.alist->addrs[op->ac.index].last_error,
				   op->call_error);
			afs_put_call(op->call);
		}
	}

	switch (op->error) {
	case 0:
	if (!afs_op_error(op)) {
		_debug("success");
		op->ops->success(op);
		break;
	case -ECONNABORTED:
	} else if (op->cumul_error.aborted) {
		if (op->ops->aborted)
			op->ops->aborted(op);
		fallthrough;
	default:
	} else {
		if (op->ops->failed)
			op->ops->failed(op);
		break;
	}

	afs_end_vnode_operation(op);
Loading