Whamcloud - gitweb
LU-9480 lnet: add the Push target 88/25788/23
authorOlaf Weber <olaf@sgi.com>
Tue, 28 Mar 2017 12:48:44 +0000 (14:48 +0200)
committerAmir Shehata <amir.shehata@intel.com>
Tue, 22 Aug 2017 16:26:23 +0000 (16:26 +0000)
Peer Discovery will send a Push message (same format as an
LNet Ping) to Multi-Rail capable peers to give the peer the
list of local interfaces.

Set up a target buffer for these pushes in the_lnet. The
size of this buffer defaults to LNET_MIN_INTERFACES, but it
is resized if required.

Test-Parameters: trivial
Signed-off-by: Olaf Weber <olaf@sgi.com>
Change-Id: I09b5ad8ae504ba8368d908539001fb8afc2c2778
Reviewed-on: https://review.whamcloud.com/25788
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/include/lnet/lib-lnet.h
lnet/include/lnet/lib-types.h
lnet/lnet/api-ni.c
lnet/lnet/peer.c

index 6725551..71039b2 100644 (file)
@@ -841,6 +841,14 @@ static inline int lnet_ping_buffer_numref(struct lnet_ping_buffer *pbuf)
        return atomic_read(&pbuf->pb_refcnt);
 }
 
