Commit b0c4b041 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'smc-next'



Ursula Braun says:

====================
net/smc: patches 2018-11-22

here are more patches for SMC:
* patches 1-3 and 7 are cleanups without functional change
* patches 4-6 and 8 are optimizations of existing code
* patches 9 and 10 introduce and exploit LLC message DELETE RKEY
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e4a3e9ff c7674c00
Loading
Loading
Loading
Loading
+26 −25
Original line number Diff line number Diff line
@@ -299,15 +299,18 @@ static void smc_copy_sock_settings_to_smc(struct smc_sock *smc)
	smc_copy_sock_settings(&smc->sk, smc->clcsock->sk, SK_FLAGS_CLC_TO_SMC);
}

/* register a new rmb, optionally send confirm_rkey msg to register with peer */
/* register a new rmb, send confirm_rkey msg to register with peer */
static int smc_reg_rmb(struct smc_link *link, struct smc_buf_desc *rmb_desc,
		       bool conf_rkey)
{
	if (!rmb_desc->wr_reg) {
		/* register memory region for new rmb */
		if (smc_wr_reg_send(link, rmb_desc->mr_rx[SMC_SINGLE_LINK])) {
			rmb_desc->regerr = 1;
			return -EFAULT;
		}
		rmb_desc->wr_reg = 1;
	}
	if (!conf_rkey)
		return 0;
	/* exchange confirm_rkey msg with peer */
@@ -335,8 +338,8 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc)
		struct smc_clc_msg_decline dclc;

		rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
				      SMC_CLC_DECLINE);
		return rc;
				      SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
		return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc;
	}

	if (link->llc_confirm_rc)
@@ -363,8 +366,8 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc)
		struct smc_clc_msg_decline dclc;

		rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
				      SMC_CLC_DECLINE);
		return rc;
				      SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
		return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_AL : rc;
	}

	/* send add link reject message, only one link supported for now */
@@ -533,7 +536,8 @@ static int smc_connect_clc(struct smc_sock *smc, int smc_type,
	if (rc)
		return rc;
	/* receive SMC Accept CLC message */
	return smc_clc_wait_msg(smc, aclc, sizeof(*aclc), SMC_CLC_ACCEPT);
	return smc_clc_wait_msg(smc, aclc, sizeof(*aclc), SMC_CLC_ACCEPT,
				CLC_WAIT_TIME);
}

/* setup for RDMA connection of client */
@@ -580,8 +584,7 @@ static int smc_connect_rdma(struct smc_sock *smc,
			return smc_connect_abort(smc, SMC_CLC_DECL_ERR_RDYLNK,
						 local_contact);
	} else {
		if (!smc->conn.rmb_desc->reused &&
		    smc_reg_rmb(link, smc->conn.rmb_desc, true))
		if (smc_reg_rmb(link, smc->conn.rmb_desc, true))
			return smc_connect_abort(smc, SMC_CLC_DECL_ERR_REGRMB,
						 local_contact);
	}
@@ -965,8 +968,8 @@ static int smc_serv_conf_first_link(struct smc_sock *smc)
		struct smc_clc_msg_decline dclc;

		rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
				      SMC_CLC_DECLINE);
		return rc;
				      SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
		return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc;
	}

	if (link->llc_confirm_resp_rc)
@@ -986,8 +989,8 @@ static int smc_serv_conf_first_link(struct smc_sock *smc)
		struct smc_clc_msg_decline dclc;

		rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
				      SMC_CLC_DECLINE);
		return rc;
				      SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
		return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_AL : rc;
	}

	smc_llc_link_active(link, net->ipv4.sysctl_tcp_keepalive_time);
@@ -1142,11 +1145,9 @@ static int smc_listen_rdma_reg(struct smc_sock *new_smc, int local_contact)
	struct smc_link *link = &new_smc->conn.lgr->lnk[SMC_SINGLE_LINK];

	if (local_contact != SMC_FIRST_CONTACT) {
		if (!new_smc->conn.rmb_desc->reused) {
		if (smc_reg_rmb(link, new_smc->conn.rmb_desc, true))
			return SMC_CLC_DECL_ERR_REGRMB;
	}
	}
	smc_rmb_sync_sg_for_device(&new_smc->conn);

	return 0;
