Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f109b94 authored by David S. Miller's avatar David S. Miller
Browse files


David Howells says:

====================
rxrpc: Fixes and improvements

Here's a set of patches that fix and improve some stuff in the AF_RXRPC
protocol:

The patches are:

 (1) Unlock mutex returned by rxrpc_accept_call().

 (2) Don't set connection upgrade by default.

 (3) Differentiate the call->user_mutex used by the kernel from that used
     by userspace calling sendmsg() to avoid lockdep warnings.

 (4) Delay terminal ACK transmission to a work queue so that it can be
     replaced by the next call if there is one.

 (5) Split the call parameters from the connection parameters so that more
     call-specific parameters can be passed through.

 (6) Fix the call timeouts to work the same as for other RxRPC/AFS
     implementations.

 (7) Don't transmit DELAY ACKs immediately, but instead delay them slightly
     so that can be discarded or can represent more packets.

 (8) Use RTT to calculate certain protocol timeouts.

 (9) Add a timeout to detect lost ACK/DATA packets.

(10) Add a keepalive function so that we ping the peer if we haven't
     transmitted for a short while, thereby keeping intervening firewall
     routes open.

(11) Make service endpoints expire like they're supposed to so that the UDP
     port can be reused.

(12) Fix connection expiry timers to make cleanup happen in a more timely
     fashion.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1d3b78bb 3d18cbb7
Loading
Loading
Loading
Loading
+63 −23
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ enum rxrpc_conn_trace {
	rxrpc_conn_put_client,
	rxrpc_conn_put_service,
	rxrpc_conn_queued,
	rxrpc_conn_reap_service,
	rxrpc_conn_seen,
};

