]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/nfs/callback.c
NFS: convert nfs4 callback thread to kthread API
[linux-2.6-omap-h63xx.git] / fs / nfs / callback.c
index 66648dd92d9731c2aa016cd82219d67268383958..2e5de77ff0308cff85ec0cdad7139c2258d9f0fe 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/nfs_fs.h>
 #include <linux/mutex.h>
 #include <linux/freezer.h>
+#include <linux/kthread.h>
 
 #include <net/inet_sock.h>
 
@@ -27,9 +28,7 @@
 struct nfs_callback_data {
        unsigned int users;
        struct svc_serv *serv;
-       pid_t pid;
-       struct completion started;
-       struct completion stopped;
+       struct task_struct *task;
 };
 
 static struct nfs_callback_data nfs_callback_info;
@@ -57,27 +56,20 @@ module_param_call(callback_tcpport, param_set_port, param_get_int,
 /*
  * This is the callback kernel thread.
  */
-static void nfs_callback_svc(struct svc_rqst *rqstp)
+static int
+nfs_callback_svc(void *vrqstp)
 {
        int err;
+       struct svc_rqst *rqstp = vrqstp;
 
-       __module_get(THIS_MODULE);
-       lock_kernel();
-
-       nfs_callback_info.pid = current->pid;
-       daemonize("nfsv4-svc");
-       /* Process request with signals blocked, but allow SIGKILL.  */
-       allow_signal(SIGKILL);
        set_freezable();
 
-       complete(&nfs_callback_info.started);
-
-       for(;;) {
-               if (signalled()) {
-                       if (nfs_callback_info.users == 0)
-                               break;
-                       flush_signals(current);
-               }
+       /*
+        * FIXME: do we really need to run this under the BKL? If so, please
+        * add a comment about what it's intended to protect.
+        */
+       lock_kernel();
+       while (!kthread_should_stop()) {
                /*
                 * Listen for a request on the socket
                 */
@@ -92,13 +84,10 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
                }
                svc_process(rqstp);
        }
-
-       flush_signals(current);
-       svc_exit_thread(rqstp);
-       nfs_callback_info.pid = 0;
-       complete(&nfs_callback_info.stopped);
        unlock_kernel();
-       module_put_and_exit(0);
+       nfs_callback_info.task = NULL;
+       svc_exit_thread(rqstp);
+       return 0;
 }
 
 /*
@@ -107,14 +96,13 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
 int nfs_callback_up(void)
 {
        struct svc_serv *serv = NULL;
+       struct svc_rqst *rqstp;
        int ret = 0;
 
        lock_kernel();
        mutex_lock(&nfs_callback_mutex);
-       if (nfs_callback_info.users++ || nfs_callback_info.pid != 0)
+       if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
                goto out;
-       init_completion(&nfs_callback_info.started);
-       init_completion(&nfs_callback_info.stopped);
        serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
        ret = -ENOMEM;
        if (!serv)
@@ -127,15 +115,28 @@ int nfs_callback_up(void)
        nfs_callback_tcpport = ret;
        dprintk("Callback port = 0x%x\n", nfs_callback_tcpport);
 
-       ret = svc_create_thread(nfs_callback_svc, serv);
-       if (ret < 0)
+       rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
+       if (IS_ERR(rqstp)) {
+               ret = PTR_ERR(rqstp);
                goto out_err;
+       }
+
+       svc_sock_update_bufs(serv);
        nfs_callback_info.serv = serv;
-       wait_for_completion(&nfs_callback_info.started);
+
+       nfs_callback_info.task = kthread_run(nfs_callback_svc, rqstp,
+                                            "nfsv4-svc");
+       if (IS_ERR(nfs_callback_info.task)) {
+               ret = PTR_ERR(nfs_callback_info.task);
+               nfs_callback_info.serv = NULL;
+               nfs_callback_info.task = NULL;
+               svc_exit_thread(rqstp);
+               goto out_err;
+       }
 out:
        /*
         * svc_create creates the svc_serv with sv_nrthreads == 1, and then
-        * svc_create_thread increments that. So we need to call svc_destroy
+        * svc_prepare_thread increments that. So we need to call svc_destroy
         * on both success and failure so that the refcount is 1 when the
         * thread exits.
         */
@@ -159,12 +160,8 @@ void nfs_callback_down(void)
        lock_kernel();
        mutex_lock(&nfs_callback_mutex);
        nfs_callback_info.users--;
-       do {
-               if (nfs_callback_info.users != 0 || nfs_callback_info.pid == 0)
-                       break;
-               if (kill_proc(nfs_callback_info.pid, SIGKILL, 1) < 0)
-                       break;
-       } while (wait_for_completion_timeout(&nfs_callback_info.stopped, 5*HZ) == 0);
+       if (nfs_callback_info.users == 0 && nfs_callback_info.task != NULL)
+               kthread_stop(nfs_callback_info.task);
        mutex_unlock(&nfs_callback_mutex);
        unlock_kernel();
 }