Skip to content

Commit b8ded9d

Browse files
karstengrdavem330
authored andcommitted
net/smc: pre-fetch send buffer outside of send_lock
Pre-fetch send buffer for the CDC validation message before entering the send_lock. Without that the send call might fail with -EBUSY because there are no free buffers and waiting for buffers is not possible under send_lock. Signed-off-by: Karsten Graul <[email protected]> Reviewed-by: Ursula Braun <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b86a372 commit b8ded9d

File tree

3 files changed

+21
-11
lines changed

3 files changed

+21
-11
lines changed

net/smc/smc_cdc.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,19 +116,15 @@ int smc_cdc_msg_send(struct smc_connection *conn,
116116
}
117117

118118
/* send a validation msg indicating the move of a conn to an other QP link */
119-
int smcr_cdc_msg_send_validation(struct smc_connection *conn)
119+
int smcr_cdc_msg_send_validation(struct smc_connection *conn,
120+
struct smc_cdc_tx_pend *pend,
121+
struct smc_wr_buf *wr_buf)
120122
{
121123
struct smc_host_cdc_msg *local = &conn->local_tx_ctrl;
122124
struct smc_link *link = conn->lnk;
123-
struct smc_cdc_tx_pend *pend;
124-
struct smc_wr_buf *wr_buf;
125125
struct smc_cdc_msg *peer;
126126
int rc;
127127

128-
rc = smc_cdc_get_free_slot(conn, link, &wr_buf, NULL, &pend);
129-
if (rc)
130-
return rc;
131-
132128
peer = (struct smc_cdc_msg *)wr_buf;
133129
peer->common.type = local->common.type;
134130
peer->len = local->len;

net/smc/smc_cdc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,9 @@ int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf,
296296
struct smc_cdc_tx_pend *pend);
297297
int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn);
298298
int smcd_cdc_msg_send(struct smc_connection *conn);
299-
int smcr_cdc_msg_send_validation(struct smc_connection *conn);
299+
int smcr_cdc_msg_send_validation(struct smc_connection *conn,
300+
struct smc_cdc_tx_pend *pend,
301+
struct smc_wr_buf *wr_buf);
300302
int smc_cdc_init(void) __init;
301303
void smcd_cdc_rx_init(struct smc_connection *conn);
302304

net/smc/smc_core.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,8 @@ static int smc_write_space(struct smc_connection *conn)
483483
return space;
484484
}
485485

486-
static int smc_switch_cursor(struct smc_sock *smc)
486+
static int smc_switch_cursor(struct smc_sock *smc, struct smc_cdc_tx_pend *pend,
487+
struct smc_wr_buf *wr_buf)
487488
{
488489
struct smc_connection *conn = &smc->conn;
489490
union smc_host_cursor cons, fin;
@@ -520,11 +521,14 @@ static int smc_switch_cursor(struct smc_sock *smc)
520521

521522
if (smc->sk.sk_state != SMC_INIT &&
522523
smc->sk.sk_state != SMC_CLOSED) {
523-
rc = smcr_cdc_msg_send_validation(conn);
524+
rc = smcr_cdc_msg_send_validation(conn, pend, wr_buf);
524525
if (!rc) {
525526
schedule_delayed_work(&conn->tx_work, 0);
526527
smc->sk.sk_data_ready(&smc->sk);
527528
}
529+
} else {
530+
smc_wr_tx_put_slot(conn->lnk,
531+
(struct smc_wr_tx_pend_priv *)pend);
528532
}
529533
return rc;
530534
}
@@ -533,7 +537,9 @@ struct smc_link *smc_switch_conns(struct smc_link_group *lgr,
533537
struct smc_link *from_lnk, bool is_dev_err)
534538
{
535539
struct smc_link *to_lnk = NULL;
540+
struct smc_cdc_tx_pend *pend;
536541
struct smc_connection *conn;
542+
struct smc_wr_buf *wr_buf;
537543
struct smc_sock *smc;
538544
struct rb_node *node;
539545
int i, rc = 0;
@@ -582,10 +588,16 @@ struct smc_link *smc_switch_conns(struct smc_link_group *lgr,
582588
}
583589
sock_hold(&smc->sk);
584590
read_unlock_bh(&lgr->conns_lock);
591+
/* pre-fetch buffer outside of send_lock, might sleep */
592+
rc = smc_cdc_get_free_slot(conn, to_lnk, &wr_buf, NULL, &pend);
593+
if (rc) {
594+
smcr_link_down_cond_sched(to_lnk);
595+
return NULL;
596+
}
585597
/* avoid race with smcr_tx_sndbuf_nonempty() */
586598
spin_lock_bh(&conn->send_lock);
587599
conn->lnk = to_lnk;
588-
rc = smc_switch_cursor(smc);
600+
rc = smc_switch_cursor(smc, pend, wr_buf);
589601
spin_unlock_bh(&conn->send_lock);
590602
sock_put(&smc->sk);
591603
if (rc) {

0 commit comments

Comments
 (0)