diff --git a/[refs] b/[refs] index ed7a910e47ef..a79270c098ef 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b8d9598c41e999fb094d3811019248197c54274a +refs/heads/master: da6b2d01d6bd2e79fd4f7a08acd37dc4e8fcdce8 diff --git a/trunk/arch/i386/kernel/nmi.c b/trunk/arch/i386/kernel/nmi.c index 8c242bb1ef45..da6c46d667cb 100644 --- a/trunk/arch/i386/kernel/nmi.c +++ b/trunk/arch/i386/kernel/nmi.c @@ -195,7 +195,7 @@ static void disable_lapic_nmi_watchdog(void) wrmsr(MSR_P6_EVNTSEL0, 0, 0); break; case 15: - if (boot_cpu_data.x86_model > 0x4) + if (boot_cpu_data.x86_model > 0x3) break; wrmsr(MSR_P4_IQ_CCCR0, 0, 0); @@ -432,7 +432,7 @@ void setup_apic_nmi_watchdog (void) setup_p6_watchdog(); break; case 15: - if (boot_cpu_data.x86_model > 0x4) + if (boot_cpu_data.x86_model > 0x3) return; if (!setup_p4_watchdog()) diff --git a/trunk/arch/sparc/kernel/sparc_ksyms.c b/trunk/arch/sparc/kernel/sparc_ksyms.c index 8faa8dc4de43..1bd430d0ca06 100644 --- a/trunk/arch/sparc/kernel/sparc_ksyms.c +++ b/trunk/arch/sparc/kernel/sparc_ksyms.c @@ -98,9 +98,8 @@ extern void ___rw_write_enter(void); * The module references will be fixed up by module_frob_arch_sections. */ #define DOT_ALIAS2(__ret, __x, __arg1, __arg2) \ - extern __ret __x(__arg1, __arg2); \ - asm(".weak " #__x);\ - asm(#__x "=." #__x); + extern __ret __x(__arg1, __arg2) \ + __attribute__((weak, alias("." # __x))); DOT_ALIAS2(int, div, int, int) DOT_ALIAS2(int, mul, int, int) diff --git a/trunk/arch/sparc64/kernel/Makefile b/trunk/arch/sparc64/kernel/Makefile index 6f00ab8b9d23..093281bdf85f 100644 --- a/trunk/arch/sparc64/kernel/Makefile +++ b/trunk/arch/sparc64/kernel/Makefile @@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror extra-y := head.o init_task.o vmlinux.lds obj-y := process.o setup.o cpu.o idprom.o \ - traps.o devices.o auxio.o una_asm.o \ + traps.o devices.o auxio.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o pci.o starfire.o semaphore.o \ power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o diff --git a/trunk/arch/sparc64/kernel/traps.c b/trunk/arch/sparc64/kernel/traps.c index 0c9e54b2f0c8..100b0107c4be 100644 --- a/trunk/arch/sparc64/kernel/traps.c +++ b/trunk/arch/sparc64/kernel/traps.c @@ -2127,9 +2127,6 @@ void __init trap_init(void) TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) || TI_NEW_CHILD != offsetof(struct thread_info, new_child) || TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) || - TI_RESTART_BLOCK != offsetof(struct thread_info, restart_block) || - TI_KUNA_REGS != offsetof(struct thread_info, kern_una_regs) || - TI_KUNA_INSN != offsetof(struct thread_info, kern_una_insn) || TI_FPREGS != offsetof(struct thread_info, fpregs) || (TI_FPREGS & (64 - 1))) thread_info_offsets_are_bolixed_dave(); diff --git a/trunk/arch/sparc64/kernel/una_asm.S b/trunk/arch/sparc64/kernel/una_asm.S deleted file mode 100644 index cbb40585253c..000000000000 --- a/trunk/arch/sparc64/kernel/una_asm.S +++ /dev/null @@ -1,153 +0,0 @@ -/* una_asm.S: Kernel unaligned trap assembler helpers. - * - * Copyright (C) 1996,2005 David S. Miller (davem@davemloft.net) - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - - .text - -kernel_unaligned_trap_fault: - call kernel_mna_trap_fault - nop - retl - nop - .size kern_unaligned_trap_fault, .-kern_unaligned_trap_fault - - .globl __do_int_store -__do_int_store: - rd %asi, %o4 - wr %o3, 0, %asi - ldx [%o2], %g3 - cmp %o1, 2 - be,pn %icc, 2f - cmp %o1, 4 - be,pt %icc, 1f - srlx %g3, 24, %g2 - srlx %g3, 56, %g1 - srlx %g3, 48, %g7 -4: stba %g1, [%o0] %asi - srlx %g3, 40, %g1 -5: stba %g7, [%o0 + 1] %asi - srlx %g3, 32, %g7 -6: stba %g1, [%o0 + 2] %asi -7: stba %g7, [%o0 + 3] %asi - srlx %g3, 16, %g1 -8: stba %g2, [%o0 + 4] %asi - srlx %g3, 8, %g7 -9: stba %g1, [%o0 + 5] %asi -10: stba %g7, [%o0 + 6] %asi - ba,pt %xcc, 0f -11: stba %g3, [%o0 + 7] %asi -1: srl %g3, 16, %g7 -12: stba %g2, [%o0] %asi - srl %g3, 8, %g2 -13: stba %g7, [%o0 + 1] %asi -14: stba %g2, [%o0 + 2] %asi - ba,pt %xcc, 0f -15: stba %g3, [%o0 + 3] %asi -2: srl %g3, 8, %g2 -16: stba %g2, [%o0] %asi -17: stba %g3, [%o0 + 1] %asi -0: - wr %o4, 0x0, %asi - retl - nop - .size __do_int_store, .-__do_int_store - - .section __ex_table - .word 4b, kernel_unaligned_trap_fault - .word 5b, kernel_unaligned_trap_fault - .word 6b, kernel_unaligned_trap_fault - .word 7b, kernel_unaligned_trap_fault - .word 8b, kernel_unaligned_trap_fault - .word 9b, kernel_unaligned_trap_fault - .word 10b, kernel_unaligned_trap_fault - .word 11b, kernel_unaligned_trap_fault - .word 12b, kernel_unaligned_trap_fault - .word 13b, kernel_unaligned_trap_fault - .word 14b, kernel_unaligned_trap_fault - .word 15b, kernel_unaligned_trap_fault - .word 16b, kernel_unaligned_trap_fault - .word 17b, kernel_unaligned_trap_fault - .previous - - .globl do_int_load -do_int_load: - rd %asi, %o5 - wr %o4, 0, %asi - cmp %o1, 8 - bge,pn %icc, 9f - cmp %o1, 4 - be,pt %icc, 6f -4: lduba [%o2] %asi, %g2 -5: lduba [%o2 + 1] %asi, %g3 - sll %g2, 8, %g2 - brz,pt %o3, 3f - add %g2, %g3, %g2 - sllx %g2, 48, %g2 - srax %g2, 48, %g2 -3: ba,pt %xcc, 0f - stx %g2, [%o0] -6: lduba [%o2 + 1] %asi, %g3 - sll %g2, 24, %g2 -7: lduba [%o2 + 2] %asi, %g7 - sll %g3, 16, %g3 -8: lduba [%o2 + 3] %asi, %g1 - sll %g7, 8, %g7 - or %g2, %g3, %g2 - or %g7, %g1, %g7 - or %g2, %g7, %g2 - brnz,a,pt %o3, 3f - sra %g2, 0, %g2 -3: ba,pt %xcc, 0f - stx %g2, [%o0] -9: lduba [%o2] %asi, %g2 -10: lduba [%o2 + 1] %asi, %g3 - sllx %g2, 56, %g2 -11: lduba [%o2 + 2] %asi, %g7 - sllx %g3, 48, %g3 -12: lduba [%o2 + 3] %asi, %g1 - sllx %g7, 40, %g7 - sllx %g1, 32, %g1 - or %g2, %g3, %g2 - or %g7, %g1, %g7 -13: lduba [%o2 + 4] %asi, %g3 - or %g2, %g7, %g7 -14: lduba [%o2 + 5] %asi, %g1 - sllx %g3, 24, %g3 -15: lduba [%o2 + 6] %asi, %g2 - sllx %g1, 16, %g1 - or %g7, %g3, %g7 -16: lduba [%o2 + 7] %asi, %g3 - sllx %g2, 8, %g2 - or %g7, %g1, %g7 - or %g2, %g3, %g2 - or %g7, %g2, %g7 - cmp %o1, 8 - be,a,pt %icc, 0f - stx %g7, [%o0] - srlx %g7, 32, %g2 - sra %g7, 0, %g7 - stx %g2, [%o0] - stx %g7, [%o0 + 8] -0: - wr %o5, 0x0, %asi - retl - nop - .size __do_int_load, .-__do_int_load - - .section __ex_table - .word 4b, kernel_unaligned_trap_fault - .word 5b, kernel_unaligned_trap_fault - .word 6b, kernel_unaligned_trap_fault - .word 7b, kernel_unaligned_trap_fault - .word 8b, kernel_unaligned_trap_fault - .word 9b, kernel_unaligned_trap_fault - .word 10b, kernel_unaligned_trap_fault - .word 11b, kernel_unaligned_trap_fault - .word 12b, kernel_unaligned_trap_fault - .word 13b, kernel_unaligned_trap_fault - .word 14b, kernel_unaligned_trap_fault - .word 15b, kernel_unaligned_trap_fault - .word 16b, kernel_unaligned_trap_fault - .previous diff --git a/trunk/arch/sparc64/kernel/unaligned.c b/trunk/arch/sparc64/kernel/unaligned.c index 11c3e88732e4..4372bf32ecf6 100644 --- a/trunk/arch/sparc64/kernel/unaligned.c +++ b/trunk/arch/sparc64/kernel/unaligned.c @@ -180,28 +180,169 @@ static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs) die_if_kernel(str, regs); } -extern void do_int_load(unsigned long *dest_reg, int size, - unsigned long *saddr, int is_signed, int asi); +#define do_integer_load(dest_reg, size, saddr, is_signed, asi, errh) ({ \ +__asm__ __volatile__ ( \ + "wr %4, 0, %%asi\n\t" \ + "cmp %1, 8\n\t" \ + "bge,pn %%icc, 9f\n\t" \ + " cmp %1, 4\n\t" \ + "be,pt %%icc, 6f\n" \ +"4:\t" " lduba [%2] %%asi, %%l1\n" \ +"5:\t" "lduba [%2 + 1] %%asi, %%l2\n\t" \ + "sll %%l1, 8, %%l1\n\t" \ + "brz,pt %3, 3f\n\t" \ + " add %%l1, %%l2, %%l1\n\t" \ + "sllx %%l1, 48, %%l1\n\t" \ + "srax %%l1, 48, %%l1\n" \ +"3:\t" "ba,pt %%xcc, 0f\n\t" \ + " stx %%l1, [%0]\n" \ +"6:\t" "lduba [%2 + 1] %%asi, %%l2\n\t" \ + "sll %%l1, 24, %%l1\n" \ +"7:\t" "lduba [%2 + 2] %%asi, %%g7\n\t" \ + "sll %%l2, 16, %%l2\n" \ +"8:\t" "lduba [%2 + 3] %%asi, %%g1\n\t" \ + "sll %%g7, 8, %%g7\n\t" \ + "or %%l1, %%l2, %%l1\n\t" \ + "or %%g7, %%g1, %%g7\n\t" \ + "or %%l1, %%g7, %%l1\n\t" \ + "brnz,a,pt %3, 3f\n\t" \ + " sra %%l1, 0, %%l1\n" \ +"3:\t" "ba,pt %%xcc, 0f\n\t" \ + " stx %%l1, [%0]\n" \ +"9:\t" "lduba [%2] %%asi, %%l1\n" \ +"10:\t" "lduba [%2 + 1] %%asi, %%l2\n\t" \ + "sllx %%l1, 56, %%l1\n" \ +"11:\t" "lduba [%2 + 2] %%asi, %%g7\n\t" \ + "sllx %%l2, 48, %%l2\n" \ +"12:\t" "lduba [%2 + 3] %%asi, %%g1\n\t" \ + "sllx %%g7, 40, %%g7\n\t" \ + "sllx %%g1, 32, %%g1\n\t" \ + "or %%l1, %%l2, %%l1\n\t" \ + "or %%g7, %%g1, %%g7\n" \ +"13:\t" "lduba [%2 + 4] %%asi, %%l2\n\t" \ + "or %%l1, %%g7, %%g7\n" \ +"14:\t" "lduba [%2 + 5] %%asi, %%g1\n\t" \ + "sllx %%l2, 24, %%l2\n" \ +"15:\t" "lduba [%2 + 6] %%asi, %%l1\n\t" \ + "sllx %%g1, 16, %%g1\n\t" \ + "or %%g7, %%l2, %%g7\n" \ +"16:\t" "lduba [%2 + 7] %%asi, %%l2\n\t" \ + "sllx %%l1, 8, %%l1\n\t" \ + "or %%g7, %%g1, %%g7\n\t" \ + "or %%l1, %%l2, %%l1\n\t" \ + "or %%g7, %%l1, %%g7\n\t" \ + "cmp %1, 8\n\t" \ + "be,a,pt %%icc, 0f\n\t" \ + " stx %%g7, [%0]\n\t" \ + "srlx %%g7, 32, %%l1\n\t" \ + "sra %%g7, 0, %%g7\n\t" \ + "stx %%l1, [%0]\n\t" \ + "stx %%g7, [%0 + 8]\n" \ +"0:\n\t" \ + "wr %%g0, %5, %%asi\n\n\t" \ + ".section __ex_table\n\t" \ + ".word 4b, " #errh "\n\t" \ + ".word 5b, " #errh "\n\t" \ + ".word 6b, " #errh "\n\t" \ + ".word 7b, " #errh "\n\t" \ + ".word 8b, " #errh "\n\t" \ + ".word 9b, " #errh "\n\t" \ + ".word 10b, " #errh "\n\t" \ + ".word 11b, " #errh "\n\t" \ + ".word 12b, " #errh "\n\t" \ + ".word 13b, " #errh "\n\t" \ + ".word 14b, " #errh "\n\t" \ + ".word 15b, " #errh "\n\t" \ + ".word 16b, " #errh "\n\n\t" \ + ".previous\n\t" \ + : : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed), \ + "r" (asi), "i" (ASI_AIUS) \ + : "l1", "l2", "g7", "g1", "cc"); \ +}) -extern void __do_int_store(unsigned long *dst_addr, int size, - unsigned long *src_val, int asi); - -static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, - struct pt_regs *regs, int asi) -{ - unsigned long zero = 0; - unsigned long *src_val = &zero; - - if (size == 16) { - size = 8; - zero = (((long)(reg_num ? - (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) | - (unsigned)fetch_reg(reg_num + 1, regs); - } else if (reg_num) { - src_val = fetch_reg_addr(reg_num, regs); - } - __do_int_store(dst_addr, size, src_val, asi); -} +#define store_common(dst_addr, size, src_val, asi, errh) ({ \ +__asm__ __volatile__ ( \ + "wr %3, 0, %%asi\n\t" \ + "ldx [%2], %%l1\n" \ + "cmp %1, 2\n\t" \ + "be,pn %%icc, 2f\n\t" \ + " cmp %1, 4\n\t" \ + "be,pt %%icc, 1f\n\t" \ + " srlx %%l1, 24, %%l2\n\t" \ + "srlx %%l1, 56, %%g1\n\t" \ + "srlx %%l1, 48, %%g7\n" \ +"4:\t" "stba %%g1, [%0] %%asi\n\t" \ + "srlx %%l1, 40, %%g1\n" \ +"5:\t" "stba %%g7, [%0 + 1] %%asi\n\t" \ + "srlx %%l1, 32, %%g7\n" \ +"6:\t" "stba %%g1, [%0 + 2] %%asi\n" \ +"7:\t" "stba %%g7, [%0 + 3] %%asi\n\t" \ + "srlx %%l1, 16, %%g1\n" \ +"8:\t" "stba %%l2, [%0 + 4] %%asi\n\t" \ + "srlx %%l1, 8, %%g7\n" \ +"9:\t" "stba %%g1, [%0 + 5] %%asi\n" \ +"10:\t" "stba %%g7, [%0 + 6] %%asi\n\t" \ + "ba,pt %%xcc, 0f\n" \ +"11:\t" " stba %%l1, [%0 + 7] %%asi\n" \ +"1:\t" "srl %%l1, 16, %%g7\n" \ +"12:\t" "stba %%l2, [%0] %%asi\n\t" \ + "srl %%l1, 8, %%l2\n" \ +"13:\t" "stba %%g7, [%0 + 1] %%asi\n" \ +"14:\t" "stba %%l2, [%0 + 2] %%asi\n\t" \ + "ba,pt %%xcc, 0f\n" \ +"15:\t" " stba %%l1, [%0 + 3] %%asi\n" \ +"2:\t" "srl %%l1, 8, %%l2\n" \ +"16:\t" "stba %%l2, [%0] %%asi\n" \ +"17:\t" "stba %%l1, [%0 + 1] %%asi\n" \ +"0:\n\t" \ + "wr %%g0, %4, %%asi\n\n\t" \ + ".section __ex_table\n\t" \ + ".word 4b, " #errh "\n\t" \ + ".word 5b, " #errh "\n\t" \ + ".word 6b, " #errh "\n\t" \ + ".word 7b, " #errh "\n\t" \ + ".word 8b, " #errh "\n\t" \ + ".word 9b, " #errh "\n\t" \ + ".word 10b, " #errh "\n\t" \ + ".word 11b, " #errh "\n\t" \ + ".word 12b, " #errh "\n\t" \ + ".word 13b, " #errh "\n\t" \ + ".word 14b, " #errh "\n\t" \ + ".word 15b, " #errh "\n\t" \ + ".word 16b, " #errh "\n\t" \ + ".word 17b, " #errh "\n\n\t" \ + ".previous\n\t" \ + : : "r" (dst_addr), "r" (size), "r" (src_val), "r" (asi), "i" (ASI_AIUS)\ + : "l1", "l2", "g7", "g1", "cc"); \ +}) + +#define do_integer_store(reg_num, size, dst_addr, regs, asi, errh) ({ \ + unsigned long zero = 0; \ + unsigned long *src_val = &zero; \ + \ + if (size == 16) { \ + size = 8; \ + zero = (((long)(reg_num ? \ + (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) | \ + (unsigned)fetch_reg(reg_num + 1, regs); \ + } else if (reg_num) src_val = fetch_reg_addr(reg_num, regs); \ + store_common(dst_addr, size, src_val, asi, errh); \ +}) + +extern void smp_capture(void); +extern void smp_release(void); + +#define do_atomic(srcdest_reg, mem, errh) ({ \ + unsigned long flags, tmp; \ + \ + smp_capture(); \ + local_irq_save(flags); \ + tmp = *srcdest_reg; \ + do_integer_load(srcdest_reg, 4, mem, 0, errh); \ + store_common(mem, 4, &tmp, errh); \ + local_irq_restore(flags); \ + smp_release(); \ +}) static inline void advance(struct pt_regs *regs) { @@ -223,29 +364,24 @@ static inline int ok_for_kernel(unsigned int insn) return !floating_point_load_or_store_p(insn); } -void kernel_mna_trap_fault(void) +void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("kernel_mna_trap_fault"); + +void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) { - struct pt_regs *regs = current_thread_info()->kern_una_regs; - unsigned int insn = current_thread_info()->kern_una_insn; - unsigned long g2 = regs->u_regs[UREG_G2]; + unsigned long g2 = regs->u_regs [UREG_G2]; unsigned long fixup = search_extables_range(regs->tpc, &g2); if (!fixup) { - unsigned long address; - - address = compute_effective_address(regs, insn, - ((insn >> 25) & 0x1f)); + unsigned long address = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f)); if (address < PAGE_SIZE) { - printk(KERN_ALERT "Unable to handle kernel NULL " - "pointer dereference in mna handler"); + printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference in mna handler"); } else - printk(KERN_ALERT "Unable to handle kernel paging " - "request in mna handler"); + printk(KERN_ALERT "Unable to handle kernel paging request in mna handler"); printk(KERN_ALERT " at virtual address %016lx\n",address); - printk(KERN_ALERT "current->{active_,}mm->context = %016lx\n", + printk(KERN_ALERT "current->{mm,active_mm}->context = %016lx\n", (current->mm ? CTX_HWBITS(current->mm->context) : CTX_HWBITS(current->active_mm->context))); - printk(KERN_ALERT "current->{active_,}mm->pgd = %016lx\n", + printk(KERN_ALERT "current->{mm,active_mm}->pgd = %016lx\n", (current->mm ? (unsigned long) current->mm->pgd : (unsigned long) current->active_mm->pgd)); die_if_kernel("Oops", regs); @@ -264,41 +400,48 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u enum direction dir = decode_direction(insn); int size = decode_access_size(insn); - current_thread_info()->kern_una_regs = regs; - current_thread_info()->kern_una_insn = insn; - if (!ok_for_kernel(insn) || dir == both) { - printk("Unsupported unaligned load/store trap for kernel " - "at <%016lx>.\n", regs->tpc); - unaligned_panic("Kernel does fpu/atomic " - "unaligned load/store.", regs); - - kernel_mna_trap_fault(); + printk("Unsupported unaligned load/store trap for kernel at <%016lx>.\n", + regs->tpc); + unaligned_panic("Kernel does fpu/atomic unaligned load/store.", regs); + + __asm__ __volatile__ ("\n" +"kernel_unaligned_trap_fault:\n\t" + "mov %0, %%o0\n\t" + "call kernel_mna_trap_fault\n\t" + " mov %1, %%o1\n\t" + : + : "r" (regs), "r" (insn) + : "o0", "o1", "o2", "o3", "o4", "o5", "o7", + "g1", "g2", "g3", "g4", "g7", "cc"); } else { - unsigned long addr; + unsigned long addr = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f)); - addr = compute_effective_address(regs, insn, - ((insn >> 25) & 0x1f)); #ifdef DEBUG_MNA - printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] " - "retpc[%016lx]\n", - regs->tpc, dirstrings[dir], addr, size, - regs->u_regs[UREG_RETPC]); + printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] retpc[%016lx]\n", + regs->tpc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]); #endif switch (dir) { case load: - do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs), - size, (unsigned long *) addr, - decode_signedness(insn), - decode_asi(insn, regs)); + do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs), + size, (unsigned long *) addr, + decode_signedness(insn), decode_asi(insn, regs), + kernel_unaligned_trap_fault); break; case store: - do_int_store(((insn>>25)&0x1f), size, - (unsigned long *) addr, regs, - decode_asi(insn, regs)); + do_integer_store(((insn>>25)&0x1f), size, + (unsigned long *) addr, regs, + decode_asi(insn, regs), + kernel_unaligned_trap_fault); break; - +#if 0 /* unsupported */ + case both: + do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs), + (unsigned long *) addr, + kernel_unaligned_trap_fault); + break; +#endif default: panic("Impossible kernel unaligned trap."); /* Not reached... */ diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index 368b8fb14023..d75c96de96e4 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -8970,6 +8970,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) tp->phy_id = hw_phy_id; if (hw_phy_id_masked == PHY_ID_BCM8002) tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + else + tp->tg3_flags2 &= ~TG3_FLG2_PHY_SERDES; } else { if (tp->phy_id != PHY_ID_INVALID) { /* Do nothing, phy ID already set up in diff --git a/trunk/fs/afs/mntpt.c b/trunk/fs/afs/mntpt.c index 31ee06590de5..bfc28abe1cb1 100644 --- a/trunk/fs/afs/mntpt.c +++ b/trunk/fs/afs/mntpt.c @@ -30,7 +30,7 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd); static int afs_mntpt_open(struct inode *inode, struct file *file); -static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); +static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); struct file_operations afs_mntpt_file_operations = { .open = afs_mntpt_open, @@ -233,7 +233,7 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) /* * follow a link from a mountpoint directory, thus causing it to be mounted */ -static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) +static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) { struct vfsmount *newmnt; struct dentry *old_dentry; @@ -249,7 +249,7 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) newmnt = afs_mntpt_do_automount(dentry); if (IS_ERR(newmnt)) { path_release(nd); - return (void *)newmnt; + return PTR_ERR(newmnt); } old_dentry = nd->dentry; @@ -267,7 +267,7 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) } kleave(" = %d", err); - return ERR_PTR(err); + return err; } /* end afs_mntpt_follow_link() */ /*****************************************************************************/ diff --git a/trunk/fs/autofs/symlink.c b/trunk/fs/autofs/symlink.c index 52e8772b066e..f028396f1383 100644 --- a/trunk/fs/autofs/symlink.c +++ b/trunk/fs/autofs/symlink.c @@ -12,12 +12,11 @@ #include "autofs_i.h" -/* Nothing to release.. */ -static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd) +static int autofs_follow_link(struct dentry *dentry, struct nameidata *nd) { char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data; nd_set_link(nd, s); - return NULL; + return 0; } struct inode_operations autofs_symlink_inode_operations = { diff --git a/trunk/fs/autofs4/symlink.c b/trunk/fs/autofs4/symlink.c index 2ea2c98fd84b..c265a66edf0f 100644 --- a/trunk/fs/autofs4/symlink.c +++ b/trunk/fs/autofs4/symlink.c @@ -12,11 +12,11 @@ #include "autofs_i.h" -static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) +static int autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) { struct autofs_info *ino = autofs4_dentry_ino(dentry); nd_set_link(nd, (char *)ino->u.symlink); - return NULL; + return 0; } struct inode_operations autofs4_symlink_inode_operations = { diff --git a/trunk/fs/befs/linuxvfs.c b/trunk/fs/befs/linuxvfs.c index abf950e5b647..de5bb280a828 100644 --- a/trunk/fs/befs/linuxvfs.c +++ b/trunk/fs/befs/linuxvfs.c @@ -41,8 +41,8 @@ static struct inode *befs_alloc_inode(struct super_block *sb); static void befs_destroy_inode(struct inode *inode); static int befs_init_inodecache(void); static void befs_destroy_inodecache(void); -static void *befs_follow_link(struct dentry *, struct nameidata *); -static void befs_put_link(struct dentry *, struct nameidata *, void *); +static int befs_follow_link(struct dentry *, struct nameidata *); +static void befs_put_link(struct dentry *, struct nameidata *); static int befs_utf2nls(struct super_block *sb, const char *in, int in_len, char **out, int *out_len); static int befs_nls2utf(struct super_block *sb, const char *in, int in_len, @@ -487,10 +487,10 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd) } nd_set_link(nd, link); - return NULL; + return 0; } -static void befs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) +static void befs_put_link(struct dentry *dentry, struct nameidata *nd) { befs_inode_info *befs_ino = BEFS_I(dentry->d_inode); if (befs_ino->i_flags & BEFS_LONG_SYMLINK) { diff --git a/trunk/fs/cifs/cifsfs.h b/trunk/fs/cifs/cifsfs.h index 1fd21f66f243..78af5850c558 100644 --- a/trunk/fs/cifs/cifsfs.h +++ b/trunk/fs/cifs/cifsfs.h @@ -83,8 +83,8 @@ extern int cifs_dir_notify(struct file *, unsigned long arg); extern struct dentry_operations cifs_dentry_ops; /* Functions related to symlinks */ -extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); -extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *); +extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd); +extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd); extern int cifs_readlink(struct dentry *direntry, char __user *buffer, int buflen); extern int cifs_symlink(struct inode *inode, struct dentry *direntry, diff --git a/trunk/fs/cifs/link.c b/trunk/fs/cifs/link.c index ab925ef4f863..bde0fabfece0 100644 --- a/trunk/fs/cifs/link.c +++ b/trunk/fs/cifs/link.c @@ -92,7 +92,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, return rc; } -void * +int cifs_follow_link(struct dentry *direntry, struct nameidata *nd) { struct inode *inode = direntry->d_inode; @@ -148,7 +148,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) out_no_free: FreeXid(xid); nd_set_link(nd, target_path); - return NULL; /* No cookie */ + return 0; } int @@ -330,7 +330,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) return rc; } -void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie) +void cifs_put_link(struct dentry *direntry, struct nameidata *nd) { char *p = nd_get_link(nd); if (!IS_ERR(p)) diff --git a/trunk/fs/devfs/base.c b/trunk/fs/devfs/base.c index 8b679b67e5e0..1ecfe1f184d4 100644 --- a/trunk/fs/devfs/base.c +++ b/trunk/fs/devfs/base.c @@ -2491,11 +2491,11 @@ static int devfs_mknod(struct inode *dir, struct dentry *dentry, int mode, return 0; } /* End Function devfs_mknod */ -static void *devfs_follow_link(struct dentry *dentry, struct nameidata *nd) +static int devfs_follow_link(struct dentry *dentry, struct nameidata *nd) { struct devfs_entry *p = get_devfs_entry_from_vfs_inode(dentry->d_inode); nd_set_link(nd, p ? p->u.symlink.linkname : ERR_PTR(-ENODEV)); - return NULL; + return 0; } /* End Function devfs_follow_link */ static struct inode_operations devfs_iops = { diff --git a/trunk/fs/ext2/symlink.c b/trunk/fs/ext2/symlink.c index 1e67d87cfa91..9f7bac01d557 100644 --- a/trunk/fs/ext2/symlink.c +++ b/trunk/fs/ext2/symlink.c @@ -21,11 +21,11 @@ #include "xattr.h" #include -static void *ext2_follow_link(struct dentry *dentry, struct nameidata *nd) +static int ext2_follow_link(struct dentry *dentry, struct nameidata *nd) { struct ext2_inode_info *ei = EXT2_I(dentry->d_inode); nd_set_link(nd, (char *)ei->i_data); - return NULL; + return 0; } struct inode_operations ext2_symlink_inode_operations = { diff --git a/trunk/fs/ext3/symlink.c b/trunk/fs/ext3/symlink.c index 4f79122cde67..8c3e72818fb0 100644 --- a/trunk/fs/ext3/symlink.c +++ b/trunk/fs/ext3/symlink.c @@ -23,11 +23,11 @@ #include #include "xattr.h" -static void * ext3_follow_link(struct dentry *dentry, struct nameidata *nd) +static int ext3_follow_link(struct dentry *dentry, struct nameidata *nd) { struct ext3_inode_info *ei = EXT3_I(dentry->d_inode); nd_set_link(nd, (char*)ei->i_data); - return NULL; + return 0; } struct inode_operations ext3_symlink_inode_operations = { diff --git a/trunk/fs/freevxfs/vxfs_immed.c b/trunk/fs/freevxfs/vxfs_immed.c index b20c3efa364b..ac677ab262b2 100644 --- a/trunk/fs/freevxfs/vxfs_immed.c +++ b/trunk/fs/freevxfs/vxfs_immed.c @@ -38,7 +38,7 @@ #include "vxfs_inode.h" -static void * vxfs_immed_follow_link(struct dentry *, struct nameidata *); +static int vxfs_immed_follow_link(struct dentry *, struct nameidata *); static int vxfs_immed_readpage(struct file *, struct page *); @@ -77,7 +77,7 @@ vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np) { struct vxfs_inode_info *vip = VXFS_INO(dp->d_inode); nd_set_link(np, vip->vii_immed.vi_immed); - return NULL; + return 0; } /** diff --git a/trunk/fs/jffs2/symlink.c b/trunk/fs/jffs2/symlink.c index 82ef484f5e12..65ab6b001dca 100644 --- a/trunk/fs/jffs2/symlink.c +++ b/trunk/fs/jffs2/symlink.c @@ -18,7 +18,7 @@ #include #include "nodelist.h" -static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd); +static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd); struct inode_operations jffs2_symlink_inode_operations = { @@ -27,10 +27,9 @@ struct inode_operations jffs2_symlink_inode_operations = .setattr = jffs2_setattr }; -static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) +static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) { struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); - char *p = (char *)f->dents; /* * We don't acquire the f->sem mutex here since the only data we @@ -46,20 +45,19 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) * nd_set_link() call. */ - if (!p) { + if (!f->dents) { printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); - p = ERR_PTR(-EIO); - } else { - D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->dents)); + return -EIO; } + D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->dents)); - nd_set_link(nd, p); + nd_set_link(nd, (char *)f->dents); /* * We unlock the f->sem mutex but VFS will use the f->dents string. This is safe * since the only way that may cause f->dents to be changed is iput() operation. * But VFS will not use f->dents after iput() has been called. */ - return NULL; + return 0; } diff --git a/trunk/fs/jfs/symlink.c b/trunk/fs/jfs/symlink.c index 16477b3835e1..287d8d6c3cfd 100644 --- a/trunk/fs/jfs/symlink.c +++ b/trunk/fs/jfs/symlink.c @@ -22,11 +22,11 @@ #include "jfs_inode.h" #include "jfs_xattr.h" -static void *jfs_follow_link(struct dentry *dentry, struct nameidata *nd) +static int jfs_follow_link(struct dentry *dentry, struct nameidata *nd) { char *s = JFS_IP(dentry->d_inode)->i_inline; nd_set_link(nd, s); - return NULL; + return 0; } struct inode_operations jfs_symlink_inode_operations = { diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index 6ec1f0fefc5b..b85f158aef0c 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -501,7 +501,6 @@ struct path { static inline int __do_follow_link(struct path *path, struct nameidata *nd) { int error; - void *cookie; struct dentry *dentry = path->dentry; touch_atime(path->mnt, dentry); @@ -509,15 +508,13 @@ static inline int __do_follow_link(struct path *path, struct nameidata *nd) if (path->mnt == nd->mnt) mntget(path->mnt); - cookie = dentry->d_inode->i_op->follow_link(dentry, nd); - error = PTR_ERR(cookie); - if (!IS_ERR(cookie)) { + error = dentry->d_inode->i_op->follow_link(dentry, nd); + if (!error) { char *s = nd_get_link(nd); - error = 0; if (s) error = __vfs_follow_link(nd, s); if (dentry->d_inode->i_op->put_link) - dentry->d_inode->i_op->put_link(dentry, nd, cookie); + dentry->d_inode->i_op->put_link(dentry, nd); } dput(dentry); mntput(path->mnt); @@ -2347,17 +2344,15 @@ int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const c int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) { struct nameidata nd; - void *cookie; - + int res; nd.depth = 0; - cookie = dentry->d_inode->i_op->follow_link(dentry, &nd); - if (!IS_ERR(cookie)) { - int res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); + res = dentry->d_inode->i_op->follow_link(dentry, &nd); + if (!res) { + res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); if (dentry->d_inode->i_op->put_link) - dentry->d_inode->i_op->put_link(dentry, &nd, cookie); - cookie = ERR_PTR(res); + dentry->d_inode->i_op->put_link(dentry, &nd); } - return PTR_ERR(cookie); + return res; } int vfs_follow_link(struct nameidata *nd, const char *link) @@ -2400,20 +2395,23 @@ int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) return res; } -void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd) +int page_follow_link_light(struct dentry *dentry, struct nameidata *nd) { - struct page *page = NULL; + struct page *page; nd_set_link(nd, page_getlink(dentry, &page)); - return page; + return 0; } -void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) +void page_put_link(struct dentry *dentry, struct nameidata *nd) { - struct page *page = cookie; - - if (page) { + if (!IS_ERR(nd_get_link(nd))) { + struct page *page; + page = find_get_page(dentry->d_inode->i_mapping, 0); + if (!page) + BUG(); kunmap(page); page_cache_release(page); + page_cache_release(page); } } diff --git a/trunk/fs/nfs/dir.c b/trunk/fs/nfs/dir.c index 2df639f143e8..147cbf9261ce 100644 --- a/trunk/fs/nfs/dir.c +++ b/trunk/fs/nfs/dir.c @@ -939,7 +939,6 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry error = nfs_revalidate_inode(NFS_SERVER(dir), dir); if (error < 0) { res = ERR_PTR(error); - unlock_kernel(); goto out; } diff --git a/trunk/fs/nfs/symlink.c b/trunk/fs/nfs/symlink.c index 18dc95b0b646..35f106599144 100644 --- a/trunk/fs/nfs/symlink.c +++ b/trunk/fs/nfs/symlink.c @@ -27,14 +27,26 @@ /* Symlink caching in the page cache is even more simplistic * and straight-forward than readdir caching. + * + * At the beginning of the page we store pointer to struct page in question, + * simplifying nfs_put_link() (if inode got invalidated we can't find the page + * to be freed via pagecache lookup). + * The NUL-terminated string follows immediately thereafter. */ +struct nfs_symlink { + struct page *page; + char body[0]; +}; + static int nfs_symlink_filler(struct inode *inode, struct page *page) { + const unsigned int pgbase = offsetof(struct nfs_symlink, body); + const unsigned int pglen = PAGE_SIZE - pgbase; int error; lock_kernel(); - error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE); + error = NFS_PROTO(inode)->readlink(inode, page, pgbase, pglen); unlock_kernel(); if (error < 0) goto error; @@ -48,10 +60,11 @@ static int nfs_symlink_filler(struct inode *inode, struct page *page) return -EIO; } -static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd) +static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; struct page *page; + struct nfs_symlink *p; void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode)); if (err) goto read_failed; @@ -65,20 +78,28 @@ static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd) err = ERR_PTR(-EIO); goto getlink_read_error; } - nd_set_link(nd, kmap(page)); - return page; + p = kmap(page); + p->page = page; + nd_set_link(nd, p->body); + return 0; getlink_read_error: page_cache_release(page); read_failed: nd_set_link(nd, err); - return NULL; + return 0; } -static void nfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) +static void nfs_put_link(struct dentry *dentry, struct nameidata *nd) { - if (cookie) { - struct page *page = cookie; + char *s = nd_get_link(nd); + if (!IS_ERR(s)) { + struct nfs_symlink *p; + struct page *page; + + p = container_of(s, struct nfs_symlink, body[0]); + page = p->page; + kunmap(page); page_cache_release(page); } diff --git a/trunk/fs/proc/base.c b/trunk/fs/proc/base.c index 491f2d9f89ac..ace151fa4878 100644 --- a/trunk/fs/proc/base.c +++ b/trunk/fs/proc/base.c @@ -890,7 +890,7 @@ static struct file_operations proc_seccomp_operations = { }; #endif /* CONFIG_SECCOMP */ -static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) +static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; int error = -EACCES; @@ -907,7 +907,7 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt); nd->last_type = LAST_BIND; out: - return ERR_PTR(error); + return error; } static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt, @@ -1692,11 +1692,11 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer, return vfs_readlink(dentry,buffer,buflen,tmp); } -static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) +static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) { char tmp[30]; sprintf(tmp, "%d", current->tgid); - return ERR_PTR(vfs_follow_link(nd,tmp)); + return vfs_follow_link(nd,tmp); } static struct inode_operations proc_self_inode_operations = { diff --git a/trunk/fs/proc/generic.c b/trunk/fs/proc/generic.c index abe8920313fb..6c6315d04028 100644 --- a/trunk/fs/proc/generic.c +++ b/trunk/fs/proc/generic.c @@ -329,10 +329,10 @@ static void release_inode_number(unsigned int inum) spin_unlock(&proc_inum_lock); } -static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) +static int proc_follow_link(struct dentry *dentry, struct nameidata *nd) { nd_set_link(nd, PDE(dentry->d_inode)->data); - return NULL; + return 0; } static struct inode_operations proc_link_inode_operations = { diff --git a/trunk/fs/smbfs/symlink.c b/trunk/fs/smbfs/symlink.c index 0c64bc3a0127..8b069e06433d 100644 --- a/trunk/fs/smbfs/symlink.c +++ b/trunk/fs/smbfs/symlink.c @@ -34,7 +34,7 @@ int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname) return smb_proc_symlink(server_from_dentry(dentry), dentry, oldname); } -static void *smb_follow_link(struct dentry *dentry, struct nameidata *nd) +static int smb_follow_link(struct dentry *dentry, struct nameidata *nd) { char *link = __getname(); DEBUG1("followlink of %s/%s\n", DENTRY_PATH(dentry)); @@ -52,10 +52,10 @@ static void *smb_follow_link(struct dentry *dentry, struct nameidata *nd) } } nd_set_link(nd, link); - return NULL; + return 0; } -static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p) +static void smb_put_link(struct dentry *dentry, struct nameidata *nd) { char *s = nd_get_link(nd); if (!IS_ERR(s)) diff --git a/trunk/fs/sysfs/symlink.c b/trunk/fs/sysfs/symlink.c index de402fa915f2..fae57c83a722 100644 --- a/trunk/fs/sysfs/symlink.c +++ b/trunk/fs/sysfs/symlink.c @@ -151,17 +151,17 @@ static int sysfs_getlink(struct dentry *dentry, char * path) } -static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) +static int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) { int error = -ENOMEM; unsigned long page = get_zeroed_page(GFP_KERNEL); if (page) error = sysfs_getlink(dentry, (char *) page); nd_set_link(nd, error ? ERR_PTR(error) : (char *)page); - return NULL; + return 0; } -static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) +static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd) { char *page = nd_get_link(nd); if (!IS_ERR(page)) diff --git a/trunk/fs/sysv/symlink.c b/trunk/fs/sysv/symlink.c index b85ce61d635c..ed637db2dcb1 100644 --- a/trunk/fs/sysv/symlink.c +++ b/trunk/fs/sysv/symlink.c @@ -8,10 +8,10 @@ #include "sysv.h" #include -static void *sysv_follow_link(struct dentry *dentry, struct nameidata *nd) +static int sysv_follow_link(struct dentry *dentry, struct nameidata *nd) { nd_set_link(nd, (char *)SYSV_I(dentry->d_inode)->i_data); - return NULL; + return 0; } struct inode_operations sysv_fast_symlink_inode_operations = { diff --git a/trunk/fs/ufs/symlink.c b/trunk/fs/ufs/symlink.c index 337512ed5781..a0e49149098f 100644 --- a/trunk/fs/ufs/symlink.c +++ b/trunk/fs/ufs/symlink.c @@ -29,11 +29,11 @@ #include #include -static void *ufs_follow_link(struct dentry *dentry, struct nameidata *nd) +static int ufs_follow_link(struct dentry *dentry, struct nameidata *nd) { struct ufs_inode_info *p = UFS_I(dentry->d_inode); nd_set_link(nd, (char*)p->i_u1.i_symlink); - return NULL; + return 0; } struct inode_operations ufs_fast_symlink_inode_operations = { diff --git a/trunk/fs/xfs/linux-2.6/xfs_iops.c b/trunk/fs/xfs/linux-2.6/xfs_iops.c index f252605514eb..407e99359391 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_iops.c +++ b/trunk/fs/xfs/linux-2.6/xfs_iops.c @@ -374,7 +374,7 @@ linvfs_rename( * we need to be very careful about how much stack we use. * uio is kmalloced for this reason... */ -STATIC void * +STATIC int linvfs_follow_link( struct dentry *dentry, struct nameidata *nd) @@ -391,14 +391,14 @@ linvfs_follow_link( link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL); if (!link) { nd_set_link(nd, ERR_PTR(-ENOMEM)); - return NULL; + return 0; } uio = (uio_t *)kmalloc(sizeof(uio_t), GFP_KERNEL); if (!uio) { kfree(link); nd_set_link(nd, ERR_PTR(-ENOMEM)); - return NULL; + return 0; } vp = LINVFS_GET_VP(dentry->d_inode); @@ -422,10 +422,10 @@ linvfs_follow_link( kfree(uio); nd_set_link(nd, link); - return NULL; + return 0; } -static void linvfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) +static void linvfs_put_link(struct dentry *dentry, struct nameidata *nd) { char *s = nd_get_link(nd); if (!IS_ERR(s)) diff --git a/trunk/include/asm-sparc64/thread_info.h b/trunk/include/asm-sparc64/thread_info.h index c94d8b3991bd..352d9943661a 100644 --- a/trunk/include/asm-sparc64/thread_info.h +++ b/trunk/include/asm-sparc64/thread_info.h @@ -68,9 +68,6 @@ struct thread_info { struct restart_block restart_block; - struct pt_regs *kern_una_regs; - unsigned int kern_una_insn; - unsigned long fpregs[0] __attribute__ ((aligned(64))); }; @@ -106,8 +103,6 @@ struct thread_info { #define TI_PCR 0x00000490 #define TI_CEE_STUFF 0x00000498 #define TI_RESTART_BLOCK 0x000004a0 -#define TI_KUNA_REGS 0x000004c8 -#define TI_KUNA_INSN 0x000004d0 #define TI_FPREGS 0x00000500 /* We embed this in the uppermost byte of thread_info->flags */ diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 67e6732d4fdc..f9adf75fd9b4 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -993,8 +993,8 @@ struct inode_operations { int (*rename) (struct inode *, struct dentry *, struct inode *, struct dentry *); int (*readlink) (struct dentry *, char __user *,int); - void * (*follow_link) (struct dentry *, struct nameidata *); - void (*put_link) (struct dentry *, struct nameidata *, void *); + int (*follow_link) (struct dentry *, struct nameidata *); + void (*put_link) (struct dentry *, struct nameidata *); void (*truncate) (struct inode *); int (*permission) (struct inode *, int, struct nameidata *); int (*setattr) (struct dentry *, struct iattr *); @@ -1602,8 +1602,8 @@ extern struct file_operations generic_ro_fops; extern int vfs_readlink(struct dentry *, char __user *, int, const char *); extern int vfs_follow_link(struct nameidata *, const char *); extern int page_readlink(struct dentry *, char __user *, int); -extern void *page_follow_link_light(struct dentry *, struct nameidata *); -extern void page_put_link(struct dentry *, struct nameidata *, void *); +extern int page_follow_link_light(struct dentry *, struct nameidata *); +extern void page_put_link(struct dentry *, struct nameidata *); extern int page_symlink(struct inode *inode, const char *symname, int len); extern struct inode_operations page_symlink_inode_operations; extern int generic_readlink(struct dentry *, char __user *, int); diff --git a/trunk/mm/shmem.c b/trunk/mm/shmem.c index 5a81b1ee4f7a..e64fa726a790 100644 --- a/trunk/mm/shmem.c +++ b/trunk/mm/shmem.c @@ -1773,27 +1773,32 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s return 0; } -static void *shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd) +static int shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd) { nd_set_link(nd, (char *)SHMEM_I(dentry->d_inode)); - return NULL; + return 0; } -static void *shmem_follow_link(struct dentry *dentry, struct nameidata *nd) +static int shmem_follow_link(struct dentry *dentry, struct nameidata *nd) { struct page *page = NULL; int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL); nd_set_link(nd, res ? ERR_PTR(res) : kmap(page)); - return page; + return 0; } -static void shmem_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) +static void shmem_put_link(struct dentry *dentry, struct nameidata *nd) { if (!IS_ERR(nd_get_link(nd))) { - struct page *page = cookie; + struct page *page; + + page = find_get_page(dentry->d_inode->i_mapping, 0); + if (!page) + BUG(); kunmap(page); mark_page_accessed(page); page_cache_release(page); + page_cache_release(page); } } diff --git a/trunk/scripts/mod/modpost.c b/trunk/scripts/mod/modpost.c index 09ffca54b373..9b9f94c915d2 100644 --- a/trunk/scripts/mod/modpost.c +++ b/trunk/scripts/mod/modpost.c @@ -359,16 +359,11 @@ handle_modversions(struct module *mod, struct elf_info *info, /* ignore __this_module, it will be resolved shortly */ if (strcmp(symname, MODULE_SYMBOL_PREFIX "__this_module") == 0) break; -/* cope with newer glibc (2.3.4 or higher) STT_ definition in elf.h */ -#if defined(STT_REGISTER) || defined(STT_SPARC_REGISTER) -/* add compatibility with older glibc */ -#ifndef STT_SPARC_REGISTER -#define STT_SPARC_REGISTER STT_REGISTER -#endif +#ifdef STT_REGISTER if (info->hdr->e_machine == EM_SPARC || info->hdr->e_machine == EM_SPARCV9) { /* Ignore register directives. */ - if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER) + if (ELF_ST_TYPE(sym->st_info) == STT_REGISTER) break; } #endif