Commit b9151761 authored by Linus Torvalds's avatar Linus Torvalds

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
...@@ -578,8 +578,10 @@ static void nlm_complain_hosts(struct net *net) ...@@ -578,8 +578,10 @@ static void nlm_complain_hosts(struct net *net)
if (ln->nrhosts == 0) if (ln->nrhosts == 0)
return; return;
printk(KERN_WARNING "lockd: couldn't shutdown host module for net %p!\n", net); pr_warn("lockd: couldn't shutdown host module for net %x!\n",
dprintk("lockd: %lu hosts left in net %p:\n", ln->nrhosts, net); net->ns.inum);
dprintk("lockd: %lu hosts left in net %x:\n", ln->nrhosts,
net->ns.inum);
} else { } else {
if (nrhosts == 0) if (nrhosts == 0)
return; return;
...@@ -590,9 +592,9 @@ static void nlm_complain_hosts(struct net *net) ...@@ -590,9 +592,9 @@ static void nlm_complain_hosts(struct net *net)
for_each_host(host, chain, nlm_server_hosts) { for_each_host(host, chain, nlm_server_hosts) {
if (net && host->net != net) if (net && host->net != net)
continue; 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_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) ...@@ -605,7 +607,8 @@ nlm_shutdown_hosts_net(struct net *net)
mutex_lock(&nlm_host_mutex); mutex_lock(&nlm_host_mutex);
/* First, make all hosts eligible for gc */ /* 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) { for_each_host(host, chain, nlm_server_hosts) {
if (net && host->net != net) if (net && host->net != net)
continue; continue;
...@@ -618,9 +621,8 @@ nlm_shutdown_hosts_net(struct net *net) ...@@ -618,9 +621,8 @@ nlm_shutdown_hosts_net(struct net *net)
/* Then, perform a garbage collection pass */ /* Then, perform a garbage collection pass */
nlm_gc_hosts(net); nlm_gc_hosts(net);
mutex_unlock(&nlm_host_mutex);
nlm_complain_hosts(net); nlm_complain_hosts(net);
mutex_unlock(&nlm_host_mutex);
} }
/* /*
...@@ -646,7 +648,8 @@ nlm_gc_hosts(struct net *net) ...@@ -646,7 +648,8 @@ nlm_gc_hosts(struct net *net)
struct hlist_node *next; struct hlist_node *next;
struct nlm_host *host; 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) { for_each_host(host, chain, nlm_server_hosts) {
if (net && host->net != net) if (net && host->net != net)
continue; continue;
...@@ -662,9 +665,10 @@ nlm_gc_hosts(struct net *net) ...@@ -662,9 +665,10 @@ nlm_gc_hosts(struct net *net)
if (atomic_read(&host->h_count) || host->h_inuse if (atomic_read(&host->h_count) || host->h_inuse
|| time_before(jiffies, host->h_expires)) { || time_before(jiffies, host->h_expires)) {
dprintk("nlm_gc_hosts skipping %s " 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_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; continue;
} }
nlm_destroy_host_locked(host); nlm_destroy_host_locked(host);
......
...@@ -110,7 +110,8 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, ...@@ -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); clnt = nsm_create(host->net, host->nodename);
if (IS_ERR(clnt)) { if (IS_ERR(clnt)) {
dprintk("lockd: failed to create NSM upcall transport, " 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); return PTR_ERR(clnt);
} }
......
...@@ -57,6 +57,9 @@ static struct task_struct *nlmsvc_task; ...@@ -57,6 +57,9 @@ static struct task_struct *nlmsvc_task;
static struct svc_rqst *nlmsvc_rqst; static struct svc_rqst *nlmsvc_rqst;
unsigned long nlmsvc_timeout; unsigned long nlmsvc_timeout;
atomic_t nlm_ntf_refcnt = ATOMIC_INIT(0);
DECLARE_WAIT_QUEUE_HEAD(nlm_ntf_wq);
unsigned int lockd_net_id; unsigned int lockd_net_id;
/* /*
...@@ -259,7 +262,7 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net) ...@@ -259,7 +262,7 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net)
if (error < 0) if (error < 0)
goto err_bind; goto err_bind;
set_grace_period(net); 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; return 0;
err_bind: err_bind:
...@@ -274,12 +277,15 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net) ...@@ -274,12 +277,15 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net)
if (ln->nlmsvc_users) { if (ln->nlmsvc_users) {
if (--ln->nlmsvc_users == 0) { if (--ln->nlmsvc_users == 0) {
nlm_shutdown_hosts_net(net); nlm_shutdown_hosts_net(net);
cancel_delayed_work_sync(&ln->grace_period_end);
locks_end_grace(&ln->lockd_manager);
svc_shutdown_net(serv, net); 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 { } else {
printk(KERN_ERR "lockd_down_net: no users! task=%p, net=%p\n", pr_err("%s: no users! task=%p, net=%x\n",
nlmsvc_task, net); __func__, nlmsvc_task, net->ns.inum);
BUG(); BUG();
} }
} }
...@@ -290,7 +296,8 @@ static int lockd_inetaddr_event(struct notifier_block *this, ...@@ -290,7 +296,8 @@ static int lockd_inetaddr_event(struct notifier_block *this,
struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
struct sockaddr_in sin; struct sockaddr_in sin;
if (event != NETDEV_DOWN) if ((event != NETDEV_DOWN) ||
!atomic_inc_not_zero(&nlm_ntf_refcnt))
goto out; goto out;
if (nlmsvc_rqst) { if (nlmsvc_rqst) {
...@@ -301,6 +308,8 @@ static int lockd_inetaddr_event(struct notifier_block *this, ...@@ -301,6 +308,8 @@ static int lockd_inetaddr_event(struct notifier_block *this,
svc_age_temp_xprts_now(nlmsvc_rqst->rq_server, svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,
(struct sockaddr *)&sin); (struct sockaddr *)&sin);
} }
atomic_dec(&nlm_ntf_refcnt);
wake_up(&nlm_ntf_wq);
out: out:
return NOTIFY_DONE; return NOTIFY_DONE;
...@@ -317,7 +326,8 @@ static int lockd_inet6addr_event(struct notifier_block *this, ...@@ -317,7 +326,8 @@ static int lockd_inet6addr_event(struct notifier_block *this,
struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
struct sockaddr_in6 sin6; struct sockaddr_in6 sin6;
if (event != NETDEV_DOWN) if ((event != NETDEV_DOWN) ||
!atomic_inc_not_zero(&nlm_ntf_refcnt))
goto out; goto out;
if (nlmsvc_rqst) { if (nlmsvc_rqst) {
...@@ -329,6 +339,8 @@ static int lockd_inet6addr_event(struct notifier_block *this, ...@@ -329,6 +339,8 @@ static int lockd_inet6addr_event(struct notifier_block *this,
svc_age_temp_xprts_now(nlmsvc_rqst->rq_server, svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,
(struct sockaddr *)&sin6); (struct sockaddr *)&sin6);
} }
atomic_dec(&nlm_ntf_refcnt);
wake_up(&nlm_ntf_wq);
out: out:
return NOTIFY_DONE; return NOTIFY_DONE;
...@@ -345,10 +357,12 @@ static void lockd_unregister_notifiers(void) ...@@ -345,10 +357,12 @@ static void lockd_unregister_notifiers(void)
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
unregister_inet6addr_notifier(&lockd_inet6addr_notifier); unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
#endif #endif
wait_event(nlm_ntf_wq, atomic_read(&nlm_ntf_refcnt) == 0);
} }
static void lockd_svc_exit_thread(void) static void lockd_svc_exit_thread(void)
{ {
atomic_dec(&nlm_ntf_refcnt);
lockd_unregister_notifiers(); lockd_unregister_notifiers();
svc_exit_thread(nlmsvc_rqst); svc_exit_thread(nlmsvc_rqst);
} }
...@@ -373,6 +387,7 @@ static int lockd_start_svc(struct svc_serv *serv) ...@@ -373,6 +387,7 @@ static int lockd_start_svc(struct svc_serv *serv)
goto out_rqst; goto out_rqst;
} }
atomic_inc(&nlm_ntf_refcnt);
svc_sock_update_bufs(serv); svc_sock_update_bufs(serv);
serv->sv_maxconn = nlm_max_connections; serv->sv_maxconn = nlm_max_connections;
...@@ -676,6 +691,17 @@ static int lockd_init_net(struct net *net) ...@@ -676,6 +691,17 @@ static int lockd_init_net(struct net *net)
static void lockd_exit_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 = { static struct pernet_operations lockd_net_ops = {
......
...@@ -370,7 +370,7 @@ nlmsvc_mark_resources(struct net *net) ...@@ -370,7 +370,7 @@ nlmsvc_mark_resources(struct net *net)
{ {
struct nlm_host hint; 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; hint.net = net;
nlm_traverse_files(&hint, nlmsvc_mark_host, NULL); nlm_traverse_files(&hint, nlmsvc_mark_host, NULL);
} }
......
...@@ -30,7 +30,11 @@ locks_start_grace(struct net *net, struct lock_manager *lm) ...@@ -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); struct list_head *grace_list = net_generic(net, grace_net_id);
spin_lock(&grace_lock); spin_lock(&grace_lock);
list_add(&lm->list, grace_list); 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); spin_unlock(&grace_lock);
} }
EXPORT_SYMBOL_GPL(locks_start_grace); EXPORT_SYMBOL_GPL(locks_start_grace);
...@@ -104,7 +108,9 @@ grace_exit_net(struct net *net) ...@@ -104,7 +108,9 @@ grace_exit_net(struct net *net)
{ {
struct list_head *grace_list = net_generic(net, grace_net_id); 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 = { static struct pernet_operations grace_net_ops = {
......
...@@ -232,7 +232,7 @@ static struct cache_head *expkey_alloc(void) ...@@ -232,7 +232,7 @@ static struct cache_head *expkey_alloc(void)
return NULL; return NULL;
} }
static struct cache_detail svc_expkey_cache_template = { static const struct cache_detail svc_expkey_cache_template = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.hash_size = EXPKEY_HASHMAX, .hash_size = EXPKEY_HASHMAX,
.name = "nfsd.fh", .name = "nfsd.fh",
...@@ -748,7 +748,7 @@ static struct cache_head *svc_export_alloc(void) ...@@ -748,7 +748,7 @@ static struct cache_head *svc_export_alloc(void)
return NULL; return NULL;
} }
static struct cache_detail svc_export_cache_template = { static const struct cache_detail svc_export_cache_template = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.hash_size = EXPORT_HASHMAX, .hash_size = EXPORT_HASHMAX,
.name = "nfsd.export", .name = "nfsd.export",
...@@ -1230,7 +1230,7 @@ nfsd_export_init(struct net *net) ...@@ -1230,7 +1230,7 @@ nfsd_export_init(struct net *net)
int rv; int rv;
struct nfsd_net *nn = net_generic(net, nfsd_net_id); struct nfsd_net *nn = net_generic(net, nfsd_net_id);
dprintk("nfsd: initializing export module (net: %p).\n", net); dprintk("nfsd: initializing export module (net: %x).\n", net->ns.inum);
nn->svc_export_cache = cache_create_net(&svc_export_cache_template, net); nn->svc_export_cache = cache_create_net(&svc_export_cache_template, net);
if (IS_ERR(nn->svc_export_cache)) if (IS_ERR(nn->svc_export_cache))
...@@ -1278,7 +1278,7 @@ nfsd_export_shutdown(struct net *net) ...@@ -1278,7 +1278,7 @@ nfsd_export_shutdown(struct net *net)
{ {
struct nfsd_net *nn = net_generic(net, nfsd_net_id); struct nfsd_net *nn = net_generic(net, nfsd_net_id);
dprintk("nfsd: shutting down export module (net: %p).\n", net); dprintk("nfsd: shutting down export module (net: %x).\n", net->ns.inum);
cache_unregister_net(nn->svc_expkey_cache, net); cache_unregister_net(nn->svc_expkey_cache, net);
cache_unregister_net(nn->svc_export_cache, net); cache_unregister_net(nn->svc_export_cache, net);
...@@ -1286,5 +1286,5 @@ nfsd_export_shutdown(struct net *net) ...@@ -1286,5 +1286,5 @@ nfsd_export_shutdown(struct net *net)
cache_destroy_net(nn->svc_export_cache, net); cache_destroy_net(nn->svc_export_cache, net);
svcauth_unix_purge(net); svcauth_unix_purge(net);
dprintk("nfsd: export shutdown complete (net: %p).\n", net); dprintk("nfsd: export shutdown complete (net: %x).\n", net->ns.inum);
} }
...@@ -119,6 +119,9 @@ struct nfsd_net { ...@@ -119,6 +119,9 @@ struct nfsd_net {
u32 clverifier_counter; u32 clverifier_counter;
struct svc_serv *nfsd_serv; struct svc_serv *nfsd_serv;
wait_queue_head_t ntf_wq;
atomic_t ntf_refcnt;
}; };
/* Simple check to find out if a given net was properly initialized */ /* Simple check to find out if a given net was properly initialized */
......
...@@ -178,7 +178,7 @@ static struct ent *idtoname_lookup(struct cache_detail *, struct ent *); ...@@ -178,7 +178,7 @@ static struct ent *idtoname_lookup(struct cache_detail *, struct ent *);
static struct ent *idtoname_update(struct cache_detail *, struct ent *, static struct ent *idtoname_update(struct cache_detail *, struct ent *,
struct ent *); struct ent *);
static struct cache_detail idtoname_cache_template = { static const struct cache_detail idtoname_cache_template = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.hash_size = ENT_HASHMAX, .hash_size = ENT_HASHMAX,
.name = "nfs4.idtoname", .name = "nfs4.idtoname",
...@@ -341,7 +341,7 @@ static struct ent *nametoid_update(struct cache_detail *, struct ent *, ...@@ -341,7 +341,7 @@ static struct ent *nametoid_update(struct cache_detail *, struct ent *,
struct ent *); struct ent *);
static int nametoid_parse(struct cache_detail *, char *, int); static int nametoid_parse(struct cache_detail *, char *, int);
static struct cache_detail nametoid_cache_template = { static const struct cache_detail nametoid_cache_template = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.hash_size = ENT_HASHMAX, .hash_size = ENT_HASHMAX,
.name = "nfs4.nametoid", .name = "nfs4.nametoid",
......
This diff is collapsed.
...@@ -1241,6 +1241,9 @@ static __net_init int nfsd_init_net(struct net *net) ...@@ -1241,6 +1241,9 @@ static __net_init int nfsd_init_net(struct net *net)
nn->nfsd4_grace = 90; nn->nfsd4_grace = 90;
nn->clverifier_counter = prandom_u32(); nn->clverifier_counter = prandom_u32();
nn->clientid_counter = prandom_u32(); nn->clientid_counter = prandom_u32();
atomic_set(&nn->ntf_refcnt, 0);
init_waitqueue_head(&nn->ntf_wq);
return 0; return 0;
out_idmap_error: out_idmap_error:
......
...@@ -335,7 +335,8 @@ static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event, ...@@ -335,7 +335,8 @@ static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event,
struct nfsd_net *nn = net_generic(net, nfsd_net_id); struct nfsd_net *nn = net_generic(net, nfsd_net_id);
struct sockaddr_in sin; struct sockaddr_in sin;
if (event != NETDEV_DOWN) if ((event != NETDEV_DOWN) ||
!atomic_inc_not_zero(&nn->ntf_refcnt))
goto out; goto out;
if (nn->nfsd_serv) { if (nn->nfsd_serv) {
...@@ -344,6 +345,8 @@ static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event, ...@@ -344,6 +345,8 @@ static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event,
sin.sin_addr.s_addr = ifa->ifa_local; sin.sin_addr.s_addr = ifa->ifa_local;
svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin); svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin);
} }
atomic_dec(&nn->ntf_refcnt);
wake_up(&nn->ntf_wq);
out: out:
return NOTIFY_DONE; return NOTIFY_DONE;
...@@ -363,7 +366,8 @@ static int nfsd_inet6addr_event(struct notifier_block *this, ...@@ -363,7 +366,8 @@ static int nfsd_inet6addr_event(struct notifier_block *this,
struct nfsd_net *nn = net_generic(net, nfsd_net_id); struct nfsd_net *nn = net_generic(net, nfsd_net_id);
struct sockaddr_in6 sin6; struct sockaddr_in6 sin6;
if (event != NETDEV_DOWN) if ((event != NETDEV_DOWN) ||
!atomic_inc_not_zero(&nn->ntf_refcnt))
goto out; goto out;
if (nn->nfsd_serv) { if (nn->nfsd_serv) {
...@@ -374,7 +378,8 @@ static int nfsd_inet6addr_event(struct notifier_block *this, ...@@ -374,7 +378,8 @@ static int nfsd_inet6addr_event(struct notifier_block *this,
sin6.sin6_scope_id = ifa->idev->dev->ifindex; sin6.sin6_scope_id = ifa->idev->dev->ifindex;
svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin6); svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin6);
} }
atomic_dec(&nn->ntf_refcnt);
wake_up(&nn->ntf_wq);
out: out:
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -391,6 +396,7 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net) ...@@ -391,6 +396,7 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
{ {
struct nfsd_net *nn = net_generic(net, nfsd_net_id); struct nfsd_net *nn = net_generic(net, nfsd_net_id);
atomic_dec(&nn->ntf_refcnt);
/* check if the notifier still has clients */ /* check if the notifier still has clients */
if (atomic_dec_return(&nfsd_notifier_refcount) == 0) { if (atomic_dec_return(&nfsd_notifier_refcount) == 0) {
unregister_inetaddr_notifier(&nfsd_inetaddr_notifier); unregister_inetaddr_notifier(&nfsd_inetaddr_notifier);
...@@ -398,6 +404,7 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net) ...@@ -398,6 +404,7 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
unregister_inet6addr_notifier(&nfsd_inet6addr_notifier); unregister_inet6addr_notifier(&nfsd_inet6addr_notifier);
#endif #endif
} }
wait_event(nn->ntf_wq, atomic_read(&nn->ntf_refcnt) == 0);
/* /*
* write_ports can create the server without actually starting * write_ports can create the server without actually starting
...@@ -517,6 +524,7 @@ int nfsd_create_serv(struct net *net) ...@@ -517,6 +524,7 @@ int nfsd_create_serv(struct net *net)
register_inet6addr_notifier(&nfsd_inet6addr_notifier); register_inet6addr_notifier(&nfsd_inet6addr_notifier);
#endif #endif
} }
atomic_inc(&nn->ntf_refcnt);
ktime_get_real_ts64(&nn->nfssvc_boot); /* record boot time */ ktime_get_real_ts64(&nn->nfssvc_boot); /* record boot time */
return 0; return 0;
} }
......
...@@ -213,7 +213,7 @@ extern void __init cache_initialize(void); ...@@ -213,7 +213,7 @@ extern void __init cache_initialize(void);
extern int cache_register_net(struct cache_detail *cd, struct net *net); extern int cache_register_net(struct cache_detail *cd, struct net *net);
extern void cache_unregister_net(struct cache_detail *cd, struct net *net); extern void cache_unregister_net(struct cache_detail *cd, struct net *net);
extern struct cache_detail *cache_create_net(struct cache_detail *tmpl, struct net *net); extern struct cache_detail *cache_create_net(const struct cache_detail *tmpl, struct net *net);
extern void cache_destroy_net(struct cache_detail *cd, struct net *net); extern void cache_destroy_net(struct cache_detail *cd, struct net *net);
extern void sunrpc_init_cache_detail(struct cache_detail *cd); extern void sunrpc_init_cache_detail(struct cache_detail *cd);
......
...@@ -264,7 +264,7 @@ static int rsi_parse(struct cache_detail *cd, ...@@ -264,7 +264,7 @@ static int rsi_parse(struct cache_detail *cd,
return status; return status;
} }
static struct cache_detail rsi_cache_template = { static const struct cache_detail rsi_cache_template = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.hash_size = RSI_HASHMAX, .hash_size = RSI_HASHMAX,
.name = "auth.rpcsec.init", .name = "auth.rpcsec.init",
...@@ -524,7 +524,7 @@ static int rsc_parse(struct cache_detail *cd, ...@@ -524,7 +524,7 @@ static int rsc_parse(struct cache_detail *cd,
return status; return status;
} }
static struct cache_detail rsc_cache_template = { static const struct cache_detail rsc_cache_template = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.hash_size = RSC_HASHMAX, .hash_size = RSC_HASHMAX,
.name = "auth.rpcsec.context", .name = "auth.rpcsec.context",
......
...@@ -1674,7 +1674,7 @@ void cache_unregister_net(struct cache_detail *cd, struct net *net) ...@@ -1674,7 +1674,7 @@ void cache_unregister_net(struct cache_detail *cd, struct net *net)
} }
EXPORT_SYMBOL_GPL(cache_unregister_net); EXPORT_SYMBOL_GPL(cache_unregister_net);
struct cache_detail *cache_create_net(struct cache_detail *tmpl, struct net *net) struct cache_detail *cache_create_net(const struct cache_detail *tmpl, struct net *net)
{ {
struct cache_detail *cd; struct cache_detail *cd;
int i; int i;
......
...@@ -569,7 +569,7 @@ static int unix_gid_show(struct seq_file *m, ...@@ -569,7 +569,7 @@ static int unix_gid_show(struct seq_file *m,
return 0; return 0;
} }
static struct cache_detail unix_gid_cache_template = { static const struct cache_detail unix_gid_cache_template = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.hash_size = GID_HASHMAX, .hash_size = GID_HASHMAX,
.name = "auth.unix.gid", .name = "auth.unix.gid",
...@@ -862,7 +862,7 @@ struct auth_ops svcauth_unix = { ...@@ -862,7 +862,7 @@ struct auth_ops svcauth_unix = {
.set_client = svcauth_unix_set_client, .set_client = svcauth_unix_set_client,
}; };
static struct cache_detail ip_map_cache_template = { static const struct cache_detail ip_map_cache_template = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.hash_size = IP_HASHMAX, .hash_size = IP_HASHMAX,
.name = "auth.unix.ip", .name = "auth.unix.ip",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment