]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sunrpc/svcsock.c
[NET] Cleanup: Use sock_owned_by_user() macro
[linux-2.6-omap-h63xx.git] / net / sunrpc / svcsock.c
index 22f61aee4824cea33b419529f62bb5eee599f5fd..c75bffeb89eb705831585ba1447c0ba77dd06a9c 100644 (file)
@@ -19,6 +19,7 @@
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  */
 
+#include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/fcntl.h>
@@ -53,7 +54,8 @@
  *     svc_serv->sv_lock protects sv_tempsocks, sv_permsocks, sv_tmpcnt.
  *     when both need to be taken (rare), svc_serv->sv_lock is first.
  *     BKL protects svc_serv->sv_nrthread.
- *     svc_sock->sk_defer_lock protects the svc_sock->sk_deferred list
+ *     svc_sock->sk_lock protects the svc_sock->sk_deferred list
+ *             and the ->sk_info_authunix cache.
  *     svc_sock->sk_flags.SK_BUSY prevents a svc_sock being enqueued multiply.
  *
  *     Some flags can be set to certain values at any time
@@ -102,7 +104,7 @@ static struct lock_class_key svc_slock_key[2];
 static inline void svc_reclassify_socket(struct socket *sock)
 {
        struct sock *sk = sock->sk;
-       BUG_ON(sk->sk_lock.owner != NULL);
+       BUG_ON(sock_owned_by_user(sk));
        switch (sk->sk_family) {
        case AF_INET:
                sock_lock_init_class_and_name(sk, "slock-AF_INET-NFSD",
@@ -130,13 +132,13 @@ static char *__svc_print_addr(struct sockaddr *addr, char *buf, size_t len)
        case AF_INET:
                snprintf(buf, len, "%u.%u.%u.%u, port=%u",
                        NIPQUAD(((struct sockaddr_in *) addr)->sin_addr),
-                       htons(((struct sockaddr_in *) addr)->sin_port));
+                       ntohs(((struct sockaddr_in *) addr)->sin_port));
                break;
 
        case AF_INET6:
                snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x, port=%u",
                        NIP6(((struct sockaddr_in6 *) addr)->sin6_addr),
-                       htons(((struct sockaddr_in6 *) addr)->sin6_port));
+                       ntohs(((struct sockaddr_in6 *) addr)->sin6_port));
                break;
 
        default:
@@ -643,6 +645,7 @@ svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen)
        struct msghdr msg = {
                .msg_flags      = MSG_DONTWAIT,
        };
+       struct sockaddr *sin;
        int len;
 
        len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
@@ -653,6 +656,19 @@ svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen)
        memcpy(&rqstp->rq_addr, &svsk->sk_remote, svsk->sk_remotelen);
        rqstp->rq_addrlen = svsk->sk_remotelen;
 
+       /* Destination address in request is needed for binding the
+        * source address in RPC callbacks later.
+        */
+       sin = (struct sockaddr *)&svsk->sk_local;
+       switch (sin->sa_family) {
+       case AF_INET:
+               rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr;
+               break;
+       case AF_INET6:
+               rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr;
+               break;
+       }
+
        dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
                svsk, iov[0].iov_base, iov[0].iov_len, len);
 
@@ -787,15 +803,20 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
        }
 
        clear_bit(SK_DATA, &svsk->sk_flags);
