|
@@ -226,7 +226,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
|
|
|
goto out_no_principal;
|
|
|
}
|
|
|
|
|
|
- kref_init(&clnt->cl_kref);
|
|
|
+ atomic_set(&clnt->cl_count, 1);
|
|
|
|
|
|
err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
|
|
|
if (err < 0)
|
|
@@ -390,14 +390,14 @@ rpc_clone_client(struct rpc_clnt *clnt)
|
|
|
if (new->cl_principal == NULL)
|
|
|
goto out_no_principal;
|
|
|
}
|
|
|
- kref_init(&new->cl_kref);
|
|
|
+ atomic_set(&new->cl_count, 1);
|
|
|
err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
|
|
|
if (err != 0)
|
|
|
goto out_no_path;
|
|
|
if (new->cl_auth)
|
|
|
atomic_inc(&new->cl_auth->au_count);
|
|
|
xprt_get(clnt->cl_xprt);
|
|
|
- kref_get(&clnt->cl_kref);
|
|
|
+ atomic_inc(&clnt->cl_count);
|
|
|
rpc_register_client(new);
|
|
|
rpciod_up();
|
|
|
return new;
|
|
@@ -465,10 +465,8 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client);
|
|
|
* Free an RPC client
|
|
|
*/
|
|
|
static void
|
|
|
-rpc_free_client(struct kref *kref)
|
|
|
+rpc_free_client(struct rpc_clnt *clnt)
|
|
|
{
|
|
|
- struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
|
|
|
-
|
|
|
dprintk("RPC: destroying %s client for %s\n",
|
|
|
clnt->cl_protname, clnt->cl_server);
|
|
|
if (!IS_ERR(clnt->cl_path.dentry)) {
|
|
@@ -495,12 +493,10 @@ out_free:
|
|
|
* Free an RPC client
|
|
|
*/
|
|
|
static void
|
|
|
-rpc_free_auth(struct kref *kref)
|
|
|
+rpc_free_auth(struct rpc_clnt *clnt)
|
|
|
{
|
|
|
- struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
|
|
|
-
|
|
|
if (clnt->cl_auth == NULL) {
|
|
|
- rpc_free_client(kref);
|
|
|
+ rpc_free_client(clnt);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -509,10 +505,11 @@ rpc_free_auth(struct kref *kref)
|
|
|
* release remaining GSS contexts. This mechanism ensures
|
|
|
* that it can do so safely.
|
|
|
*/
|
|
|
- kref_init(kref);
|
|
|
+ atomic_inc(&clnt->cl_count);
|
|
|
rpcauth_release(clnt->cl_auth);
|
|
|
clnt->cl_auth = NULL;
|
|
|
- kref_put(kref, rpc_free_client);
|
|
|
+ if (atomic_dec_and_test(&clnt->cl_count))
|
|
|
+ rpc_free_client(clnt);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -525,7 +522,8 @@ rpc_release_client(struct rpc_clnt *clnt)
|
|
|
|
|
|
if (list_empty(&clnt->cl_tasks))
|
|
|
wake_up(&destroy_wait);
|
|
|
- kref_put(&clnt->cl_kref, rpc_free_auth);
|
|
|
+ if (atomic_dec_and_test(&clnt->cl_count))
|
|
|
+ rpc_free_auth(clnt);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -588,7 +586,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
|
|
|
if (clnt != NULL) {
|
|
|
rpc_task_release_client(task);
|
|
|
task->tk_client = clnt;
|
|
|
- kref_get(&clnt->cl_kref);
|
|
|
+ atomic_inc(&clnt->cl_count);
|
|
|
if (clnt->cl_softrtry)
|
|
|
task->tk_flags |= RPC_TASK_SOFT;
|
|
|
/* Add to the client's list of all tasks */
|
|
@@ -931,7 +929,7 @@ call_reserveresult(struct rpc_task *task)
|
|
|
task->tk_status = 0;
|
|
|
if (status >= 0) {
|
|
|
if (task->tk_rqstp) {
|
|
|
- task->tk_action = call_allocate;
|
|
|
+ task->tk_action = call_refresh;
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -966,13 +964,54 @@ call_reserveresult(struct rpc_task *task)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * 2. Allocate the buffer. For details, see sched.c:rpc_malloc.
|
|
|
+ * 2. Bind and/or refresh the credentials
|
|
|
+ */
|
|
|
+static void
|
|
|
+call_refresh(struct rpc_task *task)
|
|
|
+{
|
|
|
+ dprint_status(task);
|
|
|
+
|
|
|
+ task->tk_action = call_refreshresult;
|
|
|
+ task->tk_status = 0;
|
|
|
+ task->tk_client->cl_stats->rpcauthrefresh++;
|
|
|
+ rpcauth_refreshcred(task);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * 2a. Process the results of a credential refresh
|
|
|
+ */
|
|
|
+static void
|
|
|
+call_refreshresult(struct rpc_task *task)
|
|
|
+{
|
|
|
+ int status = task->tk_status;
|
|
|
+
|
|
|
+ dprint_status(task);
|
|
|
+
|
|
|
+ task->tk_status = 0;
|
|
|
+ task->tk_action = call_allocate;
|
|
|
+ if (status >= 0 && rpcauth_uptodatecred(task))
|
|
|
+ return;
|
|
|
+ switch (status) {
|
|
|
+ case -EACCES:
|
|
|
+ rpc_exit(task, -EACCES);
|
|
|
+ return;
|
|
|
+ case -ENOMEM:
|
|
|
+ rpc_exit(task, -ENOMEM);
|
|
|
+ return;
|
|
|
+ case -ETIMEDOUT:
|
|
|
+ rpc_delay(task, 3*HZ);
|
|
|
+ }
|
|
|
+ task->tk_action = call_refresh;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * 2b. Allocate the buffer. For details, see sched.c:rpc_malloc.
|
|
|
* (Note: buffer memory is freed in xprt_release).
|
|
|
*/
|
|
|
static void
|
|
|
call_allocate(struct rpc_task *task)
|
|
|
{
|
|
|
- unsigned int slack = task->tk_client->cl_auth->au_cslack;
|
|
|
+ unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack;
|
|
|
struct rpc_rqst *req = task->tk_rqstp;
|
|
|
struct rpc_xprt *xprt = task->tk_xprt;
|
|
|
struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
|
|
@@ -980,7 +1019,7 @@ call_allocate(struct rpc_task *task)
|
|
|
dprint_status(task);
|
|
|
|
|
|
task->tk_status = 0;
|
|
|
- task->tk_action = call_refresh;
|
|
|
+ task->tk_action = call_bind;
|
|
|
|
|
|
if (req->rq_buffer)
|
|
|
return;
|
|
@@ -1017,47 +1056,6 @@ call_allocate(struct rpc_task *task)
|
|
|
rpc_exit(task, -ERESTARTSYS);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * 2a. Bind and/or refresh the credentials
|
|
|
- */
|
|
|
-static void
|
|
|
-call_refresh(struct rpc_task *task)
|
|
|
-{
|
|
|
- dprint_status(task);
|
|
|
-
|
|
|
- task->tk_action = call_refreshresult;
|
|
|
- task->tk_status = 0;
|
|
|
- task->tk_client->cl_stats->rpcauthrefresh++;
|
|
|
- rpcauth_refreshcred(task);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * 2b. Process the results of a credential refresh
|
|
|
- */
|
|
|
-static void
|
|
|
-call_refreshresult(struct rpc_task *task)
|
|
|
-{
|
|
|
- int status = task->tk_status;
|
|
|
-
|
|
|
- dprint_status(task);
|
|
|
-
|
|
|
- task->tk_status = 0;
|
|
|
- task->tk_action = call_bind;
|
|
|
- if (status >= 0 && rpcauth_uptodatecred(task))
|
|
|
- return;
|
|
|
- switch (status) {
|
|
|
- case -EACCES:
|
|
|
- rpc_exit(task, -EACCES);
|
|
|
- return;
|
|
|
- case -ENOMEM:
|
|
|
- rpc_exit(task, -ENOMEM);
|
|
|
- return;
|
|
|
- case -ETIMEDOUT:
|
|
|
- rpc_delay(task, 3*HZ);
|
|
|
- }
|
|
|
- task->tk_action = call_refresh;
|
|
|
-}
|
|
|
-
|
|
|
static inline int
|
|
|
rpc_task_need_encode(struct rpc_task *task)
|
|
|
{
|