diff options
Diffstat (limited to 'fs/lockd/host.c')
| -rw-r--r-- | fs/lockd/host.c | 519 | 
1 files changed, 312 insertions, 207 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 25e21e4023b..969d589c848 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -13,24 +13,41 @@  #include <linux/in.h>  #include <linux/in6.h>  #include <linux/sunrpc/clnt.h> +#include <linux/sunrpc/addr.h>  #include <linux/sunrpc/svc.h>  #include <linux/lockd/lockd.h>  #include <linux/mutex.h> +#include <linux/sunrpc/svc_xprt.h> +  #include <net/ipv6.h> +#include "netns.h" +  #define NLMDBG_FACILITY		NLMDBG_HOSTCACHE  #define NLM_HOST_NRHASH		32  #define NLM_HOST_REBIND		(60 * HZ)  #define NLM_HOST_EXPIRE		(300 * HZ)  #define NLM_HOST_COLLECT	(120 * HZ) -static struct hlist_head	nlm_hosts[NLM_HOST_NRHASH]; -static unsigned long		next_gc; -static int			nrhosts; +static struct hlist_head	nlm_server_hosts[NLM_HOST_NRHASH]; +static struct hlist_head	nlm_client_hosts[NLM_HOST_NRHASH]; + +#define for_each_host(host, chain, table) \ +	for ((chain) = (table); \ +	     (chain) < (table) + NLM_HOST_NRHASH; ++(chain)) \ +		hlist_for_each_entry((host), (chain), h_hash) + +#define for_each_host_safe(host, next, chain, table) \ +	for ((chain) = (table); \ +	     (chain) < (table) + NLM_HOST_NRHASH; ++(chain)) \ +		hlist_for_each_entry_safe((host), (next), \ +						(chain), h_hash) + +static unsigned long		nrhosts;  static DEFINE_MUTEX(nlm_host_mutex); -static void			nlm_gc_hosts(void); +static void			nlm_gc_hosts(struct net *net);  struct nlm_lookup_host_info {  	const int		server;		/* search for server|client */ @@ -40,9 +57,8 @@ struct nlm_lookup_host_info {  	const u32		version;	/* NLM version to search for */  	const char		*hostname;	/* remote's hostname */  	const size_t		hostname_len;	/* it's length */ -	const struct sockaddr	*src_sap;	/* our address (optional) */ -	const size_t		src_len;	/* it's length */  	const int		noresvport;	/* use non-priv port */ +	struct net		*net;		/* network namespace to bind */  };  /* @@ -88,125 +104,81 @@ static unsigned int nlm_hash_address(const struct sockaddr *sap)  }  /* - * Common host lookup routine for server & client + * Allocate and initialize an nlm_host.  Common to both client and server.   */ -static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni) +static struct nlm_host *nlm_alloc_host(struct nlm_lookup_host_info *ni, +				       struct nsm_handle *nsm)  { -	struct hlist_head *chain; -	struct hlist_node *pos; -	struct nlm_host	*host; -	struct nsm_handle *nsm = NULL; - -	mutex_lock(&nlm_host_mutex); - -	if (time_after_eq(jiffies, next_gc)) -		nlm_gc_hosts(); - -	/* We may keep several nlm_host objects for a peer, because each -	 * nlm_host is identified by -	 * (address, protocol, version, server/client) -	 * We could probably simplify this a little by putting all those -	 * different NLM rpc_clients into one single nlm_host object. -	 * This would allow us to have one nlm_host per address. -	 */ -	chain = &nlm_hosts[nlm_hash_address(ni->sap)]; -	hlist_for_each_entry(host, pos, chain, h_hash) { -		if (!rpc_cmp_addr(nlm_addr(host), ni->sap)) -			continue; - -		/* See if we have an NSM handle for this client */ -		if (!nsm) -			nsm = host->h_nsmhandle; - -		if (host->h_proto != ni->protocol) -			continue; -		if (host->h_version != ni->version) -			continue; -		if (host->h_server != ni->server) -			continue; -		if (ni->server && -		    !rpc_cmp_addr(nlm_srcaddr(host), ni->src_sap)) -			continue; - -		/* Move to head of hash chain. */ -		hlist_del(&host->h_hash); -		hlist_add_head(&host->h_hash, chain); - -		nlm_get_host(host); -		dprintk("lockd: nlm_lookup_host found host %s (%s)\n", -				host->h_name, host->h_addrbuf); -		goto out; -	} +	struct nlm_host *host = NULL; +	unsigned long now = jiffies; -	/* -	 * The host wasn't in our hash table.  If we don't -	 * have an NSM handle for it yet, create one. -	 */ -	if (nsm) +	if (nsm != NULL)  		atomic_inc(&nsm->sm_count);  	else {  		host = NULL;  		nsm = nsm_get_handle(ni->sap, ni->salen,  					ni->hostname, ni->hostname_len); -		if (!nsm) { -			dprintk("lockd: nlm_lookup_host failed; " -				"no nsm handle\n"); +		if (unlikely(nsm == NULL)) { +			dprintk("lockd: %s failed; no nsm handle\n", +				__func__);  			goto out;  		}  	} -	host = kzalloc(sizeof(*host), GFP_KERNEL); -	if (!host) { +	host = kmalloc(sizeof(*host), GFP_KERNEL); +	if (unlikely(host == NULL)) { +		dprintk("lockd: %s failed; no memory\n", __func__);  		nsm_release(nsm); -		dprintk("lockd: nlm_lookup_host failed; no memory\n");  		goto out;  	} -	host->h_name	   = nsm->sm_name; -	host->h_addrbuf    = nsm->sm_addrbuf; +  	memcpy(nlm_addr(host), ni->sap, ni->salen); -	host->h_addrlen = ni->salen; +	host->h_addrlen    = ni->salen;  	rpc_set_port(nlm_addr(host), 0); -	memcpy(nlm_srcaddr(host), ni->src_sap, ni->src_len); +	host->h_srcaddrlen = 0; + +	host->h_rpcclnt    = NULL; +	host->h_name	   = nsm->sm_name;  	host->h_version    = ni->version;  	host->h_proto      = ni->protocol; -	host->h_rpcclnt    = NULL; -	mutex_init(&host->h_mutex); -	host->h_nextrebind = jiffies + NLM_HOST_REBIND; -	host->h_expires    = jiffies + NLM_HOST_EXPIRE; -	atomic_set(&host->h_count, 1); +	host->h_reclaiming = 0; +	host->h_server     = ni->server; +	host->h_noresvport = ni->noresvport; +	host->h_inuse      = 0;  	init_waitqueue_head(&host->h_gracewait);  	init_rwsem(&host->h_rwsem); -	host->h_state      = 0;			/* pseudo NSM state */ -	host->h_nsmstate   = 0;			/* real NSM state */ -	host->h_nsmhandle  = nsm; -	host->h_server	   = ni->server; -	host->h_noresvport = ni->noresvport; -	hlist_add_head(&host->h_hash, chain); +	host->h_state      = 0; +	host->h_nsmstate   = 0; +	host->h_pidcount   = 0; +	atomic_set(&host->h_count, 1); +	mutex_init(&host->h_mutex); +	host->h_nextrebind = now + NLM_HOST_REBIND; +	host->h_expires    = now + NLM_HOST_EXPIRE;  	INIT_LIST_HEAD(&host->h_lockowners);  	spin_lock_init(&host->h_lock);  	INIT_LIST_HEAD(&host->h_granted);  	INIT_LIST_HEAD(&host->h_reclaim); - -	nrhosts++; - -	dprintk("lockd: nlm_lookup_host created host %s\n", -			host->h_name); +	host->h_nsmhandle  = nsm; +	host->h_addrbuf    = nsm->sm_addrbuf; +	host->net	   = ni->net;  out: -	mutex_unlock(&nlm_host_mutex);  	return host;  }  /* - * Destroy a host + * Destroy an nlm_host and free associated resources + * + * Caller must hold nlm_host_mutex.   */ -static void -nlm_destroy_host(struct nlm_host *host) +static void nlm_destroy_host_locked(struct nlm_host *host)  {  	struct rpc_clnt	*clnt; +	struct lockd_net *ln = net_generic(host->net, lockd_net_id); + +	dprintk("lockd: destroy host %s\n", host->h_name); -	BUG_ON(!list_empty(&host->h_lockowners)); -	BUG_ON(atomic_read(&host->h_count)); +	hlist_del_init(&host->h_hash);  	nsm_unmonitor(host);  	nsm_release(host->h_nsmhandle); @@ -215,6 +187,9 @@ nlm_destroy_host(struct nlm_host *host)  	if (clnt != NULL)  		rpc_shutdown_client(clnt);  	kfree(host); + +	ln->nrhosts--; +	nrhosts--;  }  /** @@ -236,11 +211,9 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,  				     const unsigned short protocol,  				     const u32 version,  				     const char *hostname, -				     int noresvport) +				     int noresvport, +				     struct net *net)  { -	const struct sockaddr source = { -		.sa_family	= AF_UNSPEC, -	};  	struct nlm_lookup_host_info ni = {  		.server		= 0,  		.sap		= sap, @@ -249,16 +222,81 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,  		.version	= version,  		.hostname	= hostname,  		.hostname_len	= strlen(hostname), -		.src_sap	= &source, -		.src_len	= sizeof(source),  		.noresvport	= noresvport, +		.net		= net,  	}; +	struct hlist_head *chain; +	struct nlm_host	*host; +	struct nsm_handle *nsm = NULL; +	struct lockd_net *ln = net_generic(net, lockd_net_id);  	dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,  			(hostname ? hostname : "<none>"), version,  			(protocol == IPPROTO_UDP ? "udp" : "tcp")); -	return nlm_lookup_host(&ni); +	mutex_lock(&nlm_host_mutex); + +	chain = &nlm_client_hosts[nlm_hash_address(sap)]; +	hlist_for_each_entry(host, chain, h_hash) { +		if (host->net != net) +			continue; +		if (!rpc_cmp_addr(nlm_addr(host), sap)) +			continue; + +		/* Same address. Share an NSM handle if we already have one */ +		if (nsm == NULL) +			nsm = host->h_nsmhandle; + +		if (host->h_proto != protocol) +			continue; +		if (host->h_version != version) +			continue; + +		nlm_get_host(host); +		dprintk("lockd: %s found host %s (%s)\n", __func__, +			host->h_name, host->h_addrbuf); +		goto out; +	} + +	host = nlm_alloc_host(&ni, nsm); +	if (unlikely(host == NULL)) +		goto out; + +	hlist_add_head(&host->h_hash, chain); +	ln->nrhosts++; +	nrhosts++; + +	dprintk("lockd: %s created host %s (%s)\n", __func__, +		host->h_name, host->h_addrbuf); + +out: +	mutex_unlock(&nlm_host_mutex); +	return host; +} + +/** + * nlmclnt_release_host - release client nlm_host + * @host: nlm_host to release + * + */ +void nlmclnt_release_host(struct nlm_host *host) +{ +	if (host == NULL) +		return; + +	dprintk("lockd: release client host %s\n", host->h_name); + +	WARN_ON_ONCE(host->h_server); + +	if (atomic_dec_and_test(&host->h_count)) { +		WARN_ON_ONCE(!list_empty(&host->h_lockowners)); +		WARN_ON_ONCE(!list_empty(&host->h_granted)); +		WARN_ON_ONCE(!list_empty(&host->h_reclaim)); + +		mutex_lock(&nlm_host_mutex); +		nlm_destroy_host_locked(host); +		mutex_unlock(&nlm_host_mutex); +	}  }  /** @@ -283,12 +321,12 @@ 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 hlist_head *chain; +	struct nlm_host	*host = NULL; +	struct nsm_handle *nsm = NULL; +	struct sockaddr *src_sap = svc_daddr(rqstp); +	size_t src_len = rqstp->rq_daddrlen; +	struct net *net = SVC_NET(rqstp);  	struct nlm_lookup_host_info ni = {  		.server		= 1,  		.sap		= svc_addr(rqstp), @@ -297,27 +335,80 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,  		.version	= rqstp->rq_vers,  		.hostname	= hostname,  		.hostname_len	= hostname_len, -		.src_len	= rqstp->rq_addrlen, +		.net		= net,  	}; +	struct lockd_net *ln = net_generic(net, lockd_net_id);  	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; +	mutex_lock(&nlm_host_mutex); + +	if (time_after_eq(jiffies, ln->next_gc)) +		nlm_gc_hosts(net); + +	chain = &nlm_server_hosts[nlm_hash_address(ni.sap)]; +	hlist_for_each_entry(host, chain, h_hash) { +		if (host->net != net) +			continue; +		if (!rpc_cmp_addr(nlm_addr(host), ni.sap)) +			continue; + +		/* Same address. Share an NSM handle if we already have one */ +		if (nsm == NULL) +			nsm = host->h_nsmhandle; + +		if (host->h_proto != ni.protocol) +			continue; +		if (host->h_version != ni.version) +			continue; +		if (!rpc_cmp_addr(nlm_srcaddr(host), src_sap)) +			continue; + +		/* Move to head of hash chain. */ +		hlist_del(&host->h_hash); +		hlist_add_head(&host->h_hash, chain); + +		nlm_get_host(host); +		dprintk("lockd: %s found host %s (%s)\n", +			__func__, host->h_name, host->h_addrbuf); +		goto out;  	} -	return nlm_lookup_host(&ni); +	host = nlm_alloc_host(&ni, nsm); +	if (unlikely(host == NULL)) +		goto out; + +	memcpy(nlm_srcaddr(host), src_sap, src_len); +	host->h_srcaddrlen = src_len; +	hlist_add_head(&host->h_hash, chain); +	ln->nrhosts++; +	nrhosts++; + +	dprintk("lockd: %s created host %s (%s)\n", +		__func__, host->h_name, host->h_addrbuf); + +out: +	mutex_unlock(&nlm_host_mutex); +	return host; +} + +/** + * nlmsvc_release_host - release server nlm_host + * @host: nlm_host to release + * + * Host is destroyed later in nlm_gc_host(). + */ +void nlmsvc_release_host(struct nlm_host *host) +{ +	if (host == NULL) +		return; + +	dprintk("lockd: release server host %s\n", host->h_name); + +	WARN_ON_ONCE(!host->h_server); +	atomic_dec(&host->h_count);  }  /* @@ -353,11 +444,10 @@ nlm_bind_host(struct nlm_host *host)  			.to_retries	= 5U,  		};  		struct rpc_create_args args = { -			.net		= &init_net, +			.net		= host->net,  			.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, @@ -376,6 +466,8 @@ nlm_bind_host(struct nlm_host *host)  			args.flags |= RPC_CLNT_CREATE_HARDRTRY;  		if (host->h_noresvport)  			args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; +		if (host->h_srcaddrlen) +			args.saddress = nlm_srcaddr(host);  		clnt = rpc_create(&args);  		if (!IS_ERR(clnt)) @@ -416,20 +508,28 @@ struct nlm_host * nlm_get_host(struct nlm_host *host)  	return host;  } -/* - * Release NLM host after use - */ -void nlm_release_host(struct nlm_host *host) +static struct nlm_host *next_host_state(struct hlist_head *cache, +					struct nsm_handle *nsm, +					const struct nlm_reboot *info)  { -	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)); +	struct nlm_host *host; +	struct hlist_head *chain; + +	mutex_lock(&nlm_host_mutex); +	for_each_host(host, chain, cache) { +		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); +			return host;  		}  	} + +	mutex_unlock(&nlm_host_mutex); +	return NULL;  }  /** @@ -441,8 +541,6 @@ void nlm_release_host(struct nlm_host *host)   */  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; @@ -455,77 +553,82 @@ void nlm_host_rebooted(const struct nlm_reboot *info)  	 * 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; -			} -		} +	while ((host = next_host_state(nlm_server_hosts, nsm, info)) != NULL) { +		nlmsvc_free_host_resources(host); +		nlmsvc_release_host(host);  	} -	mutex_unlock(&nlm_host_mutex); +	while ((host = next_host_state(nlm_client_hosts, nsm, info)) != NULL) { +		nlmclnt_recovery(host); +		nlmclnt_release_host(host); +	} +  	nsm_release(nsm);  } -/* - * Shut down the hosts module. - * Note that this routine is called only at server shutdown time. - */ +static void nlm_complain_hosts(struct net *net) +{ +	struct hlist_head *chain; +	struct nlm_host	*host; + +	if (net) { +		struct lockd_net *ln = net_generic(net, lockd_net_id); + +		if (ln->nrhosts == 0) +			return; +		printk(KERN_WARNING "lockd: couldn't shutdown host module for net %p!\n", net); +		dprintk("lockd: %lu hosts left in net %p:\n", ln->nrhosts, net); +	} else { +		if (nrhosts == 0) +			return; +		printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); +		dprintk("lockd: %lu hosts left:\n", nrhosts); +	} + +	for_each_host(host, chain, nlm_server_hosts) { +		if (net && host->net != net) +			continue; +		dprintk("       %s (cnt %d use %d exp %ld net %p)\n", +			host->h_name, atomic_read(&host->h_count), +			host->h_inuse, host->h_expires, host->net); +	} +} +  void -nlm_shutdown_hosts(void) +nlm_shutdown_hosts_net(struct net *net)  {  	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; -			} +	dprintk("lockd: nuking all hosts in net %p...\n", net); +	for_each_host(host, chain, nlm_server_hosts) { +		if (net && host->net != net) +			continue; +		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(); +	nlm_gc_hosts(net);  	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); -			} -		} -	} +	nlm_complain_hosts(net); +} + +/* + * Shut down the hosts module. + * Note that this routine is called only at server shutdown time. + */ +void +nlm_shutdown_hosts(void) +{ +	dprintk("lockd: shutting down host module\n"); +	nlm_shutdown_hosts_net(NULL);  }  /* @@ -534,37 +637,39 @@ nlm_shutdown_hosts(void)   * mark & sweep for resources held by remote clients.   */  static void -nlm_gc_hosts(void) +nlm_gc_hosts(struct net *net)  {  	struct hlist_head *chain; -	struct hlist_node *pos, *next; +	struct hlist_node *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; +	dprintk("lockd: host garbage collection for net %p\n", net); +	for_each_host(host, chain, nlm_server_hosts) { +		if (net && host->net != net) +			continue; +		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--; +	nlmsvc_mark_resources(net); + +	for_each_host_safe(host, next, chain, nlm_server_hosts) { +		if (net && host->net != net) +			continue; +		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 net %p)\n", +				host->h_name, atomic_read(&host->h_count), +				host->h_inuse, host->h_expires, host->net); +			continue;  		} +		nlm_destroy_host_locked(host);  	} -	next_gc = jiffies + NLM_HOST_COLLECT; +	if (net) { +		struct lockd_net *ln = net_generic(net, lockd_net_id); + +		ln->next_gc = jiffies + NLM_HOST_COLLECT; +	}  }  | 
