]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sunrpc/svcsock.c
svc: Make svc_check_conn_limits xprt independent
[linux-2.6-omap-h63xx.git] / net / sunrpc / svcsock.c
index fa57e9bc68e400571150ea44fe45fde0bd366423..0814a78ad7ad46af2ca263581393dd08f1f805ab 100644 (file)
@@ -94,6 +94,7 @@ static int svc_deferred_recv(struct svc_rqst *rqstp);
 static struct cache_deferred_req *svc_defer(struct cache_req *req);
 static struct svc_xprt *svc_create_socket(struct svc_serv *, int,
                                          struct sockaddr *, int, int);
+static void svc_age_temp_xprts(unsigned long closure);
 
 /* apparently the "standard" is that clients close
  * idle connections after 5 minutes, servers after
@@ -200,10 +201,12 @@ static void svc_release_skb(struct svc_rqst *rqstp)
        struct svc_deferred_req *dr = rqstp->rq_deferred;
 
        if (skb) {
+               struct svc_sock *svsk =
+                       container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
                rqstp->rq_xprt_ctxt = NULL;
 
                dprintk("svc: service %p, releasing skb %p\n", rqstp, skb);
-               skb_free_datagram(rqstp->rq_sock->sk_sk, skb);
+               skb_free_datagram(svsk->sk_sk, skb);
        }
        if (dr) {
                rqstp->rq_deferred = NULL;
@@ -417,7 +420,7 @@ svc_wake_up(struct svc_serv *serv)
                        dprintk("svc: daemon %p woken up.\n", rqstp);
                        /*
                        svc_thread_dequeue(pool, rqstp);
-                       rqstp->rq_sock = NULL;
+                       rqstp->rq_xprt = NULL;
                         */
                        wake_up(&rqstp->rq_wait);
                }
@@ -434,7 +437,9 @@ union svc_pktinfo_u {
 
 static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh)
 {
-       switch (rqstp->rq_sock->sk_sk->sk_family) {
+       struct svc_sock *svsk =
+               container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
+       switch (svsk->sk_sk->sk_family) {
        case AF_INET: {
                        struct in_pktinfo *pki = CMSG_DATA(cmh);
 
@@ -467,7 +472,8 @@ static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh)
 static int
 svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr)
 {
-       struct svc_sock *svsk = rqstp->rq_sock;
+       struct svc_sock *svsk =
+               container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
        struct socket   *sock = svsk->sk_sock;
        int             slen;
        union {
@@ -540,7 +546,7 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr)
        }
 out:
        dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %s)\n",
-               rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len,
+               svsk, xdr->head[0].iov_base, xdr->head[0].iov_len,
                xdr->len, len, svc_print_addr(rqstp, buf, sizeof(buf)));
 
        return len;
