rt2x00: Disable RX when switching antenna
[safe/jmp/linux-2.6] / fs / lockd / host.c
index 4449ef0..572601e 100644 (file)
@@ -9,7 +9,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/sunrpc/clnt.h>
@@ -36,38 +35,17 @@ static DEFINE_MUTEX(nlm_host_mutex);
 static void                    nlm_gc_hosts(void);
 static struct nsm_handle *     __nsm_find(const struct sockaddr_in *,
                                        const char *, int, int);
-
-/*
- * Find an NLM server handle in the cache. If there is none, create it.
- */
-struct nlm_host *
-nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version,
-                       const char *hostname, int hostname_len)
-{
-       return nlm_lookup_host(0, sin, proto, version,
-                              hostname, hostname_len);
-}
-
-/*
- * Find an NLM client handle in the cache. If there is none, create it.
- */
-struct nlm_host *
-nlmsvc_lookup_host(struct svc_rqst *rqstp,
-                       const char *hostname, int hostname_len)
-{
-       return nlm_lookup_host(1, &rqstp->rq_addr,
-                              rqstp->rq_prot, rqstp->rq_vers,
-                              hostname, hostname_len);
-}
+static struct nsm_handle *     nsm_find(const struct sockaddr_in *sin,
+                                        const char *hostname,
+                                        int hostname_len);
 
 /*
  * Common host lookup routine for server & client
  */
-struct nlm_host *
+static struct nlm_host *
 nlm_lookup_host(int server, const struct sockaddr_in *sin,
-                                       int proto, int version,
-                                       const char *hostname,
-                                       int hostname_len)
+               int proto, int version, const char *hostname,
+               int hostname_len, const struct sockaddr_in *ssin)
 {
        struct hlist_head *chain;
        struct hlist_node *pos;
@@ -75,7 +53,9 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
        struct nsm_handle *nsm = NULL;
        int             hash;
 
-       dprintk("lockd: nlm_lookup_host(%u.%u.%u.%u, p=%d, v=%d, my role=%s, name=%.*s)\n",
+       dprintk("lockd: nlm_lookup_host("NIPQUAD_FMT"->"NIPQUAD_FMT
+                       ", p=%d, v=%d, my role=%s, name=%.*s)\n",
+                       NIPQUAD(ssin->sin_addr.s_addr),
                        NIPQUAD(sin->sin_addr.s_addr), proto, version,
                        server? "server" : "client",
                        hostname_len,
@@ -103,8 +83,8 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
                        continue;
 
                /* See if we have an NSM handle for this client */
-               if (!nsm && (nsm = host->h_nsmhandle) != 0)
-                       atomic_inc(&nsm->sm_count);
+               if (!nsm)
+                       nsm = host->h_nsmhandle;
 
                if (host->h_proto != proto)
                        continue;
@@ -112,6 +92,8 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
                        continue;
                if (host->h_server != server)
                        continue;
+               if (!nlm_cmp_addr(&host->h_saddr, ssin))
+                       continue;
 
                /* Move to head of hash chain. */
                hlist_del(&host->h_hash);
@@ -120,6 +102,8 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
                nlm_get_host(host);
                goto out;
        }
+       if (nsm)
+               atomic_inc(&nsm->sm_count);
 
        host = NULL;
 
@@ -137,6 +121,7 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
        host->h_name       = nsm->sm_name;
        host->h_addr       = *sin;
        host->h_addr.sin_port = 0;      /* ouch! */
+       host->h_saddr      = *ssin;
        host->h_version    = version;
        host->h_proto      = proto;
        host->h_rpcclnt    = NULL;
@@ -164,33 +149,56 @@ out:
        return host;
 }
 
-struct nlm_host *
-nlm_find_client(void)
+/*
+ * Destroy a host
+ */
+static void
+nlm_destroy_host(struct nlm_host *host)
 {
-       struct hlist_head *chain;
-       struct hlist_node *pos;
+       struct rpc_clnt *clnt;
+
+       BUG_ON(!list_empty(&host->h_lockowners));
+       BUG_ON(atomic_read(&host->h_count));
 
-       /* find a nlm_host for a client for which h_killed == 0.
-        * and return it
+       /*
+        * Release NSM handle and unmonitor host.
         */
-       mutex_lock(&nlm_host_mutex);
-       for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
-               struct nlm_host *host;
+       nsm_unmonitor(host);
 
-               hlist_for_each_entry(host, pos, chain, h_hash) {
-                       if (host->h_server &&
-                           host->h_killed == 0) {
-                               nlm_get_host(host);
-                               mutex_unlock(&nlm_host_mutex);
-                               return host;
-                       }
-               }
-       }
-       mutex_unlock(&nlm_host_mutex);
-       return NULL;
+       clnt = host->h_rpcclnt;
+       if (clnt != NULL)
+               rpc_shutdown_client(clnt);
+       kfree(host);
+}
+
+/*
+ * Find an NLM server handle in the cache. If there is none, create it.
+ */
+struct nlm_host *
+nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version,
+                       const char *hostname, int hostname_len)
+{
+       struct sockaddr_in ssin = {0};
+
+       return nlm_lookup_host(0, sin, proto, version,
+                              hostname, hostname_len, &ssin);
+}
+
+/*
+ * Find an NLM client handle in the cache. If there is none, create it.
+ */
+struct nlm_host *
+nlmsvc_lookup_host(struct svc_rqst *rqstp,
+                       const char *hostname, int hostname_len)
+{
+       struct sockaddr_in ssin = {0};
+
+       ssin.sin_addr = rqstp->rq_daddr.addr;
+       return nlm_lookup_host(1, svc_addr_in(rqstp),
+                              rqstp->rq_prot, rqstp->rq_vers,
+                              hostname, hostname_len, &ssin);
 }
 
