|
@@ -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,
|
|
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,
|
|
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,
|
|
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)
|
|
{
|
|
{
|
|
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)
|
|
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)
|
|
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;
|
|
}
|
|
}
|