Skip to content

Commit

Permalink
Merge tag 'rxrpc-next-20180330' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/dhowells/linux-fs

David Howells says:

====================
rxrpc: Fixes and more traces

Here are some patches that add some more tracepoints to AF_RXRPC and fix
some issues therein:

 (1) Fix the use of VERSION packets to keep firewall routes open.

 (2) Fix the incorrect current time usage in a tracepoint.

 (3) Fix Tx ring annotation corruption.

 (4) Fix accidental conversion of call-level abort into connection-level
     abort.

 (5) Fix calculation of resend time.

 (6) Remove a couple of unused variables.

 (7) Fix a bunch of checker warnings and an error.  Note that not all
     warnings can be quashed as checker doesn't seem to correctly handle
     seqlocks.

 (8) Fix a potential race between call destruction and socket/net
     destruction.

 (9) Add a tracepoint to track rxrpc_local refcounting.

(10) Fix an apparent leak of rxrpc_local objects.

(11) Add a tracepoint to track rxrpc_peer refcounting.

(12) Fix a leak of rxrpc_peer objects.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 1, 2018
2 parents 3be9b5f + 17226f1 commit e2e80c0
Show file tree
Hide file tree
Showing 20 changed files with 509 additions and 71 deletions.
85 changes: 85 additions & 0 deletions include/trace/events/rxrpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ enum rxrpc_skb_trace {
rxrpc_skb_tx_seen,
};

enum rxrpc_local_trace {
rxrpc_local_got,
rxrpc_local_new,
rxrpc_local_processing,
rxrpc_local_put,
rxrpc_local_queued,
};

enum rxrpc_peer_trace {
rxrpc_peer_got,
rxrpc_peer_new,
rxrpc_peer_processing,
rxrpc_peer_put,
rxrpc_peer_queued_error,
};

