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

📄 host.c

📁 Linux中关于远程文件锁定的支持的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * the source address. */struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,				    const char *hostname,				    const size_t hostname_len){	struct sockaddr_in sin = {		.sin_family	= AF_INET,	};	struct sockaddr_in6 sin6 = {		.sin6_family	= AF_INET6,	};	struct nlm_lookup_host_info ni = {		.server		= 1,		.sap		= svc_addr(rqstp),		.salen		= rqstp->rq_addrlen,		.protocol	= rqstp->rq_prot,		.version	= rqstp->rq_vers,		.hostname	= hostname,		.hostname_len	= hostname_len,		.src_len	= rqstp->rq_addrlen,	};	dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__,			(int)hostname_len, hostname, rqstp->rq_vers,			(rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp"));	switch (ni.sap->sa_family) {	case AF_INET:		sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr;		ni.src_sap = (struct sockaddr *)&sin;		break;	case AF_INET6:		ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6);		ni.src_sap = (struct sockaddr *)&sin6;		break;	default:		return NULL;	}	return nlm_lookup_host(&ni);}/* * Create the NLM RPC client for an NLM peer */struct rpc_clnt *nlm_bind_host(struct nlm_host *host){	struct rpc_clnt	*clnt;	dprintk("lockd: nlm_bind_host %s (%s)\n",			host->h_name, host->h_addrbuf);	/* Lock host handle */	mutex_lock(&host->h_mutex);	/* If we've already created an RPC client, check whether	 * RPC rebind is required	 */	if ((clnt = host->h_rpcclnt) != NULL) {		if (time_after_eq(jiffies, host->h_nextrebind)) {			rpc_force_rebind(clnt);			host->h_nextrebind = jiffies + NLM_HOST_REBIND;			dprintk("lockd: next rebind in %lu jiffies\n",					host->h_nextrebind - jiffies);		}	} else {		unsigned long increment = nlmsvc_timeout;		struct rpc_timeout timeparms = {			.to_initval	= increment,			.to_increment	= increment,			.to_maxval	= increment * 6UL,			.to_retries	= 5U,		};		struct rpc_create_args args = {			.protocol	= host->h_proto,			.address	= nlm_addr(host),			.addrsize	= host->h_addrlen,			.saddress	= nlm_srcaddr(host),			.timeout	= &timeparms,			.servername	= host->h_name,			.program	= &nlm_program,			.version	= host->h_version,			.authflavor	= RPC_AUTH_UNIX,			.flags		= (RPC_CLNT_CREATE_NOPING |					   RPC_CLNT_CREATE_AUTOBIND),		};		/*		 * lockd retries server side blocks automatically so we want		 * those to be soft RPC calls. Client side calls need to be		 * hard RPC tasks.		 */		if (!host->h_server)			args.flags |= RPC_CLNT_CREATE_HARDRTRY;		if (host->h_noresvport)			args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;		clnt = rpc_create(&args);		if (!IS_ERR(clnt))			host->h_rpcclnt = clnt;		else {			printk("lockd: couldn't create RPC handle for %s\n", host->h_name);			clnt = NULL;		}	}	mutex_unlock(&host->h_mutex);	return clnt;}/* * Force a portmap lookup of the remote lockd port */voidnlm_rebind_host(struct nlm_host *host){	dprintk("lockd: rebind host %s\n", host->h_name);	if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) {		rpc_force_rebind(host->h_rpcclnt);		host->h_nextrebind = jiffies + NLM_HOST_REBIND;	}}/* * Increment NLM host count */struct nlm_host * nlm_get_host(struct nlm_host *host){	if (host) {		dprintk("lockd: get host %s\n", host->h_name);		atomic_inc(&host->h_count);		host->h_expires = jiffies + NLM_HOST_EXPIRE;	}	return host;}/* * Release NLM host after use */void nlm_release_host(struct nlm_host *host){	if (host != NULL) {		dprintk("lockd: release host %s\n", host->h_name);		BUG_ON(atomic_read(&host->h_count) < 0);		if (atomic_dec_and_test(&host->h_count)) {			BUG_ON(!list_empty(&host->h_lockowners));			BUG_ON(!list_empty(&host->h_granted));			BUG_ON(!list_empty(&host->h_reclaim));		}	}}/** * nlm_host_rebooted - Release all resources held by rebooted host * @info: pointer to decoded results of NLM_SM_NOTIFY call * * We were notified that the specified host has rebooted.  Release * all resources held by that peer. */void nlm_host_rebooted(const struct nlm_reboot *info){	struct hlist_head *chain;	struct hlist_node *pos;	struct nsm_handle *nsm;	struct nlm_host	*host;	nsm = nsm_reboot_lookup(info);	if (unlikely(nsm == NULL))		return;	/* Mark all hosts tied to this NSM state as having rebooted.	 * We run the loop repeatedly, because we drop the host table	 * lock for this.	 * To avoid processing a host several times, we match the nsmstate.	 */again:	mutex_lock(&nlm_host_mutex);	for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {		hlist_for_each_entry(host, pos, chain, h_hash) {			if (host->h_nsmhandle == nsm			 && host->h_nsmstate != info->state) {				host->h_nsmstate = info->state;				host->h_state++;				nlm_get_host(host);				mutex_unlock(&nlm_host_mutex);				if (host->h_server) {					/* We're server for this guy, just ditch					 * all the locks he held. */					nlmsvc_free_host_resources(host);				} else {					/* He's the server, initiate lock recovery. */					nlmclnt_recovery(host);				}				nlm_release_host(host);				goto again;			}		}	}	mutex_unlock(&nlm_host_mutex);}/* * Shut down the hosts module. * Note that this routine is called only at server shutdown time. */voidnlm_shutdown_hosts(void){	struct hlist_head *chain;	struct hlist_node *pos;	struct nlm_host	*host;	dprintk("lockd: shutting down host module\n");	mutex_lock(&nlm_host_mutex);	/* First, make all hosts eligible for gc */	dprintk("lockd: nuking all hosts...\n");	for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {		hlist_for_each_entry(host, pos, chain, h_hash) {			host->h_expires = jiffies - 1;			if (host->h_rpcclnt) {				rpc_shutdown_client(host->h_rpcclnt);				host->h_rpcclnt = NULL;			}		}	}	/* Then, perform a garbage collection pass */	nlm_gc_hosts();	mutex_unlock(&nlm_host_mutex);	/* complain if any hosts are left */	if (nrhosts) {		printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");		dprintk("lockd: %d hosts left:\n", nrhosts);		for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {			hlist_for_each_entry(host, pos, chain, h_hash) {				dprintk("       %s (cnt %d use %d exp %ld)\n",					host->h_name, atomic_read(&host->h_count),					host->h_inuse, host->h_expires);			}		}	}}/* * Garbage collect any unused NLM hosts. * This GC combines reference counting for async operations with * mark & sweep for resources held by remote clients. */static voidnlm_gc_hosts(void){	struct hlist_head *chain;	struct hlist_node *pos, *next;	struct nlm_host	*host;	dprintk("lockd: host garbage collection\n");	for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {		hlist_for_each_entry(host, pos, chain, h_hash)			host->h_inuse = 0;	}	/* Mark all hosts that hold locks, blocks or shares */	nlmsvc_mark_resources();	for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {		hlist_for_each_entry_safe(host, pos, next, chain, h_hash) {			if (atomic_read(&host->h_count) || host->h_inuse			 || time_before(jiffies, host->h_expires)) {				dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n",					host->h_name, atomic_read(&host->h_count),					host->h_inuse, host->h_expires);				continue;			}			dprintk("lockd: delete host %s\n", host->h_name);			hlist_del_init(&host->h_hash);			nlm_destroy_host(host);			nrhosts--;		}	}	next_gc = jiffies + NLM_HOST_COLLECT;}

⌨️ 快捷键说明

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