]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net/smc: mutex to protect the lgr against parallel reconfigurations
authorKarsten Graul <kgraul@linux.ibm.com>
Fri, 1 May 2020 10:48:05 +0000 (12:48 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 1 May 2020 23:20:04 +0000 (16:20 -0700)
Introduce llc_conf_mutex in the link group which is used to protect the
buffers and lgr states against parallel link reconfiguration.
This ensures that new connections do not start to register buffers with
the links of a link group when link creation or termination is running.

Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Reviewed-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/smc/af_smc.c
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_llc.c

index 20d6d3fbb86c5395a06d57e40859d2eabcc3ccba..6663a63be9e4cf008424cc99022086d179765a8c 100644 (file)
@@ -344,6 +344,13 @@ static int smcr_lgr_reg_rmbs(struct smc_link *link,
        struct smc_link_group *lgr = link->lgr;
        int i, rc = 0;
 
+       rc = smc_llc_flow_initiate(lgr, SMC_LLC_FLOW_RKEY);
+       if (rc)
+               return rc;
+       /* protect against parallel smc_llc_cli_rkey_exchange() and
+        * parallel smcr_link_reg_rmb()
+        */
+       mutex_lock(&lgr->llc_conf_mutex);
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
                if (lgr->lnk[i].state != SMC_LNK_ACTIVE)
                        continue;
@@ -360,6 +367,8 @@ static int smcr_lgr_reg_rmbs(struct smc_link *link,
        }
        rmb_desc->is_conf_rkey = true;
 out:
+       mutex_unlock(&lgr->llc_conf_mutex);
+       smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
        return rc;
 }
 
index c905675017c7ec4843748321687cc7b61c3f6ed0..4c3af05d76a5b578b04008952f83c7be08a691b4 100644 (file)
@@ -448,11 +448,21 @@ out:
 static void smcr_buf_unuse(struct smc_buf_desc *rmb_desc,
                           struct smc_link_group *lgr)
 {
+       int rc;
+
        if (rmb_desc->is_conf_rkey && !list_empty(&lgr->list)) {
                /* unregister rmb with peer */
-               smc_llc_do_delete_rkey(lgr, rmb_desc);
-               rmb_desc->is_conf_rkey = false;
+               rc = smc_llc_flow_initiate(lgr, SMC_LLC_FLOW_RKEY);
+               if (!rc) {
+                       /* protect against smc_llc_cli_rkey_exchange() */
+                       mutex_lock(&lgr->llc_conf_mutex);
+                       smc_llc_do_delete_rkey(lgr, rmb_desc);
+                       rmb_desc->is_conf_rkey = false;
+                       mutex_unlock(&lgr->llc_conf_mutex);
+                       smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
+               }
        }
+
        if (rmb_desc->is_reg_err) {
                /* buf registration failed, reuse not possible */
                mutex_lock(&lgr->rmbs_lock);
@@ -552,6 +562,7 @@ static void smcr_rtoken_clear_link(struct smc_link *lnk)
        }
 }
 
+/* must be called under lgr->llc_conf_mutex lock */
 void smcr_link_clear(struct smc_link *lnk)
 {
        struct smc_ib_device *smcibdev;
@@ -1170,7 +1181,9 @@ free_table:
        return rc;
 }
 
-/* register a new rmb on IB device */
+/* register a new rmb on IB device,
+ * must be called under lgr->llc_conf_mutex lock
+ */
 int smcr_link_reg_rmb(struct smc_link *link, struct smc_buf_desc *rmb_desc)
 {
        if (list_empty(&link->lgr->list))
@@ -1224,7 +1237,9 @@ int smcr_buf_map_lgr(struct smc_link *lnk)
        return 0;
 }
 
-/* register all used buffers of lgr for a new link */
+/* register all used buffers of lgr for a new link,
+ * must be called under lgr->llc_conf_mutex lock
+ */
 int smcr_buf_reg_lgr(struct smc_link *lnk)
 {
        struct smc_link_group *lgr = lnk->lgr;
@@ -1278,6 +1293,8 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr,
 {
        int i, rc = 0;
 
+       /* protect against parallel link reconfiguration */
+       mutex_lock(&lgr->llc_conf_mutex);
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
                struct smc_link *lnk = &lgr->lnk[i];
 
@@ -1289,6 +1306,7 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr,
                }
        }
 out:
+       mutex_unlock(&lgr->llc_conf_mutex);
        return rc;
 }
 
index 61ddb52649367a9b1264a7f2028953ebf2041344..aa198dd0f0e4dae3c93ab4232c71407fc22d0c46 100644 (file)
@@ -248,6 +248,8 @@ struct smc_link_group {
                                                /* queue for llc events */
                        spinlock_t              llc_event_q_lock;
                                                /* protects llc_event_q */
+                       struct mutex            llc_conf_mutex;
+                                               /* protects lgr reconfig. */
                        struct work_struct      llc_event_work;
                                                /* llc event worker */
                        wait_queue_head_t       llc_waiter;
index 171835926db6f67c5b032f2e02b87a036f8bfc71..ceed3c89926f4b292d9dc41bb0c991a5b066802f 100644 (file)
@@ -848,6 +848,7 @@ void smc_llc_lgr_init(struct smc_link_group *lgr, struct smc_sock *smc)
        spin_lock_init(&lgr->llc_event_q_lock);
        spin_lock_init(&lgr->llc_flow_lock);
        init_waitqueue_head(&lgr->llc_waiter);
+       mutex_init(&lgr->llc_conf_mutex);
        lgr->llc_testlink_time = net->ipv4.sysctl_tcp_keepalive_time;
 }
 
@@ -897,9 +898,6 @@ int smc_llc_do_confirm_rkey(struct smc_link *send_link,
        struct smc_llc_qentry *qentry = NULL;
        int rc = 0;
 
-       rc = smc_llc_flow_initiate(lgr, SMC_LLC_FLOW_RKEY);
-       if (rc)
-               return rc;
        rc = smc_llc_send_confirm_rkey(send_link, rmb_desc);
        if (rc)
                goto out;
@@ -911,7 +909,6 @@ int smc_llc_do_confirm_rkey(struct smc_link *send_link,
 out:
        if (qentry)
                smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
-       smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
        return rc;
 }
 
@@ -927,9 +924,6 @@ int smc_llc_do_delete_rkey(struct smc_link_group *lgr,
        if (!send_link)
                return -ENOLINK;
 
-       rc = smc_llc_flow_initiate(lgr, SMC_LLC_FLOW_RKEY);
-       if (rc)
-               return rc;
        /* protected by llc_flow control */
        rc = smc_llc_send_delete_rkey(send_link, rmb_desc);
        if (rc)
@@ -942,7 +936,6 @@ int smc_llc_do_delete_rkey(struct smc_link_group *lgr,
 out:
        if (qentry)
                smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
-       smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
        return rc;
 }