Btrfs: always pin metadata in discard mode
[safe/jmp/linux-2.6] / fs / nfs / client.c
index d9657d4..8d25ccb 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/in6.h>
 #include <net/ipv6.h>
 #include <linux/nfs_xdr.h>
+#include <linux/sunrpc/bc_xprt.h>
 
 #include <asm/system.h>
 
@@ -47,9 +48,6 @@
 #include "internal.h"
 #include "fscache.h"
 
-static int nfs4_init_callback(struct nfs_client *);
-static void nfs4_destroy_callback(struct nfs_client *);
-
 #define NFSDBG_FACILITY                NFSDBG_CLIENT
 
 static DEFINE_SPINLOCK(nfs_client_lock);
@@ -118,15 +116,13 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
 {
        struct nfs_client *clp;
        struct rpc_cred *cred;
+       int err = -ENOMEM;
 
        if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
                goto error_0;
 
        clp->rpc_ops = cl_init->rpc_ops;
 
-       if (nfs4_init_callback(clp) < 0)
-               goto error_2;
-
        atomic_set(&clp->cl_count, 1);
        clp->cl_cons_state = NFS_CS_INITING;
 
@@ -134,9 +130,10 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
        clp->cl_addrlen = cl_init->addrlen;
 
        if (cl_init->hostname) {
+               err = -ENOMEM;
                clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL);
                if (!clp->cl_hostname)
-                       goto error_3;
+                       goto error_cleanup;
        }
 
        INIT_LIST_HEAD(&clp->cl_superblocks);
@@ -161,12 +158,10 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
 
        return clp;
 
-error_3:
-       nfs4_destroy_callback(clp);
-error_2:
+error_cleanup:
        kfree(clp);
 error_0:
-       return NULL;
+       return ERR_PTR(err);
 }
 
 static void nfs4_shutdown_client(struct nfs_client *clp)
@@ -189,7 +184,7 @@ static void nfs4_destroy_callback(struct nfs_client *clp)
 {
 #ifdef CONFIG_NFS_V4
        if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
-               nfs_callback_down();
+               nfs_callback_down(clp->cl_minorversion);
 #endif /* CONFIG_NFS_V4 */
 }
 
@@ -207,6 +202,8 @@ static void nfs4_clear_client_minor_version(struct nfs_client *clp)
 
        clp->cl_call_sync = _nfs4_call_sync;
 #endif /* CONFIG_NFS_V4_1 */
+
+       nfs4_destroy_callback(clp);
 }
 
 /*
@@ -225,8 +222,6 @@ static void nfs_free_client(struct nfs_client *clp)
        if (!IS_ERR(clp->cl_rpcclient))
                rpc_shutdown_client(clp->cl_rpcclient);
 
-       nfs4_destroy_callback(clp);
-
        if (clp->cl_machine_cred != NULL)
                put_rpccred(clp->cl_machine_cred);
 
@@ -487,9 +482,10 @@ static struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_in
                spin_unlock(&nfs_client_lock);
 
                new = nfs_alloc_client(cl_init);
-       } while (new);
+       } while (!IS_ERR(new));
 
-       return ERR_PTR(-ENOMEM);
+       dprintk("--> nfs_get_client() = %ld [failed]\n", PTR_ERR(new));
+       return new;
 
        /* install a new client and return with it unready */
 install_client:
@@ -1104,7 +1100,16 @@ static int nfs4_init_callback(struct nfs_client *clp)
        int error;
 
        if (clp->rpc_ops->version == 4) {
-               error = nfs_callback_up();
+               if (nfs4_has_session(clp)) {
+                       error = xprt_setup_backchannel(
+                                               clp->cl_rpcclient->cl_xprt,
+                                               NFS41_BC_MIN_CALLBACKS);
+                       if (error < 0)
+                               return error;
+               }
+
+               error = nfs_callback_up(clp->cl_minorversion,
+                                       clp->cl_rpcclient->cl_xprt);
                if (error < 0) {
                        dprintk("%s: failed to start callback. Error = %d\n",
                                __func__, error);
@@ -1139,7 +1144,7 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp)
        }
 #endif /* CONFIG_NFS_V4_1 */
 
-       return 0;
+       return nfs4_init_callback(clp);
 }
 
 /*
@@ -1237,20 +1242,6 @@ error:
        return error;
 }
 
-/*
- * Initialize a session.
- * Note: save the mount rsize and wsize for create_server negotiation.
- */
-static void nfs4_init_session(struct nfs_client *clp,
-                             unsigned int wsize, unsigned int rsize)
-{
-#if defined(CONFIG_NFS_V4_1)
-       if (nfs4_has_session(clp)) {
-               clp->cl_session->fc_attrs.max_rqst_sz = wsize;
-               clp->cl_session->fc_attrs.max_resp_sz = rsize;
-       }
-#endif /* CONFIG_NFS_V4_1 */
-}
 
 /*
  * Session has been established, and the client marked ready.
@@ -1345,7 +1336,9 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
        BUG_ON(!server->nfs_client->rpc_ops);
        BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
 
-       nfs4_init_session(server->nfs_client, server->wsize, server->rsize);
+       error = nfs4_init_session(server);
+       if (error < 0)
+               goto error;
 
        /* Probe the root fh to retrieve its FSID */
        error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path);