[openib-general] Re: [PATCH] sdp: split sdp_inet_send to subroutines
Michael S. Tsirkin
mst at mellanox.co.il
Sun Aug 28 03:06:50 PDT 2005
Applied.
Committed revision 3211.
> Quoting Michael S. Tsirkin <mst at mellanox.co.il>:
> Subject: [PATCH] sdp: split sdp_inet_send to subroutines
>
> 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
_______________________________________________
openib-general mailing list
openib-general at openib.org
http://openib.org/mailman/listinfo/openib-general
To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general
--
MST
More information about the general
mailing list