Commit 57af281e authored by David Howells's avatar David Howells

rxrpc: Tidy up abort generation infrastructure

Tidy up the abort generation infrastructure in the following ways:

 (1) Create an enum and string mapping table to list the reasons an abort
     might be generated in tracing.

 (2) Replace the 3-char string with the values from (1) in the places that
     use that to log the abort source.  This gets rid of a memcpy() in the
     tracepoint.

 (3) Subsume the rxrpc_rx_eproto tracepoint with the rxrpc_abort tracepoint
     and use values from (1) to indicate the trace reason.

 (4) Always make a call to an abort function at the point of the abort
     rather than stashing the values into variables and using goto to get
     to a place where it reported.  The C optimiser will collapse the calls
     together as appropriate.  The abort functions return a value that can
     be returned directly if appropriate.

Note that this extends into afs also at the points where that generates an
abort.  To aid with this, the afs sources need to #define
RXRPC_TRACE_ONLY_DEFINE_ENUMS before including the rxrpc tracing header
because they don't have access to the rxrpc internal structures that some
of the tracepoints make use of.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
parent a00ce28b
......@@ -13,6 +13,8 @@
#include "internal.h"
#include "afs_cm.h"
#include "protocol_yfs.h"
#define RXRPC_TRACE_ONLY_DEFINE_ENUMS
#include <trace/events/rxrpc.h>
static int afs_deliver_cb_init_call_back_state(struct afs_call *);
static int afs_deliver_cb_init_call_back_state3(struct afs_call *);
......@@ -191,7 +193,7 @@ static void afs_cm_destructor(struct afs_call *call)
* Abort a service call from within an action function.
*/
static void afs_abort_service_call(struct afs_call *call, u32 abort_code, int error,
const char *why)
enum rxrpc_abort_reason why)
{
rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
abort_code, error, why);
......@@ -469,7 +471,7 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work)
if (memcmp(r, &call->net->uuid, sizeof(call->net->uuid)) == 0)
afs_send_empty_reply(call);
else
afs_abort_service_call(call, 1, 1, "K-1");
afs_abort_service_call(call, 1, 1, afs_abort_probeuuid_negative);
afs_put_call(call);
_leave("");
......
......@@ -13,6 +13,8 @@
#include "internal.h"
#include "afs_cm.h"
#include "protocol_yfs.h"
#define RXRPC_TRACE_ONLY_DEFINE_ENUMS
#include <trace/events/rxrpc.h>
struct workqueue_struct *afs_async_calls;
......@@ -397,7 +399,8 @@ void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
error_do_abort:
if (ret != -ECONNABORTED) {
rxrpc_kernel_abort_call(call->net->socket, rxcall,
RX_USER_ABORT, ret, "KSD");
RX_USER_ABORT, ret,
afs_abort_send_data_error);
} else {
len = 0;
iov_iter_kvec(&msg.msg_iter, ITER_DEST, NULL, 0, 0);
......@@ -527,7 +530,8 @@ static void afs_deliver_to_call(struct afs_call *call)
case -ENOTSUPP:
abort_code = RXGEN_OPCODE;
rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
abort_code, ret, "KIV");
abort_code, ret,
afs_abort_op_not_supported);
goto local_abort;
case -EIO:
pr_err("kAFS: Call %u in bad state %u\n",
......@@ -542,12 +546,14 @@ static void afs_deliver_to_call(struct afs_call *call)
if (state != AFS_CALL_CL_AWAIT_REPLY)
abort_code = RXGEN_SS_UNMARSHAL;
rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
abort_code, ret, "KUM");
abort_code, ret,
afs_abort_unmarshal_error);
goto local_abort;
default:
abort_code = RX_CALL_DEAD;
rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
abort_code, ret, "KER");
abort_code, ret,
afs_abort_general_error);
goto local_abort;
}
}
......@@ -619,7 +625,8 @@ long afs_wait_for_call_to_complete(struct afs_call *call,
/* Kill off the call if it's still live. */
_debug("call interrupted");
if (rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
RX_USER_ABORT, -EINTR, "KWI"))
RX_USER_ABORT, -EINTR,
afs_abort_interrupted))
afs_set_call_complete(call, -EINTR, 0);
}
}
......@@ -836,7 +843,8 @@ void afs_send_empty_reply(struct afs_call *call)
case -ENOMEM:
_debug("oom");
rxrpc_kernel_abort_call(net->socket, call->rxcall,
RXGEN_SS_MARSHAL, -ENOMEM, "KOO");
RXGEN_SS_MARSHAL, -ENOMEM,
afs_abort_oom);
fallthrough;
default:
_leave(" [error]");
......@@ -878,7 +886,8 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
if (n == -ENOMEM) {
_debug("oom");
rxrpc_kernel_abort_call(net->socket, call->rxcall,
RXGEN_SS_MARSHAL, -ENOMEM, "KOO");
RXGEN_SS_MARSHAL, -ENOMEM,
afs_abort_oom);
}
_leave(" [error]");
}
......
......@@ -15,6 +15,7 @@ struct key;
struct sock;
struct socket;
struct rxrpc_call;
enum rxrpc_abort_reason;
enum rxrpc_interruptibility {
RXRPC_INTERRUPTIBLE, /* Call is interruptible */
......@@ -55,7 +56,7 @@ int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *,
int rxrpc_kernel_recv_data(struct socket *, struct rxrpc_call *,
struct iov_iter *, size_t *, bool, u32 *, u16 *);
bool rxrpc_kernel_abort_call(struct socket *, struct rxrpc_call *,
u32, int, const char *);
u32, int, enum rxrpc_abort_reason);
void rxrpc_kernel_end_call(struct socket *, struct rxrpc_call *);
void rxrpc_kernel_get_peer(struct socket *, struct rxrpc_call *,
struct sockaddr_rxrpc *);
......
......@@ -16,6 +16,104 @@
/*
* Declare tracing information enums and their string mappings for display.
*/
#define rxrpc_abort_reasons \
/* AFS errors */ \
EM(afs_abort_general_error, "afs-error") \
EM(afs_abort_interrupted, "afs-intr") \
EM(afs_abort_oom, "afs-oom") \
EM(afs_abort_op_not_supported, "afs-op-notsupp") \
EM(afs_abort_probeuuid_negative, "afs-probeuuid-neg") \
EM(afs_abort_send_data_error, "afs-send-data") \
EM(afs_abort_unmarshal_error, "afs-unmarshal") \
/* rxperf errors */ \
EM(rxperf_abort_general_error, "rxperf-error") \
EM(rxperf_abort_oom, "rxperf-oom") \
EM(rxperf_abort_op_not_supported, "rxperf-op-notsupp") \
EM(rxperf_abort_unmarshal_error, "rxperf-unmarshal") \
/* RxKAD security errors */ \
EM(rxkad_abort_1_short_check, "rxkad1-short-check") \
EM(rxkad_abort_1_short_data, "rxkad1-short-data") \
EM(rxkad_abort_1_short_encdata, "rxkad1-short-encdata") \
EM(rxkad_abort_1_short_header, "rxkad1-short-hdr") \
EM(rxkad_abort_2_short_check, "rxkad2-short-check") \
EM(rxkad_abort_2_short_data, "rxkad2-short-data") \
EM(rxkad_abort_2_short_header, "rxkad2-short-hdr") \
EM(rxkad_abort_2_short_len, "rxkad2-short-len") \
EM(rxkad_abort_bad_checksum, "rxkad2-bad-cksum") \
EM(rxkad_abort_chall_key_expired, "rxkad-chall-key-exp") \
EM(rxkad_abort_chall_level, "rxkad-chall-level") \
EM(rxkad_abort_chall_no_key, "rxkad-chall-nokey") \
EM(rxkad_abort_chall_short, "rxkad-chall-short") \
EM(rxkad_abort_chall_version, "rxkad-chall-version") \
EM(rxkad_abort_resp_bad_callid, "rxkad-resp-bad-callid") \
EM(rxkad_abort_resp_bad_checksum, "rxkad-resp-bad-cksum") \
EM(rxkad_abort_resp_bad_param, "rxkad-resp-bad-param") \
EM(rxkad_abort_resp_call_ctr, "rxkad-resp-call-ctr") \
EM(rxkad_abort_resp_call_state, "rxkad-resp-call-state") \
EM(rxkad_abort_resp_key_expired, "rxkad-resp-key-exp") \
EM(rxkad_abort_resp_key_rejected, "rxkad-resp-key-rej") \
EM(rxkad_abort_resp_level, "rxkad-resp-level") \
EM(rxkad_abort_resp_nokey, "rxkad-resp-nokey") \
EM(rxkad_abort_resp_ooseq, "rxkad-resp-ooseq") \
EM(rxkad_abort_resp_short, "rxkad-resp-short") \
EM(rxkad_abort_resp_short_tkt, "rxkad-resp-short-tkt") \
EM(rxkad_abort_resp_tkt_aname, "rxkad-resp-tk-aname") \
EM(rxkad_abort_resp_tkt_expired, "rxkad-resp-tk-exp") \
EM(rxkad_abort_resp_tkt_future, "rxkad-resp-tk-future") \
EM(rxkad_abort_resp_tkt_inst, "rxkad-resp-tk-inst") \
EM(rxkad_abort_resp_tkt_len, "rxkad-resp-tk-len") \
EM(rxkad_abort_resp_tkt_realm, "rxkad-resp-tk-realm") \
EM(rxkad_abort_resp_tkt_short, "rxkad-resp-tk-short") \
EM(rxkad_abort_resp_tkt_sinst, "rxkad-resp-tk-sinst") \
EM(rxkad_abort_resp_tkt_sname, "rxkad-resp-tk-sname") \
EM(rxkad_abort_resp_unknown_tkt, "rxkad-resp-unknown-tkt") \
EM(rxkad_abort_resp_version, "rxkad-resp-version") \
/* rxrpc errors */ \
EM(rxrpc_abort_call_improper_term, "call-improper-term") \
EM(rxrpc_abort_call_reset, "call-reset") \
EM(rxrpc_abort_call_sendmsg, "call-sendmsg") \
EM(rxrpc_abort_call_sock_release, "call-sock-rel") \
EM(rxrpc_abort_call_sock_release_tba, "call-sock-rel-tba") \
EM(rxrpc_abort_call_timeout, "call-timeout") \
EM(rxrpc_abort_no_service_key, "no-serv-key") \
EM(rxrpc_abort_nomem, "nomem") \
EM(rxrpc_abort_service_not_offered, "serv-not-offered") \
EM(rxrpc_abort_shut_down, "shut-down") \
EM(rxrpc_abort_unsupported_security, "unsup-sec") \
EM(rxrpc_badmsg_bad_abort, "bad-abort") \
EM(rxrpc_badmsg_bad_jumbo, "bad-jumbo") \
EM(rxrpc_badmsg_short_ack, "short-ack") \
EM(rxrpc_badmsg_short_ack_info, "short-ack-info") \
EM(rxrpc_badmsg_short_hdr, "short-hdr") \
EM(rxrpc_badmsg_unsupported_packet, "unsup-pkt") \
EM(rxrpc_badmsg_zero_call, "zero-call") \
EM(rxrpc_badmsg_zero_seq, "zero-seq") \
EM(rxrpc_badmsg_zero_service, "zero-service") \
EM(rxrpc_eproto_ackr_outside_window, "ackr-out-win") \
EM(rxrpc_eproto_ackr_sack_overflow, "ackr-sack-over") \
EM(rxrpc_eproto_ackr_short_sack, "ackr-short-sack") \
EM(rxrpc_eproto_ackr_zero, "ackr-zero") \
EM(rxrpc_eproto_bad_upgrade, "bad-upgrade") \
EM(rxrpc_eproto_data_after_last, "data-after-last") \
EM(rxrpc_eproto_different_last, "diff-last") \
EM(rxrpc_eproto_early_reply, "early-reply") \
EM(rxrpc_eproto_improper_term, "improper-term") \
EM(rxrpc_eproto_no_client_call, "no-cl-call") \
EM(rxrpc_eproto_no_client_conn, "no-cl-conn") \
EM(rxrpc_eproto_no_service_call, "no-sv-call") \
EM(rxrpc_eproto_reupgrade, "re-upgrade") \
EM(rxrpc_eproto_rxnull_challenge, "rxnull-chall") \
EM(rxrpc_eproto_rxnull_response, "rxnull-resp") \
EM(rxrpc_eproto_tx_rot_last, "tx-rot-last") \
EM(rxrpc_eproto_unexpected_ack, "unex-ack") \
EM(rxrpc_eproto_unexpected_ackall, "unex-ackall") \
EM(rxrpc_eproto_unexpected_implicit_end, "unex-impl-end") \
EM(rxrpc_eproto_unexpected_reply, "unex-reply") \
EM(rxrpc_eproto_wrong_security, "wrong-sec") \
EM(rxrpc_recvmsg_excess_data, "recvmsg-excess") \
EM(rxrpc_recvmsg_short_data, "recvmsg-short") \
E_(rxrpc_sendmsg_late_send, "sendmsg-late")
#define rxrpc_call_poke_traces \
EM(rxrpc_call_poke_abort, "Abort") \
EM(rxrpc_call_poke_complete, "Compl") \
......@@ -382,6 +480,7 @@
#define EM(a, b) a,
#define E_(a, b) a
enum rxrpc_abort_reason { rxrpc_abort_reasons } __mode(byte);
enum rxrpc_bundle_trace { rxrpc_bundle_traces } __mode(byte);
enum rxrpc_call_poke_trace { rxrpc_call_poke_traces } __mode(byte);
enum rxrpc_call_trace { rxrpc_call_traces } __mode(byte);
......@@ -410,9 +509,13 @@ enum rxrpc_txqueue_trace { rxrpc_txqueue_traces } __mode(byte);
*/
#undef EM
#undef E_
#ifndef RXRPC_TRACE_ONLY_DEFINE_ENUMS
#define EM(a, b) TRACE_DEFINE_ENUM(a);
#define E_(a, b) TRACE_DEFINE_ENUM(a);
rxrpc_abort_reasons;
rxrpc_bundle_traces;
rxrpc_call_poke_traces;
rxrpc_call_traces;
......@@ -663,14 +766,14 @@ TRACE_EVENT(rxrpc_rx_done,
);
TRACE_EVENT(rxrpc_abort,
TP_PROTO(unsigned int call_nr, const char *why, u32 cid, u32 call_id,
rxrpc_seq_t seq, int abort_code, int error),
TP_PROTO(unsigned int call_nr, enum rxrpc_abort_reason why,
u32 cid, u32 call_id, rxrpc_seq_t seq, int abort_code, int error),
TP_ARGS(call_nr, why, cid, call_id, seq, abort_code, error),
TP_STRUCT__entry(
__field(unsigned int, call_nr )
__array(char, why, 4 )
__field(enum rxrpc_abort_reason, why )
__field(u32, cid )
__field(u32, call_id )
__field(rxrpc_seq_t, seq )
......@@ -679,8 +782,8 @@ TRACE_EVENT(rxrpc_abort,
),
TP_fast_assign(
memcpy(__entry->why, why, 4);
__entry->call_nr = call_nr;
__entry->why = why;
__entry->cid = cid;
__entry->call_id = call_id;
__entry->abort_code = abort_code;
......@@ -691,7 +794,8 @@ TRACE_EVENT(rxrpc_abort,
TP_printk("c=%08x %08x:%08x s=%u a=%d e=%d %s",
__entry->call_nr,
__entry->cid, __entry->call_id, __entry->seq,
__entry->abort_code, __entry->error, __entry->why)
__entry->abort_code, __entry->error,
__print_symbolic(__entry->why, rxrpc_abort_reasons))
);
TRACE_EVENT(rxrpc_call_complete,
......@@ -1527,30 +1631,6 @@ TRACE_EVENT(rxrpc_improper_term,
__entry->abort_code)
);
TRACE_EVENT(rxrpc_rx_eproto,
TP_PROTO(struct rxrpc_call *call, rxrpc_serial_t serial,
const char *why),
TP_ARGS(call, serial, why),
TP_STRUCT__entry(
__field(unsigned int, call )
__field(rxrpc_serial_t, serial )
__field(const char *, why )
),
TP_fast_assign(
__entry->call = call ? call->debug_id : 0;
__entry->serial = serial;
__entry->why = why;
),
TP_printk("c=%08x EPROTO %08x %s",
__entry->call,
__entry->serial,
__entry->why)
);
TRACE_EVENT(rxrpc_connect_call,
TP_PROTO(struct rxrpc_call *call),
......@@ -1848,6 +1928,8 @@ TRACE_EVENT(rxrpc_call_poked,
#undef EM
#undef E_
#endif /* RXRPC_TRACE_ONLY_DEFINE_ENUMS */
#endif /* _TRACE_RXRPC_H */
/* This part must be outside protection */
......
......@@ -627,9 +627,10 @@ struct rxrpc_call {
unsigned long events;
spinlock_t notify_lock; /* Kernel notification lock */
rwlock_t state_lock; /* lock for state transition */
const char *send_abort_why; /* String indicating why the abort was sent */
unsigned int send_abort_why; /* Why the abort [enum rxrpc_abort_reason] */
s32 send_abort; /* Abort code to be sent */
short send_abort_err; /* Error to be associated with the abort */
rxrpc_seq_t send_abort_seq; /* DATA packet that incurred the abort (or 0) */
s32 abort_code; /* Local/remote abort code */
int error; /* Local error incurred */
enum rxrpc_call_state state; /* current state of call */
......@@ -818,9 +819,11 @@ extern struct workqueue_struct *rxrpc_workqueue;
*/
int rxrpc_service_prealloc(struct rxrpc_sock *, gfp_t);
void rxrpc_discard_prealloc(struct rxrpc_sock *);
int rxrpc_new_incoming_call(struct rxrpc_local *, struct rxrpc_peer *,
struct rxrpc_connection *, struct sockaddr_rxrpc *,
struct sk_buff *);
bool rxrpc_new_incoming_call(struct rxrpc_local *local,
struct rxrpc_peer *peer,
struct rxrpc_connection *conn,
struct sockaddr_rxrpc *peer_srx,
struct sk_buff *skb);
void rxrpc_accept_incoming_calls(struct rxrpc_local *);
int rxrpc_user_charge_accept(struct rxrpc_sock *, unsigned long);
......@@ -840,7 +843,7 @@ void rxrpc_reduce_call_timer(struct rxrpc_call *call,
unsigned long now,
enum rxrpc_timer_trace why);
void rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb);
bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb);
/*
* call_object.c
......@@ -905,10 +908,10 @@ void rxrpc_clean_up_local_conns(struct rxrpc_local *);
void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn, struct sk_buff *skb,
unsigned int channel);
int rxrpc_abort_conn(struct rxrpc_connection *conn, struct sk_buff *skb,
s32 abort_code, int err, const char *why);
s32 abort_code, int err, enum rxrpc_abort_reason why);
void rxrpc_process_connection(struct work_struct *);
void rxrpc_process_delayed_final_acks(struct rxrpc_connection *, bool);
int rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb);
bool rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb);
void rxrpc_input_conn_event(struct rxrpc_connection *conn, struct sk_buff *skb);
static inline bool rxrpc_is_conn_aborted(const struct rxrpc_connection *conn)
......@@ -979,12 +982,19 @@ void rxrpc_implicit_end_call(struct rxrpc_call *, struct sk_buff *);
*/
int rxrpc_encap_rcv(struct sock *, struct sk_buff *);
void rxrpc_error_report(struct sock *);
bool rxrpc_direct_abort(struct sk_buff *skb, enum rxrpc_abort_reason why,
s32 abort_code, int err);
int rxrpc_io_thread(void *data);
static inline void rxrpc_wake_up_io_thread(struct rxrpc_local *local)
{
wake_up_process(local->io_thread);
}
static inline bool rxrpc_protocol_error(struct sk_buff *skb, enum rxrpc_abort_reason why)
{
return rxrpc_direct_abort(skb, why, RX_PROTOCOL_ERROR, -EPROTO);
}
/*
* insecure.c
*/
......@@ -1108,29 +1118,26 @@ bool __rxrpc_set_call_completion(struct rxrpc_call *, enum rxrpc_call_completion
bool rxrpc_set_call_completion(struct rxrpc_call *, enum rxrpc_call_completion, u32, int);
bool __rxrpc_call_completed(struct rxrpc_call *);
bool rxrpc_call_completed(struct rxrpc_call *);
bool __rxrpc_abort_call(const char *, struct rxrpc_call *, rxrpc_seq_t, u32, int);
bool rxrpc_abort_call(const char *, struct rxrpc_call *, rxrpc_seq_t, u32, int);
bool __rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
u32 abort_code, int error, enum rxrpc_abort_reason why);
bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
u32 abort_code, int error, enum rxrpc_abort_reason why);
int rxrpc_recvmsg(struct socket *, struct msghdr *, size_t, int);
/*
* Abort a call due to a protocol error.
*/
static inline bool __rxrpc_abort_eproto(struct rxrpc_call *call,
static inline int rxrpc_abort_eproto(struct rxrpc_call *call,
struct sk_buff *skb,
const char *eproto_why,
const char *why,
u32 abort_code)
s32 abort_code,
enum rxrpc_abort_reason why)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
trace_rxrpc_rx_eproto(call, sp->hdr.serial, eproto_why);
return rxrpc_abort_call(why, call, sp->hdr.seq, abort_code, -EPROTO);
rxrpc_abort_call(call, sp->hdr.seq, abort_code, -EPROTO, why);
return -EPROTO;
}
#define rxrpc_abort_eproto(call, skb, eproto_why, abort_why, abort_code) \
__rxrpc_abort_eproto((call), (skb), tracepoint_string(eproto_why), \
(abort_why), (abort_code))
/*
* rtt.c
*/
......@@ -1162,8 +1169,8 @@ struct key *rxrpc_look_up_server_security(struct rxrpc_connection *,
/*
* sendmsg.c
*/
bool rxrpc_propose_abort(struct rxrpc_call *call,
u32 abort_code, int error, const char *why);
bool rxrpc_propose_abort(struct rxrpc_call *call, s32 abort_code, int error,
enum rxrpc_abort_reason why);
int rxrpc_do_sendmsg(struct rxrpc_sock *, struct msghdr *, size_t);
/*
......
......@@ -326,7 +326,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
* If we want to report an error, we mark the skb with the packet type and
* abort code and return false.
*/
int rxrpc_new_incoming_call(struct rxrpc_local *local,
bool rxrpc_new_incoming_call(struct rxrpc_local *local,
struct rxrpc_peer *peer,
struct rxrpc_connection *conn,
struct sockaddr_rxrpc *peer_srx,
......@@ -339,10 +339,9 @@ int rxrpc_new_incoming_call(struct rxrpc_local *local,
_enter("");
/* Don't set up a call for anything other than the first DATA packet. */
if (sp->hdr.seq != 1 ||
sp->hdr.type != RXRPC_PACKET_TYPE_DATA)
return 0; /* Just discard */
/* Don't set up a call for anything other than a DATA packet. */
if (sp->hdr.type != RXRPC_PACKET_TYPE_DATA)
return rxrpc_protocol_error(skb, rxrpc_eproto_no_service_call);
rcu_read_lock();
......@@ -363,16 +362,14 @@ int rxrpc_new_incoming_call(struct rxrpc_local *local,
if (!conn) {
sec = rxrpc_get_incoming_security(rx, skb);
if (!sec)
goto reject;
goto unsupported_security;
}
spin_lock(&rx->incoming_lock);
if (rx->sk.sk_state == RXRPC_SERVER_LISTEN_DISABLED ||
rx->sk.sk_state == RXRPC_CLOSE) {
trace_rxrpc_abort(0, "CLS", sp->hdr.cid, sp->hdr.callNumber,
sp->hdr.seq, RX_INVALID_OPERATION, ESHUTDOWN);
skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
skb->priority = RX_INVALID_OPERATION;
rxrpc_direct_abort(skb, rxrpc_abort_shut_down,
RX_INVALID_OPERATION, -ESHUTDOWN);
goto no_call;
}
......@@ -413,22 +410,24 @@ int rxrpc_new_incoming_call(struct rxrpc_local *local,
_leave(" = %p{%d}", call, call->debug_id);
rxrpc_input_call_event(call, skb);
rxrpc_put_call(call, rxrpc_call_put_input);
return 0;
return true;
unsupported_service:
trace_rxrpc_abort(0, "INV", sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
RX_INVALID_OPERATION, EOPNOTSUPP);
skb->priority = RX_INVALID_OPERATION;
goto reject;
rcu_read_unlock();
return rxrpc_direct_abort(skb, rxrpc_abort_service_not_offered,
RX_INVALID_OPERATION, -EOPNOTSUPP);
unsupported_security:
rcu_read_unlock();
return rxrpc_direct_abort(skb, rxrpc_abort_service_not_offered,
RX_INVALID_OPERATION, -EKEYREJECTED);
no_call:
spin_unlock(&rx->incoming_lock);
reject:
rcu_read_unlock();
_leave(" = f [%u]", skb->mark);
return -EPROTO;
return false;
discard:
rcu_read_unlock();
return 0;
return true;
}
/*
......
......@@ -333,7 +333,7 @@ static void rxrpc_send_initial_ping(struct rxrpc_call *call)
/*
* Handle retransmission and deferred ACK/abort generation.
*/
void rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
{
unsigned long now, next, t;
rxrpc_serial_t ackr_serial;
......@@ -352,8 +352,8 @@ void rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
/* Handle abort request locklessly, vs rxrpc_propose_abort(). */
abort_code = smp_load_acquire(&call->send_abort);
if (abort_code) {
rxrpc_abort_call(call->send_abort_why, call, 0, call->send_abort,
call->send_abort_err);
rxrpc_abort_call(call, 0, call->send_abort, call->send_abort_err,
call->send_abort_why);
goto out;
}
......@@ -440,9 +440,11 @@ void rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
if (test_bit(RXRPC_CALL_RX_HEARD, &call->flags) &&
(int)call->conn->hi_serial - (int)call->rx_serial > 0) {
trace_rxrpc_call_reset(call);
rxrpc_abort_call("EXP", call, 0, RX_CALL_DEAD, -ECONNRESET);
rxrpc_abort_call(call, 0, RX_CALL_DEAD, -ECONNRESET,
rxrpc_abort_call_reset);
} else {
rxrpc_abort_call("EXP", call, 0, RX_CALL_TIMEOUT, -ETIME);
rxrpc_abort_call(call, 0, RX_CALL_TIMEOUT, -ETIME,
rxrpc_abort_call_timeout);
}
goto out;
}
......@@ -494,4 +496,5 @@ void rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
if (call->acks_hard_ack != call->tx_bottom)
rxrpc_shrink_call_tx_buffer(call);
_leave("");
return true;
}
......@@ -581,7 +581,8 @@ void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx)
call = list_entry(rx->to_be_accepted.next,
struct rxrpc_call, accept_link);
list_del(&call->accept_link);
rxrpc_propose_abort(call, RX_CALL_DEAD, -ECONNRESET, "SKR");
rxrpc_propose_abort(call, RX_CALL_DEAD, -ECONNRESET,
rxrpc_abort_call_sock_release_tba);
rxrpc_put_call(call, rxrpc_call_put_release_sock_tba);
}
......@@ -589,7 +590,8 @@ void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx)
call = list_entry(rx->sock_calls.next,
struct rxrpc_call, sock_link);
rxrpc_get_call(call, rxrpc_call_get_release_sock);
rxrpc_propose_abort(call, RX_CALL_DEAD, -ECONNRESET, "SKT");
rxrpc_propose_abort(call, RX_CALL_DEAD, -ECONNRESET,
rxrpc_abort_call_sock_release);
rxrpc_release_call(rx, call);
rxrpc_put_call(call, rxrpc_call_put_release_sock);
}
......
......@@ -47,7 +47,7 @@ static bool rxrpc_set_conn_aborted(struct rxrpc_connection *conn, struct sk_buff
* Mark a socket buffer to indicate that the connection it's on should be aborted.
*/
int rxrpc_abort_conn(struct rxrpc_connection *conn, struct sk_buff *skb,
s32 abort_code, int err, const char *why)
s32 abort_code, int err, enum rxrpc_abort_reason why)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
......@@ -288,8 +288,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
return 0;
default:
trace_rxrpc_rx_eproto(NULL, sp->hdr.serial,
tracepoint_string("bad_conn_pkt"));
WARN_ON_ONCE(1);
return -EPROTO;
}
}
......@@ -300,7 +299,8 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
static void rxrpc_secure_connection(struct rxrpc_connection *conn)
{
if (conn->security->issue_challenge(conn) < 0)
rxrpc_abort_conn(conn, NULL, RX_CALL_DEAD, -ENOMEM, "OOM");
rxrpc_abort_conn(conn, NULL, RX_CALL_DEAD, -ENOMEM,
rxrpc_abort_nomem);
}
/*
......@@ -405,14 +405,14 @@ static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
/*
* Input a connection-level packet.
*/
int rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb)
bool rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
switch (sp->hdr.type) {
case RXRPC_PACKET_TYPE_BUSY:
/* Just ignore BUSY packets for now. */
return 0;
return true;
case RXRPC_PACKET_TYPE_ABORT:
if (rxrpc_is_conn_aborted(conn))
......@@ -429,12 +429,11 @@ int rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb)
return true;
}
rxrpc_post_packet_to_conn(conn, skb);
return 0;
return true;
default:
trace_rxrpc_rx_eproto(NULL, sp->hdr.serial,
tracepoint_string("bad_conn_pkt"));
return -EPROTO;
WARN_ON_ONCE(1);
return true;
}
}
......
......@@ -9,10 +9,10 @@
#include "ar-internal.h"
static void rxrpc_proto_abort(const char *why,
struct rxrpc_call *call, rxrpc_seq_t seq)
static void rxrpc_proto_abort(struct rxrpc_call *call, rxrpc_seq_t seq,
enum rxrpc_abort_reason why)
{
rxrpc_abort_call(why, call, seq, RX_PROTOCOL_ERROR, -EBADMSG);
rxrpc_abort_call(call, seq, RX_PROTOCOL_ERROR, -EBADMSG, why);
}
/*
......@@ -249,8 +249,8 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
* This occurs when we get an ACKALL packet, the first DATA packet of a reply,
* or a final ACK packet.
*/
static bool rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun,
const char *abort_why)
static void rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun,
enum rxrpc_abort_reason abort_why)
{
unsigned int state;
......@@ -283,13 +283,12 @@ static bool rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun,
else
trace_rxrpc_txqueue(call, rxrpc_txqueue_end);
_leave(" = ok");
return true;
return;
bad_state:
write_unlock(&call->state_lock);
kdebug("end_tx %s", rxrpc_call_states[call->state]);
rxrpc_proto_abort(abort_why, call, call->tx_top);
return false;
rxrpc_proto_abort(call, call->tx_top, abort_why);
}
/*
......@@ -311,11 +310,13 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
if (!test_bit(RXRPC_CALL_TX_LAST, &call->flags)) {
if (!rxrpc_rotate_tx_window(call, top, &summary)) {
rxrpc_proto_abort("TXL", call, top);
rxrpc_proto_abort(call, top, rxrpc_eproto_early_reply);
return false;
}
}
return rxrpc_end_tx_phase(call, true, "ETD");
rxrpc_end_tx_phase(call, true, rxrpc_eproto_unexpected_reply);
return true;
}
static void rxrpc_input_update_ack_window(struct rxrpc_call *call,
......@@ -365,17 +366,14 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
if (last) {
if (test_and_set_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
seq + 1 != wtop) {
rxrpc_proto_abort("LSN", call, seq);
return;
}
seq + 1 != wtop)
return rxrpc_proto_abort(call, seq, rxrpc_eproto_different_last);
} else {
if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
after_eq(seq, wtop)) {
pr_warn("Packet beyond last: c=%x q=%x window=%x-%x wlimit=%x\n",
call->debug_id, seq, window, wtop, wlimit);
rxrpc_proto_abort("LSA", call, seq);
return;
return rxrpc_proto_abort(call, seq, rxrpc_eproto_data_after_last);
}
}
......@@ -583,7 +581,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
goto out_notify;
if (!rxrpc_input_split_jumbo(call, skb)) {
rxrpc_proto_abort("VLD", call, sp->hdr.seq);
rxrpc_proto_abort(call, sp->hdr.seq, rxrpc_badmsg_bad_jumbo);
goto out_notify;
}
skb = NULL;
......@@ -764,7 +762,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
offset = sizeof(struct rxrpc_wire_header);
if (skb_copy_bits(skb, offset, &ack, sizeof(ack)) < 0)
return rxrpc_proto_abort("XAK", call, 0);
return rxrpc_proto_abort(call, 0, rxrpc_badmsg_short_ack);
offset += sizeof(ack);
ack_serial = sp->hdr.serial;
......@@ -844,7 +842,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
ioffset = offset + nr_acks + 3;
if (skb->len >= ioffset + sizeof(info) &&
skb_copy_bits(skb, ioffset, &info, sizeof(info)) < 0)
return rxrpc_proto_abort("XAI", call, 0);
return rxrpc_proto_abort(call, 0, rxrpc_badmsg_short_ack_info);
if (nr_acks > 0)
skb_condense(skb);
......@@ -867,7 +865,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
rxrpc_input_ackinfo(call, skb, &info);
if (first_soft_ack == 0)
return rxrpc_proto_abort("AK0", call, 0);
return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_zero);
/* Ignore ACKs unless we are or have just been transmitting. */
switch (READ_ONCE(call->state)) {
......@@ -882,20 +880,20 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
if (before(hard_ack, call->acks_hard_ack) ||
after(hard_ack, call->tx_top))
return rxrpc_proto_abort("AKW", call, 0);
return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_outside_window);
if (nr_acks > call->tx_top - hard_ack)
return rxrpc_proto_abort("AKN", call, 0);
return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_sack_overflow);
if (after(hard_ack, call->acks_hard_ack)) {
if (rxrpc_rotate_tx_window(call, hard_ack, &summary)) {
rxrpc_end_tx_phase(call, false, "ETA");
rxrpc_end_tx_phase(call, false, rxrpc_eproto_unexpected_ack);
return;
}
}
if (nr_acks > 0) {
if (offset > (int)skb->len - nr_acks)
return rxrpc_proto_abort("XSA", call, 0);
return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_short_sack);
rxrpc_input_soft_acks(call, skb->data + offset, first_soft_ack,
nr_acks, &summary);
}
......@@ -917,7 +915,7 @@ static void rxrpc_input_ackall(struct rxrpc_call *call, struct sk_buff *skb)
struct rxrpc_ack_summary summary = { 0 };
if (rxrpc_rotate_tx_window(call, call->tx_top, &summary))
rxrpc_end_tx_phase(call, false, "ETL");
rxrpc_end_tx_phase(call, false, rxrpc_eproto_unexpected_ackall);
}
/*
......@@ -962,27 +960,23 @@ void rxrpc_input_call_packet(struct rxrpc_call *call, struct sk_buff *skb)
switch (sp->hdr.type) {
case RXRPC_PACKET_TYPE_DATA:
rxrpc_input_data(call, skb);
break;
return rxrpc_input_data(call, skb);
case RXRPC_PACKET_TYPE_ACK:
rxrpc_input_ack(call, skb);
break;
return rxrpc_input_ack(call, skb);
case RXRPC_PACKET_TYPE_BUSY:
/* Just ignore BUSY packets from the server; the retry and
* lifespan timers will take care of business. BUSY packets
* from the client don't make sense.
*/
break;
return;
case RXRPC_PACKET_TYPE_ABORT:
rxrpc_input_abort(call, skb);
break;
return rxrpc_input_abort(call, skb);
case RXRPC_PACKET_TYPE_ACKALL:
rxrpc_input_ackall(call, skb);
break;
return rxrpc_input_ackall(call, skb);
default:
break;
......@@ -1004,7 +998,8 @@ void rxrpc_implicit_end_call(struct rxrpc_call *call, struct sk_buff *skb)
case RXRPC_CALL_COMPLETE:
break;
default:
rxrpc_abort_call("IMP", call, 0, RX_CALL_DEAD, -ESHUTDOWN);
rxrpc_abort_call(call, 0, RX_CALL_DEAD, -ESHUTDOWN,
rxrpc_eproto_improper_term);
trace_rxrpc_improper_term(call);
break;
}
......
......@@ -45,13 +45,15 @@ static void none_free_call_crypto(struct rxrpc_call *call)
static int none_respond_to_challenge(struct rxrpc_connection *conn,
struct sk_buff *skb)
{
return rxrpc_abort_conn(conn, skb, RX_PROTOCOL_ERROR, -EPROTO, "RXN");
return rxrpc_abort_conn(conn, skb, RX_PROTOCOL_ERROR, -EPROTO,
rxrpc_eproto_rxnull_challenge);
}
static int none_verify_response(struct rxrpc_connection *conn,
struct sk_buff *skb)
{
return rxrpc_abort_conn(conn, skb, RX_PROTOCOL_ERROR, -EPROTO, "RXN");
return rxrpc_abort_conn(conn, skb, RX_PROTOCOL_ERROR, -EPROTO,
rxrpc_eproto_rxnull_response);
}
static void none_clear(struct rxrpc_connection *conn)
......
This diff is collapsed.
......@@ -117,8 +117,8 @@ bool rxrpc_call_completed(struct rxrpc_call *call)
/*
* Record that a call is locally aborted.
*/
bool __rxrpc_abort_call(const char *why, struct rxrpc_call *call,
rxrpc_seq_t seq, u32 abort_code, int error)
bool __rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
u32 abort_code, int error, enum rxrpc_abort_reason why)
{
trace_rxrpc_abort(call->debug_id, why, call->cid, call->call_id, seq,
abort_code, error);
......@@ -126,13 +126,13 @@ bool __rxrpc_abort_call(const char *why, struct rxrpc_call *call,
abort_code, error);
}
bool rxrpc_abort_call(const char *why, struct rxrpc_call *call,
rxrpc_seq_t seq, u32 abort_code, int error)
bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
u32 abort_code, int error, enum rxrpc_abort_reason why)
{
bool ret;
write_lock(&call->state_lock);
ret = __rxrpc_abort_call(why, call, seq, abort_code, error);
ret = __rxrpc_abort_call(call, seq, abort_code, error, why);
write_unlock(&call->state_lock);
if (ret && test_bit(RXRPC_CALL_EXPOSED, &call->flags))
rxrpc_send_abort_packet(call);
......@@ -642,11 +642,15 @@ int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call,
return ret;
short_data:
trace_rxrpc_rx_eproto(call, 0, tracepoint_string("short_data"));
trace_rxrpc_abort(call->debug_id, rxrpc_recvmsg_short_data,
call->cid, call->call_id, call->rx_consumed,
0, -EBADMSG);
ret = -EBADMSG;
goto out;
excess_data:
trace_rxrpc_rx_eproto(call, 0, tracepoint_string("excess_data"));
trace_rxrpc_abort(call->debug_id, rxrpc_recvmsg_excess_data,
call->cid, call->call_id, call->rx_consumed,
0, -EMSGSIZE);
ret = -EMSGSIZE;
goto out;
call_complete:
......
This diff is collapsed.
......@@ -10,6 +10,8 @@
#include <linux/slab.h>
#include <net/sock.h>
#include <net/af_rxrpc.h>
#define RXRPC_TRACE_ONLY_DEFINE_ENUMS
#include <trace/events/rxrpc.h>
MODULE_DESCRIPTION("rxperf test server (afs)");
MODULE_AUTHOR("Red Hat, Inc.");
......@@ -307,12 +309,14 @@ static void rxperf_deliver_to_call(struct work_struct *work)
case -EOPNOTSUPP:
abort_code = RXGEN_OPCODE;
rxrpc_kernel_abort_call(rxperf_socket, call->rxcall,
abort_code, ret, "GOP");
abort_code, ret,
rxperf_abort_op_not_supported);
goto call_complete;
case -ENOTSUPP:
abort_code = RX_USER_ABORT;
rxrpc_kernel_abort_call(rxperf_socket, call->rxcall,
abort_code, ret, "GUA");
abort_code, ret,
rxperf_abort_op_not_supported);
goto call_complete;
case -EIO:
pr_err("Call %u in bad state %u\n",
......@@ -324,11 +328,13 @@ static void rxperf_deliver_to_call(struct work_struct *work)
case -ENOMEM:
case -EFAULT:
rxrpc_kernel_abort_call(rxperf_socket, call->rxcall,
RXGEN_SS_UNMARSHAL, ret, "GUM");
RXGEN_SS_UNMARSHAL, ret,
rxperf_abort_unmarshal_error);
goto call_complete;
default:
rxrpc_kernel_abort_call(rxperf_socket, call->rxcall,
RX_CALL_DEAD, ret, "GER");
RX_CALL_DEAD, ret,
rxperf_abort_general_error);
goto call_complete;
}
}
......@@ -523,7 +529,8 @@ static int rxperf_process_call(struct rxperf_call *call)
if (n == -ENOMEM)
rxrpc_kernel_abort_call(rxperf_socket, call->rxcall,
RXGEN_SS_MARSHAL, -ENOMEM, "GOM");
RXGEN_SS_MARSHAL, -ENOMEM,
rxperf_abort_oom);
return n;
}
......
......@@ -144,21 +144,15 @@ const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *rx,
sec = rxrpc_security_lookup(sp->hdr.securityIndex);
if (!sec) {
trace_rxrpc_abort(0, "SVS",
sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
RX_INVALID_OPERATION, EKEYREJECTED);
skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
skb->priority = RX_INVALID_OPERATION;
rxrpc_direct_abort(skb, rxrpc_abort_unsupported_security,
RX_INVALID_OPERATION, -EKEYREJECTED);
return NULL;
}
if (sp->hdr.securityIndex != RXRPC_SECURITY_NONE &&
!rx->securities) {
trace_rxrpc_abort(0, "SVR",
sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
RX_INVALID_OPERATION, EKEYREJECTED);
skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
skb->priority = sec->no_key_abort;
rxrpc_direct_abort(skb, rxrpc_abort_no_service_key,
sec->no_key_abort, -EKEYREJECTED);
return NULL;
}
......
......@@ -20,14 +20,15 @@
/*
* Propose an abort to be made in the I/O thread.
*/
bool rxrpc_propose_abort(struct rxrpc_call *call,
u32 abort_code, int error, const char *why)
bool rxrpc_propose_abort(struct rxrpc_call *call, s32 abort_code, int error,
enum rxrpc_abort_reason why)
{
_enter("{%d},%d,%d,%s", call->debug_id, abort_code, error, why);
_enter("{%d},%d,%d,%u", call->debug_id, abort_code, error, why);
if (!call->send_abort && call->state < RXRPC_CALL_COMPLETE) {
call->send_abort_why = why;
call->send_abort_err = error;
call->send_abort_seq = 0;
/* Request abort locklessly vs rxrpc_input_call_event(). */
smp_store_release(&call->send_abort, abort_code);
rxrpc_poke_call(call, rxrpc_call_poke_abort);
......@@ -683,7 +684,8 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
/* it's too late for this call */
ret = -ESHUTDOWN;
} else if (p.command == RXRPC_CMD_SEND_ABORT) {
rxrpc_propose_abort(call, p.abort_code, -ECONNABORTED, "CMD");
rxrpc_propose_abort(call, p.abort_code, -ECONNABORTED,
rxrpc_abort_call_sendmsg);
ret = 0;
} else if (p.command != RXRPC_CMD_SEND_DATA) {
ret = -EINVAL;
......@@ -748,7 +750,9 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
break;
default:
/* Request phase complete for this client call */
trace_rxrpc_rx_eproto(call, 0, tracepoint_string("late_send"));
trace_rxrpc_abort(call->debug_id, rxrpc_sendmsg_late_send,
call->cid, call->call_id, call->rx_consumed,
0, -EPROTO);
ret = -EPROTO;
break;
}
......@@ -766,17 +770,17 @@ EXPORT_SYMBOL(rxrpc_kernel_send_data);
* @call: The call to be aborted
* @abort_code: The abort code to stick into the ABORT packet
* @error: Local error value
* @why: 3-char string indicating why.
* @why: Indication as to why.
*
* Allow a kernel service to abort a call, if it's still in an abortable state
* and return true if the call was aborted, false if it was already complete.
*/
bool rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call *call,
u32 abort_code, int error, const char *why)
u32 abort_code, int error, enum rxrpc_abort_reason why)
{
bool aborted;
_enter("{%d},%d,%d,%s", call->debug_id, abort_code, error, why);
_enter("{%d},%d,%d,%u", call->debug_id, abort_code, error, why);
mutex_lock(&call->user_mutex);
aborted = rxrpc_propose_abort(call, abort_code, error, why);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment