⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clntproc.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct nlm_host	*host = req->a_host;	struct rpc_clnt	*clnt;	struct nlm_args	*argp = &req->a_args;	struct nlm_res	*resp = &req->a_res;	struct file	*file = argp->lock.fl.fl_file;	struct rpc_message msg;	int		status;	dprintk("lockd: call procedure %s on %s (async)\n",			nlm_procname(proc), host->h_name);	/* If we have no RPC client yet, create one. */	if ((clnt = nlm_bind_host(host)) == NULL)		return -ENOLCK;        /* bootstrap and kick off the async RPC call */	msg.rpc_proc = proc;	msg.rpc_argp = argp;	msg.rpc_resp =resp;	if (file)		msg.rpc_cred = nfs_file_cred(file);	else		msg.rpc_cred = NULL;	/* Increment host refcount */	nlm_get_host(host);        status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);	if (status < 0)		nlm_release_host(host);	return status;}/* * TEST for the presence of a conflicting lock */static intnlmclnt_test(struct nlm_rqst *req, struct file_lock *fl){	int	status;	if ((status = nlmclnt_call(req, NLMPROC_TEST)) < 0)		return status;	status = req->a_res.status;	if (status == NLM_LCK_GRANTED) {		fl->fl_type = F_UNLCK;	} if (status == NLM_LCK_DENIED) {		/*		 * Report the conflicting lock back to the application.		 * FIXME: Is it OK to report the pid back as well?		 */		locks_copy_lock(fl, &req->a_res.lock.fl);		/* fl->fl_pid = 0; */	} else {		return nlm_stat_to_errno(req->a_res.status);	}	return 0;}staticvoid nlmclnt_insert_lock_callback(struct file_lock *fl){	nlm_get_host(fl->fl_u.nfs_fl.host);}staticvoid nlmclnt_remove_lock_callback(struct file_lock *fl){	if (fl->fl_u.nfs_fl.host) {		nlm_release_host(fl->fl_u.nfs_fl.host);		fl->fl_u.nfs_fl.host = NULL;	}}/* * LOCK: Try to create a lock * *			Programmer Harassment Alert * * When given a blocking lock request in a sync RPC call, the HPUX lockd * will faithfully return LCK_BLOCKED but never cares to notify us when * the lock could be granted. This way, our local process could hang * around forever waiting for the callback. * *  Solution A:	Implement busy-waiting *  Solution B: Use the async version of the call (NLM_LOCK_{MSG,RES}) * * For now I am implementing solution A, because I hate the idea of * re-implementing lockd for a third time in two months. The async * calls shouldn't be too hard to do, however. * * This is one of the lovely things about standards in the NFS area: * they're so soft and squishy you can't really blame HP for doing this. */static intnlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl){	struct nlm_host	*host = req->a_host;	struct nlm_res	*resp = &req->a_res;	int		status;	if (!host->h_monitored && nsm_monitor(host) < 0) {		printk(KERN_NOTICE "lockd: failed to monitor %s\n",					host->h_name);		return -ENOLCK;	}	do {		if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) {			if (resp->status != NLM_LCK_BLOCKED)				break;			status = nlmclnt_block(host, fl, &resp->status);		}		if (status < 0)			return status;	} while (resp->status == NLM_LCK_BLOCKED);	if (resp->status == NLM_LCK_GRANTED) {		fl->fl_u.nfs_fl.state = host->h_state;		fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;		fl->fl_u.nfs_fl.host = host;		fl->fl_insert = nlmclnt_insert_lock_callback;		fl->fl_remove = nlmclnt_remove_lock_callback;	}	return nlm_stat_to_errno(resp->status);}/* * RECLAIM: Try to reclaim a lock */intnlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl){	struct nlm_rqst reqst, *req;	int		status;	req = &reqst;	memset(req, 0, sizeof(*req));	locks_init_lock(&req->a_args.lock.fl);	locks_init_lock(&req->a_res.lock.fl);	req->a_host  = host;	req->a_flags = 0;	/* Set up the argument struct */	nlmclnt_setlockargs(req, fl);	req->a_args.reclaim = 1;	if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0	 && req->a_res.status == NLM_LCK_GRANTED)		return 0;	printk(KERN_WARNING "lockd: failed to reclaim lock for pid %d "				"(errno %d, status %d)\n", fl->fl_pid,				status, req->a_res.status);	/*	 * FIXME: This is a serious failure. We can	 *	 *  a.	Ignore the problem	 *  b.	Send the owning process some signal (Linux doesn't have	 *	SIGLOST, though...)	 *  c.	Retry the operation	 *	 * Until someone comes up with a simple implementation	 * for b or c, I'll choose option a.	 */	return -ENOLCK;}/* * UNLOCK: remove an existing lock */static intnlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl){	struct nlm_res	*resp = &req->a_res;	int		status;	/* Clean the GRANTED flag now so the lock doesn't get	 * reclaimed while we're stuck in the unlock call. */	fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED;	if (req->a_flags & RPC_TASK_ASYNC) {		return nlmclnt_async_call(req, NLMPROC_UNLOCK,					nlmclnt_unlock_callback);	}	if ((status = nlmclnt_call(req, NLMPROC_UNLOCK)) < 0)		return status;	if (resp->status == NLM_LCK_GRANTED)		return 0;	if (resp->status != NLM_LCK_DENIED_NOLOCKS)		printk("lockd: unexpected unlock status: %d\n", resp->status);	/* What to do now? I'm out of my depth... */	return -ENOLCK;}static voidnlmclnt_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);		goto retry_rebind;	}	if (status == NLM_LCK_DENIED_GRACE_PERIOD) {		rpc_delay(task, NLMCLNT_GRACE_WAIT);		goto retry_unlock;	}	if (status != NLM_LCK_GRANTED)		printk(KERN_WARNING "lockd: unexpected unlock status: %d\n", status);die:	nlm_release_host(req->a_host);	kfree(req);	return; retry_rebind:	nlm_rebind_host(req->a_host); retry_unlock:	rpc_restart_call(task);}/* * 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. */intnlmclnt_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);	req = nlmclnt_alloc_call();	if (!req)		return -ENOMEM;	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)		kfree(req);	spin_lock_irqsave(&current->sigmask_lock, flags);	current->blocked = oldset;	recalc_sigpending(current);	spin_unlock_irqrestore(&current->sigmask_lock, flags);	return status;}static voidnlmclnt_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:	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);}/* * Convert an NLM status code to a generic kernel errno */static intnlm_stat_to_errno(u32 status){	switch(status) {	case NLM_LCK_GRANTED:		return 0;	case NLM_LCK_DENIED:		return -EAGAIN;	case NLM_LCK_DENIED_NOLOCKS:	case NLM_LCK_DENIED_GRACE_PERIOD:		return -ENOLCK;	case NLM_LCK_BLOCKED:		printk(KERN_NOTICE "lockd: unexpected status NLM_BLOCKED\n");		return -ENOLCK;#ifdef CONFIG_LOCKD_V4	case NLM_DEADLCK:		return -EDEADLK;	case NLM_ROFS:		return -EROFS;	case NLM_STALE_FH:		return -ESTALE;	case NLM_FBIG:		return -EOVERFLOW;	case NLM_FAILED:		return -ENOLCK;#endif	}	printk(KERN_NOTICE "lockd: unexpected server status %d\n", status);	return -ENOLCK;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -