]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.10pre3 2.3.10pre3
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:26:01 +0000 (15:26 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:26:01 +0000 (15:26 -0500)
58 files changed:
CREDITS
Documentation/parport.txt
arch/alpha/kernel/ptrace.c
arch/i386/kernel/ptrace.c
arch/sparc/kernel/ptrace.c
arch/sparc/mm/asyncd.c
arch/sparc/mm/fault.c
arch/sparc64/defconfig
arch/sparc64/kernel/psycho.c
arch/sparc64/kernel/sparc64_ksyms.c
arch/sparc64/lib/Makefile
arch/sparc64/lib/atomic.S [new file with mode: 0644]
arch/sparc64/lib/rwlock.S [new file with mode: 0644]
arch/sparc64/mm/asyncd.c
arch/sparc64/mm/fault.c
drivers/ap1000/ringbuf.c
drivers/block/cmd646.c
drivers/char/ftape/lowlevel/ftape-proc.c
drivers/char/tty_io.c
drivers/misc/parport_ax.c
drivers/misc/parport_init.c
drivers/misc/parport_pc.c
drivers/misc/parport_probe.c
drivers/misc/parport_share.c
drivers/net/sunhme.c
drivers/sbus/char/sab82532.c
drivers/sbus/char/su.c
drivers/scsi/ncr53c8xx.c
drivers/usb/ohci-debug.c
drivers/usb/ohci.c
drivers/usb/ohci.h
drivers/usb/printer.c
drivers/usb/uhci.c
drivers/usb/usb.h
fs/devices.c
fs/exec.c
fs/fcntl.c
fs/fifo.c
fs/ioctl.c
fs/open.c
fs/pipe.c
fs/proc/fd.c
fs/proc/inode.c
fs/proc/link.c
fs/select.c
include/asm-sparc/asm_offsets.h
include/asm-sparc/page.h
include/asm-sparc64/asm_offsets.h
include/asm-sparc64/atomic.h
include/asm-sparc64/spinlock.h
include/linux/file.h
include/linux/mm.h
include/linux/parport.h
kernel/Makefile
kernel/exit.c
kernel/fork.c
kernel/ptrace.c [new file with mode: 0644]
net/wanrouter/wanproc.c

diff --git a/CREDITS b/CREDITS
index 745fa36c65fbbdf7c136c8656c68bf8741393f45..5fff6760b10b992b512a147d5542cb4b7a62b187 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -174,6 +174,17 @@ S: ul. Koscielna 12a
 S: 62-300 Wrzesnia
 S: Poland
 
+N: Carlos Henrique Bauer
+E: chbauer@acm.org
+E: bauer@atlas.unisinos.tche.br
+D: A test for detection of EPP-1.7 and ECP/EPP parports.
+D: Some new sysctl entries for the parport driver.
+S: Universidade do Vale do Rio dos Sinos - UNISINOS
+S: DSI/IDASI
+S: Av. Unisinos, 950
+S: 93022000 Sao Leopoldo RS
+S: Brazil
+
 N: Peter Bauer
 E: 100136.3530@compuserve.com
 D: Driver for depca-ethernet-board
index 15e3303c9e86bd89455c4737bf530fa3c8cee3e6..854290f154497440b0a5578a41a6d6c0eae6d086 100644 (file)
@@ -36,10 +36,7 @@ KMod
 ----
 
 If you use kmod, you will find it useful to edit /etc/conf.modules.
-When a driver needs to use the parport subsystem for the first time, a
-module by the name of parport_lowlevel will be automatically loaded
-via kmod.  No module actually exists with that name; it's just an
-alias.  Here is an example of the lines that need to be added:
+Here is an example of the lines that need to be added:
 
        post-install parport modprobe -k parport_pc
        options parport_pc io=0x378,0x278 irq=7,auto
index 3e20e7091a30d8e784cf0959a55fd3eb85eb6baf..b590c0bdbdc8fdf58d1297b1bae6a7abc2b78ee2 100644 (file)
@@ -135,242 +135,18 @@ put_reg(struct task_struct *task, unsigned long regno, long data)
        return 0;
 }
 
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- */
-static unsigned long
-get_long(struct task_struct * tsk, struct vm_area_struct * vma,
-        unsigned long addr)
-{
-       pgd_t * pgdir;
-       pmd_t * pgmiddle;
-       pte_t * pgtable;
-       unsigned long page;
-
-       DBG(DBG_MEM_ALL, ("getting long at 0x%lx\n", addr));
- repeat:
-       pgdir = pgd_offset(vma->vm_mm, addr);
-       if (pgd_none(*pgdir)) {
-               handle_mm_fault(tsk, vma, addr, 0);
-               goto repeat;
-       }
-       if (pgd_bad(*pgdir)) {
-               printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
-               pgd_clear(pgdir);
-               return 0;
-       }
-       pgmiddle = pmd_offset(pgdir, addr);
-       if (pmd_none(*pgmiddle)) {
-               handle_mm_fault(tsk, vma, addr, 0);
-               goto repeat;
-       }
-       if (pmd_bad(*pgmiddle)) {
-               printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
-               pmd_clear(pgmiddle);
-               return 0;
-       }
-       pgtable = pte_offset(pgmiddle, addr);
-       if (!pte_present(*pgtable)) {
-               handle_mm_fault(tsk, vma, addr, 0);
-               goto repeat;
-       }
-       page = pte_page(*pgtable);
-       /* this is a hack for non-kernel-mapped video buffers and similar */
-       if (MAP_NR(page) >= max_mapnr)
-               return 0;
-       page += addr & ~PAGE_MASK;
-       return *(unsigned long *) page;
-}
-
-/*
- * This routine puts a long into any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- *
- * Now keeps R/W state of page so that a text page stays readonly
- * even if a debugger scribbles breakpoints into it.  -M.U-
- */
-static void
-put_long(struct task_struct * tsk, struct vm_area_struct * vma,
-        unsigned long addr, unsigned long data)
-{
-       pgd_t *pgdir;
-       pmd_t *pgmiddle;
-       pte_t *pgtable;
-       unsigned long page;
-
- repeat:
-       pgdir = pgd_offset(vma->vm_mm, addr);
-       if (!pgd_present(*pgdir)) {
-               handle_mm_fault(tsk, vma, addr, 1);
-               goto repeat;
-       }
-       if (pgd_bad(*pgdir)) {
-               printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
-               pgd_clear(pgdir);
-               return;
-       }
-       pgmiddle = pmd_offset(pgdir, addr);
-       if (pmd_none(*pgmiddle)) {
-               handle_mm_fault(tsk, vma, addr, 1);
-               goto repeat;
-       }
-       if (pmd_bad(*pgmiddle)) {
-               printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
-               pmd_clear(pgmiddle);
-               return;
-       }
-       pgtable = pte_offset(pgmiddle, addr);
-       if (!pte_present(*pgtable)) {
-               handle_mm_fault(tsk, vma, addr, 1);
-               goto repeat;
-       }
-       page = pte_page(*pgtable);
-       if (!pte_write(*pgtable)) {
-               handle_mm_fault(tsk, vma, addr, 1);
-               goto repeat;
-       }
-
-       /* This is a hack for non-kernel-mapped video buffers and similar.  */
-       if (MAP_NR(page) < max_mapnr)
-               *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
-
-       /* We're bypassing pagetables, so we have to set the dirty bit
-          ourselves.  This should also re-instate whatever read-only
-          mode there was before.  */
-       set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-       flush_tlb();
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int
-read_long(struct task_struct * tsk, unsigned long addr, unsigned long * result)
-{
-       struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
-       DBG(DBG_MEM_ALL, ("in read_long\n"));
-       if (!vma)
-               return -EIO;
-       if ((addr & ~PAGE_MASK) > (PAGE_SIZE - sizeof(long))) {
-               struct vm_area_struct * vma_high = vma;
-               unsigned long low, align;
-
-               if (addr + sizeof(long) >= vma->vm_end) {
-                       vma_high = vma->vm_next;
-                       if (!vma_high || vma_high->vm_start != vma->vm_end)
-                               return -EIO;
-               }
-               align = addr & (sizeof(long) - 1);
-               addr -= align;
-               low = get_long(tsk, vma, addr);
-               if (align) {
-                       unsigned long high;
-
-                       high = get_long(tsk, vma_high, addr + sizeof(long));
-                       low >>= align * 8;
-                       low  |= high << (64 - align * 8);
-               }
-               *result = low;
-       } else {
-               long l = get_long(tsk, vma, addr);
-
-               DBG(DBG_MEM_ALL, ("value is 0x%lx\n", l));
-               *result = l;
-       }
-       return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int
-write_long(struct task_struct * tsk, unsigned long addr, unsigned long data)
-{
-       struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
-       if (!vma)
-               return -EIO;
-       if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
-               unsigned long low, high, align;
-               struct vm_area_struct * vma_high = vma;
-
-               if (addr + sizeof(long) >= vma->vm_end) {
-                       vma_high = vma->vm_next;
-                       if (!vma_high || vma_high->vm_start != vma->vm_end)
-                               return -EIO;
-               }
-               align = addr & (sizeof(long) - 1);
-               addr -= align;
-               low  = get_long(tsk, vma, addr);
-               high = get_long(tsk, vma_high, addr + sizeof(long));
-               low  &= ~0UL >> (64 - align * 8);
-               high &= ~0UL << (align * 8);
-               low  |= data << (align * 8);
-               high |= data >> (64 - align * 8);
-               put_long(tsk, vma, addr, low);
-               put_long(tsk, vma_high, addr + sizeof(long), high);
-       } else
-               put_long(tsk, vma, addr, data);
-       return 0;
-}
-
-/*
- * Read a 32bit int from address space TSK.
- */
-static int
-read_int(struct task_struct * tsk, unsigned long addr, unsigned int *data)
+static inline int
+read_int(struct task_struct *task, unsigned long addr, int * data)
 {
-       unsigned long l, align;
-       int res;
-
-       align = addr & 0x7;
-       addr &= ~0x7;
-
-       res = read_long(tsk, addr, &l);
-       if (res < 0)
-               return res;
-
-       if (align == 0) {
-               *data = l;
-       } else {
-               *data = l >> 32;
-       }
-       return 0;
+       int copied = access_process_vm(task, addr, data, sizeof(int), 0);
+       return (copied == sizeof(int)) ? 0 : -EIO;
 }
 
-/*
- * Write a 32bit word to address space TSK.
- *
- * For simplicity, do a read-modify-write of the 64bit word that
- * contains the 32bit word that we are about to write.
- */
-static int
-write_int(struct task_struct * tsk, unsigned long addr, unsigned int data)
+static inline int
+write_int(struct task_struct *task, unsigned long addr, int data)
 {
-       unsigned long l, align;
-       int res;
-
-       align = addr & 0x7;
-       addr &= ~0x7;
-
-       res = read_long(tsk, addr, &l);
-       if (res < 0)
-               return res;
-
-       if (align == 0) {
-               l = (l & 0xffffffff00000000UL) | ((unsigned long) data <<  0);
-       } else {
-               l = (l & 0x00000000ffffffffUL) | ((unsigned long) data << 32);
-       }
-       return write_long(tsk, addr, l);
+       int copied = access_process_vm(task, addr, &data, sizeof(int), 1);
+       return (copied == sizeof(int)) ? 0 : -EIO;
 }
 
 /*
@@ -521,16 +297,17 @@ sys_ptrace(long request, long pid, long addr, long data,
        switch (request) {
        /* When I and D space are separate, these will need to be fixed.  */
        case PTRACE_PEEKTEXT: /* read word at location addr. */
-       case PTRACE_PEEKDATA:
-               down(&child->mm->mmap_sem);
-               ret = read_long(child, addr, &tmp);
-               up(&child->mm->mmap_sem);
-               DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
-               if (ret < 0)
+       case PTRACE_PEEKDATA: {
+               unsigned long tmp;
+               int copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+               ret = -EIO;
+               if (copied != sizeof(tmp))
                        goto out;
+               
                regs.r0 = 0;    /* special return: no errors */
                ret = tmp;
                goto out;
+       }
 
        /* Read register number ADDR. */
        case PTRACE_PEEKUSR:
@@ -541,12 +318,12 @@ sys_ptrace(long request, long pid, long addr, long data,
 
        /* When I and D space are separate, this will have to be fixed.  */
        case PTRACE_POKETEXT: /* write the word at location addr. */
-       case PTRACE_POKEDATA:
-               DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data));
-               down(&child->mm->mmap_sem);
-               ret = write_long(child, addr, data);
-               up(&child->mm->mmap_sem);
+       case PTRACE_POKEDATA: {
+               unsigned long tmp = data;
+               int copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
+               ret = (copied == sizeof(tmp)) ? 0 : -EIO;
                goto out;
+       }
 
        case PTRACE_POKEUSR: /* write the specified register */
                DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
