From: Eric W. Biederman This should fix the big bug that has been crashing kernels when fuser is called. At least it is the bug I observed here. It seems you need the right access pattern on /proc//maps to trigger this. seq_operations ->stop is only called once per start making it safe to call put_task_struct there. However m_next was calling m_stop which totally messed me up. Technically the task_struct needs to be held for the duration, so split m_stop into two functions such that only vma_stop is called multiple times per start. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton --- fs/proc/task_mmu.c | 18 ++++++++++++------ 1 files changed, 12 insertions(+), 6 deletions(-) diff -puN fs/proc/task_mmu.c~proc-dont-lock-task_structs-indefinitely-task_mmu-bug-fix fs/proc/task_mmu.c --- devel/fs/proc/task_mmu.c~proc-dont-lock-task_structs-indefinitely-task_mmu-bug-fix 2006-03-06 18:12:37.000000000 -0800 +++ devel-akpm/fs/proc/task_mmu.c 2006-03-06 18:12:37.000000000 -0800 @@ -362,17 +362,13 @@ out: return priv->tail_vma; } -static void m_stop(struct seq_file *m, void *v) +static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma) { - struct proc_maps_private *priv = m->private; - struct vm_area_struct *vma = v; if (vma && vma != priv->tail_vma) { struct mm_struct *mm = vma->vm_mm; up_read(&mm->mmap_sem); mmput(mm); } - if (priv->task) - put_task_struct(priv->task); } static void *m_next(struct seq_file *m, void *v, loff_t *pos) @@ -384,10 +380,20 @@ static void *m_next(struct seq_file *m, (*pos)++; if (vma && (vma != tail_vma) && vma->vm_next) return vma->vm_next; - m_stop(m, v); + vma_stop(priv, vma); return (vma != tail_vma)? tail_vma: NULL; } +static void m_stop(struct seq_file *m, void *v) +{ + struct proc_maps_private *priv = m->private; + struct vm_area_struct *vma = v; + + vma_stop(priv, vma); + if (priv->task) + put_task_struct(priv->task); +} + static struct seq_operations proc_pid_maps_op = { .start = m_start, .next = m_next, _