rxrpc: Allow failed client calls to be retried
Allow a client call that failed on network error to be retried, provided that the Tx queue still holds DATA packet 1. This allows an operation to be submitted to another server or another address for the same server without having to repackage and re-encrypt the data so far processed. Two new functions are provided: (1) rxrpc_kernel_check_call() - This is used to find out the completion state of a call to guess whether it can be retried and whether it should be retried. (2) rxrpc_kernel_retry_call() - Disconnect the call from its current connection, reset the state and submit it as a new client call to a new address. The new address need not match the previous address. A call may be retried even if all the data hasn't been loaded into it yet; a partially constructed will be retained at the same point it was at when an error condition was detected. msg_data_left() can be used to find out how much data was packaged before the error occurred. Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
@@ -555,7 +555,10 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
|
||||
trace_rxrpc_client(conn, channel, rxrpc_client_chan_activate);
|
||||
|
||||
write_lock_bh(&call->state_lock);
|
||||
call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
|
||||
if (!test_bit(RXRPC_CALL_TX_LASTQ, &call->flags))
|
||||
call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
|
||||
else
|
||||
call->state = RXRPC_CALL_CLIENT_AWAIT_REPLY;
|
||||
write_unlock_bh(&call->state_lock);
|
||||
|
||||
rxrpc_see_call(call);
|
||||
@@ -688,15 +691,23 @@ int rxrpc_connect_call(struct rxrpc_call *call,
|
||||
|
||||
ret = rxrpc_get_client_conn(call, cp, srx, gfp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
rxrpc_animate_client_conn(rxnet, call->conn);
|
||||
rxrpc_activate_channels(call->conn);
|
||||
|
||||
ret = rxrpc_wait_for_channel(call, gfp);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
rxrpc_disconnect_client_call(call);
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_bh(&call->conn->params.peer->lock);
|
||||
hlist_add_head(&call->error_link,
|
||||
&call->conn->params.peer->error_targets);
|
||||
spin_unlock_bh(&call->conn->params.peer->lock);
|
||||
|
||||
out:
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user