The pid of the locking daemon can be substituted with a task struct
without a problem. Namely, the value if filled in the context of the lockd
thread and used in lockd_up/lockd_down.

It is possible to save task struct instead and use it to kill the process.
The safety of this operation is guaranteed by the RCU, i.e. task can't
disappear without passing a quiscent state.

Signed-off-by: Denis V. Lunev <[EMAIL PROTECTED]>
---
 fs/lockd/svc.c |   38 +++++++++++++++++++++++++-------------
 1 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 82e2192..4979e70 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -48,7 +48,7 @@ EXPORT_SYMBOL(nlmsvc_ops);
 
 static DEFINE_MUTEX(nlmsvc_mutex);
 static unsigned int            nlmsvc_users;
-static pid_t                   nlmsvc_pid;
+static struct task_struct      *nlmsvc_task;
 static struct svc_serv         *nlmsvc_serv;
 int                            nlmsvc_grace_period;
 unsigned long                  nlmsvc_timeout;
@@ -128,7 +128,8 @@ lockd(struct svc_rqst *rqstp)
        /*
         * Let our maker know we're running.
         */
-       nlmsvc_pid = current->pid;
+       rcu_assign_pointer(nlmsvc_task, current);
+
        nlmsvc_serv = rqstp->rq_server;
        complete(&lockd_start_done);
 
@@ -151,7 +152,7 @@ lockd(struct svc_rqst *rqstp)
         * NFS mount or NFS daemon has gone away, and we've been sent a
         * signal, or else another process has taken over our job.
         */
-       while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) {
+       while ((nlmsvc_users || !signalled()) && nlmsvc_task == current) {
                long timeout = MAX_SCHEDULE_TIMEOUT;
                char buf[RPC_MAX_ADDRBUFLEN];
 
@@ -200,12 +201,12 @@ lockd(struct svc_rqst *rqstp)
         * Check whether there's a new lockd process before
         * shutting down the hosts and clearing the slot.
         */
-       if (!nlmsvc_pid || current->pid == nlmsvc_pid) {
+       if (nlmsvc_task == NULL || current == nlmsvc_task) {
                if (nlmsvc_ops)
                        nlmsvc_invalidate_all();
                nlm_shutdown_hosts();
-               nlmsvc_pid = 0;
                nlmsvc_serv = NULL;
+               rcu_assign_pointer(nlmsvc_task, NULL);
        } else
                printk(KERN_DEBUG
                        "lockd: new process, skipping host shutdown\n");
@@ -273,7 +274,7 @@ lockd_up(int proto) /* Maybe add a 'family' option when 
IPv6 is supported ?? */
        /*
         * Check whether we're already up and running.
         */
-       if (nlmsvc_pid) {
+       if (nlmsvc_task != NULL) {
                if (proto)
                        error = make_socks(nlmsvc_serv, proto);
                goto out;
@@ -329,38 +330,49 @@ void
 lockd_down(void)
 {
        static int warned;
+       struct task_struct *tsk;
 
        mutex_lock(&nlmsvc_mutex);
+       rcu_read_lock();
+       tsk = rcu_dereference(nlmsvc_task);
        if (nlmsvc_users) {
                if (--nlmsvc_users)
-                       goto out;
+                       goto out_rcu_unlock;
        } else
-               printk(KERN_WARNING "lockd_down: no users! pid=%d\n", 
nlmsvc_pid);
+               printk(KERN_WARNING "lockd_down: no users! pid=%d\n",
+                      task_pid_nr(tsk));
 
-       if (!nlmsvc_pid) {
+       if (tsk == NULL) {
                if (warned++ == 0)
                        printk(KERN_WARNING "lockd_down: no lockd running.\n"); 
-               goto out;
+               goto out_rcu_unlock;
        }
        warned = 0;
 
-       kill_proc(nlmsvc_pid, SIGKILL, 1);
+       send_sig(SIGKILL, tsk, 1);
+       rcu_read_unlock();
+
        /*
         * Wait for the lockd process to exit, but since we're holding
         * the lockd semaphore, we can't wait around forever ...
         */
        clear_thread_flag(TIF_SIGPENDING);
        interruptible_sleep_on_timeout(&lockd_exit, HZ);
-       if (nlmsvc_pid) {
+       if (nlmsvc_task != NULL) {
                printk(KERN_WARNING 
                        "lockd_down: lockd failed to exit, clearing pid\n");
-               nlmsvc_pid = 0;
+               rcu_assign_pointer(nlmsvc_task, NULL);
        }
        spin_lock_irq(&current->sighand->siglock);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 out:
        mutex_unlock(&nlmsvc_mutex);
+       return;
+
+out_rcu_unlock:
+       rcu_read_unlock();
+       goto out;
 }
 EXPORT_SYMBOL(lockd_down);
 
-- 
1.5.3.rc5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to