diff options
author | Xin Long <lucien.xin@gmail.com> | 2016-04-14 03:35:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-04-15 17:29:37 -0400 |
commit | 53fa10369c45a51947f06e8b622d2fa2cc64fda1 (patch) | |
tree | d8a03375bdd9433670e8d16db957462a480c83fa | |
parent | b5e2f4e6998a2b999da8fa0290b692f0bd85c8b7 (diff) |
sctp: fix some rhashtable functions using in sctp proc/diag
When rhashtable_walk_init return err, no release function should be
called, and when rhashtable_walk_start return err, we should only invoke
rhashtable_walk_exit to release the source.
But now when sctp_transport_walk_start return err, we just call
rhashtable_walk_stop/exit, and never care about if rhashtable_walk_init
or start return err, which is so bad.
We will fix it by calling rhashtable_walk_exit if rhashtable_walk_start
return err in sctp_transport_walk_start, and if sctp_transport_walk_start
return err, we do not need to call sctp_transport_walk_stop any more.
For sctp proc, we will use 'iter->start_fail' to decide if we will call
rhashtable_walk_stop/exit.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/sctp/proc.c | 7 | ||||
-rw-r--r-- | net/sctp/socket.c | 15 |
2 files changed, 16 insertions, 6 deletions
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 9fe139368ad7..4cb5aedfe3ee 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -280,6 +280,7 @@ void sctp_eps_proc_exit(struct net *net) | |||
280 | struct sctp_ht_iter { | 280 | struct sctp_ht_iter { |
281 | struct seq_net_private p; | 281 | struct seq_net_private p; |
282 | struct rhashtable_iter hti; | 282 | struct rhashtable_iter hti; |
283 | int start_fail; | ||
283 | }; | 284 | }; |
284 | 285 | ||
285 | static void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos) | 286 | static void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos) |
@@ -287,8 +288,10 @@ static void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos) | |||
287 | struct sctp_ht_iter *iter = seq->private; | 288 | struct sctp_ht_iter *iter = seq->private; |
288 | int err = sctp_transport_walk_start(&iter->hti); | 289 | int err = sctp_transport_walk_start(&iter->hti); |
289 | 290 | ||
290 | if (err) | 291 | if (err) { |
292 | iter->start_fail = 1; | ||
291 | return ERR_PTR(err); | 293 | return ERR_PTR(err); |
294 | } | ||
292 | 295 | ||
293 | return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos); | 296 | return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos); |
294 | } | 297 | } |
@@ -297,6 +300,8 @@ static void sctp_transport_seq_stop(struct seq_file *seq, void *v) | |||
297 | { | 300 | { |
298 | struct sctp_ht_iter *iter = seq->private; | 301 | struct sctp_ht_iter *iter = seq->private; |
299 | 302 | ||
303 | if (iter->start_fail) | ||
304 | return; | ||
300 | sctp_transport_walk_stop(&iter->hti); | 305 | sctp_transport_walk_stop(&iter->hti); |
301 | } | 306 | } |
302 | 307 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5e5bc08d2b25..777d0324594a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -4299,8 +4299,12 @@ int sctp_transport_walk_start(struct rhashtable_iter *iter) | |||
4299 | return err; | 4299 | return err; |
4300 | 4300 | ||
4301 | err = rhashtable_walk_start(iter); | 4301 | err = rhashtable_walk_start(iter); |
4302 | if (err && err != -EAGAIN) { | ||
4303 | rhashtable_walk_exit(iter); | ||
4304 | return err; | ||
4305 | } | ||
4302 | 4306 | ||
4303 | return err == -EAGAIN ? 0 : err; | 4307 | return 0; |
4304 | } | 4308 | } |
4305 | 4309 | ||
4306 | void sctp_transport_walk_stop(struct rhashtable_iter *iter) | 4310 | void sctp_transport_walk_stop(struct rhashtable_iter *iter) |
@@ -4389,11 +4393,12 @@ EXPORT_SYMBOL_GPL(sctp_transport_lookup_process); | |||
4389 | int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), | 4393 | int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), |
4390 | struct net *net, int pos, void *p) { | 4394 | struct net *net, int pos, void *p) { |
4391 | struct rhashtable_iter hti; | 4395 | struct rhashtable_iter hti; |
4392 | int err = 0; | ||
4393 | void *obj; | 4396 | void *obj; |
4397 | int err; | ||
4394 | 4398 | ||
4395 | if (sctp_transport_walk_start(&hti)) | 4399 | err = sctp_transport_walk_start(&hti); |
4396 | goto out; | 4400 | if (err) |
4401 | return err; | ||
4397 | 4402 | ||
4398 | sctp_transport_get_idx(net, &hti, pos); | 4403 | sctp_transport_get_idx(net, &hti, pos); |
4399 | obj = sctp_transport_get_next(net, &hti); | 4404 | obj = sctp_transport_get_next(net, &hti); |
@@ -4407,8 +4412,8 @@ int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), | |||
4407 | if (err) | 4412 | if (err) |
4408 | break; | 4413 | break; |
4409 | } | 4414 | } |
4410 | out: | ||
4411 | sctp_transport_walk_stop(&hti); | 4415 | sctp_transport_walk_stop(&hti); |
4416 | |||
4412 | return err; | 4417 | return err; |
4413 | } | 4418 | } |
4414 | EXPORT_SYMBOL_GPL(sctp_for_each_transport); | 4419 | EXPORT_SYMBOL_GPL(sctp_for_each_transport); |