Unverified Commit c015c19d authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!828 [OLK-5.10] net/smc: Optimization for connect performance

Merge Pull Request from: @giree2 
 
backport patchset form upstream and anolis:
1. net/smc: Clear memory when release and reuse buffer
2. net/smc: Make smc_tcp_listen_work() independent
3. anolis: net/smc: Change listen wq to unbound highpri wq
4. anolis: net/smc: double check whether accept queue is empty before schedule_timeout
5. anolis: net/smc: optimize for smc_accept_poll
6. anolis: net/smc: Introduce multiple tcp listen works to enhance tcp_listen_work
7. net/smc: fix application data exception 
 
Link:https://gitee.com/openeuler/kernel/pulls/828

 

Reviewed-by: default avatarYue Haibing <yuehaibing@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents fc2db2a2 ae86d5c3
Loading
Loading
Loading
Loading
+32 −15
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ static DEFINE_MUTEX(smc_client_lgr_pending); /* serialize link group
						 * creation on client
						 */

static struct workqueue_struct	*smc_tcp_ls_wq;	/* wq for tcp listen work */
struct workqueue_struct	*smc_hs_wq;	/* wq for handshake work */
struct workqueue_struct	*smc_close_wq;	/* wq for close work */

@@ -254,6 +255,7 @@ static struct sock *smc_sock_alloc(struct net *net, struct socket *sock,
	struct smc_sock *smc;
	struct proto *prot;
	struct sock *sk;
	int i = 0;

	prot = (protocol == SMCPROTO_SMC6) ? &smc_proto6 : &smc_proto;
	sk = sk_alloc(net, PF_SMC, GFP_KERNEL, prot, 0);
@@ -265,7 +267,11 @@ static struct sock *smc_sock_alloc(struct net *net, struct socket *sock,
	sk->sk_destruct = smc_destruct;
	sk->sk_protocol = protocol;
	smc = smc_sk(sk);
	INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work);
	for (i = 0; i < SMC_MAX_TCP_LISTEN_WORKS; i++) {
		smc->tcp_listen_works[i].smc = smc;
		INIT_WORK(&smc->tcp_listen_works[i].work, smc_tcp_listen_work);
	}
	atomic_set(&smc->tcp_listen_work_seq, 0);
	INIT_WORK(&smc->connect_work, smc_connect_work);
	INIT_DELAYED_WORK(&smc->conn.tx_work, smc_tx_work);
	INIT_LIST_HEAD(&smc->accept_q);
@@ -1249,6 +1255,11 @@ static void smc_accept_unlink(struct sock *sk)
	sock_put(sk); /* sock_hold in smc_accept_enqueue */
}

static inline bool smc_accept_queue_empty(struct sock *sk)
{
	return list_empty(&smc_sk(sk)->accept_q);
}

/* remove a sock from the accept queue to bind it to a new socket created
 * for a socket accept call from user space
 */
@@ -1844,8 +1855,9 @@ static void smc_listen_work(struct work_struct *work)

static void smc_tcp_listen_work(struct work_struct *work)
{
	struct smc_sock *lsmc = container_of(work, struct smc_sock,
					     tcp_listen_work);
	struct smc_tcp_listen_work *twork =
		container_of(work, struct smc_tcp_listen_work, work);
	struct smc_sock *lsmc = twork->smc;
	struct sock *lsk = &lsmc->sk;
	struct smc_sock *new_smc;
	int rc = 0;
@@ -1886,8 +1898,10 @@ static void smc_clcsock_data_ready(struct sock *listen_clcsock)
		return;
	lsmc->clcsk_data_ready(listen_clcsock);
	if (lsmc->sk.sk_state == SMC_LISTEN) {
		int idx = atomic_fetch_inc(&lsmc->tcp_listen_work_seq) %
				  SMC_MAX_TCP_LISTEN_WORKS;
		sock_hold(&lsmc->sk); /* sock_put in smc_tcp_listen_work() */
		if (!queue_work(smc_hs_wq, &lsmc->tcp_listen_work))
		if (!queue_work(smc_tcp_ls_wq, &lsmc->tcp_listen_works[idx].work))
			sock_put(&lsmc->sk);
	}
}
@@ -1968,6 +1982,7 @@ static int smc_accept(struct socket *sock, struct socket *new_sock,
			break;
		}
		release_sock(sk);
		if (smc_accept_queue_empty(sk))
			timeo = schedule_timeout(timeo);
		/* wakeup by sk_data_ready in smc_listen_work() */
		sched_annotate_sleep();
@@ -2094,17 +2109,12 @@ static int smc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
	return rc;
}

static __poll_t smc_accept_poll(struct sock *parent)
static inline __poll_t smc_accept_poll(struct sock *parent)
{
	struct smc_sock *isk = smc_sk(parent);
	__poll_t mask = 0;

	spin_lock(&isk->accept_q_lock);
	if (!list_empty(&isk->accept_q))
		mask = EPOLLIN | EPOLLRDNORM;
	spin_unlock(&isk->accept_q_lock);
	if (!smc_accept_queue_empty(parent))
		return EPOLLIN | EPOLLRDNORM;

	return mask;
	return 0;
}

