afs: Better abort and net error handling
If we receive a network error, a remote abort or a protocol error whilst we're still transmitting data, make sure we return an appropriate error to the caller rather than ESHUTDOWN or ECONNABORTED. Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
parent
1157f153f3
commit
70af0e3bd6
|
@ -340,6 +340,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
|
|||
struct rxrpc_call *rxcall;
|
||||
struct msghdr msg;
|
||||
struct kvec iov[1];
|
||||
size_t offset;
|
||||
u32 abort_code;
|
||||
int ret;
|
||||
|
||||
_enter("%x,{%d},", addr->s_addr, ntohs(call->port));
|
||||
|
@ -388,9 +390,11 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
|
|||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = (call->send_pages ? MSG_MORE : 0);
|
||||
|
||||
/* have to change the state *before* sending the last packet as RxRPC
|
||||
* might give us the reply before it returns from sending the
|
||||
* request */
|
||||
/* We have to change the state *before* sending the last packet as
|
||||
* rxrpc might give us the reply before it returns from sending the
|
||||
* request. Further, if the send fails, we may already have been given
|
||||
* a notification and may have collected it.
|
||||
*/
|
||||
if (!call->send_pages)
|
||||
call->state = AFS_CALL_AWAIT_REPLY;
|
||||
ret = rxrpc_kernel_send_data(afs_socket, rxcall,
|
||||
|
@ -412,7 +416,17 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
|
|||
return afs_wait_for_call_to_complete(call);
|
||||
|
||||
error_do_abort:
|
||||
rxrpc_kernel_abort_call(afs_socket, rxcall, RX_USER_ABORT, -ret, "KSD");
|
||||
call->state = AFS_CALL_COMPLETE;
|
||||
if (ret != -ECONNABORTED) {
|
||||
rxrpc_kernel_abort_call(afs_socket, rxcall, RX_USER_ABORT,
|
||||
-ret, "KSD");
|
||||
} else {
|
||||
abort_code = 0;
|
||||
offset = 0;
|
||||
rxrpc_kernel_recv_data(afs_socket, rxcall, NULL, 0, &offset,
|
||||
false, &abort_code);
|
||||
ret = call->type->abort_to_error(abort_code);
|
||||
}
|
||||
error_kill_call:
|
||||
afs_put_call(call);
|
||||
_leave(" = %d", ret);
|
||||
|
@ -459,16 +473,18 @@ static void afs_deliver_to_call(struct afs_call *call)
|
|||
case -EINPROGRESS:
|
||||
case -EAGAIN:
|
||||
goto out;
|
||||
case -ECONNABORTED:
|
||||
goto call_complete;
|
||||
case -ENOTCONN:
|
||||
abort_code = RX_CALL_DEAD;
|
||||
rxrpc_kernel_abort_call(afs_socket, call->rxcall,
|
||||
abort_code, -ret, "KNC");
|
||||
goto do_abort;
|
||||
goto save_error;
|
||||
case -ENOTSUPP:
|
||||
abort_code = RXGEN_OPCODE;
|
||||
rxrpc_kernel_abort_call(afs_socket, call->rxcall,
|
||||
abort_code, -ret, "KIV");
|
||||
goto do_abort;
|
||||
goto save_error;
|
||||
case -ENODATA:
|
||||
case -EBADMSG:
|
||||
case -EMSGSIZE:
|
||||
|
@ -478,7 +494,7 @@ static void afs_deliver_to_call(struct afs_call *call)
|
|||
abort_code = RXGEN_SS_UNMARSHAL;
|
||||
rxrpc_kernel_abort_call(afs_socket, call->rxcall,
|
||||
abort_code, EBADMSG, "KUM");
|
||||
goto do_abort;
|
||||
goto save_error;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -489,8 +505,9 @@ out:
|
|||
_leave("");
|
||||
return;
|
||||
|
||||
do_abort:
|
||||
save_error:
|
||||
call->error = ret;
|
||||
call_complete:
|
||||
call->state = AFS_CALL_COMPLETE;
|
||||
goto done;
|
||||
}
|
||||
|
@ -538,6 +555,8 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
|
|||
_debug("call incomplete");
|
||||
rxrpc_kernel_abort_call(afs_socket, call->rxcall,
|
||||
RX_CALL_DEAD, -ret, abort_why);
|
||||
} else if (call->error < 0) {
|
||||
ret = call->error;
|
||||
}
|
||||
|
||||
_debug("call complete");
|
||||
|
|
Loading…
Reference in New Issue