index 09664ba815c087c323b9a6aa5f749cd43ff298da..9935cdf53faca9ff07990f7bc21421effc67618c 100644 (file)
@@ -67,205 +67,6 @@ static inline int put_stack_long(struct task_struct *task, int offset,
        return 0;
 }
 
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- */
-static unsigned long get_long(struct task_struct * tsk, 
-       struct vm_area_struct * vma, unsigned long addr)
-{
-       pgd_t * pgdir;
-       pmd_t * pgmiddle;
-       pte_t * pgtable;
-       unsigned long page;
-
-repeat:
-       pgdir = pgd_offset(vma->vm_mm, addr);
-       if (pgd_none(*pgdir)) {
-               handle_mm_fault(tsk, vma, addr, 0);
-               goto repeat;
-       }
-       if (pgd_bad(*pgdir)) {
-               printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
-               pgd_clear(pgdir);
-               return 0;
-       }
-       pgmiddle = pmd_offset(pgdir, addr);
-       if (pmd_none(*pgmiddle)) {
-               handle_mm_fault(tsk, vma, addr, 0);
-               goto repeat;
-       }
-       if (pmd_bad(*pgmiddle)) {
-               printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
-               pmd_clear(pgmiddle);
-               return 0;
-       }
-       pgtable = pte_offset(pgmiddle, addr);
-       if (!pte_present(*pgtable)) {
-               handle_mm_fault(tsk, vma, addr, 0);
-               goto repeat;
-       }
-       page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
-       if (MAP_NR(page) >= max_mapnr)
-               return 0;
-       page += addr & ~PAGE_MASK;
-       return *(unsigned long *) page;
-}
-
-/*
- * This routine puts a long into any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- *
- * Now keeps R/W state of page so that a text page stays readonly
- * even if a debugger scribbles breakpoints into it.  -M.U-
- */
-static void put_long(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long addr,
-       unsigned long data)
-{
-       pgd_t *pgdir;
-       pmd_t *pgmiddle;
-       pte_t *pgtable;
-       unsigned long page;
-
-repeat:
-       pgdir = pgd_offset(vma->vm_mm, addr);
-       if (!pgd_present(*pgdir)) {
-               handle_mm_fault(tsk, vma, addr, 1);
-               goto repeat;
-       }
-       if (pgd_bad(*pgdir)) {
-               printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
-               pgd_clear(pgdir);
-               return;
-       }
-       pgmiddle = pmd_offset(pgdir, addr);
-       if (pmd_none(*pgmiddle)) {
-               handle_mm_fault(tsk, vma, addr, 1);
-               goto repeat;
-       }
-       if (pmd_bad(*pgmiddle)) {
-               printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
-               pmd_clear(pgmiddle);
-               return;
-       }
-       pgtable = pte_offset(pgmiddle, addr);
-       if (!pte_present(*pgtable)) {
-               handle_mm_fault(tsk, vma, addr, 1);
-               goto repeat;
-       }
-       page = pte_page(*pgtable);
-       if (!pte_write(*pgtable)) {
-               handle_mm_fault(tsk, vma, addr, 1);
-               goto repeat;
-       }
-/* this is a hack for non-kernel-mapped video buffers and similar */
-       if (MAP_NR(page) < max_mapnr)
-               *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
-/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
-/* this should also re-instate whatever read-only mode there was before */
-       set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-       flush_tlb();
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int read_long(struct task_struct * tsk, unsigned long addr,
-       unsigned long * result)
-{
-       struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
-       if (!vma)
-               return -EIO;
-       if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
-               unsigned long low,high;
-               struct vm_area_struct * vma_high = vma;
-
-               if (addr + sizeof(long) >= vma->vm_end) {
-                       vma_high = vma->vm_next;
-                       if (!vma_high || vma_high->vm_start != vma->vm_end)
-                               return -EIO;
-               }
-               low = get_long(tsk, vma, addr & ~(sizeof(long)-1));
-               high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
-               switch (addr & (sizeof(long)-1)) {
-                       case 1:
-                               low >>= 8;
-                               low |= high << 24;
-                               break;
-                       case 2:
-                               low >>= 16;
-                               low |= high << 16;
-                               break;
-                       case 3:
-                               low >>= 24;
-                               low |= high << 8;
-                               break;
-               }
-               *result = low;
-       } else
-               *result = get_long(tsk, vma, addr);
-       return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int write_long(struct task_struct * tsk, unsigned long addr,
-       unsigned long data)
-{
-       struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
-       if (!vma)
-               return -EIO;
-       if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
-               unsigned long low,high;
-               struct vm_area_struct * vma_high = vma;
-
-               if (addr + sizeof(long) >= vma->vm_end) {
-                       vma_high = vma->vm_next;
-                       if (!vma_high || vma_high->vm_start != vma->vm_end)
-                               return -EIO;
-               }
-               low = get_long(tsk, vma, addr & ~(sizeof(long)-1));
-               high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
-               switch (addr & (sizeof(long)-1)) {
-                       case 0: /* shouldn't happen, but safety first */
-                               low = data;
-                               break;
-                       case 1:
-                               low &= 0x000000ff;
-                               low |= data << 8;
-                               high &= ~0xff;
-                               high |= data >> 24;
-                               break;
-                       case 2:
-                               low &= 0x0000ffff;
-                               low |= data << 16;
-                               high &= ~0xffff;
-                               high |= data >> 16;
-                               break;
-                       case 3:
-                               low &= 0x00ffffff;
-                               low |= data << 24;
-                               high &= ~0xffffff;
-                               high |= data >> 8;
-                               break;
-               }
-               put_long(tsk, vma, addr & ~(sizeof(long)-1),low);
-               put_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high);
-       } else
-               put_long(tsk, vma, addr, data);
-       return 0;
-}
-
 static int putreg(struct task_struct *child,
        unsigned long regno, unsigned long value)
 {
@@ -402,12 +203,13 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                case PTRACE_PEEKTEXT: /* read word at location addr. */ 
                case PTRACE_PEEKDATA: {
                        unsigned long tmp;
+                       int copied;
 
-                       down(&child->mm->mmap_sem);
-                       ret = read_long(child, addr, &tmp);
-                       up(&child->mm->mmap_sem);
-                       if (ret >= 0)
-                               ret = put_user(tmp,(unsigned long *) data);
+                       copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+                       ret = -EIO;
+                       if (copied != sizeof(tmp))
+                               goto out;
+                       ret = put_user(tmp,(unsigned long *) data);
                        goto out;
                }
 
@@ -436,9 +238,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
       /* when I and D space are separate, this will have to be fixed. */
                case PTRACE_POKETEXT: /* write the word at location addr. */
                case PTRACE_POKEDATA:
-                       down(&child->mm->mmap_sem);
-                       ret = write_long(child,addr,data);
-                       up(&child->mm->mmap_sem);
+                       ret = 0;
+                       if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+                               goto out;
+                       ret = -EIO;
                        goto out;
 
                case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
index 92c8c464f9e32e9aedd9027c323fcbfc5317ad31..bb80f65ee873d0d590602b25aa4dd03b3571b320 100644 (file)
 
 #define MAGIC_CONSTANT 0x80000000
 
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- */
-static unsigned long get_long(struct task_struct * tsk,
-       struct vm_area_struct * vma, unsigned long addr)
-{
-       pgd_t * pgdir;
-       pmd_t * pgmiddle;
-       pte_t * pgtable;
-       unsigned long page, retval;
-
-repeat:
-       pgdir = pgd_offset(vma->vm_mm, addr);
-       if (pgd_none(*pgdir)) {
-               handle_mm_fault(tsk, vma, addr, 0);
-               goto repeat;
-       }
-       if (pgd_bad(*pgdir)) {
-               printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
-               pgd_clear(pgdir);
-               return 0;
-       }
-       pgmiddle = pmd_offset(pgdir, addr);
-       if (pmd_none(*pgmiddle)) {
-               handle_mm_fault(tsk, vma, addr, 0);
-               goto repeat;
-       }
-       if (pmd_bad(*pgmiddle)) {
-               printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
-               pmd_clear(pgmiddle);
-               return 0;
-       }
-       pgtable = pte_offset(pgmiddle, addr);
-       if (!pte_present(*pgtable)) {
-               handle_mm_fault(tsk, vma, addr, 0);
-               goto repeat;
-       }
-       page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
-       if (MAP_NR(page) >= max_mapnr)
-               return 0;
-       page += addr & ~PAGE_MASK;
-       retval = *(unsigned long *) page;
-       flush_page_to_ram(page);
-       return retval;
-}
-
-/*
- * This routine puts a long into any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- *
- * Now keeps R/W state of page so that a text page stays readonly
- * even if a debugger scribbles breakpoints into it.  -M.U-
- */
-static void put_long(struct task_struct * tsk, struct vm_area_struct * vma,
-       unsigned long addr, unsigned long data)
-{
-       pgd_t *pgdir;
-       pmd_t *pgmiddle;
-       pte_t *pgtable;
-       unsigned long page;
-
-repeat:
-       pgdir = pgd_offset(vma->vm_mm, addr);
-       if (!pgd_present(*pgdir)) {
-               handle_mm_fault(tsk, vma, addr, 1);
-               goto repeat;
-       }
-       if (pgd_bad(*pgdir)) {
-               printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
-               pgd_clear(pgdir);
-               return;
-       }
-       pgmiddle = pmd_offset(pgdir, addr);
-       if (pmd_none(*pgmiddle)) {
-               handle_mm_fault(tsk, vma, addr, 1);
-               goto repeat;
-       }
-       if (pmd_bad(*pgmiddle)) {
-               printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
-               pmd_clear(pgmiddle);
-               return;
-       }
-       pgtable = pte_offset(pgmiddle, addr);
-       if (!pte_present(*pgtable)) {
-               handle_mm_fault(tsk, vma, addr, 1);
-               goto repeat;
-       }
-       page = pte_page(*pgtable);
-       if (!pte_write(*pgtable)) {
-               handle_mm_fault(tsk, vma, addr, 1);
-               goto repeat;
-       }
-/* this is a hack for non-kernel-mapped video buffers and similar */
-       flush_cache_page(vma, addr);
-       if (MAP_NR(page) < max_mapnr) {
-               *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
-               flush_page_to_ram(page);
-       }
-/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
-/* this should also re-instate whatever read-only mode there was before */
-       set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-       flush_tlb_page(vma, addr);
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int read_long(struct task_struct * tsk, unsigned long addr,
-                    unsigned long * result)
-{
-       struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
-       if (!vma)
-               return -EIO;
-       *result = get_long(tsk, vma, addr);
-       return 0;
-}
-
-static int read_byte(struct task_struct *tsk, unsigned long addr,
-                    unsigned char *result)
-{
-       struct vm_area_struct *vma = find_extend_vma(tsk, addr&~3);
-       unsigned long tmp;
-
-       if(!vma)
-               return -EIO;
-       tmp = get_long(tsk, vma, (addr & ~3));
-       switch(addr & 3) {
-       case 0:
-               *result = (tmp & 0xff000000)>>24;
-               break;
-       case 1:
-               *result = (tmp & 0x00ff0000)>>16;
-               break;
-       case 2:
-               *result = (tmp & 0x0000ff00)>>8;
-               break;
-       case 3:
-               *result = (tmp & 0x000000ff);
-               break;
-       }
-       return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int write_long(struct task_struct * tsk, unsigned long addr,
-                     unsigned long data)
-{
-       struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
-       if (!vma)
-               return -EIO;
-       put_long(tsk, vma, addr, data);
-       return 0;
-}
-
-static int write_byte(struct task_struct * tsk, unsigned long addr,
-                     unsigned char data)
-{
-       struct vm_area_struct * vma = find_extend_vma(tsk, (addr & ~3));
-       unsigned long tmp;
-
-       if (!vma)
-               return -EIO;
-       tmp = get_long(tsk, vma, (addr & ~3));
-       switch(addr & 3) {
-       case 0:
-               tmp &= 0x00ffffff;
-               tmp |= (data << 24);
-               break;
-       case 1:
-               tmp &= 0xff00ffff;
-               tmp |= ((data << 16) & 0x00ff0000);
-               break;
-       case 2:
-               tmp &= 0xffff00ff;
-               tmp |= ((data << 8) & 0x0000ff00);
-               break;
-       case 3:
-               tmp &= 0xffffff00;
-               tmp |= (data & 0x000000ff);
-               break;
-       }
-       put_long(tsk, vma, (addr & ~3), tmp);
-       return 0;
-}
 
 /* Returning from ptrace is a bit tricky because the syscall return
  * low level code assumes any value returned which is negative and
@@ -737,56 +541,31 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
 
        case PTRACE_READTEXT:
        case PTRACE_READDATA: {
-               unsigned char *dest = (unsigned char *) addr2;
-               unsigned long src = addr;
-               unsigned char tmp;
-               int res, len = data;
+               int res = ptrace_readdata(child, addr, (void *) addr2, data);
 
-               res = verify_area(VERIFY_WRITE, dest, len);
-               if(res) {
-                       pt_error_return(regs, -res);
+               if (res == data) {
+                       pt_succ_return(regs, 0);
                        goto out;
                }
-               while(len) {
-                       down(&child->mm->mmap_sem);
-                       res = read_byte(child, src, &tmp);
-                       up(&child->mm->mmap_sem);
-                       if(res < 0) {
-                               pt_error_return(regs, -res);
-                               goto out;
-                       }
-                       __put_user(tmp, dest);
-                       src++; dest++; len--;
-               }
-               pt_succ_return(regs, 0);
+               /* Partial read is an IO failure */
+               if (res >= 0)
+                       res = -EIO;
+               pt_error_return(regs, -res);
                goto out;
        }
 
        case PTRACE_WRITETEXT:
        case PTRACE_WRITEDATA: {
-               unsigned char *src = (unsigned char *) addr2;
-               unsigned long dest = addr;
-               int res, len = data;
+               int res = ptrace_writedata(child, (void *) addr2, addr, data);
 
-               res = verify_area(VERIFY_READ, src, len);
-               if(res) {
-                       pt_error_return(regs, -res);
+               if (res == data) {
+                       pt_succ_return(regs, 0);
                        goto out;
                }
-               while(len) {
-                       unsigned long tmp;
-
-                       __get_user(tmp, src);
-                       down(&child->mm->mmap_sem);
-                       res = write_byte(child, dest, tmp);
-                       up(&child->mm->mmap_sem);
-                       if(res < 0) {
-                               pt_error_return(regs, -res);
-                               goto out;
-                       }
-                       src++; dest++; len--;
-               }
-               pt_succ_return(regs, 0);
+               /* Partial write is an IO failure */
+               if (res >= 0)
+                       res = -EIO;
+               pt_error_return(regs, -res);
                goto out;
        }
 
index 1ae532b7c6eb6efc30b5854eef9bdb367cd70260..300f5aa0adad507888de80d99d164f73dd266ffd 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: asyncd.c,v 1.13 1999/05/12 11:11:34 davem Exp $
+/*  $Id: asyncd.c,v 1.15 1999/07/04 04:35:50 davem Exp $
  *  The asyncd kernel daemon. This handles paging on behalf of 
  *  processes that receive page faults due to remote (async) memory
  *  accesses. 
index a6110b8863f9fa6e58e4d99183406cb1b499d8e8..87f056c2ec0addf1c2b1618dbd00b7d4c66d5d2e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.101 1999/01/04 06:24:52 jj Exp $
+/* $Id: fault.c,v 1.103 1999/07/04 04:35:51 davem Exp $
  * fault.c:  Page fault handlers for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
index 8e3402e2c6eece0e59aa602b956b5cc2dd4e62db..9a616445782f6341306caa0308aaaa1d97d6d6c7 100644 (file)
@@ -93,11 +93,13 @@ CONFIG_BINFMT_ELF32=y
 CONFIG_BINFMT_MISC=m
 CONFIG_SOLARIS_EMUL=m
 CONFIG_PARPORT=m
-CONFIG_PARPORT_AX=m
-CONFIG_PARPORT_LOWLEVEL_MODULE=y
+# CONFIG_PARPORT_PC is not set
+# CONFIG_PARPORT_AMIGA is not set
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_ATARI is not set
 # CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
 CONFIG_PRINTER=m
-CONFIG_PRINTER_READBACK=y
 CONFIG_ENVCTRL=m
 
 #
index 7df9a58822233d6e6f238bca256f028aacf9445f..6baf5958b261a1aefb83bcc541982b8bde4991fa 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: psycho.c,v 1.85 1999/04/02 14:54:28 davem Exp $
+/* $Id: psycho.c,v 1.86 1999/07/01 10:39:43 davem Exp $
  * psycho.c: Ultra/AX U2P PCI controller support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu)
@@ -757,13 +757,15 @@ static void __init apb_init(struct linux_psycho *sabre)
        unsigned short stmp;
        unsigned int itmp;
 
+#if 0
        for(pdev = pci_devices; pdev; pdev = pdev->next) {
                if(pdev->vendor == PCI_VENDOR_ID_SUN &&
                   pdev->device == PCI_DEVICE_ID_SUN_SABRE) {
-                       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
+                       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
                        break;
                }
        }
+#endif
        for (pdev = sabre->pci_bus->devices; pdev; pdev = pdev->sibling) {
                if (pdev->vendor == PCI_VENDOR_ID_SUN &&
                    pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
@@ -795,13 +797,14 @@ static void __init apb_init(struct linux_psycho *sabre)
                        pci_read_config_dword(pdev, APB_PCI_CONTROL_LOW, &itmp);
                        itmp = APB_PCI_CTL_LOW_ERRINT_EN | 0x0f;
                        pci_write_config_dword(pdev, APB_PCI_CONTROL_LOW, itmp);
-
+#if 0
                        /* Don't mess with the retry limit and PIO/DMA latency
                         * timer settings.  But do set primary and secondary
                         * latency timers.
                         */
-                       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
-                       pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 128);
+                       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+                       pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64);
+#endif
                }
        }
 }