enum rxrpc_conn_trace {
rxrpc_conn_got,
rxrpc_conn_new_client,
Expand Down Expand Up @@ -215,6 +231,20 @@ enum rxrpc_congest_change {
EM(rxrpc_skb_tx_rotated, "Tx ROT") \
E_(rxrpc_skb_tx_seen, "Tx SEE")

#define rxrpc_local_traces \
EM(rxrpc_local_got, "GOT") \
EM(rxrpc_local_new, "NEW") \
EM(rxrpc_local_processing, "PRO") \
EM(rxrpc_local_put, "PUT") \
E_(rxrpc_local_queued, "QUE")

#define rxrpc_peer_traces \
EM(rxrpc_peer_got, "GOT") \
EM(rxrpc_peer_new, "NEW") \
EM(rxrpc_peer_processing, "PRO") \
EM(rxrpc_peer_put, "PUT") \
E_(rxrpc_peer_queued_error, "QER")

#define rxrpc_conn_traces \
EM(rxrpc_conn_got, "GOT") \
EM(rxrpc_conn_new_client, "NWc") \
Expand Down Expand Up @@ -416,6 +446,7 @@ enum rxrpc_congest_change {
#define E_(a, b) TRACE_DEFINE_ENUM(a);

rxrpc_skb_traces;
rxrpc_local_traces;
rxrpc_conn_traces;
rxrpc_client_traces;
rxrpc_call_traces;
Expand All @@ -439,6 +470,60 @@ rxrpc_congest_changes;
#define EM(a, b) { a, b },
#define E_(a, b) { a, b }

TRACE_EVENT(rxrpc_local,
TP_PROTO(struct rxrpc_local *local, enum rxrpc_local_trace op,
int usage, const void *where),

TP_ARGS(local, op, usage, where),

TP_STRUCT__entry(
__field(unsigned int, local )
__field(int, op )
__field(int, usage )
__field(const void *, where )
),

TP_fast_assign(
__entry->local = local->debug_id;
__entry->op = op;
__entry->usage = usage;
__entry->where = where;
),

TP_printk("L=%08x %s u=%d sp=%pSR",
__entry->local,
__print_symbolic(__entry->op, rxrpc_local_traces),
__entry->usage,
__entry->where)
);

TRACE_EVENT(rxrpc_peer,
TP_PROTO(struct rxrpc_peer *peer, enum rxrpc_peer_trace op,
int usage, const void *where),

TP_ARGS(peer, op, usage, where),

TP_STRUCT__entry(
__field(unsigned int, peer )
__field(int, op )
__field(int, usage )
__field(const void *, where )
),

TP_fast_assign(
__entry->peer = peer->debug_id;
__entry->op = op;
__entry->usage = usage;
__entry->where = where;
),

TP_printk("P=%08x %s u=%d sp=%pSR",
__entry->peer,
__print_symbolic(__entry->op, rxrpc_peer_traces),
__entry->usage,
__entry->where)
);

TRACE_EVENT(rxrpc_conn,
TP_PROTO(struct rxrpc_connection *conn, enum rxrpc_conn_trace op,
int usage, const void *where),
Expand Down
6 changes: 6 additions & 0 deletions net/rxrpc/af_rxrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
mutex_unlock(&call->user_mutex);
}

rxrpc_put_peer(cp.peer);
_leave(" = %p", call);
return call;
}
Expand Down Expand Up @@ -447,6 +448,7 @@ int rxrpc_kernel_retry_call(struct socket *sock, struct rxrpc_call *call,
ret = rxrpc_retry_client_call(rx, call, &cp, srx, GFP_KERNEL);

mutex_unlock(&call->user_mutex);
rxrpc_put_peer(cp.peer);
_leave(" = %d", ret);
return ret;
}
Expand Down Expand Up @@ -762,6 +764,7 @@ static __poll_t rxrpc_poll(struct file *file, struct socket *sock,
static int rxrpc_create(struct net *net, struct socket *sock, int protocol,
int kern)
{
struct rxrpc_net *rxnet;
struct rxrpc_sock *rx;
struct sock *sk;

Expand Down Expand Up @@ -801,6 +804,9 @@ static int rxrpc_create(struct net *net, struct socket *sock, int protocol,
rwlock_init(&rx->call_lock);
memset(&rx->srx, 0, sizeof(rx->srx));

rxnet = rxrpc_net(sock_net(&rx->sk));
timer_reduce(&rxnet->peer_keepalive_timer, jiffies + 1);

_leave(" = 0 [%p]", rx);
return 0;
}
Expand Down
68 changes: 25 additions & 43 deletions net/rxrpc/ar-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ struct rxrpc_net {
u32 epoch; /* Local epoch for detecting local-end reset */
struct list_head calls; /* List of calls active in this namespace */
rwlock_t call_lock; /* Lock for ->calls */
atomic_t nr_calls; /* Count of allocated calls */

atomic_t nr_conns;
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 */
Expand All @@ -97,8 +99,16 @@ struct rxrpc_net {
struct list_head local_endpoints;
struct mutex local_mutex; /* Lock for ->local_endpoints */

spinlock_t peer_hash_lock; /* Lock for ->peer_hash */
DECLARE_HASHTABLE (peer_hash, 10);
spinlock_t peer_hash_lock; /* Lock for ->peer_hash */

#define RXRPC_KEEPALIVE_TIME 20 /* NAT keepalive time in seconds */
u8 peer_keepalive_cursor;
ktime_t peer_keepalive_base;
struct hlist_head peer_keepalive[RXRPC_KEEPALIVE_TIME + 1];
struct hlist_head peer_keepalive_new;
struct timer_list peer_keepalive_timer;
struct work_struct peer_keepalive_work;
};

/*
Expand Down Expand Up @@ -285,6 +295,8 @@ struct rxrpc_peer {
struct hlist_head error_targets; /* targets for net error distribution */
struct work_struct error_distributor;
struct rb_root service_conns; /* Service connections */
struct hlist_node keepalive_link; /* Link in net->peer_keepalive[] */
time64_t last_tx_at; /* Last time packet sent here */
seqlock_t service_conn_lock;
spinlock_t lock; /* access lock */
unsigned int if_mtu; /* interface MTU for this peer */
Expand Down Expand Up @@ -518,6 +530,7 @@ struct rxrpc_call {
struct rxrpc_connection *conn; /* connection carrying call */
struct rxrpc_peer *peer; /* Peer record for remote address */
struct rxrpc_sock __rcu *socket; /* socket responsible */
struct rxrpc_net *rxnet; /* Network namespace to which call belongs */
struct mutex user_mutex; /* User access mutex */
unsigned long ack_at; /* When deferred ACK needs to happen */
unsigned long ack_lost_at; /* When ACK is figured as lost */
Expand Down Expand Up @@ -969,31 +982,12 @@ extern void rxrpc_process_local_events(struct rxrpc_local *);
* local_object.c
*/
struct rxrpc_local *rxrpc_lookup_local(struct net *, const struct sockaddr_rxrpc *);
void __rxrpc_put_local(struct rxrpc_local *);
struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *);
struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *);
void rxrpc_put_local(struct rxrpc_local *);
void rxrpc_queue_local(struct rxrpc_local *);
void rxrpc_destroy_all_locals(struct rxrpc_net *);

static inline void rxrpc_get_local(struct rxrpc_local *local)
{
atomic_inc(&local->usage);
}

static inline
struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
{
return atomic_inc_not_zero(&local->usage) ? local : NULL;
}

static inline void rxrpc_put_local(struct rxrpc_local *local)
{
if (local && atomic_dec_and_test(&local->usage))
__rxrpc_put_local(local);
}

static inline void rxrpc_queue_local(struct rxrpc_local *local)
{
rxrpc_queue_work(&local->processor);
}

/*
* misc.c
*/
Expand Down Expand Up @@ -1026,6 +1020,7 @@ 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 *);
void rxrpc_send_keepalive(struct rxrpc_peer *);

/*
* peer_event.c
Expand All @@ -1034,6 +1029,7 @@ void rxrpc_error_report(struct sock *);
void rxrpc_peer_error_distributor(struct work_struct *);
void rxrpc_peer_add_rtt(struct rxrpc_call *, enum rxrpc_rtt_rx_trace,
rxrpc_serial_t, rxrpc_serial_t, ktime_t, ktime_t);
void rxrpc_peer_keepalive_worker(struct work_struct *);

/*
* peer_object.c
Expand All @@ -1045,25 +1041,11 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *,
struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t);
struct rxrpc_peer *rxrpc_lookup_incoming_peer(struct rxrpc_local *,
struct rxrpc_peer *);

static inline struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer)
{
atomic_inc(&peer->usage);
return peer;
}

static inline
struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *peer)
{
return atomic_inc_not_zero(&peer->usage) ? peer : NULL;
}

extern void __rxrpc_put_peer(struct rxrpc_peer *peer);
static inline void rxrpc_put_peer(struct rxrpc_peer *peer)
{
if (peer && atomic_dec_and_test(&peer->usage))
__rxrpc_put_peer(peer);
}
void rxrpc_destroy_all_peers(struct rxrpc_net *);
struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *);
struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *);
void rxrpc_put_peer(struct rxrpc_peer *);
void __rxrpc_queue_peer_error(struct rxrpc_peer *);

/*
* proc.c
Expand Down
9 changes: 6 additions & 3 deletions net/rxrpc/call_accept.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,

write_unlock(&rx->call_lock);

rxnet = call->rxnet;
write_lock(&rxnet->call_lock);
list_add_tail(&call->link, &rxnet->calls);
write_unlock(&rxnet->call_lock);
Expand Down Expand Up @@ -218,14 +219,16 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx)
list_del(&conn->proc_link);
write_unlock(&rxnet->conn_lock);
kfree(conn);
if (atomic_dec_and_test(&rxnet->nr_conns))
wake_up_atomic_t(&rxnet->nr_conns);
tail = (tail + 1) & (size - 1);
}

head = b->call_backlog_head;
tail = b->call_backlog_tail;
while (CIRC_CNT(head, tail, size) > 0) {
struct rxrpc_call *call = b->call_backlog[tail];
call->socket = rx;
rcu_assign_pointer(call->socket, rx);
if (rx->discard_new_call) {
_debug("discard %lx", call->user_call_ID);
rx->discard_new_call(call, call->user_call_ID);
Expand Down Expand Up @@ -295,8 +298,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
b->conn_backlog[conn_tail] = NULL;
smp_store_release(&b->conn_backlog_tail,
(conn_tail + 1) & (RXRPC_BACKLOG_MAX - 1));
rxrpc_get_local(local);
conn->params.local = local;
conn->params.local = rxrpc_get_local(local);
conn->params.peer = peer;
rxrpc_see_connection(conn);
rxrpc_new_incoming_connection(rx, conn, skb);
Expand Down Expand Up @@ -456,6 +458,7 @@ struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *rx,
unsigned long user_call_ID,
rxrpc_notify_rx_t notify_rx)
__releases(&rx->sk.sk_lock.slock)
__acquires(call->user_mutex)
{
struct rxrpc_call *call;
struct rb_node *parent, **pp;
Expand Down
4 changes: 2 additions & 2 deletions net/rxrpc/call_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
ktime_to_ns(ktime_sub(skb->tstamp, max_age)));
}

resend_at = nsecs_to_jiffies(ktime_to_ns(ktime_sub(oldest, now)));
resend_at = nsecs_to_jiffies(ktime_to_ns(ktime_sub(now, oldest)));
resend_at += jiffies + rxrpc_resend_timeout;
WRITE_ONCE(call->resend_at, resend_at);

Expand All @@ -238,7 +238,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
* retransmitting data.
*/
if (!retrans) {
rxrpc_reduce_call_timer(call, resend_at, now,
rxrpc_reduce_call_timer(call, resend_at, now_j,
rxrpc_timer_set_for_resend);
spin_unlock_bh(&call->lock);
ack_ts = ktime_sub(now, call->acks_latest_ts);
Expand Down
Loading

0 comments on commit e2e80c0

Please sign in to comment.