Fix a second potential rpc_wakeup race...
[firefly-linux-kernel-4.4.55.git] / net / sunrpc / clnt.c
index 78696f2dc7d6d402ef200f140f897388ce383db1..a323abc7ea85b0c2563f2e664939bc8943cc8dfd 100644 (file)
@@ -253,10 +253,9 @@ rpc_clone_client(struct rpc_clnt *clnt)
 {
        struct rpc_clnt *new;
 
-       new = kmalloc(sizeof(*new), GFP_KERNEL);
+       new = kmemdup(clnt, sizeof(*new), GFP_KERNEL);
        if (!new)
                goto out_no_clnt;
-       memcpy(new, clnt, sizeof(*new));
        atomic_set(&new->cl_count, 1);
        atomic_set(&new->cl_users, 0);
        new->cl_parent = clnt;
@@ -467,10 +466,9 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 
        BUG_ON(flags & RPC_TASK_ASYNC);
 
-       status = -ENOMEM;
        task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL);
        if (task == NULL)
-               goto out;
+               return -ENOMEM;
 
        /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */
        rpc_task_sigmask(task, &oldset);
@@ -479,15 +477,17 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 
        /* Set up the call info struct and execute the task */
        status = task->tk_status;
-       if (status == 0) {
-               atomic_inc(&task->tk_count);
-               status = rpc_execute(task);
-               if (status == 0)
-                       status = task->tk_status;
+       if (status != 0) {
+               rpc_release_task(task);
+               goto out;
        }
-       rpc_restore_sigmask(&oldset);
-       rpc_release_task(task);
+       atomic_inc(&task->tk_count);
+       status = rpc_execute(task);
+       if (status == 0)
+               status = task->tk_status;
+       rpc_put_task(task);
 out:
+       rpc_restore_sigmask(&oldset);
        return status;
 }