]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - fs/nfs/super.c
NFS: Start rpciod in server common management
[mirror_ubuntu-bionic-kernel.git] / fs / nfs / super.c
index d03ede5b1aca7b4217aad1011683b6c74bdf315f..5842d510d732ce98d150ece4d7dd869bf4e66581 100644 (file)
  */
 #define NFS_MAX_READAHEAD      (RPC_DEF_SLOT_TABLE - 1)
 
-/*
- * RPC cruft for NFS
- */
-static struct rpc_version * nfs_version[] = {
-       NULL,
-       NULL,
-       &nfs_version2,
-#if defined(CONFIG_NFS_V3)
-       &nfs_version3,
-#elif defined(CONFIG_NFS_V4)
-       NULL,
-#endif
-#if defined(CONFIG_NFS_V4)
-       &nfs_version4,
-#endif
-};
-
-static struct rpc_program nfs_program = {
-       .name                   = "nfs",
-       .number                 = NFS_PROGRAM,
-       .nrvers                 = ARRAY_SIZE(nfs_version),
-       .version                = nfs_version,
-       .stats                  = &nfs_rpcstat,
-       .pipe_dir_name          = "/nfs",
-};
-
-struct rpc_stat nfs_rpcstat = {
-       .program                = &nfs_program
-};
-
-
-#ifdef CONFIG_NFS_V3_ACL
-static struct rpc_stat         nfsacl_rpcstat = { &nfsacl_program };
-static struct rpc_version *    nfsacl_version[] = {
-       [3]                     = &nfsacl_version3,
-};
-
-struct rpc_program             nfsacl_program = {
-       .name =                 "nfsacl",
-       .number =               NFS_ACL_PROGRAM,
-       .nrvers =               ARRAY_SIZE(nfsacl_version),
-       .version =              nfsacl_version,
-       .stats =                &nfsacl_rpcstat,
-};
-#endif  /* CONFIG_NFS_V3_ACL */
-
 static void nfs_umount_begin(struct vfsmount *, int);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
 static int  nfs_show_options(struct seq_file *, struct vfsmount *);
@@ -240,11 +194,10 @@ void __exit unregister_nfs_fs(void)
  */
 static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-       struct super_block *sb = dentry->d_sb;
-       struct nfs_server *server = NFS_SB(sb);
+       struct nfs_server *server = NFS_SB(dentry->d_sb);
        unsigned char blockbits;
        unsigned long blockres;
-       struct nfs_fh *rootfh = NFS_FH(sb->s_root->d_inode);
+       struct nfs_fh *fh = NFS_FH(dentry->d_inode);
        struct nfs_fattr fattr;
        struct nfs_fsstat res = {
                        .fattr = &fattr,
@@ -253,7 +206,7 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 
        lock_kernel();
 
-       error = server->rpc_ops->statfs(server, rootfh, &res);
+       error = server->nfs_client->rpc_ops->statfs(server, fh, &res);
        buf->f_type = NFS_SUPER_MAGIC;
        if (error < 0)
                goto out_err;
@@ -263,7 +216,7 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
         * case where f_frsize != f_bsize.  Eventually we want to
         * report the value of wtmult in this field.
         */
-       buf->f_frsize = sb->s_blocksize;
+       buf->f_frsize = dentry->d_sb->s_blocksize;
 
        /*
         * On most *nix systems, f_blocks, f_bfree, and f_bavail
@@ -272,8 +225,8 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
         * thus historically Linux's sys_statfs reports these
         * fields in units of f_bsize.
         */
-       buf->f_bsize = sb->s_blocksize;
-       blockbits = sb->s_blocksize_bits;
+       buf->f_bsize = dentry->d_sb->s_blocksize;
+       blockbits = dentry->d_sb->s_blocksize_bits;
        blockres = (1 << blockbits) - 1;
        buf->f_blocks = (res.tbytes + blockres) >> blockbits;
        buf->f_bfree = (res.fbytes + blockres) >> blockbits;
@@ -330,10 +283,10 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
  */
 static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
 {
-       static struct proc_nfs_info {
+       static const struct proc_nfs_info {
                int flag;
-               char *str;
-               char *nostr;
+               const char *str;
+               const char *nostr;
        } nfs_info[] = {
                { NFS_MOUNT_SOFT, ",soft", ",hard" },
                { NFS_MOUNT_INTR, ",intr", "" },
@@ -343,11 +296,12 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
                { NFS_MOUNT_NOACL, ",noacl", "" },
                { 0, NULL, NULL }
        };
-       struct proc_nfs_info *nfs_infop;
+       const struct proc_nfs_info *nfs_infop;
+       struct nfs_client *clp = nfss->nfs_client;
        char buf[12];
-       char *proto;
+       const char *proto;
 
-       seq_printf(m, ",vers=%d", nfss->rpc_ops->version);
+       seq_printf(m, ",vers=%d", clp->rpc_ops->version);
        seq_printf(m, ",rsize=%d", nfss->rsize);
        seq_printf(m, ",wsize=%d", nfss->wsize);
        if (nfss->acregmin != 3*HZ || showdefaults)
@@ -376,8 +330,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
                        proto = buf;
        }
        seq_printf(m, ",proto=%s", proto);
-       seq_printf(m, ",timeo=%lu", 10U * nfss->retrans_timeo / HZ);
-       seq_printf(m, ",retrans=%u", nfss->retrans_count);
+       seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ);
+       seq_printf(m, ",retrans=%u", clp->retrans_count);
        seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor));
 }
 