+static inline int lnet_push_target_resize_needed(void)
+{
+       return the_lnet.ln_push_target->pb_nnis < the_lnet.ln_push_target_nnis;
+}
+
+int lnet_push_target_resize(void);
+void lnet_peer_push_event(struct lnet_event *ev);
+
 int lnet_parse_ip2nets(char **networksp, char *ip2nets);
 int lnet_parse_routes(char *route_str, int *im_a_router);
 int lnet_parse_networks(struct list_head *nilist, char *networks,
index 03cfe48..99408d3 100644 (file)
@@ -544,6 +544,18 @@ struct lnet_peer {
        /* peer state flags */
        unsigned                lp_state;
 
+       /* buffer for data pushed by peer */
+       struct lnet_ping_buffer *lp_data;
+
+       /* number of NIDs for sizing push data */
+       int                     lp_data_nnis;
+
+       /* NI config sequence number of peer */
+       __u32                   lp_peer_seqno;
+
+       /* Local NI config sequence number peer knows */
+       __u32                   lp_node_seqno;
+
        /* link on discovery-related lists */
        struct list_head        lp_dc_list;
 
@@ -900,6 +912,19 @@ typedef struct lnet {
        struct lnet_ping_buffer         *ln_ping_target;
        atomic_t                        ln_ping_target_seqno;
 
+       /*
+        * Push Target
+        *
+        * ln_push_nnis contains the desired size of the push target.
+        * The lnet_net_lock is used to handle update races. The old
+        * buffer may linger a while after it has been unlinked, in
+        * which case the event handler cleans up.
+        */
+       lnet_handle_eq_t                ln_push_target_eq;
+       lnet_handle_md_t                ln_push_target_md;
+       struct lnet_ping_buffer         *ln_push_target;
+       int                             ln_push_target_nnis;
+
        /* discovery event queue handle */
        lnet_handle_eq_t                ln_dc_eqh;
        /* discovery requests */
index f5acbc9..91e8621 100644 (file)
@@ -1334,6 +1334,148 @@ lnet_ping_target_fini(void)
        lnet_ping_target_destroy();
 }
 
+/* Resize the push target. */
+int lnet_push_target_resize(void)
+{
+       lnet_process_id_t id = { LNET_NID_ANY, LNET_PID_ANY };
+       lnet_md_t md = { NULL };
+       lnet_handle_me_t meh;
+       lnet_handle_md_t mdh;
+       lnet_handle_md_t old_mdh;
+       struct lnet_ping_buffer *pbuf;
+       struct lnet_ping_buffer *old_pbuf;
+       int nnis = the_lnet.ln_push_target_nnis;
+       int rc;
+
+       if (nnis <= 0) {
+               rc = -EINVAL;
+               goto fail_return;
+       }
+again:
+       pbuf = lnet_ping_buffer_alloc(nnis, GFP_NOFS);
+       if (!pbuf) {
+               rc = -ENOMEM;
+               goto fail_return;
+       }
+
+       rc = LNetMEAttach(LNET_RESERVED_PORTAL, id,
+                         LNET_PROTO_PING_MATCHBITS, 0,
+                         LNET_UNLINK, LNET_INS_AFTER,
+                         &meh);
+       if (rc) {
+               CERROR("Can't create push target ME: %d\n", rc);
+               goto fail_decref_pbuf;
+       }
+
+       /* initialize md content */
+       md.start     = &pbuf->pb_info;
+       md.length    = LNET_PING_INFO_SIZE(nnis);
+       md.threshold = LNET_MD_THRESH_INF;
+       md.max_size  = 0;
+       md.options   = LNET_MD_OP_PUT | LNET_MD_TRUNCATE |
+                      LNET_MD_MANAGE_REMOTE;
+       md.user_ptr  = pbuf;
+       md.eq_handle = the_lnet.ln_push_target_eq;
+
+       rc = LNetMDAttach(meh, md, LNET_RETAIN, &mdh);
+       if (rc) {
+               CERROR("Can't attach push MD: %d\n", rc);
+               goto fail_unlink_meh;
+       }
+       lnet_ping_buffer_addref(pbuf);
+
+       lnet_net_lock(LNET_LOCK_EX);
+       old_pbuf = the_lnet.ln_push_target;
+       old_mdh = the_lnet.ln_push_target_md;
+       the_lnet.ln_push_target = pbuf;
+       the_lnet.ln_push_target_md = mdh;
+       lnet_net_unlock(LNET_LOCK_EX);
+
+       if (old_pbuf) {
+               LNetMDUnlink(old_mdh);
+               lnet_ping_buffer_decref(old_pbuf);
+       }
+
+       if (nnis < the_lnet.ln_push_target_nnis)
+               goto again;
+
+       CDEBUG(D_NET, "nnis %d success\n", nnis);
+
+       return 0;
+
+fail_unlink_meh:
+       LNetMEUnlink(meh);
+fail_decref_pbuf:
+       lnet_ping_buffer_decref(pbuf);
+fail_return:
+       CDEBUG(D_NET, "nnis %d error %d\n", nnis, rc);
+       return rc;
+}
+
+static void lnet_push_target_event_handler(struct lnet_event *ev)
+{
+       struct lnet_ping_buffer *pbuf = ev->md.user_ptr;
+
+       if (pbuf->pb_info.pi_magic == __swab32(LNET_PROTO_PING_MAGIC))
+               lnet_swap_pinginfo(pbuf);
+
+       if (ev->unlinked)
+               lnet_ping_buffer_decref(pbuf);
+}
+
+/* Initialize the push target. */
+static int lnet_push_target_init(void)
+{
+       int rc;
+
+       if (the_lnet.ln_push_target)
+               return -EALREADY;
+
+       rc = LNetEQAlloc(0, lnet_push_target_event_handler,
+                        &the_lnet.ln_push_target_eq);
+       if (rc) {
+               CERROR("Can't allocated push target EQ: %d\n", rc);
+               return rc;
+       }
+
+       /* Start at the required minimum, we'll enlarge if required. */
+       the_lnet.ln_push_target_nnis = LNET_INTERFACES_MIN;
+
+       rc = lnet_push_target_resize();
+
+       if (rc) {
+               LNetEQFree(the_lnet.ln_push_target_eq);
+               LNetInvalidateEQHandle(&the_lnet.ln_push_target_eq);
+       }
+
+       return rc;
+}
+
+/* Clean up the push target. */
+static void lnet_push_target_fini(void)
+{
+       if (!the_lnet.ln_push_target)
+               return;
+
+       /* Unlink and invalidate to prevent new references. */
+       LNetMDUnlink(the_lnet.ln_push_target_md);
+       LNetInvalidateMDHandle(&the_lnet.ln_push_target_md);
+
+       /* Wait for the unlink to complete. */
+       while (lnet_ping_buffer_numref(the_lnet.ln_push_target) > 1) {
+               CDEBUG(D_NET, "Still waiting for ping data MD to unlink\n");
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(cfs_time_seconds(1));
+       }
+
+       lnet_ping_buffer_decref(the_lnet.ln_push_target);
+       the_lnet.ln_push_target = NULL;
+       the_lnet.ln_push_target_nnis = 0;
+
+       LNetEQFree(the_lnet.ln_push_target_eq);
+       LNetInvalidateEQHandle(&the_lnet.ln_push_target_eq);
+}
+
 static int
 lnet_ni_tq_credits(struct lnet_ni *ni)
 {
@@ -2011,10 +2153,14 @@ LNetNIInit(lnet_pid_t requested_pid)
        if (rc != 0)
                goto err_stop_ping;
 
-       rc = lnet_peer_discovery_start();
+       rc = lnet_push_target_init();
        if (rc != 0)
                goto err_stop_router_checker;
 
+       rc = lnet_peer_discovery_start();
+       if (rc != 0)
+               goto err_destroy_push_target;
+
        lnet_fault_init();
        lnet_proc_init();
 
@@ -2022,6 +2168,8 @@ LNetNIInit(lnet_pid_t requested_pid)
 
        return 0;
 
+err_destroy_push_target:
+       lnet_push_target_fini();
 err_stop_router_checker:
        lnet_router_checker_stop();
 err_stop_ping:
@@ -2074,6 +2222,7 @@ LNetNIFini()
 
                lnet_proc_fini();
                lnet_peer_discovery_stop();
+               lnet_push_target_fini();
                lnet_router_checker_stop();
                lnet_ping_target_fini();
 
index b2f73e9..0dbbf51 100644 (file)
@@ -1685,6 +1685,8 @@ static int lnet_peer_discovery_wait_for_work(void)
                                TASK_INTERRUPTIBLE);
                if (the_lnet.ln_dc_state == LNET_DC_STATE_STOPPING)
                        break;
+               if (lnet_push_target_resize_needed())
+                       break;
                if (!list_empty(&the_lnet.ln_dc_request))
                        break;
                lnet_net_unlock(cpt);
@@ -1716,6 +1718,9 @@ static int lnet_peer_discovery(void *arg)
                if (lnet_peer_discovery_wait_for_work())
                        break;
 
+               if (lnet_push_target_resize_needed())
+                       lnet_push_target_resize();
+
                lnet_net_lock(LNET_LOCK_EX);
                if (the_lnet.ln_dc_state == LNET_DC_STATE_STOPPING)
                        break;