diff options
author | NeilBrown <neilb@suse.com> | 2017-12-13 23:43:43 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-12-19 05:51:21 -0500 |
commit | a93639090a2743c8e205c1ac25439702702b4ce4 (patch) | |
tree | 49fd142fbfba7829ce0b0dbcee6b75942de3a575 | |
parent | 1291a0d5049dbc06baaaf66a9ff3f53db493b19b (diff) |
staging: lustre: lnet: Fix recent breakage from list_for_each conversion
Commit 8e55b6fd0660 ("staging: lustre: lnet: replace list_for_each
with list_for_each_entry") was intended to be an idempotent change,
but actually broke the behavior of ksocknal_add_peer() causing mounts to fail.
The fact that it caused an existing "route2 = NULL;" to become
redundant could have been a clue. The fact that the loop body
set the new loop variable to NULL might also have been a clue
The original code relied on "route2" being NULL if nothing was found.
The new code would always set route2 to a non-NULL value if the list
was empty, and would likely crash if the list was not empty.
Restore correct functionality by using code-flow rather the value of
"route2" to determine whether to use on old route, or to add a new one.
Fixes: 8e55b6fd0660 ("staging: lustre: lnet: replace list_for_each with list_for_each_entry")
Signed-off-by: NeilBrown <neilb@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c | 23 |
1 files changed, 10 insertions, 13 deletions
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index 986c2a40d978..8267119ccc8e 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c | |||
@@ -487,21 +487,18 @@ ksocknal_add_peer(struct lnet_ni *ni, struct lnet_process_id id, __u32 ipaddr, | |||
487 | ksocknal_nid2peerlist(id.nid)); | 487 | ksocknal_nid2peerlist(id.nid)); |
488 | } | 488 | } |
489 | 489 | ||
490 | route2 = NULL; | ||
491 | list_for_each_entry(route2, &peer->ksnp_routes, ksnr_list) { | 490 | list_for_each_entry(route2, &peer->ksnp_routes, ksnr_list) { |
492 | if (route2->ksnr_ipaddr == ipaddr) | 491 | if (route2->ksnr_ipaddr == ipaddr) { |
493 | break; | 492 | /* Route already exists, use the old one */ |
494 | 493 | ksocknal_route_decref(route); | |
495 | route2 = NULL; | 494 | route2->ksnr_share_count++; |
496 | } | 495 | goto out; |
497 | if (!route2) { | 496 | } |
498 | ksocknal_add_route_locked(peer, route); | ||
499 | route->ksnr_share_count++; | ||
500 | } else { | ||
501 | ksocknal_route_decref(route); | ||
502 | route2->ksnr_share_count++; | ||
503 | } | 497 | } |
504 | 498 | /* Route doesn't already exist, add the new one */ | |
499 | ksocknal_add_route_locked(peer, route); | ||
500 | route->ksnr_share_count++; | ||
501 | out: | ||
505 | write_unlock_bh(&ksocknal_data.ksnd_global_lock); | 502 | write_unlock_bh(&ksocknal_data.ksnd_global_lock); |
506 | 503 | ||
507 | return 0; | 504 | return 0; |