From 6f267f9cc2ea3c375b3e70e336f4feb7da365fe3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 4 Feb 2002 19:14:05 -0800 Subject: v2.4.6.9 -> v2.4.7 - me: fix ptrace and /proc issues with new core-dump permissions - numerous: IDE tape driver update for completion handlers - Ben Collins: ieee1394 GUID cleanups - Jacek Stepniewski: nasty deadlock in rename() --- Makefile | 2 +- arch/alpha/kernel/ptrace.c | 27 +-- arch/arm/kernel/ptrace.c | 27 +-- arch/cris/kernel/ptrace.c | 27 +-- arch/i386/kernel/ptrace.c | 29 +-- arch/ia64/kernel/ptrace.c | 27 +-- arch/m68k/kernel/ptrace.c | 27 +-- arch/mips/kernel/ptrace.c | 29 +-- arch/mips64/kernel/ptrace.c | 54 +----- arch/parisc/kernel/ptrace.c | 27 +-- arch/ppc/kernel/ptrace.c | 28 +-- arch/s390/kernel/ptrace.c | 26 +-- arch/s390x/kernel/ptrace.c | 52 +----- arch/sh/kernel/ptrace.c | 29 +-- arch/sparc/kernel/ptrace.c | 30 +-- arch/sparc64/config.in | 4 +- arch/sparc64/defconfig | 12 +- arch/sparc64/kernel/ptrace.c | 30 +-- drivers/ide/ide-tape.c | 27 +-- drivers/ieee1394/Makefile | 4 +- drivers/ieee1394/guid.c | 305 ------------------------------ drivers/ieee1394/guid.h | 54 ------ drivers/ieee1394/ieee1394_core.c | 6 +- drivers/ieee1394/ieee1394_syms.c | 4 +- drivers/ieee1394/nodemgr.c | 391 +++++++++++++++++++++++++++++++++++++++ drivers/ieee1394/nodemgr.h | 72 +++++++ drivers/ieee1394/ohci1394.c | 32 +--- drivers/ieee1394/pcilynx.c | 1 + fs/namei.c | 4 + fs/proc/base.c | 16 +- include/linux/mm.h | 1 + include/linux/mtd/cfi.h | 3 +- kernel/ksyms.c | 5 + kernel/ptrace.c | 45 +++++ 34 files changed, 597 insertions(+), 860 deletions(-) delete mode 100644 drivers/ieee1394/guid.c delete mode 100644 drivers/ieee1394/guid.h create mode 100644 drivers/ieee1394/nodemgr.c create mode 100644 drivers/ieee1394/nodemgr.h diff --git a/Makefile b/Makefile index 0a939732b0e9..dcc1c365830b 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 7 -EXTRAVERSION =-pre9 +EXTRAVERSION = KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index 2084ff043d3d..3bd4e566b355 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -264,32 +264,7 @@ sys_ptrace(long request, long pid, long addr, long data, if (!child) goto out_notsk; if (request == PTRACE_ATTACH) { - ret = -EPERM; - if (child == current) - goto out; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (current->gid != child->gid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted))) - && !capable(CAP_SYS_PTRACE)) - goto out; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out; - child->ptrace |= PT_PTRACED; - write_lock_irq(&tasklist_lock); - if (child->p_pptr != current) { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irq(&tasklist_lock); - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out; } ret = -ESRCH; diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 4cb165ddcc53..5306de968dda 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -594,32 +594,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) goto out_tsk; if (request == PTRACE_ATTACH) { - if (child == current) - goto out_tsk; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out_tsk; - child->ptrace |= PT_PTRACED; - - write_lock_irq(&tasklist_lock); - if (child->p_pptr != current) { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irq(&tasklist_lock); - - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out_tsk; } ret = -ESRCH; diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c index a8aec56d1996..ea14381c090b 100644 --- a/arch/cris/kernel/ptrace.c +++ b/arch/cris/kernel/ptrace.c @@ -115,32 +115,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) if (pid == 1) /* you may not mess with init */ goto out_tsk; if (request == PTRACE_ATTACH) { - if (child == current) - goto out_tsk; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out_tsk; - child->ptrace |= PT_PTRACED; - - write_lock_irq(&tasklist_lock); - if (child->p_pptr != current) { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irq(&tasklist_lock); - - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out_tsk; } ret = -ESRCH; diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index 028fadfc96f8..3b4f3a6b6801 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -165,34 +165,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) goto out_tsk; if (request == PTRACE_ATTACH) { - if (child == current) - goto out_tsk; - if(((current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - rmb(); - if (!child->mm->dumpable && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out_tsk; - child->ptrace |= PT_PTRACED; - - write_lock_irq(&tasklist_lock); - if (child->p_pptr != current) { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irq(&tasklist_lock); - - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out_tsk; } ret = -ESRCH; diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 1a729add1077..89842b32eb5c 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -768,32 +768,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, goto out_tsk; if (request == PTRACE_ATTACH) { - if (child == current) - goto out_tsk; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out_tsk; - child->ptrace |= PT_PTRACED; - if (child->p_pptr != current) { - unsigned long flags; - - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - } - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out_tsk; } ret = -ESRCH; diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 7b499a569f45..c29c9b286f74 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -118,32 +118,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) goto out_tsk; if (request == PTRACE_ATTACH) { - if (child == current) - goto out_tsk; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out_tsk; - child->ptrace |= PT_PTRACED; - - write_lock_irqsave(&tasklist_lock, flags); - if (child->p_pptr != current) { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irqrestore(&tasklist_lock, flags); - - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out_tsk; } ret = -ESRCH; diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 9336c9a7f31c..fb4fe197e642 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -66,34 +66,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) goto out; if (request == PTRACE_ATTACH) { - if (child == current) - goto out_tsk; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (current->gid != child->gid) || - (!cap_issubset(child->cap_permitted, - current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out_tsk; - child->ptrace |= PT_PTRACED; - - write_lock_irq(&tasklist_lock); - if (child->p_pptr != current) { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irq(&tasklist_lock); - - send_sig(SIGSTOP, child, 1); - res = 0; + res = ptrace_attach(child); goto out_tsk; } res = -ESRCH; diff --git a/arch/mips64/kernel/ptrace.c b/arch/mips64/kernel/ptrace.c index d59aea941f2c..6eff4e198ad5 100644 --- a/arch/mips64/kernel/ptrace.c +++ b/arch/mips64/kernel/ptrace.c @@ -62,32 +62,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) goto out_tsk; if (request == PTRACE_ATTACH) { - if (child == current) - goto out_tsk; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out_tsk; - child->ptrace |= PT_PTRACED; - - write_lock_irq(&tasklist_lock); - if (child->p_pptr != current) { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irq(&tasklist_lock); - - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out_tsk; } ret = -ESRCH; @@ -336,32 +311,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) goto out; if (request == PTRACE_ATTACH) { - if (child == current) - goto out_tsk; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out_tsk; - child->ptrace |= PT_PTRACED; - - write_lock_irq(&tasklist_lock); - if (child->p_pptr != current) { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irq(&tasklist_lock); - - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out_tsk; } ret = -ESRCH; diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 8a305d5c8ce8..770df51822dc 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -61,32 +61,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) goto out_tsk; if (request == PTRACE_ATTACH) { - if (child == current) - goto out_tsk; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out_tsk; - child->ptrace |= PT_PTRACED; - if (child->p_pptr != current) { - unsigned long flags; - - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - } - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out_tsk; } ret = -ESRCH; diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c index 46168d3477c5..caea126dc198 100644 --- a/arch/ppc/kernel/ptrace.c +++ b/arch/ppc/kernel/ptrace.c @@ -118,33 +118,7 @@ int sys_ptrace(long request, long pid, long addr, long data) goto out_tsk; if (request == PTRACE_ATTACH) { - if (child == current) - goto out_tsk; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) - && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out_tsk; - child->ptrace |= PT_PTRACED; - - write_lock_irq(&tasklist_lock); - if (child->p_pptr != current) { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irq(&tasklist_lock); - - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out_tsk; } ret = -ESRCH; diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 1e52bb54bdff..b166d15272b8 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -233,31 +233,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) goto out; if (request == PTRACE_ATTACH) { - if (child == current) - goto out; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid)) && !capable(CAP_SYS_PTRACE)) - goto out; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out; - child->ptrace |= PT_PTRACED; - - write_lock_irqsave(&tasklist_lock, flags); - if (child->p_pptr != current) - { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irqrestore(&tasklist_lock, flags); - - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out; } ret = -ESRCH; diff --git a/arch/s390x/kernel/ptrace.c b/arch/s390x/kernel/ptrace.c index d523785aa296..0ade6ea3fbb2 100644 --- a/arch/s390x/kernel/ptrace.c +++ b/arch/s390x/kernel/ptrace.c @@ -247,31 +247,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) goto out; if (request == PTRACE_ATTACH) { - if (child == current) - goto out; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid)) && !capable(CAP_SYS_PTRACE)) - goto out; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out; - child->ptrace |= PT_PTRACED; - - write_lock_irqsave(&tasklist_lock, flags); - if (child->p_pptr != current) - { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irqrestore(&tasklist_lock, flags); - - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out; } ret = -ESRCH; @@ -433,31 +409,7 @@ asmlinkage int sys32_ptrace(long request, long pid, long addr, s32 data) goto out; if (request == PTRACE_ATTACH) { - if (child == current) - goto out; - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid)) && !capable(CAP_SYS_PTRACE)) - goto out; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out; - child->ptrace |= PT_PTRACED; - - write_lock_irqsave(&tasklist_lock, flags); - if (child->p_pptr != current) - { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irqrestore(&tasklist_lock, flags); - - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out; } ret = -ESRCH; diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index 2272ecae7183..83988d5e09b3 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -173,34 +173,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) goto out_tsk; if (request == PTRACE_ATTACH) { - if (child == tsk) - goto out_tsk; - if(((tsk->uid != child->euid) || - (tsk->uid != child->suid) || - (tsk->uid != child->uid) || - (tsk->gid != child->egid) || - (tsk->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, tsk->cap_permitted)) || - (tsk->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - rmb(); - if (!child->mm->dumpable && !capable(CAP_SYS_PTRACE)) - goto out_tsk; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out_tsk; - child->ptrace |= PT_PTRACED; - - write_lock_irq(&tasklist_lock); - if (child->p_pptr != tsk) { - REMOVE_LINKS(child); - child->p_pptr = tsk; - SET_LINKS(child); - } - write_unlock_irq(&tasklist_lock); - - send_sig(SIGSTOP, child, 1); - ret = 0; + ret = ptrace_attach(child); goto out_tsk; } ret = -ESRCH; diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index 9239f6f09265..0e73266b4159 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -320,38 +320,10 @@ asmlinkage void do_ptrace(struct pt_regs *regs) || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) { unsigned long flags; - if(child == current) { - /* Try this under SunOS/Solaris, bwa haha - * You'll never be able to kill the process. ;-) - */ + if (ptrace_attach(child)) { pt_error_return(regs, EPERM); goto out_tsk; } - if((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->uid) || - (current->uid != child->suid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) { - pt_error_return(regs, EPERM); - goto out_tsk; - } - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) { - pt_error_return(regs, EPERM); - goto out_tsk; - } - child->ptrace |= PT_PTRACED; - write_lock_irqsave(&tasklist_lock, flags); - if(child->p_pptr != current) { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irqrestore(&tasklist_lock, flags); - send_sig(SIGSTOP, child, 1); pt_succ_return(regs, 0); goto out_tsk; } diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in index b320d61bd016..1dd65e6d9fcc 100644 --- a/arch/sparc64/config.in +++ b/arch/sparc64/config.in @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.147 2001/07/18 07:52:34 davem Exp $ +# $Id: config.in,v 1.148 2001/07/20 07:10:35 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -207,7 +207,9 @@ fi endmenu source drivers/fc4/Config.in + source drivers/message/fusion/Config.in + source drivers/ieee1394/Config.in if [ "$CONFIG_NET" = "y" ]; then diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index d76745d1f907..a7898b493390 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -364,13 +364,23 @@ CONFIG_FUSION_LAN=m CONFIG_NET_FC=y # -# IEEE 1394 (FireWire) support +# IEEE 1394 (FireWire) support (EXPERIMENTAL) # CONFIG_IEEE1394=m + +# +# Device Drivers +# CONFIG_IEEE1394_PCILYNX=m # CONFIG_IEEE1394_PCILYNX_LOCALRAM is not set # CONFIG_IEEE1394_PCILYNX_PORTS is not set CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +# CONFIG_IEEE1394_VIDEO1394 is not set +CONFIG_IEEE1394_SBP2=m CONFIG_IEEE1394_RAWIO=m # CONFIG_IEEE1394_VERBOSEDEBUG is not set diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 249bc753a2c0..1b13e569f68a 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -170,38 +170,10 @@ asmlinkage void do_ptrace(struct pt_regs *regs) || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) { unsigned long flags; - if (child == current) { - /* Try this under SunOS/Solaris, bwa haha - * You'll never be able to kill the process. ;-) - */ + if (ptrace_attach(child)) { pt_error_return(regs, EPERM); goto out_tsk; } - if ((!child->mm->dumpable || - (current->uid != child->euid) || - (current->uid != child->uid) || - (current->uid != child->suid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) { - pt_error_return(regs, EPERM); - goto out_tsk; - } - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) { - pt_error_return(regs, EPERM); - goto out_tsk; - } - child->ptrace |= PT_PTRACED; - write_lock_irqsave(&tasklist_lock, flags); - if (child->p_pptr != current) { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - write_unlock_irqrestore(&tasklist_lock, flags); - send_sig(SIGSTOP, child, 1); pt_succ_return(regs, 0); goto out_tsk; } diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 91f24bac280b..fd96d80aad19 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -419,6 +419,7 @@ #include #include #include +#include #include #include @@ -978,7 +979,7 @@ typedef struct { int logical_blk_num; /* logical block number */ __u16 wrt_pass_cntr; /* write pass counter */ __u32 update_frame_cntr; /* update frame counter */ - struct semaphore *sem; + struct completion *waiting; int onstream_write_error; /* write error recovery active */ int header_ok; /* header frame verified ok */ int linux_media; /* reading linux-specifc media */ @@ -1886,8 +1887,8 @@ static void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup) printk("ide-tape: %s: skipping over config parition..\n", tape->name); #endif tape->onstream_write_error = OS_PART_ERROR; - if (tape->sem) - up(tape->sem); + if (tape->waiting) + complete(tape->waiting); } } remove_stage = 1; @@ -1903,8 +1904,8 @@ static void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup) tape->nr_pending_stages++; tape->next_stage = tape->first_stage; rq->current_nr_sectors = rq->nr_sectors; - if (tape->sem) - up(tape->sem); + if (tape->waiting) + complete(tape->waiting); } } } else if (rq->cmd == IDETAPE_READ_RQ) { @@ -3064,15 +3065,15 @@ static void idetape_init_stage (ide_drive_t *drive, idetape_stage_t *stage, int } /* - * idetape_wait_for_request installs a semaphore in a pending request + * idetape_wait_for_request installs a completion in a pending request * and sleeps until it is serviced. * * The caller should ensure that the request will not be serviced - * before we install the semaphore (usually by disabling interrupts). + * before we install the completion (usually by disabling interrupts). */ static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq) { - DECLARE_MUTEX_LOCKED(sem); + DECLARE_COMPLETION(wait); idetape_tape_t *tape = drive->driver_data; #if IDETAPE_DEBUG_BUGS @@ -3081,12 +3082,12 @@ static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq) return; } #endif /* IDETAPE_DEBUG_BUGS */ - rq->sem = &sem; - tape->sem = &sem; + rq->waiting = &wait; + tape->waiting = &wait; spin_unlock(&tape->spinlock); - down(&sem); - rq->sem = NULL; - tape->sem = NULL; + wait_for_completion(&wait); + rq->waiting = NULL; + tape->waiting = NULL; spin_lock_irq(&tape->spinlock); } diff --git a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile index c8059eac154a..9a38a03f0650 100644 --- a/drivers/ieee1394/Makefile +++ b/drivers/ieee1394/Makefile @@ -8,7 +8,7 @@ export-objs := ieee1394_syms.o list-multi := ieee1394.o ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \ - highlevel.o csr.o guid.o ieee1394_syms.o + highlevel.o csr.o nodemgr.o ieee1394_syms.o obj-$(CONFIG_IEEE1394) += ieee1394.o obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o @@ -16,8 +16,6 @@ obj-$(CONFIG_IEEE1394_OHCI1394) += ohci1394.o obj-$(CONFIG_IEEE1394_VIDEO1394) += video1394.o obj-$(CONFIG_IEEE1394_RAWIO) += raw1394.o obj-$(CONFIG_IEEE1394_SBP2) += sbp2.o -obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o -obj-$(CONFIG_IEEE1394_IP1394) += ip1394.o include $(TOPDIR)/Rules.make diff --git a/drivers/ieee1394/guid.c b/drivers/ieee1394/guid.c deleted file mode 100644 index ef0a2abfd033..000000000000 --- a/drivers/ieee1394/guid.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * IEEE 1394 for Linux - * - * GUID collection and management - * - * Copyright (C) 2000 Andreas E. Bombe - * - * This code is licensed under the GPL. See the file COPYING in the root - * directory of the kernel sources for details. - */ - -#include -#include -#include -#include -#include - -#include "ieee1394_types.h" -#include "ieee1394.h" -#include "hosts.h" -#include "ieee1394_transactions.h" -#include "highlevel.h" -#include "csr.h" - - -static atomic_t outstanding_requests; - -static LIST_HEAD(guid_list); -rwlock_t guid_lock = RW_LOCK_UNLOCKED; - -struct guid_entry { - struct list_head list; - atomic_t refcount; - - u64 guid; - - struct hpsb_host *host; - nodeid_t node_id; - - atomic_t generation; -}; - -struct guid_req { - struct hpsb_packet *pkt; - int retry; - unsigned int hdr_size; - int hdr_ptr; - u32 bus_info[5]; - struct tq_struct tq; -}; - -static struct guid_entry *create_guid_entry(void) -{ - struct guid_entry *ge; - unsigned long flags; - - ge = kmalloc(sizeof(struct guid_entry), SLAB_ATOMIC); - if (!ge) return NULL; - - INIT_LIST_HEAD(&ge->list); - atomic_set(&ge->refcount, 0); - ge->guid = (u64) -1; - ge->host = NULL; - ge->node_id = 0; - atomic_set(&ge->generation, -1); - - write_lock_irqsave(&guid_lock, flags); - list_add_tail(&ge->list, &guid_list); - write_unlock_irqrestore(&guid_lock, flags); - - return ge; -} - -static struct guid_entry *find_entry(u64 guid) -{ - struct list_head *lh; - struct guid_entry *ge; - - lh = guid_list.next; - while (lh != &guid_list) { - ge = list_entry(lh, struct guid_entry, list); - if (ge->guid == guid) return ge; - lh = lh->next; - } - - return NULL; -} - -static void associate_guid(struct hpsb_host *host, nodeid_t nodeid, u64 guid) -{ - struct guid_entry *ge; - unsigned long flags; - - HPSB_DEBUG("Node %d on %s host: GUID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - nodeid & NODE_MASK, host->template->name, ((u8 *)&guid)[0], - ((u8 *)&guid)[1], ((u8 *)&guid)[2], ((u8 *)&guid)[3], - ((u8 *)&guid)[4], ((u8 *)&guid)[5], ((u8 *)&guid)[6], - ((u8 *)&guid)[7]); - - read_lock_irqsave(&guid_lock, flags); - ge = find_entry(guid); - read_unlock_irqrestore(&guid_lock, flags); - - if (!ge) ge = create_guid_entry(); - if (!ge) return; - - ge->host = host; - ge->node_id = nodeid; - ge->guid = guid; - - atomic_set(&ge->generation, get_hpsb_generation()); -} - -static void pkt_complete(struct guid_req *req) -{ - struct hpsb_packet *pkt = req->pkt; - struct hpsb_host *host = pkt->host; - nodeid_t nodeid = pkt->node_id; - - if (hpsb_packet_success (pkt)) { - HPSB_ERR("GUID quadlet transaction error for %d, retry: %d", nodeid, - req->retry); - req->retry++; - if (req->retry > 3) - goto finish; - else - goto retry; - } - - /* Copy our received quadlet */ - req->bus_info[req->hdr_ptr++] = be32_to_cpu(pkt->header[3]); - - /* First quadlet, let's get some info */ - if (req->hdr_ptr == 1) { - /* Get the bus_info_length from first quadlet */ - req->hdr_size = req->bus_info[0] >> 24; - - /* Make sure this isn't one of those minimal proprietary - * ROMs. IMO, we should just barf all over them. We need - * atleast four bus_info quads to get our EUI-64. */ - if (req->hdr_size < 4) { - HPSB_INFO("Node %d on %s host has non-standard ROM format (%d quads), " - "cannot parse", nodeid, host->template->name, req->hdr_size); - goto finish; - } - - /* Make sure we don't overflow. We have one quad for this - * first bus info block, the other 4 should be part of the - * bus info itself. */ - if (req->hdr_size > (sizeof (req->bus_info) >> 2) - 1) - req->hdr_size = (sizeof (req->bus_info) >> 2) - 1; - } - - /* We've got all the info we need, so let's check the EUI-64, and - * add it to our list. */ - if (req->hdr_ptr >= req->hdr_size + 1) { - associate_guid(pkt->host, pkt->node_id, - ((u64)req->bus_info[3] << 32) | req->bus_info[4]); - goto finish; - } - -retry: - - /* Here, we either retry a failed retrieve, or we have incremented - * our counter, to get the next quad in our header. */ - free_tlabel(pkt->host, pkt->node_id, pkt->tlabel); - free_hpsb_packet(pkt); - pkt = hpsb_make_readqpacket(host, nodeid, CSR_REGISTER_BASE + - CSR_CONFIG_ROM + (req->hdr_ptr<<2)); - if (!pkt) { - kfree(req); - HPSB_ERR("Out of memory in GUID processing"); - return; - } - - req->pkt = pkt; - req->retry = 0; - - queue_task(&req->tq, &pkt->complete_tq); - if (!hpsb_send_packet(pkt)) { - HPSB_NOTICE("Failed to send GUID request to node %d", nodeid); - goto finish; - } - - return; - -finish: - - free_tlabel(pkt->host, nodeid, pkt->tlabel); - free_hpsb_packet(pkt); - kfree(req); - - if (atomic_dec_and_test(&outstanding_requests)) { - /* Do something useful */ - } - - return; -} - - -static void host_reset(struct hpsb_host *host) -{ - struct guid_req *greq; - struct hpsb_packet *pkt; - struct selfid *sid = (struct selfid *)host->topology_map; - int nodecount = host->node_count; - nodeid_t nodeid = LOCAL_BUS; - - for (; nodecount; nodecount--, nodeid++, sid++) { - while (sid->extended) - sid++; - if (!sid->link_active) - continue; - if (nodeid == host->node_id) - continue; - - greq = kmalloc(sizeof(struct guid_req), SLAB_ATOMIC); - if (!greq) { - HPSB_ERR("Out of memory in GUID processing"); - return; - } - - pkt = hpsb_make_readqpacket(host, nodeid, CSR_REGISTER_BASE + - CSR_CONFIG_ROM); - - if (!pkt) { - kfree(greq); - HPSB_ERR("Out of memory in GUID processing"); - return; - } - - INIT_TQUEUE(&greq->tq, (void (*)(void*))pkt_complete, greq); - - greq->hdr_size = 4; - greq->hdr_ptr = 0; - greq->retry = 0; - greq->pkt = pkt; - - queue_task(&greq->tq, &pkt->complete_tq); - - if (!hpsb_send_packet(pkt)) { - free_tlabel(pkt->host, pkt->node_id, pkt->tlabel); - free_hpsb_packet(pkt); - kfree(greq); - HPSB_NOTICE("Failed to send GUID request to node %d", nodeid); - } - - HPSB_DEBUG("GUID request sent to node %d", nodeid & NODE_MASK); - - atomic_inc(&outstanding_requests); - } -} - - -struct guid_entry *hpsb_guid_get_handle(u64 guid) -{ - unsigned long flags; - struct guid_entry *ge; - - read_lock_irqsave(&guid_lock, flags); - ge = find_entry(guid); - if (ge) atomic_inc(&ge->refcount); - read_unlock_irqrestore(&guid_lock, flags); - - return ge; -} - -struct hpsb_host *hpsb_guid_localhost(struct guid_entry *ge) -{ - if (atomic_read(&ge->generation) != get_hpsb_generation()) return NULL; - if (ge->node_id == ge->host->node_id) return ge->host; - return NULL; -} - -int hpsb_guid_fill_packet(struct guid_entry *ge, struct hpsb_packet *pkt) -{ - if (atomic_read(&ge->generation) != get_hpsb_generation()) return 0; - - pkt->host = ge->host; - pkt->node_id = ge->node_id; - pkt->generation = atomic_read(&ge->generation); - return 1; -} - - -static struct hpsb_highlevel_ops guid_ops = { - host_reset: host_reset, -}; - -static struct hpsb_highlevel *hl; - -void init_ieee1394_guid(void) -{ - atomic_set(&outstanding_requests, 0); - - hl = hpsb_register_highlevel("GUID manager", &guid_ops); - if (!hl) { - HPSB_ERR("out of memory during ieee1394 initialization"); - } -} - -void cleanup_ieee1394_guid(void) -{ - hpsb_unregister_highlevel(hl); -} diff --git a/drivers/ieee1394/guid.h b/drivers/ieee1394/guid.h deleted file mode 100644 index 0ea8a842c79c..000000000000 --- a/drivers/ieee1394/guid.h +++ /dev/null @@ -1,54 +0,0 @@ - -#ifndef _IEEE1394_GUID_H -#define _IEEE1394_GUID_H - - -/* - * General information: Finding out which GUID belongs to which node is done by - * sending packets and therefore waiting for the answers. Wherever it is - * mentioned that a node is inaccessible this could just as well mean that we - * just don't know yet (usually, bus reset handlers can't rely on GUIDs being - * associated with current nodes). - */ - -struct guid_entry; -typedef struct guid_entry *hpsb_guid_t; - - -/* - * Returns a guid handle (which has its reference count incremented) or NULL if - * there is the GUID in question is not known of. Getting a valid handle does - * not mean that the node with this GUID is currently accessible (might not be - * plugged in or powered down). - */ -hpsb_guid_t hpsb_guid_get_handle(u64 guid); - -/* - * If the handle refers to a local host, this function will return the pointer - * to the hpsb_host structure. It will return NULL otherwise. Once you have - * established it is a local host, you can use that knowledge from then on (the - * GUID won't wander to an external node). - * - * Note that the local GUID currently isn't collected, so this will always - * return NULL. - */ -struct hpsb_host *hpsb_guid_localhost(hpsb_guid_t handle); - -/* - * This will fill in the given, pre-initialised hpsb_packet with the current - * information from the GUID handle (host, node ID, generation number). It will - * return false if the node owning the GUID is not accessible (and not modify the - * hpsb_packet) and return true otherwise. - * - * Note that packet sending may still fail in hpsb_send_packet if a bus reset - * happens while you are trying to set up the packet (due to obsolete generation - * number). It will at least reliably fail so that you don't accidentally and - * unknowingly send your packet to the wrong node. - */ -int hpsb_guid_fill_packet(hpsb_guid_t handle, struct hpsb_packet *pkt); - - -void init_ieee1394_guid(void); -void cleanup_ieee1394_guid(void); - -#endif /* _IEEE1394_GUID_H */ diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 50f74060b0f9..dc8bf319eaae 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -29,7 +29,7 @@ #include "highlevel.h" #include "ieee1394_transactions.h" #include "csr.h" -#include "guid.h" +#include "nodemgr.h" atomic_t hpsb_generation = ATOMIC_INIT(0); @@ -782,13 +782,13 @@ static int __init ieee1394_init(void) { init_hpsb_highlevel(); init_csr(); - init_ieee1394_guid(); + init_ieee1394_nodemgr(); return 0; } static void __exit ieee1394_cleanup(void) { - cleanup_ieee1394_guid(); + cleanup_ieee1394_nodemgr(); cleanup_csr(); } diff --git a/drivers/ieee1394/ieee1394_syms.c b/drivers/ieee1394/ieee1394_syms.c index 0311393f50ca..534f8b5a2a5a 100644 --- a/drivers/ieee1394/ieee1394_syms.c +++ b/drivers/ieee1394/ieee1394_syms.c @@ -18,7 +18,7 @@ #include "ieee1394_core.h" #include "ieee1394_transactions.h" #include "highlevel.h" -#include "guid.h" +#include "nodemgr.h" EXPORT_SYMBOL(hpsb_register_lowlevel); EXPORT_SYMBOL(hpsb_unregister_lowlevel); @@ -76,5 +76,5 @@ EXPORT_SYMBOL(highlevel_remove_host); EXPORT_SYMBOL(highlevel_host_reset); EXPORT_SYMBOL(highlevel_add_one_host); EXPORT_SYMBOL(hpsb_guid_get_handle); -EXPORT_SYMBOL(hpsb_guid_localhost); +EXPORT_SYMBOL(hpsb_get_host_by_ge); EXPORT_SYMBOL(hpsb_guid_fill_packet); diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c new file mode 100644 index 000000000000..39f910afce99 --- /dev/null +++ b/drivers/ieee1394/nodemgr.c @@ -0,0 +1,391 @@ +/* + * Node information (ConfigROM) collection and management. + * + * Copyright (C) 2000 Andreas E. Bombe + * 2001 Ben Collins + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "ieee1394_types.h" +#include "ieee1394.h" +#include "hosts.h" +#include "ieee1394_transactions.h" +#include "highlevel.h" +#include "csr.h" + + +/* Basically what we do here is start off retrieving the bus_info block. + * From there will fill in some info about the node, verify it is of IEEE + * 1394 type, and the the crc checks out ok. After that we start off with + * the root directory, and subdirectories. To do this, we retrieve the + * quadlet header for a directory, find out the length, and retrieve the + * complete directory entry (be it a leaf or a directory). We then process + * it and add the info to our structure for that particular node. + * + * We verify CRC's along the way for each directory/block/leaf. The + * entire node structure is generic, and simply stores the information in + * a way that's easy to parse by the protocol interface. + * + * XXX: Most of this isn't done yet :) */ + + +static atomic_t outstanding_requests; + +static LIST_HEAD(node_list); +rwlock_t node_lock = RW_LOCK_UNLOCKED; + +static LIST_HEAD(host_info_list); +spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED; + +struct host_info { + struct hpsb_host *host; + int pid; + wait_queue_head_t reset_wait; + struct list_head list; +}; + +struct node_entry { + struct list_head list; + atomic_t refcount; + + u64 guid; + + struct hpsb_host *host; + nodeid_t node_id; + + atomic_t generation; +}; + +static struct node_entry *create_node_entry(void) +{ + struct node_entry *ge; + unsigned long flags; + + ge = kmalloc(sizeof(struct node_entry), SLAB_ATOMIC); + if (!ge) return NULL; + + INIT_LIST_HEAD(&ge->list); + atomic_set(&ge->refcount, 0); + ge->guid = (u64) -1; + ge->host = NULL; + ge->node_id = 0; + atomic_set(&ge->generation, -1); + + write_lock_irqsave(&node_lock, flags); + list_add_tail(&ge->list, &node_list); + write_unlock_irqrestore(&node_lock, flags); + + return ge; +} + +static struct node_entry *find_entry(u64 guid) +{ + struct list_head *lh; + struct node_entry *ge; + + lh = node_list.next; + while (lh != &node_list) { + ge = list_entry(lh, struct node_entry, list); + if (ge->guid == guid) return ge; + lh = lh->next; + } + + return NULL; +} + +static void associate_guid(struct hpsb_host *host, nodeid_t nodeid, u64 guid) +{ + struct node_entry *ge; + unsigned long flags; + + HPSB_DEBUG("Node %d on %s host: GUID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + nodeid & NODE_MASK, host->template->name, ((u8 *)&guid)[0], + ((u8 *)&guid)[1], ((u8 *)&guid)[2], ((u8 *)&guid)[3], + ((u8 *)&guid)[4], ((u8 *)&guid)[5], ((u8 *)&guid)[6], + ((u8 *)&guid)[7]); + + read_lock_irqsave(&node_lock, flags); + ge = find_entry(guid); + read_unlock_irqrestore(&node_lock, flags); + + if (!ge) ge = create_node_entry(); + if (!ge) return; + + ge->host = host; + ge->node_id = nodeid; + ge->guid = guid; + + atomic_set(&ge->generation, get_hpsb_generation()); +} + +/* This is where we probe the nodes for their information and provided + * features. */ +static void nodemgr_node_probe(struct hpsb_host *host) +{ + struct selfid *sid = (struct selfid *)host->topology_map; + int nodecount = host->node_count; + nodeid_t nodeid = LOCAL_BUS; + quadlet_t buffer[5], quad; + octlet_t base = CSR_REGISTER_BASE + CSR_CONFIG_ROM; + int retval; + + /* We need to detect when the ConfigROM's generation has changed, + * so we only update the node's info when it needs to be. */ + for (; nodecount; nodecount--, nodeid++, sid++) { + int header_count = 0; + unsigned header_size = 0; + while (sid->extended) + sid++; + if (!sid->link_active) + continue; + if (nodeid == host->node_id) + continue; + + HPSB_DEBUG("Initiating ConfigROM request for node %d", nodeid & NODE_MASK); + + retval = hpsb_read(host, nodeid, base, &quad, 4); + buffer[header_count++] = be32_to_cpu(quad); + + if (retval) { + HPSB_ERR("ConfigROM quadlet transaction error for %d", + nodeid & NODE_MASK); + continue; + } + + header_size = buffer[0] >> 24; + + if (header_size < 4) { + HPSB_INFO("Node %d on %s host has non-standard ROM format (%d quads), " + "cannot parse", nodeid & NODE_MASK, host->template->name, + header_size); + continue; + } + + while (header_count <= header_size && (header_count<<2) < sizeof(buffer)) { + retval = hpsb_read(host, nodeid, base + (header_count<<2), &quad, 4); + buffer[header_count++] = be32_to_cpu(quad); + + if (retval) { + HPSB_ERR("ConfigROM quadlet transaction error for %d", + nodeid & NODE_MASK); + goto failed_read; + } + + } + + associate_guid(host, nodeid, be64_to_cpu(((u64)buffer[3] << 32) | buffer[4])); +failed_read: + continue; + } + + /* Need to detect when nodes are no longer associated with + * anything. I believe we can do this using the generation of the + * entries after a reset, compared the the hosts generation. */ +} + + +struct node_entry *hpsb_guid_get_handle(u64 guid) +{ + unsigned long flags; + struct node_entry *ge; + + read_lock_irqsave(&node_lock, flags); + ge = find_entry(guid); + if (ge) atomic_inc(&ge->refcount); + read_unlock_irqrestore(&node_lock, flags); + + return ge; +} + +struct hpsb_host *hpsb_get_host_by_ge(struct node_entry *ge) +{ + if (atomic_read(&ge->generation) != get_hpsb_generation()) return NULL; + if (ge->node_id == ge->host->node_id) return ge->host; + return NULL; +} + +int hpsb_guid_fill_packet(struct node_entry *ge, struct hpsb_packet *pkt) +{ + if (atomic_read(&ge->generation) != get_hpsb_generation()) return 0; + + pkt->host = ge->host; + pkt->node_id = ge->node_id; + pkt->generation = atomic_read(&ge->generation); + return 1; +} + +static int nodemgr_reset_handler(void *__hi) +{ + struct host_info *hi = (struct host_info *)__hi; + struct hpsb_host *host = hi->host; + + /* Standard thread setup */ + lock_kernel(); + daemonize(); + strcpy(current->comm, "NodeMngr"); + unlock_kernel(); + + for (;;) { + if (signal_pending(current)) + break; + + /* Let's take a short pause to make sure all the devices + * have time to settle. */ + + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/50); + + if (hi && host) + nodemgr_node_probe(host); + + /* Wait for the next bus reset */ + if (hi && host) + interruptible_sleep_on(&hi->reset_wait); + } + + return(0); +} + +static void nodemgr_add_host(struct hpsb_host *host) +{ + struct host_info *hi = kmalloc (sizeof (struct host_info), GFP_KERNEL); + int flags; + + if (!hi) { + HPSB_ERR ("Out of memory in Node Manager"); + return; + } + + hi->host = host; + INIT_LIST_HEAD(&hi->list); + hi->pid = -1; + init_waitqueue_head(&hi->reset_wait); + + spin_lock_irqsave (&host_info_lock, flags); + list_add_tail (&hi->list, &host_info_list); + spin_unlock_irqrestore (&host_info_lock, flags); + + return; +} + +static void nodemgr_schedule_thread (void *__hi) +{ + struct host_info *hi = (struct host_info *)__hi; + + hi->pid = kernel_thread(nodemgr_reset_handler, hi, + CLONE_FS|CLONE_FILES|CLONE_SIGHAND); +} + +static void nodemgr_host_reset(struct hpsb_host *host) +{ + struct list_head *lh; + struct host_info *hi = NULL; + int flags; + + spin_lock_irqsave (&host_info_lock, flags); + lh = host_info_list.next; + while (lh != &host_info_list) { + struct host_info *myhi = list_entry(lh, struct host_info, list); + if (myhi->host == host) { + hi = myhi; + break; + } + lh = lh->next; + } + + if (hi == NULL) { + HPSB_ERR ("Could not process reset of non-existent host in Node Manager"); + goto done_reset_host; + } + + if (hi->pid >= 0) { + wake_up(&hi->reset_wait); + } else { + if (in_interrupt()) { + static struct tq_struct task; + memset(&task, 0, sizeof(struct tq_struct)); + + task.routine = nodemgr_schedule_thread; + task.data = (void*)hi; + + if (schedule_task(&task) < 0) + HPSB_ERR ("Failed to schedule Node Manager thread!\n"); + } else { + nodemgr_schedule_thread(hi); + } + } + +done_reset_host: + spin_unlock_irqrestore (&host_info_lock, flags); + + return; +} + +static void nodemgr_remove_host(struct hpsb_host *host) +{ + struct list_head *lh; + struct host_info *hi = NULL; + int flags; + + spin_lock_irqsave (&host_info_lock, flags); + lh = host_info_list.next; + while (lh != &host_info_list) { + struct host_info *myhi = list_entry(lh, struct host_info, list); + if (myhi->host == host) { + hi = myhi; + break; + } + lh = lh->next; + } + + if (hi == NULL) { + HPSB_ERR ("Could not remove non-exitent host in Node Manager"); + goto done_remove_host; + } + + if (hi->pid >= 0) + kill_proc(hi->pid, SIGINT, 1); + + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ*2); /* 2 second delay */ + + kfree (hi); + +done_remove_host: + spin_unlock_irqrestore (&host_info_lock, flags); + + return; +} + +static struct hpsb_highlevel_ops guid_ops = { + add_host: nodemgr_add_host, + host_reset: nodemgr_host_reset, + remove_host: nodemgr_remove_host, +}; + +static struct hpsb_highlevel *hl; + +void init_ieee1394_nodemgr(void) +{ + atomic_set(&outstanding_requests, 0); + + hl = hpsb_register_highlevel("Node manager", &guid_ops); + if (!hl) { + HPSB_ERR("Out of memory during ieee1394 initialization"); + } +} + +void cleanup_ieee1394_nodemgr(void) +{ + hpsb_unregister_highlevel(hl); +} diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h new file mode 100644 index 000000000000..b544b413c5fc --- /dev/null +++ b/drivers/ieee1394/nodemgr.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2000 Andreas E. Bombe + * 2001 Ben Collins + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _IEEE1394_NODEMGR_H +#define _IEEE1394_NODEMGR_H + + +/* + * General information: Finding out which GUID belongs to which node is done by + * sending packets and therefore waiting for the answers. Wherever it is + * mentioned that a node is inaccessible this could just as well mean that we + * just don't know yet (usually, bus reset handlers can't rely on GUIDs being + * associated with current nodes). + */ + +struct node_entry; +typedef struct node_entry *hpsb_guid_t; + + +/* + * Returns a guid handle (which has its reference count incremented) or NULL if + * there is the GUID in question is not known of. Getting a valid handle does + * not mean that the node with this GUID is currently accessible (might not be + * plugged in or powered down). + */ +hpsb_guid_t hpsb_guid_get_handle(u64 guid); + +/* + * If the handle refers to a local host, this function will return the pointer + * to the hpsb_host structure. It will return NULL otherwise. Once you have + * established it is a local host, you can use that knowledge from then on (the + * GUID won't wander to an external node). + * + * Note that the local GUID currently isn't collected, so this will always + * return NULL. + */ +struct hpsb_host *hpsb_get_host_by_ge(hpsb_guid_t handle); + +/* + * This will fill in the given, pre-initialised hpsb_packet with the current + * information from the GUID handle (host, node ID, generation number). It will + * return false if the node owning the GUID is not accessible (and not modify the + * hpsb_packet) and return true otherwise. + * + * Note that packet sending may still fail in hpsb_send_packet if a bus reset + * happens while you are trying to set up the packet (due to obsolete generation + * number). It will at least reliably fail so that you don't accidentally and + * unknowingly send your packet to the wrong node. + */ +int hpsb_guid_fill_packet(hpsb_guid_t handle, struct hpsb_packet *pkt); + + +void init_ieee1394_nodemgr(void); +void cleanup_ieee1394_nodemgr(void); + +#endif /* _IEEE1394_NODEMGR_H */ diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index baf6d484cbe0..0d1ce4e59f96 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -178,7 +178,7 @@ static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, ohci1394_pci_tbl); static char version[] __devinitdata = - "ohci1394.c:v0.50 15/Jul/01 Ben Collins "; + "v0.50 15/Jul/01 Ben Collins "; /* Module Parameters */ MODULE_PARM(attempt_root,"i"); @@ -216,6 +216,7 @@ static u8 get_phy_reg(struct ti_ohci *ohci, u8 addr) for (i = 0; i < OHCI_LOOP_COUNT; i++) { if (reg_read(ohci, OHCI1394_PhyControl) & 0x80000000) break; + mdelay(1); } @@ -243,6 +244,7 @@ static void set_phy_reg(struct ti_ohci *ohci, u8 addr, u8 data) r = reg_read(ohci, OHCI1394_PhyControl); if (!(r & 0x00004000)) break; + mdelay(1); } @@ -516,22 +518,6 @@ static int ohci_initialize(struct hpsb_host *host) /* Set the configuration ROM mapping register */ reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus); - /* Set bus options */ - reg_write(ohci, OHCI1394_BusOptions, - cpu_to_be32(ohci->csr_config_rom_cpu[2])); - -#if 0 - /* Write the GUID into the csr config rom */ - ohci->csr_config_rom_cpu[3] = - be32_to_cpu(reg_read(ohci, OHCI1394_GUIDHi)); - ohci->csr_config_rom_cpu[4] = - be32_to_cpu(reg_read(ohci, OHCI1394_GUIDLo)); -#endif - - /* Write the config ROM header */ - reg_write(ohci, OHCI1394_ConfigROMhdr, - cpu_to_be32(ohci->csr_config_rom_cpu[0])); - ohci->max_packet_size = 1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1); PRINT(KERN_DEBUG, ohci->id, "Max packet size = %d bytes", @@ -725,7 +711,7 @@ static void insert_packet(struct ti_ohci *ohci, OHCI_DMA_ALLOC("single, block transmit packet"); if (ohci->payload_swap) - block_swab32(packet->data, packet->data_size>>2); + block_swab32(packet->data, packet->data_size >> 2); d->prg_cpu[idx]->end.branchAddress = 0; d->prg_cpu[idx]->end.status = 0; @@ -1897,6 +1883,9 @@ static void ohci_init_config_rom(struct ti_ohci *ohci) cf_put_1quad(&cr, reg_read(ohci, OHCI1394_GUIDLo)); cf_unit_end(&cr); + DBGMSG(ohci->id, "GUID: %08x:%08x\n", reg_read(ohci, OHCI1394_GUIDHi), + reg_read(ohci, OHCI1394_GUIDLo)); + /* IEEE P1212 suggests the initial ROM header CRC should only * cover the header itself (and not the entire ROM). Since we use * this, then we can make our bus_info_len the same as the CRC @@ -1991,6 +1980,7 @@ int ohci_compare_swap(struct ti_ohci *ohci, quadlet_t *data, for (i = 0; i < OHCI_LOOP_COUNT; i++) { if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000) break; + mdelay(10); } @@ -2180,7 +2170,7 @@ static int __devinit ohci1394_add_one(struct pci_dev *dev, const struct pci_devi if (ohci->ir_context == NULL) FAIL("Failed to allocate IR context"); - ohci->ISO_channel_usage= 0; + ohci->ISO_channel_usage = 0; spin_lock_init(&ohci->IR_channel_lock); if (!request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ, @@ -2191,10 +2181,6 @@ static int __devinit ohci1394_add_one(struct pci_dev *dev, const struct pci_devi ohci_init_config_rom(ohci); - DBGMSG(ohci->id, "The 1st byte at offset 0x404 is: 0x%02x", - *((char *)ohci->csr_config_rom_cpu+4)); - - /* Tell the highlevel this host is ready */ highlevel_add_one_host (host); diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c index 5e6b99992803..03f200b077c5 100644 --- a/drivers/ieee1394/pcilynx.c +++ b/drivers/ieee1394/pcilynx.c @@ -1351,6 +1351,7 @@ static int add_card(struct pci_dev *dev) lynx->id = num_of_cards-1; lynx->dev = dev; + lynx->host->pdev = dev; lynx->lock = SPIN_LOCK_UNLOCKED; lynx->phy_reg_lock = SPIN_LOCK_UNLOCKED; diff --git a/fs/namei.c b/fs/namei.c index fe7f8fa59aaa..e2a0efa0e1bf 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1688,6 +1688,10 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, error = -EINVAL; if (is_subdir(new_dentry, old_dentry)) goto out_unlock; + /* Don't eat your daddy, dear... */ + /* This also avoids locking issues */ + if (old_dentry->d_parent == new_dentry) + goto out_unlock; target = new_dentry->d_inode; if (target) { /* Hastur! Hastur! Hastur! */ triple_down(&old_dir->i_zombie, diff --git a/fs/proc/base.c b/fs/proc/base.c index 969b91d8981e..edae3acee910 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -645,6 +645,20 @@ static int proc_base_readdir(struct file * filp, /* building an inode */ +static int task_dumpable(struct task_struct *task) +{ + int dumpable = 0; + struct mm_struct *mm; + + task_lock(task); + mm = task->mm; + if (mm) + dumpable = mm->dumpable; + task_unlock(task); + return dumpable; +} + + static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task, int ino) { struct inode * inode; @@ -670,7 +684,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st inode->u.proc_i.task = task; inode->i_uid = 0; inode->i_gid = 0; - if (ino == PROC_PID_INO || task->mm->dumpable) { + if (ino == PROC_PID_INO || task_dumpable(task)) { inode->i_uid = task->euid; inode->i_gid = task->egid; } diff --git a/include/linux/mm.h b/include/linux/mm.h index 6e5d72757d05..48b8dbd14a3c 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -442,6 +442,7 @@ extern int make_pages_present(unsigned long addr, unsigned long end); extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int len); +extern int ptrace_attach(struct task_struct *tsk); /* * On a two-level page table, this ends up being trivial. Thus the diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index bda9f0ae74b6..d32afe265335 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -1,7 +1,7 @@ /* Common Flash Interface structures * See http://support.intel.com/design/flash/technote/index.htm - * $Id: cfi.h,v 1.21 2001/06/03 01:32:57 nico Exp $ + * $Id: cfi.h,v 1.22 2001/07/06 09:29:07 dwmw2 Exp $ */ #ifndef __MTD_CFI_H__ @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 30800c1e9cde..6eb9bc55a276 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #if defined(CONFIG_PROC_FS) @@ -362,6 +363,10 @@ EXPORT_SYMBOL(add_wait_queue); EXPORT_SYMBOL(add_wait_queue_exclusive); EXPORT_SYMBOL(remove_wait_queue); +/* completion handling */ +EXPORT_SYMBOL(wait_for_completion); +EXPORT_SYMBOL(complete); + /* The notion of irq probe/assignment is foreign to S/390 */ #if !defined(CONFIG_ARCH_S390) diff --git a/kernel/ptrace.c b/kernel/ptrace.c index bb094496a904..2b95bad07d92 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -16,6 +16,51 @@ #include #include +int ptrace_attach(struct task_struct *task) +{ + task_lock(task); + if (task->pid <= 1) + goto bad; + if (task == current) + goto bad; + if (!task->mm) + goto bad; + if(((current->uid != task->euid) || + (current->uid != task->suid) || + (current->uid != task->uid) || + (current->gid != task->egid) || + (current->gid != task->sgid) || + (!cap_issubset(task->cap_permitted, current->cap_permitted)) || + (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) + goto bad; + rmb(); + if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) + goto bad; + /* the same process cannot be attached many times */ + if (task->ptrace & PT_PTRACED) + goto bad; + + /* Go */ + task->ptrace |= PT_PTRACED; + task_unlock(task); + + write_lock_irq(&tasklist_lock); + if (task->p_pptr != current) { + REMOVE_LINKS(task); + task->p_pptr = current; + SET_LINKS(task); + } + write_unlock_irq(&tasklist_lock); + + send_sig(SIGSTOP, task, 1); + return 0; + +bad: + task_unlock(task); + return -EPERM; +} + + /* * Access another process' address space, one page at a time. */ -- cgit v1.2.3