/* * Note: rpc_new_task releases the client after a failure. */ struct rpc_task * rpc_new_child(struct rpc_clnt *clnt, struct rpc_task *parent) { struct rpc_task *task; task = rpc_new_task(clnt, NULL, RPC_TASK_ASYNC | RPC_TASK_CHILD); if (!task) goto fail; task->tk_exit = rpc_child_exit; task->tk_calldata = parent; return task; fail: parent->tk_status = -ENOMEM; return NULL; }
/* * New rpc_call implementation */ int rpc_do_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags, rpc_action func, void *data) { struct rpc_task my_task, *task = &my_task; sigset_t oldset; int async, status; /* If this client is slain all further I/O fails */ if (clnt->cl_dead) return -EIO; rpc_clnt_sigmask(clnt, &oldset); /* Create/initialize a new RPC task */ if ((async = (flags & RPC_TASK_ASYNC)) != 0) { if (!func) func = rpc_default_callback; status = -ENOMEM; if (!(task = rpc_new_task(clnt, func, flags))) goto out; task->tk_calldata = data; } else { rpc_init_task(task, clnt, NULL, flags); } /* Bind the user cred, set up the call info struct and * execute the task */ if (rpcauth_lookupcred(task) != NULL) { rpc_call_setup(task, proc, argp, resp, 0); rpc_execute(task); } else async = 0; status = 0; if (!async) { status = task->tk_status; rpc_release_task(task); } out: rpc_clnt_sigunmask(clnt, &oldset); return status; }
int nfs_reqlist_init(struct nfs_server *server) { struct nfs_reqlist *cache; struct rpc_task *task; int status; dprintk("NFS: writecache_init\n"); lock_kernel(); status = -ENOMEM; /* Create the RPC task */ if (!(task = rpc_new_task(server->client, NULL, RPC_TASK_ASYNC))) goto out_unlock; cache = server->rw_requests; status = 0; if (cache->task) goto out_unlock; task->tk_calldata = server; cache->task = task; /* Run the task */ cache->runat = jiffies; cache->auth = server->client->cl_auth; task->tk_action = nfs_flushd; task->tk_exit = nfs_flushd_exit; rpc_execute(task); unlock_kernel(); return 0; out_unlock: if (task) rpc_release_task(task); unlock_kernel(); return status; }
/* * New rpc_call implementation */ int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, rpc_action callback, void *data) { struct rpc_task *task; sigset_t oldset; int status; /* If this client is slain all further I/O fails */ if (clnt->cl_dead) return -EIO; flags |= RPC_TASK_ASYNC; rpc_clnt_sigmask(clnt, &oldset); /* Create/initialize a new RPC task */ if (!callback) callback = rpc_default_callback; status = -ENOMEM; if (!(task = rpc_new_task(clnt, callback, flags))) goto out; task->tk_calldata = data; rpc_call_setup(task, msg, 0); /* Set up the call info struct and execute the task */ if (task->tk_status == 0) status = rpc_execute(task); else { status = task->tk_status; rpc_release_task(task); } out: rpc_clnt_sigunmask(clnt, &oldset); return status; }