@@ -428,7 +382,7 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
        seq_printf(m, ",namelen=%d", nfss->namelen);
 
 #ifdef CONFIG_NFS_V4
-       if (nfss->rpc_ops->version == 4) {
+       if (nfss->nfs_client->cl_nfsversion == 4) {
                seq_printf(m, "\n\tnfsv4:\t");
                seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
                seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
@@ -504,7 +458,7 @@ nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *f
        struct nfs_server       *server = NFS_SB(sb);
        int                     error;
 
-       error = server->rpc_ops->getroot(server, rootfh, fsinfo);
+       error = server->nfs_client->rpc_ops->getroot(server, rootfh, fsinfo);
        if (error < 0) {
                dprintk("nfs_get_root: getattr error = %d\n", -error);
                return ERR_PTR(error);
@@ -554,14 +508,14 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
                no_root_error = -ENOMEM;
                goto out_no_root;
        }
-       sb->s_root->d_op = server->rpc_ops->dentry_ops;
+       sb->s_root->d_op = server->nfs_client->rpc_ops->dentry_ops;
 
        /* mount time stamp, in seconds */
        server->mount_time = jiffies;
 
        /* Get some general file system info */
        if (server->namelen == 0 &&
-           server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
+           server->nfs_client->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
                server->namelen = pathinfo.max_namelen;
        /* Work out a lot of parameters */
        if (server->rsize == 0)
@@ -621,76 +575,77 @@ out_no_root:
        return no_root_error;
 }
 
-/*
- * Initialise the timeout values for a connection
- */
-static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans)
-{
-       to->to_initval = timeo * HZ / 10;
-       to->to_retries = retrans;
-       if (!to->to_retries)
-               to->to_retries = 2;
-
-       switch (proto) {
-       case IPPROTO_TCP:
-               if (!to->to_initval)
-                       to->to_initval = 60 * HZ;
-               if (to->to_initval > NFS_MAX_TCP_TIMEOUT)
-                       to->to_initval = NFS_MAX_TCP_TIMEOUT;
-               to->to_increment = to->to_initval;
-               to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
-               to->to_exponential = 0;
-               break;
-       case IPPROTO_UDP:
-       default:
-               if (!to->to_initval)
-                       to->to_initval = 11 * HZ / 10;
-               if (to->to_initval > NFS_MAX_UDP_TIMEOUT)
-                       to->to_initval = NFS_MAX_UDP_TIMEOUT;
-               to->to_maxval = NFS_MAX_UDP_TIMEOUT;
-               to->to_exponential = 1;
-               break;
-       }
-}
-
 /*
  * Create an RPC client handle.
  */
 static struct rpc_clnt *
 nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
 {
-       struct rpc_timeout      timeparms;
-       struct rpc_xprt         *xprt = NULL;
-       struct rpc_clnt         *clnt = NULL;
+       struct nfs_client       *clp;
+       struct rpc_clnt         *clnt;
        int                     proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
+       int                     nfsversion = 2;
+       int                     err;
 
-       nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans);
+#ifdef CONFIG_NFS_V3
+       if (server->flags & NFS_MOUNT_VER3)
+               nfsversion = 3;
+#endif
+
+       clp = nfs_get_client(server->hostname, &server->addr, nfsversion);
+       if (!clp) {
+               dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
+               return ERR_PTR(PTR_ERR(clp));
+       }
+
+       if (clp->cl_cons_state == NFS_CS_INITING) {
+               /* Check NFS protocol revision and initialize RPC op
+                * vector and file handle pool. */
+#ifdef CONFIG_NFS_V3
+               if (nfsversion == 3) {
+                       clp->rpc_ops = &nfs_v3_clientops;
+                       server->caps |= NFS_CAP_READDIRPLUS;
+               } else {
+                       clp->rpc_ops = &nfs_v2_clientops;
+               }
+#else
+               clp->rpc_ops = &nfs_v2_clientops;
+#endif
 
-       server->retrans_timeo = timeparms.to_initval;
-       server->retrans_count = timeparms.to_retries;
+               /* create transport and client */
+               err = nfs_create_rpc_client(clp, proto, data->timeo,
+                                           data->retrans, RPC_AUTH_UNIX);
+               if (err < 0)
+                       goto client_init_error;
 
-       /* create transport and client */
-       xprt = xprt_create_proto(proto, &server->addr, &timeparms);
-       if (IS_ERR(xprt)) {
-               dprintk("%s: cannot create RPC transport. Error = %ld\n",
-                               __FUNCTION__, PTR_ERR(xprt));
-               return (struct rpc_clnt *)xprt;
+               nfs_mark_client_ready(clp, 0);
        }
-       clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
-                                server->rpc_ops->version, data->pseudoflavor);
+
+       /* create an nfs_server-specific client */
+       clnt = rpc_clone_client(clp->cl_rpcclient);
        if (IS_ERR(clnt)) {
-               dprintk("%s: cannot create RPC client. Error = %ld\n",
-                               __FUNCTION__, PTR_ERR(xprt));
-               goto out_fail;
+               dprintk("%s: couldn't create rpc_client!\n", __FUNCTION__);
+               nfs_put_client(clp);
+               return ERR_PTR(PTR_ERR(clnt));
        }
 
-       clnt->cl_intr     = 1;
-       clnt->cl_softrtry = 1;
+       if (data->pseudoflavor != clp->cl_rpcclient->cl_auth->au_flavor) {
+               struct rpc_auth *auth;
 
-       return clnt;
+               auth = rpcauth_create(data->pseudoflavor, server->client);
+               if (IS_ERR(auth)) {
+                       dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
+                       return ERR_PTR(PTR_ERR(auth));
+               }
+       }
 
-out_fail:
+       server->nfs_client = clp;
        return clnt;
+
+client_init_error:
+       nfs_mark_client_ready(clp, err);
+       nfs_put_client(clp);
+       return ERR_PTR(err);
 }
 
 /*
@@ -709,7 +664,7 @@ static struct nfs_server *nfs_clone_server(struct super_block *sb, struct nfs_cl
        sb->s_blocksize_bits = data->sb->s_blocksize_bits;
        sb->s_maxbytes = data->sb->s_maxbytes;
 
-       server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
+       server->client_acl = ERR_PTR(-EINVAL);
        server->io_stats = nfs_alloc_iostats();
        if (server->io_stats == NULL)
                goto out;
@@ -718,11 +673,6 @@ static struct nfs_server *nfs_clone_server(struct super_block *sb, struct nfs_cl
        if (IS_ERR((err = server->client)))
                goto out;
 
-       if (!IS_ERR(parent->client_sys)) {
-               server->client_sys = rpc_clone_client(parent->client_sys);
-               if (IS_ERR((err = server->client_sys)))
-                       goto out;
-       }
        if (!IS_ERR(parent->client_acl)) {
                server->client_acl = rpc_clone_client(parent->client_acl);
                if (IS_ERR((err = server->client_acl)))
@@ -737,7 +687,7 @@ static struct nfs_server *nfs_clone_server(struct super_block *sb, struct nfs_cl
        fsinfo.fattr = data->fattr;
        if (NFS_PROTO(root_inode)->fsinfo(server, data->fh, &fsinfo) == 0)
                nfs_super_set_maxbytes(sb, fsinfo.maxfilesize);
-       sb->s_root->d_op = server->rpc_ops->dentry_ops;
+       sb->s_root->d_op = server->nfs_client->rpc_ops->dentry_ops;
        sb->s_flags |= MS_ACTIVE;
        return server;
 out_put_root:
@@ -765,24 +715,22 @@ static int nfs_clone_generic_sb(struct nfs_clone_mount *data,
        if (server == NULL)
                goto out_err;
        memcpy(server, parent, sizeof(*server));
+       atomic_inc(&server->nfs_client->cl_count);
        hostname = (data->hostname != NULL) ? data->hostname : parent->hostname;
        len = strlen(hostname) + 1;
        server->hostname = kmalloc(len, GFP_KERNEL);
        if (server->hostname == NULL)
                goto free_server;
        memcpy(server->hostname, hostname, len);
-       error = rpciod_up();
-       if (error != 0)
-               goto free_hostname;
 
        sb = fill_sb(server, data);
        if (IS_ERR(sb)) {
                error = PTR_ERR(sb);
-               goto kill_rpciod;
+               goto free_hostname;
        }
-               
+
        if (sb->s_root)
-               goto out_rpciod_down;
+               goto out_share;
 
        server = fill_server(sb, data);
        if (IS_ERR(server)) {
@@ -794,16 +742,15 @@ out_deactivate:
        up_write(&sb->s_umount);
        deactivate_super(sb);
        return error;
-out_rpciod_down:
-       rpciod_down();
+out_share:
        kfree(server->hostname);
+       nfs_put_client(server->nfs_client);
        kfree(server);
        return simple_set_mnt(mnt, sb);
-kill_rpciod:
-       rpciod_down();
 free_hostname:
        kfree(server->hostname);
 free_server:
+       nfs_put_client(server->nfs_client);
        kfree(server);
 out_err:
        return error;
@@ -849,19 +796,6 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
                return -ENOMEM;
        strcpy(server->hostname, data->hostname);
 
-       /* Check NFS protocol revision and initialize RPC op vector
-        * and file handle pool. */
-#ifdef CONFIG_NFS_V3
-       if (server->flags & NFS_MOUNT_VER3) {
-               server->rpc_ops = &nfs_v3_clientops;
-               server->caps |= NFS_CAP_READDIRPLUS;
-       } else {
-               server->rpc_ops = &nfs_v2_clientops;
-       }
-#else
-       server->rpc_ops = &nfs_v2_clientops;
-#endif
-
        /* Fill in pseudoflavor for mount version < 5 */
        if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
                data->pseudoflavor = RPC_AUTH_UNIX;
