netfilter: ip6table_raw: fix table priority
[safe/jmp/linux-2.6] / net / sunrpc / sched.c
index 385f427..aae6907 100644 (file)
 #include <linux/slab.h>
 #include <linux/mempool.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
 
 #include <linux/sunrpc/clnt.h>
 
+#include "sunrpc.h"
+
 #ifdef RPC_DEBUG
 #define RPCDBG_FACILITY                RPCDBG_SCHED
 #define RPC_TASK_MAGIC_ID      0xf00baa
@@ -209,6 +210,7 @@ void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qnam
 {
        __rpc_init_priority_wait_queue(queue, qname, RPC_NR_PRIORITY);
 }
+EXPORT_SYMBOL_GPL(rpc_init_priority_wait_queue);
 
 void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname)
 {
@@ -293,11 +295,6 @@ static void rpc_make_runnable(struct rpc_task *task)
        rpc_clear_queued(task);
        if (rpc_test_and_set_running(task))
                return;
-       /* We might have raced */
-       if (RPC_IS_QUEUED(task)) {
-               rpc_clear_running(task);
-               return;
-       }
        if (RPC_IS_ASYNC(task)) {
                int status;
 
@@ -389,6 +386,20 @@ static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct r
 }
 
 /*
+ * Tests whether rpc queue is empty
+ */
+int rpc_queue_empty(struct rpc_wait_queue *queue)
+{
+       int res;
+
+       spin_lock_bh(&queue->lock);
+       res = queue->qlen;
+       spin_unlock_bh(&queue->lock);
+       return (res == 0);
+}
+EXPORT_SYMBOL_GPL(rpc_queue_empty);
+
+/*
  * Wake up a task on a specific queue
  */
 void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task)
@@ -574,7 +585,7 @@ EXPORT_SYMBOL_GPL(rpc_delay);
 /*
  * Helper to call task->tk_ops->rpc_call_prepare
  */
-static void rpc_prepare_task(struct rpc_task *task)
+void rpc_prepare_task(struct rpc_task *task)
 {
        task->tk_ops->rpc_call_prepare(task, task->tk_calldata);
 }
@@ -607,7 +618,9 @@ void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata)
  */
 static void __rpc_execute(struct rpc_task *task)
 {
-       int             status = 0;
+       struct rpc_wait_queue *queue;
+       int task_is_async = RPC_IS_ASYNC(task);
+       int status = 0;
 
        dprintk("RPC: %5u __rpc_execute flags=0x%x\n",
                        task->tk_pid, task->tk_flags);
@@ -647,15 +660,25 @@ static void __rpc_execute(struct rpc_task *task)
                 */
                if (!RPC_IS_QUEUED(task))
                        continue;
-               rpc_clear_running(task);
-               if (RPC_IS_ASYNC(task)) {
-                       /* Careful! we may have raced... */
-                       if (RPC_IS_QUEUED(task))
-                               return;
-                       if (rpc_test_and_set_running(task))
-                               return;
+               /*
+                * The queue->lock protects against races with
+                * rpc_make_runnable().
+                *
+                * Note that once we clear RPC_TASK_RUNNING on an asynchronous
+                * rpc_task, rpc_make_runnable() can assign it to a
+                * different workqueue. We therefore cannot assume that the
+                * rpc_task pointer may still be dereferenced.
+                */
+               queue = task->tk_waitqueue;
+               spin_lock_bh(&queue->lock);
+               if (!RPC_IS_QUEUED(task)) {
+                       spin_unlock_bh(&queue->lock);
                        continue;
                }
+               rpc_clear_running(task);
+               spin_unlock_bh(&queue->lock);
+               if (task_is_async)
+                       return;
 
                /* sync task: sleep here */
                dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid);
@@ -705,11 +728,6 @@ static void rpc_async_schedule(struct work_struct *work)
        __rpc_execute(container_of(work, struct rpc_task, u.tk_work));
 }
 
-struct rpc_buffer {
-       size_t  len;
-       char    data[];
-};
-
 /**
  * rpc_malloc - allocate an RPC buffer
  * @task: RPC task that will use this buffer