Skip to content

Commit

Permalink
Check for dead timer
Browse files Browse the repository at this point in the history
  • Loading branch information
dhowells committed Mar 25, 2022
1 parent 5409fb5 commit 1eba43e
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 8 deletions.
5 changes: 5 additions & 0 deletions include/linux/timer.h
Expand Up @@ -17,6 +17,9 @@ struct timer_list {
unsigned long expires;
void (*function)(struct timer_list *);
u32 flags;
unsigned long dead;
#define TIMER_NOT_DEAD 0xb9b9b9b9
#define TIMER_DEAD 0x5e5ee5e5

#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
Expand Down Expand Up @@ -77,6 +80,7 @@ struct timer_list {
.entry = { .next = TIMER_ENTRY_STATIC }, \
.function = (_function), \
.flags = (_flags), \
.dead = TIMER_NOT_DEAD, \
__TIMER_LOCKDEP_MAP_INITIALIZER( \
__FILE__ ":" __stringify(__LINE__)) \
}
Expand All @@ -91,6 +95,7 @@ struct timer_list {
void init_timer_key(struct timer_list *timer,
void (*func)(struct timer_list *), unsigned int flags,
const char *name, struct lock_class_key *key);
void mark_timer_dead(struct timer_list *timer);

#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
extern void init_timer_on_stack_key(struct timer_list *timer,
Expand Down
13 changes: 13 additions & 0 deletions kernel/time/timer.c
Expand Up @@ -791,12 +791,22 @@ static void do_init_timer(struct timer_list *timer,
{
timer->entry.pprev = NULL;
timer->function = func;
timer->dead = TIMER_NOT_DEAD;
if (WARN_ON_ONCE(flags & ~TIMER_INIT_FLAGS))
flags &= TIMER_INIT_FLAGS;
timer->flags = flags | raw_smp_processor_id();
lockdep_init_map(&timer->lockdep_map, name, key, 0);
}

void mark_timer_dead(struct timer_list *timer)
{
BUG_ON(timer_pending(timer));
if (xchg(&timer->dead, TIMER_DEAD) != TIMER_NOT_DEAD)
BUG();
BUG_ON(timer_pending(timer));
}
EXPORT_SYMBOL(mark_timer_dead);

/**
* init_timer_key - initialize a timer
* @timer: the timer to be initialized
Expand Down Expand Up @@ -965,6 +975,7 @@ __mod_timer(struct timer_list *timer, unsigned long expires, unsigned int option
int ret = 0;

BUG_ON(!timer->function);
BUG_ON(timer->dead != TIMER_NOT_DEAD);

/*
* This is a common optimization triggered by the networking code - if
Expand Down Expand Up @@ -1140,6 +1151,7 @@ EXPORT_SYMBOL(timer_reduce);
*/
void add_timer(struct timer_list *timer)
{
BUG_ON(timer->dead != TIMER_NOT_DEAD);
BUG_ON(timer_pending(timer));
__mod_timer(timer, timer->expires, MOD_TIMER_NOTPENDING);
}
Expand All @@ -1157,6 +1169,7 @@ void add_timer_on(struct timer_list *timer, int cpu)
struct timer_base *new_base, *base;
unsigned long flags;

BUG_ON(timer->dead != TIMER_NOT_DEAD);
BUG_ON(timer_pending(timer) || !timer->function);

new_base = get_timer_cpu_base(timer->flags, cpu);
Expand Down
2 changes: 1 addition & 1 deletion net/rxrpc/call_accept.c
Expand Up @@ -210,7 +210,7 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx)
list_del(&conn->link);
list_del(&conn->proc_link);
write_unlock(&rxnet->conn_lock);
BUG_ON(timer_pending(&conn->timer));
mark_timer_dead(&conn->timer);
kfree(conn);
if (atomic_dec_and_test(&rxnet->nr_conns))
wake_up_var(&rxnet->nr_conns);
Expand Down
4 changes: 2 additions & 2 deletions net/rxrpc/call_object.c
Expand Up @@ -164,7 +164,7 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp,
nomem_2:
kfree(call->rxtx_buffer);
nomem:
BUG_ON(timer_pending(&call->timer));
mark_timer_dead(&call->timer);
kmem_cache_free(rxrpc_call_jar, call);
return NULL;
}
Expand Down Expand Up @@ -623,7 +623,7 @@ static void rxrpc_destroy_call(struct work_struct *work)
rxrpc_put_peer(call->peer);
kfree(call->rxtx_buffer);
kfree(call->rxtx_annotations);
BUG_ON(timer_pending(&call->timer));
mark_timer_dead(&call->timer);
kmem_cache_free(rxrpc_call_jar, call);
if (atomic_dec_and_test(&rxnet->nr_calls))
wake_up_var(&rxnet->nr_calls);
Expand Down
2 changes: 1 addition & 1 deletion net/rxrpc/conn_client.c
Expand Up @@ -206,7 +206,7 @@ rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle, gfp_t gfp)
error_1:
rxrpc_put_client_connection_id(conn);
error_0:
BUG_ON(timer_pending(&conn->timer));
mark_timer_dead(&conn->timer);
kfree(conn);
_leave(" = %d", ret);
return ERR_PTR(ret);
Expand Down
2 changes: 1 addition & 1 deletion net/rxrpc/conn_object.c
Expand Up @@ -369,7 +369,7 @@ static void rxrpc_destroy_connection(struct rcu_head *rcu)
wake_up_var(&conn->params.local->rxnet->nr_conns);
rxrpc_put_local(conn->params.local);

BUG_ON(timer_pending(&conn->timer));
mark_timer_dead(&conn->timer);
kfree(conn);
_leave("");
}
Expand Down
6 changes: 3 additions & 3 deletions net/rxrpc/net_ns.c
Expand Up @@ -120,9 +120,9 @@ static __net_exit void rxrpc_exit_net(struct net *net)
rxrpc_destroy_all_peers(rxnet);
rxrpc_destroy_all_locals(rxnet);
proc_remove(rxnet->proc_net);
BUG_ON(timer_pending(&rxnet->service_conn_reap_timer));
BUG_ON(timer_pending(&rxnet->client_conn_reap_timer));
BUG_ON(timer_pending(&rxnet->peer_keepalive_timer));
mark_timer_dead(&rxnet->service_conn_reap_timer);
mark_timer_dead(&rxnet->client_conn_reap_timer);
mark_timer_dead(&rxnet->peer_keepalive_timer);
}

struct pernet_operations rxrpc_net_ops = {
Expand Down

0 comments on commit 1eba43e

Please sign in to comment.