rxrpc: Call rxrpc_release_call() on error in rxrpc_new_client_call()
Call rxrpc_release_call() on getting an error in rxrpc_new_client_call() rather than trying to do the cleanup ourselves. This isn't a problem, provided we set RXRPC_CALL_HAS_USERID only if we actually add the call to the calls tree as cleanup code fragments that would otherwise cause problems are conditional. Without this, we miss some of the cleanup. Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
parent
66d58af7f4
commit
357f5ef646
1 changed files with 12 additions and 24 deletions
|
@ -226,9 +226,6 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
|
|||
(const void *)user_call_ID);
|
||||
|
||||
/* Publish the call, even though it is incompletely set up as yet */
|
||||
call->user_call_ID = user_call_ID;
|
||||
__set_bit(RXRPC_CALL_HAS_USERID, &call->flags);
|
||||
|
||||
write_lock(&rx->call_lock);
|
||||
|
||||
pp = &rx->calls.rb_node;
|
||||
|
@ -242,10 +239,12 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
|
|||
else if (user_call_ID > xcall->user_call_ID)
|
||||
pp = &(*pp)->rb_right;
|
||||
else
|
||||
goto found_user_ID_now_present;
|
||||
goto error_dup_user_ID;
|
||||
}
|
||||
|
||||
rcu_assign_pointer(call->socket, rx);
|
||||
call->user_call_ID = user_call_ID;
|
||||
__set_bit(RXRPC_CALL_HAS_USERID, &call->flags);
|
||||
rxrpc_get_call(call, rxrpc_call_got_userid);
|
||||
rb_link_node(&call->sock_node, parent, pp);
|
||||
rb_insert_color(&call->sock_node, &rx->calls);
|
||||
|
@ -276,33 +275,22 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
|
|||
_leave(" = %p [new]", call);
|
||||
return call;
|
||||
|
||||
error:
|
||||
write_lock(&rx->call_lock);
|
||||
rb_erase(&call->sock_node, &rx->calls);
|
||||
write_unlock(&rx->call_lock);
|
||||
rxrpc_put_call(call, rxrpc_call_put_userid);
|
||||
|
||||
write_lock(&rxrpc_call_lock);
|
||||
list_del_init(&call->link);
|
||||
write_unlock(&rxrpc_call_lock);
|
||||
|
||||
error_out:
|
||||
__rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
|
||||
RX_CALL_DEAD, ret);
|
||||
set_bit(RXRPC_CALL_RELEASED, &call->flags);
|
||||
rxrpc_put_call(call, rxrpc_call_put);
|
||||
_leave(" = %d", ret);
|
||||
return ERR_PTR(ret);
|
||||
|
||||
/* We unexpectedly found the user ID in the list after taking
|
||||
* the call_lock. This shouldn't happen unless the user races
|
||||
* with itself and tries to add the same user ID twice at the
|
||||
* same time in different threads.
|
||||
*/
|
||||
found_user_ID_now_present:
|
||||
error_dup_user_ID:
|
||||
write_unlock(&rx->call_lock);
|
||||
ret = -EEXIST;
|
||||
goto error_out;
|
||||
|
||||
error:
|
||||
__rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
|
||||
RX_CALL_DEAD, ret);
|
||||
rxrpc_release_call(rx, call);
|
||||
rxrpc_put_call(call, rxrpc_call_put);
|
||||
_leave(" = %d", ret);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue