Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9151761 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'nfsd-4.15-1' of git://linux-nfs.org/~bfields/linux

Pull nfsd fixes from Bruce Fields:
 "I screwed up my merge window pull request; I only sent half of what I
  meant to.

  There were no new features, just bugfixes of various importance and
  some very minor cleanup, so I think it's all still appropriate for
  -rc2.

  Highlights:

   - Fixes from Trond for some races in the NFSv4 state code.

   - Fix from Naofumi Honda for a typo in the blocked lock notificiation
     code

   - Fixes from Vasily Averin for some problems starting and stopping
     lockd especially in network namespaces"

* tag 'nfsd-4.15-1' of git://linux-nfs.org/~bfields/linux: (23 commits)
  lockd: fix "list_add double add" caused by legacy signal interface
  nlm_shutdown_hosts_net() cleanup
  race of nfsd inetaddr notifiers vs nn->nfsd_serv change
  race of lockd inetaddr notifiers vs nlmsvc_rqst change
  SUNRPC: make cache_detail structures const
  NFSD: make cache_detail structures const
  sunrpc: make the function arg as const
  nfsd: check for use of the closed special stateid
  nfsd: fix panic in posix_unblock_lock called from nfs4_laundromat
  lockd: lost rollback of set_grace_period() in lockd_down_net()
  lockd: added cleanup checks in exit_net hook
  grace: replace BUG_ON by WARN_ONCE in exit_net hook
  nfsd: fix locking validator warning on nfs4_ol_stateid->st_mutex class
  lockd: remove net pointer from messages
  nfsd: remove net pointer from debug messages
  nfsd: Fix races with check_stateid_generation()
  nfsd: Ensure we check stateid validity in the seqid operation checks
  nfsd: Fix race in lock stateid creation
  nfsd4: move find_lock_stateid
  nfsd: Ensure we don't recognise lock stateids after freeing them
  ...
parents 26cd9474 81833de1
Loading
Loading
Loading
Loading
+14 −10
Original line number Diff line number Diff line
@@ -578,8 +578,10 @@ static void nlm_complain_hosts(struct net *net)

		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);
		pr_warn("lockd: couldn't shutdown host module for net %x!\n",
			net->ns.inum);
		dprintk("lockd: %lu hosts left in net %x:\n", ln->nrhosts,
			net->ns.inum);
	} else {
		if (nrhosts == 0)
			return;
@@ -590,9 +592,9 @@ static void nlm_complain_hosts(struct net *net)
	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",
		dprintk("       %s (cnt %d use %d exp %ld net %x)\n",
			host->h_name, atomic_read(&host->h_count),
			host->h_inuse, host->h_expires, host->net);
			host->h_inuse, host->h_expires, host->net->ns.inum);
	}
}

@@ -605,7 +607,8 @@ nlm_shutdown_hosts_net(struct net *net)
	mutex_lock(&nlm_host_mutex);

	/* First, make all hosts eligible for gc */
	dprintk("lockd: nuking all hosts in net %p...\n", net);
	dprintk("lockd: nuking all hosts in net %x...\n",
		net ? net->ns.inum : 0);
	for_each_host(host, chain, nlm_server_hosts) {
		if (net && host->net != net)
			continue;
@@ -618,9 +621,8 @@ nlm_shutdown_hosts_net(struct net *net)

	/* Then, perform a garbage collection pass */
	nlm_gc_hosts(net);
	mutex_unlock(&nlm_host_mutex);

	nlm_complain_hosts(net);
	mutex_unlock(&nlm_host_mutex);
}

