lkml.org 
[lkml]   [2004]   [Aug]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[Patch 2.6.7]might-sleep-in-atomic while dumping elf
Date
From
Here is a patch to fix a problem of might-sleep-in-atomic which
David Mosberger mentioned at
http://www.gelato.unsw.edu.au/linux-ia64/0407/10526.html

On IA64 platform, a might-sleep-in-atomic warning raise while dumping a
multi-thread process.
That is because elf_cord_dump hold the tasklist_lock before kernel doing
a access_process_vm in elf_core_copy_task_regs,

This patch detached elf_core_copy_task_regs function from inside
tasklist_lock to remove the warning.

diff -Nraup a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c 2004-06-24 09:25:07.000000000 +0800
+++ b/fs/binfmt_elf.c 2004-07-30 16:44:10.000000000 +0800
@@ -1216,6 +1216,7 @@ struct elf_thread_status
struct list_head list;
struct elf_prstatus prstatus; /* NT_PRSTATUS */
elf_fpregset_t fpu; /* NT_PRFPREG */
+ struct task_struct *thread;
#ifdef ELF_CORE_COPY_XFPREGS
elf_fpxregset_t xfpu; /* NT_PRXFPREG */
#endif
@@ -1228,18 +1229,10 @@ struct elf_thread_status
* we need to keep a linked list of every threads pr_status and then
* create a single section for them in the final core file.
*/
-static int elf_dump_thread_status(long signr, struct task_struct * p,
struct list_head * thread_list)
+static int elf_dump_thread_status(long signr, struct elf_thread_status
*t)
{
-
- struct elf_thread_status *t;
int sz = 0;
-
- t = kmalloc(sizeof(*t), GFP_ATOMIC);
- if (!t)
- return 0;
- memset(t, 0, sizeof(*t));
-
- INIT_LIST_HEAD(&t->list);
+ struct task_struct *p = t->thread;
t->num_notes = 0;

fill_prstatus(&t->prstatus, p, signr);
@@ -1262,7 +1255,6 @@ static int elf_dump_thread_status(long s
sz += notesize(&t->notes[2]);
}
#endif
- list_add(&t->list, thread_list);
return sz;
}

@@ -1333,22 +1325,32 @@ static int elf_core_dump(long signr, str
goto cleanup;
#endif

- /* capture the status of all other threads */
if (signr) {
+ struct elf_thread_status *tmp;
read_lock(&tasklist_lock);
do_each_thread(g,p)
if (current->mm == p->mm && current != p) {
- int sz = elf_dump_thread_status(signr,
p, &thread_list);
- if (!sz) {
+ tmp = kmalloc(sizeof(*tmp), GFP_ATOMIC);
+ if (!tmp) {
read_unlock(&tasklist_lock);
goto cleanup;
- } else
- thread_status_size += sz;
+ }
+ memset(tmp, 0, sizeof(*tmp));
+ INIT_LIST_HEAD(&tmp->list);
+ tmp->thread = p;
+ list_add(&tmp->list, &thread_list);
}
while_each_thread(g,p);
read_unlock(&tasklist_lock);
+ list_for_each(t, &thread_list) {
+ struct elf_thread_status *tmp = list_entry(t,
struct elf_thread_status, list);
+ int sz = elf_dump_thread_status(signr, tmp);
+ if (!sz)
+ goto cleanup;
+ else
+ thread_status_size += sz;
+ }
}
-
/* now collect the dump for the current */
memset(prstatus, 0, sizeof(*prstatus));
fill_prstatus(prstatus, current, signr);


[unhandled content-type:application/octet-stream]
\
 
 \ /
  Last update: 2005-03-22 14:04    [W:0.103 / U:0.040 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site