@@ -616,7 +622,8 @@ svc_recv_available(struct svc_sock *svsk)
 static int
 svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen)
 {
-       struct svc_sock *svsk = rqstp->rq_sock;
+       struct svc_sock *svsk =
+               container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
        struct msghdr msg = {
                .msg_flags      = MSG_DONTWAIT,
        };
@@ -706,7 +713,9 @@ svc_write_space(struct sock *sk)
 static void svc_udp_get_dest_address(struct svc_rqst *rqstp,
                                     struct cmsghdr *cmh)
 {
-       switch (rqstp->rq_sock->sk_sk->sk_family) {
+       struct svc_sock *svsk =
+               container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
+       switch (svsk->sk_sk->sk_family) {
        case AF_INET: {
                struct in_pktinfo *pki = CMSG_DATA(cmh);
                rqstp->rq_daddr.addr.s_addr = pki->ipi_spec_dst.s_addr;
@@ -726,7 +735,8 @@ static void svc_udp_get_dest_address(struct svc_rqst *rqstp,
 static int
 svc_udp_recvfrom(struct svc_rqst *rqstp)
 {
-       struct svc_sock *svsk = rqstp->rq_sock;
+       struct svc_sock *svsk =
+               container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
        struct svc_serv *serv = svsk->sk_xprt.xpt_server;
        struct sk_buff  *skb;
        union {
@@ -1108,7 +1118,8 @@ failed:
 static int
 svc_tcp_recvfrom(struct svc_rqst *rqstp)
 {
-       struct svc_sock *svsk = rqstp->rq_sock;
+       struct svc_sock *svsk =
+               container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
        struct svc_serv *serv = svsk->sk_xprt.xpt_server;
        int             len;
        struct kvec *vec;
@@ -1272,16 +1283,16 @@ svc_tcp_sendto(struct svc_rqst *rqstp)
        reclen = htonl(0x80000000|((xbufp->len ) - 4));
        memcpy(xbufp->head[0].iov_base, &reclen, 4);
 
-       if (test_bit(XPT_DEAD, &rqstp->rq_sock->sk_xprt.xpt_flags))
+       if (test_bit(XPT_DEAD, &rqstp->rq_xprt->xpt_flags))
                return -ENOTCONN;
 
        sent = svc_sendto(rqstp, &rqstp->rq_res);
        if (sent != xbufp->len) {
                printk(KERN_NOTICE "rpc-srv/tcp: %s: %s %d when sending %d bytes - shutting down socket\n",
-                      rqstp->rq_sock->sk_xprt.xpt_server->sv_name,
+                      rqstp->rq_xprt->xpt_server->sv_name,
                       (sent<0)?"got error":"sent only",
                       sent, xbufp->len);
-               set_bit(XPT_CLOSE, &rqstp->rq_sock->sk_xprt.xpt_flags);
+               set_bit(XPT_CLOSE, &rqstp->rq_xprt->xpt_flags);
                svc_xprt_enqueue(rqstp->rq_xprt);
                sent = -EAGAIN;
        }
@@ -1301,7 +1312,7 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp)
 
 static int svc_tcp_has_wspace(struct svc_xprt *xprt)
 {
-       struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
+       struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
        struct svc_serv *serv = svsk->sk_xprt.xpt_server;
        int required;
        int wspace;
@@ -1437,31 +1448,31 @@ svc_sock_update_bufs(struct svc_serv *serv)
 static void svc_check_conn_limits(struct svc_serv *serv)
 {
        if (serv->sv_tmpcnt > (serv->sv_nrthreads+3)*20) {
-               struct svc_sock *svsk = NULL;
+               struct svc_xprt *xprt = NULL;
                spin_lock_bh(&serv->sv_lock);
                if (!list_empty(&serv->sv_tempsocks)) {
                        if (net_ratelimit()) {
                                /* Try to help the admin */
-                               printk(KERN_NOTICE "%s: too many open TCP "
-                                      "sockets, consider increasing the "
+                               printk(KERN_NOTICE "%s: too many open  "
+                                      "connections, consider increasing the "
                                       "number of nfsd threads\n",
                                       serv->sv_name);
                        }
                        /*
-                        * Always select the oldest socket. It's not fair,
+                        * Always select the oldest connection. It's not fair,
                         * but so is life
                         */
-                       svsk = list_entry(serv->sv_tempsocks.prev,
-                                         struct svc_sock,
-                                         sk_xprt.xpt_list);
-                       set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
-                       svc_xprt_get(&svsk->sk_xprt);
+                       xprt = list_entry(serv->sv_tempsocks.prev,
+                                         struct svc_xprt,
+                                         xpt_list);
+                       set_bit(XPT_CLOSE, &xprt->xpt_flags);
+                       svc_xprt_get(xprt);
                }
                spin_unlock_bh(&serv->sv_lock);
 
-               if (svsk) {
-                       svc_xprt_enqueue(&svsk->sk_xprt);
-                       svc_xprt_put(&svsk->sk_xprt);
+               if (xprt) {
+                       svc_xprt_enqueue(xprt);
+                       svc_xprt_put(xprt);
                }
        }
 }
@@ -1573,6 +1584,19 @@ svc_recv(struct svc_rqst *rqstp, long timeout)
                         */
                        __module_get(newxpt->xpt_class->xcl_owner);
                        svc_check_conn_limits(xprt->xpt_server);
+                       spin_lock_bh(&serv->sv_lock);
+                       set_bit(XPT_TEMP, &newxpt->xpt_flags);
+                       list_add(&newxpt->xpt_list, &serv->sv_tempsocks);
+                       serv->sv_tmpcnt++;
+                       if (serv->sv_temptimer.function == NULL) {
+                               /* setup timer to age temp sockets */
+                               setup_timer(&serv->sv_temptimer,
+                                           svc_age_temp_xprts,
+                                           (unsigned long)serv);
+                               mod_timer(&serv->sv_temptimer,
+                                         jiffies + svc_conn_age_period * HZ);
+                       }
+                       spin_unlock_bh(&serv->sv_lock);
                        svc_xprt_received(newxpt);
                }
                svc_xprt_received(xprt);
@@ -1611,7 +1635,7 @@ svc_recv(struct svc_rqst *rqstp, long timeout)
 void
 svc_drop(struct svc_rqst *rqstp)
 {
-       dprintk("svc: socket %p dropped request\n", rqstp->rq_sock);
+       dprintk("svc: xprt %p dropped request\n", rqstp->rq_xprt);
        svc_xprt_release(rqstp);
 }
 
@@ -1656,49 +1680,50 @@ svc_send(struct svc_rqst *rqstp)
  * Timer function to close old temporary sockets, using
  * a mark-and-sweep algorithm.
  */
-static void
-svc_age_temp_sockets(unsigned long closure)
+static void svc_age_temp_xprts(unsigned long closure)
 {
        struct svc_serv *serv = (struct svc_serv *)closure;
-       struct svc_sock *svsk;
+       struct svc_xprt *xprt;
        struct list_head *le, *next;
        LIST_HEAD(to_be_aged);
 
-       dprintk("svc_age_temp_sockets\n");
+       dprintk("svc_age_temp_xprts\n");
 
        if (!spin_trylock_bh(&serv->sv_lock)) {
                /* busy, try again 1 sec later */
-               dprintk("svc_age_temp_sockets: busy\n");
+               dprintk("svc_age_temp_xprts: busy\n");
                mod_timer(&serv->sv_temptimer, jiffies + HZ);
                return;
        }
 
        list_for_each_safe(le, next, &serv->sv_tempsocks) {
-               svsk = list_entry(le, struct svc_sock, sk_xprt.xpt_list);
+               xprt = list_entry(le, struct svc_xprt, xpt_list);
 
-               if (!test_and_set_bit(XPT_OLD, &svsk->sk_xprt.xpt_flags))
+               /* First time through, just mark it OLD. Second time
+                * through, close it. */
+               if (!test_and_set_bit(XPT_OLD, &xprt->xpt_flags))
                        continue;
-               if (atomic_read(&svsk->sk_xprt.xpt_ref.refcount) > 1
-                   || test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags))
+               if (atomic_read(&xprt->xpt_ref.refcount) > 1
+                   || test_bit(XPT_BUSY, &xprt->xpt_flags))
                        continue;
-               svc_xprt_get(&svsk->sk_xprt);
+               svc_xprt_get(xprt);
                list_move(le, &to_be_aged);
-               set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
-               set_bit(XPT_DETACHED, &svsk->sk_xprt.xpt_flags);
+               set_bit(XPT_CLOSE, &xprt->xpt_flags);
+               set_bit(XPT_DETACHED, &xprt->xpt_flags);
        }
        spin_unlock_bh(&serv->sv_lock);
 
        while (!list_empty(&to_be_aged)) {
                le = to_be_aged.next;
-               /* fiddling the sk_xprt.xpt_list node is safe 'cos we're XPT_DETACHED */
+               /* fiddling the xpt_list node is safe 'cos we're XPT_DETACHED */
                list_del_init(le);
-               svsk = list_entry(le, struct svc_sock, sk_xprt.xpt_list);
+               xprt = list_entry(le, struct svc_xprt, xpt_list);
 
-               dprintk("queuing svsk %p for closing\n", svsk);
+               dprintk("queuing xprt %p for closing\n", xprt);
 
                /* a thread will dequeue and close it soon */
-               svc_xprt_enqueue(&svsk->sk_xprt);
-               svc_xprt_put(&svsk->sk_xprt);
+               svc_xprt_enqueue(xprt);
+               svc_xprt_put(xprt);
        }
 
        mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ);
@@ -1715,7 +1740,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
        struct svc_sock *svsk;
        struct sock     *inet;
        int             pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
-       int             is_temporary = flags & SVC_SOCK_TEMPORARY;
 
        dprintk("svc: svc_setup_socket %p\n", sock);
        if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) {
@@ -1735,7 +1759,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
                return NULL;
        }
 
-       set_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags);
        inet->sk_user_data = svsk;
        svsk->sk_sock = sock;
        svsk->sk_sk = inet;
@@ -1749,24 +1772,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
        else
                svc_tcp_init(svsk, serv);
 
-       spin_lock_bh(&serv->sv_lock);
-       if (is_temporary) {
-               set_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags);
-               list_add(&svsk->sk_xprt.xpt_list, &serv->sv_tempsocks);
-               serv->sv_tmpcnt++;
-               if (serv->sv_temptimer.function == NULL) {
-                       /* setup timer to age temp sockets */
-                       setup_timer(&serv->sv_temptimer, svc_age_temp_sockets,
-                                       (unsigned long)serv);
-                       mod_timer(&serv->sv_temptimer,
-                                       jiffies + svc_conn_age_period * HZ);
-               }
-       } else {
-               clear_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags);
-               list_add(&svsk->sk_xprt.xpt_list, &serv->sv_permsocks);
-       }
-       spin_unlock_bh(&serv->sv_lock);
-
        dprintk("svc: svc_setup_socket created %p (inet %p)\n",
                                svsk, svsk->sk_sk);
 
@@ -1799,6 +1804,10 @@ int svc_addsock(struct svc_serv *serv,
                        int salen;
                        if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0)
                                svc_xprt_set_local(&svsk->sk_xprt, sin, salen);
+                       clear_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags);
+                       spin_lock_bh(&serv->sv_lock);
+                       list_add(&svsk->sk_xprt.xpt_list, &serv->sv_permsocks);
+                       spin_unlock_bh(&serv->sv_lock);
                        svc_xprt_received(&svsk->sk_xprt);
                        err = 0;
                }
@@ -1864,7 +1873,6 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
 
        if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) {
                svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen);
-               svc_xprt_received(&svsk->sk_xprt);
                return (struct svc_xprt *)svsk;
        }