[openib-general] [PATCH] sdp: split sdp_inet_send to subroutines

Michael S. Tsirkin mst at mellanox.co.il
Mon Aug 22 07:17:01 PDT 2005


The following is not yet applied. Opinions on othis?

---

Split the sdp_inet_send to smaller subroutines.

Signed-off-by: Michael S. Tsirkin <mst at mellanox.co.il>

Index: linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_send.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/ulp/sdp/sdp_send.c
+++ linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_send.c
@@ -1907,6 +1907,136 @@ done:
 	return result;
 }
 
+static inline int sdp_send_while_space(struct sock *sk, struct sdp_sock *conn,
+				       struct msghdr *msg, int oob,
+				       size_t size, size_t *copied)
+{
+	struct sdpc_buff *buff;
+	int result = 0;
+	int copy;
+	/*
+	 * send while there is room... (thresholds should be
+	 * observed...) use a different threshold for urgent
+	 * data to allow some space for sending.
+	 */
+	while (sdp_inet_write_space(conn, oob) > 0) {
+		buff = sdp_send_data_buff_get(conn);
+		if (!buff) {
+			result = -ENOMEM;
+			goto done;
+		}
+
+		copy = min((size_t)(buff->end - buff->tail), size - *copied);
+		copy = min(copy, sdp_inet_write_space(conn, oob));
+
+#ifndef _SDP_DATA_PATH_NULL
+		result = memcpy_fromiovec(buff->tail, msg->msg_iov, copy);
+		if (result < 0) {
+			sdp_buff_pool_put(buff);
+			goto done;
+		}
+#endif
+		buff->tail += copy;
+		*copied += copy;
+
+		SDP_CONN_STAT_SEND_INC(conn, copy);
+
+		result = sdp_send_data_buff_put(conn, buff, copy,
+						(*copied == size ? oob : 0));
+		if (result < 0)
+			goto done;
+
+		if (*copied == size)
+			goto done;
+	}
+	/*
+	 * set no space bits since this code path is taken
+	 * when there is no write space.
+	 */
+	set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
+	set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+
+done:
+	return result;
+}
+
+/* Returns new timeout value */
+static inline long sdp_wait_till_space(struct sock *sk, struct sdp_sock *conn,
+				       int oob, long timeout)
+{
+	DECLARE_WAITQUEUE(wait, current);
+
+	add_wait_queue(sk->sk_sleep, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	/*
+	 * ASYNC_NOSPACE is only set if we're not sleeping,
+	 * while NOSPACE is set whenever there is no space,
+	 * and is only cleared once space opens up, in
+	 * DevConnAck()
+	 */
+	clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
+
+	sdp_conn_unlock(conn);
+	if (sdp_inet_write_space(conn, oob) <= 0)
+		timeout = schedule_timeout(timeout);
+	sdp_conn_lock(conn);
+
+	remove_wait_queue(sk->sk_sleep, &wait);
+	set_current_state(TASK_RUNNING);
+	return timeout;
+}
+
+static inline int sdp_queue_iocb(struct kiocb *req, struct sdp_sock *conn,
+				 struct msghdr *msg, size_t size,
+				 size_t *copied)
+{
+	struct sdpc_iocb *iocb;
+	int result;
+	/*
+	 * create IOCB with remaining space
+	 */
+	iocb = sdp_iocb_create();
+	if (!iocb) {
+		sdp_dbg_warn(conn, "Failed to allocate IOCB <%Zu:%ld>",
+			     size, (long)*copied);
+		return -ENOMEM;
+	}
+
+	iocb->len  = size - *copied;
+	iocb->post = *copied;
+	iocb->size = size;
+	iocb->req  = req;
+	iocb->key  = req->ki_key;
+	iocb->addr = (unsigned long)msg->msg_iov->iov_base - *copied;
+
+	req->ki_cancel = sdp_inet_write_cancel;
+
+	result = sdp_iocb_lock(iocb);
+	if (result < 0) {
+		sdp_dbg_warn(conn, "Error <%d> locking IOCB <%Zu:%ld>",
+			     result, size, (long)copied);
+
+		sdp_iocb_destroy(iocb);
+		return result;
+	}
+
+	SDP_CONN_STAT_WQ_INC(conn, iocb->size);
+
+	conn->send_pipe += iocb->len;
+
+	result = sdp_send_data_queue(conn, (struct sdpc_desc *)iocb);
+	if (result < 0) {
+		sdp_dbg_warn(conn, "Error <%d> queueing write IOCB",
+			     result);
+
+		sdp_iocb_destroy(iocb);
+		return result;
+	}
+
+	*copied = 0; /* copied amount was saved in IOCB. */
+	return -EIOCBQUEUED;
+}
+
 /*
  * sdp_inet_send - send data from user space to the network
  */
@@ -1915,12 +2045,9 @@ int sdp_inet_send(struct kiocb *req, str
 {
 	struct sock      *sk;
 	struct sdp_sock   *conn;
-	struct sdpc_buff *buff;
-	struct sdpc_iocb *iocb;
 	int result = 0;
-	int copied = 0;
-	int copy;
-	int oob;
+	size_t copied = 0;
+	int oob, zcopy;
 	long timeout = -1;
 
 	/*
@@ -1954,75 +2081,35 @@ int sdp_inet_send(struct kiocb *req, str
 	 * they are smaller then the zopy threshold, but only if there is
 	 * no buffer write space.
 	 */
-	if (!(conn->src_zthresh > size) && !is_sync_kiocb(req))
-		goto skip;
+	zcopy = (size >= conn->src_zthresh && !is_sync_kiocb(req));
+
 	/*
 	 * clear ASYN space bit, it'll be reset if there is no space.
 	 */
-	clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
+	if (!zcopy)
+		clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
 	/*
 	 * process data first if window is open, next check conditions, then
 	 * wait if there is more work to be done. The absolute window size is
 	 * used to 'block' the caller if the connection is still connecting.
 	 */
 	while (!result && copied < size) {
-		/*
-		 * send while there is room... (thresholds should be
-		 * observed...) use a different threshold for urgent
-		 * data to allow some space for sending.
-		 */
-		while (sdp_inet_write_space(conn, oob) > 0) {
-			buff = sdp_send_data_buff_get(conn);
-			if (!buff) {
-				result = -ENOMEM;
-				goto done;
-			}
-
-			copy = min((size_t)(buff->end - buff->tail),
-				   (size_t)(size - copied));
-			copy = min(copy, sdp_inet_write_space(conn, oob));
-
-#ifndef _SDP_DATA_PATH_NULL
-			result = memcpy_fromiovec(buff->tail,
-						  msg->msg_iov,
-						  copy);
-			if (result < 0) {
-				sdp_buff_pool_put(buff);
-				goto done;
-			}
-#endif
-			buff->tail += copy;
-			copied += copy;
-
-			SDP_CONN_STAT_SEND_INC(conn, copy);
-
-			result = sdp_send_data_buff_put(conn, buff, copy,
-							((copied ==
-							size) ? oob : 0));
-			if (result < 0)
-				goto done;
-
-			if (copied == size)
-				goto done;
+		if (!zcopy) {
+			result = sdp_send_while_space(sk, conn, msg, oob, size,
+						      &copied);
+			if (result < 0 || copied == size)
+				break;
 		}
-		/*
-		 * set no space bits since this code path is taken
-		 * when there is no write space.
-		 */
-		set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
-		set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
-		/*
-		 * check status.
-		 */
-skip: /* entry point for IOCB based transfers. Before processing IOCB,
-         check that the connection is OK, otherwise return error
-         synchronously. */
+
+		/* entry point for IOCB based transfers. Before processing IOCB,
+		   check that the connection is OK, otherwise return error
+		   synchronously. */
 		/*
 		 * onetime setup of timeout, but only if it's needed.
 		 */
 		if (timeout < 0)
 			timeout = sock_sndtimeo(sk,
-						MSG_DONTWAIT & msg->msg_flags);
+						msg->msg_flags & MSG_DONTWAIT);
 
 		if (sk->sk_err) {
 			result = (copied > 0) ? 0 : sock_error(sk);
@@ -2051,77 +2138,14 @@ skip: /* entry point for IOCB based tran
 			break;
 		}
 		/*
-		 * Either wait or create and queue an IOCB for defered
+		 * Either wait or create and queue an IOCB for deferred
 		 * completion. Wait on sync IO call create IOCB for async
 		 * call.
 		 */
-		if (is_sync_kiocb(req)) {
-			DECLARE_WAITQUEUE(wait, current);
-
-			add_wait_queue(sk->sk_sleep, &wait);
-			set_current_state(TASK_INTERRUPTIBLE);
-			/*
-			 * ASYNC_NOSPACE is only set if we're not sleeping,
-			 * while NOSPACE is set whenever there is no space,
-			 * and is only cleared once space opens up, in
-			 * DevConnAck()
-			 */
-			clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
-
-			sdp_conn_unlock(conn);
-			if (sdp_inet_write_space(conn, oob) <= 0)
-				timeout = schedule_timeout(timeout);
-			sdp_conn_lock(conn);
-
-			remove_wait_queue(sk->sk_sleep, &wait);
-			set_current_state(TASK_RUNNING);
-
-			continue;
-		}
-		/*
-		 * create IOCB with remaining space
-		 */
-		iocb = sdp_iocb_create();
-		if (!iocb) {
-			sdp_dbg_warn(conn, "Failed to allocate IOCB <%Zu:%d>",
-				     size, copied);
-			result = -ENOMEM;
-			break;
-		}
-
-		iocb->len  = size - copied;
-		iocb->post = copied;
-		iocb->size = size;
-		iocb->req  = req;
-		iocb->key  = req->ki_key;
-		iocb->addr = (unsigned long)msg->msg_iov->iov_base - copied;
-
-		req->ki_cancel = sdp_inet_write_cancel;
-
-		result = sdp_iocb_lock(iocb);
-		if (result < 0) {
-			sdp_dbg_warn(conn, "Error <%d> locking IOCB <%Zu:%d>",
-				     result, size, copied);
-
-			sdp_iocb_destroy(iocb);
-			break;
-		}
-
-		SDP_CONN_STAT_WQ_INC(conn, iocb->size);
-
-		conn->send_pipe += iocb->len;
-
-		result = sdp_send_data_queue(conn, (struct sdpc_desc *)iocb);
-		if (result < 0) {
-			sdp_dbg_warn(conn, "Error <%d> queueing write IOCB",
-				     result);
-
-			sdp_iocb_destroy(iocb);
-			break;
-		}
-
-		copied = 0; /* copied amount was saved in IOCB. */
-		result = -EIOCBQUEUED;
+		if (is_sync_kiocb(req))
+			timeout = sdp_wait_till_space(sk, conn, oob, timeout);
+		else
+			result = sdp_queue_iocb(req, conn, msg, size, &copied);
 	}
 
 done:

-- 
MST



More information about the general mailing list