index 18d9d44beb5f3903ebab231edef01b9a45579d06..9eca01cca175ea83f7523a0c38ea40b6d262adb1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.59 1999/06/28 11:28:50 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.60 1999/07/03 22:11:12 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -118,6 +118,12 @@ __attribute__((section("__ksymtab"))) =                            \
 
 /* used by various drivers */
 #ifdef __SMP__
+/* Out of line rw-locking implementation. */
+EXPORT_SYMBOL_PRIVATE(read_lock);
+EXPORT_SYMBOL_PRIVATE(read_unlock);
+EXPORT_SYMBOL_PRIVATE(write_lock);
+EXPORT_SYMBOL_PRIVATE(write_unlock);
+
 /* Kernel wide locking */
 EXPORT_SYMBOL(kernel_flag);
 
@@ -158,6 +164,10 @@ EXPORT_SYMBOL(local_irq_count);
 EXPORT_SYMBOL(local_bh_count);
 #endif
 
+/* Atomic counter implementation. */
+EXPORT_SYMBOL_PRIVATE(atomic_add);
+EXPORT_SYMBOL_PRIVATE(atomic_sub);
+
 EXPORT_SYMBOL(ivector_table);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
index 2a3c63e9121e2f51b6e5cf43594620de9b233317..90d1c4e7c79136b27c037d74ecfde8c652c078e4 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.18 1998/10/13 09:07:24 davem Exp $
+# $Id: Makefile,v 1.19 1999/07/03 22:11:08 davem Exp $
 # Makefile for Sparc library files..
 #
 
@@ -6,7 +6,8 @@ CFLAGS := $(CFLAGS)
 
 OBJS  = PeeCeeI.o blockops.o debuglocks.o strlen.o strncmp.o \
        memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \
-       VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o VISsave.o
+       VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o VISsave.o \
+       atomic.o rwlock.o
 
 lib.a: $(OBJS)
        $(AR) rcs lib.a $(OBJS)
diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S
new file mode 100644 (file)
index 0000000..3c0dce1
--- /dev/null
@@ -0,0 +1,32 @@
+/* $Id: atomic.S,v 1.1 1999/07/03 22:11:04 davem Exp $
+ * atomic.S: These things are too big to do inline.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include <asm/asi.h>
+
+       .text
+       .align  64
+
+       .globl  __atomic_add
+__atomic_add:
+       lduw    [%g1], %g5
+       add     %g5, %g2, %g7
+       cas     [%g1], %g5, %g7
+       cmp     %g5, %g7
+       bne,pn  %icc, __atomic_add
+        nop
+       jmpl    %g3 + 8, %g0
+        add    %g7, %g2, %g2
+
+       .globl  __atomic_sub
+__atomic_sub:
+       lduw    [%g1], %g5
+       sub     %g5, %g2, %g7
+       cas     [%g1], %g5, %g7
+       cmp     %g5, %g7
+       bne,pn  %icc, __atomic_sub
+        nop
+       jmpl    %g3 + 8, %g0
+        sub    %g7, %g2, %g2
diff --git a/arch/sparc64/lib/rwlock.S b/arch/sparc64/lib/rwlock.S
new file mode 100644 (file)
index 0000000..cee94ee
--- /dev/null
@@ -0,0 +1,81 @@
+/* $Id: rwlock.S,v 1.1 1999/07/03 22:11:06 davem Exp $
+ * rwlocks.S: These things are too big to do inline.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+       .text
+       .align  64
+
+       /* The non-contention read lock usage is 2 cache lines. */
+
+       .globl  __read_lock, __read_unlock
+       /* g1=lock, g3=retpc, g5/g7=scratch */
+__read_lock:
+       ldsw            [%g1], %g5
+       brlz,pn         %g5, __read_wait_for_writer
+4:      add            %g5, 1, %g7
+       cas             [%g1], %g5, %g7
+       cmp             %g5, %g7
+       bne,pn          %icc, __read_lock
+        membar         #StoreLoad | #StoreStore
+99:    jmpl            %g3 + 8, %g0
+        nop
+__read_unlock:
+       lduw            [%g1], %g5
+       sub             %g5, 1, %g7
+       cas             [%g1], %g5, %g7
+       cmp             %g5, %g7
+       be,pt           %xcc, 99b
+        membar         #StoreLoad | #StoreStore
+       b,a,pt          %xcc, __read_unlock
+
+__read_wait_for_writer:
+       ldsw            [%g1], %g5
+       brlz,pt         %g5, __read_wait_for_writer
+        membar         #LoadLoad
+       b,a,pt          %xcc, 4b
+__write_wait_for_writer:
+       ldsw            [%g1], %g5
+       brlz,pt         %g5, __write_wait_for_writer
+        membar         #LoadLoad
+       b,a,pt          %xcc, 4f
+
+       /* Similarly, 2 cache lines for non-contention write locks. */
+
+       .align          64
+       .globl          __write_unlock
+       /* g1=lock, g3=retpc, g2/g5/g7=scratch */
+__write_unlock:
+       sethi           %hi(0x80000000), %g2
+1:     lduw            [%g1], %g5
+       andn            %g5, %g2, %g7
+       cas             [%g1], %g5, %g7
+       cmp             %g5, %g7
+       be,pt           %icc, 99b
+        membar         #StoreLoad | #StoreStore
+       b,a,pt          %xcc, 1b
+
+       .globl          __write_lock
+__write_lock:
+       sethi           %hi(0x80000000), %g2
+1:     ldsw            [%g1], %g5
+4:     brnz,pn         %g5, 5f
+        or             %g5, %g2, %g7
+       cas             [%g1], %g5, %g7
+       cmp             %g5, %g7
+       be,pt           %icc, 99b
+        membar         #StoreLoad | #StoreStore
+
+       b,a,pt          %xcc, 1b
+5:     brlz            %g5, __write_wait_for_writer
+       or              %g5, %g2, %g7
+       cas             [%g1], %g5, %g7
+       cmp             %g5, %g7
+       bne,pn          %icc, 5b
+8:      ldsw           [%g1], %g5
+       cmp             %g5, %g2
+       be,pn           %icc, 99b
+        membar         #LoadLoad
+       b,a,pt          %xcc, 99b
+
index d1c7f5d201f6438e823ed96b074c026e92f7a154..e9607cb8f819c2f600d8a82fce182b3eb51e2cce 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: asyncd.c,v 1.6 1999/05/12 11:11:48 davem Exp $
+/*  $Id: asyncd.c,v 1.8 1999/07/04 04:35:55 davem Exp $
  *  The asyncd kernel daemon. This handles paging on behalf of 
  *  processes that receive page faults due to remote (async) memory
  *  accesses. 
index 88fd55e0327af7e72c6a485794ffdf18a03d066c..04aa8284e6638b8bbd580c3b3c75f2b385e19474 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.34 1999/03/16 12:12:28 jj Exp $
+/* $Id: fault.c,v 1.36 1999/07/04 04:35:56 davem Exp $
  * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
index 69682437ed019c175c30ae34fa7b67d02c102125..49c71673220db9b8588d78b5a9250cca56cf23f0 100644 (file)
@@ -318,6 +318,7 @@ struct inode_operations proc_ringbuf_inode_operations = {
        NULL,                   /* mknod */
        NULL,                   /* rename */
        NULL,                   /* readlink */
+       NULL,                   /* follow_link */
        NULL,                   /* get_block */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
index 4775093fb20d7663d397b25678839000fa57d959..1a1d5a7335911d06f62d27bea879e3d1cfa5ec73 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: cmd646.c,v 1.13 1999/05/27 04:49:38 davem Exp $
+/* $Id: cmd646.c,v 1.14 1999/07/03 08:56:09 davem Exp $
  * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines.
  *           Note, this driver is not used at all on other systems because
  *           there the "BIOS" has done all of the following already.
index ef91ff6c985f9e2bcff96773441e4e44eb8ca82b..7ba77804857e8afde4822209d9e2c3e04fc104cf 100644 (file)
@@ -112,6 +112,7 @@ static struct inode_operations ftape_proc_inode_operations =
        NULL,                   /* mknod */
        NULL,                   /* rename */
        NULL,                   /* readlink */
+       NULL,                   /* follow_link */
        NULL,                   /* get_block */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
index d0ceb78fe15b4f203d73b3b43eaf3e8911e740cf..62ec86628bc414e1d6645c994a10a63f0e9d3902 100644 (file)
@@ -1790,6 +1790,10 @@ int tty_ioctl(struct inode * inode, struct file * file,
  * have to coordinate with the init process, since all processes associated
  * with the current tty must be dead before the new getty is allowed
  * to spawn.
+ *
+ * Now, if it would be correct ;-/ The current code has a nasty hole -
+ * it doesn't catch files in flight. We may send the descriptor to ourselves
+ * via AF_UNIX socket, close it and later fetch from socket. FIXME.
  */
 void do_SAK( struct tty_struct *tty)
 {
@@ -1814,6 +1818,7 @@ void do_SAK( struct tty_struct *tty)
                    ((session > 0) && (p->session == session)))
                        send_sig(SIGKILL, p, 1);
                else if (p->files) {
+                       read_lock(&p->files->file_lock);
                        for (i=0; i < p->files->max_fds; i++) {
                                filp = fcheck_task(p, i);
                                if (filp && (filp->f_op == &tty_fops) &&
@@ -1822,6 +1827,7 @@ void do_SAK( struct tty_struct *tty)
                                        break;
                                }
                        }
+                       read_unlock(&p->files->file_lock);
                }
        }
        read_unlock(&tasklist_lock);
index 40ef8d0d9e1c9e1345244d59014b1fb6ad49bd41..dfa057feec72d64f3c7b231dc9da71906beb5ad0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: parport_ax.c,v 1.19 1999/06/09 08:24:40 davem Exp $
+/* $Id: parport_ax.c,v 1.20 1999/07/03 08:56:21 davem Exp $
  * Parallel-port routines for Sun Ultra/AX architecture
  * 
  * Author: Eddie C. Dost <ecd@skynet.be>
index 974dcf7253fa41cdb8a4ecc65a91cdf0ef5a85fd..18c3fde0df052aeed14ccdc732e056de0fc56863 100644 (file)
@@ -184,7 +184,7 @@ EXPORT_SYMBOL(parport_default_proc_register);
 EXPORT_SYMBOL(parport_default_proc_unregister);
 EXPORT_SYMBOL(parport_parse_irqs);
 EXPORT_SYMBOL(parport_parse_dmas);
-#ifdef CONFIG_PARPORT_12843
+#ifdef CONFIG_PARPORT_1284
 EXPORT_SYMBOL(parport_open);
 EXPORT_SYMBOL(parport_close);
 EXPORT_SYMBOL(parport_device_id);
index bfba506ea3c3b03ac64b2c2ab8045c0401c91a2b..f9db1830eaf224a4352adfe484c26c29a51c1b44 100644 (file)
@@ -1313,17 +1313,16 @@ static int __init parport_EPP_supported(struct parport *pb)
        clear_epp_timeout(pb);
        udelay(30); /* Wait for possible EPP timeout */
 
-       /* Enable outputs. */
+       /* We must enable the outputs to be able to read the address
+       register. */
+
        parport_pc_data_forward (pb);
+
        outb (0x55, EPPADDR (pb));
 
        clear_epp_timeout(pb);
        udelay(30); /* Wait for possible EPP timeout */
 
