|
@@ -204,22 +204,6 @@ static void 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,22 +253,24 @@ 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)) {
|
|
|
+ /* Handle pending connection */
|
|
|
+ if (test_bit(SK_CONN, &svsk->sk_flags))
|
|
|
+ goto process;
|
|
|
+
|
|
|
+ /* Handle close in-progress */
|
|
|
+ if (test_bit(SK_CLOSE, &svsk->sk_flags))
|
|
|
+ goto process;
|
|
|
+
|
|
|
+ /* Check if we have space to reply to a request */
|
|
|
+ if (!svsk->sk_xprt.xpt_ops->xpo_has_wspace(&svsk->sk_xprt)) {
|
|
|
/* 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));
|
|
|
+ dprintk("svc: no write space, socket %p not enqueued\n", svsk);
|
|
|
svsk->sk_pool = NULL;
|
|
|
clear_bit(SK_BUSY, &svsk->sk_flags);
|
|
|
goto out_unlock;
|
|
|
}
|
|
|
- clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
|
|
|
-
|
|
|
|
|
|
+ process:
|
|
|
if (!list_empty(&pool->sp_threads)) {
|
|
|
rqstp = list_entry(pool->sp_threads.next,
|
|
|
struct svc_rqst,
|
|
@@ -897,6 +883,24 @@ static void svc_udp_prep_reply_hdr(struct svc_rqst *rqstp)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
+static int svc_udp_has_wspace(struct svc_xprt *xprt)
|
|
|
+{
|
|
|
+ struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
|
|
|
+ struct svc_serv *serv = svsk->sk_server;
|
|
|
+ unsigned long required;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Set the SOCK_NOSPACE flag before checking the available
|
|
|
+ * sock space.
|
|
|
+ */
|
|
|
+ set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
|
|
|
+ required = atomic_read(&svsk->sk_reserved) + serv->sv_max_mesg;
|
|
|
+ if (required*2 > sock_wspace(svsk->sk_sk))
|
|
|
+ return 0;
|
|
|
+ clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
static struct svc_xprt_ops svc_udp_ops = {
|
|
|
.xpo_recvfrom = svc_udp_recvfrom,
|
|
|
.xpo_sendto = svc_udp_sendto,
|
|
@@ -904,6 +908,7 @@ static struct svc_xprt_ops svc_udp_ops = {
|
|
|
.xpo_detach = svc_sock_detach,
|
|
|
.xpo_free = svc_sock_free,
|
|
|
.xpo_prep_reply_hdr = svc_udp_prep_reply_hdr,
|
|
|
+ .xpo_has_wspace = svc_udp_has_wspace,
|
|
|
};
|
|
|
|
|
|
static struct svc_xprt_class svc_udp_class = {
|
|
@@ -1366,6 +1371,30 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp)
|
|
|
svc_putnl(resv, 0);
|
|
|
}
|
|
|
|
|
|
+static int svc_tcp_has_wspace(struct svc_xprt *xprt)
|
|
|
+{
|
|
|
+ struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
|
|
|
+ struct svc_serv *serv = svsk->sk_server;
|
|
|
+ int required;
|
|
|
+ int wspace;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Set the SOCK_NOSPACE flag before checking the available
|
|
|
+ * sock space.
|
|
|
+ */
|
|
|
+ set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
|
|
|
+ required = atomic_read(&svsk->sk_reserved) + serv->sv_max_mesg;
|
|
|
+ wspace = sk_stream_wspace(svsk->sk_sk);
|
|
|
+
|
|
|
+ if (wspace < sk_stream_min_wspace(svsk->sk_sk))
|
|
|
+ return 0;
|
|
|
+ if (required * 2 > wspace)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
static struct svc_xprt_ops svc_tcp_ops = {
|
|
|
.xpo_recvfrom = svc_tcp_recvfrom,
|
|
|
.xpo_sendto = svc_tcp_sendto,
|
|
@@ -1373,6 +1402,7 @@ static struct svc_xprt_ops svc_tcp_ops = {
|
|
|
.xpo_detach = svc_sock_detach,
|
|
|
.xpo_free = svc_sock_free,
|
|
|
.xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr,
|
|
|
+ .xpo_has_wspace = svc_tcp_has_wspace,
|
|
|
};
|
|
|
|
|
|
static struct svc_xprt_class svc_tcp_class = {
|