@@ -138,10 +139,24 @@ enum rxrpc_rtt_rx_trace {

enum rxrpc_timer_trace {
	rxrpc_timer_begin,
	rxrpc_timer_exp_ack,
	rxrpc_timer_exp_hard,
	rxrpc_timer_exp_idle,
	rxrpc_timer_exp_keepalive,
	rxrpc_timer_exp_lost_ack,
	rxrpc_timer_exp_normal,
	rxrpc_timer_exp_ping,
	rxrpc_timer_exp_resend,
	rxrpc_timer_expired,
	rxrpc_timer_init_for_reply,
	rxrpc_timer_init_for_send_reply,
	rxrpc_timer_restart,
	rxrpc_timer_set_for_ack,
	rxrpc_timer_set_for_hard,
	rxrpc_timer_set_for_idle,
	rxrpc_timer_set_for_keepalive,
	rxrpc_timer_set_for_lost_ack,
	rxrpc_timer_set_for_normal,
	rxrpc_timer_set_for_ping,
	rxrpc_timer_set_for_resend,
	rxrpc_timer_set_for_send,
@@ -150,6 +165,7 @@ enum rxrpc_timer_trace {
enum rxrpc_propose_ack_trace {
	rxrpc_propose_ack_client_tx_end,
	rxrpc_propose_ack_input_data,
	rxrpc_propose_ack_ping_for_keepalive,
	rxrpc_propose_ack_ping_for_lost_ack,
	rxrpc_propose_ack_ping_for_lost_reply,
	rxrpc_propose_ack_ping_for_params,
@@ -206,6 +222,7 @@ enum rxrpc_congest_change {
	EM(rxrpc_conn_put_client,		"PTc") \
	EM(rxrpc_conn_put_service,		"PTs") \
	EM(rxrpc_conn_queued,			"QUE") \
	EM(rxrpc_conn_reap_service,		"RPs") \
	E_(rxrpc_conn_seen,			"SEE")

#define rxrpc_client_traces \
@@ -296,16 +313,31 @@ enum rxrpc_congest_change {
#define rxrpc_timer_traces \
	EM(rxrpc_timer_begin,			"Begin ") \
	EM(rxrpc_timer_expired,			"*EXPR*") \
	EM(rxrpc_timer_exp_ack,			"ExpAck") \
	EM(rxrpc_timer_exp_hard,		"ExpHrd") \
	EM(rxrpc_timer_exp_idle,		"ExpIdl") \
	EM(rxrpc_timer_exp_keepalive,		"ExpKA ") \
	EM(rxrpc_timer_exp_lost_ack,		"ExpLoA") \
	EM(rxrpc_timer_exp_normal,		"ExpNml") \
	EM(rxrpc_timer_exp_ping,		"ExpPng") \
	EM(rxrpc_timer_exp_resend,		"ExpRsn") \
	EM(rxrpc_timer_init_for_reply,		"IniRpl") \
	EM(rxrpc_timer_init_for_send_reply,	"SndRpl") \
	EM(rxrpc_timer_restart,			"Restrt") \
	EM(rxrpc_timer_set_for_ack,		"SetAck") \
	EM(rxrpc_timer_set_for_hard,		"SetHrd") \
	EM(rxrpc_timer_set_for_idle,		"SetIdl") \
	EM(rxrpc_timer_set_for_keepalive,	"KeepAl") \
	EM(rxrpc_timer_set_for_lost_ack,	"SetLoA") \
	EM(rxrpc_timer_set_for_normal,		"SetNml") \
	EM(rxrpc_timer_set_for_ping,		"SetPng") \
	EM(rxrpc_timer_set_for_resend,		"SetRTx") \
	E_(rxrpc_timer_set_for_send,		"SetTx ")
	E_(rxrpc_timer_set_for_send,		"SetSnd")

#define rxrpc_propose_ack_traces \
	EM(rxrpc_propose_ack_client_tx_end,	"ClTxEnd") \
	EM(rxrpc_propose_ack_input_data,	"DataIn ") \
	EM(rxrpc_propose_ack_ping_for_keepalive, "KeepAlv") \
	EM(rxrpc_propose_ack_ping_for_lost_ack,	"LostAck") \
	EM(rxrpc_propose_ack_ping_for_lost_reply, "LostRpl") \
	EM(rxrpc_propose_ack_ping_for_params,	"Params ") \
@@ -932,39 +964,47 @@ TRACE_EVENT(rxrpc_rtt_rx,

TRACE_EVENT(rxrpc_timer,
	    TP_PROTO(struct rxrpc_call *call, enum rxrpc_timer_trace why,
		     ktime_t now, unsigned long now_j),
		     unsigned long now),

	    TP_ARGS(call, why, now, now_j),
	    TP_ARGS(call, why, now),

	    TP_STRUCT__entry(
		    __field(struct rxrpc_call *,		call		)
		    __field(enum rxrpc_timer_trace,		why		)
		    __field_struct(ktime_t,			now		)
		    __field_struct(ktime_t,			expire_at	)
		    __field_struct(ktime_t,			ack_at		)
		    __field_struct(ktime_t,			resend_at	)
		    __field(unsigned long,			now_j		)
		    __field(unsigned long,			timer		)
		    __field(long,				now		)
		    __field(long,				ack_at		)
		    __field(long,				ack_lost_at	)
		    __field(long,				resend_at	)
		    __field(long,				ping_at		)
		    __field(long,				expect_rx_by	)
		    __field(long,				expect_req_by	)
		    __field(long,				expect_term_by	)
		    __field(long,				timer		)
			     ),

	    TP_fast_assign(
		    __entry->call		= call;
		    __entry->why		= why;
		    __entry->now		= now;
		    __entry->expire_at	= call->expire_at;
		    __entry->ack_at		= call->ack_at;
		    __entry->ack_lost_at	= call->ack_lost_at;
		    __entry->resend_at		= call->resend_at;
		    __entry->now_j	= now_j;
		    __entry->expect_rx_by	= call->expect_rx_by;
		    __entry->expect_req_by	= call->expect_req_by;
		    __entry->expect_term_by	= call->expect_term_by;
		    __entry->timer		= call->timer.expires;
			   ),

	    TP_printk("c=%p %s x=%lld a=%lld r=%lld t=%ld",
	    TP_printk("c=%p %s a=%ld la=%ld r=%ld xr=%ld xq=%ld xt=%ld t=%ld",
		      __entry->call,
		      __print_symbolic(__entry->why, rxrpc_timer_traces),
		      ktime_to_ns(ktime_sub(__entry->expire_at, __entry->now)),
		      ktime_to_ns(ktime_sub(__entry->ack_at, __entry->now)),
		      ktime_to_ns(ktime_sub(__entry->resend_at, __entry->now)),
		      __entry->timer - __entry->now_j)
		      __entry->ack_at - __entry->now,
		      __entry->ack_lost_at - __entry->now,
		      __entry->resend_at - __entry->now,
		      __entry->expect_rx_by - __entry->now,
		      __entry->expect_req_by - __entry->now,
		      __entry->expect_term_by - __entry->now,
		      __entry->timer - __entry->now)
	    );

TRACE_EVENT(rxrpc_rx_lose,
@@ -1080,7 +1120,7 @@ TRACE_EVENT(rxrpc_congest,
		    memcpy(&__entry->sum, summary, sizeof(__entry->sum));
			   ),

	    TP_printk("c=%p %08x %s %08x %s cw=%u ss=%u nr=%u,%u nw=%u,%u r=%u b=%u u=%u d=%u l=%x%s%s%s",
	    TP_printk("c=%p r=%08x %s q=%08x %s cw=%u ss=%u nr=%u,%u nw=%u,%u r=%u b=%u u=%u d=%u l=%x%s%s%s",
		      __entry->call,
		      __entry->ack_serial,
		      __print_symbolic(__entry->sum.ack_reason, rxrpc_ack_names),
+1 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ enum rxrpc_cmsg_type {
	RXRPC_EXCLUSIVE_CALL	= 10,	/* s-: Call should be on exclusive connection */
	RXRPC_UPGRADE_SERVICE	= 11,	/* s-: Request service upgrade for client call */
	RXRPC_TX_LENGTH		= 12,	/* s-: Total length of Tx data */
	RXRPC_SET_CALL_TIMEOUT	= 13,	/* s-: Set one or more call timeouts */
	RXRPC__SUPPORTED
};

+21 −2
Original line number Diff line number Diff line
@@ -285,6 +285,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
					   bool upgrade)
{
	struct rxrpc_conn_parameters cp;
	struct rxrpc_call_params p;
	struct rxrpc_call *call;
	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
	int ret;
@@ -302,6 +303,10 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
	if (key && !key->payload.data[0])
		key = NULL; /* a no-security key */

	memset(&p, 0, sizeof(p));
	p.user_call_ID = user_call_ID;
	p.tx_total_len = tx_total_len;

	memset(&cp, 0, sizeof(cp));
	cp.local		= rx->local;
	cp.key			= key;
@@ -309,8 +314,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
	cp.exclusive		= false;
	cp.upgrade		= upgrade;
	cp.service_id		= srx->srx_service;
	call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, tx_total_len,
				     gfp);
	call = rxrpc_new_client_call(rx, &cp, srx, &p, gfp);
	/* The socket has been unlocked. */
	if (!IS_ERR(call)) {
		call->notify_rx = notify_rx;
@@ -863,6 +867,19 @@ static int rxrpc_release_sock(struct sock *sk)
	sock_orphan(sk);
	sk->sk_shutdown = SHUTDOWN_MASK;

	/* We want to kill off all connections from a service socket
	 * as fast as possible because we can't share these; client
	 * sockets, on the other hand, can share an endpoint.
	 */
	switch (sk->sk_state) {
	case RXRPC_SERVER_BOUND:
	case RXRPC_SERVER_BOUND2:
	case RXRPC_SERVER_LISTENING:
	case RXRPC_SERVER_LISTEN_DISABLED:
		rx->local->service_closed = true;
		break;
	}

	spin_lock_bh(&sk->sk_receive_queue.lock);
	sk->sk_state = RXRPC_CLOSE;
	spin_unlock_bh(&sk->sk_receive_queue.lock);
@@ -878,6 +895,8 @@ static int rxrpc_release_sock(struct sock *sk)
	rxrpc_release_calls_on_socket(rx);
	flush_workqueue(rxrpc_workqueue);
	rxrpc_purge_queue(&sk->sk_receive_queue);
	rxrpc_queue_work(&rx->local->rxnet->service_conn_reaper);
	rxrpc_queue_work(&rx->local->rxnet->client_conn_reaper);

	rxrpc_put_local(rx->local);
	rx->local = NULL;
+85 −18
Original line number Diff line number Diff line
@@ -79,17 +79,20 @@ struct rxrpc_net {
	struct list_head	conn_proc_list;	/* List of conns in this namespace for proc */
	struct list_head	service_conns;	/* Service conns in this namespace */
	rwlock_t		conn_lock;	/* Lock for ->conn_proc_list, ->service_conns */
	struct delayed_work	service_conn_reaper;
	struct work_struct	service_conn_reaper;
	struct timer_list	service_conn_reap_timer;

	unsigned int		nr_client_conns;
	unsigned int		nr_active_client_conns;
	bool			kill_all_client_conns;
	bool			live;
	spinlock_t		client_conn_cache_lock; /* Lock for ->*_client_conns */
	spinlock_t		client_conn_discard_lock; /* Prevent multiple discarders */
	struct list_head	waiting_client_conns;
	struct list_head	active_client_conns;
	struct list_head	idle_client_conns;
	struct delayed_work	client_conn_reaper;
	struct work_struct	client_conn_reaper;
	struct timer_list	client_conn_reap_timer;

	struct list_head	local_endpoints;
	struct mutex		local_mutex;	/* Lock for ->local_endpoints */
@@ -265,6 +268,7 @@ struct rxrpc_local {
	rwlock_t		services_lock;	/* lock for services list */
	int			debug_id;	/* debug ID for printks */
	bool			dead;
	bool			service_closed;	/* Service socket closed */
	struct sockaddr_rxrpc	srx;		/* local address */
};

@@ -338,8 +342,17 @@ enum rxrpc_conn_flag {
	RXRPC_CONN_DONT_REUSE,		/* Don't reuse this connection */
	RXRPC_CONN_COUNTED,		/* Counted by rxrpc_nr_client_conns */
	RXRPC_CONN_PROBING_FOR_UPGRADE,	/* Probing for service upgrade */
	RXRPC_CONN_FINAL_ACK_0,		/* Need final ACK for channel 0 */
	RXRPC_CONN_FINAL_ACK_1,		/* Need final ACK for channel 1 */
	RXRPC_CONN_FINAL_ACK_2,		/* Need final ACK for channel 2 */
	RXRPC_CONN_FINAL_ACK_3,		/* Need final ACK for channel 3 */
};

#define RXRPC_CONN_FINAL_ACK_MASK ((1UL << RXRPC_CONN_FINAL_ACK_0) |	\
				   (1UL << RXRPC_CONN_FINAL_ACK_1) |	\
				   (1UL << RXRPC_CONN_FINAL_ACK_2) |	\
				   (1UL << RXRPC_CONN_FINAL_ACK_3))

/*
 * Events that can be raised upon a connection.
 */
@@ -393,6 +406,7 @@ struct rxrpc_connection {
#define RXRPC_ACTIVE_CHANS_MASK	((1 << RXRPC_MAXCALLS) - 1)
	struct list_head	waiting_calls;	/* Calls waiting for channels */
	struct rxrpc_channel {
		unsigned long		final_ack_at;	/* Time at which to issue final ACK */
		struct rxrpc_call __rcu	*call;		/* Active call */
		u32			call_id;	/* ID of current call */
		u32			call_counter;	/* Call ID counter */
@@ -404,6 +418,7 @@ struct rxrpc_connection {
		};
	} channels[RXRPC_MAXCALLS];

	struct timer_list	timer;		/* Conn event timer */
	struct work_struct	processor;	/* connection event processor */
	union {
		struct rb_node	client_node;	/* Node in local->client_conns */
@@ -457,9 +472,10 @@ enum rxrpc_call_flag {
enum rxrpc_call_event {
	RXRPC_CALL_EV_ACK,		/* need to generate ACK */
	RXRPC_CALL_EV_ABORT,		/* need to generate abort */
	RXRPC_CALL_EV_TIMER,		/* Timer expired */
	RXRPC_CALL_EV_RESEND,		/* Tx resend required */
	RXRPC_CALL_EV_PING,		/* Ping send required */
	RXRPC_CALL_EV_EXPIRED,		/* Expiry occurred */
	RXRPC_CALL_EV_ACK_LOST,		/* ACK may be lost, send ping */
};

/*
@@ -503,10 +519,16 @@ struct rxrpc_call {
	struct rxrpc_peer	*peer;		/* Peer record for remote address */
	struct rxrpc_sock __rcu	*socket;	/* socket responsible */
	struct mutex		user_mutex;	/* User access mutex */
	ktime_t			ack_at;		/* When deferred ACK needs to happen */
	ktime_t			resend_at;	/* When next resend needs to happen */
	ktime_t			ping_at;	/* When next to send a ping */
	ktime_t			expire_at;	/* When the call times out */
	unsigned long		ack_at;		/* When deferred ACK needs to happen */
	unsigned long		ack_lost_at;	/* When ACK is figured as lost */
	unsigned long		resend_at;	/* When next resend needs to happen */
	unsigned long		ping_at;	/* When next to send a ping */
	unsigned long		keepalive_at;	/* When next to send a keepalive ping */
	unsigned long		expect_rx_by;	/* When we expect to get a packet by */
	unsigned long		expect_req_by;	/* When we expect to get a request DATA packet by */
	unsigned long		expect_term_by;	/* When we expect call termination by */
	u32			next_rx_timo;	/* Timeout for next Rx packet (jif) */
	u32			next_req_timo;	/* Timeout for next Rx request packet (jif) */
	struct timer_list	timer;		/* Combined event timer */
	struct work_struct	processor;	/* Event processor */
	rxrpc_notify_rx_t	notify_rx;	/* kernel service Rx notification function */
@@ -609,6 +631,8 @@ struct rxrpc_call {
	ktime_t			acks_latest_ts;	/* Timestamp of latest ACK received */
	rxrpc_serial_t		acks_latest;	/* serial number of latest ACK received */
	rxrpc_seq_t		acks_lowest_nak; /* Lowest NACK in the buffer (or ==tx_hard_ack) */
	rxrpc_seq_t		acks_lost_top;	/* tx_top at the time lost-ack ping sent */
	rxrpc_serial_t		acks_lost_ping;	/* Serial number of probe ACK */
};

/*
@@ -632,6 +656,35 @@ struct rxrpc_ack_summary {
	u8			cumulative_acks;
};

/*
 * sendmsg() cmsg-specified parameters.
 */
enum rxrpc_command {
	RXRPC_CMD_SEND_DATA,		/* send data message */
	RXRPC_CMD_SEND_ABORT,		/* request abort generation */
	RXRPC_CMD_ACCEPT,		/* [server] accept incoming call */
	RXRPC_CMD_REJECT_BUSY,		/* [server] reject a call as busy */
};

struct rxrpc_call_params {
	s64			tx_total_len;	/* Total Tx data length (if send data) */
	unsigned long		user_call_ID;	/* User's call ID */
	struct {
		u32		hard;		/* Maximum lifetime (sec) */
		u32		idle;		/* Max time since last data packet (msec) */
		u32		normal;		/* Max time since last call packet (msec) */
	} timeouts;
	u8			nr_timeouts;	/* Number of timeouts specified */
};

struct rxrpc_send_params {
	struct rxrpc_call_params call;
	u32			abort_code;	/* Abort code to Tx (if abort) */
	enum rxrpc_command	command : 8;	/* The command to implement */
	bool			exclusive;	/* Shared or exclusive call */
	bool			upgrade;	/* If the connection is upgradeable */
};

#include <trace/events/rxrpc.h>

/*
@@ -657,12 +710,19 @@ int rxrpc_reject_call(struct rxrpc_sock *);
/*
 * call_event.c
 */
void __rxrpc_set_timer(struct rxrpc_call *, enum rxrpc_timer_trace, ktime_t);
void rxrpc_set_timer(struct rxrpc_call *, enum rxrpc_timer_trace, ktime_t);
void rxrpc_propose_ACK(struct rxrpc_call *, u8, u16, u32, bool, bool,
		       enum rxrpc_propose_ack_trace);
void rxrpc_process_call(struct work_struct *);

static inline void rxrpc_reduce_call_timer(struct rxrpc_call *call,
					   unsigned long expire_at,
					   unsigned long now,
					   enum rxrpc_timer_trace why)
{
	trace_rxrpc_timer(call, why, now);
	timer_reduce(&call->timer, expire_at);
}

/*
 * call_object.c
 */
@@ -672,11 +732,11 @@ extern unsigned int rxrpc_max_call_lifetime;
extern struct kmem_cache *rxrpc_call_jar;

struct rxrpc_call *rxrpc_find_call_by_user_ID(struct rxrpc_sock *, unsigned long);
struct rxrpc_call *rxrpc_alloc_call(gfp_t);
struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *, gfp_t);
struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *,
					 struct rxrpc_conn_parameters *,
					 struct sockaddr_rxrpc *,
					 unsigned long, s64, gfp_t);
					 struct rxrpc_call_params *, gfp_t);
int rxrpc_retry_client_call(struct rxrpc_sock *,
			    struct rxrpc_call *,
			    struct rxrpc_conn_parameters *,
@@ -803,8 +863,8 @@ static inline bool __rxrpc_abort_eproto(struct rxrpc_call *call,
 */
extern unsigned int rxrpc_max_client_connections;
extern unsigned int rxrpc_reap_client_connections;
extern unsigned int rxrpc_conn_idle_client_expiry;
extern unsigned int rxrpc_conn_idle_client_fast_expiry;
extern unsigned long rxrpc_conn_idle_client_expiry;
extern unsigned long rxrpc_conn_idle_client_fast_expiry;
extern struct idr rxrpc_client_conn_ids;

void rxrpc_destroy_client_conn_ids(void);
@@ -825,6 +885,7 @@ void rxrpc_process_connection(struct work_struct *);
 * conn_object.c
 */
extern unsigned int rxrpc_connection_expiry;
extern unsigned int rxrpc_closed_conn_expiry;

struct rxrpc_connection *rxrpc_alloc_connection(gfp_t);
struct rxrpc_connection *rxrpc_find_connection_rcu(struct rxrpc_local *,
@@ -861,6 +922,12 @@ static inline void rxrpc_put_connection(struct rxrpc_connection *conn)
		rxrpc_put_service_conn(conn);
}

static inline void rxrpc_reduce_conn_timer(struct rxrpc_connection *conn,
					   unsigned long expire_at)
{
	timer_reduce(&conn->timer, expire_at);
}

/*
 * conn_service.c
 */
@@ -930,13 +997,13 @@ static inline void rxrpc_queue_local(struct rxrpc_local *local)
 * misc.c
 */
extern unsigned int rxrpc_max_backlog __read_mostly;
extern unsigned int rxrpc_requested_ack_delay;
extern unsigned int rxrpc_soft_ack_delay;
extern unsigned int rxrpc_idle_ack_delay;
extern unsigned long rxrpc_requested_ack_delay;
extern unsigned long rxrpc_soft_ack_delay;
extern unsigned long rxrpc_idle_ack_delay;
extern unsigned int rxrpc_rx_window_size;
extern unsigned int rxrpc_rx_mtu;
extern unsigned int rxrpc_rx_jumbo_max;
extern unsigned int rxrpc_resend_timeout;
extern unsigned long rxrpc_resend_timeout;

extern const s8 rxrpc_ack_priority[];

@@ -954,7 +1021,7 @@ static inline struct rxrpc_net *rxrpc_net(struct net *net)
/*
 * output.c
 */
int rxrpc_send_ack_packet(struct rxrpc_call *, bool);
int rxrpc_send_ack_packet(struct rxrpc_call *, bool, rxrpc_serial_t *);
int rxrpc_send_abort_packet(struct rxrpc_call *);
int rxrpc_send_data_packet(struct rxrpc_call *, struct sk_buff *, bool);
void rxrpc_reject_packets(struct rxrpc_local *);
+1 −1
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
	/* Now it gets complicated, because calls get registered with the
	 * socket here, particularly if a user ID is preassigned by the user.
	 */
	call = rxrpc_alloc_call(gfp);
	call = rxrpc_alloc_call(rx, gfp);
	if (!call)
		return -ENOMEM;
	call->flags |= (1 << RXRPC_CALL_IS_SERVICE);
Loading