diff options
author | Eric Dumazet <edumazet@google.com> | 2013-12-20 13:04:18 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-12-20 17:06:27 -0500 |
commit | dcd76081340da2f262a8c8efade200cc7554a3b9 (patch) | |
tree | bc7529f7af81514dc4d4e8d5440719e87212e99c /net/sched | |
parent | 568a153a22d8f338a5ebda70e6bd139f6d8bb2c3 (diff) |
net_sched: fix a regression in tcf_proto_lookup_ops()
list_for_each_entry(t, &tcf_proto_base, head) doesn't
exit with t = NULL if we reached the end of the list.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Fixes: 3627287463b4 ("net_sched: convert tcf_proto_ops to use struct
list_head")
Cc: Cong Wang <xiyou.wangcong@gmail.com>
Reviewed-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/cls_api.c | 22 |
1 files changed, 10 insertions, 12 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 6b085cf27a65..12e882ef596b 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -40,20 +40,20 @@ static DEFINE_RWLOCK(cls_mod_lock); | |||
40 | 40 | ||
41 | static const struct tcf_proto_ops *tcf_proto_lookup_ops(struct nlattr *kind) | 41 | static const struct tcf_proto_ops *tcf_proto_lookup_ops(struct nlattr *kind) |
42 | { | 42 | { |
43 | const struct tcf_proto_ops *t = NULL; | 43 | const struct tcf_proto_ops *t, *res = NULL; |
44 | 44 | ||
45 | if (kind) { | 45 | if (kind) { |
46 | read_lock(&cls_mod_lock); | 46 | read_lock(&cls_mod_lock); |
47 | list_for_each_entry(t, &tcf_proto_base, head) { | 47 | list_for_each_entry(t, &tcf_proto_base, head) { |
48 | if (nla_strcmp(kind, t->kind) == 0) { | 48 | if (nla_strcmp(kind, t->kind) == 0) { |
49 | if (!try_module_get(t->owner)) | 49 | if (try_module_get(t->owner)) |
50 | t = NULL; | 50 | res = t; |
51 | break; | 51 | break; |
52 | } | 52 | } |
53 | } | 53 | } |
54 | read_unlock(&cls_mod_lock); | 54 | read_unlock(&cls_mod_lock); |
55 | } | 55 | } |
56 | return t; | 56 | return res; |
57 | } | 57 | } |
58 | 58 | ||
59 | /* Register(unregister) new classifier type */ | 59 | /* Register(unregister) new classifier type */ |
@@ -82,15 +82,13 @@ int unregister_tcf_proto_ops(struct tcf_proto_ops *ops) | |||
82 | int rc = -ENOENT; | 82 | int rc = -ENOENT; |
83 | 83 | ||
84 | write_lock(&cls_mod_lock); | 84 | write_lock(&cls_mod_lock); |
85 | list_for_each_entry(t, &tcf_proto_base, head) | 85 | list_for_each_entry(t, &tcf_proto_base, head) { |
86 | if (t == ops) | 86 | if (t == ops) { |
87 | list_del(&t->head); | ||
88 | rc = 0; | ||
87 | break; | 89 | break; |
88 | 90 | } | |
89 | if (!t) | 91 | } |
90 | goto out; | ||
91 | list_del(&t->head); | ||
92 | rc = 0; | ||
93 | out: | ||
94 | write_unlock(&cls_mod_lock); | 92 | write_unlock(&cls_mod_lock); |
95 | return rc; | 93 | return rc; |
96 | } | 94 | } |