rfkill: fix rfkill_fop_read wait_event usage
[pandora-kernel.git] / net / sunrpc / svc.c
index 6a69a11..c80c162 100644 (file)
@@ -167,6 +167,7 @@ svc_pool_map_alloc_arrays(struct svc_pool_map *m, unsigned int maxpools)
 
 fail_free:
        kfree(m->to_pool);
+       m->to_pool = NULL;
 fail:
        return -ENOMEM;
 }
@@ -287,7 +288,9 @@ svc_pool_map_put(void)
        if (!--m->count) {
                m->mode = SVC_POOL_DEFAULT;
                kfree(m->to_pool);
+               m->to_pool = NULL;
                kfree(m->pool_to);
+               m->pool_to = NULL;
                m->npools = 0;
        }
 
@@ -295,6 +298,18 @@ svc_pool_map_put(void)
 }
 
 
+static int svc_pool_map_get_node(unsigned int pidx)
+{
+       const struct svc_pool_map *m = &svc_pool_map;
+
+       if (m->count) {
+               if (m->mode == SVC_POOL_PERCPU)
+                       return cpu_to_node(m->pool_to[pidx]);
+               if (m->mode == SVC_POOL_PERNODE)
+                       return m->pool_to[pidx];
+       }
+       return NUMA_NO_NODE;
+}
 /*
  * Set the given thread's cpus_allowed mask so that it
  * will only run on cpus in the given pool.
@@ -354,6 +369,42 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu)
        return &serv->sv_pools[pidx % serv->sv_nrpools];
 }
 
+static int svc_rpcb_setup(struct svc_serv *serv)
+{
+       int err;
+
+       err = rpcb_create_local();
+       if (err)
+               return err;
+
+       /* Remove any stale portmap registrations */
+       svc_unregister(serv);
+       return 0;
+}
+
+void svc_rpcb_cleanup(struct svc_serv *serv)
+{
+       svc_unregister(serv);
+       rpcb_put_local();
+}
+EXPORT_SYMBOL_GPL(svc_rpcb_cleanup);
+
+static int svc_uses_rpcbind(struct svc_serv *serv)
+{
+       struct svc_program      *progp;
+       unsigned int            i;
+
+       for (progp = serv->sv_program; progp; progp = progp->pg_next) {
+               for (i = 0; i < progp->pg_nvers; i++) {
+                       if (progp->pg_vers[i] == NULL)
+                               continue;
+                       if (progp->pg_vers[i]->vs_hidden == 0)
+                               return 1;
+               }
+       }
+
+       return 0;
+}
 
 /*
  * Create an RPC service
@@ -419,8 +470,15 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools,
                spin_lock_init(&pool->sp_lock);
        }
 
-       /* Remove any stale portmap registrations */
-       svc_unregister(serv);
+       if (svc_uses_rpcbind(serv)) {
+               if (svc_rpcb_setup(serv) < 0) {
+                       kfree(serv->sv_pools);
+                       kfree(serv);
+                       return NULL;
+               }
+               if (!serv->sv_shutdown)
+                       serv->sv_shutdown = svc_rpcb_cleanup;
+       }
 
        return serv;
 }
@@ -472,23 +530,25 @@ svc_destroy(struct svc_serv *serv)
                printk("svc_destroy: no threads for serv=%p!\n", serv);
 
        del_timer_sync(&serv->sv_temptimer);
-
-       svc_close_all(&serv->sv_tempsocks);
+       /*
+        * The set of xprts (contained in the sv_tempsocks and
+        * sv_permsocks lists) is now constant, since it is modified
+        * only by accepting new sockets (done by service threads in
+        * svc_recv) or aging old ones (done by sv_temptimer), or
+        * configuration changes (excluded by whatever locking the
+        * caller is using--nfsd_mutex in the case of nfsd).  So it's
+        * safe to traverse those lists and shut everything down:
+        */
+       svc_close_all(serv);
 
        if (serv->sv_shutdown)
                serv->sv_shutdown(serv);
 
