linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport
@ 2018-05-07 22:20 Long Li
  2018-05-07 22:20 ` [PATCH 2/7] cifs: smbd: Don't destroy transport on RDMA disconnect Long Li
                   ` (7 more replies)
  0 siblings, 8 replies; 12+ messages in thread
From: Long Li @ 2018-05-07 22:20 UTC (permalink / raw)
  To: Steve French, linux-cifs, samba-technical, linux-kernel, linux-rdma
  Cc: Long Li

From: Long Li <longli@microsoft.com>

On transport recoonect, upper layer CIFS code destroys the current
transport and then recoonect. This code path is not used by SMBD, in that
SMBD destroys its transport on RDMA disconnect notification independent of
CIFS upper layer behavior.

This approach adds some costs to SMBD layer to handle transport shutdown
and restart, and to deal with several racing conditions on reconnecting
transport.

Re-work this code path by introducing a new smbd_destroy. This function is
called form upper layer to ask SMBD to destroy the transport. SMBD will no
longer need to destroy the transport by itself while worrying about data
transfer is in progress. The upper layer guarantees the transport is
locked.

Signed-off-by: Long Li <longli@microsoft.com>
---
 fs/cifs/connect.c   |   9 ++---
 fs/cifs/smbdirect.c | 114 +++++++++++++++++++++++++++++++++++++++++++---------
 fs/cifs/smbdirect.h |   3 +-
 3 files changed, 100 insertions(+), 26 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 83b0234..5db3e9d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -377,7 +377,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
 			 server->ssocket->state, server->ssocket->flags);
 		sock_release(server->ssocket);
 		server->ssocket = NULL;
-	}
+	} else if (cifs_rdma_enabled(server))
+		smbd_destroy(server);
 	server->sequence_number = 0;
 	server->session_estab = false;
 	kfree(server->session_key.response);
@@ -710,10 +711,8 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
 	wake_up_all(&server->request_q);
 	/* give those requests time to exit */
 	msleep(125);
-	if (cifs_rdma_enabled(server) && server->smbd_conn) {
-		smbd_destroy(server->smbd_conn);
-		server->smbd_conn = NULL;
-	}
+	if (cifs_rdma_enabled(server))
+		smbd_destroy(server);
 	if (server->ssocket) {
 		sock_release(server->ssocket);
 		server->ssocket = NULL;
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index c62f7c9..1aa2d35 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -318,6 +318,9 @@ static int smbd_conn_upcall(
 
 		info->transport_status = SMBD_DISCONNECTED;
 		smbd_process_disconnected(info);
+		wake_up(&info->disconn_wait);
+		wake_up_interruptible(&info->wait_reassembly_queue);
+		wake_up_interruptible_all(&info->wait_send_queue);
 		break;
 
 	default:
@@ -1476,17 +1479,97 @@ static void idle_connection_timer(struct work_struct *work)
 			info->keep_alive_interval*HZ);
 }
 