-                               
 /*
  * Create the NLM RPC client for an NLM peer
  */
@@ -199,8 +207,9 @@ nlm_bind_host(struct nlm_host *host)
 {
        struct rpc_clnt *clnt;
 
-       dprintk("lockd: nlm_bind_host(%08x)\n",
-                       (unsigned)ntohl(host->h_addr.sin_addr.s_addr));
+       dprintk("lockd: nlm_bind_host("NIPQUAD_FMT"->"NIPQUAD_FMT")\n",
+                       NIPQUAD(host->h_saddr.sin_addr),
+                       NIPQUAD(host->h_addr.sin_addr));
 
        /* Lock host handle */
        mutex_lock(&host->h_mutex);
@@ -216,7 +225,7 @@ nlm_bind_host(struct nlm_host *host)
                                        host->h_nextrebind - jiffies);
                }
        } else {
-               unsigned long increment = nlmsvc_timeout * HZ;
+               unsigned long increment = nlmsvc_timeout;
                struct rpc_timeout timeparms = {
                        .to_initval     = increment,
                        .to_increment   = increment,
@@ -227,6 +236,7 @@ nlm_bind_host(struct nlm_host *host)
                        .protocol       = host->h_proto,
                        .address        = (struct sockaddr *)&host->h_addr,
                        .addrsize       = sizeof(host->h_addr),
+                       .saddress       = (struct sockaddr *)&host->h_saddr,
                        .timeout        = &timeparms,
                        .servername     = host->h_name,
                        .program        = &nlm_program,
@@ -400,7 +410,6 @@ nlm_gc_hosts(void)
        struct hlist_head *chain;
        struct hlist_node *pos, *next;
        struct nlm_host *host;
-       struct rpc_clnt *clnt;
 
        dprintk("lockd: host garbage collection\n");
        for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
@@ -423,21 +432,7 @@ nlm_gc_hosts(void)
                        dprintk("lockd: delete host %s\n", host->h_name);
                        hlist_del_init(&host->h_hash);
 
-                       /*
-                        * Unmonitor unless host was invalidated (i.e. lockd restarted)
-                        */
-                       nsm_unmonitor(host);
-
-                       if ((clnt = host->h_rpcclnt) != NULL) {
-                               if (atomic_read(&clnt->cl_users)) {
-                                       printk(KERN_WARNING
-                                               "lockd: active RPC handle\n");
-                                       clnt->cl_dead = 1;
-                               } else {
-                                       rpc_destroy_client(host->h_rpcclnt);
-                               }
-                       }
-                       kfree(host);
+                       nlm_destroy_host(host);
                        nrhosts--;
                }
        }
@@ -450,7 +445,7 @@ nlm_gc_hosts(void)
  * Manage NSM handles
  */
 static LIST_HEAD(nsm_handles);
-static DECLARE_MUTEX(nsm_sema);
+static DEFINE_MUTEX(nsm_mutex);
 
 static struct nsm_handle *
 __nsm_find(const struct sockaddr_in *sin,
@@ -472,11 +467,15 @@ __nsm_find(const struct sockaddr_in *sin,
                return NULL;
        }
 
-       down(&nsm_sema);
+       mutex_lock(&nsm_mutex);
        list_for_each(pos, &nsm_handles) {
                nsm = list_entry(pos, struct nsm_handle, sm_link);
 
-               if (!nlm_cmp_addr(&nsm->sm_addr, sin))
+               if (hostname && nsm_use_hostnames) {
+                       if (strlen(nsm->sm_name) != hostname_len
+                        || memcmp(nsm->sm_name, hostname, hostname_len))
+                               continue;
+               } else if (!nlm_cmp_addr(&nsm->sm_addr, sin))
                        continue;
                atomic_inc(&nsm->sm_count);
                goto out;
@@ -498,11 +497,12 @@ __nsm_find(const struct sockaddr_in *sin,
                list_add(&nsm->sm_link, &nsm_handles);
        }
 
-out:   up(&nsm_sema);
+out:
+       mutex_unlock(&nsm_mutex);
        return nsm;
 }
 
-struct nsm_handle *
+static struct nsm_handle *
 nsm_find(const struct sockaddr_in *sin, const char *hostname, int hostname_len)
 {
        return __nsm_find(sin, hostname, hostname_len, 1);
@@ -517,11 +517,11 @@ nsm_release(struct nsm_handle *nsm)
        if (!nsm)
                return;
        if (atomic_dec_and_test(&nsm->sm_count)) {
-               down(&nsm_sema);
+               mutex_lock(&nsm_mutex);
                if (atomic_read(&nsm->sm_count) == 0) {
                        list_del(&nsm->sm_link);
                        kfree(nsm);
                }
-               up(&nsm_sema);
+               mutex_unlock(&nsm_mutex);
        }
 }