Whamcloud - gitweb
LU-9480 lnet: refactor lnet_del_peer_ni() 79/25779/23
authorOlaf Weber <olaf@sgi.com>
Fri, 27 Jan 2017 15:23:51 +0000 (16:23 +0100)
committerAmir Shehata <amir.shehata@intel.com>
Tue, 22 Aug 2017 16:23:16 +0000 (16:23 +0000)
Refactor lnet_del_peer_ni(). In particular break out the code
that removes an lnet_peer_ni from an lnet_peer and put it into
a separate function, lnet_peer_del_nid().

Test-Parameters: trivial
Signed-off-by: Olaf Weber <olaf@sgi.com>
Change-Id: Id5988b308afb093f83cc2e7029d3f2961171c906
Reviewed-on: https://review.whamcloud.com/25779
Reviewed-by: Olaf Weber <olaf.weber@hpe.com>
Reviewed-by: Amir Shehata <amir.shehata@intel.com>
Tested-by: Amir Shehata <amir.shehata@intel.com>
lnet/lnet/peer.c

index 7afcf6e..4b3568b 100644 (file)
@@ -287,7 +287,7 @@ lnet_peer_ni_del_locked(struct lnet_peer_ni *lpni)
         *
         * The last reference may be lost in a place where the
         * lnet_net_lock locks only a single cpt, and that cpt may not
-        * be lpni->lpni_cpt. So the zombie list of this peer_table
+        * be lpni->lpni_cpt. So the zombie list of lnet_peer_table
         * has its own lock.
         */
        spin_lock(&ptable->pt_zombie_lock);
@@ -338,6 +338,61 @@ lnet_peer_del_locked(struct lnet_peer *peer)
        return rc2;
 }
 
+static int
+lnet_peer_del(struct lnet_peer *peer)
+{
+       lnet_net_lock(LNET_LOCK_EX);
+       lnet_peer_del_locked(peer);
+       lnet_net_unlock(LNET_LOCK_EX);
+
+       return 0;
+}
+
+/*
+ * Delete a NID from a peer.
+ * Implements a few sanity checks.
+ * Call with ln_api_mutex held.
+ */
+static int
+lnet_peer_del_nid(struct lnet_peer *lp, lnet_nid_t nid)
+{
+       struct lnet_peer *lp2;
+       struct lnet_peer_ni *lpni;
+
+       lpni = lnet_find_peer_ni_locked(nid);
+       if (!lpni) {
+               CERROR("Cannot remove unknown nid %s from peer %s\n",
+                      libcfs_nid2str(nid),
+                      libcfs_nid2str(lp->lp_primary_nid));
+               return -ENOENT;
+       }
+       lnet_peer_ni_decref_locked(lpni);
+       lp2 = lpni->lpni_peer_net->lpn_peer;
+       if (lp2 != lp) {
+               CERROR("Nid %s is attached to peer %s, not peer %s\n",
+                      libcfs_nid2str(nid),
+                      libcfs_nid2str(lp2->lp_primary_nid),
+                      libcfs_nid2str(lp->lp_primary_nid));
+               return -EINVAL;
+       }
+
+       /*
+        * This function only allows deletion of the primary NID if it
+        * is the only NID.
+        */
+       if (nid == lp->lp_primary_nid && lnet_get_num_peer_nis(lp) != 1) {
+               CERROR("Cannot delete primary NID %s from multi-NID peer\n",
+                      libcfs_nid2str(nid));
+               return -EINVAL;
+       }
+
+       lnet_net_lock(LNET_LOCK_EX);
+       lnet_peer_ni_del_locked(lpni);
+       lnet_net_unlock(LNET_LOCK_EX);
+
+       return 0;
+}
+
 static void
 lnet_peer_table_cleanup_locked(struct lnet_net *net,
                               struct lnet_peer_table *ptable)
@@ -932,45 +987,36 @@ lnet_add_peer_ni(lnet_nid_t prim_nid, lnet_nid_t nid, bool mr)
  *   Delete a NI from a peer if both prim_nid and nid are provided.
  *   Delete a peer if only prim_nid is provided.
  *   Delete a peer if its primary nid is provided.
+ *
+ * The caller must hold ln_api_mutex. This prevents the peer from
+ * being modified/deleted by a different thread.
  */
 int
 lnet_del_peer_ni(lnet_nid_t prim_nid, lnet_nid_t nid)
 {
-       lnet_nid_t local_nid;
-       struct lnet_peer *peer;
+       struct lnet_peer *lp;
        struct lnet_peer_ni *lpni;
-       int rc;
 
        if (prim_nid == LNET_NID_ANY)
                return -EINVAL;
 
-       local_nid = (nid != LNET_NID_ANY) ? nid : prim_nid;
-
-       lpni = lnet_find_peer_ni_locked(local_nid);
+       lpni = lnet_find_peer_ni_locked(prim_nid);
        if (!lpni)
-               return -EINVAL;
+               return -ENOENT;
        lnet_peer_ni_decref_locked(lpni);
+       lp = lpni->lpni_peer_net->lpn_peer;
 
-       peer = lpni->lpni_peer_net->lpn_peer;
-       LASSERT(peer != NULL);
-
-       if (peer->lp_primary_nid == lpni->lpni_nid) {
-               /*
-                * deleting the primary ni is equivalent to deleting the
-                * entire peer
-                */
-               lnet_net_lock(LNET_LOCK_EX);
-               rc = lnet_peer_del_locked(peer);
-               lnet_net_unlock(LNET_LOCK_EX);
-
-               return rc;
+       if (prim_nid != lp->lp_primary_nid) {
+               CDEBUG(D_NET, "prim_nid %s is not primary for peer %s\n",
+                      libcfs_nid2str(prim_nid),
+                      libcfs_nid2str(lp->lp_primary_nid));
+               return -ENODEV;
        }
 
-       lnet_net_lock(LNET_LOCK_EX);
-       rc = lnet_peer_ni_del_locked(lpni);
-       lnet_net_unlock(LNET_LOCK_EX);
+       if (nid == LNET_NID_ANY || nid == lp->lp_primary_nid)
+               return lnet_peer_del(lp);
 
-       return rc;
+       return lnet_peer_del_nid(lp, nid);
 }
 
 void