/* * Create a new task for the specified client. We have to * clean up after an allocation failure, as the client may * have specified "oneshot". */ struct rpc_task * rpc_new_task(struct rpc_clnt *clnt, rpc_action callback, int flags) { struct rpc_task *task; task = (struct rpc_task *) rpc_allocate(flags, sizeof(*task)); if (!task) goto cleanup; rpc_init_task(task, clnt, callback, flags); dprintk("RPC: %4d allocated task\n", task->tk_pid); task->tk_flags |= RPC_TASK_DYNAMIC; out: return task; cleanup: /* Check whether to release the client */ if (clnt) { printk("rpc_new_task: failed, users=%d, oneshot=%d\n", clnt->cl_users, clnt->cl_oneshot); clnt->cl_users++; /* pretend we were used ... */ rpc_release_client(clnt); } goto out; }
/* * Create an RPC client * FIXME: This should also take a flags argument (as in task->tk_flags). * It's called (among others) from pmap_create_client, which may in * turn be called by an async task. In this case, rpciod should not be * made to sleep too long. */ struct rpc_clnt * rpc_create_client(struct rpc_xprt *xprt, char *servname, struct rpc_program *program, u32 vers, int flavor) { struct rpc_version *version; struct rpc_clnt *clnt = NULL; dprintk("RPC: creating %s client for %s (xprt %p)\n", program->name, servname, xprt); if (!xprt) goto out; if (vers >= program->nrvers || !(version = program->version[vers])) goto out; clnt = (struct rpc_clnt *) rpc_allocate(0, sizeof(*clnt)); if (!clnt) goto out_no_clnt; memset(clnt, 0, sizeof(*clnt)); atomic_set(&clnt->cl_users, 0); clnt->cl_xprt = xprt; clnt->cl_procinfo = version->procs; clnt->cl_maxproc = version->nrprocs; clnt->cl_server = servname; clnt->cl_protname = program->name; clnt->cl_port = xprt->addr.sin_port; clnt->cl_prog = program->number; clnt->cl_vers = version->number; clnt->cl_prot = xprt->prot; clnt->cl_stats = program->stats; INIT_RPC_WAITQ(&clnt->cl_bindwait, "bindwait"); if (!clnt->cl_port) clnt->cl_autobind = 1; rpc_init_rtt(&clnt->cl_rtt, xprt->timeout.to_initval); if (!rpcauth_create(flavor, clnt)) goto out_no_auth; /* save the nodename */ clnt->cl_nodelen = strlen(system_utsname.nodename); if (clnt->cl_nodelen > UNX_MAXNODENAME) clnt->cl_nodelen = UNX_MAXNODENAME; memcpy(clnt->cl_nodename, system_utsname.nodename, clnt->cl_nodelen); out: return clnt; out_no_clnt: printk(KERN_INFO "RPC: out of memory in rpc_create_client\n"); goto out; out_no_auth: printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %d)\n", flavor); rpc_free(clnt); clnt = NULL; goto out; }
/* * Create NULL creds for current process */ static struct rpc_cred * nul_create_cred(int flags) { struct rpc_cred *cred; if (!(cred = (struct rpc_cred *) rpc_allocate(flags, sizeof(*cred)))) return NULL; atomic_set(&cred->cr_count, 0); cred->cr_flags = RPCAUTH_CRED_UPTODATE; cred->cr_uid = current->uid; cred->cr_ops = &null_credops; return cred; }
static struct rpc_auth * nul_create(struct rpc_clnt *clnt) { struct rpc_auth *auth; dprintk("RPC: creating NULL authenticator for client %p\n", clnt); if (!(auth = (struct rpc_auth *) rpc_allocate(0, sizeof(*auth)))) return NULL; auth->au_cslack = 4; auth->au_rslack = 2; auth->au_ops = &authnull_ops; auth->au_expire = 1800 * HZ; rpcauth_init_credcache(auth); return (struct rpc_auth *) auth; }
/* * Allocate an NLM RPC call struct */ struct nlm_rqst * nlmclnt_alloc_call(void) { struct nlm_rqst *call; while (!signalled()) { call = (struct nlm_rqst *) rpc_allocate(RPC_TASK_ASYNC, sizeof(struct nlm_rqst)); if (call) return call; printk("nlmclnt_alloc_call: failed, waiting for memory\n"); current->state = TASK_INTERRUPTIBLE; schedule_timeout(5*HZ); } return NULL; }
static inline int nfs_readpage_async(struct dentry *dentry, struct inode *inode, struct page *page) { unsigned long address = page_address(page); struct nfs_rreq *req; int result = -1, flags; dprintk("NFS: nfs_readpage_async(%p)\n", page); if (NFS_CONGESTED(inode)) goto out_defer; /* N.B. Do we need to test? Never called for swapfile inode */ flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); req = (struct nfs_rreq *) rpc_allocate(flags, sizeof(*req)); if (!req) goto out_defer; /* Initialize request */ /* N.B. Will the dentry remain valid for life of request? */ nfs_readreq_setup(req, NFS_FH(dentry), page->offset, (void *) address, PAGE_SIZE); req->ra_inode = inode; req->ra_page = page; /* count has been incremented by caller */ /* Start the async call */ dprintk("NFS: executing async READ request.\n"); result = rpc_do_call(NFS_CLIENT(inode), NFSPROC_READ, &req->ra_args, &req->ra_res, flags, nfs_readpage_result, req); if (result < 0) goto out_free; result = 0; out: return result; out_defer: dprintk("NFS: deferring async READ request.\n"); goto out; out_free: dprintk("NFS: failed to enqueue async READ request.\n"); kfree(req); goto out; }
/* * Cancel a blocked lock request. * We always use an async RPC call for this in order not to hang a * process that has been Ctrl-C'ed. */ int nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl) { struct nlm_rqst *req; unsigned long flags; sigset_t oldset; int status; /* Block all signals while setting up call */ spin_lock_irqsave(¤t->sigmask_lock, flags); oldset = current->blocked; sigfillset(¤t->blocked); recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags); do { req = (struct nlm_rqst *) rpc_allocate(RPC_TASK_ASYNC, sizeof(*req)); } while (req == NULL); req->a_host = host; req->a_flags = RPC_TASK_ASYNC; nlmclnt_setlockargs(req, fl); status = nlmclnt_async_call(req, NLMPROC_CANCEL, nlmclnt_cancel_callback); if (status < 0) rpc_free(req); spin_lock_irqsave(¤t->sigmask_lock, flags); current->blocked = oldset; recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags); return status; }