SUNRPC: don't map EKEYEXPIRED to EACCES in call_refreshresult
[pandora-kernel.git] / net / sunrpc / clnt.c
index e862f8c..631085f 100644 (file)
@@ -102,12 +102,7 @@ static void rpc_unregister_client(struct rpc_clnt *clnt)
 
 static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
 {
-       if (clnt->cl_dentry) {
-               if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy)
-                       clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth);
-               rpc_remove_client_dir(clnt->cl_dentry);
-       }
-       clnt->cl_dentry = NULL;
+       rpc_remove_client_dir(clnt);
 }
 
 static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
@@ -123,10 +118,10 @@ static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
 }
 
 static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
-                                   struct rpc_clnt *clnt,
-                                   const char *dir_name)
+                                   struct rpc_clnt *clnt)
 {
        static uint32_t clntid;
+       const char *dir_name = clnt->cl_program->pipe_dir_name;
        char name[15];
        struct dentry *dir, *dentry;
 
@@ -153,28 +148,35 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
 }
 
 static int
-rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name,
-                 struct super_block *pipefs_sb)
+rpc_setup_pipedir(struct super_block *pipefs_sb, struct rpc_clnt *clnt)
 {
        struct dentry *dentry;
 
-       clnt->cl_dentry = NULL;
-       if (dir_name == NULL)
-               return 0;
-       dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name);
-       if (IS_ERR(dentry))
-               return PTR_ERR(dentry);
-       clnt->cl_dentry = dentry;
+       if (clnt->cl_program->pipe_dir_name != NULL) {
+               dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt);
+               if (IS_ERR(dentry))
+                       return PTR_ERR(dentry);
+       }
        return 0;
 }
 
-static inline int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event)
+static int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event)
 {
-       if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) ||
-           ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry))
-               return 1;
-       if ((event == RPC_PIPEFS_MOUNT) && atomic_read(&clnt->cl_count) == 0)
+       if (clnt->cl_program->pipe_dir_name == NULL)
                return 1;
+
+       switch (event) {
+       case RPC_PIPEFS_MOUNT:
+               if (clnt->cl_pipedir_objects.pdh_dentry != NULL)
+                       return 1;
+               if (atomic_read(&clnt->cl_count) == 0)
+                       return 1;
+               break;
+       case RPC_PIPEFS_UMOUNT:
+               if (clnt->cl_pipedir_objects.pdh_dentry == NULL)
+                       return 1;
+               break;
+       }
        return 0;
 }
 
