Re: 2.6.30-rc1 regression? -- epoll: BUG: sleeping function calledfrom invalid context

From: Stefan Richter
Date: Tue Jun 16 2009 - 08:26:27 EST


Davide Libenzi wrote:
Do you have a chance to give the patch below a spin, in your context?



- Davide

This works for me, i.e. the previously 100% reliably triggered BUGs went away, and testing did not reveal any issues anymore.

---
fs/eventpoll.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)

Index: linux-2.6.mod/fs/eventpoll.c
===================================================================
--- linux-2.6.mod.orig/fs/eventpoll.c 2009-06-15 19:27:05.000000000 -0700
+++ linux-2.6.mod/fs/eventpoll.c 2009-06-15 21:14:36.000000000 -0700
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/hardirq.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/file.h>
@@ -98,7 +99,7 @@ struct epoll_filefd {
struct nested_call_node {
struct list_head llink;
void *cookie;
- int cpu;
+ void *ctx;
};
/*
@@ -317,17 +318,17 @@ static void ep_nested_calls_init(struct * @nproc: Nested call core function pointer.
* @priv: Opaque data to be passed to the @nproc callback.
* @cookie: Cookie to be used to identify this nested call.
+ * @ctx: This instance context.
*
* Returns: Returns the code returned by the @nproc callback, or -1 if
* the maximum recursion limit has been exceeded.
*/
static int ep_call_nested(struct nested_calls *ncalls, int max_nests,
int (*nproc)(void *, void *, int), void *priv,
- void *cookie)
+ void *cookie, void *ctx)
{
int error, call_nests = 0;
unsigned long flags;
- int this_cpu = get_cpu();
struct list_head *lsthead = &ncalls->tasks_call_list;
struct nested_call_node *tncur;
struct nested_call_node tnode;
@@ -340,7 +341,7 @@ static int ep_call_nested(struct nested_
* very much limited.
*/
list_for_each_entry(tncur, lsthead, llink) {
- if (tncur->cpu == this_cpu &&
+ if (tncur->ctx == ctx &&
(tncur->cookie == cookie || ++call_nests > max_nests)) {
/*
* Ops ... loop detected or maximum nest level reached.
@@ -352,7 +353,7 @@ static int ep_call_nested(struct nested_
}
/* Add the current task and cookie to the list */
- tnode.cpu = this_cpu;
+ tnode.ctx = ctx;
tnode.cookie = cookie;
list_add(&tnode.llink, lsthead);
@@ -364,10 +365,9 @@ static int ep_call_nested(struct nested_
/* Remove the current task from the list */
spin_lock_irqsave(&ncalls->lock, flags);
list_del(&tnode.llink);
- out_unlock:
+out_unlock:
spin_unlock_irqrestore(&ncalls->lock, flags);
- put_cpu();
return error;
}
@@ -408,8 +408,12 @@ static int ep_poll_wakeup_proc(void *pri
*/
static void ep_poll_safewake(wait_queue_head_t *wq)
{
+ int this_cpu = get_cpu();
+
ep_call_nested(&poll_safewake_ncalls, EP_MAX_NESTS,
- ep_poll_wakeup_proc, NULL, wq);
+ ep_poll_wakeup_proc, NULL, wq, (void *) (long) this_cpu);
+
+ put_cpu();
}
/*
@@ -663,7 +667,7 @@ static unsigned int ep_eventpoll_poll(st
* could re-enter here.
*/
pollflags = ep_call_nested(&poll_readywalk_ncalls, EP_MAX_NESTS,
- ep_poll_readyevents_proc, ep, ep);
+ ep_poll_readyevents_proc, ep, ep, current);
return pollflags != -1 ? pollflags : 0;
}

Thanks for the quick response,
--
Stefan Richter
-=====-==--= -==- =----
http://arcgraph.de/sr/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/