net/smc: reduce unnecessary blocking in smcr_lgr_reg_rmbs()
authorD. Wythe <alibuda@linux.alibaba.com>
Thu, 2 Feb 2023 08:26:41 +0000 (16:26 +0800)
committerDavid S. Miller <davem@davemloft.net>
Sat, 4 Feb 2023 09:48:19 +0000 (09:48 +0000)
Unlike smc_buf_create() and smcr_buf_unuse(), smcr_lgr_reg_rmbs() is
exclusive when assigned rmb_desc was not registered, although it can be
executed in parallel when assigned rmb_desc was registered already
and only performs read semtamics on it. Hence, we can not simply replace
it with read semaphore.

The idea here is that if the assigned rmb_desc was registered already,
use read semaphore to protect the critical section, once the assigned
rmb_desc was not registered, keep using keep write semaphore still
to keep its exclusivity.

Thanks to the reusable features of rmb_desc, which allows us to execute
in parallel in most cases.

Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/smc/af_smc.c

index 6e93ad61d6a229174f479e24282188298cef88a2..b163266e581ad38485e389d529cd437cc30fd7d8 100644 (file)
@@ -519,11 +519,26 @@ static int smcr_lgr_reg_rmbs(struct smc_link *link,
                             struct smc_buf_desc *rmb_desc)
 {
        struct smc_link_group *lgr = link->lgr;
+       bool do_slow = false;
        int i, rc = 0;
 
        rc = smc_llc_flow_initiate(lgr, SMC_LLC_FLOW_RKEY);
        if (rc)
                return rc;
+
+       down_read(&lgr->llc_conf_mutex);
+       for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
+               if (!smc_link_active(&lgr->lnk[i]))
+                       continue;
+               if (!rmb_desc->is_reg_mr[link->link_idx]) {
+                       up_read(&lgr->llc_conf_mutex);
+                       goto slow_path;
+               }
+       }
+       /* mr register already */
+       goto fast_path;
+slow_path:
+       do_slow = true;
        /* protect against parallel smc_llc_cli_rkey_exchange() and
         * parallel smcr_link_reg_buf()
         */
@@ -535,7 +550,7 @@ static int smcr_lgr_reg_rmbs(struct smc_link *link,
                if (rc)
                        goto out;
        }
-
+fast_path:
        /* exchange confirm_rkey msg with peer */
        rc = smc_llc_do_confirm_rkey(link, rmb_desc);
        if (rc) {
@@ -544,7 +559,7 @@ static int smcr_lgr_reg_rmbs(struct smc_link *link,
        }
        rmb_desc->is_conf_rkey = true;
 out:
-       up_write(&lgr->llc_conf_mutex);
+       do_slow ? up_write(&lgr->llc_conf_mutex) : up_read(&lgr->llc_conf_mutex);
        smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
        return rc;
 }