Move the code that checks for available write space on the socket, into a new transport function. This will allow transports flexibility when determining if enough space/memory is available to process the reply. The role of this function for RDMA is to avoid stalling an knfsd thread when SQ space is not available.
Signed-off-by: Greg Banks <[EMAIL PROTECTED]> Signed-off-by: Peter Leckie <[EMAIL PROTECTED]> Signed-off-by: Tom Tucker <[EMAIL PROTECTED]> --- include/linux/sunrpc/svcsock.h | 4 ++ net/sunrpc/svcsock.c | 75 ++++++++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index 1da42c2..3faa95c 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h @@ -31,6 +31,10 @@ struct svc_xprt { * Prepare any transport-specific RPC header. */ int (*xpt_prep_reply_hdr)(struct svc_rqst *); + /* + * Return 1 if sufficient space to write reply to network. + */ + int (*xpt_has_wspace)(struct svc_sock *); }; /* diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index ca473ee..b16dad4 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -205,22 +205,6 @@ svc_release_skb(struct svc_rqst *rqstp) } /* - * Any space to write? - */ -static inline unsigned long -svc_sock_wspace(struct svc_sock *svsk) -{ - int wspace; - - if (svsk->sk_sock->type == SOCK_STREAM) - wspace = sk_stream_wspace(svsk->sk_sk); - else - wspace = sock_wspace(svsk->sk_sk); - - return wspace; -} - -/* * Queue up a socket with data pending. If there are idle nfsd * processes, wake 'em up. * @@ -269,21 +253,13 @@ svc_sock_enqueue(struct svc_sock *svsk) BUG_ON(svsk->sk_pool != NULL); svsk->sk_pool = pool; - set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); - if (((atomic_read(&svsk->sk_reserved) + serv->sv_max_mesg)*2 - > svc_sock_wspace(svsk)) - && !test_bit(SK_CLOSE, &svsk->sk_flags) - && !test_bit(SK_CONN, &svsk->sk_flags)) { - /* Don't enqueue while not enough space for reply */ - dprintk("svc: socket %p no space, %d*2 > %ld, not enqueued\n", - svsk->sk_sk, atomic_read(&svsk->sk_reserved)+serv->sv_max_mesg, - svc_sock_wspace(svsk)); + if (!test_bit(SK_CLOSE, &svsk->sk_flags) + && !test_bit(SK_CONN, &svsk->sk_flags) + && !svsk->sk_xprt->xpt_has_wspace(svsk)) { svsk->sk_pool = NULL; clear_bit(SK_BUSY, &svsk->sk_flags); goto out_unlock; } - clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); - if (!list_empty(&pool->sp_threads)) { rqstp = list_entry(pool->sp_threads.next, @@ -882,12 +858,45 @@ svc_udp_sendto(struct svc_rqst *rqstp) return error; } +/** + * svc_sock_has_write_space - Checks if there is enough space + * to send the reply on the socket. + * @svsk: the svc_sock to write on + * @wspace: the number of bytes available for writing + */ +static int svc_sock_has_write_space(struct svc_sock *svsk, int wspace) +{ + struct svc_serv *serv = svsk->sk_server; + int required = atomic_read(&svsk->sk_reserved) + serv->sv_max_mesg; + + if (required*2 > wspace) { + /* Don't enqueue while not enough space for reply */ + dprintk("svc: socket %p no space, %d*2 > %d, not enqueued\n", + svsk->sk_sk, required, wspace); + return 0; + } + clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); + return 1; +} + +static int +svc_udp_has_wspace(struct svc_sock *svsk) +{ + /* + * Set the SOCK_NOSPACE flag before checking the available + * sock space. + */ + set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); + return svc_sock_has_write_space(svsk, sock_wspace(svsk->sk_sk)); +} + static const struct svc_xprt svc_udp_xprt = { .xpt_name = "udp", .xpt_recvfrom = svc_udp_recvfrom, .xpt_sendto = svc_udp_sendto, .xpt_detach = svc_sock_detach, .xpt_free = svc_sock_free, + .xpt_has_wspace = svc_udp_has_wspace, }; static void @@ -1340,6 +1349,17 @@ svc_tcp_prep_reply_hdr(struct svc_rqst * return 0; } +static int +svc_tcp_has_wspace(struct svc_sock *svsk) +{ + /* + * Set the SOCK_NOSPACE flag before checking the available + * sock space. + */ + set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); + return svc_sock_has_write_space(svsk, sk_stream_wspace(svsk->sk_sk)); +} + static const struct svc_xprt svc_tcp_xprt = { .xpt_name = "tcp", .xpt_recvfrom = svc_tcp_recvfrom, @@ -1347,6 +1367,7 @@ static const struct svc_xprt svc_tcp_xpr .xpt_detach = svc_sock_detach, .xpt_free = svc_sock_free, .xpt_prep_reply_hdr = svc_tcp_prep_reply_hdr, + .xpt_has_wspace = svc_tcp_has_wspace, }; static void _______________________________________________ general mailing list general@lists.openfabrics.org http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general