Exemplo n.º 1
0
/*
 * 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;
}
Exemplo n.º 2
0
/*
 * 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;
}
Exemplo n.º 3
0
/*
 * 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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
/*
 * 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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
/*
 * 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(&current->sigmask_lock, flags);
	oldset = current->blocked;
	sigfillset(&current->blocked);
	recalc_sigpending(current);
	spin_unlock_irqrestore(&current->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(&current->sigmask_lock, flags);
	current->blocked = oldset;
	recalc_sigpending(current);
	spin_unlock_irqrestore(&current->sigmask_lock, flags);

	return status;
}