-/* Destroy this SMBD connection, called from upper layer */
-void smbd_destroy(struct smbd_connection *info)
+/*
+ * Destroy the transport and related RDMA and memory resources
+ * Need to go through all the pending counters and make sure on one is using
+ * the transport while it is destroyed
+ */
+void smbd_destroy(struct TCP_Server_Info *server)
 {
+	struct smbd_connection *info = server->smbd_conn;
+	struct smbd_response *response;
+	unsigned long flags;
+
+	if (!info) {
+		log_rdma_event(INFO, "rdma session already destroyed\n");
+		return;
+	}
+
 	log_rdma_event(INFO, "destroying rdma session\n");
+	if (info->transport_status != SMBD_DISCONNECTED) {
+		rdma_disconnect(server->smbd_conn->id);
+		log_rdma_event(INFO, "wait for transport being disconnected\n");
+		wait_event(
+			info->disconn_wait,
+			info->transport_status == SMBD_DISCONNECTED);
+	}
 
-	/* Kick off the disconnection process */
-	smbd_disconnect_rdma_connection(info);
+	log_rdma_event(INFO, "destroying qp\n");
+	ib_drain_qp(info->id->qp);
+	rdma_destroy_qp(info->id);
+
+	log_rdma_event(INFO, "cancelling idle timer\n");
+	cancel_delayed_work_sync(&info->idle_timer_work);
+	log_rdma_event(INFO, "cancelling send immediate work\n");
+	cancel_delayed_work_sync(&info->send_immediate_work);
 
-	log_rdma_event(INFO, "wait for transport being destroyed\n");
-	wait_event(info->wait_destroy,
-		info->transport_status == SMBD_DESTROYED);
+	log_rdma_event(INFO, "wait for all send posted to IB to finish\n");
+	wait_event(info->wait_send_pending,
+		atomic_read(&info->send_pending) == 0);
+	wait_event(info->wait_send_payload_pending,
+		atomic_read(&info->send_payload_pending) == 0);
+
+	/* It's not posssible for upper layer to get to reassembly */
+	log_rdma_event(INFO, "drain the reassembly queue\n");
+	do {
+		spin_lock_irqsave(&info->reassembly_queue_lock, flags);
+		response = _get_first_reassembly(info);
+		if (response) {
+			list_del(&response->list);
+			spin_unlock_irqrestore(
+				&info->reassembly_queue_lock, flags);
+			put_receive_buffer(info, response);
+		} else
+			spin_unlock_irqrestore(
+				&info->reassembly_queue_lock, flags);
+	} while (response);
+	info->reassembly_data_length = 0;
+
+	log_rdma_event(INFO, "free receive buffers\n");
+	wait_event(info->wait_receive_queues,
+		info->count_receive_queue + info->count_empty_packet_queue
+			== info->receive_credit_max);
+	destroy_receive_buffers(info);
+
+	/*
+	 * For performance reasons, memory registration and deregistration
+	 * are not locked by srv_mutex. It is possible some processes are
+	 * blocked on transport srv_mutex while holding memory registration.
+	 * Release the transport srv_mutex to allow them to hit the failure
+	 * path when sending data, and then release memory registartions.
+	 */
+	log_rdma_event(INFO, "freeing mr list\n");
+	wake_up_interruptible_all(&info->wait_mr);
+	while (atomic_read(&info->mr_used_count)) {
+		mutex_unlock(&server->srv_mutex);
+		msleep(1000);
+		mutex_lock(&server->srv_mutex);
+	}
+	destroy_mr_list(info);
+
+	ib_free_cq(info->send_cq);
+	ib_free_cq(info->recv_cq);
+	ib_dealloc_pd(info->pd);
+	rdma_destroy_id(info->id);
+
+	/* free mempools */
+	mempool_destroy(info->request_mempool);
+	kmem_cache_destroy(info->request_cache);
+
+	mempool_destroy(info->response_mempool);
+	kmem_cache_destroy(info->response_cache);
+
+	info->transport_status = SMBD_DESTROYED;
 
 	destroy_workqueue(info->workqueue);
 	kfree(info);
@@ -1511,17 +1594,9 @@ int smbd_reconnect(struct TCP_Server_Info *server)
 	 */
 	if (server->smbd_conn->transport_status == SMBD_CONNECTED) {
 		log_rdma_event(INFO, "disconnecting transport\n");
-		smbd_disconnect_rdma_connection(server->smbd_conn);
+		smbd_destroy(server);
 	}
 
-	/* wait until the transport is destroyed */
-	if (!wait_event_timeout(server->smbd_conn->wait_destroy,
-		server->smbd_conn->transport_status == SMBD_DESTROYED, 5*HZ))
-		return -EAGAIN;
-
-	destroy_workqueue(server->smbd_conn->workqueue);
-	kfree(server->smbd_conn);
-
 create_conn:
 	log_rdma_event(INFO, "creating rdma session\n");
 	server->smbd_conn = smbd_get_connection(
@@ -1730,12 +1805,13 @@ static struct smbd_connection *_smbd_get_connection(
 	conn_param.retry_count = SMBD_CM_RETRY;
 	conn_param.rnr_retry_count = SMBD_CM_RNR_RETRY;
 	conn_param.flow_control = 0;
-	init_waitqueue_head(&info->wait_destroy);
 
 	log_rdma_event(INFO, "connecting to IP %pI4 port %d\n",
 		&addr_in->sin_addr, port);
 
 	init_waitqueue_head(&info->conn_wait);
+	init_waitqueue_head(&info->disconn_wait);
+	init_waitqueue_head(&info->wait_reassembly_queue);
 	rc = rdma_connect(info->id, &conn_param);
 	if (rc) {
 		log_rdma_event(ERR, "rdma_connect() failed with %i\n", rc);
@@ -1759,8 +1835,6 @@ static struct smbd_connection *_smbd_get_connection(
 	}
 
 	init_waitqueue_head(&info->wait_send_queue);
-	init_waitqueue_head(&info->wait_reassembly_queue);
-
 	INIT_DELAYED_WORK(&info->idle_timer_work, idle_connection_timer);
 	INIT_DELAYED_WORK(&info->send_immediate_work, send_immediate_work);
 	queue_delayed_work(info->workqueue, &info->idle_timer_work,
@@ -1801,7 +1875,7 @@ static struct smbd_connection *_smbd_get_connection(
 
 allocate_mr_failed:
 	/* At this point, need to a full transport shutdown */
-	smbd_destroy(info);
+	smbd_destroy(server);
 	return NULL;
 
 negotiation_failed:
diff --git a/fs/cifs/smbdirect.h b/fs/cifs/smbdirect.h
index f9038da..7849989 100644
--- a/fs/cifs/smbdirect.h
+++ b/fs/cifs/smbdirect.h
@@ -71,6 +71,7 @@ struct smbd_connection {
 	struct completion ri_done;
 	wait_queue_head_t conn_wait;
 	wait_queue_head_t wait_destroy;
+	wait_queue_head_t disconn_wait;
 
 	struct completion negotiate_completion;
 	bool negotiate_done;
@@ -288,7 +289,7 @@ struct smbd_connection *smbd_get_connection(
 /* Reconnect SMBDirect session */
 int smbd_reconnect(struct TCP_Server_Info *server);
 /* Destroy SMBDirect session */
-void smbd_destroy(struct smbd_connection *info);
+void smbd_destroy(struct TCP_Server_Info *server);
 
 /* Interface for carrying upper layer I/O through send/recv */
 int smbd_recv(struct smbd_connection *info, struct msghdr *msg);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/7] cifs: smbd: Don't destroy transport on RDMA disconnect
  2018-05-07 22:20 [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport Long Li
@ 2018-05-07 22:20 ` Long Li
  2018-05-07 22:20 ` [PATCH 3/7] cifs: smbd: Return EINTR when interrupted Long Li
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Long Li @ 2018-05-07 22:20 UTC (permalink / raw)
  To: Steve French, linux-cifs, samba-technical, linux-kernel, linux-rdma
  Cc: Long Li

From: Long Li <longli@microsoft.com>

Now upper layer is handling the transport shutdown and reconnect, remove
the code that handling transport shutdown on RDMA disconnect.

Signed-off-by: Long Li <longli@microsoft.com>
---
 fs/cifs/cifs_debug.c |   8 ++--
 fs/cifs/smbdirect.c  | 122 ++++-----------------------------------------------
 fs/cifs/smbdirect.h  |   9 ----
 3 files changed, 11 insertions(+), 128 deletions(-)

diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index e6025e9..0337ee8 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -214,12 +214,10 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
 			atomic_read(&server->smbd_conn->send_credits),
 			atomic_read(&server->smbd_conn->receive_credits),
 			server->smbd_conn->receive_credit_target);
-		seq_printf(m, "\nPending send_pending: %x send_payload_pending:"
-			" %x smbd_send_pending: %x smbd_recv_pending: %x",
+		seq_printf(m, "\nPending send_pending: %x "
+			"send_payload_pending: %x",
 			atomic_read(&server->smbd_conn->send_pending),
-			atomic_read(&server->smbd_conn->send_payload_pending),
-			server->smbd_conn->smbd_send_pending,
-			server->smbd_conn->smbd_recv_pending);
+			atomic_read(&server->smbd_conn->send_payload_pending));
 		seq_printf(m, "\nReceive buffers count_receive_queue: %x "
 			"count_empty_packet_queue: %x",
 			server->smbd_conn->count_receive_queue,
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index 1aa2d35..79b025e 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -162,95 +162,6 @@ do {									\
 #define log_rdma_mr(level, fmt, args...) \
 		log_rdma(level, LOG_RDMA_MR, fmt, ##args)
 
-/*
- * Destroy the transport and related RDMA and memory resources
- * Need to go through all the pending counters and make sure on one is using
- * the transport while it is destroyed
- */
-static void smbd_destroy_rdma_work(struct work_struct *work)
-{
-	struct smbd_response *response;
-	struct smbd_connection *info =
-		container_of(work, struct smbd_connection, destroy_work);
-	unsigned long flags;
-
-	log_rdma_event(INFO, "destroying qp\n");
-	ib_drain_qp(info->id->qp);
-	rdma_destroy_qp(info->id);
-
-	/* Unblock all I/O waiting on the send queue */
-	wake_up_interruptible_all(&info->wait_send_queue);
-
-	log_rdma_event(INFO, "cancelling idle timer\n");
-	cancel_delayed_work_sync(&info->idle_timer_work);
-	log_rdma_event(INFO, "cancelling send immediate work\n");
-	cancel_delayed_work_sync(&info->send_immediate_work);
-
-	log_rdma_event(INFO, "wait for all send to finish\n");
-	wait_event(info->wait_smbd_send_pending,
-		info->smbd_send_pending == 0);
-
-	log_rdma_event(INFO, "wait for all recv to finish\n");
-	wake_up_interruptible(&info->wait_reassembly_queue);
-	wait_event(info->wait_smbd_recv_pending,
-		info->smbd_recv_pending == 0);
-
-	log_rdma_event(INFO, "wait for all send posted to IB to finish\n");
-	wait_event(info->wait_send_pending,
-		atomic_read(&info->send_pending) == 0);
-	wait_event(info->wait_send_payload_pending,
-		atomic_read(&info->send_payload_pending) == 0);
-
-	log_rdma_event(INFO, "freeing mr list\n");
-	wake_up_interruptible_all(&info->wait_mr);
-	wait_event(info->wait_for_mr_cleanup,
-		atomic_read(&info->mr_used_count) == 0);
-	destroy_mr_list(info);
-
-	/* It's not posssible for upper layer to get to reassembly */
-	log_rdma_event(INFO, "drain the reassembly queue\n");
-	do {
-		spin_lock_irqsave(&info->reassembly_queue_lock, flags);
-		response = _get_first_reassembly(info);
-		if (response) {
-			list_del(&response->list);
-			spin_unlock_irqrestore(
-				&info->reassembly_queue_lock, flags);
-			put_receive_buffer(info, response);
-		} else
-			spin_unlock_irqrestore(&info->reassembly_queue_lock, flags);
-	} while (response);
-
-	info->reassembly_data_length = 0;
-
-	log_rdma_event(INFO, "free receive buffers\n");
-	wait_event(info->wait_receive_queues,
-		info->count_receive_queue + info->count_empty_packet_queue
-			== info->receive_credit_max);
-	destroy_receive_buffers(info);
-
-	ib_free_cq(info->send_cq);
-	ib_free_cq(info->recv_cq);
-	ib_dealloc_pd(info->pd);
-	rdma_destroy_id(info->id);
-
-	/* free mempools */
-	mempool_destroy(info->request_mempool);
-	kmem_cache_destroy(info->request_cache);
-
-	mempool_destroy(info->response_mempool);
-	kmem_cache_destroy(info->response_cache);
-
-	info->transport_status = SMBD_DESTROYED;
-	wake_up_all(&info->wait_destroy);
-}
-
-static int smbd_process_disconnected(struct smbd_connection *info)
-{
-	schedule_work(&info->destroy_work);
-	return 0;
-}
-
 static void smbd_disconnect_rdma_work(struct work_struct *work)
 {
 	struct smbd_connection *info =
@@ -317,8 +228,7 @@ static int smbd_conn_upcall(
 		}
 
 		info->transport_status = SMBD_DISCONNECTED;
-		smbd_process_disconnected(info);
-		wake_up(&info->disconn_wait);
+		wake_up_interruptible(&info->disconn_wait);
 		wake_up_interruptible(&info->wait_reassembly_queue);
 		wake_up_interruptible_all(&info->wait_send_queue);
 		break;
@@ -1499,7 +1409,7 @@ void smbd_destroy(struct TCP_Server_Info *server)
 	if (info->transport_status != SMBD_DISCONNECTED) {
 		rdma_disconnect(server->smbd_conn->id);
 		log_rdma_event(INFO, "wait for transport being disconnected\n");
-		wait_event(
+		wait_event_interruptible(
 			info->disconn_wait,
 			info->transport_status == SMBD_DISCONNECTED);
 	}
@@ -1840,12 +1750,6 @@ static struct smbd_connection *_smbd_get_connection(
 	queue_delayed_work(info->workqueue, &info->idle_timer_work,
 		info->keep_alive_interval*HZ);
 
-	init_waitqueue_head(&info->wait_smbd_send_pending);
-	info->smbd_send_pending = 0;
-
-	init_waitqueue_head(&info->wait_smbd_recv_pending);
-	info->smbd_recv_pending = 0;
-
 	init_waitqueue_head(&info->wait_send_pending);
 	atomic_set(&info->send_pending, 0);
 
@@ -1853,7 +1757,6 @@ static struct smbd_connection *_smbd_get_connection(
 	atomic_set(&info->send_payload_pending, 0);
 
 	INIT_WORK(&info->disconnect_work, smbd_disconnect_rdma_work);
-	INIT_WORK(&info->destroy_work, smbd_destroy_rdma_work);
 	INIT_WORK(&info->recv_done_work, smbd_recv_done_work);
 	INIT_WORK(&info->post_send_credits_work, smbd_post_send_credits);
 	info->new_credits_offered = 0;
@@ -1947,11 +1850,6 @@ static int smbd_recv_buf(struct smbd_connection *info, char *buf,
 	int rc;
 
 again:
-	if (info->transport_status != SMBD_CONNECTED) {
-		log_read(ERR, "disconnected\n");
-		return -ENODEV;
-	}
-
 	/*
 	 * No need to hold the reassembly queue lock all the time as we are
 	 * the only one reading from the front of the queue. The transport
@@ -2067,6 +1965,11 @@ static int smbd_recv_buf(struct smbd_connection *info, char *buf,
 	if (rc)
 		return -ENODEV;
 
+	if (info->transport_status != SMBD_CONNECTED) {
+		log_read(ERR, "disconnected\n");
+		return 0;
+	}
+
 	goto again;
 }
 
@@ -2114,8 +2017,6 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
 	unsigned int to_read;
 	int rc;
 
-	info->smbd_recv_pending++;
-
 	switch (msg->msg_iter.type) {
 	case READ | ITER_KVEC:
 		buf = msg->msg_iter.kvec->iov_base;
@@ -2133,12 +2034,9 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
 		/* It's a bug in upper layer to get there */
 		cifs_dbg(VFS, "CIFS: invalid msg type %d\n",
 			msg->msg_iter.type);
-		rc = -EIO;
+		rc = -EINVAL;
 	}
 
-	info->smbd_recv_pending--;
-	wake_up(&info->wait_smbd_recv_pending);
-
 	/* SMBDirect will read it all or nothing */
 	if (rc > 0)
 		msg->msg_iter.count = 0;
@@ -2163,7 +2061,6 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
 	struct kvec *iov;
 	int rc;
 
-	info->smbd_send_pending++;
 	if (info->transport_status != SMBD_CONNECTED) {
 		rc = -ENODEV;
 		goto done;
@@ -2319,9 +2216,6 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
 	wait_event(info->wait_send_payload_pending,
 		atomic_read(&info->send_payload_pending) == 0);
 
-	info->smbd_send_pending--;
-	wake_up(&info->wait_smbd_send_pending);
-
 	return rc;
 }
 
diff --git a/fs/cifs/smbdirect.h b/fs/cifs/smbdirect.h
index 7849989..4563c0c 100644
--- a/fs/cifs/smbdirect.h
+++ b/fs/cifs/smbdirect.h
@@ -70,13 +70,11 @@ struct smbd_connection {
 	int ri_rc;
 	struct completion ri_done;
 	wait_queue_head_t conn_wait;
-	wait_queue_head_t wait_destroy;
 	wait_queue_head_t disconn_wait;
 
 	struct completion negotiate_completion;
 	bool negotiate_done;
 
-	struct work_struct destroy_work;
 	struct work_struct disconnect_work;
 	struct work_struct recv_done_work;
 	struct work_struct post_send_credits_work;
@@ -124,13 +122,6 @@ struct smbd_connection {
 	wait_queue_head_t wait_for_mr_cleanup;
 
 	/* Activity accoutning */
-	/* Pending reqeusts issued from upper layer */
-	int smbd_send_pending;
-	wait_queue_head_t wait_smbd_send_pending;
-
-	int smbd_recv_pending;
-	wait_queue_head_t wait_smbd_recv_pending;
-
 	atomic_t send_pending;
 	wait_queue_head_t wait_send_pending;
 	atomic_t send_payload_pending;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/7] cifs: smbd: Return EINTR when interrupted
  2018-05-07 22:20 [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport Long Li
  2018-05-07 22:20 ` [PATCH 2/7] cifs: smbd: Don't destroy transport on RDMA disconnect Long Li
@ 2018-05-07 22:20 ` Long Li
  2018-05-07 22:20 ` [PATCH 4/7] cifs: smbd: Indicate to retry on transport sending failure Long Li
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Long Li @ 2018-05-07 22:20 UTC (permalink / raw)
  To: Steve French, linux-cifs, samba-technical, linux-kernel, linux-rdma
  Cc: Long Li

From: Long Li <longli@microsoft.com>

When packets are waiting for outbound I/O and interrupted, return the
proper error code to user process.

Signed-off-by: Long Li <longli@microsoft.com>
---
 fs/cifs/smbdirect.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index 79b025e..b8dd493 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -1963,7 +1963,7 @@ static int smbd_recv_buf(struct smbd_connection *info, char *buf,
 			info->transport_status != SMBD_CONNECTED);
 	/* Don't return any data if interrupted */
 	if (rc)
-		return -ENODEV;
+		return rc;
 
 	if (info->transport_status != SMBD_CONNECTED) {
 		log_read(ERR, "disconnected\n");
@@ -1991,7 +1991,7 @@ static int smbd_recv_page(struct smbd_connection *info,
 		info->reassembly_data_length >= to_read ||
 			info->transport_status != SMBD_CONNECTED);
 	if (ret)
-		return 0;
+		return ret;
 
 	/* now we can read from reassembly queue and not sleep */
 	to_address = kmap_atomic(page);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/7] cifs: smbd: Indicate to retry on transport sending failure
  2018-05-07 22:20 [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport Long Li
  2018-05-07 22:20 ` [PATCH 2/7] cifs: smbd: Don't destroy transport on RDMA disconnect Long Li
  2018-05-07 22:20 ` [PATCH 3/7] cifs: smbd: Return EINTR when interrupted Long Li
@ 2018-05-07 22:20 ` Long Li
  2018-05-07 22:20 ` [PATCH 5/7] cifs: smbd: Protect memory registration using RCU Long Li
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Long Li @ 2018-05-07 22:20 UTC (permalink / raw)
  To: Steve French, linux-cifs, samba-technical, linux-kernel, linux-rdma
  Cc: Long Li

From: Long Li <longli@microsoft.com>

Failure to send a packet doesn't mean it's a permanent failure, it can't be
returned to user process. This I/O should be retried or failed based on
server packet response and transport health. This logic is handled by the
upper layer.

Give this decision to upper layer.

Signed-off-by: Long Li <longli@microsoft.com>
---
 fs/cifs/smbdirect.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index b8dd493..74620f5 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -851,7 +851,7 @@ static int smbd_create_header(struct smbd_connection *info,
 
 	if (info->transport_status != SMBD_CONNECTED) {
 		log_outgoing(ERR, "disconnected not sending\n");
-		return -ENOENT;
+		return -EAGAIN;
 	}
 	atomic_dec(&info->send_credits);
 
@@ -977,6 +977,7 @@ static int smbd_post_send(struct smbd_connection *info,
 				wake_up(&info->wait_send_pending);
 		}
 		smbd_disconnect_rdma_connection(info);
+		rc = -EAGAIN;
 	} else
 		/* Reset timer for idle connection after packet is sent */
 		mod_delayed_work(info->workqueue, &info->idle_timer_work,
@@ -2062,7 +2063,7 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
 	int rc;
 
 	if (info->transport_status != SMBD_CONNECTED) {
-		rc = -ENODEV;
+		rc = -EAGAIN;
 		goto done;
 	}
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/7] cifs: smbd: Protect memory registration using RCU
  2018-05-07 22:20 [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport Long Li
                   ` (2 preceding siblings ...)
  2018-05-07 22:20 ` [PATCH 4/7] cifs: smbd: Indicate to retry on transport sending failure Long Li
@ 2018-05-07 22:20 ` Long Li
  2018-05-08  6:35   ` kbuild test robot
  2018-05-07 22:20 ` [PATCH 6/7] cifs: smbd: Retry on memory registration failure Long Li
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 12+ messages in thread
From: Long Li @ 2018-05-07 22:20 UTC (permalink / raw)
  To: Steve French, linux-cifs, samba-technical, linux-kernel, linux-rdma
  Cc: Long Li

From: Long Li <longli@microsoft.com>

Unlike packet I/O sending path, the memory registration is not locked. They
need to be protected when doing transport reconnect or shutdown.

It's not necessary to lock for memory deregistration, since at the time the
transport is already destroyed so it's impossible to pick up the wrong
transport.

Signed-off-by: Long Li <longli@microsoft.com>
---
 fs/cifs/smb2pdu.c   | 6 ++++++
 fs/cifs/smbdirect.c | 3 +++
 2 files changed, 9 insertions(+)

diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 8cd164e..09ca098 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2609,10 +2609,13 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
 		bool need_invalidate =
 			io_parms->tcon->ses->server->dialect == SMB30_PROT_ID;
 
+		rcu_read_lock();
+		rcu_dereference(server->smbd_conn);
 		rdata->mr = smbd_register_mr(
 				server->smbd_conn, rdata->pages,
 				rdata->nr_pages, rdata->tailsz,
 				true, need_invalidate);
+		rcu_read_unlock();
 		if (!rdata->mr)
 			return -ENOBUFS;
 
@@ -2986,10 +2989,13 @@ smb2_async_writev(struct cifs_writedata *wdata,
 		struct smbd_buffer_descriptor_v1 *v1;
 		bool need_invalidate = server->dialect == SMB30_PROT_ID;
 
+		rcu_read_lock();
+		rcu_dereference(server->smbd_conn);
 		wdata->mr = smbd_register_mr(
 				server->smbd_conn, wdata->pages,
 				wdata->nr_pages, wdata->tailsz,
 				false, need_invalidate);
+		rcu_read_unlock();
 		if (!wdata->mr) {
 			rc = -ENOBUFS;
 			goto async_writev_out;
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index 74620f5..8c46898 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -1482,6 +1482,9 @@ void smbd_destroy(struct TCP_Server_Info *server)
 
 	info->transport_status = SMBD_DESTROYED;
 
+	rcu_assign_pointer(server->smbd_conn, NULL);
+	synchronize_rcu();
+
 	destroy_workqueue(info->workqueue);
 	kfree(info);
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6/7] cifs: smbd: Retry on memory registration failure
  2018-05-07 22:20 [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport Long Li
                   ` (3 preceding siblings ...)
  2018-05-07 22:20 ` [PATCH 5/7] cifs: smbd: Protect memory registration using RCU Long Li
@ 2018-05-07 22:20 ` Long Li
  2018-05-07 22:20 ` [PATCH 7/7] cifs: Call MID callback before destroying transport Long Li
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Long Li @ 2018-05-07 22:20 UTC (permalink / raw)
  To: Steve French, linux-cifs, samba-technical, linux-kernel, linux-rdma
  Cc: Long Li

From: Long Li <longli@microsoft.com>

Memory registration failure doesn't mean this I/O has failed, it means the
transport is hitting I/O error or needs reconnect. This error is not from
the server.

Indicate this error to upper layer, and let upper layer decide how to
reconnect and proceed with this I/O.

Signed-off-by: Long Li <longli@microsoft.com>
---
 fs/cifs/smb2pdu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 09ca098..c72d1fa 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2617,7 +2617,7 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
 				true, need_invalidate);
 		rcu_read_unlock();
 		if (!rdata->mr)
-			return -ENOBUFS;
+			return -EAGAIN;
 
 		req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
 		if (need_invalidate)
@@ -2997,7 +2997,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
 				false, need_invalidate);
 		rcu_read_unlock();
 		if (!wdata->mr) {
-			rc = -ENOBUFS;
+			rc = -EAGAIN;
 			goto async_writev_out;
 		}
 		req->Length = 0;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 7/7] cifs: Call MID callback before destroying transport
  2018-05-07 22:20 [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport Long Li
                   ` (4 preceding siblings ...)
  2018-05-07 22:20 ` [PATCH 6/7] cifs: smbd: Retry on memory registration failure Long Li
@ 2018-05-07 22:20 ` Long Li
  2018-05-08  3:45 ` [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport kbuild test robot
  2018-05-08  5:24 ` kbuild test robot
  7 siblings, 0 replies; 12+ messages in thread
From: Long Li @ 2018-05-07 22:20 UTC (permalink / raw)
  To: Steve French, linux-cifs, samba-technical, linux-kernel, linux-rdma
  Cc: Long Li

From: Long Li <longli@microsoft.com>

When transport is being destroyed, it's possible that some processes may
hold memory registrations that need to be deregistred.

Call them first so nobody is using transport resources, and it can be
destroyed.

Signed-off-by: Long Li <longli@microsoft.com>
---
 fs/cifs/connect.c | 36 +++++++++++++++++++-----------------
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 5db3e9d..7e7d40e 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -369,22 +369,6 @@ cifs_reconnect(struct TCP_Server_Info *server)
 	/* do not want to be sending data on a socket we are freeing */
 	cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
 	mutex_lock(&server->srv_mutex);
-	if (server->ssocket) {
-		cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
-			 server->ssocket->state, server->ssocket->flags);
-		kernel_sock_shutdown(server->ssocket, SHUT_WR);
-		cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
-			 server->ssocket->state, server->ssocket->flags);
-		sock_release(server->ssocket);
-		server->ssocket = NULL;
-	} else if (cifs_rdma_enabled(server))
-		smbd_destroy(server);
-	server->sequence_number = 0;
-	server->session_estab = false;
-	kfree(server->session_key.response);
-	server->session_key.response = NULL;
-	server->session_key.len = 0;
-	server->lstrp = jiffies;
 
 	/* mark submitted MIDs for retry and issue callback */
 	INIT_LIST_HEAD(&retry_list);
@@ -397,7 +381,6 @@ cifs_reconnect(struct TCP_Server_Info *server)
 		list_move(&mid_entry->qhead, &retry_list);
 	}
 	spin_unlock(&GlobalMid_Lock);
-	mutex_unlock(&server->srv_mutex);
 
 	cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
 	list_for_each_safe(tmp, tmp2, &retry_list) {
@@ -406,6 +389,25 @@ cifs_reconnect(struct TCP_Server_Info *server)
 		mid_entry->callback(mid_entry);
 	}
 
+	if (server->ssocket) {
+		cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
+			 server->ssocket->state, server->ssocket->flags);
+		kernel_sock_shutdown(server->ssocket, SHUT_WR);
+		cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
+			 server->ssocket->state, server->ssocket->flags);
+		sock_release(server->ssocket);
+		server->ssocket = NULL;
+	} else if (cifs_rdma_enabled(server))
+		smbd_destroy(server);
+	server->sequence_number = 0;
+	server->session_estab = false;
+	kfree(server->session_key.response);
+	server->session_key.response = NULL;
+	server->session_key.len = 0;
+	server->lstrp = jiffies;
+
+	mutex_unlock(&server->srv_mutex);
+
 	do {
 		try_to_freeze();
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport
  2018-05-07 22:20 [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport Long Li
                   ` (5 preceding siblings ...)
  2018-05-07 22:20 ` [PATCH 7/7] cifs: Call MID callback before destroying transport Long Li
@ 2018-05-08  3:45 ` kbuild test robot
  2018-05-08  5:24 ` kbuild test robot
  7 siblings, 0 replies; 12+ messages in thread
From: kbuild test robot @ 2018-05-08  3:45 UTC (permalink / raw)
  To: Long Li
  Cc: kbuild-all, Steve French, linux-cifs, samba-technical,
	linux-kernel, linux-rdma, Long Li

[-- Attachment #1: Type: text/plain, Size: 6758 bytes --]

Hi Long,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on cifs/for-next]
[also build test WARNING on v4.17-rc4 next-20180507]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Long-Li/cifs-smbd-Make-upper-layer-decide-when-to-destroy-the-transport/20180508-110150
base:   git://git.samba.org/sfrench/cifs-2.6.git for-next
config: i386-randconfig-a1-05080831 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

   fs//cifs/connect.c: In function 'cifs_reconnect':
>> fs//cifs/connect.c:381:16: warning: passing argument 1 of 'smbd_destroy' from incompatible pointer type
      smbd_destroy(server);
                   ^
   In file included from fs//cifs/connect.c:58:0:
   fs//cifs/smbdirect.h:334:20: note: expected 'struct smbd_connection *' but argument is of type 'struct TCP_Server_Info *'
    static inline void smbd_destroy(struct smbd_connection *info) {}
                       ^
   fs//cifs/connect.c: In function 'clean_demultiplex_info':
   fs//cifs/connect.c:715:16: warning: passing argument 1 of 'smbd_destroy' from incompatible pointer type
      smbd_destroy(server);
                   ^
   In file included from fs//cifs/connect.c:58:0:
   fs//cifs/smbdirect.h:334:20: note: expected 'struct smbd_connection *' but argument is of type 'struct TCP_Server_Info *'
    static inline void smbd_destroy(struct smbd_connection *info) {}
                       ^

vim +/smbd_destroy +381 fs//cifs/connect.c

   312	
   313	static int ip_connect(struct TCP_Server_Info *server);
   314	static int generic_ip_connect(struct TCP_Server_Info *server);
   315	static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
   316	static void cifs_prune_tlinks(struct work_struct *work);
   317	static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
   318						const char *devname);
   319	
   320	/*
   321	 * cifs tcp session reconnection
   322	 *
   323	 * mark tcp session as reconnecting so temporarily locked
   324	 * mark all smb sessions as reconnecting for tcp session
   325	 * reconnect tcp session
   326	 * wake up waiters on reconnection? - (not needed currently)
   327	 */
   328	int
   329	cifs_reconnect(struct TCP_Server_Info *server)
   330	{
   331		int rc = 0;
   332		struct list_head *tmp, *tmp2;
   333		struct cifs_ses *ses;
   334		struct cifs_tcon *tcon;
   335		struct mid_q_entry *mid_entry;
   336		struct list_head retry_list;
   337	
   338		spin_lock(&GlobalMid_Lock);
   339		if (server->tcpStatus == CifsExiting) {
   340			/* the demux thread will exit normally
   341			next time through the loop */
   342			spin_unlock(&GlobalMid_Lock);
   343			return rc;
   344		} else
   345			server->tcpStatus = CifsNeedReconnect;
   346		spin_unlock(&GlobalMid_Lock);
   347		server->maxBuf = 0;
   348		server->max_read = 0;
   349	
   350		cifs_dbg(FYI, "Reconnecting tcp session\n");
   351	
   352		/* before reconnecting the tcp session, mark the smb session (uid)
   353			and the tid bad so they are not used until reconnected */
   354		cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
   355			 __func__);
   356		spin_lock(&cifs_tcp_ses_lock);
   357		list_for_each(tmp, &server->smb_ses_list) {
   358			ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
   359			ses->need_reconnect = true;
   360			list_for_each(tmp2, &ses->tcon_list) {
   361				tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
   362				tcon->need_reconnect = true;
   363			}
   364			if (ses->tcon_ipc)
   365				ses->tcon_ipc->need_reconnect = true;
   366		}
   367		spin_unlock(&cifs_tcp_ses_lock);
   368	
   369		/* do not want to be sending data on a socket we are freeing */
   370		cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
   371		mutex_lock(&server->srv_mutex);
   372		if (server->ssocket) {
   373			cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
   374				 server->ssocket->state, server->ssocket->flags);
   375			kernel_sock_shutdown(server->ssocket, SHUT_WR);
   376			cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
   377				 server->ssocket->state, server->ssocket->flags);
   378			sock_release(server->ssocket);
   379			server->ssocket = NULL;
   380		} else if (cifs_rdma_enabled(server))
 > 381			smbd_destroy(server);
   382		server->sequence_number = 0;
   383		server->session_estab = false;
   384		kfree(server->session_key.response);
   385		server->session_key.response = NULL;
   386		server->session_key.len = 0;
   387		server->lstrp = jiffies;
   388	
   389		/* mark submitted MIDs for retry and issue callback */
   390		INIT_LIST_HEAD(&retry_list);
   391		cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
   392		spin_lock(&GlobalMid_Lock);
   393		list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
   394			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
   395			if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
   396				mid_entry->mid_state = MID_RETRY_NEEDED;
   397			list_move(&mid_entry->qhead, &retry_list);
   398		}
   399		spin_unlock(&GlobalMid_Lock);
   400		mutex_unlock(&server->srv_mutex);
   401	
   402		cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
   403		list_for_each_safe(tmp, tmp2, &retry_list) {
   404			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
   405			list_del_init(&mid_entry->qhead);
   406			mid_entry->callback(mid_entry);
   407		}
   408	
   409		do {
   410			try_to_freeze();
   411	
   412			/* we should try only the port we connected to before */
   413			mutex_lock(&server->srv_mutex);
   414			if (cifs_rdma_enabled(server))
   415				rc = smbd_reconnect(server);
   416			else
   417				rc = generic_ip_connect(server);
   418			if (rc) {
   419				cifs_dbg(FYI, "reconnect error %d\n", rc);
   420				mutex_unlock(&server->srv_mutex);
   421				msleep(3000);
   422			} else {
   423				atomic_inc(&tcpSesReconnectCount);
   424				spin_lock(&GlobalMid_Lock);
   425				if (server->tcpStatus != CifsExiting)
   426					server->tcpStatus = CifsNeedNegotiate;
   427				spin_unlock(&GlobalMid_Lock);
   428				mutex_unlock(&server->srv_mutex);
   429			}
   430		} while (server->tcpStatus == CifsNeedReconnect);
   431	
   432		if (server->tcpStatus == CifsNeedNegotiate)
   433			mod_delayed_work(cifsiod_wq, &server->echo, 0);
   434	
   435		return rc;
   436	}
   437	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 33165 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport
  2018-05-07 22:20 [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport Long Li
                   ` (6 preceding siblings ...)
  2018-05-08  3:45 ` [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport kbuild test robot
@ 2018-05-08  5:24 ` kbuild test robot
  2018-05-08 19:29   ` Long Li
  7 siblings, 1 reply; 12+ messages in thread
From: kbuild test robot @ 2018-05-08  5:24 UTC (permalink / raw)
  To: Long Li
  Cc: kbuild-all, Steve French, linux-cifs, samba-technical,
	linux-kernel, linux-rdma, Long Li

[-- Attachment #1: Type: text/plain, Size: 12484 bytes --]

Hi Long,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on cifs/for-next]
[also build test ERROR on v4.17-rc4 next-20180507]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Long-Li/cifs-smbd-Make-upper-layer-decide-when-to-destroy-the-transport/20180508-110150
base:   git://git.samba.org/sfrench/cifs-2.6.git for-next
config: i386-randconfig-x013-201818 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   fs//cifs/connect.c: In function 'cifs_reconnect':
>> fs//cifs/connect.c:381:16: error: passing argument 1 of 'smbd_destroy' from incompatible pointer type [-Werror=incompatible-pointer-types]
      smbd_destroy(server);
                   ^~~~~~
   In file included from fs//cifs/connect.c:58:0:
   fs//cifs/smbdirect.h:334:20: note: expected 'struct smbd_connection *' but argument is of type 'struct TCP_Server_Info *'
    static inline void smbd_destroy(struct smbd_connection *info) {}
                       ^~~~~~~~~~~~
   fs//cifs/connect.c: In function 'clean_demultiplex_info':
   fs//cifs/connect.c:715:16: error: passing argument 1 of 'smbd_destroy' from incompatible pointer type [-Werror=incompatible-pointer-types]
      smbd_destroy(server);
                   ^~~~~~
   In file included from fs//cifs/connect.c:58:0:
   fs//cifs/smbdirect.h:334:20: note: expected 'struct smbd_connection *' but argument is of type 'struct TCP_Server_Info *'
    static inline void smbd_destroy(struct smbd_connection *info) {}
                       ^~~~~~~~~~~~
   Cyclomatic Complexity 5 include/linux/compiler.h:__read_once_size
   Cyclomatic Complexity 5 include/linux/compiler.h:__write_once_size
   Cyclomatic Complexity 1 include/linux/kasan-checks.h:kasan_check_read
   Cyclomatic Complexity 1 include/linux/kasan-checks.h:kasan_check_write
   Cyclomatic Complexity 2 arch/x86/include/asm/bitops.h:set_bit
   Cyclomatic Complexity 2 arch/x86/include/asm/bitops.h:clear_bit
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:test_and_set_bit
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:constant_test_bit
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:variable_test_bit
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:fls
   Cyclomatic Complexity 1 include/uapi/linux/byteorder/little_endian.h:__le16_to_cpup
   Cyclomatic Complexity 1 include/linux/log2.h:__ilog2_u32
   Cyclomatic Complexity 1 include/linux/list.h:INIT_LIST_HEAD
   Cyclomatic Complexity 1 include/linux/list.h:__list_add_valid
   Cyclomatic Complexity 1 include/linux/list.h:__list_del_entry_valid
   Cyclomatic Complexity 2 include/linux/list.h:__list_add
   Cyclomatic Complexity 1 include/linux/list.h:list_add
   Cyclomatic Complexity 1 include/linux/list.h:__list_del
   Cyclomatic Complexity 2 include/linux/list.h:__list_del_entry
   Cyclomatic Complexity 1 include/linux/list.h:list_del_init
   Cyclomatic Complexity 1 include/linux/list.h:list_move
   Cyclomatic Complexity 1 include/linux/list.h:list_empty
   Cyclomatic Complexity 1 arch/x86/include/asm/current.h:get_current
   Cyclomatic Complexity 1 include/linux/string.h:strnlen
   Cyclomatic Complexity 4 include/linux/string.h:strlen
   Cyclomatic Complexity 6 include/linux/string.h:strlcpy
   Cyclomatic Complexity 3 include/linux/string.h:memset
   Cyclomatic Complexity 4 include/linux/string.h:memcpy
   Cyclomatic Complexity 2 include/linux/string.h:strcpy
   Cyclomatic Complexity 1 include/asm-generic/getorder.h:__get_order
   Cyclomatic Complexity 1 include/linux/err.h:ERR_PTR
   Cyclomatic Complexity 1 include/linux/err.h:PTR_ERR
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_read
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_inc
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_dec_and_test
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_add_return
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_sub_return
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_read
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_inc
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_inc_return
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_dec_return
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_dec_and_test
   Cyclomatic Complexity 5 arch/x86/include/asm/preempt.h:__preempt_count_sub
   Cyclomatic Complexity 1 include/linux/spinlock.h:spinlock_check
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_lock
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock
   Cyclomatic Complexity 1 include/linux/uidgid.h:__kuid_val
   Cyclomatic Complexity 1 include/linux/uidgid.h:__kgid_val
   Cyclomatic Complexity 1 include/linux/uidgid.h:uid_eq
   Cyclomatic Complexity 1 include/linux/uidgid.h:gid_eq
   Cyclomatic Complexity 1 include/linux/uidgid.h:uid_gt
   Cyclomatic Complexity 1 include/linux/uidgid.h:uid_lt
   Cyclomatic Complexity 1 include/linux/uidgid.h:uid_valid
   Cyclomatic Complexity 1 include/linux/uidgid.h:gid_valid
   Cyclomatic Complexity 1 include/linux/uidgid.h:make_kuid
   Cyclomatic Complexity 1 include/linux/uidgid.h:make_kgid
   Cyclomatic Complexity 1 include/linux/uidgid.h:from_kuid
   Cyclomatic Complexity 1 include/linux/rbtree.h:rb_link_node
   Cyclomatic Complexity 1 include/linux/debug_locks.h:debug_check_no_locks_held
   Cyclomatic Complexity 1 include/linux/workqueue.h:__init_work
   Cyclomatic Complexity 1 include/linux/uio.h:iov_iter_count
   Cyclomatic Complexity 1 include/linux/socket.h:msg_data_left
   Cyclomatic Complexity 1 include/linux/sched.h:task_pid_nr
   Cyclomatic Complexity 1 include/linux/sched.h:task_thread_info
   Cyclomatic Complexity 1 include/linux/cred.h:current_user_ns
   Cyclomatic Complexity 1 include/linux/kasan.h:kasan_kmalloc
   Cyclomatic Complexity 28 include/linux/slab.h:kmalloc_index
   Cyclomatic Complexity 1 include/linux/slab.h:kmem_cache_alloc_trace
   Cyclomatic Complexity 1 include/linux/slab.h:kmalloc_order_trace
   Cyclomatic Complexity 67 include/linux/slab.h:kmalloc_large
   Cyclomatic Complexity 5 include/linux/slab.h:kmalloc
   Cyclomatic Complexity 1 include/linux/slab.h:kzalloc
   Cyclomatic Complexity 2 include/linux/ctype.h:__toupper
   Cyclomatic Complexity 1 include/linux/utsname.h:utsname
   Cyclomatic Complexity 1 include/net/net_namespace.h:get_net
   Cyclomatic Complexity 1 include/net/net_namespace.h:put_net
   Cyclomatic Complexity 1 include/net/net_namespace.h:net_eq
   Cyclomatic Complexity 1 include/linux/module.h:__module_get
   Cyclomatic Complexity 1 include/linux/module.h:module_put
   Cyclomatic Complexity 1 include/keys/user-type.h:user_key_payload_locked
   Cyclomatic Complexity 1 include/net/ipv6.h:ipv6_addr_equal
   Cyclomatic Complexity 1 include/linux/unaligned/access_ok.h:get_unaligned_le16
   Cyclomatic Complexity 1 fs//cifs/cifspdu.h:BCC
   Cyclomatic Complexity 1 fs//cifs/cifspdu.h:get_bcc
   Cyclomatic Complexity 1 fs//cifs/cifsglob.h:set_credits
   Cyclomatic Complexity 1 fs//cifs/cifsglob.h:get_next_mid

vim +/smbd_destroy +381 fs//cifs/connect.c

   312	
   313	static int ip_connect(struct TCP_Server_Info *server);
   314	static int generic_ip_connect(struct TCP_Server_Info *server);
   315	static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
   316	static void cifs_prune_tlinks(struct work_struct *work);
   317	static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
   318						const char *devname);
   319	
   320	/*
   321	 * cifs tcp session reconnection
   322	 *
   323	 * mark tcp session as reconnecting so temporarily locked
   324	 * mark all smb sessions as reconnecting for tcp session
   325	 * reconnect tcp session
   326	 * wake up waiters on reconnection? - (not needed currently)
   327	 */
   328	int
   329	cifs_reconnect(struct TCP_Server_Info *server)
   330	{
   331		int rc = 0;
   332		struct list_head *tmp, *tmp2;
   333		struct cifs_ses *ses;
   334		struct cifs_tcon *tcon;
   335		struct mid_q_entry *mid_entry;
   336		struct list_head retry_list;
   337	
   338		spin_lock(&GlobalMid_Lock);
   339		if (server->tcpStatus == CifsExiting) {
   340			/* the demux thread will exit normally
   341			next time through the loop */
   342			spin_unlock(&GlobalMid_Lock);
   343			return rc;
   344		} else
   345			server->tcpStatus = CifsNeedReconnect;
   346		spin_unlock(&GlobalMid_Lock);
   347		server->maxBuf = 0;
   348		server->max_read = 0;
   349	
   350		cifs_dbg(FYI, "Reconnecting tcp session\n");
   351	
   352		/* before reconnecting the tcp session, mark the smb session (uid)
   353			and the tid bad so they are not used until reconnected */
   354		cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
   355			 __func__);
   356		spin_lock(&cifs_tcp_ses_lock);
   357		list_for_each(tmp, &server->smb_ses_list) {
   358			ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
   359			ses->need_reconnect = true;
   360			list_for_each(tmp2, &ses->tcon_list) {
   361				tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
   362				tcon->need_reconnect = true;
   363			}
   364			if (ses->tcon_ipc)
   365				ses->tcon_ipc->need_reconnect = true;
   366		}
   367		spin_unlock(&cifs_tcp_ses_lock);
   368	
   369		/* do not want to be sending data on a socket we are freeing */
   370		cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
   371		mutex_lock(&server->srv_mutex);
   372		if (server->ssocket) {
   373			cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
   374				 server->ssocket->state, server->ssocket->flags);
   375			kernel_sock_shutdown(server->ssocket, SHUT_WR);
   376			cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
   377				 server->ssocket->state, server->ssocket->flags);
   378			sock_release(server->ssocket);
   379			server->ssocket = NULL;
   380		} else if (cifs_rdma_enabled(server))
 > 381			smbd_destroy(server);
   382		server->sequence_number = 0;
   383		server->session_estab = false;
   384		kfree(server->session_key.response);
   385		server->session_key.response = NULL;
   386		server->session_key.len = 0;
   387		server->lstrp = jiffies;
   388	
   389		/* mark submitted MIDs for retry and issue callback */
   390		INIT_LIST_HEAD(&retry_list);
   391		cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
   392		spin_lock(&GlobalMid_Lock);
   393		list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
   394			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
   395			if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
   396				mid_entry->mid_state = MID_RETRY_NEEDED;
   397			list_move(&mid_entry->qhead, &retry_list);
   398		}
   399		spin_unlock(&GlobalMid_Lock);
   400		mutex_unlock(&server->srv_mutex);
   401	
   402		cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
   403		list_for_each_safe(tmp, tmp2, &retry_list) {
   404			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
   405			list_del_init(&mid_entry->qhead);
   406			mid_entry->callback(mid_entry);
   407		}
   408	
   409		do {
   410			try_to_freeze();
   411	
   412			/* we should try only the port we connected to before */
   413			mutex_lock(&server->srv_mutex);
   414			if (cifs_rdma_enabled(server))
   415				rc = smbd_reconnect(server);
   416			else
   417				rc = generic_ip_connect(server);
   418			if (rc) {
   419				cifs_dbg(FYI, "reconnect error %d\n", rc);
   420				mutex_unlock(&server->srv_mutex);
   421				msleep(3000);
   422			} else {
   423				atomic_inc(&tcpSesReconnectCount);
   424				spin_lock(&GlobalMid_Lock);
   425				if (server->tcpStatus != CifsExiting)
   426					server->tcpStatus = CifsNeedNegotiate;
   427				spin_unlock(&GlobalMid_Lock);
   428				mutex_unlock(&server->srv_mutex);
   429			}
   430		} while (server->tcpStatus == CifsNeedReconnect);
   431	
   432		if (server->tcpStatus == CifsNeedNegotiate)
   433			mod_delayed_work(cifsiod_wq, &server->echo, 0);
   434	
   435		return rc;
   436	}
   437	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 27621 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 5/7] cifs: smbd: Protect memory registration using RCU
  2018-05-07 22:20 ` [PATCH 5/7] cifs: smbd: Protect memory registration using RCU Long Li
@ 2018-05-08  6:35   ` kbuild test robot
  2018-05-08 22:16     ` Long Li
  0 siblings, 1 reply; 12+ messages in thread
From: kbuild test robot @ 2018-05-08  6:35 UTC (permalink / raw)
  To: Long Li
  Cc: kbuild-all, Steve French, linux-cifs, samba-technical,
	linux-kernel, linux-rdma, Long Li

Hi Long,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on cifs/for-next]
[also build test WARNING on v4.17-rc4 next-20180507]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Long-Li/cifs-smbd-Make-upper-layer-decide-when-to-destroy-the-transport/20180508-110150
base:   git://git.samba.org/sfrench/cifs-2.6.git for-next
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

   fs/cifs/smb2pdu.c:110:47: sparse: expression using sizeof(void)
   fs/cifs/smb2pdu.c:681:26: sparse: expression using sizeof(void)
>> fs/cifs/smb2pdu.c:2613:17: sparse: incompatible types in comparison expression (different address spaces)
   fs/cifs/smb2pdu.c:2993:17: sparse: incompatible types in comparison expression (different address spaces)
   fs/cifs/smb2pdu.c:3251:23: sparse: expression using sizeof(void)
   fs/cifs/smb2pdu.c:3251:23: sparse: expression using sizeof(void)
   fs/cifs/smb2pdu.c:3252:23: sparse: expression using sizeof(void)
   fs/cifs/smb2pdu.c:3713:17: sparse: expression using sizeof(void)
   fs/cifs/smb2pdu.c:3713:17: sparse: expression using sizeof(void)

vim +2613 fs/cifs/smb2pdu.c

  2565	
  2566	/*
  2567	 * To form a chain of read requests, any read requests after the first should
  2568	 * have the end_of_chain boolean set to true.
  2569	 */
  2570	static int
  2571	smb2_new_read_req(void **buf, unsigned int *total_len,
  2572		struct cifs_io_parms *io_parms, struct cifs_readdata *rdata,
  2573		unsigned int remaining_bytes, int request_type)
  2574	{
  2575		int rc = -EACCES;
  2576		struct smb2_read_plain_req *req = NULL;
  2577		struct smb2_sync_hdr *shdr;
  2578		struct TCP_Server_Info *server;
  2579	
  2580		rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, (void **) &req,
  2581					 total_len);
  2582		if (rc)
  2583			return rc;
  2584	
  2585		server = io_parms->tcon->ses->server;
  2586		if (server == NULL)
  2587			return -ECONNABORTED;
  2588	
  2589		shdr = &req->sync_hdr;
  2590		shdr->ProcessId = cpu_to_le32(io_parms->pid);
  2591	
  2592		req->PersistentFileId = io_parms->persistent_fid;
  2593		req->VolatileFileId = io_parms->volatile_fid;
  2594		req->ReadChannelInfoOffset = 0; /* reserved */
  2595		req->ReadChannelInfoLength = 0; /* reserved */
  2596		req->Channel = 0; /* reserved */
  2597		req->MinimumCount = 0;
  2598		req->Length = cpu_to_le32(io_parms->length);
  2599		req->Offset = cpu_to_le64(io_parms->offset);
  2600	#ifdef CONFIG_CIFS_SMB_DIRECT
  2601		/*
  2602		 * If we want to do a RDMA write, fill in and append
  2603		 * smbd_buffer_descriptor_v1 to the end of read request
  2604		 */
  2605		if (server->rdma && rdata && !server->sign &&
  2606			rdata->bytes >= server->smbd_conn->rdma_readwrite_threshold) {
  2607	
  2608			struct smbd_buffer_descriptor_v1 *v1;
  2609			bool need_invalidate =
  2610				io_parms->tcon->ses->server->dialect == SMB30_PROT_ID;
  2611	
  2612			rcu_read_lock();
> 2613			rcu_dereference(server->smbd_conn);
  2614			rdata->mr = smbd_register_mr(
  2615					server->smbd_conn, rdata->pages,
  2616					rdata->nr_pages, rdata->tailsz,
  2617					true, need_invalidate);
  2618			rcu_read_unlock();
  2619			if (!rdata->mr)
  2620				return -ENOBUFS;
  2621	
  2622			req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
  2623			if (need_invalidate)
  2624				req->Channel = SMB2_CHANNEL_RDMA_V1;
  2625			req->ReadChannelInfoOffset =
  2626				cpu_to_le16(offsetof(struct smb2_read_plain_req, Buffer));
  2627			req->ReadChannelInfoLength =
  2628				cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
  2629			v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
  2630			v1->offset = cpu_to_le64(rdata->mr->mr->iova);
  2631			v1->token = cpu_to_le32(rdata->mr->mr->rkey);
  2632			v1->length = cpu_to_le32(rdata->mr->mr->length);
  2633	
  2634			*total_len += sizeof(*v1) - 1;
  2635		}
  2636	#endif
  2637		if (request_type & CHAINED_REQUEST) {
  2638			if (!(request_type & END_OF_CHAIN)) {
  2639				/* next 8-byte aligned request */
  2640				*total_len = DIV_ROUND_UP(*total_len, 8) * 8;
  2641				shdr->NextCommand = cpu_to_le32(*total_len);
  2642			} else /* END_OF_CHAIN */
  2643				shdr->NextCommand = 0;
  2644			if (request_type & RELATED_REQUEST) {
  2645				shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS;
  2646				/*
  2647				 * Related requests use info from previous read request
  2648				 * in chain.
  2649				 */
  2650				shdr->SessionId = 0xFFFFFFFF;
  2651				shdr->TreeId = 0xFFFFFFFF;
  2652				req->PersistentFileId = 0xFFFFFFFF;
  2653				req->VolatileFileId = 0xFFFFFFFF;
  2654			}
  2655		}
  2656		if (remaining_bytes > io_parms->length)
  2657			req->RemainingBytes = cpu_to_le32(remaining_bytes);
  2658		else
  2659			req->RemainingBytes = 0;
  2660	
  2661		*buf = req;
  2662		return rc;
  2663	}
  2664	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport
  2018-05-08  5:24 ` kbuild test robot
@ 2018-05-08 19:29   ` Long Li
  0 siblings, 0 replies; 12+ messages in thread
From: Long Li @ 2018-05-08 19:29 UTC (permalink / raw)
  To: kbuild test robot, Long Li
  Cc: kbuild-all, Steve French, linux-cifs, samba-technical,
	linux-kernel, linux-rdma

> Subject: Re: [PATCH 1/7] cifs: smbd: Make upper layer decide when to
> destroy the transport
> 
> Hi Long,
> 
> Thank you for the patch! Yet something to improve:
> 
> [auto build test ERROR on cifs/for-next] [also build test ERROR on v4.17-rc4
> next-20180507] [if your patch is applied to the wrong git tree, please drop us
> a note to help improve the system]
> 
> url:
> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub
> .com%2F0day-ci%2Flinux%2Fcommits%2FLong-Li%2Fcifs-smbd-Make-upper-
> layer-decide-when-to-destroy-the-transport%2F20180508-
> 110150&data=02%7C01%7Clongli%40microsoft.com%7C8eeef6813ee14ded2
> dcc08d5b4a4113a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636
> 613539125415461&sdata=6EzmQWCVBK9EESOC3UQwrObR9AL9W5u660M4k
> bDvoJw%3D&reserved=0
> base:   git://git.samba.org/sfrench/cifs-2.6.git for-next
> config: i386-randconfig-x013-201818 (attached as .config)
> compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=i386
> 
> All errors (new ones prefixed by >>):
> 
>    fs//cifs/connect.c: In function 'cifs_reconnect':
> >> fs//cifs/connect.c:381:16: error: passing argument 1 of
> >> 'smbd_destroy' from incompatible pointer type
> >> [-Werror=incompatible-pointer-types]
>       smbd_destroy(server);
>                    ^~~~~~

Thanks! I will send v2.

>    In file included from fs//cifs/connect.c:58:0:
>    fs//cifs/smbdirect.h:334:20: note: expected 'struct smbd_connection *' but
> argument is of type 'struct TCP_Server_Info *'
>     static inline void smbd_destroy(struct smbd_connection *info) {}
>                        ^~~~~~~~~~~~
>    fs//cifs/connect.c: In function 'clean_demultiplex_info':
>    fs//cifs/connect.c:715:16: error: passing argument 1 of 'smbd_destroy' from
> incompatible pointer type [-Werror=incompatible-pointer-types]
>       smbd_destroy(server);
>                    ^~~~~~
>    In file included from fs//cifs/connect.c:58:0:
>    fs//cifs/smbdirect.h:334:20: note: expected 'struct smbd_connection *' but
> argument is of type 'struct TCP_Server_Info *'
>     static inline void smbd_destroy(struct smbd_connection *info) {}
>                        ^~~~~~~~~~~~
>    Cyclomatic Complexity 5 include/linux/compiler.h:__read_once_size
>    Cyclomatic Complexity 5 include/linux/compiler.h:__write_once_size
>    Cyclomatic Complexity 1 include/linux/kasan-checks.h:kasan_check_read
>    Cyclomatic Complexity 1 include/linux/kasan-checks.h:kasan_check_write
>    Cyclomatic Complexity 2 arch/x86/include/asm/bitops.h:set_bit
>    Cyclomatic Complexity 2 arch/x86/include/asm/bitops.h:clear_bit
>    Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:test_and_set_bit
>    Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:constant_test_bit
>    Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:variable_test_bit
>    Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:fls
>    Cyclomatic Complexity 1
> include/uapi/linux/byteorder/little_endian.h:__le16_to_cpup
>    Cyclomatic Complexity 1 include/linux/log2.h:__ilog2_u32
>    Cyclomatic Complexity 1 include/linux/list.h:INIT_LIST_HEAD
>    Cyclomatic Complexity 1 include/linux/list.h:__list_add_valid
>    Cyclomatic Complexity 1 include/linux/list.h:__list_del_entry_valid
>    Cyclomatic Complexity 2 include/linux/list.h:__list_add
>    Cyclomatic Complexity 1 include/linux/list.h:list_add
>    Cyclomatic Complexity 1 include/linux/list.h:__list_del
>    Cyclomatic Complexity 2 include/linux/list.h:__list_del_entry
>    Cyclomatic Complexity 1 include/linux/list.h:list_del_init
>    Cyclomatic Complexity 1 include/linux/list.h:list_move
>    Cyclomatic Complexity 1 include/linux/list.h:list_empty
>    Cyclomatic Complexity 1 arch/x86/include/asm/current.h:get_current
>    Cyclomatic Complexity 1 include/linux/string.h:strnlen
>    Cyclomatic Complexity 4 include/linux/string.h:strlen
>    Cyclomatic Complexity 6 include/linux/string.h:strlcpy
>    Cyclomatic Complexity 3 include/linux/string.h:memset
>    Cyclomatic Complexity 4 include/linux/string.h:memcpy
>    Cyclomatic Complexity 2 include/linux/string.h:strcpy
>    Cyclomatic Complexity 1 include/asm-generic/getorder.h:__get_order
>    Cyclomatic Complexity 1 include/linux/err.h:ERR_PTR
>    Cyclomatic Complexity 1 include/linux/err.h:PTR_ERR
>    Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_read
>    Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_inc
>    Cyclomatic Complexity 1
> arch/x86/include/asm/atomic.h:arch_atomic_dec_and_test
>    Cyclomatic Complexity 1
> arch/x86/include/asm/atomic.h:arch_atomic_add_return
>    Cyclomatic Complexity 1
> arch/x86/include/asm/atomic.h:arch_atomic_sub_return
>    Cyclomatic Complexity 1 include/asm-generic/atomic-
> instrumented.h:atomic_read
>    Cyclomatic Complexity 1 include/asm-generic/atomic-
> instrumented.h:atomic_inc
>    Cyclomatic Complexity 1 include/asm-generic/atomic-
> instrumented.h:atomic_inc_return
>    Cyclomatic Complexity 1 include/asm-generic/atomic-
> instrumented.h:atomic_dec_return
>    Cyclomatic Complexity 1 include/asm-generic/atomic-
> instrumented.h:atomic_dec_and_test
>    Cyclomatic Complexity 5
> arch/x86/include/asm/preempt.h:__preempt_count_sub
>    Cyclomatic Complexity 1 include/linux/spinlock.h:spinlock_check
>    Cyclomatic Complexity 1 include/linux/spinlock.h:spin_lock
>    Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock
>    Cyclomatic Complexity 1 include/linux/uidgid.h:__kuid_val
>    Cyclomatic Complexity 1 include/linux/uidgid.h:__kgid_val
>    Cyclomatic Complexity 1 include/linux/uidgid.h:uid_eq
>    Cyclomatic Complexity 1 include/linux/uidgid.h:gid_eq
>    Cyclomatic Complexity 1 include/linux/uidgid.h:uid_gt
>    Cyclomatic Complexity 1 include/linux/uidgid.h:uid_lt
>    Cyclomatic Complexity 1 include/linux/uidgid.h:uid_valid
>    Cyclomatic Complexity 1 include/linux/uidgid.h:gid_valid
>    Cyclomatic Complexity 1 include/linux/uidgid.h:make_kuid
>    Cyclomatic Complexity 1 include/linux/uidgid.h:make_kgid
>    Cyclomatic Complexity 1 include/linux/uidgid.h:from_kuid
>    Cyclomatic Complexity 1 include/linux/rbtree.h:rb_link_node
>    Cyclomatic Complexity 1
> include/linux/debug_locks.h:debug_check_no_locks_held
>    Cyclomatic Complexity 1 include/linux/workqueue.h:__init_work
>    Cyclomatic Complexity 1 include/linux/uio.h:iov_iter_count
>    Cyclomatic Complexity 1 include/linux/socket.h:msg_data_left
>    Cyclomatic Complexity 1 include/linux/sched.h:task_pid_nr
>    Cyclomatic Complexity 1 include/linux/sched.h:task_thread_info
>    Cyclomatic Complexity 1 include/linux/cred.h:current_user_ns
>    Cyclomatic Complexity 1 include/linux/kasan.h:kasan_kmalloc
>    Cyclomatic Complexity 28 include/linux/slab.h:kmalloc_index
>    Cyclomatic Complexity 1 include/linux/slab.h:kmem_cache_alloc_trace
>    Cyclomatic Complexity 1 include/linux/slab.h:kmalloc_order_trace
>    Cyclomatic Complexity 67 include/linux/slab.h:kmalloc_large
>    Cyclomatic Complexity 5 include/linux/slab.h:kmalloc
>    Cyclomatic Complexity 1 include/linux/slab.h:kzalloc
>    Cyclomatic Complexity 2 include/linux/ctype.h:__toupper
>    Cyclomatic Complexity 1 include/linux/utsname.h:utsname
>    Cyclomatic Complexity 1 include/net/net_namespace.h:get_net
>    Cyclomatic Complexity 1 include/net/net_namespace.h:put_net
>    Cyclomatic Complexity 1 include/net/net_namespace.h:net_eq
>    Cyclomatic Complexity 1 include/linux/module.h:__module_get
>    Cyclomatic Complexity 1 include/linux/module.h:module_put
>    Cyclomatic Complexity 1 include/keys/user-
> type.h:user_key_payload_locked
>    Cyclomatic Complexity 1 include/net/ipv6.h:ipv6_addr_equal
>    Cyclomatic Complexity 1
> include/linux/unaligned/access_ok.h:get_unaligned_le16
>    Cyclomatic Complexity 1 fs//cifs/cifspdu.h:BCC
>    Cyclomatic Complexity 1 fs//cifs/cifspdu.h:get_bcc
>    Cyclomatic Complexity 1 fs//cifs/cifsglob.h:set_credits
>    Cyclomatic Complexity 1 fs//cifs/cifsglob.h:get_next_mid
> 
> vim +/smbd_destroy +381 fs//cifs/connect.c
> 
>    312
>    313	static int ip_connect(struct TCP_Server_Info *server);
>    314	static int generic_ip_connect(struct TCP_Server_Info *server);
>    315	static void tlink_rb_insert(struct rb_root *root, struct tcon_link
> *new_tlink);
>    316	static void cifs_prune_tlinks(struct work_struct *work);
>    317	static int cifs_setup_volume_info(struct smb_vol *volume_info, char
> *mount_data,
>    318						const char *devname);
>    319
>    320	/*
>    321	 * cifs tcp session reconnection
>    322	 *
>    323	 * mark tcp session as reconnecting so temporarily locked
>    324	 * mark all smb sessions as reconnecting for tcp session
>    325	 * reconnect tcp session
>    326	 * wake up waiters on reconnection? - (not needed currently)
>    327	 */
>    328	int
>    329	cifs_reconnect(struct TCP_Server_Info *server)
>    330	{
>    331		int rc = 0;
>    332		struct list_head *tmp, *tmp2;
>    333		struct cifs_ses *ses;
>    334		struct cifs_tcon *tcon;
>    335		struct mid_q_entry *mid_entry;
>    336		struct list_head retry_list;
>    337
>    338		spin_lock(&GlobalMid_Lock);
>    339		if (server->tcpStatus == CifsExiting) {
>    340			/* the demux thread will exit normally
>    341			next time through the loop */
>    342			spin_unlock(&GlobalMid_Lock);
>    343			return rc;
>    344		} else
>    345			server->tcpStatus = CifsNeedReconnect;
>    346		spin_unlock(&GlobalMid_Lock);
>    347		server->maxBuf = 0;
>    348		server->max_read = 0;
>    349
>    350		cifs_dbg(FYI, "Reconnecting tcp session\n");
>    351
>    352		/* before reconnecting the tcp session, mark the smb
> session (uid)
>    353			and the tid bad so they are not used until
> reconnected */
>    354		cifs_dbg(FYI, "%s: marking sessions and tcons for
> reconnect\n",
>    355			 __func__);
>    356		spin_lock(&cifs_tcp_ses_lock);
>    357		list_for_each(tmp, &server->smb_ses_list) {
>    358			ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
>    359			ses->need_reconnect = true;
>    360			list_for_each(tmp2, &ses->tcon_list) {
>    361				tcon = list_entry(tmp2, struct cifs_tcon,
> tcon_list);
>    362				tcon->need_reconnect = true;
>    363			}
>    364			if (ses->tcon_ipc)
>    365				ses->tcon_ipc->need_reconnect = true;
>    366		}
>    367		spin_unlock(&cifs_tcp_ses_lock);
>    368
>    369		/* do not want to be sending data on a socket we are freeing
> */
>    370		cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
>    371		mutex_lock(&server->srv_mutex);
>    372		if (server->ssocket) {
>    373			cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
>    374				 server->ssocket->state, server->ssocket-
> >flags);
>    375			kernel_sock_shutdown(server->ssocket, SHUT_WR);
>    376			cifs_dbg(FYI, "Post shutdown state: 0x%x Flags:
> 0x%lx\n",
>    377				 server->ssocket->state, server->ssocket-
> >flags);
>    378			sock_release(server->ssocket);
>    379			server->ssocket = NULL;
>    380		} else if (cifs_rdma_enabled(server))
>  > 381			smbd_destroy(server);
>    382		server->sequence_number = 0;
>    383		server->session_estab = false;
>    384		kfree(server->session_key.response);
>    385		server->session_key.response = NULL;
>    386		server->session_key.len = 0;
>    387		server->lstrp = jiffies;
>    388
>    389		/* mark submitted MIDs for retry and issue callback */
>    390		INIT_LIST_HEAD(&retry_list);
>    391		cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
>    392		spin_lock(&GlobalMid_Lock);
>    393		list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
>    394			mid_entry = list_entry(tmp, struct mid_q_entry,
> qhead);
>    395			if (mid_entry->mid_state ==
> MID_REQUEST_SUBMITTED)
>    396				mid_entry->mid_state =
> MID_RETRY_NEEDED;
>    397			list_move(&mid_entry->qhead, &retry_list);
>    398		}
>    399		spin_unlock(&GlobalMid_Lock);
>    400		mutex_unlock(&server->srv_mutex);
>    401
>    402		cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
>    403		list_for_each_safe(tmp, tmp2, &retry_list) {
>    404			mid_entry = list_entry(tmp, struct mid_q_entry,
> qhead);
>    405			list_del_init(&mid_entry->qhead);
>    406			mid_entry->callback(mid_entry);
>    407		}
>    408
>    409		do {
>    410			try_to_freeze();
>    411
>    412			/* we should try only the port we connected to
> before */
>    413			mutex_lock(&server->srv_mutex);
>    414			if (cifs_rdma_enabled(server))
>    415				rc = smbd_reconnect(server);
>    416			else
>    417				rc = generic_ip_connect(server);
>    418			if (rc) {
>    419				cifs_dbg(FYI, "reconnect error %d\n", rc);
>    420				mutex_unlock(&server->srv_mutex);
>    421				msleep(3000);
>    422			} else {
>    423				atomic_inc(&tcpSesReconnectCount);
>    424				spin_lock(&GlobalMid_Lock);
>    425				if (server->tcpStatus != CifsExiting)
>    426					server->tcpStatus =
> CifsNeedNegotiate;
>    427				spin_unlock(&GlobalMid_Lock);
>    428				mutex_unlock(&server->srv_mutex);
>    429			}
>    430		} while (server->tcpStatus == CifsNeedReconnect);
>    431
>    432		if (server->tcpStatus == CifsNeedNegotiate)
>    433			mod_delayed_work(cifsiod_wq, &server->echo, 0);
>    434
>    435		return rc;
>    436	}
>    437
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01
> .org%2Fpipermail%2Fkbuild-
> all&data=02%7C01%7Clongli%40microsoft.com%7C8eeef6813ee14ded2dcc08
> d5b4a4113a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C63661353
> 9125415461&sdata=OrOmZ1yCHuTbOlK8c6oBG9FpUbjBcQR5nGGa%2BntzwL
> E%3D&reserved=0                   Intel Corporation

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH 5/7] cifs: smbd: Protect memory registration using RCU
  2018-05-08  6:35   ` kbuild test robot
@ 2018-05-08 22:16     ` Long Li
  0 siblings, 0 replies; 12+ messages in thread
From: Long Li @ 2018-05-08 22:16 UTC (permalink / raw)
  To: kbuild test robot, Long Li
  Cc: kbuild-all, Steve French, linux-cifs, samba-technical,
	linux-kernel, linux-rdma

Hi Steve

Please drop this patch. I will find another solution.

The other patches in the series can be reviewed and applied.

Long

> -----Original Message-----
> From: kbuild test robot <lkp@intel.com>
> Sent: Monday, May 7, 2018 11:36 PM
> To: Long Li <longli@linuxonhyperv.com>
> Cc: kbuild-all@01.org; Steve French <sfrench@samba.org>; linux-
> cifs@vger.kernel.org; samba-technical@lists.samba.org; linux-
> kernel@vger.kernel.org; linux-rdma@vger.kernel.org; Long Li
> <longli@microsoft.com>
> Subject: Re: [PATCH 5/7] cifs: smbd: Protect memory registration using RCU
> 
> Hi Long,
> 
> Thank you for the patch! Perhaps something to improve:
> 
> [auto build test WARNING on cifs/for-next] [also build test WARNING on
> v4.17-rc4 next-20180507] [if your patch is applied to the wrong git tree,
> please drop us a note to help improve the system]
> 
> url:
> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub
> .com%2F0day-ci%2Flinux%2Fcommits%2FLong-Li%2Fcifs-smbd-Make-upper-
> layer-decide-when-to-destroy-the-transport%2F20180508-
> 110150&data=02%7C01%7Clongli%40microsoft.com%7C56045b01aeae4e53b1
> 9408d5b4ae0502%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C6366
> 13581873868980&sdata=a1Ds3qI7sRrLCE77Eoasifonm1rUQYi7rdUEnLnGOB4%
> 3D&reserved=0
> base:   git://git.samba.org/sfrench/cifs-2.6.git for-next
> reproduce:
>         # apt-get install sparse
>         make ARCH=x86_64 allmodconfig
>         make C=1 CF=-D__CHECK_ENDIAN__
> 
> 
> sparse warnings: (new ones prefixed by >>)
> 
>    fs/cifs/smb2pdu.c:110:47: sparse: expression using sizeof(void)
>    fs/cifs/smb2pdu.c:681:26: sparse: expression using sizeof(void)
> >> fs/cifs/smb2pdu.c:2613:17: sparse: incompatible types in comparison
> >> expression (different address spaces)
>    fs/cifs/smb2pdu.c:2993:17: sparse: incompatible types in comparison
> expression (different address spaces)
>    fs/cifs/smb2pdu.c:3251:23: sparse: expression using sizeof(void)
>    fs/cifs/smb2pdu.c:3251:23: sparse: expression using sizeof(void)
>    fs/cifs/smb2pdu.c:3252:23: sparse: expression using sizeof(void)
>    fs/cifs/smb2pdu.c:3713:17: sparse: expression using sizeof(void)
>    fs/cifs/smb2pdu.c:3713:17: sparse: expression using sizeof(void)
> 
> vim +2613 fs/cifs/smb2pdu.c
> 
>   2565
>   2566	/*
>   2567	 * To form a chain of read requests, any read requests after the first
> should
>   2568	 * have the end_of_chain boolean set to true.
>   2569	 */
>   2570	static int
>   2571	smb2_new_read_req(void **buf, unsigned int *total_len,
>   2572		struct cifs_io_parms *io_parms, struct cifs_readdata *rdata,
>   2573		unsigned int remaining_bytes, int request_type)
>   2574	{
>   2575		int rc = -EACCES;
>   2576		struct smb2_read_plain_req *req = NULL;
>   2577		struct smb2_sync_hdr *shdr;
>   2578		struct TCP_Server_Info *server;
>   2579
>   2580		rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, (void
> **) &req,
>   2581					 total_len);
>   2582		if (rc)
>   2583			return rc;
>   2584
>   2585		server = io_parms->tcon->ses->server;
>   2586		if (server == NULL)
>   2587			return -ECONNABORTED;
>   2588
>   2589		shdr = &req->sync_hdr;
>   2590		shdr->ProcessId = cpu_to_le32(io_parms->pid);
>   2591
>   2592		req->PersistentFileId = io_parms->persistent_fid;
>   2593		req->VolatileFileId = io_parms->volatile_fid;
>   2594		req->ReadChannelInfoOffset = 0; /* reserved */
>   2595		req->ReadChannelInfoLength = 0; /* reserved */
>   2596		req->Channel = 0; /* reserved */
>   2597		req->MinimumCount = 0;
>   2598		req->Length = cpu_to_le32(io_parms->length);
>   2599		req->Offset = cpu_to_le64(io_parms->offset);
>   2600	#ifdef CONFIG_CIFS_SMB_DIRECT
>   2601		/*
>   2602		 * If we want to do a RDMA write, fill in and append
>   2603		 * smbd_buffer_descriptor_v1 to the end of read request
>   2604		 */
>   2605		if (server->rdma && rdata && !server->sign &&
>   2606			rdata->bytes >= server->smbd_conn-
> >rdma_readwrite_threshold) {
>   2607
>   2608			struct smbd_buffer_descriptor_v1 *v1;
>   2609			bool need_invalidate =
>   2610				io_parms->tcon->ses->server->dialect ==
> SMB30_PROT_ID;
>   2611
>   2612			rcu_read_lock();
> > 2613			rcu_dereference(server->smbd_conn);
>   2614			rdata->mr = smbd_register_mr(
>   2615					server->smbd_conn, rdata->pages,
>   2616					rdata->nr_pages, rdata->tailsz,
>   2617					true, need_invalidate);
>   2618			rcu_read_unlock();
>   2619			if (!rdata->mr)
>   2620				return -ENOBUFS;
>   2621
>   2622			req->Channel =
> SMB2_CHANNEL_RDMA_V1_INVALIDATE;
>   2623			if (need_invalidate)
>   2624				req->Channel = SMB2_CHANNEL_RDMA_V1;
>   2625			req->ReadChannelInfoOffset =
>   2626				cpu_to_le16(offsetof(struct
> smb2_read_plain_req, Buffer));
>   2627			req->ReadChannelInfoLength =
>   2628				cpu_to_le16(sizeof(struct
> smbd_buffer_descriptor_v1));
>   2629			v1 = (struct smbd_buffer_descriptor_v1 *) &req-
> >Buffer[0];
>   2630			v1->offset = cpu_to_le64(rdata->mr->mr->iova);
>   2631			v1->token = cpu_to_le32(rdata->mr->mr->rkey);
>   2632			v1->length = cpu_to_le32(rdata->mr->mr->length);
>   2633
>   2634			*total_len += sizeof(*v1) - 1;
>   2635		}
>   2636	#endif
>   2637		if (request_type & CHAINED_REQUEST) {
>   2638			if (!(request_type & END_OF_CHAIN)) {
>   2639				/* next 8-byte aligned request */
>   2640				*total_len = DIV_ROUND_UP(*total_len, 8) *
> 8;
>   2641				shdr->NextCommand =
> cpu_to_le32(*total_len);
>   2642			} else /* END_OF_CHAIN */
>   2643				shdr->NextCommand = 0;
>   2644			if (request_type & RELATED_REQUEST) {
>   2645				shdr->Flags |=
> SMB2_FLAGS_RELATED_OPERATIONS;
>   2646				/*
>   2647				 * Related requests use info from previous
> read request
>   2648				 * in chain.
>   2649				 */
>   2650				shdr->SessionId = 0xFFFFFFFF;
>   2651				shdr->TreeId = 0xFFFFFFFF;
>   2652				req->PersistentFileId = 0xFFFFFFFF;
>   2653				req->VolatileFileId = 0xFFFFFFFF;
>   2654			}
>   2655		}
>   2656		if (remaining_bytes > io_parms->length)
>   2657			req->RemainingBytes =
> cpu_to_le32(remaining_bytes);
>   2658		else
>   2659			req->RemainingBytes = 0;
>   2660
>   2661		*buf = req;
>   2662		return rc;
>   2663	}
>   2664
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01
> .org%2Fpipermail%2Fkbuild-
> all&data=02%7C01%7Clongli%40microsoft.com%7C56045b01aeae4e53b19408
> d5b4ae0502%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C63661358
> 1873868980&sdata=y3BYFeKEayhIfrs6hodamCPCyz8n3YQdN1yX3yXKs80%3D
> &reserved=0                   Intel Corporation

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2018-05-08 22:16 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-07 22:20 [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport Long Li
2018-05-07 22:20 ` [PATCH 2/7] cifs: smbd: Don't destroy transport on RDMA disconnect Long Li
2018-05-07 22:20 ` [PATCH 3/7] cifs: smbd: Return EINTR when interrupted Long Li
2018-05-07 22:20 ` [PATCH 4/7] cifs: smbd: Indicate to retry on transport sending failure Long Li
2018-05-07 22:20 ` [PATCH 5/7] cifs: smbd: Protect memory registration using RCU Long Li
2018-05-08  6:35   ` kbuild test robot
2018-05-08 22:16     ` Long Li
2018-05-07 22:20 ` [PATCH 6/7] cifs: smbd: Retry on memory registration failure Long Li
2018-05-07 22:20 ` [PATCH 7/7] cifs: Call MID callback before destroying transport Long Li
2018-05-08  3:45 ` [PATCH 1/7] cifs: smbd: Make upper layer decide when to destroy the transport kbuild test robot
2018-05-08  5:24 ` kbuild test robot
2018-05-08 19:29   ` Long Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).