]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/sunrpc/clnt.c
Merge git://www.linux-watchdog.org/linux-watchdog
[karo-tx-linux.git] / net / sunrpc / clnt.c
index cdc7564b4512d7f79606bc87fb7726a668a9b9a0..822f020fa7f458e07a8e216e6609447daefb8747 100644 (file)
@@ -132,8 +132,10 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
        int error;
 
        dir = rpc_d_lookup_sb(sb, dir_name);
-       if (dir == NULL)
+       if (dir == NULL) {
+               pr_info("RPC: pipefs directory doesn't exist: %s\n", dir_name);
                return dir;
+       }
        for (;;) {
                q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
                name[sizeof(name) - 1] = '\0';
@@ -192,7 +194,8 @@ static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event,
        case RPC_PIPEFS_MOUNT:
                dentry = rpc_setup_pipedir_sb(sb, clnt,
                                              clnt->cl_program->pipe_dir_name);
-               BUG_ON(dentry == NULL);
+               if (!dentry)
+                       return -ENOENT;
                if (IS_ERR(dentry))
                        return PTR_ERR(dentry);
                clnt->cl_dentry = dentry;
@@ -234,7 +237,7 @@ 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)
-                       break;
+                       continue;
                if (rpc_clnt_skip_event(clnt, event))
                        continue;
                if (atomic_inc_not_zero(&clnt->cl_count) == 0)
@@ -607,6 +610,13 @@ EXPORT_SYMBOL_GPL(rpc_killall_tasks);
  */
 void rpc_shutdown_client(struct rpc_clnt *clnt)
 {
+       /*
+        * To avoid deadlock, never call rpc_shutdown_client from a
+        * workqueue context!
+        */
+       WARN_ON_ONCE(current->flags & PF_WQ_WORKER);
+       might_sleep();
+
        dprintk_rcu("RPC:       shutting down %s client for %s\n",
                        clnt->cl_protname,
                        rcu_dereference(clnt->cl_xprt)->servername);
@@ -693,21 +703,19 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
                                      const struct rpc_program *program,
                                      u32 vers)
 {
+       struct rpc_create_args args = {
+               .program        = program,
+               .prognumber     = program->number,
+               .version        = vers,
+               .authflavor     = old->cl_auth->au_flavor,
+               .client_name    = old->cl_principal,
+       };
        struct rpc_clnt *clnt;
-       const struct rpc_version *version;
        int err;
 
-       BUG_ON(vers >= program->nrvers || !program->version[vers]);
-       version = program->version[vers];
-       clnt = rpc_clone_client(old);
+       clnt = __rpc_clone_client(&args, old);
        if (IS_ERR(clnt))
                goto out;
-       clnt->cl_procinfo = version->procs;
-       clnt->cl_maxproc  = version->nrprocs;
-       clnt->cl_protname = program->name;
-       clnt->cl_prog     = program->number;
-       clnt->cl_vers     = version->number;
-       clnt->cl_stats    = program->stats;
        err = rpc_ping(clnt);
        if (err != 0) {
                rpc_shutdown_client(clnt);
@@ -832,7 +840,12 @@ int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flag
        };
        int status;
 
-       BUG_ON(flags & RPC_TASK_ASYNC);
+       WARN_ON_ONCE(flags & RPC_TASK_ASYNC);
+       if (flags & RPC_TASK_ASYNC) {
+               rpc_release_calldata(task_setup_data.callback_ops,
+                       task_setup_data.callback_data);
+               return -EINVAL;
+       }
 
        task = rpc_run_task(&task_setup_data);
        if (IS_ERR(task))
@@ -908,7 +921,7 @@ struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
 
        task->tk_action = call_bc_transmit;
        atomic_inc(&task->tk_count);
-       BUG_ON(atomic_read(&task->tk_count) != 2);
+       WARN_ON_ONCE(atomic_read(&task->tk_count) != 2);
        rpc_execute(task);
 
 out:
@@ -1368,6 +1381,7 @@ call_refreshresult(struct rpc_task *task)
                return;
        case -ETIMEDOUT:
                rpc_delay(task, 3*HZ);
+       case -EKEYEXPIRED:
        case -EAGAIN:
                status = -EACCES;
                if (!task->tk_cred_retry)
@@ -1654,7 +1668,6 @@ call_transmit(struct rpc_task *task)
        task->tk_action = call_transmit_status;
        /* Encode here so that rpcsec_gss can use correct sequence number. */
        if (rpc_task_need_encode(task)) {
-               BUG_ON(task->tk_rqstp->rq_bytes_sent != 0);
                rpc_xdr_encode(task);
                /* Did the encode result in an error condition? */
                if (task->tk_status != 0) {
@@ -1738,7 +1751,6 @@ call_bc_transmit(struct rpc_task *task)
 {
        struct rpc_rqst *req = task->tk_rqstp;
 
-       BUG_ON(task->tk_status != 0);
        task->tk_status = xprt_prepare_transmit(task);
        if (task->tk_status == -EAGAIN) {
                /*
@@ -1785,7 +1797,7 @@ call_bc_transmit(struct rpc_task *task)
                 * We were unable to reply and will have to drop the
                 * request.  The server should reconnect and retransmit.
                 */
-               BUG_ON(task->tk_status == -EAGAIN);
+               WARN_ON_ONCE(task->tk_status == -EAGAIN);
                printk(KERN_NOTICE "RPC: Could not send backchannel reply "
                        "error: %d\n", task->tk_status);
                break;