/*
@@ -646,7 +648,8 @@ nlm_gc_hosts(struct net *net)
	struct hlist_node *next;
	struct nlm_host	*host;

	dprintk("lockd: host garbage collection for net %p\n", net);
	dprintk("lockd: host garbage collection for net %x\n",
		net ? net->ns.inum : 0);
	for_each_host(host, chain, nlm_server_hosts) {
		if (net && host->net != net)
			continue;
@@ -662,9 +665,10 @@ nlm_gc_hosts(struct net *net)
		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",
				"(cnt %d use %d exp %ld net %x)\n",
				host->h_name, atomic_read(&host->h_count),
				host->h_inuse, host->h_expires, host->net);
				host->h_inuse, host->h_expires,
				host->net->ns.inum);
			continue;
		}
		nlm_destroy_host_locked(host);
+2 −1
Original line number Diff line number Diff line
@@ -110,7 +110,8 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
	clnt = nsm_create(host->net, host->nodename);
	if (IS_ERR(clnt)) {
		dprintk("lockd: failed to create NSM upcall transport, "
			"status=%ld, net=%p\n", PTR_ERR(clnt), host->net);
			"status=%ld, net=%x\n", PTR_ERR(clnt),
			host->net->ns.inum);
		return PTR_ERR(clnt);
	}

+32 −6
Original line number Diff line number Diff line
@@ -57,6 +57,9 @@ static struct task_struct *nlmsvc_task;
static struct svc_rqst		*nlmsvc_rqst;
unsigned long			nlmsvc_timeout;

atomic_t nlm_ntf_refcnt = ATOMIC_INIT(0);
DECLARE_WAIT_QUEUE_HEAD(nlm_ntf_wq);

unsigned int lockd_net_id;

/*
@@ -259,7 +262,7 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net)
	if (error < 0)
		goto err_bind;
	set_grace_period(net);
	dprintk("lockd_up_net: per-net data created; net=%p\n", net);
	dprintk("%s: per-net data created; net=%x\n", __func__, net->ns.inum);
	return 0;

err_bind:
@@ -274,12 +277,15 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net)
	if (ln->nlmsvc_users) {
		if (--ln->nlmsvc_users == 0) {
			nlm_shutdown_hosts_net(net);
			cancel_delayed_work_sync(&ln->grace_period_end);
			locks_end_grace(&ln->lockd_manager);
			svc_shutdown_net(serv, net);
			dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net);
			dprintk("%s: per-net data destroyed; net=%x\n",
				__func__, net->ns.inum);
		}
	} else {
		printk(KERN_ERR "lockd_down_net: no users! task=%p, net=%p\n",
				nlmsvc_task, net);
		pr_err("%s: no users! task=%p, net=%x\n",
			__func__, nlmsvc_task, net->ns.inum);
		BUG();
	}
}
@@ -290,7 +296,8 @@ static int lockd_inetaddr_event(struct notifier_block *this,
	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
	struct sockaddr_in sin;

	if (event != NETDEV_DOWN)
	if ((event != NETDEV_DOWN) ||
	    !atomic_inc_not_zero(&nlm_ntf_refcnt))
		goto out;

	if (nlmsvc_rqst) {
@@ -301,6 +308,8 @@ static int lockd_inetaddr_event(struct notifier_block *this,
		svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,
			(struct sockaddr *)&sin);
	}
	atomic_dec(&nlm_ntf_refcnt);
	wake_up(&nlm_ntf_wq);

out:
	return NOTIFY_DONE;
@@ -317,7 +326,8 @@ static int lockd_inet6addr_event(struct notifier_block *this,
	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
	struct sockaddr_in6 sin6;

	if (event != NETDEV_DOWN)
	if ((event != NETDEV_DOWN) ||
	    !atomic_inc_not_zero(&nlm_ntf_refcnt))
		goto out;

	if (nlmsvc_rqst) {
@@ -329,6 +339,8 @@ static int lockd_inet6addr_event(struct notifier_block *this,
		svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,
			(struct sockaddr *)&sin6);
	}
	atomic_dec(&nlm_ntf_refcnt);
	wake_up(&nlm_ntf_wq);

out:
	return NOTIFY_DONE;
@@ -345,10 +357,12 @@ static void lockd_unregister_notifiers(void)
#if IS_ENABLED(CONFIG_IPV6)
	unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
#endif
	wait_event(nlm_ntf_wq, atomic_read(&nlm_ntf_refcnt) == 0);
}

static void lockd_svc_exit_thread(void)
{
	atomic_dec(&nlm_ntf_refcnt);
	lockd_unregister_notifiers();
	svc_exit_thread(nlmsvc_rqst);
}
@@ -373,6 +387,7 @@ static int lockd_start_svc(struct svc_serv *serv)
		goto out_rqst;
	}

	atomic_inc(&nlm_ntf_refcnt);
	svc_sock_update_bufs(serv);
	serv->sv_maxconn = nlm_max_connections;

@@ -676,6 +691,17 @@ static int lockd_init_net(struct net *net)

static void lockd_exit_net(struct net *net)
{
	struct lockd_net *ln = net_generic(net, lockd_net_id);

	WARN_ONCE(!list_empty(&ln->lockd_manager.list),
		  "net %x %s: lockd_manager.list is not empty\n",
		  net->ns.inum, __func__);
	WARN_ONCE(!list_empty(&ln->nsm_handles),
		  "net %x %s: nsm_handles list is not empty\n",
		  net->ns.inum, __func__);
	WARN_ONCE(delayed_work_pending(&ln->grace_period_end),
		  "net %x %s: grace_period_end was not cancelled\n",
		  net->ns.inum, __func__);
}

static struct pernet_operations lockd_net_ops = {
+1 −1
Original line number Diff line number Diff line
@@ -370,7 +370,7 @@ nlmsvc_mark_resources(struct net *net)
{
	struct nlm_host hint;

	dprintk("lockd: nlmsvc_mark_resources for net %p\n", net);
	dprintk("lockd: %s for net %x\n", __func__, net ? net->ns.inum : 0);
	hint.net = net;
	nlm_traverse_files(&hint, nlmsvc_mark_host, NULL);
}
+8 −2
Original line number Diff line number Diff line
@@ -30,7 +30,11 @@ locks_start_grace(struct net *net, struct lock_manager *lm)
	struct list_head *grace_list = net_generic(net, grace_net_id);

	spin_lock(&grace_lock);
	if (list_empty(&lm->list))
		list_add(&lm->list, grace_list);
	else
		WARN(1, "double list_add attempt detected in net %x %s\n",
		     net->ns.inum, (net == &init_net) ? "(init_net)" : "");
	spin_unlock(&grace_lock);
}
EXPORT_SYMBOL_GPL(locks_start_grace);
@@ -104,7 +108,9 @@ grace_exit_net(struct net *net)
{
	struct list_head *grace_list = net_generic(net, grace_net_id);

	BUG_ON(!list_empty(grace_list));
	WARN_ONCE(!list_empty(grace_list),
		  "net %x %s: grace_list is not empty\n",
		  net->ns.inum, __func__);
}

static struct pernet_operations grace_net_ops = {
Loading