|
@@ -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");
|