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 rxrpc_call *rxcall;
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
struct kvec iov[1];
|
struct kvec iov[1];
|
||||||
|
size_t offset;
|
||||||
|
u32 abort_code;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
_enter("%x,{%d},", addr->s_addr, ntohs(call->port));
|
_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_controllen = 0;
|
||||||
msg.msg_flags = (call->send_pages ? MSG_MORE : 0);
|
msg.msg_flags = (call->send_pages ? MSG_MORE : 0);
|
||||||
|
|
||||||
/* have to change the state *before* sending the last packet as RxRPC
|
/* We have to change the state *before* sending the last packet as
|
||||||
* might give us the reply before it returns from sending the
|
* rxrpc might give us the reply before it returns from sending the
|
||||||
* request */
|
* request. Further, if the send fails, we may already have been given
|
||||||
|
* a notification and may have collected it.
|
||||||
|
*/
|
||||||
if (!call->send_pages)
|
if (!call->send_pages)
|
||||||
call->state = AFS_CALL_AWAIT_REPLY;
|
call->state = AFS_CALL_AWAIT_REPLY;
|
||||||
ret = rxrpc_kernel_send_data(afs_socket, rxcall,
|
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);
|
return afs_wait_for_call_to_complete(call);
|
||||||
|
|
||||||
error_do_abort:
|
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:
|
error_kill_call:
|
||||||
afs_put_call(call);
|
afs_put_call(call);
|
||||||
_leave(" = %d", ret);
|
_leave(" = %d", ret);
|
||||||
|
@ -459,16 +473,18 @@ static void afs_deliver_to_call(struct afs_call *call)
|
||||||
case -EINPROGRESS:
|
case -EINPROGRESS:
|
||||||
case -EAGAIN:
|
case -EAGAIN:
|
||||||
goto out;
|
goto out;
|
||||||
|
case -ECONNABORTED:
|
||||||
|
goto call_complete;
|
||||||
case -ENOTCONN:
|
case -ENOTCONN:
|
||||||
abort_code = RX_CALL_DEAD;
|
abort_code = RX_CALL_DEAD;
|
||||||
rxrpc_kernel_abort_call(afs_socket, call->rxcall,
|
rxrpc_kernel_abort_call(afs_socket, call->rxcall,
|
||||||
abort_code, -ret, "KNC");
|
abort_code, -ret, "KNC");
|
||||||
goto do_abort;
|
goto save_error;
|
||||||
case -ENOTSUPP:
|
case -ENOTSUPP:
|
||||||
abort_code = RXGEN_OPCODE;
|
abort_code = RXGEN_OPCODE;
|
||||||
rxrpc_kernel_abort_call(afs_socket, call->rxcall,
|
rxrpc_kernel_abort_call(afs_socket, call->rxcall,
|
||||||
abort_code, -ret, "KIV");
|
abort_code, -ret, "KIV");
|
||||||
goto do_abort;
|
goto save_error;
|
||||||
case -ENODATA:
|
case -ENODATA:
|
||||||
case -EBADMSG:
|
case -EBADMSG:
|
||||||
case -EMSGSIZE:
|
case -EMSGSIZE:
|
||||||
|
@ -478,7 +494,7 @@ static void afs_deliver_to_call(struct afs_call *call)
|
||||||
abort_code = RXGEN_SS_UNMARSHAL;
|
abort_code = RXGEN_SS_UNMARSHAL;
|
||||||
rxrpc_kernel_abort_call(afs_socket, call->rxcall,
|
rxrpc_kernel_abort_call(afs_socket, call->rxcall,
|
||||||
abort_code, EBADMSG, "KUM");
|
abort_code, EBADMSG, "KUM");
|
||||||
goto do_abort;
|
goto save_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,8 +505,9 @@ static void afs_deliver_to_call(struct afs_call *call)
|
||||||
_leave("");
|
_leave("");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
do_abort:
|
save_error:
|
||||||
call->error = ret;
|
call->error = ret;
|
||||||
|
call_complete:
|
||||||
call->state = AFS_CALL_COMPLETE;
|
call->state = AFS_CALL_COMPLETE;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -538,6 +555,8 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
|
||||||
_debug("call incomplete");
|
_debug("call incomplete");
|
||||||
rxrpc_kernel_abort_call(afs_socket, call->rxcall,
|
rxrpc_kernel_abort_call(afs_socket, call->rxcall,
|
||||||
RX_CALL_DEAD, -ret, abort_why);
|
RX_CALL_DEAD, -ret, abort_why);
|
||||||
|
} else if (call->error < 0) {
|
||||||
|
ret = call->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
_debug("call complete");
|
_debug("call complete");
|
||||||
|
|
Loading…
Reference in New Issue