diff options
author | Tom Herbert <tom@quantonium.net> | 2017-10-20 19:40:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-10-24 21:37:11 -0400 |
commit | 829385f08ae99740276cbd46c9db29764c519211 (patch) | |
tree | a95d023c7d12186bd605660c93841df05086e65c | |
parent | 864f5af3a3525f588391cd230cb8129ad758708e (diff) |
strparser: Use delayed work instead of timer for msg timeout
Sock lock may be taken in the message timer function which is a
problem since timers run in BH. Instead of timers use delayed_work.
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
Fixes: bbb03029a899 ("strparser: Generalize strparser")
Signed-off-by: Tom Herbert <tom@quantonium.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/strparser.h | 3 | ||||
-rw-r--r-- | net/strparser/strparser.c | 17 |
2 files changed, 9 insertions, 11 deletions
diff --git a/include/net/strparser.h b/include/net/strparser.h index 7dc131d62ad5..d96b59f45eba 100644 --- a/include/net/strparser.h +++ b/include/net/strparser.h | |||
@@ -74,10 +74,9 @@ struct strparser { | |||
74 | u32 unrecov_intr : 1; | 74 | u32 unrecov_intr : 1; |
75 | 75 | ||
76 | struct sk_buff **skb_nextp; | 76 | struct sk_buff **skb_nextp; |
77 | struct timer_list msg_timer; | ||
78 | struct sk_buff *skb_head; | 77 | struct sk_buff *skb_head; |
79 | unsigned int need_bytes; | 78 | unsigned int need_bytes; |
80 | struct delayed_work delayed_work; | 79 | struct delayed_work msg_timer_work; |
81 | struct work_struct work; | 80 | struct work_struct work; |
82 | struct strp_stats stats; | 81 | struct strp_stats stats; |
83 | struct strp_callbacks cb; | 82 | struct strp_callbacks cb; |
diff --git a/net/strparser/strparser.c b/net/strparser/strparser.c index d4ea46a5f233..c5fda15ba319 100644 --- a/net/strparser/strparser.c +++ b/net/strparser/strparser.c | |||
@@ -49,7 +49,7 @@ static void strp_abort_strp(struct strparser *strp, int err) | |||
49 | { | 49 | { |
50 | /* Unrecoverable error in receive */ | 50 | /* Unrecoverable error in receive */ |
51 | 51 | ||
52 | del_timer(&strp->msg_timer); | 52 | cancel_delayed_work(&strp->msg_timer_work); |
53 | 53 | ||
54 | if (strp->stopped) | 54 | if (strp->stopped) |
55 | return; | 55 | return; |
@@ -68,7 +68,7 @@ static void strp_abort_strp(struct strparser *strp, int err) | |||
68 | static void strp_start_timer(struct strparser *strp, long timeo) | 68 | static void strp_start_timer(struct strparser *strp, long timeo) |
69 | { | 69 | { |
70 | if (timeo) | 70 | if (timeo) |
71 | mod_timer(&strp->msg_timer, timeo); | 71 | mod_delayed_work(strp_wq, &strp->msg_timer_work, timeo); |
72 | } | 72 | } |
73 | 73 | ||
74 | /* Lower lock held */ | 74 | /* Lower lock held */ |
@@ -319,7 +319,7 @@ static int __strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb, | |||
319 | eaten += (cand_len - extra); | 319 | eaten += (cand_len - extra); |
320 | 320 | ||
321 | /* Hurray, we have a new message! */ | 321 | /* Hurray, we have a new message! */ |
322 | del_timer(&strp->msg_timer); | 322 | cancel_delayed_work(&strp->msg_timer_work); |
323 | strp->skb_head = NULL; | 323 | strp->skb_head = NULL; |
324 | STRP_STATS_INCR(strp->stats.msgs); | 324 | STRP_STATS_INCR(strp->stats.msgs); |
325 | 325 | ||
@@ -450,9 +450,10 @@ static void strp_work(struct work_struct *w) | |||
450 | do_strp_work(container_of(w, struct strparser, work)); | 450 | do_strp_work(container_of(w, struct strparser, work)); |
451 | } | 451 | } |
452 | 452 | ||
453 | static void strp_msg_timeout(unsigned long arg) | 453 | static void strp_msg_timeout(struct work_struct *w) |
454 | { | 454 | { |
455 | struct strparser *strp = (struct strparser *)arg; | 455 | struct strparser *strp = container_of(w, struct strparser, |
456 | msg_timer_work.work); | ||
456 | 457 | ||
457 | /* Message assembly timed out */ | 458 | /* Message assembly timed out */ |
458 | STRP_STATS_INCR(strp->stats.msg_timeouts); | 459 | STRP_STATS_INCR(strp->stats.msg_timeouts); |
@@ -505,9 +506,7 @@ int strp_init(struct strparser *strp, struct sock *sk, | |||
505 | strp->cb.read_sock_done = cb->read_sock_done ? : default_read_sock_done; | 506 | strp->cb.read_sock_done = cb->read_sock_done ? : default_read_sock_done; |
506 | strp->cb.abort_parser = cb->abort_parser ? : strp_abort_strp; | 507 | strp->cb.abort_parser = cb->abort_parser ? : strp_abort_strp; |
507 | 508 | ||
508 | setup_timer(&strp->msg_timer, strp_msg_timeout, | 509 | INIT_DELAYED_WORK(&strp->msg_timer_work, strp_msg_timeout); |
509 | (unsigned long)strp); | ||
510 | |||
511 | INIT_WORK(&strp->work, strp_work); | 510 | INIT_WORK(&strp->work, strp_work); |
512 | 511 | ||
513 | return 0; | 512 | return 0; |
@@ -532,7 +531,7 @@ void strp_done(struct strparser *strp) | |||
532 | { | 531 | { |
533 | WARN_ON(!strp->stopped); | 532 | WARN_ON(!strp->stopped); |
534 | 533 | ||
535 | del_timer_sync(&strp->msg_timer); | 534 | cancel_delayed_work_sync(&strp->msg_timer_work); |
536 | cancel_work_sync(&strp->work); | 535 | cancel_work_sync(&strp->work); |
537 | 536 | ||
538 | if (strp->skb_head) { | 537 | if (strp->skb_head) { |