staging: lustre: lnet: Fix recent breakage from list_for_each conversion
authorNeilBrown <neilb@suse.com>
Thu, 14 Dec 2017 04:43:43 +0000 (15:43 +1100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 19 Dec 2017 10:51:21 +0000 (11:51 +0100)
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>
drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c

index 986c2a4..8267119 100644 (file)
@@ -487,21 +487,18 @@ ksocknal_add_peer(struct lnet_ni *ni, struct lnet_process_id id, __u32 ipaddr,
                              ksocknal_nid2peerlist(id.nid));
        }
 
-       route2 = NULL;
        list_for_each_entry(route2, &peer->ksnp_routes, ksnr_list) {
-               if (route2->ksnr_ipaddr == ipaddr)
-                       break;
-
-               route2 = NULL;
-       }
-       if (!route2) {
-               ksocknal_add_route_locked(peer, route);
-               route->ksnr_share_count++;
-       } else {
-               ksocknal_route_decref(route);
-               route2->ksnr_share_count++;
+               if (route2->ksnr_ipaddr == ipaddr) {
+                       /* Route already exists, use the old one */
+                       ksocknal_route_decref(route);
+                       route2->ksnr_share_count++;
+                       goto out;
+               }
        }
-
+       /* Route doesn't already exist, add the new one */
+       ksocknal_add_route_locked(peer, route);
+       route->ksnr_share_count++;
+out:
        write_unlock_bh(&ksocknal_data.ksnd_global_lock);
 
        return 0;