]> err.no Git - linux-2.6/blobdiff - net/sunrpc/clnt.c
SUNRPC: Clean up rpc_pipefs.
[linux-2.6] / net / sunrpc / clnt.c
index fe838e996ee330f6e52584be261345ed8ad12d9a..76eef19cf995f1cf61efc83af0916629a9a5ffde 100644 (file)
        dprintk("RPC: %5u %s (status %d)\n", t->tk_pid,         \
                        __FUNCTION__, t->tk_status)
 
+/*
+ * All RPC clients are linked into this list
+ */
+static LIST_HEAD(all_clients);
+static DEFINE_SPINLOCK(rpc_client_lock);
+
 static DECLARE_WAIT_QUEUE_HEAD(destroy_wait);
 
 
@@ -66,6 +72,19 @@ static void  call_connect_status(struct rpc_task *task);
 static __be32 *        call_header(struct rpc_task *task);
 static __be32 *        call_verify(struct rpc_task *task);
 
+static void rpc_register_client(struct rpc_clnt *clnt)
+{
+       spin_lock(&rpc_client_lock);
+       list_add(&clnt->cl_clients, &all_clients);
+       spin_unlock(&rpc_client_lock);
+}
+
+static void rpc_unregister_client(struct rpc_clnt *clnt)
+{
+       spin_lock(&rpc_client_lock);
+       list_del(&clnt->cl_clients);
+       spin_unlock(&rpc_client_lock);
+}
 
 static int
 rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
@@ -455,73 +474,96 @@ void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset)
        rpc_restore_sigmask(oldset);
 }
 
-/*
- * New rpc_call implementation
+static
+struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt,
+               struct rpc_message *msg,
+               int flags,
+               const struct rpc_call_ops *ops,
+               void *data)
+{
+       struct rpc_task *task, *ret;
+       sigset_t oldset;
+
+       task = rpc_new_task(clnt, flags, ops, data);
+       if (task == NULL) {
+               rpc_release_calldata(ops, data);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       /* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */
+       rpc_task_sigmask(task, &oldset);
+       if (msg != NULL) {
+               rpc_call_setup(task, msg, 0);
+               if (task->tk_status != 0) {
+                       ret = ERR_PTR(task->tk_status);
+                       rpc_put_task(task);
+                       goto out;
+               }
+       }
+       atomic_inc(&task->tk_count);
+       rpc_execute(task);
+       ret = task;
+out:
+       rpc_restore_sigmask(&oldset);
+       return ret;
+}
+
+/**
+ * rpc_call_sync - Perform a synchronous RPC call
+ * @clnt: pointer to RPC client
+ * @msg: RPC call parameters
+ * @flags: RPC call flags
  */
 int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 {
        struct rpc_task *task;
-       sigset_t        oldset;
-       int             status;
+       int status;
 
        BUG_ON(flags & RPC_TASK_ASYNC);
 
-       task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL);
-       if (task == NULL)
-               return -ENOMEM;
-
-       /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */
-       rpc_task_sigmask(task, &oldset);
-
-       /* Set up the call info struct and execute the task */
-       rpc_call_setup(task, msg, 0);
-       if (task->tk_status == 0) {
-               atomic_inc(&task->tk_count);
-               rpc_execute(task);
-       }
+       task = rpc_do_run_task(clnt, msg, flags, &rpc_default_ops, NULL);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
        status = task->tk_status;
        rpc_put_task(task);
-       rpc_restore_sigmask(&oldset);
        return status;
 }
 
-/*
- * New rpc_call implementation
+/**
+ * rpc_call_async - Perform an asynchronous RPC call
+ * @clnt: pointer to RPC client
+ * @msg: RPC call parameters
+ * @flags: RPC call flags
+ * @ops: RPC call ops
+ * @data: user call data
  */
 int
 rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
               const struct rpc_call_ops *tk_ops, void *data)
 {
        struct rpc_task *task;
-       sigset_t        oldset;
-       int             status;
-
-       flags |= RPC_TASK_ASYNC;
-
-       /* Create/initialize a new RPC task */
-       status = -ENOMEM;
-       if (!(task = rpc_new_task(clnt, flags, tk_ops, data)))
-               goto out_release;
-
-       /* Mask signals on GSS_AUTH upcalls */
-       rpc_task_sigmask(task, &oldset);
-
-       rpc_call_setup(task, msg, 0);
 
-       /* Set up the call info struct and execute the task */
-       status = task->tk_status;
-       if (status == 0)
-               rpc_execute(task);
-       else
-               rpc_put_task(task);
-
-       rpc_restore_sigmask(&oldset);
-       return status;
-out_release:
-       rpc_release_calldata(tk_ops, data);
-       return status;
+       task = rpc_do_run_task(clnt, msg, flags|RPC_TASK_ASYNC, tk_ops, data);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+       rpc_put_task(task);
+       return 0;
 }
 
+/**
+ * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
+ * @clnt: pointer to RPC client
+ * @flags: RPC flags
+ * @ops: RPC call ops
+ * @data: user call data
+ */
+struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
+                                       const struct rpc_call_ops *tk_ops,
+                                       void *data)
+{
+       return rpc_do_run_task(clnt, NULL, flags, tk_ops, data);
+}
+EXPORT_SYMBOL(rpc_run_task);
 
 void
 rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
@@ -1410,3 +1452,41 @@ int rpc_ping(struct rpc_clnt *clnt, int flags)
        put_rpccred(msg.rpc_cred);
        return err;
 }
+
+#ifdef RPC_DEBUG
+void rpc_show_tasks(void)
+{
+       struct rpc_clnt *clnt;
+       struct rpc_task *t;
+
+       spin_lock(&rpc_client_lock);
+       if (list_empty(&all_clients))
+               goto out;
+       printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
+               "-rpcwait -action- ---ops--\n");
+       list_for_each_entry(clnt, &all_clients, cl_clients) {
+               if (list_empty(&clnt->cl_tasks))
+                       continue;
+               spin_lock(&clnt->cl_lock);
+               list_for_each_entry(t, &clnt->cl_tasks, tk_task) {
+                       const char *rpc_waitq = "none";
+
+                       if (RPC_IS_QUEUED(t))
+                               rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
+
+                       printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
+                               t->tk_pid,
+                               (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
+                               t->tk_flags, t->tk_status,
+                               t->tk_client,
+                               (t->tk_client ? t->tk_client->cl_prog : 0),
+                               t->tk_rqstp, t->tk_timeout,
+                               rpc_waitq,
+                               t->tk_action, t->tk_ops);
+               }
+               spin_unlock(&clnt->cl_lock);
+       }
+out:
+       spin_unlock(&rpc_client_lock);
+}
+#endif