@@ -186,18 +188,11 @@ static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event,
 
        switch (event) {
        case RPC_PIPEFS_MOUNT:
-               dentry = rpc_setup_pipedir_sb(sb, clnt,
-                                             clnt->cl_program->pipe_dir_name);
+               dentry = rpc_setup_pipedir_sb(sb, clnt);
                if (!dentry)
                        return -ENOENT;
                if (IS_ERR(dentry))
                        return PTR_ERR(dentry);
-               clnt->cl_dentry = dentry;
-               if (clnt->cl_auth->au_ops->pipes_create) {
-                       err = clnt->cl_auth->au_ops->pipes_create(clnt->cl_auth);
-                       if (err)
-                               __rpc_clnt_remove_pipedir(clnt);
-               }
                break;
        case RPC_PIPEFS_UMOUNT:
                __rpc_clnt_remove_pipedir(clnt);
@@ -230,8 +225,6 @@ static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event)
 
        spin_lock(&sn->rpc_client_lock);
        list_for_each_entry(clnt, &sn->all_clients, cl_clients) {
-               if (clnt->cl_program->pipe_dir_name == NULL)
-                       continue;
                if (rpc_clnt_skip_event(clnt, event))
                        continue;
                spin_unlock(&sn->rpc_client_lock);
@@ -282,7 +275,10 @@ static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
 static int rpc_client_register(const struct rpc_create_args *args,
                               struct rpc_clnt *clnt)
 {
-       const struct rpc_program *program = args->program;
+       struct rpc_auth_create_args auth_args = {
+               .pseudoflavor = args->authflavor,
+               .target_name = args->client_name,
+       };
        struct rpc_auth *auth;
        struct net *net = rpc_net_ns(clnt);
        struct super_block *pipefs_sb;
@@ -290,7 +286,7 @@ static int rpc_client_register(const struct rpc_create_args *args,
 
        pipefs_sb = rpc_get_sb_net(net);
        if (pipefs_sb) {
-               err = rpc_setup_pipedir(clnt, program->pipe_dir_name, pipefs_sb);
+               err = rpc_setup_pipedir(pipefs_sb, clnt);
                if (err)
                        goto out;
        }
@@ -299,7 +295,7 @@ static int rpc_client_register(const struct rpc_create_args *args,
        if (pipefs_sb)
                rpc_put_sb_net(net);
 
-       auth = rpcauth_create(args->authflavor, clnt);
+       auth = rpcauth_create(&auth_args, clnt);
        if (IS_ERR(auth)) {
                dprintk("RPC:       Couldn't create auth handle (flavor %u)\n",
                                args->authflavor);
@@ -317,7 +313,9 @@ out:
        return err;
 }
 
-static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt)
+static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
+               struct rpc_xprt *xprt,
+               struct rpc_clnt *parent)
 {
        const struct rpc_program *program = args->program;
        const struct rpc_version *version;
@@ -343,16 +341,16 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
        clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
        if (!clnt)
                goto out_err;
-       clnt->cl_parent = clnt;
+       clnt->cl_parent = parent ? : clnt;
 
        rcu_assign_pointer(clnt->cl_xprt, xprt);
        clnt->cl_procinfo = version->procs;
        clnt->cl_maxproc  = version->nrprocs;
-       clnt->cl_protname = program->name;
        clnt->cl_prog     = args->prognumber ? : program->number;
        clnt->cl_vers     = version->number;
        clnt->cl_stats    = program->stats;
        clnt->cl_metrics  = rpc_alloc_iostats(clnt);
+       rpc_init_pipe_dir_head(&clnt->cl_pipedir_objects);
        err = -ENOMEM;
        if (clnt->cl_metrics == NULL)
                goto out_no_stats;
@@ -372,12 +370,6 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
 
        clnt->cl_rtt = &clnt->cl_rtt_default;
        rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval);
-       clnt->cl_principal = NULL;
-       if (args->client_name) {
-               clnt->cl_principal = kstrdup(args->client_name, GFP_KERNEL);
-               if (!clnt->cl_principal)
-                       goto out_no_principal;
-       }
 
        atomic_set(&clnt->cl_count, 1);
 
@@ -387,11 +379,11 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
        err = rpc_client_register(args, clnt);
        if (err)
                goto out_no_path;
+       if (parent)
+               atomic_inc(&parent->cl_count);
        return clnt;
 
 out_no_path:
-       kfree(clnt->cl_principal);
-out_no_principal:
        rpc_free_iostats(clnt->cl_metrics);
 out_no_stats:
        kfree(clnt);
@@ -479,7 +471,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
        if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT)
                xprt->resvport = 0;
 
-       clnt = rpc_new_client(args, xprt);
+       clnt = rpc_new_client(args, xprt, NULL);
        if (IS_ERR(clnt))
                return clnt;
 
@@ -526,15 +518,12 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
                goto out_err;
        args->servername = xprt->servername;
 
-       new = rpc_new_client(args, xprt);
+       new = rpc_new_client(args, xprt, clnt);
        if (IS_ERR(new)) {
                err = PTR_ERR(new);
                goto out_err;
        }
 
-       atomic_inc(&clnt->cl_count);
-       new->cl_parent = clnt;
-
        /* Turn off autobind on clones */
        new->cl_autobind = 0;
        new->cl_softrtry = clnt->cl_softrtry;
@@ -561,7 +550,6 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt)
                .prognumber     = clnt->cl_prog,
                .version        = clnt->cl_vers,
                .authflavor     = clnt->cl_auth->au_flavor,
-               .client_name    = clnt->cl_principal,
        };
        return __rpc_clone_client(&args, clnt);
 }
@@ -583,7 +571,6 @@ rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
                .prognumber     = clnt->cl_prog,
                .version        = clnt->cl_vers,
                .authflavor     = flavor,
-               .client_name    = clnt->cl_principal,
        };
        return __rpc_clone_client(&args, clnt);
 }
@@ -656,7 +643,6 @@ rpc_free_client(struct rpc_clnt *clnt)
        rpc_clnt_remove_pipedir(clnt);
        rpc_unregister_client(clnt);
        rpc_free_iostats(clnt->cl_metrics);
-       kfree(clnt->cl_principal);
        clnt->cl_metrics = NULL;
        xprt_put(rcu_dereference_raw(clnt->cl_xprt));
        rpciod_down();
@@ -720,7 +706,6 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
                .prognumber     = program->number,
                .version        = vers,
                .authflavor     = old->cl_auth->au_flavor,
-               .client_name    = old->cl_principal,
        };
        struct rpc_clnt *clnt;
        int err;
@@ -1423,9 +1408,9 @@ call_refreshresult(struct rpc_task *task)
                return;
        case -ETIMEDOUT:
                rpc_delay(task, 3*HZ);
-       case -EKEYEXPIRED:
        case -EAGAIN:
                status = -EACCES;
+       case -EKEYEXPIRED:
                if (!task->tk_cred_retry)
                        break;
                task->tk_cred_retry--;