-       /* We must enable the outputs to be able to read the address
-           register. */
-       parport_pc_data_forward (pb);
-
        if (inb (EPPADDR (pb)) == 0x55) {
                clear_epp_timeout(pb);
                udelay(30); /* Wait for possible EPP timeout */
@@ -1594,8 +1593,8 @@ static int __init probe_one_port(unsigned long int base,
 
        parport_PS2_supported (p);
 
-               if (!(p = parport_register_port(base, PARPORT_IRQ_NONE,
-                                       PARPORT_DMA_NONE, &parport_pc_ops))) {
+       if (!(p = parport_register_port(base, PARPORT_IRQ_NONE,
+                                                                       PARPORT_DMA_NONE, &parport_pc_ops))) {
                kfree (priv);
                return 0;
        }
@@ -1663,7 +1662,9 @@ static int __init probe_one_port(unsigned long int base,
                printk("%s: irq %d detected\n", p->name, probedirq);
        parport_proc_register(p);
 
-       request_region (p->base, p->size, p->name);
+       request_region (p->base, 3, p->name);
+       if (p->size > 3)
+               request_region (p->base + 3, p->size - 3, p->name);
        if (p->modes & PARPORT_MODE_ECP)
                request_region (p->base_hi, 3, p->name);
 
@@ -1915,7 +1916,9 @@ void cleanup_module(void)
                                free_dma(p->dma);
                        if (p->irq != PARPORT_IRQ_NONE)
                                free_irq(p->irq, p);
-                       release_region(p->base, p->size);
+                       release_region(p->base, 3);
+                       if (p->size > 3);
+                               release_region(p->base + 3, p->size - 3);
                        if (p->modes & PARPORT_MODE_ECP)
                                release_region(p->base_hi, 3);
                        parport_proc_unregister(p);
index a5b1524bdefd15c6f73d7eebe91b22c96a3b4f1a..a3c24c989c45df9f54755497044c2a6e086170ef 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: parport_probe.c,v 1.3 1997/10/19 18:18:46 phil Exp $
+/* $Id: parport_probe.c,v 1.1 1999/07/03 08:56:17 davem Exp $
  * Parallel port device probing code
  *
  * Authors:    Carsten Gross, carsten@sol.wohnheim.uni-ulm.de
index 0ca126a41c64dc64feda496a3105653d2013cab8..b5b9ff9d47b1991652cc2d16376a96a5b97e2bdc 100644 (file)
 #undef PARPORT_DEBUG_SHARING           /* undef for production */
 
 #include <linux/config.h>
-
 #include <linux/string.h>
-
 #include <linux/tasks.h>
-
 #include <linux/parport.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <asm/spinlock.h>
 #include <asm/irq.h>
 
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
 #undef PARPORT_PARANOID
 
 #define PARPORT_DEFAULT_TIMESLICE      (HZ/5)
@@ -97,11 +90,6 @@ void parport_unregister_driver (struct parport_driver *arg)
 /* Return a list of all the ports we know about. */
 struct parport *parport_enumerate(void)
 {
-#ifdef CONFIG_KMOD
-       if (portlist == NULL) {
-               request_module("parport_lowlevel");
-       }
-#endif /* CONFIG_KMOD */
        return portlist;
 }
 
index 1cc57315b1444c45b42972be93e09fc0972ac3f2..86ce459515ce487b1b01a4c6d05378d7be4d7290 100644 (file)
@@ -3406,7 +3406,7 @@ static int __init happy_meal_pci_init(struct device *dev, struct pci_dev *pdev)
        /* Set the latency timer and cache line size as well,
         * PROM leaves it at zero.
         */
-       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
+       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
 #ifdef __sparc_v9__
        /* NOTE: Cache line size is in 32-bit word units. */
        pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x10);
index f2b0df9c5e9c36d31e30bc49d6df4d92049e2670..1387a6f15bba62e0b46115f1c84e9c0891f690aa 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.31 1999/05/12 11:15:10 davem Exp $
+/* $Id: sab82532.c,v 1.32 1999/07/03 08:57:41 davem Exp $
  * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -2135,7 +2135,7 @@ sab82532_kgdb_hook(int line))
 
 __initfunc(static inline void show_serial_version(void))
 {
-       char *revision = "$Revision: 1.31 $";
+       char *revision = "$Revision: 1.32 $";
        char *version, *p;
 
        version = strchr(revision, ' ');
index 7aacd3291728e9b6e4949f6e0153e4477d1bc0f6..b1c95163cdc477ad51b7c8a4021c877f55422dfd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.21 1999/06/11 10:23:42 davem Exp $
+/* $Id: su.c,v 1.22 1999/07/03 08:57:43 davem Exp $
  * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -2214,7 +2214,7 @@ done:
  */
 __initfunc(static __inline__ void show_su_version(void))
 {
-       char *revision = "$Revision: 1.21 $";
+       char *revision = "$Revision: 1.22 $";
        char *version, *p;
 
        version = strchr(revision, ' ');
index 80a79016eab0be8cc367f624bf1340d33f94b3d9..637e6f960c9fb40906574fa06d2556f6744b64e1 100644 (file)
@@ -9858,7 +9858,7 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
        }
 
        if (!latency_timer) {
-               latency_timer = 128;
+               latency_timer = 64;
                if (initverbose >= 2)
                        printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fixup)\n", latency_timer);
                pcibios_write_config_byte(bus, device_fn,
index 56b9fff0afdc8b79244c55260ef2ab1b096a296e..8bf2736921bb737e8dc24307f06a830ebe3fd37e 100644 (file)
@@ -119,10 +119,9 @@ void show_ohci_td(struct ohci_td *td)
                (td_toggle < 2) ? " " :
                (td_toggle & 1) ? "Data1" : "Data0",
                "ErrorCnt ", td_errcnt);
-       printk(KERN_DEBUG "        ComplCode 0x%x, %sAccessed, %sActive\n",
+       printk(KERN_DEBUG "        ComplCode 0x%x, %sAccessed\n",
                td_cc,
-               td_cc_accessed(*td) ? "" : "Not ",
-               td_active(*td) ? "" : "Not ");
+               td_cc_accessed(*td) ? "" : "Not ");
 
        printk(KERN_DEBUG "        %s%s\n",
                td_allocated(*td) ? "Allocated" : "Free",
@@ -159,7 +158,7 @@ void show_ohci_td_chain(struct ohci_td *td)
                if (td_dummy(*cur_td)) break;
        }
 
-       printk(KERN_DEBUG "--- End  TD Chain %lx: ---\n", virt_to_bus(td));
+       printk(KERN_DEBUG "--- End  TD Chain %lx. ---\n", virt_to_bus(td));
 } /* show_ohci_td_chain () */
 
 
index 261306949d997c4d6dd90d45e455cd0e7f9015d9..c768b32856eea3b13db7a4662eb2d030780e2edd 100644 (file)
@@ -179,27 +179,27 @@ static struct ohci_td *ohci_add_td_chain_to_ed(struct ohci_td *td, struct ohci_e
 /* .......... */
 
 
-inline void ohci_start_control(struct ohci *ohci)
+void ohci_start_control(struct ohci *ohci)
 {
        /* tell the HC to start processing the control list */
        writel_set(OHCI_USB_CLE, &ohci->regs->control);
        writel_set(OHCI_CMDSTAT_CLF, &ohci->regs->cmdstatus);
 }
 
-inline void ohci_start_bulk(struct ohci *ohci)
+void ohci_start_bulk(struct ohci *ohci)
 {
        /* tell the HC to start processing the bulk list */
        writel_set(OHCI_USB_BLE, &ohci->regs->control);
        writel_set(OHCI_CMDSTAT_BLF, &ohci->regs->cmdstatus);
 }
 
-inline void ohci_start_periodic(struct ohci *ohci)
+void ohci_start_periodic(struct ohci *ohci)
 {
        /* enable processing periodic (intr) transfers starting next frame */
        writel_set(OHCI_USB_PLE, &ohci->regs->control);
 }
 
-inline void ohci_start_isoc(struct ohci *ohci)
+void ohci_start_isoc(struct ohci *ohci)
 {
        /* enable processing isoc. transfers starting next frame */
        writel_set(OHCI_USB_IE, &ohci->regs->control);
@@ -658,7 +658,7 @@ void ohci_free_ed(struct ohci_ed *ed)
  *     dir = OHCI_TD_D_IN, OHCI_TD_D_OUT, or OHCI_TD_D_SETUP
  *     toggle = TOGGLE_AUTO, TOGGLE_DATA0, TOGGLE_DATA1
  */
-inline struct ohci_td *ohci_fill_new_td(struct ohci_td *td, int dir, int toggle, __u32 flags, void *data, __u32 len, void *dev_id, usb_device_irq completed)
+struct ohci_td *ohci_fill_new_td(struct ohci_td *td, int dir, int toggle, __u32 flags, void *data, __u32 len, void *dev_id, usb_device_irq completed)
 {
        /* hardware fields */
        td->info = cpu_to_le32(OHCI_TD_CC_NEW |
@@ -846,16 +846,20 @@ static __u16 ohci_td_bytes_done(struct ohci_td *td)
                return 0;
 
        /* if cur_buf is 0, all data has been transferred */
-       bus_data_end = td->cur_buf ? td->cur_buf : td->buf_end;
+       if (!td->cur_buf) {
+               return td->buf_end - bus_data_start + 1;
+       }
+
+       bus_data_end = td->cur_buf;
 
        /* is it on the same page? */
        if ((bus_data_start & ~0xfff) == (bus_data_end & ~0xfff)) {
-               result = bus_data_end - bus_data_start + 1;
+               result = bus_data_end - bus_data_start;
        } else {
                /* compute the amount transferred on the first page */
                result = 0x1000 - (bus_data_start & 0xfff);
                /* add the amount done in the second page */
-               result += (bus_data_end & 0xfff) + 1;
+               result += (bus_data_end & 0xfff);
        }
 
        return result;
@@ -1190,16 +1194,12 @@ static int ohci_bulk_td_handler(int stats, void *buffer, int len, void *dev_id)
        if (stats == USB_ST_NOERROR)
                req->_bytes_done += len;
 
-#ifdef OHCI_DEBUG
-       printk(KERN_DEBUG "ohci_bulk_td_handler %d bytes done\n", req->_bytes_done);
-#endif
-
        /* call the real completion handler when done or on an error */
        if ((stats != USB_ST_NOERROR) ||
            (req->_bytes_done >= req->length && req->completion != NULL)) {
                *req->bytes_transferred_p += req->_bytes_done;
 #ifdef OHCI_DEBUG
-               printk(KERN_DEBUG "usb-ohci: bulk request %p ending after %d bytes\n", req, req->_bytes_done);
+               printk(KERN_DEBUG "usb-ohci: bulk request %p ending\n", req);
 #endif
                req->completion(stats, buffer, req->_bytes_done, req->dev_id);
        }
@@ -1282,13 +1282,13 @@ static struct ohci_ed* ohci_request_bulk(struct ohci_bulk_request_state *bulk_re
 
 
 #ifdef OHCI_DEBUG
-/*     if (MegaDebug) { */
-       /* complete transaction debugging output (before) */
+       if (MegaDebug) {
+       /* complete request debugging output (before) */
        printk(KERN_DEBUG " Bulk ED %lx:\n", virt_to_bus(bulk_ed));
        show_ohci_ed(bulk_ed);
        printk(KERN_DEBUG " Bulk TDs %lx:\n", virt_to_bus(head_td));
        show_ohci_td_chain(head_td);
-/*     } */
+       }
 #endif
 
        /* Give the ED to the HC */
@@ -1303,6 +1303,9 @@ static DECLARE_WAIT_QUEUE_HEAD(bulk_wakeup);
 
 static int ohci_bulk_msg_completed(int stats, void *buffer, int len, void *dev_id)
 {
+#ifdef OHCI_DEBUG
+       printk("ohci_bulk_msg_completed %x, %p, %d, %p\n", stats, buffer, len, dev_id);
+#endif
        if (dev_id != NULL) {
                int *completion_status = (int *)dev_id;
                *completion_status = stats;
@@ -1320,12 +1323,15 @@ static int ohci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
        struct ohci_bulk_request_state req;
        struct ohci_ed *req_ed;
 
-       /* ....... */
-
 #ifdef OHCI_DEBUG 
        printk(KERN_DEBUG "ohci_bulk_msg %p pipe %x, data %p, len %d, bytes_transferred %p\n", usb_dev, pipe, data, len, bytes_transferred_p);
 #endif
 
+       /* initialize bytes transferred to nothing */
+       *bytes_transferred_p = 0;
+
+       /* Hopefully this is similar to the "URP" (USB Request Packet) code
+        * that michael gee is working on... */
        req.usb_dev = usb_dev;
        req.pipe = pipe;
        req.data = data;
@@ -1345,9 +1351,44 @@ static int ohci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
        /* FIXME this should to wait for a caller specified time... */
        schedule_timeout(HZ*5);
 
+       /* it'll only stay in this state of the request never finished */
+       if (completion_status == USB_ST_INTERNALERROR) {
+               struct ohci_device *dev = usb_to_ohci(usb_dev);
+               struct ohci_regs *regs = dev->ohci->regs;
+
 #ifdef OHCI_DEBUG
-       printk(KERN_DEBUG "ohci_bulk_msg request completed or timed out w/ status %x\n", completion_status);
+               printk(KERN_DEBUG "ohci_bulk_msg timing out\n");
 #endif
+               /* XXX This code should go into a function used to stop
+                * a previously requested bulk transfer. -greg */
+
+               /* stop the transfer & collect the number of bytes */
+               ohci_wait_for_ed_safe(regs, req_ed, HCD_ED_BULK);
+
+               /* Get the number of bytes transferred out of the head TD
+                * on the ED if it didn't finish while we were waiting. */
+               if ( ed_head_td(req_ed) &&
+                    (ed_head_td(req_ed) != ed_tail_td(req_ed)) ) {
+                       struct ohci_td *partial_td;
+                       partial_td = bus_to_virt(ed_head_td(req_ed));
+
+#ifdef OHCI_DEBUG
+                       if (MegaDebug) {
+                       show_ohci_td(partial_td);
+                       }
+#endif
+                       /* Record the bytes as transferred */
+                       *bytes_transferred_p += ohci_td_bytes_done(partial_td);
+                       
+                       /* If there was an unreported error, return it.
+                        * Otherwise return a timeout */
+                       completion_status = OHCI_TD_CC_GET(partial_td->info);
+                       if (completion_status == USB_ST_NOERROR) {
+                               completion_status = USB_ST_TIMEOUT;
+                       }
+               }
+
+       }
 
        remove_wait_queue(&bulk_wakeup, &wait);
 
@@ -1356,7 +1397,7 @@ static int ohci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
        ohci_free_ed(req_ed);    /* return it to the pool */
 
 #ifdef OHCI_DEBUG
-       printk(KERN_DEBUG "ohci_bulk_msg done.\n");
+       printk(KERN_DEBUG "ohci_bulk_msg done, status %x (bytes_transferred = %ld).\n", completion_status, *bytes_transferred_p);
 #endif
 
        return completion_status;
@@ -1761,7 +1802,7 @@ static void ohci_reap_donelist(struct ohci *ohci)
        struct ohci_td *td;             /* used for walking the list */
 
        /* um... isn't this dangerous to do in an interrupt handler? -greg */
-       spin_lock(&ohci_edtd_lock);
+//     spin_lock(&ohci_edtd_lock);
 
        /* create the FIFO ordered donelist */
        td = ohci_reverse_donelist(ohci);
@@ -1832,6 +1873,7 @@ static void ohci_reap_donelist(struct ohci *ohci)
 
                        /* insert it back on its ED */
                        ohci_add_td_to_ed(td, td, td->ed);
+                       ohci_unhalt_ed(td->ed);
                } else {
                        /* return it to the pool of free TDs */
                        if (can_auto_free(*td))
@@ -1841,7 +1883,7 @@ static void ohci_reap_donelist(struct ohci *ohci)
                td = next_td;
        }
 
-       spin_unlock(&ohci_edtd_lock);
+//     spin_unlock(&ohci_edtd_lock);
 } /* ohci_reap_donelist() */
 
 
index 88b08750fed57bf2540aeaea6ee37f14761ae2eb..09e609725208e6741f95e33251cb9c9004911612 100644 (file)
@@ -71,7 +71,6 @@ struct ohci_td {
 #define td_cc_notaccessed(td)  ((le32_to_cpup(&(td).info) >> 29) == 7)
 #define td_cc_accessed(td)     ((le32_to_cpup(&(td).info) >> 29) != 7)
 #define td_cc_noerror(td)      (((le32_to_cpup(&(td).info)) & OHCI_TD_CC) == 0)
-#define td_active(td)  (!td_cc_noerror((td)) && (td_errorcount((td)) < 3))
 #define td_done(td)    (td_cc_noerror((td)) || (td_errorcount((td)) == 3))
 
 /*
index 157d58898055bf32c00413dd2a0b03f85b49d543..a5864498cc97a286eedaf02119c13479591a4b29 100644 (file)
@@ -166,7 +166,6 @@ static ssize_t write_printer(struct file * file,
        do {
                char *obuf = p->obuf;
                unsigned long thistime;
-               partial = 0;
 
                thistime = copy_size = (count > p->maxout) ? p->maxout : count;
                if (copy_from_user(p->obuf, buffer, copy_size))
@@ -303,7 +302,11 @@ static int printer_probe(struct usb_device *dev)
        minor_data[i] = PPDATA(dev->private);
        minor_data[i]->minor = i;
        minor_data[i]->pusb_dev = dev;
-       minor_data[i]->maxout = interface->endpoint[0].wMaxPacketSize * 16;
+       /* The max packet size can't be more than 64 (& will be 64 for
+        * any decent bulk device); this calculation was silly.  -greg
+        * minor_data[i]->maxout = interface->endpoint[0].wMaxPacketSize * 16;
+        */
+       minor_data[i]->maxout = 8192;
        if (minor_data[i]->maxout > PAGE_SIZE) {
                 minor_data[i]->maxout = PAGE_SIZE;
        }
index 48233703c2d3bf20aa0ef09f0bc62bd8303bf3bd..23718517cb255a09d9546d3005fdd09084ef60f4 100644 (file)
@@ -70,7 +70,7 @@ static int uhci_map_status(int status, int dir_out)
            return USB_ST_BITSTUFF;
     if (status & 0x04) {                       /* CRC/Timeout */
        if (dir_out)
-           return USB_ST_TIMEOUT;
+           return USB_ST_NORESPONSE;
        else
            return USB_ST_CRC;
     }
index 5c36dad34fc565b4a5be2decf57e954293e758e5..f0ebc9a2683d14a1965a6ff9085f7072971de8c2 100644 (file)
@@ -97,16 +97,16 @@ typedef struct {
 #define USB_RT_HIDD                    (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
 
 /* 
- * Status codes 
+ * Status codes (these follow an OHCI controllers condition codes)
  */
 #define USB_ST_NOERROR         0x0
 #define USB_ST_CRC             0x1
 #define USB_ST_BITSTUFF                0x2
-#define USB_ST_DTMISMATCH      0x3
+#define USB_ST_DTMISMATCH      0x3     /* data toggle mismatch */
 #define USB_ST_STALL           0x4
-#define USB_ST_TIMEOUT         0x5
-#define USB_ST_PIDCHECK                0x6
-#define USB_ST_PIDUNDEF                0x7
+#define USB_ST_NORESPONSE      0x5     /* device not responding/handshaking */
+#define USB_ST_PIDCHECK                0x6     /* Check bits on PID failed */
+#define USB_ST_PIDUNDEF                0x7     /* PID unexpected/undefined */
 #define USB_ST_DATAOVERRUN     0x8
 #define USB_ST_DATAUNDERRUN    0x9
 #define USB_ST_RESERVED1       0xA
@@ -118,6 +118,7 @@ typedef struct {
 
 /* internal errors */
 #define USB_ST_REMOVED         0x100
+#define USB_ST_TIMEOUT         0x110
 #define USB_ST_INTERNALERROR   -1
 
 /*
index 7bdadd5fb20eb81bb6da94e5ac4daa53bc48ccd3..a436f60de4da28c16b64b62ed1d5e968630157af 100644 (file)
@@ -277,6 +277,7 @@ struct inode_operations blkdev_inode_operations = {
        NULL,                   /* mknod */
        NULL,                   /* rename */
        NULL,                   /* readlink */
+       NULL,                   /* follow_link */
        NULL,                   /* get_block */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
@@ -333,6 +334,7 @@ struct inode_operations chrdev_inode_operations = {
        NULL,                   /* mknod */
        NULL,                   /* rename */
        NULL,                   /* readlink */
+       NULL,                   /* follow_link */
        NULL,                   /* get_block */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
index 7215f69f15ff3aef265feb716f9c0c7ae67199e0..b4fb29776fd98fa5c047317bfef49ba0e6f12500 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -470,8 +470,7 @@ static inline void flush_old_files(struct files_struct * files)
                i = j * __NFDBITS;
                if (i >= files->max_fds)
                        break;
-               set = files->close_on_exec.fds_bits[j];
-               files->close_on_exec.fds_bits[j] = 0;
+               set = xchg(&files->close_on_exec.fds_bits[j], 0);
                j++;
                for ( ; set ; i++,set >>= 1) {
                        if (set & 1)
index 666d88881d9f366cdf64d07e122799c3125cb979..d12e66244cf57f8149ba688329e3b161767fd798 100644 (file)
 
 extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
 
-static inline int dupfd(unsigned int fd, unsigned int arg)
+static inline int dupfd(struct file *file, unsigned int arg)
 {
        struct files_struct * files = current->files;
-       struct file * file;
        int error;
 
-       error = -EINVAL;
-       if (arg >= NR_OPEN)
-               goto out;
-
-       error = -EBADF;
-       file = fget(fd);
-       if (!file)
-               goto out;
-
        error = -EMFILE;
+       write_lock(&files->file_lock);
        arg = find_next_zero_bit(&files->open_fds, NR_OPEN, arg);
        if (arg >= current->rlim[RLIMIT_NOFILE].rlim_cur)
                goto out_putf;
        FD_SET(arg, &files->open_fds);
        FD_CLR(arg, &files->close_on_exec);
+       write_unlock(&files->file_lock);
        fd_install(arg, file);
        error = arg;
 out:
@@ -46,31 +38,35 @@ out_putf:
 asmlinkage int sys_dup2(unsigned int oldfd, unsigned int newfd)
 {
        int err = -EBADF;
+       struct file * file;
 
-       lock_kernel();
-       if (!fcheck(oldfd))
-               goto out;
+       read_lock(&current->files->file_lock);
+       if (!(file = fcheck(oldfd)))
+               goto out_unlock;
        err = newfd;
        if (newfd == oldfd)
-               goto out;
+               goto out_unlock;
        err = -EBADF;
        if (newfd >= NR_OPEN)
-               goto out;       /* following POSIX.1 6.2.1 */
+               goto out_unlock;        /* following POSIX.1 6.2.1 */
+       get_file(file);
+       read_unlock(&current->files->file_lock);
 
        sys_close(newfd);
-       err = dupfd(oldfd, newfd);
+       err = dupfd(file, newfd);
 out:
-       unlock_kernel();
        return err;
+out_unlock:
+       read_unlock(&current->files->file_lock);
+       goto out;
 }
 
 asmlinkage int sys_dup(unsigned int fildes)
 {
-       int ret;
-
-       lock_kernel();
-       ret = dupfd(fildes, 0);
-       unlock_kernel();
+       int ret = -EBADF;
+       struct file * file = fget(fildes);
+       if (file)
+               ret = dupfd(file, 0);
        return ret;
 }
 
@@ -107,14 +103,18 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
        struct file * filp;
        long err = -EBADF;
 
-       lock_kernel();
        filp = fget(fd);
        if (!filp)
                goto out;
        err = 0;
+       lock_kernel();
        switch (cmd) {
                case F_DUPFD:
-                       err = dupfd(fd, arg);
+                       err = -EINVAL;
+                       if (arg < NR_OPEN) {
+                               get_file(filp);
+                               err = dupfd(filp, arg);
+                       }
                        break;
                case F_GETFD:
                        err = FD_ISSET(fd, &current->files->close_on_exec);
@@ -178,8 +178,8 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
                        break;
        }
        fput(filp);
-out:
        unlock_kernel();
+out:
        return err;
 }
 
index 4566f97f414fbe1602864903815001578abfa035..3e641a6fe891696f820ecb8f7175709aafce42c5 100644 (file)
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -179,6 +179,7 @@ struct inode_operations fifo_inode_operations = {
        NULL,                   /* mknod */
        NULL,                   /* rename */
        NULL,                   /* readlink */
+       NULL,                   /* follow_link */
        NULL,                   /* get_block */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
index e9f8e09b6348520059e6e87b3065fb00cc79e3c0..aded88dd76fe02fd544fedc6ceaba44f68f7808c 100644 (file)
@@ -52,11 +52,11 @@ asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
        unsigned int flag;
        int on, error = -EBADF;
 
-       lock_kernel();
        filp = fget(fd);
        if (!filp)
                goto out;
        error = 0;
+       lock_kernel();
        switch (cmd) {
                case FIOCLEX:
                        FD_SET(fd, &current->files->close_on_exec);
@@ -107,8 +107,8 @@ asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
                                error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
        }
        fput(filp);
+       unlock_kernel();
 
 out:
-       unlock_kernel();
        return error;
 }
index 06ac9610cd04205b6aea5521644549b425f32a4f..dd81531ec32088fb01bde137c8eb4ab94ab748d3 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -42,24 +42,18 @@ asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf)
        struct super_block * sb;
        int error;
 
-       lock_kernel();
        error = -EBADF;
        file = fget(fd);
        if (!file)
                goto out;
-       error = -ENOENT;
-       if (!(dentry = file->f_dentry))
-               goto out_putf;
-       if (!(inode = dentry->d_inode))
-               goto out_putf;
        error = -ENODEV;
-       sb = inode->i_sb;
+       sb = file->f_dentry->d_inode->i_sb;
+       lock_kernel();
        if (sb && sb->s_op && sb->s_op->statfs)
                error = sb->s_op->statfs(sb, buf, sizeof(struct statfs));
-out_putf:
+       unlock_kernel();
        fput(file);
 out:
-       unlock_kernel();
        return error;
 }
 
@@ -143,7 +137,6 @@ asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length)
        struct file * file;
        int error;
 
-       lock_kernel();
        error = -EBADF;
        file = fget(fd);
        if (!file)
@@ -162,12 +155,13 @@ asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length)
        error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file,
                                  length<inode->i_size ? length : inode->i_size,
                                  abs(inode->i_size - length));
+       lock_kernel();
        if (!error)
                error = do_truncate(dentry, length);
+       unlock_kernel();
 out_putf:
        fput(file);
 out:
-       unlock_kernel();
        return error;
 }
 
@@ -361,8 +355,6 @@ asmlinkage int sys_fchdir(unsigned int fd)
        struct inode *inode;
        int error;
 
-       lock_kernel();
-
        error = -EBADF;
        file = fget(fd);
        if (!file)
@@ -378,16 +370,17 @@ asmlinkage int sys_fchdir(unsigned int fd)
        if (!S_ISDIR(inode->i_mode))
                goto out_putf;
 
+       lock_kernel();
        error = permission(inode, MAY_EXEC);
        if (!error) {
                struct dentry *tmp = current->fs->pwd;
                current->fs->pwd = dget(dentry);
                dput(tmp);
        }
+       unlock_kernel();
 out_putf:
        fput(file);
 out:
-       unlock_kernel();
        return error;
 }
 
@@ -439,7 +432,6 @@ asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
        int err = -EBADF;
        struct iattr newattrs;
 
-       lock_kernel();
        file = fget(fd);
        if (!file)
                goto out;
@@ -460,12 +452,13 @@ asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
                mode = inode->i_mode;
        newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+       lock_kernel();
        err = notify_change(dentry, &newattrs);
+       unlock_kernel();
 
 out_putf:
        fput(file);
 out:
-       unlock_kernel();
        return err;
 }
 
@@ -601,17 +594,17 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
        struct file * file;
        int error = -EBADF;
 
-       lock_kernel();
        file = fget(fd);
        if (!file)
                goto out;
        error = -ENOENT;
+       lock_kernel();
        if ((dentry = file->f_dentry) != NULL)
                error = chown_common(dentry, user, group);
+       unlock_kernel();
        fput(file);
 
 out:
-       unlock_kernel();
        return error;
 }
 
@@ -695,6 +688,8 @@ int get_unused_fd(void)
        int fd, error;
 
        error = -EMFILE;
+
+       write_lock(&files->file_lock);
        fd = find_first_zero_bit(&files->open_fds, NR_OPEN);
        /*
         * N.B. For clone tasks sharing a files structure, this test
@@ -717,12 +712,15 @@ int get_unused_fd(void)
        error = fd;
 
 out:
+       write_unlock(&files->file_lock);
        return error;
 }
 
 inline void put_unused_fd(unsigned int fd)
 {
+       write_lock(&current->files->file_lock);
        FD_CLR(fd, &current->files->open_fds);
+       write_unlock(&current->files->file_lock);
 }
 
 asmlinkage int sys_open(const char * filename, int flags, int mode)
@@ -733,17 +731,18 @@ asmlinkage int sys_open(const char * filename, int flags, int mode)
        tmp = getname(filename);
        fd = PTR_ERR(tmp);
        if (!IS_ERR(tmp)) {
-               lock_kernel();
                fd = get_unused_fd();
                if (fd >= 0) {
-                       struct file * f = filp_open(tmp, flags, mode);
+                       struct file * f;
+                       lock_kernel();
+                       f = filp_open(tmp, flags, mode);
+                       unlock_kernel();
                        error = PTR_ERR(f);
                        if (IS_ERR(f))
                                goto out_error;
                        fd_install(fd, f);
                }
 out:
-               unlock_kernel();
                putname(tmp);
        }
        return fd;
@@ -792,7 +791,7 @@ int filp_close(struct file *filp, fl_owner_t id)
        int retval;
        struct dentry *dentry = filp->f_dentry;
 
-       if (!atomic_read(&filp->f_count)) {
+       if (!file_count(filp)) {
                printk("VFS: Close: file count is 0\n");
                return 0;
        }
@@ -814,19 +813,24 @@ asmlinkage int sys_close(unsigned int fd)
 {
        int error;
        struct file * filp;
+       struct files_struct * files = current->files;
 
-       lock_kernel();
        error = -EBADF;
-       filp = fcheck(fd);
-       if (filp) {
-               struct files_struct * files = current->files;
-               files->fd[fd] = NULL;
-               put_unused_fd(fd);
-               FD_CLR(fd, &files->close_on_exec);
-               error = filp_close(filp, files);
-       }
+       write_lock(&files->file_lock);
+       filp = frip(fd);
+       if (!filp)
+               goto out_unlock;
+       FD_CLR(fd, &files->close_on_exec);
+       write_unlock(&files->file_lock);
+       put_unused_fd(fd);
+       lock_kernel();
+       error = filp_close(filp, files);
        unlock_kernel();
+out:
        return error;
+out_unlock:
+       write_unlock(&files->file_lock);
+       goto out;
 }
 
 /*
@@ -837,14 +841,14 @@ asmlinkage int sys_vhangup(void)
 {
        int ret = -EPERM;
 
-       lock_kernel();
        if (!capable(CAP_SYS_TTY_CONFIG))
                goto out;
        /* If there is a controlling tty, hang it up */
+       lock_kernel();
        if (current->tty)
                tty_vhangup(current->tty);
+       unlock_kernel();
        ret = 0;
 out:
-       unlock_kernel();
        return ret;
 }
index 71f20bec52ffcacd8fb0a919dfa4e69e86270e26..b7c955c79d690d2b85efedca86a86fc2dc316f3e 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -480,6 +480,7 @@ struct inode_operations pipe_inode_operations = {
        NULL,                   /* mknod */
        NULL,                   /* rename */
        NULL,                   /* readlink */
+       NULL,                   /* follow_link */
        NULL,                   /* get_block */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
index a900d01bf6790d66c0afabfe80df3516e3f0d162..195ca41b8144aa8e8069c539e92d3538420099a5 100644 (file)
@@ -104,7 +104,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
        read_lock(&tasklist_lock);
        file = NULL;
        p = find_task_by_pid(pid);
-       if (p)
+       if (p && p->files)
                file = fcheck_task(p, fd);
        read_unlock(&tasklist_lock);
 
@@ -114,7 +114,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
         *      is NULL
         */
 
-       if (!file || !file->f_dentry)
+       if (!file)
                goto out;
 
        ino = (pid << 16) + PROC_PID_FD_DIR + fd;
@@ -161,10 +161,9 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
 
        for (fd -= 2 ; p->files && fd < p->files->max_fds; fd++, filp->f_pos++)
        {
-               struct file * file = fcheck_task(p, fd);
                unsigned int i,j;
 
-               if (!file || !file->f_dentry)
+               if (!fcheck_task(p, fd))
                        continue;
 
                j = NUMBUF;
index 4d329d090bd9bc77ab233bca1e461159188072f8..a5596e4ee404ed9e8b17afb7edeff8e66458e147 100644 (file)
@@ -400,9 +400,12 @@ void proc_read_inode(struct inode * inode)
        if (ino & PROC_PID_FD_DIR) {
                struct file * file;
                ino &= 0x7fff;
+               if (!p->files)  /* can we ever get here if that's the case? */
+                       goto out_unlock;
+               read_lock(&p->files->file_lock);
                file = fcheck_task(p, ino);
                if (!file)
-                       goto out_unlock;
+                       goto out_unlock2;
 
                inode->i_op = &proc_link_inode_operations;
                inode->i_size = 64;
@@ -411,6 +414,8 @@ void proc_read_inode(struct inode * inode)
                        inode->i_mode |= S_IRUSR | S_IXUSR;
                if (file->f_mode & 2)
                        inode->i_mode |= S_IWUSR | S_IXUSR;
+out_unlock2:
+               read_unlock(&p->files->file_lock);
        }
 out_unlock:
        /* Defer unlocking until we're done with the task */
index 647dc339fb4d3bd07cfb01558cfaea0a39f0f9c6..c08ebda4a5175ccafffc86bf68fd620d7a21c201 100644 (file)
@@ -119,10 +119,14 @@ static struct dentry * proc_follow_link(struct dentry *dentry,
                        if (ino & PROC_PID_FD_DIR) {
                                struct file * file;
                                ino &= 0x7fff;
+                               if (!p->files) /* shouldn't happen here */
+                                       goto out_unlock;
+                               read_lock(&p->files->file_lock);
                                file = fcheck_task(p, ino);
                                if (!file || !file->f_dentry)
                                        goto out_unlock;
                                result = file->f_dentry;
+                               read_unlock(&p->files->file_lock);
                                goto out_dget;
                        }
        }
index 4cb1a6d5515302c3dec87a9cf1c487df6a295923..3f278187e3dbd94168a4b59ee00b748549ae0db3 100644 (file)
@@ -64,9 +64,9 @@ void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table
                if (p->nr < __MAX_POLL_TABLE_ENTRIES) {
                        struct poll_table_entry * entry;
 ok_table:
-                       entry = p->entry + p->nr;
-                       entry->filp = filp;
-                       atomic_inc(&filp->f_count);
+                       entry = p->entry + p->nr;
+                       get_file(filp);
+                       entry->filp = filp;
                        entry->wait_address = wait_address;
                        init_waitqueue_entry(&entry->wait, current);
                        add_wait_queue(wait_address,&entry->wait);
@@ -164,9 +164,11 @@ int do_select(int n, fd_set_bits *fds, long *timeout)
                wait = wait_table;
        }
 
-       lock_kernel();
-
+       read_lock(&current->files->file_lock);
        retval = max_select_fd(n, fds);
+       read_unlock(&current->files->file_lock);
+
+       lock_kernel();
        if (retval < 0)
                goto out;
        n = retval;
index f8ffd64a2aa53ca55292d220e52b001b9242cb73..dc35d54816dd88269d6ec6b712f47b027bf3b1ca 100644 (file)
 #define ASIZ_mm_map_count      0x00000004
 #define AOFF_mm_mmap_sem       0x00000018
 #define ASIZ_mm_mmap_sem       0x00000020
-#define AOFF_mm_context        0x00000038
+#define AOFF_mm_page_table_lock        0x00000038
+#define ASIZ_mm_page_table_lock        0x00000001
+#define AOFF_mm_context        0x0000003c
 #define ASIZ_mm_context        0x00000004
-#define AOFF_mm_start_code     0x0000003c
+#define AOFF_mm_start_code     0x00000040
 #define ASIZ_mm_start_code     0x00000004
-#define AOFF_mm_end_code       0x00000040
+#define AOFF_mm_end_code       0x00000044
 #define ASIZ_mm_end_code       0x00000004
-#define AOFF_mm_start_data     0x00000044
+#define AOFF_mm_start_data     0x00000048
 #define ASIZ_mm_start_data     0x00000004
-#define AOFF_mm_end_data       0x00000048
+#define AOFF_mm_end_data       0x0000004c
 #define ASIZ_mm_end_data       0x00000004
-#define AOFF_mm_start_brk      0x0000004c
+#define AOFF_mm_start_brk      0x00000050
 #define ASIZ_mm_start_brk      0x00000004
-#define AOFF_mm_brk    0x00000050
+#define AOFF_mm_brk    0x00000054
 #define ASIZ_mm_brk    0x00000004
-#define AOFF_mm_start_stack    0x00000054
+#define AOFF_mm_start_stack    0x00000058
 #define ASIZ_mm_start_stack    0x00000004
-#define AOFF_mm_arg_start      0x00000058
+#define AOFF_mm_arg_start      0x0000005c
 #define ASIZ_mm_arg_start      0x00000004
-#define AOFF_mm_arg_end        0x0000005c
+#define AOFF_mm_arg_end        0x00000060
 #define ASIZ_mm_arg_end        0x00000004
-#define AOFF_mm_env_start      0x00000060
+#define AOFF_mm_env_start      0x00000064
 #define ASIZ_mm_env_start      0x00000004
-#define AOFF_mm_env_end        0x00000064
+#define AOFF_mm_env_end        0x00000068
 #define ASIZ_mm_env_end        0x00000004
-#define AOFF_mm_rss    0x00000068
+#define AOFF_mm_rss    0x0000006c
 #define ASIZ_mm_rss    0x00000004
-#define AOFF_mm_total_vm       0x0000006c
+#define AOFF_mm_total_vm       0x00000070
 #define ASIZ_mm_total_vm       0x00000004
-#define AOFF_mm_locked_vm      0x00000070
+#define AOFF_mm_locked_vm      0x00000074
 #define ASIZ_mm_locked_vm      0x00000004
-#define AOFF_mm_def_flags      0x00000074
+#define AOFF_mm_def_flags      0x00000078
 #define ASIZ_mm_def_flags      0x00000004
-#define AOFF_mm_cpu_vm_mask    0x00000078
+#define AOFF_mm_cpu_vm_mask    0x0000007c
 #define ASIZ_mm_cpu_vm_mask    0x00000004
-#define AOFF_mm_swap_cnt       0x0000007c
+#define AOFF_mm_swap_cnt       0x00000080
 #define ASIZ_mm_swap_cnt       0x00000004
-#define AOFF_mm_swap_address   0x00000080
+#define AOFF_mm_swap_address   0x00000084
 #define ASIZ_mm_swap_address   0x00000004
-#define AOFF_mm_segments       0x00000084
+#define AOFF_mm_segments       0x00000088
 #define ASIZ_mm_segments       0x00000004
 #define AOFF_thread_uwinmask   0x00000000
 #define ASIZ_thread_uwinmask   0x00000004
 #define ASIZ_mm_map_count      0x00000004
 #define AOFF_mm_mmap_sem       0x00000018
 #define ASIZ_mm_mmap_sem       0x00000024
-#define AOFF_mm_context        0x0000003c
+#define AOFF_mm_page_table_lock        0x0000003c
+#define ASIZ_mm_page_table_lock        0x00000008
+#define AOFF_mm_context        0x00000044
 #define ASIZ_mm_context        0x00000004
-#define AOFF_mm_start_code     0x00000040
+#define AOFF_mm_start_code     0x00000048
 #define ASIZ_mm_start_code     0x00000004
-#define AOFF_mm_end_code       0x00000044
+#define AOFF_mm_end_code       0x0000004c
 #define ASIZ_mm_end_code       0x00000004
-#define AOFF_mm_start_data     0x00000048
+#define AOFF_mm_start_data     0x00000050
 #define ASIZ_mm_start_data     0x00000004
-#define AOFF_mm_end_data       0x0000004c
+#define AOFF_mm_end_data       0x00000054
 #define ASIZ_mm_end_data       0x00000004
-#define AOFF_mm_start_brk      0x00000050
+#define AOFF_mm_start_brk      0x00000058
 #define ASIZ_mm_start_brk      0x00000004
-#define AOFF_mm_brk    0x00000054
+#define AOFF_mm_brk    0x0000005c
 #define ASIZ_mm_brk    0x00000004
-#define AOFF_mm_start_stack    0x00000058
+#define AOFF_mm_start_stack    0x00000060
 #define ASIZ_mm_start_stack    0x00000004
-#define AOFF_mm_arg_start      0x0000005c
+#define AOFF_mm_arg_start      0x00000064
 #define ASIZ_mm_arg_start      0x00000004
-#define AOFF_mm_arg_end        0x00000060
+#define AOFF_mm_arg_end        0x00000068
 #define ASIZ_mm_arg_end        0x00000004
-#define AOFF_mm_env_start      0x00000064
+#define AOFF_mm_env_start      0x0000006c
 #define ASIZ_mm_env_start      0x00000004
-#define AOFF_mm_env_end        0x00000068
+#define AOFF_mm_env_end        0x00000070
 #define ASIZ_mm_env_end        0x00000004
-#define AOFF_mm_rss    0x0000006c
+#define AOFF_mm_rss    0x00000074
 #define ASIZ_mm_rss    0x00000004
-#define AOFF_mm_total_vm       0x00000070
+#define AOFF_mm_total_vm       0x00000078
 #define ASIZ_mm_total_vm       0x00000004
-#define AOFF_mm_locked_vm      0x00000074
+#define AOFF_mm_locked_vm      0x0000007c
 #define ASIZ_mm_locked_vm      0x00000004
-#define AOFF_mm_def_flags      0x00000078
+#define AOFF_mm_def_flags      0x00000080
 #define ASIZ_mm_def_flags      0x00000004
-#define AOFF_mm_cpu_vm_mask    0x0000007c
+#define AOFF_mm_cpu_vm_mask    0x00000084
 #define ASIZ_mm_cpu_vm_mask    0x00000004
-#define AOFF_mm_swap_cnt       0x00000080
+#define AOFF_mm_swap_cnt       0x00000088
 #define ASIZ_mm_swap_cnt       0x00000004
-#define AOFF_mm_swap_address   0x00000084
+#define AOFF_mm_swap_address   0x0000008c
 #define ASIZ_mm_swap_address   0x00000004
-#define AOFF_mm_segments       0x00000088
+#define AOFF_mm_segments       0x00000090
 #define ASIZ_mm_segments       0x00000004
 #define AOFF_thread_uwinmask   0x00000000
 #define ASIZ_thread_uwinmask   0x00000004
index 5e2c8d63274ede4784e112c6a064b5a9ff011251..a3754dfe2105c01c6e4b067132a1a37a2b84e442 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: page.h,v 1.44 1999/06/23 03:53:11 davem Exp $
+/* $Id: page.h,v 1.45 1999/07/03 08:58:05 davem Exp $
  * page.h:  Various defines and such for MMU operations on the Sparc for
  *          the Linux kernel.
  *
index 6f5cb96d96231b8cd35726589e0d620fb2523600..b1f87cc587915c11b90f8437ea9e62b44a0070e4 100644 (file)
 #define ASIZ_mm_map_count      0x00000004
 #define AOFF_mm_mmap_sem       0x00000028
 #define ASIZ_mm_mmap_sem       0x00000038
-#define AOFF_mm_context        0x00000060
+#define AOFF_mm_page_table_lock        0x00000060
+#define ASIZ_mm_page_table_lock        0x00000001
+#define AOFF_mm_context        0x00000068
 #define ASIZ_mm_context        0x00000008
-#define AOFF_mm_start_code     0x00000068
+#define AOFF_mm_start_code     0x00000070
 #define ASIZ_mm_start_code     0x00000008
-#define AOFF_mm_end_code       0x00000070
+#define AOFF_mm_end_code       0x00000078
 #define ASIZ_mm_end_code       0x00000008
-#define AOFF_mm_start_data     0x00000078
+#define AOFF_mm_start_data     0x00000080
 #define ASIZ_mm_start_data     0x00000008
-#define AOFF_mm_end_data       0x00000080
+#define AOFF_mm_end_data       0x00000088
 #define ASIZ_mm_end_data       0x00000008
-#define AOFF_mm_start_brk      0x00000088
+#define AOFF_mm_start_brk      0x00000090
 #define ASIZ_mm_start_brk      0x00000008
-#define AOFF_mm_brk    0x00000090
+#define AOFF_mm_brk    0x00000098
 #define ASIZ_mm_brk    0x00000008
-#define AOFF_mm_start_stack    0x00000098
+#define AOFF_mm_start_stack    0x000000a0
 #define ASIZ_mm_start_stack    0x00000008
-#define AOFF_mm_arg_start      0x000000a0
+#define AOFF_mm_arg_start      0x000000a8
 #define ASIZ_mm_arg_start      0x00000008
-#define AOFF_mm_arg_end        0x000000a8
+#define AOFF_mm_arg_end        0x000000b0
 #define ASIZ_mm_arg_end        0x00000008
-#define AOFF_mm_env_start      0x000000b0
+#define AOFF_mm_env_start      0x000000b8
 #define ASIZ_mm_env_start      0x00000008
-#define AOFF_mm_env_end        0x000000b8
+#define AOFF_mm_env_end        0x000000c0
 #define ASIZ_mm_env_end        0x00000008
-#define AOFF_mm_rss    0x000000c0
+#define AOFF_mm_rss    0x000000c8
 #define ASIZ_mm_rss    0x00000008
-#define AOFF_mm_total_vm       0x000000c8
+#define AOFF_mm_total_vm       0x000000d0
 #define ASIZ_mm_total_vm       0x00000008
-#define AOFF_mm_locked_vm      0x000000d0
+#define AOFF_mm_locked_vm      0x000000d8
 #define ASIZ_mm_locked_vm      0x00000008
-#define AOFF_mm_def_flags      0x000000d8
+#define AOFF_mm_def_flags      0x000000e0
 #define ASIZ_mm_def_flags      0x00000008
-#define AOFF_mm_cpu_vm_mask    0x000000e0
+#define AOFF_mm_cpu_vm_mask    0x000000e8
 #define ASIZ_mm_cpu_vm_mask    0x00000008
-#define AOFF_mm_swap_cnt       0x000000e8
+#define AOFF_mm_swap_cnt       0x000000f0
 #define ASIZ_mm_swap_cnt       0x00000008
-#define AOFF_mm_swap_address   0x000000f0
+#define AOFF_mm_swap_address   0x000000f8
 #define ASIZ_mm_swap_address   0x00000008
-#define AOFF_mm_segments       0x000000f8
+#define AOFF_mm_segments       0x00000100
 #define ASIZ_mm_segments       0x00000008
-#define ASIZ_mm        0x00000100
+#define ASIZ_mm        0x00000108
 #define AOFF_thread_ksp        0x00000000
 #define ASIZ_thread_ksp        0x00000008
 #define AOFF_thread_wstate     0x00000008
 #define ASIZ_mm_map_count      0x00000004
 #define AOFF_mm_mmap_sem       0x00000028
 #define ASIZ_mm_mmap_sem       0x00000038
-#define AOFF_mm_context        0x00000060
+#define AOFF_mm_page_table_lock        0x00000060
+#define ASIZ_mm_page_table_lock        0x00000001
+#define AOFF_mm_context        0x00000068
 #define ASIZ_mm_context        0x00000008
-#define AOFF_mm_start_code     0x00000068
+#define AOFF_mm_start_code     0x00000070
 #define ASIZ_mm_start_code     0x00000008
-#define AOFF_mm_end_code       0x00000070
+#define AOFF_mm_end_code       0x00000078
 #define ASIZ_mm_end_code       0x00000008
-#define AOFF_mm_start_data     0x00000078
+#define AOFF_mm_start_data     0x00000080
 #define ASIZ_mm_start_data     0x00000008
-#define AOFF_mm_end_data       0x00000080
+#define AOFF_mm_end_data       0x00000088
 #define ASIZ_mm_end_data       0x00000008
-#define AOFF_mm_start_brk      0x00000088
+#define AOFF_mm_start_brk      0x00000090
 #define ASIZ_mm_start_brk      0x00000008
-#define AOFF_mm_brk    0x00000090
+#define AOFF_mm_brk    0x00000098
 #define ASIZ_mm_brk    0x00000008
-#define AOFF_mm_start_stack    0x00000098
+#define AOFF_mm_start_stack    0x000000a0
 #define ASIZ_mm_start_stack    0x00000008
-#define AOFF_mm_arg_start      0x000000a0
+#define AOFF_mm_arg_start      0x000000a8
 #define ASIZ_mm_arg_start      0x00000008
-#define AOFF_mm_arg_end        0x000000a8
+#define AOFF_mm_arg_end        0x000000b0
 #define ASIZ_mm_arg_end        0x00000008
-#define AOFF_mm_env_start      0x000000b0
+#define AOFF_mm_env_start      0x000000b8
 #define ASIZ_mm_env_start      0x00000008
-#define AOFF_mm_env_end        0x000000b8
+#define AOFF_mm_env_end        0x000000c0
 #define ASIZ_mm_env_end        0x00000008
-#define AOFF_mm_rss    0x000000c0
+#define AOFF_mm_rss    0x000000c8
 #define ASIZ_mm_rss    0x00000008
-#define AOFF_mm_total_vm       0x000000c8
+#define AOFF_mm_total_vm       0x000000d0
 #define ASIZ_mm_total_vm       0x00000008
-#define AOFF_mm_locked_vm      0x000000d0
+#define AOFF_mm_locked_vm      0x000000d8
 #define ASIZ_mm_locked_vm      0x00000008
-#define AOFF_mm_def_flags      0x000000d8
+#define AOFF_mm_def_flags      0x000000e0
 #define ASIZ_mm_def_flags      0x00000008
-#define AOFF_mm_cpu_vm_mask    0x000000e0
+#define AOFF_mm_cpu_vm_mask    0x000000e8
 #define ASIZ_mm_cpu_vm_mask    0x00000008
-#define AOFF_mm_swap_cnt       0x000000e8
+#define AOFF_mm_swap_cnt       0x000000f0
 #define ASIZ_mm_swap_cnt       0x00000008
-#define AOFF_mm_swap_address   0x000000f0
+#define AOFF_mm_swap_address   0x000000f8
 #define ASIZ_mm_swap_address   0x00000008
-#define AOFF_mm_segments       0x000000f8
+#define AOFF_mm_segments       0x00000100
 #define ASIZ_mm_segments       0x00000008
-#define ASIZ_mm        0x00000100
+#define ASIZ_mm        0x00000108
 #define AOFF_thread_ksp        0x00000000
 #define ASIZ_thread_ksp        0x00000008
 #define AOFF_thread_wstate     0x00000008
 #define ASIZ_mm_map_count      0x00000004
 #define AOFF_mm_mmap_sem       0x00000028
 #define ASIZ_mm_mmap_sem       0x00000040
-#define AOFF_mm_context        0x00000068
+#define AOFF_mm_page_table_lock        0x00000068
+#define ASIZ_mm_page_table_lock        0x0000000c
+#define AOFF_mm_context        0x00000078
 #define ASIZ_mm_context        0x00000008
-#define AOFF_mm_start_code     0x00000070
+#define AOFF_mm_start_code     0x00000080
 #define ASIZ_mm_start_code     0x00000008
-#define AOFF_mm_end_code       0x00000078
+#define AOFF_mm_end_code       0x00000088
 #define ASIZ_mm_end_code       0x00000008
-#define AOFF_mm_start_data     0x00000080
+#define AOFF_mm_start_data     0x00000090
 #define ASIZ_mm_start_data     0x00000008
-#define AOFF_mm_end_data       0x00000088
+#define AOFF_mm_end_data       0x00000098
 #define ASIZ_mm_end_data       0x00000008
-#define AOFF_mm_start_brk      0x00000090
+#define AOFF_mm_start_brk      0x000000a0
 #define ASIZ_mm_start_brk      0x00000008
-#define AOFF_mm_brk    0x00000098
+#define AOFF_mm_brk    0x000000a8
 #define ASIZ_mm_brk    0x00000008
-#define AOFF_mm_start_stack    0x000000a0
+#define AOFF_mm_start_stack    0x000000b0
 #define ASIZ_mm_start_stack    0x00000008
-#define AOFF_mm_arg_start      0x000000a8
+#define AOFF_mm_arg_start      0x000000b8
 #define ASIZ_mm_arg_start      0x00000008
-#define AOFF_mm_arg_end        0x000000b0
+#define AOFF_mm_arg_end        0x000000c0
 #define ASIZ_mm_arg_end        0x00000008
-#define AOFF_mm_env_start      0x000000b8
+#define AOFF_mm_env_start      0x000000c8
 #define ASIZ_mm_env_start      0x00000008
-#define AOFF_mm_env_end        0x000000c0
+#define AOFF_mm_env_end        0x000000d0
 #define ASIZ_mm_env_end        0x00000008
-#define AOFF_mm_rss    0x000000c8
+#define AOFF_mm_rss    0x000000d8
 #define ASIZ_mm_rss    0x00000008
-#define AOFF_mm_total_vm       0x000000d0
+#define AOFF_mm_total_vm       0x000000e0
 #define ASIZ_mm_total_vm       0x00000008
-#define AOFF_mm_locked_vm      0x000000d8
+#define AOFF_mm_locked_vm      0x000000e8
 #define ASIZ_mm_locked_vm      0x00000008
-#define AOFF_mm_def_flags      0x000000e0
+#define AOFF_mm_def_flags      0x000000f0
 #define ASIZ_mm_def_flags      0x00000008
-#define AOFF_mm_cpu_vm_mask    0x000000e8
+#define AOFF_mm_cpu_vm_mask    0x000000f8
 #define ASIZ_mm_cpu_vm_mask    0x00000008
-#define AOFF_mm_swap_cnt       0x000000f0
+#define AOFF_mm_swap_cnt       0x00000100
 #define ASIZ_mm_swap_cnt       0x00000008
-#define AOFF_mm_swap_address   0x000000f8
+#define AOFF_mm_swap_address   0x00000108
 #define ASIZ_mm_swap_address   0x00000008
-#define AOFF_mm_segments       0x00000100
+#define AOFF_mm_segments       0x00000110
 #define ASIZ_mm_segments       0x00000008
-#define ASIZ_mm        0x00000108
+#define ASIZ_mm        0x00000118
 #define AOFF_thread_ksp        0x00000000
 #define ASIZ_thread_ksp        0x00000008
 #define AOFF_thread_wstate     0x00000008
index 33341d3996ec7c4bed22207e6cfe8d9cab58554c..96ef1a5853d61ba82c5c227e9f93bb5d9bc467ee 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: atomic.h,v 1.18 1997/08/07 03:38:31 davem Exp $
+/* $Id: atomic.h,v 1.19 1999/07/03 22:11:17 davem Exp $
  * atomic.h: Thankfully the V9 is at least reasonable for this
  *           stuff.
  *
@@ -20,66 +20,34 @@ typedef struct { int counter; } atomic_t;
 #define atomic_read(v)         ((v)->counter)
 #define atomic_set(v, i)       (((v)->counter) = i)
 
-extern __inline__ void atomic_add(int i, atomic_t *v)
-{
-       __asm__ __volatile__("
-1:     lduw            [%1], %%g5
-       add             %%g5, %0, %%g7
-       cas             [%1], %%g5, %%g7
-       sub             %%g5, %%g7, %%g5
-       brnz,pn         %%g5, 1b
-        nop"
-       : /* No outputs */
-       : "HIr" (i), "r" (__atomic_fool_gcc(v))
-       : "g5", "g7", "memory");
-}
-
-extern __inline__ void atomic_sub(int i, atomic_t *v)
-{
-       __asm__ __volatile__("
-1:     lduw            [%1], %%g5
-       sub             %%g5, %0, %%g7
-       cas             [%1], %%g5, %%g7
-       sub             %%g5, %%g7, %%g5
-       brnz,pn         %%g5, 1b
-        nop"
-       : /* No outputs */
-       : "HIr" (i), "r" (__atomic_fool_gcc(v))
-       : "g5", "g7", "memory");
-}
-
-/* Same as above, but return the result value. */
-extern __inline__ int atomic_add_return(int i, atomic_t *v)
-{
-       unsigned long oldval;
-       __asm__ __volatile__("
-1:     lduw            [%2], %%g5
-       add             %%g5, %1, %%g7
-       cas             [%2], %%g5, %%g7
-       sub             %%g5, %%g7, %%g5
-       brnz,pn         %%g5, 1b
-        add            %%g7, %1, %0"
-       : "=&r" (oldval)
-       : "HIr" (i), "r" (__atomic_fool_gcc(v))
-       : "g5", "g7", "memory");
-       return (int)oldval;
-}
-
-extern __inline__ int atomic_sub_return(int i, atomic_t *v)
-{
-       unsigned long oldval;
-       __asm__ __volatile__("
-1:     lduw            [%2], %%g5
-       sub             %%g5, %1, %%g7
-       cas             [%2], %%g5, %%g7
-       sub             %%g5, %%g7, %%g5
-       brnz,pn         %%g5, 1b
-        sub            %%g7, %1, %0"
-       : "=&r" (oldval)
-       : "HIr" (i), "r" (__atomic_fool_gcc(v))
-       : "g5", "g7", "memory");
-       return (int)oldval;
-}
+#define atomic_add_return(__i, __v) \
+({     register atomic_t *__V asm("g1"); \
+       register int __I asm("g2"); \
+       __V = (__v); __I = (__i); \
+       __asm__ __volatile__("sethi     %%hi(__atomic_add), %%g3\n\t" \
+                            "jmpl      %%g3 + %%lo(__atomic_add), %%g3\n\t" \
+                            " nop\n1:" \
+                            : "=&r" (__I) \
+                            : "0" (__I), "r" (__V) \
+                            : "g3", "g5", "g7", "cc", "memory"); \
+       __I; \
+})
+
+#define atomic_sub_return(__i, __v) \
+({     register atomic_t *__V asm("g1"); \
+       register int __I asm("g2"); \
+       __V = (__v); __I = (__i); \
+       __asm__ __volatile__("sethi     %%hi(__atomic_sub), %%g3\n\t" \
+                            "jmpl      %%g3 + %%lo(__atomic_sub), %%g3\n\t" \
+                            " nop\n1:" \
+                            : "=&r" (__I) \
+                            : "0" (__I), "r" (__V) \
+                            : "g3", "g5", "g7", "cc", "memory"); \
+       __I; \
+})
+
+#define atomic_add(i, v) atomic_add_return(i, v)
+#define atomic_sub(i, v) atomic_sub_return(i, v)
 
 #define atomic_dec_return(v) atomic_sub_return(1,(v))
 #define atomic_inc_return(v) atomic_add_return(1,(v))
index b3311df9db07a6fb2355c548a3824962ee4fd3b5..e8d68eca31f2f679518e79392fb8e22c38164988 100644 (file)
@@ -42,7 +42,7 @@ do {  barrier(); \
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
  */
-typedef unsigned long rwlock_t;
+typedef unsigned int rwlock_t;
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
 
 #define read_lock(lock)                do { } while(0)
@@ -255,90 +255,44 @@ extern int _spin_trylock (spinlock_t *lock);
 
 #ifndef SPIN_LOCK_DEBUG
 
-typedef unsigned long rwlock_t;
+typedef unsigned int rwlock_t;
 #define RW_LOCK_UNLOCKED       0
 
-extern __inline__ void read_lock(rwlock_t *rw)
-{
-       __asm__ __volatile__("
-1:     ldx             [%0], %%g5
-       brlz,pn         %%g5, 2f
-4:      add            %%g5, 1, %%g7
-       casx            [%0], %%g5, %%g7
-       cmp             %%g5, %%g7
-       bne,pn          %%xcc, 1b
-        membar         #StoreLoad | #StoreStore
-       .subsection     2
-2:     ldx             [%0], %%g5
-       brlz,pt         %%g5, 2b
-        membar         #LoadLoad
-       b,a,pt          %%xcc, 4b
-       .previous
-"      : /* no outputs */
-       : "r" (rw)
-       : "g5", "g7", "cc", "memory");
-}
+#define read_lock(__rw_lck) \
+do {   register rwlock_t *__X asm("g1"); \
+       __asm__ __volatile__("sethi     %%hi(__read_lock), %%g3\n\t" \
+                            "jmpl      %%g3 + %%lo(__read_lock), %%g3\n\t" \
+                            " nop\n1:" \
+       : : "r" (__X = (__rw_lck)) \
+         : "g3", "g5", "g7", "cc", "memory"); \
+} while(0)
 
-extern __inline__ void read_unlock(rwlock_t *rw)
-{
-       __asm__ __volatile__("
-1:     ldx             [%0], %%g5
-       sub             %%g5, 1, %%g7
-       casx            [%0], %%g5, %%g7
-       cmp             %%g5, %%g7
-       bne,pn          %%xcc, 1b
-        membar         #StoreLoad | #StoreStore
-"      : /* no outputs */
-       : "r" (rw)
-       : "g5", "g7", "cc", "memory");
-}
+#define read_unlock(__rw_lck) \
+do {   register rwlock_t *__X asm("g1"); \
+       __asm__ __volatile__("sethi     %%hi(__read_unlock), %%g3\n\t" \
+                            "jmpl      %%g3 + %%lo(__read_unlock), %%g3\n\t" \
+                            " nop\n1:" \
+       : : "r" (__X = (__rw_lck)) \
+         : "g3", "g5", "g7", "cc", "memory"); \
+} while(0)
 
-extern __inline__ void write_lock(rwlock_t *rw)
-{
-       __asm__ __volatile__("
-       sethi           %%uhi(0x8000000000000000), %%g3
-       sllx            %%g3, 32, %%g3
-1:     ldx             [%0], %%g5
-       brlz,pn         %%g5, 5f
-4:      or             %%g5, %%g3, %%g7
-       casx            [%0], %%g5, %%g7
-       cmp             %%g5, %%g7
-       bne,pn          %%xcc, 1b
-        andncc         %%g7, %%g3, %%g0
-       bne,pn          %%xcc, 7f
-        membar         #StoreLoad | #StoreStore
-       .subsection     2
-7:     ldx             [%0], %%g5
-       andn            %%g5, %%g3, %%g7
-       casx            [%0], %%g5, %%g7
-       cmp             %%g5, %%g7
-       bne,pn          %%xcc, 7b
-        membar         #StoreLoad | #StoreStore
-5:     ldx             [%0], %%g5
-       brnz,pt         %%g5, 5b
-        membar         #LoadLoad
-       b,a,pt          %%xcc, 4b
-       .previous
-"      : /* no outputs */
-       : "r" (rw)
-       : "g3", "g5", "g7", "memory", "cc");
-}
+#define write_lock(__rw_lck) \
+do {   register rwlock_t *__X asm("g1"); \
+       __asm__ __volatile__("sethi     %%hi(__write_lock), %%g3\n\t" \
+                            "jmpl      %%g3 + %%lo(__write_lock), %%g3\n\t" \
+                            " nop\n1:" \
+       : : "r" (__X = (__rw_lck)) \
+         : "g2", "g3", "g5", "g7", "cc", "memory"); \
+} while(0)
 
-extern __inline__ void write_unlock(rwlock_t *rw)
-{
-       __asm__ __volatile__("
-       sethi           %%uhi(0x8000000000000000), %%g3
-       sllx            %%g3, 32, %%g3
-1:     ldx             [%0], %%g5
-       andn            %%g5, %%g3, %%g7
-       casx            [%0], %%g5, %%g7
-       cmp             %%g5, %%g7
-       bne,pn          %%xcc, 1b
-        membar         #StoreLoad | #StoreStore
-"      : /* no outputs */
-       : "r" (rw)
-       : "g3", "g5", "g7", "memory", "cc");
-}
+#define write_unlock(__rw_lck) \
+do {   register rwlock_t *__X asm("g1"); \
+       __asm__ __volatile__("sethi     %%hi(__write_unlock), %%g3\n\t" \
+                            "jmpl      %%g3 + %%lo(__write_unlock), %%g3\n\t" \
+                            " nop\n1:" \
+       : : "r" (__X = (__rw_lck)) \
+         : "g2", "g3", "g5", "g7", "cc", "memory"); \
+} while(0)
 
 #define read_lock_irq(lock)    do { __cli(); read_lock(lock); } while (0)
 #define read_unlock_irq(lock)  do { read_unlock(lock); __sti(); } while (0)
index 699098733ce85866a1d319355c9d844e930e890c..1bdd56a0cf22a1110db889b2f403ecd10ca83c5d 100644 (file)
@@ -16,7 +16,7 @@ extern inline struct file * fcheck_task(struct task_struct *p, unsigned int fd)
 {
        struct file * file = NULL;
 
-       if (p->files && fd < p->files->max_fds)
+       if (fd < p->files->max_fds)
                file = p->files->fd[fd];
        return file;
 }
@@ -29,10 +29,17 @@ extern inline struct file * fcheck(unsigned int fd)
        struct file * file = NULL;
        struct files_struct *files = current->files;
 
-       read_lock(&files->file_lock);
        if (fd < files->max_fds)
                file = files->fd[fd];
-       read_unlock(&files->file_lock);
+       return file;
+}
+
+extern inline struct file * frip(unsigned int fd)
+{
+       struct file * file = NULL;
+
+       if (fd < current->files->max_fds)
+               file = xchg(&current->files->fd[fd], NULL);
        return file;
 }
 
@@ -42,11 +49,9 @@ extern inline struct file * fget(unsigned int fd)
        struct files_struct *files = current->files;
 
        read_lock(&files->file_lock);
-       if (fd < files->max_fds) {
-               file = files->fd[fd];
-               if (file)
-                       atomic_inc(&file->f_count);
-       }
+       file = fcheck(fd);
+       if (file)
+               get_file(file);
        read_unlock(&files->file_lock);
        return file;
 }
index cb5a5809ee3ad6feccee69408f82685a89c072e2..7b511f008b7ab01ef47600bbc8853aa0540ae5f4 100644 (file)
@@ -316,6 +316,7 @@ extern int zeromap_page_range(unsigned long from, unsigned long size, pgprot_t p
 extern void vmtruncate(struct inode * inode, unsigned long offset);
 extern int handle_mm_fault(struct task_struct *tsk,struct vm_area_struct *vma, unsigned long address, int write_access);
 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 pgt_cache_water[2];
 extern int check_pgt_cache(void);
index c07cbaccf51aacda3d189ea4fe139c0d026e7490..0d65afa67c162797cd1771841bbd829007fb2c10 100644 (file)
@@ -73,6 +73,7 @@ typedef enum {
 /* The rest is for the kernel only */
 #ifdef __KERNEL__
 
+#include <linux/wait.h>
 #include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/spinlock.h>
index abd520d4499d51a6eb283e4e686bb73bf488a5b5..05357e3480e969556cf43fc58f716d2a5c72f3a5 100644 (file)
@@ -13,7 +13,7 @@
 O_TARGET := kernel.o
 O_OBJS    = sched.o dma.o fork.o exec_domain.o panic.o printk.o sys.o \
            module.o exit.o itimer.o info.o time.o softirq.o resource.o \
-           sysctl.o acct.o capability.o
+           sysctl.o acct.o capability.o ptrace.o
 
 OX_OBJS  += signal.o
 
index 57d8441da5e1e7056f83e05ba3ccf31d115f57a5..c4b2c4eb94d94ee4f02097b33bf5e2ff253c9683 100644 (file)
@@ -166,11 +166,9 @@ static inline void close_files(struct files_struct * files)
                        break;
                while (set) {
                        if (set & 1) {
-                               struct file * file = files->fd[i];
-                               if (file) {
-                                       files->fd[i] = NULL;
+                               struct file * file = xchg(&files->fd[i], NULL);
+                               if (file)
                                        filp_close(file, files);
-                               }
                        }
                        i++;
                        set >>= 1;
@@ -182,10 +180,9 @@ extern kmem_cache_t *files_cachep;
 
 static inline void __exit_files(struct task_struct *tsk)
 {
-       struct files_struct * files = tsk->files;
+       struct files_struct * files = xchg(&tsk->files, NULL);
 
        if (files) {
-               tsk->files = NULL;
                if (atomic_dec_and_test(&files->count)) {
                        close_files(files);
                        /*
index c940938838def29b67f0cfe725fec88f86d73786..418b6e4b3ebc9d4b02ed06bcf153857e95a043d1 100644 (file)
@@ -249,7 +249,7 @@ static inline int dup_mmap(struct mm_struct * mm)
                tmp->vm_next = NULL;
                file = tmp->vm_file;
                if (file) {
-                       atomic_inc(&file->f_count);
+                       get_file(file);
                        if (tmp->vm_flags & VM_DENYWRITE)
                                file->f_dentry->d_inode->i_writecount--;
       
@@ -479,17 +479,18 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
        atomic_set(&newf->count, 1);
        newf->max_fds = NR_OPEN;
        newf->fd = new_fds;
+       read_lock(&oldf->file_lock);
        newf->close_on_exec = oldf->close_on_exec;
        i = copy_fdset(&newf->open_fds, &oldf->open_fds);
 
        old_fds = oldf->fd;
        for (; i != 0; i--) {
                struct file *f = *old_fds++;
-               *new_fds = f;
                if (f)
-                       atomic_inc(&f->f_count);
-               new_fds++;
+                       get_file(f);
+               *new_fds++ = f;
        }
+       read_unlock(&oldf->file_lock);
        /* This is long word aligned thus could use a optimized version */ 
        memset(new_fds, 0, (char *)newf->fd + size - (char *)new_fds); 
       
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
new file mode 100644 (file)
index 0000000..21f306a
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * linux/kernel/ptrace.c
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * Common interfaces for "ptrace()" which we do not want
+ * to continually duplicate across every architecture.
+ */
+
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+
+/*
+ * Access another process' address space, one page at a time.
+ */
+static int access_one_page(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long addr, void *buf, int len, int write)
+{
+       pgd_t * pgdir;
+       pmd_t * pgmiddle;
+       pte_t * pgtable;
+       unsigned long page;
+
+repeat:
+       pgdir = pgd_offset(vma->vm_mm, addr);
+       if (pgd_none(*pgdir))
+               goto fault_in_page;
+       if (pgd_bad(*pgdir))
+               goto bad_pgd;
+       pgmiddle = pmd_offset(pgdir, addr);
+       if (pmd_none(*pgmiddle))
+               goto fault_in_page;
+       if (pmd_bad(*pgmiddle))
+               goto bad_pmd;
+       pgtable = pte_offset(pgmiddle, addr);
+       if (!pte_present(*pgtable))
+               goto fault_in_page;
+       page = pte_page(*pgtable);
+       if (MAP_NR(page) >= max_mapnr)
+               return 0;
+       flush_cache_page(vma, addr);
+       {
+               void *src = (void *) (page + (addr & ~PAGE_MASK));
+               void *dst = buf;
+
+               if (write) {
+                       dst = src;
+                       src = buf;
+               }
+               memcpy(dst, src, len);
+       }
+       flush_page_to_ram(page);
+       return len;
+
+fault_in_page:
+       /* -1: out of memory. 0 - unmapped page */
+       if (handle_mm_fault(tsk, vma, addr, write) > 0)
+               goto repeat;
+       return 0;
+
+bad_pgd:
+       printk("ptrace: bad pgd in '%s' at %08lx (%08lx)\n", tsk->comm, addr, pgd_val(*pgdir));
+       return 0;
+
+bad_pmd:
+       printk("ptrace: bad pmd in '%s' at %08lx (%08lx)\n", tsk->comm, addr, pmd_val(*pgmiddle));
+       return 0;
+}
+
+int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
+{
+       int copied;
+       struct vm_area_struct * vma = find_extend_vma(tsk, addr);
+
+       if (!vma)
+               return 0;
+
+       down(&tsk->mm->mmap_sem);
+       copied = 0;
+       for (;;) {
+               unsigned long offset = addr & ~PAGE_MASK;
+               int this_len = PAGE_SIZE - offset;
+               int retval;
+
+               if (this_len > len)
+                       this_len = len;
+               retval = access_one_page(tsk, vma, addr, buf, this_len, write);
+               copied += retval;
+               if (retval != this_len)
+                       break;
+
+               len -= retval;
+               if (!len)
+                       break;
+
+               addr += retval;
+               buf += retval;
+
+               if (addr < vma->vm_end)
+                       continue;       
+               if (!vma->vm_next)
+                       break;
+               if (vma->vm_next->vm_start != vma->vm_end)
+                       break;
+       
+               vma = vma->vm_next;
+       }
+       up(&tsk->mm->mmap_sem);
+       return copied;
+}
+
+int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len)
+{
+       int copied = 0;
+       while (len) {
+               char buf[128];
+               int this_len, retval;
+
+               this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
+               retval = access_process_vm(tsk, src, buf, this_len, 0);
+               if (!retval) {
+                       if (copied)
+                               break;
+                       return -EIO;
+               }
+               if (copy_to_user(dst, buf, retval))
+                       return -EFAULT;
+               copied += retval;
+               src += retval;
+               dst += retval;
+               len -= retval;                  
+       }
+       return copied;
+}
+
+int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int len)
+{
+       int copied = 0;
+       while (len) {
+               char buf[128];
+               int this_len, retval;
+
+               this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
+               if (copy_from_user(buf, src, this_len))
+                       return -EFAULT;
+               retval = access_process_vm(tsk, dst, buf, this_len, 1);
+               if (!retval) {
+                       if (copied)
+                               break;
+                       return -EIO;
+               }
+               copied += retval;
+               src += retval;
+               dst += retval;
+               len -= retval;                  
+       }
+       return copied;
+}
index d8bd1e33d9af75537e5b3c0c3f8fb09da9b81e77..1cafd9aeb5e5faf609649f4f216fed8bd500ba92 100644 (file)
@@ -123,13 +123,16 @@ static struct inode_operations router_inode =
        NULL,                   /* rmdir */
        NULL,                   /* mknod */
        NULL,                   /* rename */
-       NULL,                   /* follow link */
        NULL,                   /* readlink */
+       NULL,                   /* follow_link */
+       NULL,                   /* get_block */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
-       NULL,                   /* get_block */
+       NULL,                   /* flushpage */
        NULL,                   /* truncate */
-       router_proc_perms
+       router_proc_perms,      /* permission */
+       NULL,                   /* smap */
+       NULL                    /* revalidate */
 };
 
 /*
@@ -165,15 +168,18 @@ static struct inode_operations wandev_inode =
        NULL,                   /* rename */
        NULL,                   /* readlink */
        NULL,                   /* follow_link */
+       NULL,                   /* get_block */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
-       NULL,                   /* get_block */
+       NULL,                   /* flushpage */
        NULL,                   /* truncate */
-       router_proc_perms
+       router_proc_perms,      /* permission */
+       NULL,                   /* smap */
+       NULL                    /* revalidate */
 };
 
 /*
- * Proc filesystem derectory entries.
+ * Proc filesystem directory entries.
  */
 
 /*