SUNRPC: don't map EKEYEXPIRED to EACCES in call_refreshresult
[pandora-kernel.git] / net / sunrpc / clnt.c
index aa40156..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,14 +118,12 @@ 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 qstr q = { .name = name };
        struct dentry *dir, *dentry;
-       int error;
 
        dir = rpc_d_lookup_sb(sb, dir_name);
        if (dir == NULL) {
@@ -138,47 +131,52 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
                return dir;
        }
        for (;;) {
-               q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
+               snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
                name[sizeof(name) - 1] = '\0';
-               q.hash = full_name_hash(q.name, q.len);
-               dentry = rpc_create_client_dir(dir, &q, clnt);
+               dentry = rpc_create_client_dir(dir, name, clnt);
                if (!IS_ERR(dentry))
                        break;
-               error = PTR_ERR(dentry);
-               if (error != -EEXIST) {
-                       printk(KERN_INFO "RPC: Couldn't create pipefs entry"
-                                       " %s/%s, error %d\n",
-                                       dir_name, name, error);
-                       break;
-               }
+               if (dentry == ERR_PTR(-EEXIST))
+                       continue;
+               printk(KERN_INFO "RPC: Couldn't create pipefs entry"
+                               " %s/%s, error %ld\n",
+                               dir_name, name, PTR_ERR(dentry));
+               break;
        }
        dput(dir);
        return dentry;
 }
 
 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;
 }
 
@@ -190,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);
@@ -234,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);
@@ -286,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;
@@ -294,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;
        }
@@ -303,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);
@@ -313,6 +305,7 @@ static int rpc_client_register(const struct rpc_create_args *args,
        return 0;
 err_auth:
        pipefs_sb = rpc_get_sb_net(net);
+       rpc_unregister_client(clnt);
        __rpc_clnt_remove_pipedir(clnt);
 out:
        if (pipefs_sb)
@@ -320,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;
@@ -346,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;
@@ -375,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);
 
@@ -390,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);
@@ -482,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;
 
@@ -529,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;
@@ -564,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);
 }
@@ -586,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);
 }
@@ -632,7 +616,7 @@ void rpc_shutdown_client(struct rpc_clnt *clnt)
        might_sleep();
 
        dprintk_rcu("RPC:       shutting down %s client for %s\n",
-                       clnt->cl_protname,
+                       clnt->cl_program->name,
                        rcu_dereference(clnt->cl_xprt)->servername);
 
        while (!list_empty(&clnt->cl_tasks)) {
@@ -652,14 +636,13 @@ static void
 rpc_free_client(struct rpc_clnt *clnt)
 {
        dprintk_rcu("RPC:       destroying %s client for %s\n",
-                       clnt->cl_protname,
+                       clnt->cl_program->name,
                        rcu_dereference(clnt->cl_xprt)->servername);
        if (clnt->cl_parent != clnt)
                rpc_release_client(clnt->cl_parent);
        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();
@@ -723,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;
@@ -1302,7 +1284,7 @@ call_start(struct rpc_task *task)
        struct rpc_clnt *clnt = task->tk_client;
 
        dprintk("RPC: %5u call_start %s%d proc %s (%s)\n", task->tk_pid,
-                       clnt->cl_protname, clnt->cl_vers,
+                       clnt->cl_program->name, clnt->cl_vers,
                        rpc_proc_name(task),
                        (RPC_IS_ASYNC(task) ? "async" : "sync"));
 
@@ -1426,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--;
@@ -1911,7 +1893,7 @@ call_status(struct rpc_task *task)
        default:
                if (clnt->cl_chatty)
                        printk("%s: RPC call returned error %d\n",
-                              clnt->cl_protname, -status);
+                              clnt->cl_program->name, -status);
                rpc_exit(task, status);
        }
 }
@@ -1942,7 +1924,7 @@ call_timeout(struct rpc_task *task)
                if (clnt->cl_chatty) {
                        rcu_read_lock();
                        printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
-                               clnt->cl_protname,
+                               clnt->cl_program->name,
                                rcu_dereference(clnt->cl_xprt)->servername);
                        rcu_read_unlock();
                }
@@ -1958,7 +1940,7 @@ call_timeout(struct rpc_task *task)
                if (clnt->cl_chatty) {
                        rcu_read_lock();
                        printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
-                       clnt->cl_protname,
+                       clnt->cl_program->name,
                        rcu_dereference(clnt->cl_xprt)->servername);
                        rcu_read_unlock();
                }
@@ -1993,7 +1975,7 @@ call_decode(struct rpc_task *task)
                if (clnt->cl_chatty) {
                        rcu_read_lock();
                        printk(KERN_NOTICE "%s: server %s OK\n",
-                               clnt->cl_protname,
+                               clnt->cl_program->name,
                                rcu_dereference(clnt->cl_xprt)->servername);
                        rcu_read_unlock();
                }
@@ -2018,7 +2000,7 @@ call_decode(struct rpc_task *task)
                        goto out_retry;
                }
                dprintk("RPC:       %s: too small RPC reply size (%d bytes)\n",
-                               clnt->cl_protname, task->tk_status);
+                               clnt->cl_program->name, task->tk_status);
                task->tk_action = call_timeout;
                goto out_retry;
        }
@@ -2290,7 +2272,7 @@ static void rpc_show_task(const struct rpc_clnt *clnt,
        printk(KERN_INFO "%5u %04x %6d %8p %8p %8ld %8p %sv%u %s a:%ps q:%s\n",
                task->tk_pid, task->tk_flags, task->tk_status,
                clnt, task->tk_rqstp, task->tk_timeout, task->tk_ops,
-               clnt->cl_protname, clnt->cl_vers, rpc_proc_name(task),
+               clnt->cl_program->name, clnt->cl_vers, rpc_proc_name(task),
                task->tk_action, rpc_waitq);
 }