lkml.org 
[lkml]   [2000]   [Aug]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
Subject[PATCH 2.4.0-test7-pre7]: Fix 2 rpc_wait_queue hangups (slight rewrite)
From

The following patch is a slight rewrite of the 2 patches that I sent
in last week. It fixes the following conditions:

- Fix deadlock between rpc_unlock_task() and rpc_wake_up() /
rpc_wake_up_status(). The latter 2 functions would loop forever
if a task was locked since __rpc_wake_up_task() would not remove
it from the wait queue. In addition since the spinlock was being
held, rpc_unlock_task() could never succeed.

This patch changes the above so that running __rpc_wake_up_task()
on a locked task will remove it from the wait queue, but will not
schedule it for running until tk_lock goes to zero.

- Fix loop in rpc_find_parent(). The latter was assuming the wrong
topology for rpc_wait_queue: it assumed a linear rather than a
circular list.

In addition, a bit of documentation has been thrown in so as to make
the above clear.

Cheers,
Trond

diff -u --recursive --new-file linux-2.4.0-test7-pre7/net/sunrpc/sched.c linux-2.4.0-test7-fix_rpc/net/sunrpc/sched.c
--- linux-2.4.0-test7-pre7/net/sunrpc/sched.c Sat Aug 5 03:18:49 2000
+++ linux-2.4.0-test7-fix_rpc/net/sunrpc/sched.c Wed Aug 23 12:55:57 2000
@@ -369,8 +369,15 @@
spin_unlock_bh(&rpc_queue_lock);
}

-/*
- * Wake up a single task -- must be invoked with spin lock held.
+/**
+ * __rpc_wake_up_task - wake up a single rpc_task
+ * @task: task to be woken up
+ *
+ * If the task is locked, it is merely removed from the queue, and
+ * 'task->tk_wakeup' is set. rpc_unlock_task() will then ensure
+ * that it is woken up as soon as the lock count goes to zero.
+ *
+ * Caller must hold rpc_queue_lock
*/
static void
__rpc_wake_up_task(struct rpc_task *task)
@@ -395,6 +402,8 @@
return;

__rpc_disable_timer(task);
+ if (task->tk_rpcwait != &schedq)
+ __rpc_remove_wait_queue(task);

/* If the task has been locked, then set tk_wakeup so that
* rpc_unlock_task() wakes us up... */
@@ -404,8 +413,6 @@
} else
task->tk_wakeup = 0;

- if (task->tk_rpcwait != &schedq)
- __rpc_remove_wait_queue(task);
rpc_make_runnable(task);

dprintk("RPC: __rpc_wake_up_task done\n");
@@ -452,8 +459,11 @@
return task;
}

-/*
- * Wake up all tasks on a queue
+/**
+ * rpc_wake_up - wake up all rpc_tasks
+ * @queue: rpc_wait_queue on which the tasks are sleeping
+ *
+ * Grabs rpc_queue_lock
*/
void
rpc_wake_up(struct rpc_wait_queue *queue)
@@ -464,8 +474,12 @@
spin_unlock_bh(&rpc_queue_lock);
}

-/*
- * Wake up all tasks on a queue, and set their status value.
+/**
+ * rpc_wake_up_status - wake up all rpc_tasks and set their status value.
+ * @queue: rpc_wait_queue on which the tasks are sleeping
+ * @status: status value to set
+ *
+ * Grabs rpc_queue_lock
*/
void
rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
@@ -931,20 +945,27 @@
task->tk_release(task);
}

-/*
- * Handling of RPC child tasks
- * We can't simply call wake_up(parent) here, because the
- * parent task may already have gone away
+/**
+ * rpc_find_parent - find the parent of a child task.
+ * @child: child task
+ *
+ * Checks that the parent task is still sleeping on the
+ * queue 'childq'. If so returns a pointer to the parent.
+ * Upon failure returns NULL.
+ *
+ * Caller must hold rpc_queue_lock
*/
static inline struct rpc_task *
rpc_find_parent(struct rpc_task *child)
{
- struct rpc_task *temp, *parent;
+ struct rpc_task *task, *parent;

parent = (struct rpc_task *) child->tk_calldata;
- for (temp = childq.task; temp; temp = temp->tk_next) {
- if (temp == parent)
- return parent;
+ if ((task = childq.task) != NULL) {
+ do {
+ if (task == parent)
+ return parent;
+ } while ((task = task->tk_next) != childq.task);
}
return NULL;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 12:38    [W:0.024 / U:0.012 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site