예제 #1
0
/*
 * This is the callback from RPC telling us whether a reply was
 * received or some error occurred (timeout or socket shutdown).
 */
static void
nfs_readpage_result(struct rpc_task *task)
{
	struct nfs_rreq	*req = (struct nfs_rreq *) task->tk_calldata;
	struct page	*page = req->ra_page;
	unsigned long	address = page_address(page);
	int		result = task->tk_status;
	static int	succ = 0, fail = 0;

	dprintk("NFS: %4d received callback for page %lx, result %d\n",
			task->tk_pid, address, result);

	if (result >= 0) {
		result = req->ra_res.count;
		if (result < PAGE_SIZE) {
			memset((char *) address + result, 0, PAGE_SIZE - result);
		}
		nfs_refresh_inode(req->ra_inode, &req->ra_fattr);
		set_bit(PG_uptodate, &page->flags);
		succ++;
	} else {
		set_bit(PG_error, &page->flags);
		fail++;
		dprintk("NFS: %d successful reads, %d failures\n", succ, fail);
	}
	/* N.B. Use nfs_unlock_page here? */
	clear_bit(PG_locked, &page->flags);
	wake_up(&page->wait);

	free_page(address);

	rpc_release_task(task);
	kfree(req);
}
예제 #2
0
파일: clnt.c 프로젝트: muromec/linux-ezxdev
/*
 * New rpc_call implementation
 */
int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
{
	struct rpc_task	my_task, *task = &my_task;
	sigset_t	oldset;
	int		status;

	/* If this client is slain all further I/O fails */
	if (clnt->cl_dead) 
		return -EIO;

	if (flags & RPC_TASK_ASYNC) {
		printk("rpc_call_sync: Illegal flag combination for synchronous task\n");
		flags &= ~RPC_TASK_ASYNC;
	}

	rpc_clnt_sigmask(clnt, &oldset);		

	/* Create/initialize a new RPC task */
	rpc_init_task(task, clnt, NULL, flags);
	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);
	}

	rpc_clnt_sigunmask(clnt, &oldset);		

	return status;
}
예제 #3
0
/*
 * This is the callback from the RPC layer when the NLM_GRANTED_MSG
 * RPC call has succeeded or timed out.
 * Like all RPC callbacks, it is invoked by the rpciod process, so it
 * better not sleep. Therefore, we put the blocked lock on the nlm_blocked
 * chain once more in order to have it removed by lockd itself (which can
 * then sleep on the file semaphore without disrupting e.g. the nfs client).
 */
static void
nlmsvc_grant_callback(struct rpc_task *task)
{
	struct nlm_rqst		*call = (struct nlm_rqst *) task->tk_calldata;
	struct nlm_block	*block;
	unsigned long		timeout;

	dprintk("lockd: GRANT_MSG RPC callback\n");
	if (!(block = nlmsvc_find_block(call->a_args.cookie))) {
		dprintk("lockd: no block for cookie %x\n", call->a_args.cookie);
		return;
	}

	/* Technically, we should down the file semaphore here. Since we
	 * move the block towards the head of the queue only, no harm
	 * can be done, though. */
	if (task->tk_status < 0) {
		/* RPC error: Re-insert for retransmission */
		timeout = jiffies + 10 * HZ;
	} else if (block->b_done) {
		/* Block already removed, kill it for real */
		timeout = 0;
	} else {
		/* Call was successful, now wait for client callback */
		timeout = jiffies + 60 * HZ;
	}
	nlmsvc_insert_block(block, timeout);
	svc_wake_up(block->b_daemon);
	block->b_incall = 0;

	nlm_release_host(call->a_host);
	rpc_release_task(task);
}
예제 #4
0
/*
 * Restart an (async) RPC call. Usually called from within the
 * exit handler.
 */
void
rpc_restart_call(struct rpc_task *task)
{
	if (task->tk_flags & RPC_TASK_KILLED) {
		rpc_release_task(task);
		return;
	}
	task->tk_action = call_bind;
	rpcproc_count(task->tk_client, task->tk_proc)++;
}
예제 #5
0
static void
rpc_child_exit(struct rpc_task *child)
{
	struct rpc_task	*parent;

	if ((parent = rpc_find_parent(child)) != NULL) {
		parent->tk_status = child->tk_status;
		rpc_wake_up_task(parent);
	}
	rpc_release_task(child);
}
예제 #6
0
static void
nlmsvc_callback_exit(struct rpc_task *task)
{
	struct nlm_rqst	*call = (struct nlm_rqst *) task->tk_calldata;

	if (task->tk_status < 0) {
		dprintk("lockd: %4d callback failed (errno = %d)\n",
					task->tk_pid, -task->tk_status);
	}
	nlm_release_host(call->a_host);
	rpc_release_task(task);
	kfree(call);
}
예제 #7
0
/*
 * 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;
}
예제 #8
0
static void
nlmclnt_cancel_callback(struct rpc_task *task)
{
	struct nlm_rqst	*req = (struct nlm_rqst *) task->tk_calldata;

	if (RPC_ASSASSINATED(task))
		goto die;

	if (task->tk_status < 0) {
		dprintk("lockd: CANCEL call error %d, retrying.\n",
					task->tk_status);
		goto retry_cancel;
	}

	dprintk("lockd: cancel status %d (task %d)\n",
			req->a_res.status, task->tk_pid);

	switch (req->a_res.status) {
	case NLM_LCK_GRANTED:
	case NLM_LCK_DENIED_GRACE_PERIOD:
		/* Everything's good */
		break;
	case NLM_LCK_DENIED_NOLOCKS:
		dprintk("lockd: CANCEL failed (server has no locks)\n");
		goto retry_cancel;
	default:
		printk(KERN_NOTICE "lockd: weird return %d for CANCEL call\n",
			req->a_res.status);
	}

die:
	rpc_release_task(task);
	nlm_release_host(req->a_host);
	kfree(req);
	return;

retry_cancel:
	nlm_rebind_host(req->a_host);
	rpc_restart_call(task);
	rpc_delay(task, 30 * HZ);
	return;
}
예제 #9
0
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;
}
예제 #10
0
파일: clnt.c 프로젝트: muromec/linux-ezxdev
/*
 * 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;
}
예제 #11
0
static void
nlmclnt_unlock_callback(struct rpc_task *task)
{
	struct nlm_rqst	*req = (struct nlm_rqst *) task->tk_calldata;
	int		status = req->a_res.status;

	if (RPC_ASSASSINATED(task))
		goto die;

	if (task->tk_status < 0) {
		dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status);
		nlm_rebind_host(req->a_host);
		rpc_restart_call(task);
		return;
	}
	if (status != NLM_LCK_GRANTED
	 && status != NLM_LCK_DENIED_GRACE_PERIOD) {
		printk("lockd: unexpected unlock status: %d\n", status);
	}

die:
	rpc_release_task(task);
}
예제 #12
0
/*
 * Default callback for async RPC calls
 */
static void
rpc_default_callback(struct rpc_task *task)
{
	rpc_release_task(task);
}