@@ -872,20 +806,8 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
        server->client = nfs_create_client(server, data);
        if (IS_ERR(server->client))
                return PTR_ERR(server->client);
-       /* RFC 2623, sec 2.3.2 */
-       if (authflavor != RPC_AUTH_UNIX) {
-               struct rpc_auth *auth;
 
-               server->client_sys = rpc_clone_client(server->client);
-               if (IS_ERR(server->client_sys))
-                       return PTR_ERR(server->client_sys);
-               auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys);
-               if (IS_ERR(auth))
-                       return PTR_ERR(auth);
-       } else {
-               atomic_inc(&server->client->cl_count);
-               server->client_sys = server->client;
-       }
+       /* RFC 2623, sec 2.3.2 */
        if (server->flags & NFS_MOUNT_VER3) {
 #ifdef CONFIG_NFS_V3_ACL
                if (!(server->flags & NFS_MOUNT_NOACL)) {
@@ -989,7 +911,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
                goto out_err_noserver;
        /* Zero out the NFS state stuff */
        init_nfsv4_state(server);
-       server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
+       server->client = server->client_acl = ERR_PTR(-EINVAL);
 
        root = &server->fh;
        if (data->flags & NFS_MOUNT_VER3)
@@ -1011,22 +933,14 @@ static int nfs_get_sb(struct file_system_type *fs_type,
                goto out_err;
        }
 
-       /* Fire up rpciod if not yet running */
-       error = rpciod_up();
-       if (error < 0) {
-               dprintk("%s: couldn't start rpciod! Error = %d\n",
-                               __FUNCTION__, error);
-               goto out_err;
-       }
-
        s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
-               goto out_err_rpciod;
+               goto out_err;
        }
 
        if (s->s_root)
-               goto out_rpciod_down;
+               goto out_share;
 
        s->s_flags = flags;
 
@@ -1039,13 +953,10 @@ static int nfs_get_sb(struct file_system_type *fs_type,
        s->s_flags |= MS_ACTIVE;
        return simple_set_mnt(mnt, s);
 
-out_rpciod_down:
-       rpciod_down();
+out_share:
        kfree(server);
        return simple_set_mnt(mnt, s);
 
-out_err_rpciod:
-       rpciod_down();
 out_err:
        kfree(server);
 out_err_noserver:
@@ -1060,18 +971,15 @@ static void nfs_kill_super(struct super_block *s)
 
        if (!IS_ERR(server->client))
                rpc_shutdown_client(server->client);
-       if (!IS_ERR(server->client_sys))
-               rpc_shutdown_client(server->client_sys);
        if (!IS_ERR(server->client_acl))
                rpc_shutdown_client(server->client_acl);
 
        if (!(server->flags & NFS_MOUNT_NONLM))
                lockd_down();   /* release rpc.lockd */
 
-       rpciod_down();          /* release rpciod */
-
        nfs_free_iostats(server->io_stats);
        kfree(server->hostname);
+       nfs_put_client(server->nfs_client);
        kfree(server);
        nfs_release_automount_timer();
 }
@@ -1097,53 +1005,38 @@ static int nfs_clone_nfs_sb(struct file_system_type *fs_type,
 
 #ifdef CONFIG_NFS_V4
 static struct rpc_clnt *nfs4_create_client(struct nfs_server *server,
-       struct rpc_timeout *timeparms, int proto, rpc_authflavor_t flavor)
+       int timeo, int retrans, int proto, rpc_authflavor_t flavor)
 {
        struct nfs_client *clp;
-       struct rpc_xprt *xprt = NULL;
        struct rpc_clnt *clnt = NULL;
        int err = -EIO;
 
-       clp = nfs4_get_client(&server->addr.sin_addr);
+       clp = nfs_get_client(server->hostname, &server->addr, 4);
        if (!clp) {
                dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
                return ERR_PTR(err);
        }
 
        /* Now create transport and client */
-       down_write(&clp->cl_sem);
-       if (IS_ERR(clp->cl_rpcclient)) {
-               xprt = xprt_create_proto(proto, &server->addr, timeparms);
-               if (IS_ERR(xprt)) {
-                       up_write(&clp->cl_sem);
-                       err = PTR_ERR(xprt);
-                       dprintk("%s: cannot create RPC transport. Error = %d\n",
-                                       __FUNCTION__, err);
-                       goto out_fail;
-               }
-               /* Bind to a reserved port! */
-               xprt->resvport = 1;
-               clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
-                               server->rpc_ops->version, flavor);
-               if (IS_ERR(clnt)) {
-                       up_write(&clp->cl_sem);
-                       err = PTR_ERR(clnt);
-                       dprintk("%s: cannot create RPC client. Error = %d\n",
-                                       __FUNCTION__, err);
-                       goto out_fail;
-               }
-               clnt->cl_intr     = 1;
-               clnt->cl_softrtry = 1;
-               clp->cl_rpcclient = clnt;
+       if (clp->cl_cons_state == NFS_CS_INITING) {
+               clp->rpc_ops = &nfs_v4_clientops;
+
+               err = nfs_create_rpc_client(clp, proto, timeo, retrans, flavor);
+               if (err < 0)
+                       goto client_init_error;
+
                memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
-               nfs_idmap_new(clp);
+               err = nfs_idmap_new(clp);
+               if (err < 0) {
+                       dprintk("%s: failed to create idmapper.\n",
+                               __FUNCTION__);
+                       goto client_init_error;
+               }
+               __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
+               nfs_mark_client_ready(clp, 0);
        }
-       list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
+
        clnt = rpc_clone_client(clp->cl_rpcclient);
-       if (!IS_ERR(clnt))
-               server->nfs4_state = clp;
-       up_write(&clp->cl_sem);
-       clp = NULL;
 
        if (IS_ERR(clnt)) {
                dprintk("%s: cannot create RPC client. Error = %d\n",
@@ -1151,11 +1044,6 @@ static struct rpc_clnt *nfs4_create_client(struct nfs_server *server,
                return clnt;
        }
 
-       if (server->nfs4_state->cl_idmap == NULL) {
-               dprintk("%s: failed to create idmapper.\n", __FUNCTION__);
-               return ERR_PTR(-ENOMEM);
-       }
-
        if (clnt->cl_auth->au_flavor != flavor) {
                struct rpc_auth *auth;
 
@@ -1165,11 +1053,16 @@ static struct rpc_clnt *nfs4_create_client(struct nfs_server *server,
                        return (struct rpc_clnt *)auth;
                }
        }
+
+       server->nfs_client = clp;
+       down_write(&clp->cl_sem);
+       list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
+       up_write(&clp->cl_sem);
        return clnt;
 
- out_fail:
-       if (clp)
-               nfs4_put_client(clp);
+client_init_error:
+       nfs_mark_client_ready(clp, err);
+       nfs_put_client(clp);
        return ERR_PTR(err);
 }
 
@@ -1179,7 +1072,6 @@ static struct rpc_clnt *nfs4_create_client(struct nfs_server *server,
 static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent)
 {
        struct nfs_server *server;
-       struct rpc_timeout timeparms;
        rpc_authflavor_t authflavour;
        int err = -EIO;
 
@@ -1198,13 +1090,6 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
        server->acdirmin = data->acdirmin*HZ;
        server->acdirmax = data->acdirmax*HZ;
 
-       server->rpc_ops = &nfs_v4_clientops;
-
-       nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans);
-
-       server->retrans_timeo = timeparms.to_initval;
-       server->retrans_count = timeparms.to_retries;
-
        /* Now create transport and client */
        authflavour = RPC_AUTH_UNIX;
        if (data->auth_flavourlen != 0) {
@@ -1220,7 +1105,8 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
                }
        }
 
-       server->client = nfs4_create_client(server, &timeparms, data->proto, authflavour);
+       server->client = nfs4_create_client(server, data->timeo, data->retrans,
+                                           data->proto, authflavour);
        if (IS_ERR(server->client)) {
                err = PTR_ERR(server->client);
                        dprintk("%s: cannot create RPC client. Error = %d\n",
@@ -1294,7 +1180,7 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
                return -ENOMEM;
        /* Zero out the NFS state stuff */
        init_nfsv4_state(server);
-       server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
+       server->client = server->client_acl = ERR_PTR(-EINVAL);
 
        p = nfs_copy_user_string(NULL, &data->hostname, 256);
        if (IS_ERR(p))
@@ -1328,14 +1214,6 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
                goto out_free;
        }
 
-       /* Fire up rpciod if not yet running */
-       error = rpciod_up();
-       if (error < 0) {
-               dprintk("%s: couldn't start rpciod! Error = %d\n",
-                               __FUNCTION__, error);
-               goto out_free;
-       }
-
        s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
@@ -1382,8 +1260,6 @@ static void nfs4_kill_super(struct super_block *sb)
 
        destroy_nfsv4_state(server);
 
-       rpciod_down();
-
        nfs_free_iostats(server->io_stats);
        kfree(server->hostname);
        kfree(server);
@@ -1416,7 +1292,7 @@ static inline char *nfs4_dup_path(const struct dentry *dentry)
 static struct super_block *nfs4_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data)
 {
        const struct dentry *dentry = data->dentry;
-       struct nfs_client *clp = server->nfs4_state;
+       struct nfs_client *clp = server->nfs_client;
        struct super_block *sb;
 
        server->fsid = data->fattr->fsid;
@@ -1432,7 +1308,6 @@ static struct super_block *nfs4_clone_sb(struct nfs_server *server, struct nfs_c
        nfs4_server_capabilities(server, &server->fh);
 
        down_write(&clp->cl_sem);
-       atomic_inc(&clp->cl_count);
        list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
        up_write(&clp->cl_sem);
        return sb;
@@ -1476,7 +1351,6 @@ err:
 static struct nfs_server *nfs4_referral_server(struct super_block *sb, struct nfs_clone_mount *data)
 {
        struct nfs_server *server = NFS_SB(sb);
-       struct rpc_timeout timeparms;
        int proto, timeo, retrans;
        void *err;
 
@@ -1485,9 +1359,11 @@ static struct nfs_server *nfs4_referral_server(struct super_block *sb, struct nf
           set the timeouts and retries to low values */
        timeo = 2;
        retrans = 1;
-       nfs_init_timeout_values(&timeparms, proto, timeo, retrans);
 
-       server->client = nfs4_create_client(server, &timeparms, proto, data->authflavor);
+       nfs_put_client(server->nfs_client);
+       server->nfs_client = NULL;
+       server->client = nfs4_create_client(server, timeo, retrans, proto,
+                                           data->authflavor);
        if (IS_ERR((err = server->client)))
                goto out_err;