lockd: close potential race with rapid lockd_up/lockd_down cycle
If lockd_down is called very rapidly after lockd_up returns, then there is a slim chance that lockd() will never be called. kthread() will return before calling the function, so we'll end up never actually calling the cleanup functions for the thread. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
This commit is contained in:
committed by
J. Bruce Fields
parent
a75c5d01e4
commit
abd1ec4efd
@@ -50,7 +50,7 @@ EXPORT_SYMBOL(nlmsvc_ops);
|
|||||||
static DEFINE_MUTEX(nlmsvc_mutex);
|
static DEFINE_MUTEX(nlmsvc_mutex);
|
||||||
static unsigned int nlmsvc_users;
|
static unsigned int nlmsvc_users;
|
||||||
static struct task_struct *nlmsvc_task;
|
static struct task_struct *nlmsvc_task;
|
||||||
static struct svc_serv *nlmsvc_serv;
|
static struct svc_rqst *nlmsvc_rqst;
|
||||||
int nlmsvc_grace_period;
|
int nlmsvc_grace_period;
|
||||||
unsigned long nlmsvc_timeout;
|
unsigned long nlmsvc_timeout;
|
||||||
|
|
||||||
@@ -194,20 +194,11 @@ lockd(void *vrqstp)
|
|||||||
|
|
||||||
svc_process(rqstp);
|
svc_process(rqstp);
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_signals(current);
|
flush_signals(current);
|
||||||
if (nlmsvc_ops)
|
if (nlmsvc_ops)
|
||||||
nlmsvc_invalidate_all();
|
nlmsvc_invalidate_all();
|
||||||
nlm_shutdown_hosts();
|
nlm_shutdown_hosts();
|
||||||
|
|
||||||
unlock_kernel();
|
unlock_kernel();
|
||||||
|
|
||||||
nlmsvc_task = NULL;
|
|
||||||
nlmsvc_serv = NULL;
|
|
||||||
|
|
||||||
/* Exit the RPC thread */
|
|
||||||
svc_exit_thread(rqstp);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,16 +245,15 @@ int
|
|||||||
lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
|
lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
|
||||||
{
|
{
|
||||||
struct svc_serv *serv;
|
struct svc_serv *serv;
|
||||||
struct svc_rqst *rqstp;
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
mutex_lock(&nlmsvc_mutex);
|
mutex_lock(&nlmsvc_mutex);
|
||||||
/*
|
/*
|
||||||
* Check whether we're already up and running.
|
* Check whether we're already up and running.
|
||||||
*/
|
*/
|
||||||
if (nlmsvc_serv) {
|
if (nlmsvc_rqst) {
|
||||||
if (proto)
|
if (proto)
|
||||||
error = make_socks(nlmsvc_serv, proto);
|
error = make_socks(nlmsvc_rqst->rq_server, proto);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,9 +278,10 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
|
|||||||
/*
|
/*
|
||||||
* Create the kernel thread and wait for it to start.
|
* Create the kernel thread and wait for it to start.
|
||||||
*/
|
*/
|
||||||
rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
|
nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0]);
|
||||||
if (IS_ERR(rqstp)) {
|
if (IS_ERR(nlmsvc_rqst)) {
|
||||||
error = PTR_ERR(rqstp);
|
error = PTR_ERR(nlmsvc_rqst);
|
||||||
|
nlmsvc_rqst = NULL;
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"lockd_up: svc_rqst allocation failed, error=%d\n",
|
"lockd_up: svc_rqst allocation failed, error=%d\n",
|
||||||
error);
|
error);
|
||||||
@@ -298,16 +289,15 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
|
|||||||
}
|
}
|
||||||
|
|
||||||
svc_sock_update_bufs(serv);
|
svc_sock_update_bufs(serv);
|
||||||
nlmsvc_serv = rqstp->rq_server;
|
|
||||||
|
|
||||||
nlmsvc_task = kthread_run(lockd, rqstp, serv->sv_name);
|
nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name);
|
||||||
if (IS_ERR(nlmsvc_task)) {
|
if (IS_ERR(nlmsvc_task)) {
|
||||||
error = PTR_ERR(nlmsvc_task);
|
error = PTR_ERR(nlmsvc_task);
|
||||||
|
svc_exit_thread(nlmsvc_rqst);
|
||||||
nlmsvc_task = NULL;
|
nlmsvc_task = NULL;
|
||||||
nlmsvc_serv = NULL;
|
nlmsvc_rqst = NULL;
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"lockd_up: kthread_run failed, error=%d\n", error);
|
"lockd_up: kthread_run failed, error=%d\n", error);
|
||||||
svc_exit_thread(rqstp);
|
|
||||||
goto destroy_and_out;
|
goto destroy_and_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,6 +336,9 @@ lockd_down(void)
|
|||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
kthread_stop(nlmsvc_task);
|
kthread_stop(nlmsvc_task);
|
||||||
|
svc_exit_thread(nlmsvc_rqst);
|
||||||
|
nlmsvc_task = NULL;
|
||||||
|
nlmsvc_rqst = NULL;
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&nlmsvc_mutex);
|
mutex_unlock(&nlmsvc_mutex);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user