@@ -1181,7 +1182,6 @@ static int smc_listen_rdma_finish(struct smc_sock *new_smc,
	return 0;

decline:
	mutex_unlock(&smc_create_lgr_pending);
	smc_listen_decline(new_smc, reason_code, local_contact);
	return reason_code;
}
@@ -1222,7 +1222,7 @@ static void smc_listen_work(struct work_struct *work)
	 */
	pclc = (struct smc_clc_msg_proposal *)&buf;
	reason_code = smc_clc_wait_msg(new_smc, pclc, SMC_CLC_MAX_LEN,
				       SMC_CLC_PROPOSAL);
				       SMC_CLC_PROPOSAL, CLC_WAIT_TIME);
	if (reason_code) {
		smc_listen_decline(new_smc, reason_code, 0);
		return;
@@ -1272,7 +1272,7 @@ static void smc_listen_work(struct work_struct *work)

	/* receive SMC Confirm CLC message */
	reason_code = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc),
				       SMC_CLC_CONFIRM);
				       SMC_CLC_CONFIRM, CLC_WAIT_TIME);
	if (reason_code) {
		mutex_unlock(&smc_create_lgr_pending);
		smc_listen_decline(new_smc, reason_code, local_contact);
@@ -1281,9 +1281,11 @@ static void smc_listen_work(struct work_struct *work)

	/* finish worker */
	if (!ism_supported) {
		if (smc_listen_rdma_finish(new_smc, &cclc, local_contact))
		if (smc_listen_rdma_finish(new_smc, &cclc, local_contact)) {
			mutex_unlock(&smc_create_lgr_pending);
			return;
		}
	}
	smc_conn_save_peer_info(new_smc, &cclc);
	mutex_unlock(&smc_create_lgr_pending);
	smc_listen_out_connected(new_smc);
@@ -1354,7 +1356,6 @@ static int smc_listen(struct socket *sock, int backlog)
	sk->sk_max_ack_backlog = backlog;
	sk->sk_ack_backlog = 0;
	sk->sk_state = SMC_LISTEN;
	INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work);
	sock_hold(sk); /* sock_hold in tcp_listen_worker */
	if (!schedule_work(&smc->tcp_listen_work))
		sock_put(sk);
+15 −18
Original line number Diff line number Diff line
@@ -265,7 +265,7 @@ out:
 * clcsock error, -EINTR, -ECONNRESET, -EPROTO otherwise.
 */
int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
		     u8 expected_type)
		     u8 expected_type, unsigned long timeout)
{
	long rcvtimeo = smc->clcsock->sk->sk_rcvtimeo;
	struct sock *clc_sk = smc->clcsock->sk;
@@ -285,7 +285,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
	 * sizeof(struct smc_clc_msg_hdr)
	 */
	krflags = MSG_PEEK | MSG_WAITALL;
	smc->clcsock->sk->sk_rcvtimeo = CLC_WAIT_TIME;
	clc_sk->sk_rcvtimeo = timeout;
	iov_iter_kvec(&msg.msg_iter, READ, &vec, 1,
			sizeof(struct smc_clc_msg_hdr));
	len = sock_recvmsg(smc->clcsock, &msg, krflags);
@@ -297,6 +297,10 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
	}
	if (clc_sk->sk_err) {
		reason_code = -clc_sk->sk_err;
		if (clc_sk->sk_err == EAGAIN &&
		    expected_type == SMC_CLC_DECLINE)
			clc_sk->sk_err = 0; /* reset for fallback usage */
		else
			smc->sk.sk_err = clc_sk->sk_err;
		goto out;
	}
@@ -306,6 +310,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
		goto out;
	}
	if (len < 0) {
		if (len != -EAGAIN || expected_type != SMC_CLC_DECLINE)
			smc->sk.sk_err = -len;
		reason_code = len;
		goto out;
@@ -346,7 +351,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
	}

out:
	smc->clcsock->sk->sk_rcvtimeo = rcvtimeo;
	clc_sk->sk_rcvtimeo = rcvtimeo;
	return reason_code;
}

@@ -374,10 +379,8 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
	len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1,
			     sizeof(struct smc_clc_msg_decline));
	if (len < sizeof(struct smc_clc_msg_decline))
		smc->sk.sk_err = EPROTO;
	if (len < 0)
		smc->sk.sk_err = -len;
	return sock_error(&smc->sk);
		len = -EPROTO;
	return len > 0 ? 0 : len;
}

/* send CLC PROPOSAL message across internal TCP socket */
@@ -536,7 +539,6 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
	struct smc_link *link;
	struct msghdr msg;
	struct kvec vec;
	int rc = 0;
	int len;

	memset(&aclc, 0, sizeof(aclc));