static __poll_t smc_poll(struct file *file, struct socket *sock,
@@ -2589,9 +2599,13 @@ static int __init smc_init(void)
		goto out_pernet_subsys;

	rc = -ENOMEM;

	smc_tcp_ls_wq = alloc_workqueue("smc_tcp_ls_wq", WQ_UNBOUND | WQ_HIGHPRI, 0);
	if (!smc_tcp_ls_wq)
		goto out_pnet;
	smc_hs_wq = alloc_workqueue("smc_hs_wq", 0, 0);
	if (!smc_hs_wq)
		goto out_pnet;
		goto out_alloc_tcp_ls_wq;

	smc_close_wq = alloc_workqueue("smc_close_wq", 0, 0);
	if (!smc_close_wq)
@@ -2656,6 +2670,8 @@ static int __init smc_init(void)
	destroy_workqueue(smc_close_wq);
out_alloc_hs_wq:
	destroy_workqueue(smc_hs_wq);
out_alloc_tcp_ls_wq:
	destroy_workqueue(smc_tcp_ls_wq);
out_pnet:
	smc_pnet_exit();
out_pernet_subsys:
@@ -2671,6 +2687,7 @@ static void __exit smc_exit(void)
	smc_core_exit();
	smc_ib_unregister_client();
	destroy_workqueue(smc_close_wq);
	destroy_workqueue(smc_tcp_ls_wq);
	destroy_workqueue(smc_hs_wq);
	proto_unregister(&smc_proto6);
	proto_unregister(&smc_proto);
+10 −1
Original line number Diff line number Diff line
@@ -220,6 +220,13 @@ struct smc_connection {
	u8			out_of_sync : 1; /* out of sync with peer */
};

#define SMC_MAX_TCP_LISTEN_WORKS 2

struct smc_tcp_listen_work {
	struct smc_sock *smc;
	struct work_struct	work;
};

struct smc_sock {				/* smc sock container */
	struct sock		sk;
	struct socket		*clcsock;	/* internal tcp socket */
@@ -228,7 +235,9 @@ struct smc_sock { /* smc sock container */
	struct smc_connection	conn;		/* smc connection */
	struct smc_sock		*listen_smc;	/* listen parent */
	struct work_struct	connect_work;	/* handle non-blocking connect*/
	struct work_struct	tcp_listen_work;/* handle tcp socket accepts */
	struct smc_tcp_listen_work	tcp_listen_works[SMC_MAX_TCP_LISTEN_WORKS];
						/* handle tcp socket accepts */
	atomic_t		tcp_listen_work_seq;/* used to select tcp_listen_works */
	struct work_struct	smc_listen_work;/* prepare new accept socket */
	struct list_head	accept_q;	/* sockets to be accepted */
	spinlock_t		accept_q_lock;	/* protects accept_q */
+3 −1
Original line number Diff line number Diff line
@@ -199,6 +199,7 @@ int smc_close_active(struct smc_sock *smc)
	long timeout;
	int rc = 0;
	int rc1 = 0;
	int i = 0;

	timeout = current->flags & PF_EXITING ?
		  0 : sock_flag(sk, SOCK_LINGER) ?
@@ -220,7 +221,8 @@ int smc_close_active(struct smc_sock *smc)
		}
		smc_close_cleanup_listen(sk);
		release_sock(sk);
		flush_work(&smc->tcp_listen_work);
		for (i = 0; i < SMC_MAX_TCP_LISTEN_WORKS; i++)
			flush_work(&smc->tcp_listen_works[i].work);
		lock_sock(sk);
		break;
	case SMC_ACTIVE:
+13 −8
Original line number Diff line number Diff line
@@ -630,20 +630,27 @@ static void smcr_buf_unuse(struct smc_buf_desc *rmb_desc,

		smc_buf_free(lgr, true, rmb_desc);
	} else {
		rmb_desc->used = 0;
		/* memzero_explicit provides potential memory barrier semantics */
		memzero_explicit(rmb_desc->cpu_addr, rmb_desc->len);
		WRITE_ONCE(rmb_desc->used, 0);
	}
}

static void smc_buf_unuse(struct smc_connection *conn,
			  struct smc_link_group *lgr)
{
	if (conn->sndbuf_desc)
		conn->sndbuf_desc->used = 0;
	if (conn->rmb_desc && lgr->is_smcd)
		conn->rmb_desc->used = 0;
	else if (conn->rmb_desc)
	if (conn->sndbuf_desc) {
		memzero_explicit(conn->sndbuf_desc->cpu_addr, conn->sndbuf_desc->len);
		WRITE_ONCE(conn->sndbuf_desc->used, 0);
	}
	if (conn->rmb_desc && lgr->is_smcd) {
		memzero_explicit(conn->rmb_desc->cpu_addr,
				 conn->rmb_desc->len + sizeof(struct smcd_cdc_msg));
		WRITE_ONCE(conn->rmb_desc->used, 0);
	} else if (conn->rmb_desc) {
		smcr_buf_unuse(conn->rmb_desc, lgr);
	}
}

/* remove a finished connection from its link group */
void smc_conn_free(struct smc_connection *conn)
@@ -1684,8 +1691,6 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
		/* check for reusable slot in the link group */
		buf_desc = smc_buf_get_slot(bufsize_short, lock, buf_list);
		if (buf_desc) {
			buf_desc->is_dma_need_sync = 0;
			memset(buf_desc->cpu_addr, 0, bufsize);
			break; /* found reusable slot */
		}