* [PATCH net] inet: frags: better deal with smp races
@ 2018-11-08 6:10 Eric Dumazet
2018-11-09 1:02 ` David Miller
0 siblings, 1 reply; 3+ messages in thread
From: Eric Dumazet @ 2018-11-08 6:10 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Eric Dumazet, Eric Dumazet, 배석진
Multiple cpus might attempt to insert a new fragment in rhashtable,
if for example RPS is buggy, as reported by 배석진in
https://patchwork.ozlabs.org/patch/994601/
We use rhashtable_lookup_get_insert_key() instead of
rhashtable_insert_fast() to let cpus losing the race
free their own inet_frag_queue and use the one that
was inserted by another cpu.
Fixes: 648700f76b03 ("inet: frags: use rhashtables for reassembly units")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: 배석진 <soukjin.bae@samsung.com>
---
net/ipv4/inet_fragment.c | 29 +++++++++++++++--------------
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index bcb11f3a27c0c34115af05034a5a20f57842eb0a..ced9abd4bec6cd494e352c1d6a97da8f67cf6073 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -178,21 +178,22 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,
}
static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf,
- void *arg)
+ void *arg,
+ struct inet_frag_queue **prev)
{
struct inet_frags *f = nf->f;
struct inet_frag_queue *q;
- int err;
q = inet_frag_alloc(nf, f, arg);
- if (!q)
+ if (!q) {
+ *prev = ERR_PTR(-ENOMEM);
return NULL;
-
+ }
mod_timer(&q->timer, jiffies + nf->timeout);
- err = rhashtable_insert_fast(&nf->rhashtable, &q->node,
- f->rhash_params);
- if (err < 0) {
+ *prev = rhashtable_lookup_get_insert_key(&nf->rhashtable, &q->key,
+ &q->node, f->rhash_params);
+ if (*prev) {
q->flags |= INET_FRAG_COMPLETE;
inet_frag_kill(q);
inet_frag_destroy(q);
@@ -204,22 +205,22 @@ static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf,
/* TODO : call from rcu_read_lock() and no longer use refcount_inc_not_zero() */
struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, void *key)
{
- struct inet_frag_queue *fq;
+ struct inet_frag_queue *fq, *prev;
if (!nf->high_thresh || frag_mem_limit(nf) > nf->high_thresh)
return NULL;
rcu_read_lock();
- fq = rhashtable_lookup(&nf->rhashtable, key, nf->f->rhash_params);
- if (fq) {
+ prev = rhashtable_lookup(&nf->rhashtable, key, nf->f->rhash_params);
+ if (!prev)
+ fq = inet_frag_create(nf, key, &prev);
+ if (prev && !IS_ERR(prev)) {
+ fq = prev;
if (!refcount_inc_not_zero(&fq->refcnt))
fq = NULL;
- rcu_read_unlock();
- return fq;
}
rcu_read_unlock();
-
- return inet_frag_create(nf, key);
+ return fq;
}
EXPORT_SYMBOL(inet_frag_find);
--
2.19.1.930.g4563a0d9d0-goog
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH net] inet: frags: better deal with smp races
2018-11-08 6:10 [PATCH net] inet: frags: better deal with smp races Eric Dumazet
@ 2018-11-09 1:02 ` David Miller
2018-11-09 1:31 ` Eric Dumazet
0 siblings, 1 reply; 3+ messages in thread
From: David Miller @ 2018-11-09 1:02 UTC (permalink / raw)
To: edumazet; +Cc: netdev, eric.dumazet, soukjin.bae
From: Eric Dumazet <edumazet@google.com>
Date: Wed, 7 Nov 2018 22:10:53 -0800
> @@ -204,22 +205,22 @@ static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf,
> /* TODO : call from rcu_read_lock() and no longer use refcount_inc_not_zero() */
> struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, void *key)
> {
> - struct inet_frag_queue *fq;
> + struct inet_frag_queue *fq, *prev;
>
> if (!nf->high_thresh || frag_mem_limit(nf) > nf->high_thresh)
> return NULL;
>
> rcu_read_lock();
>
> - fq = rhashtable_lookup(&nf->rhashtable, key, nf->f->rhash_params);
> - if (fq) {
> + prev = rhashtable_lookup(&nf->rhashtable, key, nf->f->rhash_params);
> + if (!prev)
> + fq = inet_frag_create(nf, key, &prev);
> + if (prev && !IS_ERR(prev)) {
> + fq = prev;
> if (!refcount_inc_not_zero(&fq->refcnt))
> fq = NULL;
> - rcu_read_unlock();
> - return fq;
> }
> rcu_read_unlock();
> -
> - return inet_frag_create(nf, key);
> + return fq;
GCC is unwilling to see that all paths leading to that final return
statement do in fact set 'fq' one way or another:
net/ipv4/inet_fragment.c: In function ‘inet_frag_find’:
net/ipv4/inet_fragment.c:224:9: warning: ‘fq’ may be used uninitialized in this function [-Wmaybe-uninitialized]
This is with:
gcc (GCC) 8.2.1 20181011 (Red Hat 8.2.1-4)
Please adjust your patch so that the warning is eliminated.
Thanks.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net] inet: frags: better deal with smp races
2018-11-09 1:02 ` David Miller
@ 2018-11-09 1:31 ` Eric Dumazet
0 siblings, 0 replies; 3+ messages in thread
From: Eric Dumazet @ 2018-11-09 1:31 UTC (permalink / raw)
To: David Miller, edumazet; +Cc: netdev, eric.dumazet, soukjin.bae
On 11/08/2018 05:02 PM, David Miller wrote:
> GCC is unwilling to see that all paths leading to that final return
> statement do in fact set 'fq' one way or another:
>
> net/ipv4/inet_fragment.c: In function ‘inet_frag_find’:
> net/ipv4/inet_fragment.c:224:9: warning: ‘fq’ may be used uninitialized in this function [-Wmaybe-uninitialized]
>
> This is with:
>
> gcc (GCC) 8.2.1 20181011 (Red Hat 8.2.1-4)
>
> Please adjust your patch so that the warning is eliminated.
>
Interesting, I will init *fq to NULL in v2, thanks.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-11-09 11:10 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-11-08 6:10 [PATCH net] inet: frags: better deal with smp races Eric Dumazet
2018-11-09 1:02 ` David Miller
2018-11-09 1:31 ` Eric Dumazet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).