@@ -589,13 +591,8 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
	vec.iov_len = ntohs(aclc.hdr.length);
	len = kernel_sendmsg(new_smc->clcsock, &msg, &vec, 1,
			     ntohs(aclc.hdr.length));
	if (len < ntohs(aclc.hdr.length)) {
		if (len >= 0)
			new_smc->sk.sk_err = EPROTO;
		else
			new_smc->sk.sk_err = new_smc->clcsock->sk->sk_err;
		rc = sock_error(&new_smc->sk);
	}
	if (len < ntohs(aclc.hdr.length))
		len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err;

	return rc;
	return len > 0 ? 0 : len;
}
+2 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#define SMC_TYPE_D		1		/* SMC-D only		      */
#define SMC_TYPE_B		3		/* SMC-R and SMC-D	      */
#define CLC_WAIT_TIME		(6 * HZ)	/* max. wait time on clcsock  */
#define CLC_WAIT_TIME_SHORT	HZ		/* short wait time on clcsock */
#define SMC_CLC_DECL_MEM	0x01010000  /* insufficient memory resources  */
#define SMC_CLC_DECL_TIMEOUT_CL	0x02010000  /* timeout w4 QP confirm link     */
#define SMC_CLC_DECL_TIMEOUT_AL	0x02020000  /* timeout w4 QP add link	      */
@@ -182,7 +183,7 @@ struct smcd_dev;
int smc_clc_prfx_match(struct socket *clcsock,
		       struct smc_clc_msg_proposal_prefix *prop);
int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
		     u8 expected_type);
		     u8 expected_type, unsigned long timeout);
int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
			  struct smc_ib_device *smcibdev, u8 ibport, u8 gid[],
+13 −3
Original line number Diff line number Diff line
@@ -149,6 +149,8 @@ static int smc_link_send_delete(struct smc_link *lnk)
	return -ENOTCONN;
}

static void smc_lgr_free(struct smc_link_group *lgr);

static void smc_lgr_free_work(struct work_struct *work)
{
	struct smc_link_group *lgr = container_of(to_delayed_work(work),
@@ -171,8 +173,11 @@ free:
	spin_unlock_bh(&smc_lgr_list.lock);

	if (!lgr->is_smcd && !lgr->terminating)	{
		struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];

		/* try to send del link msg, on error free lgr immediately */
		if (!smc_link_send_delete(&lgr->lnk[SMC_SINGLE_LINK])) {
		if (lnk->state == SMC_LNK_ACTIVE &&
		    !smc_link_send_delete(lnk)) {
			/* reschedule in case we never receive a response */
			smc_lgr_schedule_free_work(lgr);
			return;
@@ -293,8 +298,13 @@ static void smc_buf_unuse(struct smc_connection *conn,
		conn->sndbuf_desc->used = 0;
	if (conn->rmb_desc) {
		if (!conn->rmb_desc->regerr) {
			conn->rmb_desc->reused = 1;
			conn->rmb_desc->used = 0;
			if (!lgr->is_smcd) {
				/* unregister rmb with peer */
				smc_llc_do_delete_rkey(
						&lgr->lnk[SMC_SINGLE_LINK],
						conn->rmb_desc);
			}
		} else {
			/* buf registration failed, reuse not possible */
			write_lock_bh(&lgr->rmbs_lock);
@@ -408,7 +418,7 @@ static void smc_lgr_free_bufs(struct smc_link_group *lgr)
}

/* remove a link group */
void smc_lgr_free(struct smc_link_group *lgr)
static void smc_lgr_free(struct smc_link_group *lgr)
{
	smc_lgr_free_bufs(lgr);
	if (lgr->is_smcd)
+4 −2
Original line number Diff line number Diff line
@@ -109,6 +109,9 @@ struct smc_link {
	int			llc_testlink_time; /* testlink interval */
	struct completion	llc_confirm_rkey; /* wait 4 rx of cnf rkey */
	int			llc_confirm_rkey_rc; /* rc from cnf rkey msg */
	struct completion	llc_delete_rkey; /* wait 4 rx of del rkey */
	int			llc_delete_rkey_rc; /* rc from del rkey msg */
	struct mutex		llc_delete_rkey_mutex; /* serialize usage */
};

/* For now we just allow one parallel link per link group. The SMC protocol
@@ -127,7 +130,7 @@ struct smc_buf_desc {
	struct page		*pages;
	int			len;		/* length of buffer */
	u32			used;		/* currently used / unused */
	u8			reused	: 1;	/* new created / reused */
	u8			wr_reg	: 1;	/* mem region registered */
	u8			regerr	: 1;	/* err during registration */
	union {
		struct { /* SMC-R */
@@ -243,7 +246,6 @@ struct smc_sock;
struct smc_clc_msg_accept_confirm;
struct smc_clc_msg_local;

void smc_lgr_free(struct smc_link_group *lgr);
void smc_lgr_forget(struct smc_link_group *lgr);
void smc_lgr_terminate(struct smc_link_group *lgr);
void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport);
Loading