NFS: clean up short packet handling for NFSv4 readdir
[safe/jmp/linux-2.6] / fs / nfs / client.c
index 0b3ce86..06f064d 100644 (file)
@@ -170,6 +170,8 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
        BUG_ON(!RB_EMPTY_ROOT(&clp->cl_state_owners));
        if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
                nfs_idmap_delete(clp);
+
+       rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
 #endif
 }
 
@@ -276,6 +278,41 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
 }
 
 /*
+ * Find a client by IP address and protocol version
+ * - returns NULL if no such client
+ */
+struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
+{
+       struct sockaddr *sap = (struct sockaddr *)&clp->cl_addr;
+       u32 nfsvers = clp->rpc_ops->version;
+
+       spin_lock(&nfs_client_lock);
+       list_for_each_entry_continue(clp, &nfs_client_list, cl_share_link) {
+               struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
+
+               /* Don't match clients that failed to initialise properly */
+               if (clp->cl_cons_state != NFS_CS_READY)
+                       continue;
+
+               /* Different NFS versions cannot share the same nfs_client */
+               if (clp->rpc_ops->version != nfsvers)
+                       continue;
+
+               if (sap->sa_family != clap->sa_family)
+                       continue;
+               /* Match only the IP address, not the port number */
+               if (!nfs_sockaddr_match_ipaddr(sap, clap))
+                       continue;
+
+               atomic_inc(&clp->cl_count);
+               spin_unlock(&nfs_client_lock);
+               return clp;
+       }
+       spin_unlock(&nfs_client_lock);
+       return NULL;
+}
+
+/*
  * Find an nfs_client on the list that matches the initialisation data
  * that is supplied.
  */
@@ -351,7 +388,7 @@ found_client:
        if (new)
                nfs_free_client(new);
 
-       error = wait_event_interruptible(nfs_client_active_wq,
+       error = wait_event_killable(nfs_client_active_wq,
                                clp->cl_cons_state != NFS_CS_INITING);
        if (error < 0) {
                nfs_put_client(clp);
@@ -468,18 +505,21 @@ static int nfs_start_lockd(struct nfs_server *server)
 {
        struct nlm_host *host;
        struct nfs_client *clp = server->nfs_client;
-       u32 nfs_version = clp->rpc_ops->version;
-       unsigned short protocol = server->flags & NFS_MOUNT_TCP ?
-                                               IPPROTO_TCP : IPPROTO_UDP;
+       struct nlmclnt_initdata nlm_init = {
+               .hostname       = clp->cl_hostname,
+               .address        = (struct sockaddr *)&clp->cl_addr,
+               .addrlen        = clp->cl_addrlen,
+               .protocol       = server->flags & NFS_MOUNT_TCP ?
+                                               IPPROTO_TCP : IPPROTO_UDP,
+               .nfs_version    = clp->rpc_ops->version,
+       };
 
-       if (nfs_version > 3)
+       if (nlm_init.nfs_version > 3)
                return 0;
        if (server->flags & NFS_MOUNT_NONLM)
                return 0;
 
-       host = nlmclnt_init(clp->cl_hostname,
-                           (struct sockaddr *)&clp->cl_addr,
-                           clp->cl_addrlen, protocol, nfs_version);
+       host = nlmclnt_init(&nlm_init);
        if (IS_ERR(host))
                return PTR_ERR(host);
 
@@ -551,10 +591,6 @@ static int nfs_init_server_rpcclient(struct nfs_server *server,
        if (server->flags & NFS_MOUNT_SOFT)
                server->client->cl_softrtry = 1;
 
-       server->client->cl_intr = 0;
-       if (server->flags & NFS4_MOUNT_INTR)
-               server->client->cl_intr = 1;
-
        return 0;
 }