-       while ((err = kernel_recvmsg(svsk->sk_sock, &msg, NULL,
-                                    0, 0, MSG_PEEK | MSG_DONTWAIT)) < 0 ||
-              (skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) {
-               if (err == -EAGAIN) {
-                       svc_sock_received(svsk);
-                       return err;
+       skb = NULL;
+       err = kernel_recvmsg(svsk->sk_sock, &msg, NULL,
+                            0, 0, MSG_PEEK | MSG_DONTWAIT);
+       if (err >= 0)
+               skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err);
+
+       if (skb == NULL) {
+               if (err != -EAGAIN) {
+                       /* possibly an icmp error */
+                       dprintk("svc: recvfrom returned error %d\n", -err);
+                       set_bit(SK_DATA, &svsk->sk_flags);
                }
-               /* possibly an icmp error */
-               dprintk("svc: recvfrom returned error %d\n", -err);
+               svc_sock_received(svsk);
+               return -EAGAIN;
        }
        rqstp->rq_addrlen = sizeof(rqstp->rq_addr);
        if (skb->tstamp.tv64 == 0) {
@@ -857,7 +878,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
        } else {
                rqstp->rq_arg.page_len = len - rqstp->rq_arg.head[0].iov_len;
                rqstp->rq_respages = rqstp->rq_pages + 1 +
-                       (rqstp->rq_arg.page_len + PAGE_SIZE - 1)/ PAGE_SIZE;
+                       DIV_ROUND_UP(rqstp->rq_arg.page_len, PAGE_SIZE);
        }
 
        if (serv->sv_stats)
@@ -1058,6 +1079,12 @@ svc_tcp_accept(struct svc_sock *svsk)
                goto failed;
        memcpy(&newsvsk->sk_remote, sin, slen);
        newsvsk->sk_remotelen = slen;
+       err = kernel_getsockname(newsock, sin, &slen);
+       if (unlikely(err < 0)) {
+               dprintk("svc_tcp_accept: kernel_getsockname error %d\n", -err);
+               slen = offsetof(struct sockaddr, sa_data);
+       }
+       memcpy(&newsvsk->sk_local, sin, slen);
 
        svc_sock_received(newsvsk);
 
@@ -1084,7 +1111,8 @@ svc_tcp_accept(struct svc_sock *svsk)
                                                   serv->sv_name);
                                printk(KERN_NOTICE
                                       "%s: last TCP connect from %s\n",
-                                      serv->sv_name, buf);
+                                      serv->sv_name, __svc_print_addr(sin,
+                                                       buf, sizeof(buf)));
                        }
                        /*
                         * Always select the oldest socket. It's not fair,
@@ -1566,7 +1594,7 @@ svc_age_temp_sockets(unsigned long closure)
 
                if (!test_and_set_bit(SK_OLD, &svsk->sk_flags))
                        continue;
-               if (atomic_read(&svsk->sk_inuse) || test_bit(SK_BUSY, &svsk->sk_flags))
+               if (atomic_read(&svsk->sk_inuse) > 1 || test_bit(SK_BUSY, &svsk->sk_flags))
                        continue;
                atomic_inc(&svsk->sk_inuse);
                list_move(le, &to_be_aged);
@@ -1633,7 +1661,7 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
        svsk->sk_server = serv;
        atomic_set(&svsk->sk_inuse, 1);
        svsk->sk_lastrecv = get_seconds();
-       spin_lock_init(&svsk->sk_defer_lock);
+       spin_lock_init(&svsk->sk_lock);
        INIT_LIST_HEAD(&svsk->sk_deferred);
        INIT_LIST_HEAD(&svsk->sk_ready);
        mutex_init(&svsk->sk_mutex);
@@ -1857,9 +1885,9 @@ static void svc_revisit(struct cache_deferred_req *dreq, int too_many)
        dprintk("revisit queued\n");
        svsk = dr->svsk;
        dr->svsk = NULL;
-       spin_lock_bh(&svsk->sk_defer_lock);
+       spin_lock(&svsk->sk_lock);
        list_add(&dr->handle.recent, &svsk->sk_deferred);
-       spin_unlock_bh(&svsk->sk_defer_lock);
+       spin_unlock(&svsk->sk_lock);
        set_bit(SK_DEFERRED, &svsk->sk_flags);
        svc_sock_enqueue(svsk);
        svc_sock_put(svsk);
@@ -1925,7 +1953,7 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk)
 
        if (!test_bit(SK_DEFERRED, &svsk->sk_flags))
                return NULL;
-       spin_lock_bh(&svsk->sk_defer_lock);
+       spin_lock(&svsk->sk_lock);
        clear_bit(SK_DEFERRED, &svsk->sk_flags);
        if (!list_empty(&svsk->sk_deferred)) {
                dr = list_entry(svsk->sk_deferred.next,
@@ -1934,6 +1962,6 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk)
                list_del_init(&dr->handle.recent);
                set_bit(SK_DEFERRED, &svsk->sk_flags);
        }
-       spin_unlock_bh(&svsk->sk_defer_lock);
+       spin_unlock(&svsk->sk_lock);
        return dr;
 }