-       svc_close_all(&serv->sv_permsocks);
-
-       BUG_ON(!list_empty(&serv->sv_permsocks));
-       BUG_ON(!list_empty(&serv->sv_tempsocks));
-
        cache_clean_deferred(serv);
 
        if (svc_serv_is_pooled(serv))
                svc_pool_map_put();
 
-       svc_unregister(serv);
        kfree(serv->sv_pools);
        kfree(serv);
 }
@@ -499,7 +559,7 @@ EXPORT_SYMBOL_GPL(svc_destroy);
  * We allocate pages and place them in rq_argpages.
  */
 static int
-svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
+svc_init_buffer(struct svc_rqst *rqstp, unsigned int size, int node)
 {
        unsigned int pages, arghi;
 
@@ -513,7 +573,7 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
        arghi = 0;
        BUG_ON(pages > RPCSVC_MAXPAGES);
        while (pages) {
-               struct page *p = alloc_page(GFP_KERNEL);
+               struct page *p = alloc_pages_node(node, GFP_KERNEL, 0);
                if (!p)
                        break;
                rqstp->rq_pages[arghi++] = p;
@@ -536,11 +596,11 @@ svc_release_buffer(struct svc_rqst *rqstp)
 }
 
 struct svc_rqst *
-svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool)
+svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node)
 {
        struct svc_rqst *rqstp;
 
-       rqstp = kzalloc(sizeof(*rqstp), GFP_KERNEL);
+       rqstp = kzalloc_node(sizeof(*rqstp), GFP_KERNEL, node);
        if (!rqstp)
                goto out_enomem;
 
@@ -554,15 +614,15 @@ svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool)
        rqstp->rq_server = serv;
        rqstp->rq_pool = pool;
 
-       rqstp->rq_argp = kmalloc(serv->sv_xdrsize, GFP_KERNEL);
+       rqstp->rq_argp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node);
        if (!rqstp->rq_argp)
                goto out_thread;
 
-       rqstp->rq_resp = kmalloc(serv->sv_xdrsize, GFP_KERNEL);
+       rqstp->rq_resp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node);
        if (!rqstp->rq_resp)
                goto out_thread;
 
-       if (!svc_init_buffer(rqstp, serv->sv_max_mesg))
+       if (!svc_init_buffer(rqstp, serv->sv_max_mesg, node))
                goto out_thread;
 
        return rqstp;
@@ -647,6 +707,7 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
        struct svc_pool *chosen_pool;
        int error = 0;
        unsigned int state = serv->sv_nrthreads-1;
+       int node;
 
        if (pool == NULL) {
                /* The -1 assumes caller has done a svc_get() */
@@ -662,14 +723,16 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
                nrservs--;
                chosen_pool = choose_pool(serv, pool, &state);
 
-               rqstp = svc_prepare_thread(serv, chosen_pool);
+               node = svc_pool_map_get_node(chosen_pool->sp_id);
+               rqstp = svc_prepare_thread(serv, chosen_pool, node);
                if (IS_ERR(rqstp)) {
                        error = PTR_ERR(rqstp);
                        break;
                }
 
                __module_get(serv->sv_module);
-               task = kthread_create(serv->sv_function, rqstp, serv->sv_name);
+               task = kthread_create_on_node(serv->sv_function, rqstp,
+                                             node, serv->sv_name);
                if (IS_ERR(task)) {
                        error = PTR_ERR(task);
                        module_put(serv->sv_module);
@@ -956,9 +1019,8 @@ static void svc_unregister(const struct svc_serv *serv)
 /*
  * Printk the given error with the address of the client that caused it.
  */
-static int
-__attribute__ ((format (printf, 2, 3)))
-svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
+static __printf(2, 3)
+int svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
 {
        va_list args;
        int     r;
@@ -1296,7 +1358,8 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
                                                sizeof(req->rq_snd_buf));
                return bc_send(req);
        } else {
-               /* Nothing to do to drop request */
+               /* drop request */
+               xprt_free_bc_request(req);
                return 0;
        }
 }