Commit d5500667 authored by Karsten Graul's avatar Karsten Graul Committed by David S. Miller

net/smc: mutex to protect the lgr against parallel reconfigurations

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: default avatarKarsten Graul <kgraul@linux.ibm.com>
Reviewed-by: default avatarUrsula Braun <ubraun@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fbed3b37
...@@ -344,6 +344,13 @@ static int smcr_lgr_reg_rmbs(struct smc_link *link, ...@@ -344,6 +344,13 @@ static int smcr_lgr_reg_rmbs(struct smc_link *link,
struct smc_link_group *lgr = link->lgr; struct smc_link_group *lgr = link->lgr;
int i, rc = 0; 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++) { for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
if (lgr->lnk[i].state != SMC_LNK_ACTIVE) if (lgr->lnk[i].state != SMC_LNK_ACTIVE)
continue; continue;
...@@ -360,6 +367,8 @@ static int smcr_lgr_reg_rmbs(struct smc_link *link, ...@@ -360,6 +367,8 @@ static int smcr_lgr_reg_rmbs(struct smc_link *link,
} }
rmb_desc->is_conf_rkey = true; rmb_desc->is_conf_rkey = true;
out: out:
mutex_unlock(&lgr->llc_conf_mutex);
smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
return rc; return rc;
} }
......
...@@ -448,11 +448,21 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini) ...@@ -448,11 +448,21 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
static void smcr_buf_unuse(struct smc_buf_desc *rmb_desc, static void smcr_buf_unuse(struct smc_buf_desc *rmb_desc,
struct smc_link_group *lgr) struct smc_link_group *lgr)
{ {
int rc;
if (rmb_desc->is_conf_rkey && !list_empty(&lgr->list)) { if (rmb_desc->is_conf_rkey && !list_empty(&lgr->list)) {
/* unregister rmb with peer */ /* unregister rmb with peer */
smc_llc_do_delete_rkey(lgr, rmb_desc); rc = smc_llc_flow_initiate(lgr, SMC_LLC_FLOW_RKEY);
rmb_desc->is_conf_rkey = false; 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) { if (rmb_desc->is_reg_err) {
/* buf registration failed, reuse not possible */ /* buf registration failed, reuse not possible */
mutex_lock(&lgr->rmbs_lock); mutex_lock(&lgr->rmbs_lock);
...@@ -552,6 +562,7 @@ static void smcr_rtoken_clear_link(struct smc_link *lnk) ...@@ -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) void smcr_link_clear(struct smc_link *lnk)
{ {
struct smc_ib_device *smcibdev; struct smc_ib_device *smcibdev;
...@@ -1170,7 +1181,9 @@ static int smcr_buf_map_link(struct smc_buf_desc *buf_desc, bool is_rmb, ...@@ -1170,7 +1181,9 @@ static int smcr_buf_map_link(struct smc_buf_desc *buf_desc, bool is_rmb,
return rc; 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) int smcr_link_reg_rmb(struct smc_link *link, struct smc_buf_desc *rmb_desc)
{ {
if (list_empty(&link->lgr->list)) if (list_empty(&link->lgr->list))
...@@ -1224,7 +1237,9 @@ int smcr_buf_map_lgr(struct smc_link *lnk) ...@@ -1224,7 +1237,9 @@ int smcr_buf_map_lgr(struct smc_link *lnk)
return 0; 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) int smcr_buf_reg_lgr(struct smc_link *lnk)
{ {
struct smc_link_group *lgr = lnk->lgr; struct smc_link_group *lgr = lnk->lgr;
...@@ -1278,6 +1293,8 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr, ...@@ -1278,6 +1293,8 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr,
{ {
int i, rc = 0; 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++) { for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
struct smc_link *lnk = &lgr->lnk[i]; struct smc_link *lnk = &lgr->lnk[i];
...@@ -1289,6 +1306,7 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr, ...@@ -1289,6 +1306,7 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr,
} }
} }
out: out:
mutex_unlock(&lgr->llc_conf_mutex);
return rc; return rc;
} }
......
...@@ -248,6 +248,8 @@ struct smc_link_group { ...@@ -248,6 +248,8 @@ struct smc_link_group {
/* queue for llc events */ /* queue for llc events */
spinlock_t llc_event_q_lock; spinlock_t llc_event_q_lock;
/* protects llc_event_q */ /* protects llc_event_q */
struct mutex llc_conf_mutex;
/* protects lgr reconfig. */
struct work_struct llc_event_work; struct work_struct llc_event_work;
/* llc event worker */ /* llc event worker */
wait_queue_head_t llc_waiter; wait_queue_head_t llc_waiter;
......
...@@ -848,6 +848,7 @@ void smc_llc_lgr_init(struct smc_link_group *lgr, struct smc_sock *smc) ...@@ -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_event_q_lock);
spin_lock_init(&lgr->llc_flow_lock); spin_lock_init(&lgr->llc_flow_lock);
init_waitqueue_head(&lgr->llc_waiter); init_waitqueue_head(&lgr->llc_waiter);
mutex_init(&lgr->llc_conf_mutex);
lgr->llc_testlink_time = net->ipv4.sysctl_tcp_keepalive_time; 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, ...@@ -897,9 +898,6 @@ int smc_llc_do_confirm_rkey(struct smc_link *send_link,
struct smc_llc_qentry *qentry = NULL; struct smc_llc_qentry *qentry = NULL;
int rc = 0; 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); rc = smc_llc_send_confirm_rkey(send_link, rmb_desc);
if (rc) if (rc)
goto out; goto out;
...@@ -911,7 +909,6 @@ int smc_llc_do_confirm_rkey(struct smc_link *send_link, ...@@ -911,7 +909,6 @@ int smc_llc_do_confirm_rkey(struct smc_link *send_link,
out: out:
if (qentry) if (qentry)
smc_llc_flow_qentry_del(&lgr->llc_flow_lcl); smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
return rc; return rc;
} }
...@@ -927,9 +924,6 @@ int smc_llc_do_delete_rkey(struct smc_link_group *lgr, ...@@ -927,9 +924,6 @@ int smc_llc_do_delete_rkey(struct smc_link_group *lgr,
if (!send_link) if (!send_link)
return -ENOLINK; return -ENOLINK;
rc = smc_llc_flow_initiate(lgr, SMC_LLC_FLOW_RKEY);
if (rc)
return rc;
/* protected by llc_flow control */ /* protected by llc_flow control */
rc = smc_llc_send_delete_rkey(send_link, rmb_desc); rc = smc_llc_send_delete_rkey(send_link, rmb_desc);
if (rc) if (rc)
...@@ -942,7 +936,6 @@ int smc_llc_do_delete_rkey(struct smc_link_group *lgr, ...@@ -942,7 +936,6 @@ int smc_llc_do_delete_rkey(struct smc_link_group *lgr,
out: out:
if (qentry) if (qentry)
smc_llc_flow_qentry_del(&lgr->llc_flow_lcl); smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
return rc; return rc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment