]> err.no Git - linux-2.6/blobdiff - net/sunrpc/clnt.c
[PATCH] SUNRPC: fix a NULL pointer dereference in net/sunrpc/clnt.c
[linux-2.6] / net / sunrpc / clnt.c
index 25cba94c5683c4fae35aa398088be222dcd29ed6..d784797820456de4c2837a256fe76cdbf2ed36d0 100644 (file)
@@ -113,12 +113,12 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
 
        err = -EINVAL;
        if (!xprt)
-               goto out_err;
+               goto out_no_xprt;
        if (vers >= program->nrvers || !(version = program->version[vers]))
                goto out_err;
 
        err = -ENOMEM;
-       clnt = (struct rpc_clnt *) kmalloc(sizeof(*clnt), GFP_KERNEL);
+       clnt = kmalloc(sizeof(*clnt), GFP_KERNEL);
        if (!clnt)
                goto out_err;
        memset(clnt, 0, sizeof(*clnt));
@@ -182,6 +182,7 @@ out_no_path:
        kfree(clnt);
 out_err:
        xprt_destroy(xprt);
+out_no_xprt:
        return ERR_PTR(err);
 }
 
@@ -225,7 +226,7 @@ rpc_clone_client(struct rpc_clnt *clnt)
 {
        struct rpc_clnt *new;
 
-       new = (struct rpc_clnt *)kmalloc(sizeof(*new), GFP_KERNEL);
+       new = kmalloc(sizeof(*new), GFP_KERNEL);
        if (!new)
                goto out_no_clnt;
        memcpy(new, clnt, sizeof(*new));
@@ -268,7 +269,8 @@ rpc_shutdown_client(struct rpc_clnt *clnt)
                clnt->cl_oneshot = 0;
                clnt->cl_dead = 0;
                rpc_killall_tasks(clnt);
-               sleep_on_timeout(&destroy_wait, 1*HZ);
+               wait_event_timeout(destroy_wait,
+                       !atomic_read(&clnt->cl_users), 1*HZ);
        }
 
        if (atomic_read(&clnt->cl_users) < 0) {
@@ -538,6 +540,18 @@ size_t rpc_max_payload(struct rpc_clnt *clnt)
 }
 EXPORT_SYMBOL(rpc_max_payload);
 
+/**
+ * rpc_force_rebind - force transport to check that remote port is unchanged
+ * @clnt: client to rebind
+ *
+ */
+void rpc_force_rebind(struct rpc_clnt *clnt)
+{
+       if (clnt->cl_autobind)
+               clnt->cl_port = 0;
+}
+EXPORT_SYMBOL(rpc_force_rebind);
+
 /*
  * Restart an (async) RPC call. Usually called from within the
  * exit handler.
@@ -853,8 +867,7 @@ call_connect_status(struct rpc_task *task)
        }
 
        /* Something failed: remote service port may have changed */
-       if (clnt->cl_autobind)
-               clnt->cl_port = 0;
+       rpc_force_rebind(clnt);
 
        switch (status) {
        case -ENOTCONN:
@@ -935,8 +948,7 @@ call_status(struct rpc_task *task)
                break;
        case -ECONNREFUSED:
        case -ENOTCONN:
-               if (clnt->cl_autobind)
-                       clnt->cl_port = 0;
+               rpc_force_rebind(clnt);
                task->tk_action = call_bind;
                break;
        case -EAGAIN:
@@ -947,8 +959,7 @@ call_status(struct rpc_task *task)
                rpc_exit(task, status);
                break;
        default:
-               if (clnt->cl_chatty)
-                       printk("%s: RPC call returned error %d\n",
+               printk("%s: RPC call returned error %d\n",
                               clnt->cl_protname, -status);
                rpc_exit(task, status);
                break;
@@ -983,20 +994,18 @@ call_timeout(struct rpc_task *task)
 
        dprintk("RPC: %4d call_timeout (major)\n", task->tk_pid);
        if (RPC_IS_SOFT(task)) {
-               if (clnt->cl_chatty)
-                       printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
+               printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
                                clnt->cl_protname, clnt->cl_server);
                rpc_exit(task, -EIO);
                return;
        }
 
-       if (clnt->cl_chatty && !(task->tk_flags & RPC_CALL_MAJORSEEN)) {
+       if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) {
                task->tk_flags |= RPC_CALL_MAJORSEEN;
                printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
                        clnt->cl_protname, clnt->cl_server);
        }
-       if (clnt->cl_autobind)
-               clnt->cl_port = 0;
+       rpc_force_rebind(clnt);
 
 retry:
        clnt->cl_stats->rpcretrans++;
@@ -1018,7 +1027,7 @@ call_decode(struct rpc_task *task)
        dprintk("RPC: %4d call_decode (status %d)\n", 
                                task->tk_pid, task->tk_status);
 
-       if (clnt->cl_chatty && (task->tk_flags & RPC_CALL_MAJORSEEN)) {
+       if (task->tk_flags & RPC_CALL_MAJORSEEN) {
                printk(KERN_NOTICE "%s: server %s OK\n",
                        clnt->cl_protname, clnt->cl_server);
                task->tk_flags &= ~RPC_CALL_MAJORSEEN;