diff options
367 files changed, 4946 insertions, 5030 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index dd0bfc291a6..fe11fccf7e4 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -856,6 +856,49 @@ running once the system is up. mga= [HW,DRM] + migration_cost= + [KNL,SMP] debug: override scheduler migration costs + Format: <level-1-usecs>,<level-2-usecs>,... + This debugging option can be used to override the + default scheduler migration cost matrix. The numbers + are indexed by 'CPU domain distance'. + E.g. migration_cost=1000,2000,3000 on an SMT NUMA + box will set up an intra-core migration cost of + 1 msec, an inter-core migration cost of 2 msecs, + and an inter-node migration cost of 3 msecs. + + WARNING: using the wrong values here can break + scheduler performance, so it's only for scheduler + development purposes, not production environments. + + migration_debug= + [KNL,SMP] migration cost auto-detect verbosity + Format=<0|1|2> + If a system's migration matrix reported at bootup + seems erroneous then this option can be used to + increase verbosity of the detection process. + We default to 0 (no extra messages), 1 will print + some more information, and 2 will be really + verbose (probably only useful if you also have a + serial console attached to the system). + + migration_factor= + [KNL,SMP] multiply/divide migration costs by a factor + Format=<percent> + This debug option can be used to proportionally + increase or decrease the auto-detected migration + costs for all entries of the migration matrix. + E.g. migration_factor=150 will increase migration + costs by 50%. (and thus the scheduler will be less + eager migrating cache-hot tasks) + migration_factor=80 will decrease migration costs + by 20%. (thus the scheduler will be more eager to + migrate tasks) + + WARNING: using the wrong values here can break + scheduler performance, so it's only for scheduler + development purposes, not production environments. + mousedev.tap_time= [MOUSE] Maximum time between finger touching and leaving touchpad surface for touch to be considered diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index abb739b88ed..9924fd07743 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -276,7 +276,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, { extern void ret_from_fork(void); - struct thread_info *childti = p->thread_info; + struct thread_info *childti = task_thread_info(p); struct pt_regs * childregs; struct switch_stack * childstack, *stack; unsigned long stack_offset, settls; @@ -285,7 +285,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, if (!(regs->ps & 8)) stack_offset = (PAGE_SIZE-1) & (unsigned long) regs; childregs = (struct pt_regs *) - (stack_offset + PAGE_SIZE + (long) childti); + (stack_offset + PAGE_SIZE + task_stack_page(p)); *childregs = *regs; settls = regs->r20; @@ -428,30 +428,15 @@ dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti) int dump_elf_task(elf_greg_t *dest, struct task_struct *task) { - struct thread_info *ti; - struct pt_regs *pt; - - ti = task->thread_info; - pt = (struct pt_regs *)((unsigned long)ti + 2*PAGE_SIZE) - 1; - - dump_elf_thread(dest, pt, ti); - + dump_elf_thread(dest, task_pt_regs(task), task_thread_info(task)); return 1; } int dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task) { - struct thread_info *ti; - struct pt_regs *pt; - struct switch_stack *sw; - - ti = task->thread_info; - pt = (struct pt_regs *)((unsigned long)ti + 2*PAGE_SIZE) - 1; - sw = (struct switch_stack *)pt - 1; - + struct switch_stack *sw = (struct switch_stack *)task_pt_regs(task) - 1; memcpy(dest, sw->fp, 32 * 8); - return 1; } @@ -492,8 +477,8 @@ out: unsigned long thread_saved_pc(task_t *t) { - unsigned long base = (unsigned long)t->thread_info; - unsigned long fp, sp = t->thread_info->pcb.ksp; + unsigned long base = (unsigned long)task_stack_page(t); + unsigned long fp, sp = task_thread_info(t)->pcb.ksp; if (sp > base && sp+6*8 < base + 16*1024) { fp = ((unsigned long*)sp)[6]; @@ -523,7 +508,7 @@ get_wchan(struct task_struct *p) pc = thread_saved_pc(p); if (in_sched_functions(pc)) { - schedule_frame = ((unsigned long *)p->thread_info->pcb.ksp)[6]; + schedule_frame = ((unsigned long *)task_thread_info(p)->pcb.ksp)[6]; return ((unsigned long *)schedule_frame)[12]; } return pc; diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index 9969d212e94..0cd060598f9 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -72,6 +72,13 @@ enum { REG_R0 = 0, REG_F0 = 32, REG_FPCR = 63, REG_PC = 64 }; +#define PT_REG(reg) \ + (PAGE_SIZE*2 - sizeof(struct pt_regs) + offsetof(struct pt_regs, reg)) + +#define SW_REG(reg) \ + (PAGE_SIZE*2 - sizeof(struct pt_regs) - sizeof(struct switch_stack) \ + + offsetof(struct switch_stack, reg)) + static int regoff[] = { PT_REG( r0), PT_REG( r1), PT_REG( r2), PT_REG( r3), PT_REG( r4), PT_REG( r5), PT_REG( r6), PT_REG( r7), @@ -103,14 +110,14 @@ get_reg_addr(struct task_struct * task, unsigned long regno) unsigned long *addr; if (regno == 30) { - addr = &task->thread_info->pcb.usp; + addr = &task_thread_info(task)->pcb.usp; } else if (regno == 65) { - addr = &task->thread_info->pcb.unique; + addr = &task_thread_info(task)->pcb.unique; } else if (regno == 31 || regno > 65) { zero = 0; addr = &zero; } else { - addr = (void *)task->thread_info + regoff[regno]; + addr = task_stack_page(task) + regoff[regno]; } return addr; } @@ -125,7 +132,7 @@ get_reg(struct task_struct * task, unsigned long regno) if (regno == 63) { unsigned long fpcr = *get_reg_addr(task, regno); unsigned long swcr - = task->thread_info->ieee_state & IEEE_SW_MASK; + = task_thread_info(task)->ieee_state & IEEE_SW_MASK; swcr = swcr_update_status(swcr, fpcr); return fpcr | swcr; } @@ -139,8 +146,8 @@ static int put_reg(struct task_struct *task, unsigned long regno, unsigned long data) { if (regno == 63) { - task->thread_info->ieee_state - = ((task->thread_info->ieee_state & ~IEEE_SW_MASK) + task_thread_info(task)->ieee_state + = ((task_thread_info(task)->ieee_state & ~IEEE_SW_MASK) | (data & IEEE_SW_MASK)); data = (data & FPCR_DYN_MASK) | ieee_swcr_to_fpcr(data); } @@ -188,35 +195,35 @@ ptrace_set_bpt(struct task_struct * child) * branch (emulation can be tricky for fp branches). */ displ = ((s32)(insn << 11)) >> 9; - child->thread_info->bpt_addr[nsaved++] = pc + 4; + task_thread_info(child)->bpt_addr[nsaved++] = pc + 4; if (displ) /* guard against unoptimized code */ - child->thread_info->bpt_addr[nsaved++] + task_thread_info(child)->bpt_addr[nsaved++] = pc + 4 + displ; DBG(DBG_BPT, ("execing branch\n")); } else if (op_code == 0x1a) { reg_b = (insn >> 16) & 0x1f; - child->thread_info->bpt_addr[nsaved++] = get_reg(child, reg_b); + task_thread_info(child)->bpt_addr[nsaved++] = get_reg(child, reg_b); DBG(DBG_BPT, ("execing jump\n")); } else { - child->thread_info->bpt_addr[nsaved++] = pc + 4; + task_thread_info(child)->bpt_addr[nsaved++] = pc + 4; DBG(DBG_BPT, ("execing normal insn\n")); } /* install breakpoints: */ for (i = 0; i < nsaved; ++i) { - res = read_int(child, child->thread_info->bpt_addr[i], + res = read_int(child, task_thread_info(child)->bpt_addr[i], (int *) &insn); if (res < 0) return res; - child->thread_info->bpt_insn[i] = insn; + task_thread_info(child)->bpt_insn[i] = insn; DBG(DBG_BPT, (" -> next_pc=%lx\n", - child->thread_info->bpt_addr[i])); - res = write_int(child, child->thread_info->bpt_addr[i], + task_thread_info(child)->bpt_addr[i])); + res = write_int(child, task_thread_info(child)->bpt_addr[i], BREAKINST); if (res < 0) return res; } - child->thread_info->bpt_nsaved = nsaved; + task_thread_info(child)->bpt_nsaved = nsaved; return 0; } @@ -227,9 +234,9 @@ ptrace_set_bpt(struct task_struct * child) int ptrace_cancel_bpt(struct task_struct * child) { - int i, nsaved = child->thread_info->bpt_nsaved; + int i, nsaved = task_thread_info(child)->bpt_nsaved; - child->thread_info->bpt_nsaved = 0; + task_thread_info(child)->bpt_nsaved = 0; if (nsaved > 2) { printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); @@ -237,8 +244,8 @@ ptrace_cancel_bpt(struct task_struct * child) } for (i = 0; i < nsaved; ++i) { - write_int(child, child->thread_info->bpt_addr[i], - child->thread_info->bpt_insn[i]); + write_int(child, task_thread_info(child)->bpt_addr[i], + task_thread_info(child)->bpt_insn[i]); } return (nsaved != 0); } @@ -355,7 +362,7 @@ do_sys_ptrace(long request, long pid, long addr, long data, if (!valid_signal(data)) break; /* Mark single stepping. */ - child->thread_info->bpt_nsaved = -1; + task_thread_info(child)->bpt_nsaved = -1; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->exit_code = data; wake_up_process(child); diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index da0be346579..4b873527ce1 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -302,7 +302,7 @@ secondary_cpu_start(int cpuid, struct task_struct *idle) + hwrpb->processor_offset + cpuid * hwrpb->processor_size); hwpcb = (struct pcb_struct *) cpu->hwpcb; - ipcb = &idle->thread_info->pcb; + ipcb = &task_thread_info(idle)->pcb; /* Initialize the CPU's HWPCB to something just good enough for us to get started. Immediately after starting, we'll swpctx diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 54a21bdcba5..4b4e4cf79c8 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -342,10 +342,10 @@ void flush_thread(void) void release_thread(struct task_struct *dead_task) { #if defined(CONFIG_VFP) - vfp_release_thread(&dead_task->thread_info->vfpstate); + vfp_release_thread(&task_thread_info(dead_task)->vfpstate); #endif #if defined(CONFIG_IWMMXT) - iwmmxt_task_release(dead_task->thread_info); + iwmmxt_task_release(task_thread_info(dead_task)); #endif } @@ -355,10 +355,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs) { - struct thread_info *thread = p->thread_info; - struct pt_regs *childregs; + struct thread_info *thread = task_thread_info(p); + struct pt_regs *childregs = task_pt_regs(p); - childregs = (void *)thread + THREAD_START_SP - sizeof(*regs); *childregs = *regs; childregs->ARM_r0 = 0; childregs->ARM_sp = stack_start; @@ -460,8 +459,8 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_start = (unsigned long)(p->thread_info + 1); - stack_end = ((unsigned long)p->thread_info) + THREAD_SIZE; + stack_start = (unsigned long)end_of_stack(p); + stack_end = (unsigned long)task_stack_page(p) + THREAD_SIZE; fp = thread_saved_fp(p); do { diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 2b84f78d7b0..e591f72bcde 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -55,23 +55,6 @@ #endif /* - * Get the address of the live pt_regs for the specified task. - * These are saved onto the top kernel stack when the process - * is not running. - * - * Note: if a user thread is execve'd from kernel space, the - * kernel stack will not be empty on entry to the kernel, so - * ptracing these tasks will fail. - */ -static inline struct pt_regs * -get_user_regs(struct task_struct *task) -{ - return (struct pt_regs *) - ((unsigned long)task->thread_info + THREAD_SIZE - - 8 - sizeof(struct pt_regs)); -} - -/* * this routine will get a word off of the processes privileged stack. * the offset is how far from the base addr as stored in the THREAD. * this routine assumes that all the privileged stacks are in our @@ -79,7 +62,7 @@ get_user_regs(struct task_struct *task) */ static inline long get_user_reg(struct task_struct *task, int offset) { - return get_user_regs(task)->uregs[offset]; + return task_pt_regs(task)->uregs[offset]; } /* @@ -91,7 +74,7 @@ static inline long get_user_reg(struct task_struct *task, int offset) static inline int put_user_reg(struct task_struct *task, int offset, long data) { - struct pt_regs newregs, *regs = get_user_regs(task); + struct pt_regs newregs, *regs = task_pt_regs(task); int ret = -EINVAL; newregs = *regs; @@ -421,7 +404,7 @@ void ptrace_set_bpt(struct task_struct *child) u32 insn; int res; - regs = get_user_regs(child); + regs = task_pt_regs(child); pc = instruction_pointer(regs); if (thumb_mode(regs)) { @@ -572,7 +555,7 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off, */ static int ptrace_getregs(struct task_struct *tsk, void __user *uregs) { - struct pt_regs *regs = get_user_regs(tsk); + struct pt_regs *regs = task_pt_regs(tsk); return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0; } @@ -587,7 +570,7 @@ static int ptrace_setregs(struct task_struct *tsk, void __user *uregs) ret = -EFAULT; if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) { - struct pt_regs *regs = get_user_regs(tsk); + struct pt_regs *regs = task_pt_regs(tsk); ret = -EINVAL; if (valid_user_regs(&newregs)) { @@ -604,7 +587,7 @@ static int ptrace_setregs(struct task_struct *tsk, void __user *uregs) */ static int ptrace_getfpregs(struct task_struct *tsk, void __user *ufp) { - return copy_to_user(ufp, &tsk->thread_info->fpstate, + return copy_to_user(ufp, &task_thread_info(tsk)->fpstate, sizeof(struct user_fp)) ? -EFAULT : 0; } @@ -613,7 +596,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void __user *ufp) */ static int ptrace_setfpregs(struct task_struct *tsk, void __user *ufp) { - struct thread_info *thread = tsk->thread_info; + struct thread_info *thread = task_thread_info(tsk); thread->used_cp[1] = thread->used_cp[2] = 1; return copy_from_user(&thread->fpstate, ufp, sizeof(struct user_fp)) ? -EFAULT : 0; @@ -626,7 +609,7 @@ static int ptrace_setfpregs(struct task_struct *tsk, void __user *ufp) */ static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp) { - struct thread_info *thread = tsk->thread_info; + struct thread_info *thread = task_thread_info(tsk); void *ptr = &thread->fpstate; if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) @@ -643,7 +626,7 @@ static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp) */ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp) { - struct thread_info *thread = tsk->thread_info; + struct thread_info *thread = task_thread_info(tsk); void *ptr = &thread->fpstate; if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) @@ -779,7 +762,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) #endif case PTRACE_GET_THREAD_AREA: - ret = put_user(child->thread_info->tp_value, + ret = put_user(task_thread_info(child)->tp_value, (unsigned long __user *) data); break; diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 373c0959bc2..7338948bd7d 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -114,7 +114,7 @@ int __cpuinit __cpu_up(unsigned int cpu) * We need to tell the secondary core where to find * its stack and the page tables. */ - secondary_data.stack = (void *)idle->thread_info + THREAD_START_SP; + secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; secondary_data.pgdir = virt_to_phys(pgd); wmb(); @@ -245,7 +245,7 @@ void __cpuexit cpu_die(void) __asm__("mov sp, %0\n" " b secondary_start_kernel" : - : "r" ((void *)current->thread_info + THREAD_SIZE - 8)); + : "r" (task_stack_page(current) + THREAD_SIZE - 8)); } #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index c9fe6f5f7ee..93cfd3ffcc7 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -164,7 +164,7 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) } else if (verify_stack(fp)) { printk("invalid frame pointer 0x%08x", fp); ok = 0; - } else if (fp < (unsigned long)(tsk->thread_info + 1)) + } else if (fp < (unsigned long)end_of_stack(tsk)) printk("frame pointer underflow"); printk("\n"); @@ -210,7 +210,7 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p if (!user_mode(regs) || in_interrupt()) { dump_mem("Stack: ", regs->ARM_sp, - THREAD_SIZE + (unsigned long)tsk->thread_info); + THREAD_SIZE + (unsigned long)task_stack_page(tsk)); dump_backtrace(regs, tsk); dump_instr(regs); } diff --git a/arch/arm26/kernel/process.c b/arch/arm26/kernel/process.c index 15833a0057d..38630565917 100644 --- a/arch/arm26/kernel/process.c +++ b/arch/arm26/kernel/process.c @@ -277,10 +277,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, unsigned long unused, struct task_struct *p, struct pt_regs *regs) { - struct thread_info *thread = p->thread_info; - struct pt_regs *childregs; + struct thread_info *thread = task_thread_info(p); + struct pt_regs *childregs = task_pt_regs(p); - childregs = __get_user_regs(thread); *childregs = *regs; childregs->ARM_r0 = 0; childregs->ARM_sp = stack_start; diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index 4e6b7356a72..3c3371d4683 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -40,21 +40,6 @@ #define BREAKINST_ARM 0xef9f0001 /* - * Get the address of the live pt_regs for the specified task. - * These are saved onto the top kernel stack when the process - * is not running. - * - * Note: if a user thread is execve'd from kernel space, the - * kernel stack will not be empty on entry to the kernel, so - * ptracing these tasks will fail. - */ -static inline struct pt_regs * -get_user_regs(struct task_struct *task) -{ - return __get_user_regs(task->thread_info); -} - -/* * this routine will get a word off of the processes privileged stack. * the offset is how far from the base addr as stored in the THREAD. * this routine assumes that all the privileged stacks are in our @@ -62,7 +47,7 @@ get_user_regs(struct task_struct *task) */ static inline long get_user_reg(struct task_struct *task, int offset) { - return get_user_regs(task)->uregs[offset]; + return task_pt_regs(task)->uregs[offset]; } /* @@ -74,7 +59,7 @@ static inline long get_user_reg(struct task_struct *task, int offset) static inline int put_user_reg(struct task_struct *task, int offset, long data) { - struct pt_regs newregs, *regs = get_user_regs(task); + struct pt_regs newregs, *regs = task_pt_regs(task); int ret = -EINVAL; newregs = *regs; @@ -377,7 +362,7 @@ void ptrace_set_bpt(struct task_struct *child) u32 insn; int res; - regs = get_user_regs(child); + regs = task_pt_regs(child); pc = instruction_pointer(regs); res = read_instr(child, pc, &insn); @@ -500,7 +485,7 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off, */ static int ptrace_getregs(struct task_struct *tsk, void *uregs) { - struct pt_regs *regs = get_user_regs(tsk); + struct pt_regs *regs = task_pt_regs(tsk); return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0; } @@ -515,7 +500,7 @@ static int ptrace_setregs(struct task_struct *tsk, void *uregs) ret = -EFAULT; if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) { - struct pt_regs *regs = get_user_regs(tsk); + struct pt_regs *regs = task_pt_regs(tsk); ret = -EINVAL; if (valid_user_regs(&newregs)) { @@ -532,7 +517,7 @@ static int ptrace_setregs(struct task_struct *tsk, void *uregs) */ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp) { - return copy_to_user(ufp, &tsk->thread_info->fpstate, + return copy_to_user(ufp, &task_thread_info(tsk)->fpstate, sizeof(struct user_fp)) ? -EFAULT : 0; } @@ -542,7 +527,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp) static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) { set_stopped_child_used_math(tsk); - return copy_from_user(&tsk->thread_info->fpstate, ufp, + return copy_from_user(&task_threas_info(tsk)->fpstate, ufp, sizeof(struct user_fp)) ? -EFAULT : 0; } diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c index f64f5902239..5847ea5d774 100644 --- a/arch/arm26/kernel/traps.c +++ b/arch/arm26/kernel/traps.c @@ -132,7 +132,7 @@ static void dump_instr(struct pt_regs *regs) /*static*/ void __dump_stack(struct task_struct *tsk, unsigned long sp) { - dump_mem("Stack: ", sp, 8192+(unsigned long)tsk->thread_info); + dump_mem("Stack: ", sp, 8192+(unsigned long)task_stack_page(tsk)); } void dump_stack(void) @@ -158,7 +158,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) } else if (verify_stack(fp)) { printk("invalid frame pointer 0x%08x", fp); ok = 0; - } else if (fp < (unsigned long)(tsk->thread_info + 1)) + } else if (fp < (unsigned long)end_of_stack(tsk)) printk("frame pointer underflow"); printk("\n"); @@ -168,7 +168,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) /* FIXME - this is probably wrong.. */ void show_stack(struct task_struct *task, unsigned long *sp) { - dump_mem("Stack: ", (unsigned long)sp, 8192+(unsigned long)task->thread_info); + dump_mem("Stack: ", (unsigned long)sp, 8192+(unsigned long)task_stack_page(task)); } DEFINE_SPINLOCK(die_lock); @@ -187,7 +187,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) printk("CPU: %d\n", smp_processor_id()); show_regs(regs); printk("Process %s (pid: %d, stack limit = 0x%p)\n", - current->comm, current->pid, tsk->thread_info + 1); + current->comm, current->pid, end_of_stack(tsk)); if (!user_mode(regs) || in_interrupt()) { __dump_stack(tsk, (unsigned long)(regs + 1)); diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c index 69e28b4057e..0a675ce9e09 100644 --- a/arch/cris/arch-v10/kernel/process.c +++ b/arch/cris/arch-v10/kernel/process.c @@ -79,7 +79,7 @@ void hard_reset_now (void) */ unsigned long thread_saved_pc(struct task_struct *t) { - return (unsigned long)user_regs(t->thread_info)->irp; + return task_pt_regs(t)->irp; } static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg) @@ -128,7 +128,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, * remember that the task_struct doubles as the kernel stack for the task */ - childregs = user_regs(p->thread_info); + childregs = task_pt_regs(p); *childregs = *regs; /* struct copy of pt_regs */ diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index 6cbd34a27b9..f214f74f264 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c @@ -37,7 +37,7 @@ inline long get_reg(struct task_struct *task, unsigned int regno) if (regno == PT_USP) return task->thread.usp; else if (regno < PT_MAX) - return ((unsigned long *)user_regs(task->thread_info))[regno]; + return ((unsigned long *)task_pt_regs(task))[regno]; else return 0; } @@ -51,7 +51,7 @@ inline int put_reg(struct task_struct *task, unsigned int regno, if (regno == PT_USP) task->thread.usp = data; else if (regno < PT_MAX) - ((unsigned long *)user_regs(task->thread_info))[regno] = data; + ((unsigned long *)task_pt_regs(task))[regno] = data; else return -1; return 0; diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c index 882be42114f..843513102d3 100644 --- a/arch/cris/arch-v32/kernel/process.c +++ b/arch/cris/arch-v32/kernel/process.c @@ -96,7 +96,7 @@ hard_reset_now(void) */ unsigned long thread_saved_pc(struct task_struct *t) { - return (unsigned long)user_regs(t->thread_info)->erp; + return task_pt_regs(t)->erp; } static void @@ -148,7 +148,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, * fix it up. Note: the task_struct doubles as the kernel stack for the * task. */ - childregs = user_regs(p->thread_info); + childregs = task_pt_regs(p); *childregs = *regs; /* Struct copy of pt_regs. */ p->set_child_tid = p->clear_child_tid = NULL; childregs->r10 = 0; /* Child returns 0 after a fork/clone. */ @@ -157,7 +157,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, * The TLS is in $mof beacuse it is the 5th argument to sys_clone. */ if (p->mm && (clone_flags & CLONE_SETTLS)) { - p->thread_info->tls = regs->mof; + task_thread_info(p)->tls = regs->mof; } /* Put the switch stack right below the pt_regs. */ diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c index 5528b83a622..82cf2e3624a 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c @@ -46,7 +46,7 @@ long get_reg(struct task_struct *task, unsigned int regno) unsigned long ret; if (regno <= PT_EDA) - ret = ((unsigned long *)user_regs(task->thread_info))[regno]; + ret = ((unsigned long *)task_pt_regs(task))[regno]; else if (regno == PT_USP) ret = task->thread.usp; else if (regno == PT_PPC) @@ -65,13 +65,13 @@ long get_reg(struct task_struct *task, unsigned int regno) int put_reg(struct task_struct *task, unsigned int regno, unsigned long data) { if (regno <= PT_EDA) - ((unsigned long *)user_regs(task->thread_info))[regno] = data; + ((unsigned long *)task_pt_regs(task))[regno] = data; else if (regno == PT_USP) task->thread.usp = data; else if (regno == PT_PPC) { /* Write pseudo-PC to ERP only if changed. */ if (data != get_pseudo_pc(task)) - ((unsigned long *)user_regs(task->thread_info))[PT_ERP] = data; + task_pt_regs(task)->erp = data; } else if (regno <= PT_MAX) return put_debugreg(task->pid, regno, data); else diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 13867f4fad1..da40d19a151 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -113,10 +113,10 @@ smp_boot_one_cpu(int cpuid) if (IS_ERR(idle)) panic("SMP: fork failed for CPU:%d", cpuid); - idle->thread_info->cpu = cpuid; + task_thread_info(idle)->cpu = cpuid; /* Information to the CPU that is about to boot */ - smp_init_current_idle_thread = idle->thread_info; + smp_init_current_idle_thread = task_thread_info(idle); cpu_now_booting = cpuid; /* Wait for CPU to come online */ diff --git a/arch/cris/arch-v32/mm/tlb.c b/arch/cris/arch-v32/mm/tlb.c index b08a28bb58a..9d75d769230 100644 --- a/arch/cris/arch-v32/mm/tlb.c +++ b/arch/cris/arch-v32/mm/tlb.c @@ -198,9 +198,9 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, per_cpu(current_pgd, cpu) = next->pgd; /* Switch context in the MMU. */ - if (tsk && tsk->thread_info) + if (tsk && task_thread_info(tsk)) { - SPEC_REG_WR(SPEC_REG_PID, next->context.page_id | tsk->thread_info->tls); + SPEC_REG_WR(SPEC_REG_PID, next->context.page_id | task_thread_info(tsk)->tls); } else { diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index c4488379ac3..0fff8a61ef2 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -204,7 +204,7 @@ int copy_thread(int nr, unsigned long clone_flags, regs0 = __kernel_frame0_ptr; childregs0 = (struct pt_regs *) - ((unsigned long) p->thread_info + THREAD_SIZE - USER_CONTEXT_SIZE); + (task_stack_page(p) + THREAD_SIZE - USER_CONTEXT_SIZE); childregs = childregs0; /* set up the userspace frame (the only place that the USP is stored) */ @@ -220,7 +220,7 @@ int copy_thread(int nr, unsigned long clone_flags, *childregs = *regs; childregs->sp = (unsigned long) childregs0; childregs->next_frame = childregs0; - childregs->gr15 = (unsigned long) p->thread_info; + childregs->gr15 = (unsigned long) task_thread_info(p); childregs->gr29 = (unsigned long) p; } diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index 585ed5efd0f..ed79ae20e88 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -195,7 +195,7 @@ int copy_thread(int nr, unsigned long clone_flags, { struct pt_regs * childregs; - childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; + childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1; *childregs = *regs; childregs->retpc = (unsigned long) ret_from_fork; diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 035928f3f6c..2185377fdde 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -424,18 +424,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, struct task_struct *tsk; int err; - childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; - /* - * The below -8 is to reserve 8 bytes on top of the ring0 stack. - * This is necessary to guarantee that the entire "struct pt_regs" - * is accessable even if the CPU haven't stored the SS/ESP registers - * on the stack (interrupt gate does not save these registers - * when switching to the same priv ring). - * Therefore beware: accessing the xss/esp fields of the - * "struct pt_regs" is possible, but they may contain the - * completely wrong values. - */ - childregs = (struct pt_regs *) ((unsigned long) childregs - 8); + childregs = task_pt_regs(p); *childregs = *regs; childregs->eax = 0; childregs->esp = esp; @@ -540,12 +529,7 @@ EXPORT_SYMBOL(dump_thread); */ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) { - struct pt_regs ptregs; - - ptregs = *(struct pt_regs *) - ((unsigned long)tsk->thread_info + - /* see comments in copy_thread() about -8 */ - THREAD_SIZE - sizeof(ptregs) - 8); + struct pt_regs ptregs = *task_pt_regs(tsk); ptregs.xcs &= 0xffff; ptregs.xds &= 0xffff; ptregs.xes &= 0xffff; @@ -601,8 +585,8 @@ static inline void disable_tsc(struct task_struct *prev_p, * gcc should eliminate the ->thread_info dereference if * has_secure_computing returns 0 at compile time (SECCOMP=n). */ - prev = prev_p->thread_info; - next = next_p->thread_info; + prev = task_thread_info(prev_p); + next = task_thread_info(next_p); if (has_secure_computing(prev) || has_secure_computing(next)) { /* slow path here */ @@ -787,7 +771,7 @@ unsigned long get_wchan(struct task_struct *p) int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = (unsigned long)p->thread_info; + stack_page = (unsigned long)task_stack_page(p); esp = p->thread.esp; if (!stack_page || esp < stack_page || esp > top_esp+stack_page) return 0; diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index b3c2e2c2674..255adb49826 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -875,8 +875,7 @@ static inline struct task_struct * alloc_idle_task(int cpu) /* initialize thread_struct. we really want to avoid destroy * idle tread */ - idle->thread.esp = (unsigned long)(((struct pt_regs *) - (THREAD_SIZE + (unsigned long) idle->thread_info)) - 1); + idle->thread.esp = (unsigned long)task_pt_regs(idle); init_idle(idle, cpu); return idle; } @@ -1096,6 +1095,7 @@ static void smp_tune_scheduling (void) cachesize = 16; /* Pentiums, 2x8kB cache */ bandwidth = 100; } + max_cache_size = cachesize * 1024; } } diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c index cbdb0afed76..0c90ae54ddf 100644 --- a/arch/i386/kernel/vm86.c +++ b/arch/i386/kernel/vm86.c @@ -311,7 +311,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk "movl %1,%%ebp\n\t" "jmp resume_userspace" : /* no outputs */ - :"r" (&info->regs), "r" (tsk->thread_info) : "ax"); + :"r" (&info->regs), "r" (task_thread_info(tsk)) : "ax"); /* we never return here */ } diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h index b73b8b6b10c..a47f63b204f 100644 --- a/arch/ia64/ia32/elfcore32.h +++ b/arch/ia64/ia32/elfcore32.h @@ -95,8 +95,7 @@ static inline void elf_core_copy_regs(elf_gregset_t *elfregs, static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs) { - struct pt_regs *pp = ia64_task_regs(t); - ELF_CORE_COPY_REGS((*elfregs), pp); + ELF_CORE_COPY_REGS((*elfregs), task_pt_regs(t)); return 1; } diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c index aa891c9bc9b..5856510210f 100644 --- a/arch/ia64/ia32/ia32_signal.c +++ b/arch/ia64/ia32/ia32_signal.c @@ -255,7 +255,7 @@ save_ia32_fpstate_live (struct _fpstate_ia32 __user *save) */ fp_tos = (fsr>>11)&0x7; fr8_st_map = (8-fp_tos)&0x7; - ptp = ia64_task_regs(tsk); + ptp = task_pt_regs(tsk); fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15); ia64f2ia32f(fpregp, &ptp->f8); copy_to_user(&save->_st[(0+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); @@ -389,7 +389,7 @@ restore_ia32_fpstate_live (struct _fpstate_ia32 __user *save) fr8_st_map = (8-fp_tos)&0x7; fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15); - ptp = ia64_task_regs(tsk); + ptp = task_pt_regs(tsk); copy_from_user(fpregp, &save->_st[(0+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); ia32f2ia64f(&ptp->f8, fpregp); copy_from_user(fpregp, &save->_st[(1+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c index 4f630043b3a..c187743965a 100644 --- a/arch/ia64/ia32/ia32_support.c +++ b/arch/ia64/ia32/ia32_support.c @@ -58,7 +58,7 @@ load_desc (u16 selector) void ia32_load_segment_descriptors (struct task_struct *task) { - struct pt_regs *regs = ia64_task_regs(task); + struct pt_regs *regs = task_pt_regs(task); /* Setup the segment descriptors */ regs->r24 = load_desc(regs->r16 >> 16); /* ESD */ @@ -113,7 +113,7 @@ void ia32_load_state (struct task_struct *t) { unsigned long eflag, fsr, fcr, fir, fdr, tssd; - struct pt_regs *regs = ia64_task_regs(t); + struct pt_regs *regs = task_pt_regs(t); eflag = t->thread.eflag; fsr = t->thread.fsr; diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 0668b2b7714..3945d378bd7 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -1482,7 +1482,7 @@ getreg (struct task_struct *child, int regno) { struct pt_regs *child_regs; - child_regs = ia64_task_regs(child); + child_regs = task_pt_regs(child); switch (regno / sizeof(int)) { case PT_EBX: return child_regs->r11; case PT_ECX: return child_regs->r9; @@ -1510,7 +1510,7 @@ putreg (struct task_struct *child, int regno, unsigned int value) { struct pt_regs *child_regs; - child_regs = ia64_task_regs(child); + child_regs = task_pt_regs(child); switch (regno / sizeof(int)) { case PT_EBX: child_regs->r11 = value; break; case PT_ECX: child_regs->r9 = value; break; @@ -1626,7 +1626,7 @@ save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user * Stack frames start with 16-bytes of temp space */ swp = (struct switch_stack *)(tsk->thread.ksp + 16); - ptp = ia64_task_regs(tsk); + ptp = task_pt_regs(tsk); tos = (tsk->thread.fsr >> 11) & 7; for (i = 0; i < 8; i++) put_fpreg(i, &save->st_space[i], ptp, swp, tos); @@ -1659,7 +1659,7 @@ restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __us * Stack frames start with 16-bytes of temp space */ swp = (struct switch_stack *)(tsk->thread.ksp + 16); - ptp = ia64_task_regs(tsk); + ptp = task_pt_regs(tsk); tos = (tsk->thread.fsr >> 11) & 7; for (i = 0; i < 8; i++) get_fpreg(i, &save->st_space[i], ptp, swp, tos); @@ -1690,7 +1690,7 @@ save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user * Stack frames start with 16-bytes of temp space */ swp = (struct switch_stack *)(tsk->thread.ksp + 16); - ptp = ia64_task_regs(tsk); + ptp = task_pt_regs(tsk); tos = (tsk->thread.fsr >> 11) & 7; for (i = 0; i < 8; i++) put_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos); @@ -1734,7 +1734,7 @@ restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __u * Stack frames start with 16-bytes of temp space */ swp = (struct switch_stack *)(tsk->thread.ksp + 16); - ptp = ia64_task_regs(tsk); + ptp = task_pt_regs(tsk); tos = (tsk->thread.fsr >> 11) & 7; for (i = 0; i < 8; i++) get_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos); diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 355af15287c..ee7eec9ee57 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -766,7 +766,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs, l = strlen(previous_current->comm); snprintf(comm, sizeof(comm), "%s %*s %d", current->comm, l, previous_current->comm, - previous_current->thread_info->cpu); + task_thread_info(previous_current)->cpu); } memcpy(current->comm, comm, sizeof(current->comm)); @@ -1423,7 +1423,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset, struct task_struct *p = (struct task_struct *)((char *)mca_data + offset); struct thread_info *ti; memset(p, 0, KERNEL_STACK_SIZE); - ti = (struct thread_info *)((char *)p + IA64_TASK_SIZE); + ti = task_thread_info(p); ti->flags = _TIF_MCA_INIT; ti->preempt_count = 1; ti->task = p; diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index c026ac1142a..bd87cb6b7a8 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -1710,7 +1710,7 @@ static void pfm_syswide_force_stop(void *info) { pfm_context_t *ctx = (pfm_context_t *)info; - struct pt_regs *regs = ia64_task_regs(current); + struct pt_regs *regs = task_pt_regs(current); struct task_struct *owner; unsigned long flags; int ret; @@ -1815,7 +1815,7 @@ pfm_flush(struct file *filp) is_system = ctx->ctx_fl_system; task = PFM_CTX_TASK(ctx); - regs = ia64_task_regs(task); + regs = task_pt_regs(task); DPRINT(("ctx_state=%d is_current=%d\n", state, @@ -1945,7 +1945,7 @@ pfm_close(struct inode *inode, struct file *filp) is_system = ctx->ctx_fl_system; task = PFM_CTX_TASK(ctx); - regs = ia64_task_regs(task); + regs = task_pt_regs(task); DPRINT(("ctx_state=%d is_current=%d\n", state, @@ -4052,7 +4052,7 @@ pfm_stop(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) */ ia64_psr(regs)->up = 0; } else { - tregs = ia64_task_regs(task); + tregs = task_pt_regs(task); /* * stop monitoring at the user level @@ -4134,7 +4134,7 @@ pfm_start(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) ia64_psr(regs)->up = 1; } else { - tregs = ia64_task_regs(ctx->ctx_task); + tregs = task_pt_regs(ctx->ctx_task); /* * start monitoring at the kernel level the next @@ -4404,7 +4404,7 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) /* * when not current, task MUST be stopped, so this is safe */ - regs = ia64_task_regs(task); + regs = task_pt_regs(task); /* force a full reload */ ctx->ctx_last_activation = PFM_INVALID_ACTIVATION; @@ -4530,7 +4530,7 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg /* * per-task mode */ - tregs = task == current ? regs : ia64_task_regs(task); + tregs = task == current ? regs : task_pt_regs(task); if (task == current) { /* @@ -4593,7 +4593,7 @@ pfm_exit_thread(struct task_struct *task) { pfm_context_t *ctx; unsigned long flags; - struct pt_regs *regs = ia64_task_regs(task); + struct pt_regs *regs = task_pt_regs(task); int ret, state; int free_ok = 0; @@ -4926,7 +4926,7 @@ restart_args: if (unlikely(ret)) goto abort_locked; skip_fd: - ret = (*func)(ctx, args_k, count, ia64_task_regs(current)); + ret = (*func)(ctx, args_k, count, task_pt_regs(current)); call_made = 1; @@ -5050,7 +5050,7 @@ pfm_handle_work(void) pfm_clear_task_notify(); - regs = ia64_task_regs(current); + regs = task_pt_regs(current); /* * extract reason for being here and clear @@ -5794,7 +5794,7 @@ pfm_syst_wide_update_task(struct task_struct *task, unsigned long info, int is_c * on every CPU, so we can rely on the pid to identify the idle task. */ if ((info & PFM_CPUINFO_EXCL_IDLE) == 0 || task->pid) { - regs = ia64_task_regs(task); + regs = task_pt_regs(task); ia64_psr(regs)->pp = is_ctxswin ? dcr_pp : 0; return; } @@ -5877,7 +5877,7 @@ pfm_save_regs(struct task_struct *task) flags = pfm_protect_ctx_ctxsw(ctx); if (ctx->ctx_state == PFM_CTX_ZOMBIE) { - struct pt_regs *regs = ia64_task_regs(task); + struct pt_regs *regs = task_pt_regs(task); pfm_clear_psr_up(); @@ -6077,7 +6077,7 @@ pfm_load_regs (struct task_struct *task) BUG_ON(psr & IA64_PSR_I); if (unlikely(ctx->ctx_state == PFM_CTX_ZOMBIE)) { - struct pt_regs *regs = ia64_task_regs(task); + struct pt_regs *regs = task_pt_regs(task); BUG_ON(ctx->ctx_smpl_hdr); @@ -6446,7 +6446,7 @@ pfm_alt_save_pmu_state(void *data) { struct pt_regs *regs; - regs = ia64_task_regs(current); + regs = task_pt_regs(current); DPRINT(("called\n")); @@ -6472,7 +6472,7 @@ pfm_alt_restore_pmu_state(void *data) { struct pt_regs *regs; - regs = ia64_task_regs(current); + regs = task_pt_regs(current); DPRINT(("called\n")); @@ -6754,7 +6754,7 @@ dump_pmu_state(const char *from) local_irq_save(flags); this_cpu = smp_processor_id(); - regs = ia64_task_regs(current); + regs = task_pt_regs(current); info = PFM_CPUINFO_GET(); dcr = ia64_getreg(_IA64_REG_CR_DCR); diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index e9904c74d2b..309d59658e5 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -328,7 +328,7 @@ ia64_save_extra (struct task_struct *task) #endif #ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(ia64_task_regs(task))) + if (IS_IA32_PROCESS(task_pt_regs(task))) ia32_save_state(task); #endif } @@ -353,7 +353,7 @@ ia64_load_extra (struct task_struct *task) #endif #ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(ia64_task_regs(task))) + if (IS_IA32_PROCESS(task_pt_regs(task))) ia32_load_state(task); #endif } @@ -488,7 +488,7 @@ copy_thread (int nr, unsigned long clone_flags, * If we're cloning an IA32 task then save the IA32 extra * state from the current task to the new task */ - if (IS_IA32_PROCESS(ia64_task_regs(current))) { + if (IS_IA32_PROCESS(task_pt_regs(current))) { ia32_save_state(p); if (clone_flags & CLONE_SETTLS) retval = ia32_clone_tls(p, child_ptregs); @@ -701,7 +701,7 @@ int kernel_thread_helper (int (*fn)(void *), void *arg) { #ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(ia64_task_regs(current))) { + if (IS_IA32_PROCESS(task_pt_regs(current))) { /* A kernel thread is always a 64-bit process. */ current->thread.map_base = DEFAULT_MAP_BASE; current->thread.task_size = DEFAULT_TASK_SIZE; @@ -722,7 +722,7 @@ flush_thread (void) current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID); ia64_drop_fpu(current); #ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(ia64_task_regs(current))) { + if (IS_IA32_PROCESS(task_pt_regs(current))) { ia32_drop_partial_page_list(current); current->thread.task_size = IA32_PAGE_OFFSET; set_fs(USER_DS); @@ -755,7 +755,7 @@ exit_thread (void) if (current->thread.flags & IA64_THREAD_DBG_VALID) pfm_release_debug_registers(current); #endif - if (IS_IA32_PROCESS(ia64_task_regs(current))) + if (IS_IA32_PROCESS(task_pt_regs(current))) ia32_drop_partial_page_list(current); } diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 8d88eeea02d..eaed14aac6a 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -254,7 +254,7 @@ get_rnat (struct task_struct *task, struct switch_stack *sw, long num_regs, nbits; struct pt_regs *pt; - pt = ia64_task_regs(task); + pt = task_pt_regs(task); kbsp = (unsigned long *) sw->ar_bspstore; ubspstore = (unsigned long *) pt->ar_bspstore; @@ -314,7 +314,7 @@ put_rnat (struct task_struct *task, struct switch_stack *sw, struct pt_regs *pt; unsigned long cfm, *urbs_kargs; - pt = ia64_task_regs(task); + pt = task_pt_regs(task); kbsp = (unsigned long *) sw->ar_bspstore; ubspstore = (unsigned long *) pt->ar_bspstore; @@ -407,7 +407,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack, urbs_end = (long *) user_rbs_end; laddr = (unsigned long *) addr; - child_regs = ia64_task_regs(child); + child_regs = task_pt_regs(child); bspstore = (unsigned long *) child_regs->ar_bspstore; krbs = (unsigned long *) child + IA64_RBS_OFFSET/8; if (on_kernel_rbs(addr, (unsigned long) bspstore, @@ -467,7 +467,7 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack, struct pt_regs *child_regs; laddr = (unsigned long *) addr; - child_regs = ia64_task_regs(child); + child_regs = task_pt_regs(child); bspstore = (unsigned long *) child_regs->ar_bspstore; krbs = (unsigned long *) child + IA64_RBS_OFFSET/8; if (on_kernel_rbs(addr, (unsigned long) bspstore, @@ -567,7 +567,7 @@ thread_matches (struct task_struct *thread, unsigned long addr) */ return 0; - thread_regs = ia64_task_regs(thread); + thread_regs = task_pt_regs(thread); thread_rbs_end = ia64_get_user_rbs_end(thread, thread_regs, NULL); if (!on_kernel_rbs(addr, thread_regs->ar_bspstore, thread_rbs_end)) return 0; @@ -627,7 +627,7 @@ find_thread_for_addr (struct task_struct *child, unsigned long addr) inline void ia64_flush_fph (struct task_struct *task) { - struct ia64_psr *psr = ia64_psr(ia64_task_regs(task)); + struct ia64_psr *psr = ia64_psr(task_pt_regs(task)); /* * Prevent migrating this task while @@ -653,7 +653,7 @@ ia64_flush_fph (struct task_struct *task) void ia64_sync_fph (struct task_struct *task) { - struct ia64_psr *psr = ia64_psr(ia64_task_regs(task)); + struct ia64_psr *psr = ia64_psr(task_pt_regs(task)); ia64_flush_fph(task); if (!(task->thread.flags & IA64_THREAD_FPH_VALID)) { @@ -794,7 +794,7 @@ access_uarea (struct task_struct *child, unsigned long addr, + offsetof(struct pt_regs, reg))) - pt = ia64_task_regs(child); + pt = task_pt_regs(child); sw = (struct switch_stack *) (child->thread.ksp + 16); if ((addr & 0x7) != 0) { @@ -1120,7 +1120,7 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) if (!access_ok(VERIFY_WRITE, ppr, sizeof(struct pt_all_user_regs))) return -EIO; - pt = ia64_task_regs(child); + pt = task_pt_regs(child); sw = (struct switch_stack *) (child->thread.ksp + 16); unw_init_from_blocked_task(&info, child); if (unw_unwind_to_user(&info) < 0) { @@ -1265,7 +1265,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) if (!access_ok(VERIFY_READ, ppr, sizeof(struct pt_all_user_regs))) return -EIO; - pt = ia64_task_regs(child); + pt = task_pt_regs(child); sw = (struct switch_stack *) (child->thread.ksp + 16); unw_init_from_blocked_task(&info, child); if (unw_unwind_to_user(&info) < 0) { @@ -1403,7 +1403,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) void ptrace_disable (struct task_struct *child) { - struct ia64_psr *child_psr = ia64_psr(ia64_task_regs(child)); + struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child)); /* make sure the single step/taken-branch trap bits are not set: */ child_psr->ss = 0; @@ -1456,7 +1456,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) if (ret < 0) goto out_tsk; - pt = ia64_task_regs(child); + pt = task_pt_regs(child); sw = (struct switch_stack *) (child->thread.ksp + 16); switch (request) { diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index c33305d8e5e..c0766575a3a 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -60,6 +60,7 @@ #include <asm/smp.h> #include <asm/system.h> #include <asm/unistd.h> +#include <asm/system.h> #if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE) # error "struct cpuinfo_ia64 too big!" @@ -695,6 +696,7 @@ static void get_max_cacheline_size (void) { unsigned long line_size, max = 1; + unsigned int cache_size = 0; u64 l, levels, unique_caches; pal_cache_config_info_t cci; s64 status; @@ -724,6 +726,8 @@ get_max_cacheline_size (void) line_size = 1 << cci.pcci_line_size; if (line_size > max) max = line_size; + if (cache_size < cci.pcci_cache_size) + cache_size = cci.pcci_cache_size; if (!cci.pcci_unified) { status = ia64_pal_cache_config_info(l, /* cache_type (instruction)= */ 1, @@ -740,6 +744,9 @@ get_max_cacheline_size (void) ia64_i_cache_stride_shift = cci.pcci_stride; } out: +#ifdef CONFIG_SMP + max_cache_size = max(max_cache_size, cache_size); +#endif if (max > ia64_max_cacheline_size) ia64_max_cacheline_size = max; } @@ -794,7 +801,7 @@ cpu_init (void) #endif /* Clear the stack memory reserved for pt_regs: */ - memset(ia64_task_regs(current), 0, sizeof(struct pt_regs)); + memset(task_pt_regs(current), 0, sizeof(struct pt_regs)); ia64_set_kr(IA64_KR_FPU_OWNER, 0); @@ -870,6 +877,15 @@ cpu_init (void) pm_idle = default_idle; } +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + */ +void sched_cacheflush(void) +{ + ia64_sal_cache_flush(3); +} + void check_bugs (void) { diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 58ce07efc56..463f6bb44d0 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -655,11 +655,11 @@ set_sigdelayed(pid_t pid, int signo, int code, void __user *addr) if (!t) return; - t->thread_info->sigdelayed.signo = signo; - t->thread_info->sigdelayed.code = code; - t->thread_info->sigdelayed.addr = addr; - t->thread_info->sigdelayed.start_time = start_time; - t->thread_info->sigdelayed.pid = pid; + task_thread_info(t)->sigdelayed.signo = signo; + task_thread_info(t)->sigdelayed.code = code; + task_thread_info(t)->sigdelayed.addr = addr; + task_thread_info(t)->sigdelayed.start_time = start_time; + task_thread_info(t)->sigdelayed.pid = pid; wmb(); set_tsk_thread_flag(t, TIF_SIGDELAYED); } diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index f2dbcd1db0d..c7b943f1019 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c @@ -151,7 +151,7 @@ out: asmlinkage long sys_pipe (void) { - struct pt_regs *regs = ia64_task_regs(current); + struct pt_regs *regs = task_pt_regs(current); int fd[2]; int retval; diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index 2a1f250349b..5dfc7ea45cf 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -242,13 +242,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) int copy_thread(int nr, unsigned long clone_flags, unsigned long spu, unsigned long unused, struct task_struct *tsk, struct pt_regs *regs) { - struct pt_regs *childregs; - unsigned long sp = (unsigned long)tsk->thread_info + THREAD_SIZE; + struct pt_regs *childregs = task_pt_regs(tsk); extern void ret_from_fork(void); /* Copy registers */ - sp -= sizeof (struct pt_regs); - childregs = (struct pt_regs *)sp; *childregs = *regs; childregs->spu = spu; diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index 9b75caaf5ce..340a3bf59b8 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -35,23 +35,6 @@ #include <asm/mmu_context.h> /* - * Get the address of the live pt_regs for the specified task. - * These are saved onto the top kernel stack when the process - * is not running. - * - * Note: if a user thread is execve'd from kernel space, the - * kernel stack will not be empty on entry to the kernel, so - * ptracing these tasks will fail. - */ -static inline struct pt_regs * -get_user_regs(struct task_struct *task) -{ - return (struct pt_regs *) - ((unsigned long)task->thread_info + THREAD_SIZE - - sizeof(struct pt_regs)); -} - -/* * This routine will get a word off of the process kernel stack. */ static inline unsigned long int @@ -59,7 +42,7 @@ get_stack_long(struct task_struct *task, int offset) { unsigned long *stack; - stack = (unsigned long *)get_user_regs(task); + stack = (unsigned long *)task_pt_regs(task); return stack[offset]; } @@ -72,7 +55,7 @@ put_stack_long(struct task_struct *task, int offset, unsigned long data) { unsigned long *stack; - stack = (unsigned long *)get_user_regs(task); + stack = (unsigned long *)task_pt_regs(task); stack[offset] = data; return 0; @@ -208,7 +191,7 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off, */ static int ptrace_getregs(struct task_struct *tsk, void __user *uregs) { - struct pt_regs *regs = get_user_regs(tsk); + struct pt_regs *regs = task_pt_regs(tsk); return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0; } @@ -223,7 +206,7 @@ static int ptrace_setregs(struct task_struct *tsk, void __user *uregs) ret = -EFAULT; if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) { - struct pt_regs *regs = get_user_regs(tsk); + struct pt_regs *regs = task_pt_regs(tsk); *regs = newregs; ret = 0; } diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c index b90c54169fa..d7ec16e7fb2 100644 --- a/arch/m32r/kernel/smpboot.c +++ b/arch/m32r/kernel/smpboot.c @@ -286,7 +286,7 @@ static void __init do_boot_cpu(int phys_id) /* So we see what's up */ printk("Booting processor %d/%d\n", phys_id, cpu_id); stack_start.spi = (void *)idle->thread.sp; - idle->thread_info->cpu = cpu_id; + task_thread_info(idle)->cpu = cpu_id; /* * Send Startup IPI diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index d9edf2d1a49..b0aa61bf870 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -126,9 +126,9 @@ void __init amiga_init_IRQ(void) gayle.inten = GAYLE_IRQ_IDE; /* turn off all interrupts and enable the master interrupt bit */ - custom.intena = 0x7fff; - custom.intreq = 0x7fff; - custom.intena = IF_SETCLR | IF_INTEN; + amiga_custom.intena = 0x7fff; + amiga_custom.intreq = 0x7fff; + amiga_custom.intena = IF_SETCLR | IF_INTEN; cia_init_IRQ(&ciaa_base); cia_init_IRQ(&ciab_base); @@ -245,7 +245,7 @@ int amiga_request_irq(unsigned int irq, /* enable the interrupt */ if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq]) - custom.intena = IF_SETCLR | amiga_intena_vals[irq]; + amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq]; return error; } @@ -274,7 +274,7 @@ void amiga_free_irq(unsigned int irq, void *dev_id) amiga_delete_irq(&ami_irq_list[irq], dev_id); /* if server list empty, disable the interrupt */ if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS) - custom.intena = amiga_intena_vals[irq]; + amiga_custom.intena = amiga_intena_vals[irq]; } else { if (ami_irq_list[irq]->dev_id != dev_id) printk("%s: removing probably wrong IRQ %d from %s\n", @@ -283,7 +283,7 @@ void amiga_free_irq(unsigned int irq, void *dev_id) ami_irq_list[irq]->flags = 0; ami_irq_list[irq]->dev_id = NULL; ami_irq_list[irq]->devname = NULL; - custom.intena = amiga_intena_vals[irq]; + amiga_custom.intena = amiga_intena_vals[irq]; } } @@ -327,7 +327,7 @@ void amiga_enable_irq(unsigned int irq) } /* enable the interrupt */ - custom.intena = IF_SETCLR | amiga_intena_vals[irq]; + amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq]; } void amiga_disable_irq(unsigned int irq) @@ -358,7 +358,7 @@ void amiga_disable_irq(unsigned int irq) } /* disable the interrupt */ - custom.intena = amiga_intena_vals[irq]; + amiga_custom.intena = amiga_intena_vals[irq]; } inline void amiga_do_irq(int irq, struct pt_regs *fp) @@ -373,7 +373,7 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp) kstat_cpu(0).irqs[SYS_IRQS + irq]++; - custom.intreq = amiga_intena_vals[irq]; + amiga_custom.intreq = amiga_intena_vals[irq]; for (node = ami_irq_list[irq]; node; node = node->next) node->handler(irq, node->dev_id, fp); @@ -385,23 +385,23 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp) static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if serial transmit buffer empty, interrupt */ if (ints & IF_TBE) { - custom.intreq = IF_TBE; + amiga_custom.intreq = IF_TBE; amiga_do_irq(IRQ_AMIGA_TBE, fp); } /* if floppy disk transfer complete, interrupt */ if (ints & IF_DSKBLK) { - custom.intreq = IF_DSKBLK; + amiga_custom.intreq = IF_DSKBLK; amiga_do_irq(IRQ_AMIGA_DSKBLK, fp); } /* if software interrupt set, interrupt */ if (ints & IF_SOFT) { - custom.intreq = IF_SOFT; + amiga_custom.intreq = IF_SOFT; amiga_do_irq(IRQ_AMIGA_SOFT, fp); } return IRQ_HANDLED; @@ -409,17 +409,17 @@ static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp) static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if a blitter interrupt */ if (ints & IF_BLIT) { - custom.intreq = IF_BLIT; + amiga_custom.intreq = IF_BLIT; amiga_do_irq(IRQ_AMIGA_BLIT, fp); } /* if a copper interrupt */ if (ints & IF_COPER) { - custom.intreq = IF_COPER; + amiga_custom.intreq = IF_COPER; amiga_do_irq(IRQ_AMIGA_COPPER, fp); } @@ -431,29 +431,29 @@ static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp) static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if audio 0 interrupt */ if (ints & IF_AUD0) { - custom.intreq = IF_AUD0; + amiga_custom.intreq = IF_AUD0; amiga_do_irq(IRQ_AMIGA_AUD0, fp); } /* if audio 1 interrupt */ if (ints & IF_AUD1) { - custom.intreq = IF_AUD1; + amiga_custom.intreq = IF_AUD1; amiga_do_irq(IRQ_AMIGA_AUD1, fp); } /* if audio 2 interrupt */ if (ints & IF_AUD2) { - custom.intreq = IF_AUD2; + amiga_custom.intreq = IF_AUD2; amiga_do_irq(IRQ_AMIGA_AUD2, fp); } /* if audio 3 interrupt */ if (ints & IF_AUD3) { - custom.intreq = IF_AUD3; + amiga_custom.intreq = IF_AUD3; amiga_do_irq(IRQ_AMIGA_AUD3, fp); } return IRQ_HANDLED; @@ -461,7 +461,7 @@ static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp) static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if serial receive buffer full interrupt */ if (ints & IF_RBF) { @@ -471,7 +471,7 @@ static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp) /* if a disk sync interrupt */ if (ints & IF_DSKSYN) { - custom.intreq = IF_DSKSYN; + amiga_custom.intreq = IF_DSKSYN; amiga_do_irq(IRQ_AMIGA_DSKSYN, fp); } return IRQ_HANDLED; diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c index bd5d134e9f1..ae94db5d93b 100644 --- a/arch/m68k/amiga/amisound.c +++ b/arch/m68k/amiga/amisound.c @@ -24,6 +24,8 @@ static const signed char sine_data[] = { }; #define DATA_SIZE (sizeof(sine_data)/sizeof(sine_data[0])) +#define custom amiga_custom + /* * The minimum period for audio may be modified by the frame buffer * device since it depends on htotal (for OCS/ECS/AGA) diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c index 7d55682615e..9476eb9440f 100644 --- a/arch/m68k/amiga/cia.c +++ b/arch/m68k/amiga/cia.c @@ -60,7 +60,7 @@ unsigned char cia_set_irq(struct ciabase *base, unsigned char mask) else base->icr_data &= ~mask; if (base->icr_data & base->icr_mask) - custom.intreq = IF_SETCLR | base->int_mask; + amiga_custom.intreq = IF_SETCLR | base->int_mask; return old & base->icr_mask; } @@ -89,7 +89,7 @@ unsigned char cia_able_irq(struct ciabase *base, unsigned char mask) } } if (base->icr_data & base->icr_mask) - custom.intreq = IF_SETCLR | base->int_mask; + amiga_custom.intreq = IF_SETCLR | base->int_mask; return old; } @@ -133,7 +133,7 @@ static irqreturn_t cia_handler(int irq, void *dev_id, struct pt_regs *fp) mach_irq = base->cia_irq; irq = SYS_IRQS + mach_irq; ints = cia_set_irq(base, CIA_ICR_ALL); - custom.intreq = base->int_mask; + amiga_custom.intreq = base->int_mask; for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) { if (ints & 1) { kstat_cpu(0).irqs[irq]++; @@ -162,7 +162,7 @@ void __init cia_init_IRQ(struct ciabase *base) /* install CIA handler */ request_irq(base->handler_irq, cia_handler, 0, base->name, base); - custom.intena = IF_SETCLR | base->int_mask; + amiga_custom.intena = IF_SETCLR | base->int_mask; } int cia_get_irq_list(struct ciabase *base, struct seq_file *p) diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index 4775e18a78f..12e3706fe02 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c @@ -105,9 +105,6 @@ static int a2000_hwclk (int, struct rtc_time *); static int amiga_set_clock_mmss (unsigned long); static unsigned int amiga_get_ss (void); extern void amiga_mksound( unsigned int count, unsigned int ticks ); -#ifdef CONFIG_AMIGA_FLOPPY -extern void amiga_floppy_setup(char *, int *); -#endif static void amiga_reset (void); extern void amiga_init_sound(void); static void amiga_savekmsg_init(void); @@ -290,7 +287,7 @@ static void __init amiga_identify(void) case CS_OCS: case CS_ECS: case CS_AGA: - switch (custom.deniseid & 0xf) { + switch (amiga_custom.deniseid & 0xf) { case 0x0c: AMIGAHW_SET(DENISE_HR); break; @@ -303,7 +300,7 @@ static void __init amiga_identify(void) AMIGAHW_SET(DENISE); break; } - switch ((custom.vposr>>8) & 0x7f) { + switch ((amiga_custom.vposr>>8) & 0x7f) { case 0x00: AMIGAHW_SET(AGNUS_PAL); break; @@ -427,13 +424,7 @@ void __init config_amiga(void) mach_set_clock_mmss = amiga_set_clock_mmss; mach_get_ss = amiga_get_ss; -#ifdef CONFIG_AMIGA_FLOPPY - mach_floppy_setup = amiga_floppy_setup; -#endif mach_reset = amiga_reset; -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) mach_beep = amiga_mksound; #endif @@ -447,9 +438,9 @@ void __init config_amiga(void) amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */ /* clear all DMA bits */ - custom.dmacon = DMAF_ALL; + amiga_custom.dmacon = DMAF_ALL; /* ensure that the DMA master bit is set */ - custom.dmacon = DMAF_SETCLR | DMAF_MASTER; + amiga_custom.dmacon = DMAF_SETCLR | DMAF_MASTER; /* don't use Z2 RAM as system memory on Z3 capable machines */ if (AMIGAHW_PRESENT(ZORRO3)) { @@ -830,8 +821,8 @@ static void amiga_savekmsg_init(void) static void amiga_serial_putc(char c) { - custom.serdat = (unsigned char)c | 0x100; - while (!(custom.serdatr & 0x2000)) + amiga_custom.serdat = (unsigned char)c | 0x100; + while (!(amiga_custom.serdatr & 0x2000)) ; } @@ -855,11 +846,11 @@ int amiga_serial_console_wait_key(struct console *co) { int ch; - while (!(custom.intreqr & IF_RBF)) + while (!(amiga_custom.intreqr & IF_RBF)) barrier(); - ch = custom.serdatr & 0xff; + ch = amiga_custom.serdatr & 0xff; /* clear the interrupt, so that another character can be read */ - custom.intreq = IF_RBF; + amiga_custom.intreq = IF_RBF; return ch; } diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c index 26492947125..d401962d9b2 100644 --- a/arch/m68k/apollo/config.c +++ b/arch/m68k/apollo/config.c @@ -176,9 +176,6 @@ void config_apollo(void) { mach_set_clock_mmss = dn_dummy_set_clock_mmss; /* */ mach_process_int = dn_process_int; mach_reset = dn_dummy_reset; /* */ -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif #ifdef CONFIG_HEARTBEAT mach_heartbeat = dn_heartbeat; #endif diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c index 9261d2deeaf..1012b08e552 100644 --- a/arch/m68k/atari/config.c +++ b/arch/m68k/atari/config.c @@ -52,9 +52,6 @@ int atari_rtc_year_offset; /* local function prototypes */ static void atari_reset( void ); -#ifdef CONFIG_ATARI_FLOPPY -extern void atari_floppy_setup(char *, int *); -#endif static void atari_get_model(char *model); static int atari_get_hardware_list(char *buffer); @@ -244,12 +241,6 @@ void __init config_atari(void) mach_get_irq_list = show_atari_interrupts; mach_gettimeoffset = atari_gettimeoffset; mach_reset = atari_reset; -#ifdef CONFIG_ATARI_FLOPPY - mach_floppy_setup = atari_floppy_setup; -#endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif mach_max_dma_address = 0xffffff; #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) mach_beep = atari_mksound; diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c index f7573f2bcb9..703cbc6dc9c 100644 --- a/arch/m68k/bvme6000/rtc.c +++ b/arch/m68k/bvme6000/rtc.c @@ -47,6 +47,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned char msr; unsigned long flags; struct rtc_time wtime; + void __user *argp = (void __user *)arg; switch (cmd) { case RTC_RD_TIME: /* Read the time/date from RTC */ @@ -69,7 +70,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } while (wtime.tm_sec != BCD2BIN(rtc->bcd_sec)); rtc->msr = msr; local_irq_restore(flags); - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? + return copy_to_user(argp, &wtime, sizeof wtime) ? -EFAULT : 0; } case RTC_SET_TIME: /* Set the RTC */ @@ -81,8 +82,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, - sizeof(struct rtc_time))) + if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time))) return -EFAULT; yrs = rtc_tm.tm_year; diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c index a0b854f3f94..6d129eef370 100644 --- a/arch/m68k/hp300/config.c +++ b/arch/m68k/hp300/config.c @@ -261,9 +261,6 @@ void __init config_hp300(void) #ifdef CONFIG_HEARTBEAT mach_heartbeat = hp300_pulse; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif mach_max_dma_address = 0xffffffff; if (hp300_model >= HP_330 && hp300_model <= HP_433S && hp300_model != HP_350) { diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c index c787c5ba951..246a8820c22 100644 --- a/arch/m68k/kernel/asm-offsets.c +++ b/arch/m68k/kernel/asm-offsets.c @@ -92,7 +92,7 @@ int main(void) DEFINE(TRAP_TRACE, TRAP_TRACE); /* offsets into the custom struct */ - DEFINE(CUSTOMBASE, &custom); + DEFINE(CUSTOMBASE, &amiga_custom); DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar)); DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr)); DEFINE(C_INTENA, offsetof(struct CUSTOM, intena)); diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S index d4336d846df..70002c146ee 100644 --- a/arch/m68k/kernel/head.S +++ b/arch/m68k/kernel/head.S @@ -273,8 +273,10 @@ * Macintosh console support */ +#ifdef CONFIG_FRAMEBUFFER_CONSOLE #define CONSOLE #define CONSOLE_PENGUIN +#endif /* * Macintosh serial debug support; outputs boot info to the printer diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 13d109328a4..3f9cb55d035 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -238,10 +238,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, { struct pt_regs * childregs; struct switch_stack * childstack, *stack; - unsigned long stack_offset, *retp; + unsigned long *retp; - stack_offset = THREAD_SIZE - sizeof(struct pt_regs); - childregs = (struct pt_regs *) ((unsigned long) (p->thread_info) + stack_offset); + childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; *childregs = *regs; childregs->d0 = 0; @@ -386,7 +385,7 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = (unsigned long)(p->thread_info); + stack_page = (unsigned long)task_stack_page(p); fp = ((struct switch_stack *)p->thread.ksp)->a6; do { if (fp < stack_page+sizeof(struct thread_info) || diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c index d6ca99242e5..750d5b3c971 100644 --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -84,9 +84,6 @@ void (*mach_reset)( void ); void (*mach_halt)( void ); void (*mach_power_off)( void ); long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ -#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) -void (*mach_floppy_setup) (char *, int *) __initdata = NULL; -#endif #ifdef CONFIG_HEARTBEAT void (*mach_heartbeat) (int); EXPORT_SYMBOL(mach_heartbeat); @@ -100,6 +97,8 @@ void (*mach_beep)(unsigned int, unsigned int); #if defined(CONFIG_ISA) && defined(MULTI_ISA) int isa_type; int isa_sex; +EXPORT_SYMBOL(isa_type); +EXPORT_SYMBOL(isa_sex); #endif extern int amiga_parse_bootinfo(const struct bi_record *); @@ -280,6 +279,10 @@ void __init setup_arch(char **cmdline_p) } } +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + switch (m68k_machtype) { #ifdef CONFIG_AMIGA case MACH_AMIGA: @@ -521,16 +524,6 @@ int get_hardware_list(char *buffer) return(len); } - -#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) -void __init floppy_setup(char *str, int *ints) -{ - if (mach_floppy_setup) - mach_floppy_setup (str, ints); -} - -#endif - void check_bugs(void) { #ifndef CONFIG_M68KFPU_EMU diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 9c636a4c238..866917bfa02 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -96,7 +96,7 @@ asmlinkage int do_sigsuspend(struct pt_regs *regs) asmlinkage int do_rt_sigsuspend(struct pt_regs *regs) { - sigset_t *unewset = (sigset_t *)regs->d1; + sigset_t __user *unewset = (sigset_t __user *)regs->d1; size_t sigsetsize = (size_t)regs->d2; sigset_t saveset, newset; @@ -122,8 +122,8 @@ do_rt_sigsuspend(struct pt_regs *regs) } asmlinkage int -sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact) +sys_sigaction(int sig, const struct old_sigaction __user *act, + struct old_sigaction __user *oact) { struct k_sigaction new_ka, old_ka; int ret; @@ -154,7 +154,7 @@ sys_sigaction(int sig, const struct old_sigaction *act, } asmlinkage int -sys_sigaltstack(const stack_t *uss, stack_t *uoss) +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) { return do_sigaltstack(uss, uoss, rdusp()); } @@ -169,10 +169,10 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss) struct sigframe { - char *pretcode; + char __user *pretcode; int sig; int code; - struct sigcontext *psc; + struct sigcontext __user *psc; char retcode[8]; unsigned long extramask[_NSIG_WORDS-1]; struct sigcontext sc; @@ -180,10 +180,10 @@ struct sigframe struct rt_sigframe { - char *pretcode; + char __user *pretcode; int sig; - struct siginfo *pinfo; - void *puc; + struct siginfo __user *pinfo; + void __user *puc; char retcode[8]; struct siginfo info; struct ucontext uc; @@ -248,7 +248,7 @@ out: #define uc_formatvec uc_filler[FPCONTEXT_SIZE/4] #define uc_extra uc_filler[FPCONTEXT_SIZE/4+1] -static inline int rt_restore_fpu_state(struct ucontext *uc) +static inline int rt_restore_fpu_state(struct ucontext __user *uc) { unsigned char fpstate[FPCONTEXT_SIZE]; int context_size = CPU_IS_060 ? 8 : 0; @@ -267,7 +267,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) return 0; } - if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate)) + if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate)) goto out; if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { if (!CPU_IS_060) @@ -306,7 +306,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) "m" (*fpregs.f_fpcntl)); } if (context_size && - __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1, + __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1, context_size)) goto out; __asm__ volatile (".chip 68k/68881\n\t" @@ -319,7 +319,7 @@ out: } static inline int -restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp, +restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp, int *pd0) { int fsize, formatvec; @@ -404,10 +404,10 @@ badframe: static inline int rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, - struct ucontext *uc, int *pd0) + struct ucontext __user *uc, int *pd0) { int fsize, temp; - greg_t *gregs = uc->uc_mcontext.gregs; + greg_t __user *gregs = uc->uc_mcontext.gregs; unsigned long usp; int err; @@ -506,7 +506,7 @@ asmlinkage int do_sigreturn(unsigned long __unused) struct switch_stack *sw = (struct switch_stack *) &__unused; struct pt_regs *regs = (struct pt_regs *) (sw + 1); unsigned long usp = rdusp(); - struct sigframe *frame = (struct sigframe *)(usp - 4); + struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); sigset_t set; int d0; @@ -536,7 +536,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) struct switch_stack *sw = (struct switch_stack *) &__unused; struct pt_regs *regs = (struct pt_regs *) (sw + 1); unsigned long usp = rdusp(); - struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4); + struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); sigset_t set; int d0; @@ -596,7 +596,7 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) } } -static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) +static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs) { unsigned char fpstate[FPCONTEXT_SIZE]; int context_size = CPU_IS_060 ? 8 : 0; @@ -617,7 +617,7 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) ".chip 68k" : : "m" (*fpstate) : "memory"); - err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate); + err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate); if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { fpregset_t fpregs; if (!CPU_IS_060) @@ -642,7 +642,7 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) sizeof(fpregs)); } if (context_size) - err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4, + err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4, context_size); return err; } @@ -662,10 +662,10 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, save_fpu_state(sc, regs); } -static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs) +static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs) { struct switch_stack *sw = (struct switch_stack *)regs - 1; - greg_t *gregs = uc->uc_mcontext.gregs; + greg_t __user *gregs = uc->uc_mcontext.gregs; int err = 0; err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); @@ -753,7 +753,7 @@ static inline void push_cache (unsigned long vaddr) } } -static inline void * +static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { unsigned long usp; @@ -766,13 +766,13 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) if (!on_sig_stack(usp)) usp = current->sas_ss_sp + current->sas_ss_size; } - return (void *)((usp - frame_size) & -8UL); + return (void __user *)((usp - frame_size) & -8UL); } static void setup_frame (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) { - struct sigframe *frame; + struct sigframe __user *frame; int fsize = frame_extra_sizes[regs->format]; struct sigcontext context; int err = 0; @@ -813,7 +813,7 @@ static void setup_frame (int sig, struct k_sigaction *ka, err |= __put_user(frame->retcode, &frame->pretcode); /* moveq #,d0; trap #0 */ err |= __put_user(0x70004e40 + (__NR_sigreturn << 16), - (long *)(frame->retcode)); + (long __user *)(frame->retcode)); if (err) goto give_sigsegv; @@ -849,7 +849,7 @@ give_sigsegv: static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { - struct rt_sigframe *frame; + struct rt_sigframe __user *frame; int fsize = frame_extra_sizes[regs->format]; int err = 0; @@ -880,8 +880,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user((void *)current->sas_ss_sp, + err |= __put_user(NULL, &frame->uc.uc_link); + err |= __put_user((void __user *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(rdusp()), &frame->uc.uc_stack.ss_flags); @@ -893,8 +893,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(frame->retcode, &frame->pretcode); /* moveq #,d0; notb d0; trap #0 */ err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16), - (long *)(frame->retcode + 0)); - err |= __put_user(0x4e40, (short *)(frame->retcode + 4)); + (long __user *)(frame->retcode + 0)); + err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4)); if (err) goto give_sigsegv; diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 640895b2c51..143c552d38f 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -32,7 +32,7 @@ * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. */ -asmlinkage int sys_pipe(unsigned long * fildes) +asmlinkage int sys_pipe(unsigned long __user * fildes) { int fd[2]; int error; @@ -94,7 +94,7 @@ struct mmap_arg_struct { unsigned long offset; }; -asmlinkage int old_mmap(struct mmap_arg_struct *arg) +asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) { struct mmap_arg_struct a; int error = -EFAULT; @@ -160,11 +160,11 @@ out: struct sel_arg_struct { unsigned long n; - fd_set *inp, *outp, *exp; - struct timeval *tvp; + fd_set __user *inp, *outp, *exp; + struct timeval __user *tvp; }; -asmlinkage int old_select(struct sel_arg_struct *arg) +asmlinkage int old_select(struct sel_arg_struct __user *arg) { struct sel_arg_struct a; @@ -180,7 +180,7 @@ asmlinkage int old_select(struct sel_arg_struct *arg) * This is really horribly ugly. */ asmlinkage int sys_ipc (uint call, int first, int second, - int third, void *ptr, long fifth) + int third, void __user *ptr, long fifth) { int version, ret; @@ -190,14 +190,14 @@ asmlinkage int sys_ipc (uint call, int first, int second, if (call <= SEMCTL) switch (call) { case SEMOP: - return sys_semop (first, (struct sembuf *)ptr, second); + return sys_semop (first, ptr, second); case SEMGET: return sys_semget (first, second, third); case SEMCTL: { union semun fourth; if (!ptr) return -EINVAL; - if (get_user(fourth.__pad, (void **) ptr)) + if (get_user(fourth.__pad, (void __user *__user *) ptr)) return -EFAULT; return sys_semctl (first, second, third, fourth); } @@ -207,31 +207,26 @@ asmlinkage int sys_ipc (uint call, int first, int second, if (call <= MSGCTL) switch (call) { case MSGSND: - return sys_msgsnd (first, (struct msgbuf *) ptr, - second, third); + return sys_msgsnd (first, ptr, second, third); case MSGRCV: switch (version) { case 0: { struct ipc_kludge tmp; if (!ptr) return -EINVAL; - if (copy_from_user (&tmp, - (struct ipc_kludge *)ptr, - sizeof (tmp))) + if (copy_from_user (&tmp, ptr, sizeof (tmp))) return -EFAULT; return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); } default: - return sys_msgrcv (first, - (struct msgbuf *) ptr, + return sys_msgrcv (first, ptr, second, fifth, third); } case MSGGET: return sys_msgget ((key_t) first, second); case MSGCTL: - return sys_msgctl (first, second, - (struct msqid_ds *) ptr); + return sys_msgctl (first, second, ptr); default: return -ENOSYS; } @@ -241,20 +236,18 @@ asmlinkage int sys_ipc (uint call, int first, int second, switch (version) { default: { ulong raddr; - ret = do_shmat (first, (char *) ptr, - second, &raddr); + ret = do_shmat (first, ptr, second, &raddr); if (ret) return ret; - return put_user (raddr, (ulong *) third); + return put_user (raddr, (ulong __user *) third); } } case SHMDT: - return sys_shmdt ((char *)ptr); + return sys_shmdt (ptr); case SHMGET: return sys_shmget (first, second, third); case SHMCTL: - return sys_shmctl (first, second, - (struct shmid_ds *) ptr); + return sys_shmctl (first, second, ptr); default: return -ENOSYS; } diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index deb36e8b04a..cdf58fbb3e7 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -169,25 +169,25 @@ void __init trap_init (void) if (CPU_IS_060 && !FPU_IS_EMU) { /* set up IFPSP entry points */ - asmlinkage void snan_vec(void) asm ("_060_fpsp_snan"); - asmlinkage void operr_vec(void) asm ("_060_fpsp_operr"); - asmlinkage void ovfl_vec(void) asm ("_060_fpsp_ovfl"); - asmlinkage void unfl_vec(void) asm ("_060_fpsp_unfl"); - asmlinkage void dz_vec(void) asm ("_060_fpsp_dz"); - asmlinkage void inex_vec(void) asm ("_060_fpsp_inex"); - asmlinkage void fline_vec(void) asm ("_060_fpsp_fline"); - asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp"); - asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd"); - - vectors[VEC_FPNAN] = snan_vec; - vectors[VEC_FPOE] = operr_vec; - vectors[VEC_FPOVER] = ovfl_vec; - vectors[VEC_FPUNDER] = unfl_vec; - vectors[VEC_FPDIVZ] = dz_vec; - vectors[VEC_FPIR] = inex_vec; - vectors[VEC_LINE11] = fline_vec; - vectors[VEC_FPUNSUP] = unsupp_vec; - vectors[VEC_UNIMPEA] = effadd_vec; + asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan"); + asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr"); + asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl"); + asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl"); + asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz"); + asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex"); + asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline"); + asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp"); + asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd"); + + vectors[VEC_FPNAN] = snan_vec6; + vectors[VEC_FPOE] = operr_vec6; + vectors[VEC_FPOVER] = ovfl_vec6; + vectors[VEC_FPUNDER] = unfl_vec6; + vectors[VEC_FPDIVZ] = dz_vec6; + vectors[VEC_FPIR] = inex_vec6; + vectors[VEC_LINE11] = fline_vec6; + vectors[VEC_FPUNSUP] = unsupp_vec6; + vectors[VEC_UNIMPEA] = effadd_vec6; } /* if running on an amiga, make the NMI interrupt do nothing */ diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds index e58654f3f8d..69d1d3d30c7 100644 --- a/arch/m68k/kernel/vmlinux-std.lds +++ b/arch/m68k/kernel/vmlinux-std.lds @@ -13,6 +13,7 @@ SECTIONS .text : { *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.gnu.warning) } :text = 0x4e75 diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds index cc37e8d3c1e..65cc39c2418 100644 --- a/arch/m68k/kernel/vmlinux-sun3.lds +++ b/arch/m68k/kernel/vmlinux-sun3.lds @@ -14,6 +14,7 @@ SECTIONS *(.head) *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.gnu.warning) } :text = 0x4e75 @@ -66,7 +67,7 @@ __init_begin = .; __initramfs_end = .; . = ALIGN(8192); __init_end = .; - .init.task : { *(init_task) } + .data.init.task : { *(.data.init_task) } .bss : { *(.bss) } /* BSS */ diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c index 4a5c5445c61..cb13c6e3cca 100644 --- a/arch/m68k/lib/checksum.c +++ b/arch/m68k/lib/checksum.c @@ -134,7 +134,7 @@ EXPORT_SYMBOL(csum_partial); */ unsigned int -csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, +csum_partial_copy_from_user(const unsigned char __user *src, unsigned char *dst, int len, int sum, int *csum_err) { /* diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index cd19cbb213e..14f8d3f4e19 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -212,9 +212,6 @@ void __init config_mac(void) mach_reset = mac_reset; mach_halt = mac_poweroff; mach_power_off = mac_poweroff; -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif mach_max_dma_address = 0xffffffff; #if 0 mach_debug_init = mac_debug_init; diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c index d889ba80ccd..9179a379840 100644 --- a/arch/m68k/mac/iop.c +++ b/arch/m68k/mac/iop.c @@ -293,8 +293,8 @@ void __init iop_init(void) } for (i = 0 ; i < NUM_IOP_CHAN ; i++) { - iop_send_queue[IOP_NUM_SCC][i] = 0; - iop_send_queue[IOP_NUM_ISM][i] = 0; + iop_send_queue[IOP_NUM_SCC][i] = NULL; + iop_send_queue[IOP_NUM_ISM][i] = NULL; iop_listeners[IOP_NUM_SCC][i].devname = NULL; iop_listeners[IOP_NUM_SCC][i].handler = NULL; iop_listeners[IOP_NUM_ISM][i].devname = NULL; diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c index 5b80d7cd954..bbb0c3b95e9 100644 --- a/arch/m68k/mac/misc.c +++ b/arch/m68k/mac/misc.c @@ -39,72 +39,163 @@ extern struct mac_booter_data mac_bi_data; static void (*rom_reset)(void); -#ifdef CONFIG_ADB -/* - * Return the current time as the number of seconds since January 1, 1904. - */ - -static long adb_read_time(void) +#ifdef CONFIG_ADB_CUDA +static long cuda_read_time(void) { - volatile struct adb_request req; + struct adb_request req; long time; - adb_request((struct adb_request *) &req, NULL, - ADBREQ_RAW|ADBREQ_SYNC, - 2, CUDA_PACKET, CUDA_GET_TIME); + if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) + return 0; + while (!req.complete) + cuda_poll(); time = (req.reply[3] << 24) | (req.reply[4] << 16) | (req.reply[5] << 8) | req.reply[6]; return time - RTC_OFFSET; } -/* - * Set the current system time - */ +static void cuda_write_time(long data) +{ + struct adb_request req; + data += RTC_OFFSET; + if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, + (data >> 24) & 0xFF, (data >> 16) & 0xFF, + (data >> 8) & 0xFF, data & 0xFF) < 0) + return; + while (!req.complete) + cuda_poll(); +} -static void adb_write_time(long data) +static __u8 cuda_read_pram(int offset) { - volatile struct adb_request req; + struct adb_request req; + if (cuda_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM, + (offset >> 8) & 0xFF, offset & 0xFF) < 0) + return 0; + while (!req.complete) + cuda_poll(); + return req.reply[3]; +} - data += RTC_OFFSET; +static void cuda_write_pram(int offset, __u8 data) +{ + struct adb_request req; + if (cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM, + (offset >> 8) & 0xFF, offset & 0xFF, data) < 0) + return; + while (!req.complete) + cuda_poll(); +} +#else +#define cuda_read_time() 0 +#define cuda_write_time(n) +#define cuda_read_pram NULL +#define cuda_write_pram NULL +#endif + +#ifdef CONFIG_ADB_PMU68K +static long pmu_read_time(void) +{ + struct adb_request req; + long time; + + if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) + return 0; + while (!req.complete) + pmu_poll(); - adb_request((struct adb_request *) &req, NULL, - ADBREQ_RAW|ADBREQ_SYNC, - 6, CUDA_PACKET, CUDA_SET_TIME, + time = (req.reply[0] << 24) | (req.reply[1] << 16) + | (req.reply[2] << 8) | req.reply[3]; + return time - RTC_OFFSET; +} + +static void pmu_write_time(long data) +{ + struct adb_request req; + data += RTC_OFFSET; + if (pmu_request(&req, NULL, 5, PMU_SET_RTC, (data >> 24) & 0xFF, (data >> 16) & 0xFF, - (data >> 8) & 0xFF, data & 0xFF); + (data >> 8) & 0xFF, data & 0xFF) < 0) + return; + while (!req.complete) + pmu_poll(); } -/* - * Get a byte from the NVRAM - */ +static __u8 pmu_read_pram(int offset) +{ + struct adb_request req; + if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM, + (offset >> 8) & 0xFF, offset & 0xFF) < 0) + return 0; + while (!req.complete) + pmu_poll(); + return req.reply[3]; +} -static __u8 adb_read_pram(int offset) +static void pmu_write_pram(int offset, __u8 data) { - volatile struct adb_request req; + struct adb_request req; + if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM, + (offset >> 8) & 0xFF, offset & 0xFF, data) < 0) + return; + while (!req.complete) + pmu_poll(); +} +#else +#define pmu_read_time() 0 +#define pmu_write_time(n) +#define pmu_read_pram NULL +#define pmu_write_pram NULL +#endif - adb_request((struct adb_request *) &req, NULL, - ADBREQ_RAW|ADBREQ_SYNC, - 4, CUDA_PACKET, CUDA_GET_PRAM, - (offset >> 8) & 0xFF, offset & 0xFF); - return req.reply[3]; +#ifdef CONFIG_ADB_MACIISI +extern int maciisi_request(struct adb_request *req, + void (*done)(struct adb_request *), int nbytes, ...); + +static long maciisi_read_time(void) +{ + struct adb_request req; + long time; + + if (maciisi_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME)) + return 0; + + time = (req.reply[3] << 24) | (req.reply[4] << 16) + | (req.reply[5] << 8) | req.reply[6]; + return time - RTC_OFFSET; } -/* - * Write a byte to the NVRAM - */ +static void maciisi_write_time(long data) +{ + struct adb_request req; + data += RTC_OFFSET; + maciisi_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, + (data >> 24) & 0xFF, (data >> 16) & 0xFF, + (data >> 8) & 0xFF, data & 0xFF); +} -static void adb_write_pram(int offset, __u8 data) +static __u8 maciisi_read_pram(int offset) { - volatile struct adb_request req; + struct adb_request req; + if (maciisi_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM, + (offset >> 8) & 0xFF, offset & 0xFF)) + return 0; + return req.reply[3]; +} - adb_request((struct adb_request *) &req, NULL, - ADBREQ_RAW|ADBREQ_SYNC, - 5, CUDA_PACKET, CUDA_SET_PRAM, - (offset >> 8) & 0xFF, offset & 0xFF, - data); +static void maciisi_write_pram(int offset, __u8 data) +{ + struct adb_request req; + maciisi_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM, + (offset >> 8) & 0xFF, offset & 0xFF, data); } -#endif /* CONFIG_ADB */ +#else +#define maciisi_read_time() 0 +#define maciisi_write_time(n) +#define maciisi_read_pram NULL +#define maciisi_write_pram NULL +#endif /* * VIA PRAM/RTC access routines @@ -305,42 +396,55 @@ static void oss_shutdown(void) static void cuda_restart(void) { - adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, - 2, CUDA_PACKET, CUDA_RESET_SYSTEM); + struct adb_request req; + if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM) < 0) + return; + while (!req.complete) + cuda_poll(); } static void cuda_shutdown(void) { - adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, - 2, CUDA_PACKET, CUDA_POWERDOWN); + struct adb_request req; + if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN) < 0) + return; + while (!req.complete) + cuda_poll(); } #endif /* CONFIG_ADB_CUDA */ -#ifdef CONFIG_ADB_PMU +#ifdef CONFIG_ADB_PMU68K void pmu_restart(void) { - adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, - 3, PMU_PACKET, PMU_SET_INTR_MASK, - PMU_INT_ADB|PMU_INT_TICK); - - adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, - 2, PMU_PACKET, PMU_RESET); + struct adb_request req; + if (pmu_request(&req, NULL, + 2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0) + return; + while (!req.complete) + pmu_poll(); + if (pmu_request(&req, NULL, 1, PMU_RESET) < 0) + return; + while (!req.complete) + pmu_poll(); } void pmu_shutdown(void) { - adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, - 3, PMU_PACKET, PMU_SET_INTR_MASK, - PMU_INT_ADB|PMU_INT_TICK); - - adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, - 6, PMU_PACKET, PMU_SHUTDOWN, - 'M', 'A', 'T', 'T'); + struct adb_request req; + if (pmu_request(&req, NULL, + 2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0) + return; + while (!req.complete) + pmu_poll(); + if (pmu_request(&req, NULL, 5, PMU_SHUTDOWN, 'M', 'A', 'T', 'T') < 0) + return; + while (!req.complete) + pmu_poll(); } -#endif /* CONFIG_ADB_PMU */ +#endif /* *------------------------------------------------------------------- @@ -351,21 +455,22 @@ void pmu_shutdown(void) void mac_pram_read(int offset, __u8 *buffer, int len) { - __u8 (*func)(int) = NULL; + __u8 (*func)(int); int i; - if (macintosh_config->adb_type == MAC_ADB_IISI || - macintosh_config->adb_type == MAC_ADB_PB1 || - macintosh_config->adb_type == MAC_ADB_PB2 || - macintosh_config->adb_type == MAC_ADB_CUDA) { -#ifdef CONFIG_ADB - func = adb_read_pram; -#else - return; -#endif - } else { + switch(macintosh_config->adb_type) { + case MAC_ADB_IISI: + func = maciisi_read_pram; break; + case MAC_ADB_PB1: + case MAC_ADB_PB2: + func = pmu_read_pram; break; + case MAC_ADB_CUDA: + func = cuda_read_pram; break; + default: func = via_read_pram; } + if (!func) + return; for (i = 0 ; i < len ; i++) { buffer[i] = (*func)(offset++); } @@ -373,21 +478,22 @@ void mac_pram_read(int offset, __u8 *buffer, int len) void mac_pram_write(int offset, __u8 *buffer, int len) { - void (*func)(int, __u8) = NULL; + void (*func)(int, __u8); int i; - if (macintosh_config->adb_type == MAC_ADB_IISI || - macintosh_config->adb_type == MAC_ADB_PB1 || - macintosh_config->adb_type == MAC_ADB_PB2 || - macintosh_config->adb_type == MAC_ADB_CUDA) { -#ifdef CONFIG_ADB - func = adb_write_pram; -#else - return; -#endif - } else { + switch(macintosh_config->adb_type) { + case MAC_ADB_IISI: + func = maciisi_write_pram; break; + case MAC_ADB_PB1: + case MAC_ADB_PB2: + func = pmu_write_pram; break; + case MAC_ADB_CUDA: + func = cuda_write_pram; break; + default: func = via_write_pram; } + if (!func) + return; for (i = 0 ; i < len ; i++) { (*func)(offset++, buffer[i]); } @@ -408,7 +514,7 @@ void mac_poweroff(void) } else if (macintosh_config->adb_type == MAC_ADB_CUDA) { cuda_shutdown(); #endif -#ifdef CONFIG_ADB_PMU +#ifdef CONFIG_ADB_PMU68K } else if (macintosh_config->adb_type == MAC_ADB_PB1 || macintosh_config->adb_type == MAC_ADB_PB2) { pmu_shutdown(); @@ -448,7 +554,7 @@ void mac_reset(void) } else if (macintosh_config->adb_type == MAC_ADB_CUDA) { cuda_restart(); #endif -#ifdef CONFIG_ADB_PMU +#ifdef CONFIG_ADB_PMU68K } else if (macintosh_config->adb_type == MAC_ADB_PB1 || macintosh_config->adb_type == MAC_ADB_PB2) { pmu_restart(); @@ -466,12 +572,13 @@ void mac_reset(void) /* make a 1-to-1 mapping, using the transparent tran. reg. */ unsigned long virt = (unsigned long) mac_reset; unsigned long phys = virt_to_phys(mac_reset); + unsigned long addr = (phys&0xFF000000)|0x8777; unsigned long offset = phys-virt; local_irq_disable(); /* lets not screw this up, ok? */ __asm__ __volatile__(".chip 68030\n\t" "pmove %0,%/tt0\n\t" ".chip 68k" - : : "m" ((phys&0xFF000000)|0x8777)); + : : "m" (addr)); /* Now jump to physical address so we can disable MMU */ __asm__ __volatile__( ".chip 68030\n\t" @@ -588,20 +695,22 @@ int mac_hwclk(int op, struct rtc_time *t) unsigned long now; if (!op) { /* read */ - if (macintosh_config->adb_type == MAC_ADB_II) { + switch (macintosh_config->adb_type) { + case MAC_ADB_II: + case MAC_ADB_IOP: now = via_read_time(); - } else -#ifdef CONFIG_ADB - if ((macintosh_config->adb_type == MAC_ADB_IISI) || - (macintosh_config->adb_type == MAC_ADB_PB1) || - (macintosh_config->adb_type == MAC_ADB_PB2) || - (macintosh_config->adb_type == MAC_ADB_CUDA)) { - now = adb_read_time(); - } else -#endif - if (macintosh_config->adb_type == MAC_ADB_IOP) { - now = via_read_time(); - } else { + break; + case MAC_ADB_IISI: + now = maciisi_read_time(); + break; + case MAC_ADB_PB1: + case MAC_ADB_PB2: + now = pmu_read_time(); + break; + case MAC_ADB_CUDA: + now = cuda_read_time(); + break; + default: now = 0; } @@ -619,15 +728,20 @@ int mac_hwclk(int op, struct rtc_time *t) now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); - if (macintosh_config->adb_type == MAC_ADB_II) { - via_write_time(now); - } else if ((macintosh_config->adb_type == MAC_ADB_IISI) || - (macintosh_config->adb_type == MAC_ADB_PB1) || - (macintosh_config->adb_type == MAC_ADB_PB2) || - (macintosh_config->adb_type == MAC_ADB_CUDA)) { - adb_write_time(now); - } else if (macintosh_config->adb_type == MAC_ADB_IOP) { + switch (macintosh_config->adb_type) { + case MAC_ADB_II: + case MAC_ADB_IOP: via_write_time(now); + break; + case MAC_ADB_CUDA: + cuda_write_time(now); + break; + case MAC_ADB_PB1: + case MAC_ADB_PB2: + pmu_write_time(now); + break; + case MAC_ADB_IISI: + maciisi_write_time(now); } #endif } diff --git a/arch/m68k/math-emu/multi_arith.h b/arch/m68k/math-emu/multi_arith.h index 02251e5afd8..4ad0ca918e2 100644 --- a/arch/m68k/math-emu/multi_arith.h +++ b/arch/m68k/math-emu/multi_arith.h @@ -366,7 +366,7 @@ static inline void fp_submant(struct fp_ext *dest, struct fp_ext *src1, #define fp_mul64(desth, destl, src1, src2) ({ \ asm ("mulu.l %2,%1:%0" : "=d" (destl), "=d" (desth) \ - : "g" (src1), "0" (src2)); \ + : "dm" (src1), "0" (src2)); \ }) #define fp_div64(quot, rem, srch, srcl, div) \ asm ("divu.l %2,%1:%0" : "=d" (quot), "=d" (rem) \ diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c index fe2383e36b0..85ad19a0ac7 100644 --- a/arch/m68k/mm/kmap.c +++ b/arch/m68k/mm/kmap.c @@ -102,7 +102,7 @@ static inline void free_io_area(void *addr) */ /* Rewritten by Andreas Schwab to remove all races. */ -void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) +void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) { struct vm_struct *area; unsigned long virtaddr, retaddr; @@ -121,7 +121,7 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) if (MACH_IS_AMIGA) { if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000) && (cacheflag == IOMAP_NOCACHE_SER)) - return (void *)physaddr; + return (void __iomem *)physaddr; } #endif @@ -218,21 +218,21 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) #endif flush_tlb_all(); - return (void *)retaddr; + return (void __iomem *)retaddr; } /* * Unmap a ioremap()ed region again */ -void iounmap(void *addr) +void iounmap(void __iomem *addr) { #ifdef CONFIG_AMIGA if ((!MACH_IS_AMIGA) || (((unsigned long)addr < 0x40000000) || ((unsigned long)addr > 0x60000000))) - free_io_area(addr); + free_io_area((__force void *)addr); #else - free_io_area(addr); + free_io_area((__force void *)addr); #endif } diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c index 30f5921ece9..a69fe3048ed 100644 --- a/arch/m68k/mvme16x/rtc.c +++ b/arch/m68k/mvme16x/rtc.c @@ -45,6 +45,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, volatile MK48T08ptr_t rtc = (MK48T08ptr_t)MVME_RTC_BASE; unsigned long flags; struct rtc_time wtime; + void __user *argp = (void __user *)arg; switch (cmd) { case RTC_RD_TIME: /* Read the time/date from RTC */ @@ -64,7 +65,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1; rtc->ctrl = 0; local_irq_restore(flags); - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? + return copy_to_user(argp, &wtime, sizeof wtime) ? -EFAULT : 0; } case RTC_SET_TIME: /* Set the RTC */ @@ -76,8 +77,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, - sizeof(struct rtc_time))) + if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time))) return -EFAULT; yrs = rtc_tm.tm_year; diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c index 02b626bae4a..5e0f9b04d45 100644 --- a/arch/m68k/q40/config.c +++ b/arch/m68k/q40/config.c @@ -36,8 +36,6 @@ #include <asm/machdep.h> #include <asm/q40_master.h> -extern void floppy_setup(char *str, int *ints); - extern irqreturn_t q40_process_int (int level, struct pt_regs *regs); extern irqreturn_t (*q40_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */ extern void q40_init_IRQ (void); @@ -194,9 +192,6 @@ void __init config_q40(void) mach_heartbeat = q40_heartbeat; #endif mach_halt = q40_halt; -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif /* disable a few things that SMSQ might have left enabled */ q40_disable_irqs(); diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c index 77d05bcc322..f1ca0dfbaa6 100644 --- a/arch/m68k/sun3/config.c +++ b/arch/m68k/sun3/config.c @@ -160,9 +160,6 @@ void __init config_sun3(void) mach_hwclk = sun3_hwclk; mach_halt = sun3_halt; mach_get_hardware_list = sun3_get_hardware_list; -#if defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; -#endif memory_start = ((((int)&_end) + 0x2000) & ~0x1fff); // PROM seems to want the last couple of physical pages. --m diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c index 0ef547f5494..0920f5d3360 100644 --- a/arch/m68k/sun3x/config.c +++ b/arch/m68k/sun3x/config.c @@ -71,10 +71,6 @@ void __init config_sun3x(void) mach_get_model = sun3_get_model; mach_get_hardware_list = sun3x_get_hardware_list; -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - sun3_intreg = (unsigned char *)SUN3X_INTREG; /* only the serial console is known to work anyway... */ diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c index 8b3cf57ba70..99bf4382479 100644 --- a/arch/m68knommu/kernel/process.c +++ b/arch/m68knommu/kernel/process.c @@ -198,10 +198,9 @@ int copy_thread(int nr, unsigned long clone_flags, { struct pt_regs * childregs; struct switch_stack * childstack, *stack; - unsigned long stack_offset, *retp; + unsigned long *retp; - stack_offset = THREAD_SIZE - sizeof(struct pt_regs); - childregs = (struct pt_regs *) ((unsigned long) p->thread_info + stack_offset); + childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; *childregs = *regs; childregs->d0 = 0; diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 0476a4dce14..fa98f10d013 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -140,12 +140,12 @@ void flush_thread(void) int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, unsigned long unused, struct task_struct *p, struct pt_regs *regs) { - struct thread_info *ti = p->thread_info; + struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs; long childksp; p->set_child_tid = p->clear_child_tid = NULL; - childksp = (unsigned long)ti + THREAD_SIZE - 32; + childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32; preempt_disable(); @@ -229,9 +229,7 @@ void elf_dump_regs(elf_greg_t *gp, struct pt_regs *regs) int dump_task_regs (struct task_struct *tsk, elf_gregset_t *regs) { - struct thread_info *ti = tsk->thread_info; - long ksp = (unsigned long)ti + THREAD_SIZE - 32; - elf_dump_regs(&(*regs)[0], (struct pt_regs *) ksp - 1); + elf_dump_regs(*regs, task_pt_regs(tsk)); return 1; } @@ -409,7 +407,7 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = (unsigned long)p->thread_info; + stack_page = (unsigned long)task_stack_page(p); if (!stack_page || !mips_frame_info_initialized) return 0; diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 8d254933530..f838b36cc76 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -64,8 +64,7 @@ int ptrace_getregs (struct task_struct *child, __s64 __user *data) if (!access_ok(VERIFY_WRITE, data, 38 * 8)) return -EIO; - regs = (struct pt_regs *) ((unsigned long) child->thread_info + - THREAD_SIZE - 32 - sizeof(struct pt_regs)); + regs = task_pt_regs(child); for (i = 0; i < 32; i++) __put_user (regs->regs[i], data + i); @@ -92,8 +91,7 @@ int ptrace_setregs (struct task_struct *child, __s64 __user *data) if (!access_ok(VERIFY_READ, data, 38 * 8)) return -EIO; - regs = (struct pt_regs *) ((unsigned long) child->thread_info + - THREAD_SIZE - 32 - sizeof(struct pt_regs)); + regs = task_pt_regs(child); for (i = 0; i < 32; i++) __get_user (regs->regs[i], data + i); @@ -198,8 +196,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) struct pt_regs *regs; unsigned long tmp = 0; - regs = (struct pt_regs *) ((unsigned long) child->thread_info + - THREAD_SIZE - 32 - sizeof(struct pt_regs)); + regs = task_pt_regs(child); ret = 0; /* Default return value. */ switch (addr) { @@ -314,8 +311,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_POKEUSR: { struct pt_regs *regs; ret = 0; - regs = (struct pt_regs *) ((unsigned long) child->thread_info + - THREAD_SIZE - 32 - sizeof(struct pt_regs)); + regs = task_pt_regs(child); switch (addr) { case 0 ... 31: @@ -442,7 +438,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_GET_THREAD_AREA: - ret = put_user(child->thread_info->tp_value, + ret = put_user(task_thread_info(child)->tp_value, (unsigned long __user *) data); break; diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 1f998bfde16..0c82b25d8c6 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -126,8 +126,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) struct pt_regs *regs; unsigned int tmp; - regs = (struct pt_regs *) ((unsigned long) child->thread_info + - THREAD_SIZE - 32 - sizeof(struct pt_regs)); + regs = task_pt_regs(child); ret = 0; /* Default return value. */ switch (addr) { @@ -259,8 +258,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) case PTRACE_POKEUSR: { struct pt_regs *regs; ret = 0; - regs = (struct pt_regs *) ((unsigned long) child->thread_info + - THREAD_SIZE - 32 - sizeof(struct pt_regs)); + regs = task_pt_regs(child); switch (addr) { case 0 ... 31: @@ -377,7 +375,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) break; case PTRACE_GET_THREAD_AREA: - ret = put_user(child->thread_info->tp_value, + ret = put_user(task_thread_info(child)->tp_value, (unsigned int __user *) (unsigned long) data); break; @@ -391,7 +389,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) break; case PTRACE_GET_THREAD_AREA_3264: - ret = put_user(child->thread_info->tp_value, + ret = put_user(task_thread_info(child)->tp_value, (unsigned long __user *) (unsigned long) data); break; diff --git a/arch/mips/kernel/smp_mt.c b/arch/mips/kernel/smp_mt.c index d429544ba4b..794a1c3de2a 100644 --- a/arch/mips/kernel/smp_mt.c +++ b/arch/mips/kernel/smp_mt.c @@ -287,6 +287,7 @@ void prom_prepare_cpus(unsigned int max_cpus) */ void prom_boot_secondary(int cpu, struct task_struct *idle) { + struct thread_info *gp = task_thread_info(idle); dvpe(); set_c0_mvpcontrol(MVPCONTROL_VPC); @@ -307,11 +308,9 @@ void prom_boot_secondary(int cpu, struct task_struct *idle) write_tc_gpr_sp( __KSTK_TOS(idle)); /* global pointer */ - write_tc_gpr_gp((unsigned long)idle->thread_info); + write_tc_gpr_gp((unsigned long)gp); - flush_icache_range((unsigned long)idle->thread_info, - (unsigned long)idle->thread_info + - sizeof(struct thread_info)); + flush_icache_range((unsigned long)gp, (unsigned long)(gp + 1)); /* finally out of configuration and into chaos */ clear_c0_mvpcontrol(MVPCONTROL_VPC); diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 006881942aa..332358430ff 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -263,7 +263,7 @@ asmlinkage int sys_olduname(struct oldold_utsname * name) void sys_set_thread_area(unsigned long addr) { - struct thread_info *ti = current->thread_info; + struct thread_info *ti = task_thread_info(current); ti->tp_value = addr; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 7058893d5ad..59a187956de 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -519,7 +519,7 @@ static inline int simulate_llsc(struct pt_regs *regs) */ static inline int simulate_rdhwr(struct pt_regs *regs) { - struct thread_info *ti = current->thread_info; + struct thread_info *ti = task_thread_info(current); unsigned int opcode; if (unlikely(get_insn_opcode(regs, &opcode))) diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index 0527170d6ad..f17f575f58f 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c @@ -93,8 +93,8 @@ void __init prom_prepare_cpus(unsigned int max_cpus) */ void prom_boot_secondary(int cpu, struct task_struct *idle) { - unsigned long gp = (unsigned long) idle->thread_info; - unsigned long sp = gp + THREAD_SIZE - 32; + unsigned long gp = (unsigned long) task_thread_info(idle); + unsigned long sp = __KSTK_TOP(idle); secondary_sp = sp; secondary_gp = gp; diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index 3a8291b7d26..dbef3f6b565 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -168,8 +168,8 @@ void __init prom_prepare_cpus(unsigned int max_cpus) */ void __init prom_boot_secondary(int cpu, struct task_struct *idle) { - unsigned long gp = (unsigned long) idle->thread_info; - unsigned long sp = gp + THREAD_SIZE - 32; + unsigned long gp = (unsigned long)task_thread_info(idle); + unsigned long sp = __KSTK_TOS(idle); LAUNCH_SLAVE(cputonasid(cpu),cputoslice(cpu), (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap), diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c index e8485124b8f..4477af3d807 100644 --- a/arch/mips/sibyte/cfe/smp.c +++ b/arch/mips/sibyte/cfe/smp.c @@ -60,7 +60,7 @@ void prom_boot_secondary(int cpu, struct task_struct *idle) retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap, __KSTK_TOS(idle), - (unsigned long)idle->thread_info, 0); + (unsigned long)task_thread_info(idle), 0); if (retval != 0) printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); } diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 4eb70a40ec7..5da41677e70 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -295,7 +295,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct * p, struct pt_regs * pregs) { struct pt_regs * cregs = &(p->thread.regs); - struct thread_info *ti = p->thread_info; + void *stack = task_stack_page(p); /* We have to use void * instead of a function pointer, because * function pointers aren't a pointer to the function on 64-bit. @@ -322,7 +322,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, */ if (usp == 1) { /* kernel thread */ - cregs->ksp = (((unsigned long)(ti)) + THREAD_SZ_ALGN); + cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN; /* Must exit via ret_from_kernel_thread in order * to call schedule_tail() */ @@ -344,7 +344,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, */ /* Use same stack depth as parent */ - cregs->ksp = ((unsigned long)(ti)) + cregs->ksp = (unsigned long)stack + (pregs->gr[21] & (THREAD_SIZE - 1)); cregs->gr[30] = usp; if (p->personality == PER_HPUX) { diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 17f23c26f1c..25564b7ca6b 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -517,7 +517,7 @@ int __init smp_boot_one_cpu(int cpuid) if (IS_ERR(idle)) panic("SMP: fork failed for CPU:%d", cpuid); - idle->thread_info->cpu = cpuid; + task_thread_info(idle)->cpu = cpuid; /* Let _start know what logical CPU we're booting ** (offset into init_tasks[],cpu_data[]) diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index bbfa1bdceb4..a94699d8dc5 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -11,7 +11,8 @@ CFLAGS_btext.o += -fPIC endif obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ - irq.o align.o signal_32.o pmc.o vdso.o + irq.o align.o signal_32.o pmc.o vdso.o \ + init_task.o process.o obj-y += vdso32/ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ signal_64.o ptrace32.o systbl.o \ @@ -44,8 +45,7 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o extra-$(CONFIG_8xx) := head_8xx.o extra-y += vmlinux.lds -obj-y += process.o init_task.o time.o \ - prom.o traps.o setup-common.o udbg.o +obj-y += time.o prom.o traps.o setup-common.o udbg.o obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 24fe70f40b6..c367520bc1c 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -53,6 +53,7 @@ EXPORT_SYMBOL(io_page_mask); #ifdef CONFIG_PPC_MULTIPLATFORM static void fixup_resource(struct resource *res, struct pci_dev *dev); static void do_bus_setup(struct pci_bus *bus); +static void phbs_remap_io(void); #endif /* pci_io_base -- the base address from which io bars are offsets. @@ -251,6 +252,7 @@ void pcibios_free_controller(struct pci_controller *phb) kfree(phb); } +#ifndef CONFIG_PPC_ISERIES void __devinit pcibios_claim_one_bus(struct pci_bus *b) { struct pci_dev *dev; @@ -275,7 +277,6 @@ void __devinit pcibios_claim_one_bus(struct pci_bus *b) EXPORT_SYMBOL_GPL(pcibios_claim_one_bus); #endif -#ifndef CONFIG_PPC_ISERIES static void __init pcibios_claim_of_setup(void) { struct pci_bus *b; @@ -1218,7 +1219,7 @@ int remap_bus_range(struct pci_bus *bus) } EXPORT_SYMBOL(remap_bus_range); -void phbs_remap_io(void) +static void phbs_remap_io(void) { struct pci_controller *hose, *tmp; diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 105d5609ff5..57703994a06 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -201,13 +201,13 @@ int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) } #endif /* CONFIG_SPE */ +#ifndef CONFIG_SMP /* * If we are doing lazy switching of CPU state (FP, altivec or SPE), * and the current task has some state, discard it. */ -static inline void discard_lazy_cpu_state(void) +void discard_lazy_cpu_state(void) { -#ifndef CONFIG_SMP preempt_disable(); if (last_task_used_math == current) last_task_used_math = NULL; @@ -220,9 +220,10 @@ static inline void discard_lazy_cpu_state(void) last_task_used_spe = NULL; #endif preempt_enable(); -#endif /* CONFIG_SMP */ } +#endif /* CONFIG_SMP */ +#ifdef CONFIG_PPC_MERGE /* XXX for now */ int set_dabr(unsigned long dabr) { if (ppc_md.set_dabr) @@ -231,6 +232,7 @@ int set_dabr(unsigned long dabr) mtspr(SPRN_DABR, dabr); return 0; } +#endif #ifdef CONFIG_PPC64 DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); @@ -424,7 +426,7 @@ void show_regs(struct pt_regs * regs) if (trap == 0x300 || trap == 0x600) printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr); printk("TASK = %p[%d] '%s' THREAD: %p", - current, current->pid, current->comm, current->thread_info); + current, current->pid, current->comm, task_thread_info(current)); #ifdef CONFIG_SMP printk(" CPU: %d", smp_processor_id()); @@ -503,7 +505,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, { struct pt_regs *childregs, *kregs; extern void ret_from_fork(void); - unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE; + unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; CHECK_FULL_REGS(regs); /* Copy registers */ @@ -516,7 +518,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, #ifdef CONFIG_PPC32 childregs->gpr[2] = (unsigned long) p; #else - clear_ti_thread_flag(p->thread_info, TIF_32BIT); + clear_tsk_thread_flag(p, TIF_32BIT); #endif p->thread.regs = NULL; /* no user register state */ } else { @@ -588,10 +590,8 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) * set. Do it now. */ if (!current->thread.regs) { - unsigned long childregs = (unsigned long)current->thread_info + - THREAD_SIZE; - childregs -= sizeof(struct pt_regs); - current->thread.regs = (struct pt_regs *)childregs; + struct pt_regs *regs = task_stack_page(current) + THREAD_SIZE; + current->thread.regs = regs - 1; } memset(regs->gpr, 0, sizeof(regs->gpr)); @@ -767,7 +767,7 @@ out: static int validate_sp(unsigned long sp, struct task_struct *p, unsigned long nbytes) { - unsigned long stack_page = (unsigned long)p->thread_info; + unsigned long stack_page = (unsigned long)task_stack_page(p); if (sp >= stack_page + sizeof(struct thread_struct) && sp <= stack_page + THREAD_SIZE - nbytes) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 34ab0daec3a..02e2115323e 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1100,17 +1100,37 @@ static int __init early_init_dt_scan_memory(unsigned long node, static void __init early_reserve_mem(void) { - unsigned long base, size; - unsigned long *reserve_map; + u64 base, size; + u64 *reserve_map; - reserve_map = (unsigned long *)(((unsigned long)initial_boot_params) + + reserve_map = (u64 *)(((unsigned long)initial_boot_params) + initial_boot_params->off_mem_rsvmap); +#ifdef CONFIG_PPC32 + /* + * Handle the case where we might be booting from an old kexec + * image that setup the mem_rsvmap as pairs of 32-bit values + */ + if (*reserve_map > 0xffffffffull) { + u32 base_32, size_32; + u32 *reserve_map_32 = (u32 *)reserve_map; + + while (1) { + base_32 = *(reserve_map_32++); + size_32 = *(reserve_map_32++); + if (size_32 == 0) + break; + DBG("reserving: %lx -> %lx\n", base_32, size_32); + lmb_reserve(base_32, size_32); + } + return; + } +#endif while (1) { base = *(reserve_map++); size = *(reserve_map++); if (size == 0) break; - DBG("reserving: %lx -> %lx\n", base, size); + DBG("reserving: %llx -> %llx\n", base, size); lmb_reserve(base, size); } diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index e381f2fc121..d963a12ec64 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -137,8 +137,8 @@ struct prom_t { }; struct mem_map_entry { - unsigned long base; - unsigned long size; + u64 base; + u64 size; }; typedef u32 cell_t; @@ -897,9 +897,9 @@ static unsigned long __init prom_next_cell(int s, cell_t **cellp) * If problems seem to show up, it would be a good start to track * them down. */ -static void reserve_mem(unsigned long base, unsigned long size) +static void reserve_mem(u64 base, u64 size) { - unsigned long top = base + size; + u64 top = base + size; unsigned long cnt = RELOC(mem_reserve_cnt); if (size == 0) diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h index b1babb72967..5ccbdbe0d5c 100644 --- a/arch/powerpc/kernel/ptrace-common.h +++ b/arch/powerpc/kernel/ptrace-common.h @@ -62,7 +62,7 @@ static inline void set_single_step(struct task_struct *task) struct pt_regs *regs = task->thread.regs; if (regs != NULL) regs->msr |= MSR_SE; - set_ti_thread_flag(task->thread_info, TIF_SINGLESTEP); + set_tsk_thread_flag(task, TIF_SINGLESTEP); } static inline void clear_single_step(struct task_struct *task) @@ -70,7 +70,7 @@ static inline void clear_single_step(struct task_struct *task) struct pt_regs *regs = task->thread.regs; if (regs != NULL) regs->msr &= ~MSR_SE; - clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP); + clear_tsk_thread_flag(task, TIF_SINGLESTEP); } #ifdef CONFIG_ALTIVEC diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index d3f0b6d452f..177bba78fb0 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -497,6 +497,15 @@ static long restore_user_regs(struct pt_regs *regs, if (err) return 1; + /* + * Do this before updating the thread state in + * current->thread.fpr/vr/evr. That way, if we get preempted + * and another task grabs the FPU/Altivec/SPE, it won't be + * tempted to save the current CPU state into the thread_struct + * and corrupt what we are writing there. + */ + discard_lazy_cpu_state(); + /* force the process to reload the FP registers from current->thread when it next does FP instructions */ regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); @@ -538,18 +547,6 @@ static long restore_user_regs(struct pt_regs *regs, return 1; #endif /* CONFIG_SPE */ -#ifndef CONFIG_SMP - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif - preempt_enable(); -#endif return 0; } diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 5462bef898f..7b9d999e211 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -207,10 +207,20 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, if (!sig) regs->gpr[13] = save_r13; - err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); if (set != NULL) err |= __get_user(set->sig[0], &sc->oldmask); + /* + * Do this before updating the thread state in + * current->thread.fpr/vr. That way, if we get preempted + * and another task grabs the FPU/Altivec, it won't be + * tempted to save the current CPU state into the thread_struct + * and corrupt what we are writing there. + */ + discard_lazy_cpu_state(); + + err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); + #ifdef CONFIG_ALTIVEC err |= __get_user(v_regs, &sc->v_regs); err |= __get_user(msr, &sc->gp_regs[PT_MSR]); @@ -229,14 +239,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, current->thread.vrsave = 0; #endif /* CONFIG_ALTIVEC */ -#ifndef CONFIG_SMP - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; - preempt_enable(); -#endif /* Force reload of FP/VEC */ regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index d381ec90b75..c8458c531b2 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -338,8 +338,8 @@ static void __init smp_create_idle(unsigned int cpu) #ifdef CONFIG_PPC64 paca[cpu].__current = p; #endif - current_set[cpu] = p->thread_info; - p->thread_info->cpu = cpu; + current_set[cpu] = task_thread_info(p); + task_thread_info(p)->cpu = cpu; } void __init smp_prepare_cpus(unsigned int max_cpus) @@ -375,7 +375,7 @@ void __devinit smp_prepare_boot_cpu(void) #ifdef CONFIG_PPC64 paca[boot_cpuid].__current = current; #endif - current_set[boot_cpuid] = current->thread_info; + current_set[boot_cpuid] = task_thread_info(current); } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index 85152544c15..e0e051c675d 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -142,7 +142,7 @@ static void cbe_idle(void) } } -int cbe_system_reset_exception(struct pt_regs *regs) +static int cbe_system_reset_exception(struct pt_regs *regs) { switch (regs->msr & SRR1_WAKEMASK) { case SRR1_WAKEEE: diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 18e25e65c04..b33a4443f5a 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -57,7 +57,7 @@ #define DBG(fmt...) #endif -void cell_show_cpuinfo(struct seq_file *m) +static void cell_show_cpuinfo(struct seq_file *m) { struct device_node *root; const char *model = ""; diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c index de96eadf419..bdf6c5fe58c 100644 --- a/arch/powerpc/platforms/cell/smp.c +++ b/arch/powerpc/platforms/cell/smp.c @@ -86,7 +86,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) pcpu = get_hard_smp_processor_id(lcpu); /* Fixup atomic count: it exited inside IRQ handler. */ - paca[lcpu].__current->thread_info->preempt_count = 0; + task_thread_info(paca[lcpu].__current)->preempt_count = 0; /* * If the RTAS start-cpu token does not exist then presume the diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c index d549aa7ebea..e6565a949dd 100644 --- a/arch/powerpc/platforms/cell/spufs/syscalls.c +++ b/arch/powerpc/platforms/cell/spufs/syscalls.c @@ -29,7 +29,9 @@ * value of the spu_status register after the SPU has stopped. * */ -long do_spu_run(struct file *filp, __u32 __user *unpc, __u32 __user *ustatus) +static long do_spu_run(struct file *filp, + __u32 __user *unpc, + __u32 __user *ustatus) { long ret; struct spufs_inode_info *i; diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index 127b465308b..ce8c0b943fa 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,8 +1,8 @@ EXTRA_CFLAGS += -mno-minimal-toc obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ - hvcall.o proc.o htab.o iommu.o misc.o -obj-$(CONFIG_PCI) += pci.o irq.o vpdinfo.o + hvcall.o proc.o htab.o iommu.o misc.o irq.o +obj-$(CONFIG_PCI) += pci.o vpdinfo.o obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_VIOPATH) += viopath.o diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 2b54eeb2c89..bea0b703f40 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -34,6 +34,8 @@ #include <asm/pci-bridge.h> #include <asm/iseries/hv_call_xm.h> +#include "iommu.h" + extern struct list_head iSeries_Global_Device_List; diff --git a/arch/powerpc/platforms/iseries/iommu.h b/arch/powerpc/platforms/iseries/iommu.h new file mode 100644 index 00000000000..cb5658fbe65 --- /dev/null +++ b/arch/powerpc/platforms/iseries/iommu.h @@ -0,0 +1,35 @@ +#ifndef _PLATFORMS_ISERIES_IOMMU_H +#define _PLATFORMS_ISERIES_IOMMU_H + +/* + * Copyright (C) 2005 Stephen Rothwell, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ + +struct device_node; +struct iommu_table; + +/* Creates table for an individual device node */ +extern void iommu_devnode_init_iSeries(struct device_node *dn); + +/* Get table parameters from HV */ +extern void iommu_table_getparms_iSeries(unsigned long busno, + unsigned char slotno, unsigned char virtbus, + struct iommu_table *tbl); + +#endif /* _PLATFORMS_ISERIES_IOMMU_H */ diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 42e978e4897..83442ea7747 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -48,6 +48,8 @@ extern void iSeries_smp_message_recv(struct pt_regs *); #endif +#ifdef CONFIG_PCI + enum pci_event_type { pe_bus_created = 0, /* PHB has been created */ pe_bus_error = 1, /* PHB has failed */ @@ -147,20 +149,11 @@ static void int_received(struct pci_event *event, struct pt_regs *regs) static void pci_event_handler(struct HvLpEvent *event, struct pt_regs *regs) { if (event && (event->xType == HvLpEvent_Type_PciIo)) { - switch (event->xFlags.xFunction) { - case HvLpEvent_Function_Int: + if (hvlpevent_is_int(event)) int_received((struct pci_event *)event, regs); - break; - case HvLpEvent_Function_Ack: + else printk(KERN_ERR "pci_event_handler: unexpected ack received\n"); - break; - default: - printk(KERN_ERR - "pci_event_handler: unexpected event function %d\n", - (int)event->xFlags.xFunction); - break; - } } else if (event) printk(KERN_ERR "pci_event_handler: Unrecognized PCI event type 0x%x\n", @@ -334,6 +327,8 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus, return virtirq; } +#endif /* CONFIG_PCI */ + /* * Get the next pending IRQ. */ @@ -353,6 +348,7 @@ int iSeries_get_irq(struct pt_regs *regs) if (hvlpevent_is_pending()) process_hvlpevents(regs); +#ifdef CONFIG_PCI if (num_pending_irqs) { spin_lock(&pending_irqs_lock); for (irq = 0; irq < NR_IRQS; irq++) { @@ -366,6 +362,7 @@ int iSeries_get_irq(struct pt_regs *regs) if (irq >= NR_IRQS) irq = -2; } +#endif return irq; } diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c index ea72385aaf0..438e2dba63b 100644 --- a/arch/powerpc/platforms/iseries/lpardata.c +++ b/arch/powerpc/platforms/iseries/lpardata.c @@ -93,10 +93,7 @@ struct ItLpNaca itLpNaca = { .xPirEnvironMode = 0, /* Piranha stuff */ .xPirConsoleMode = 0, .xPirDasdMode = 0, - .xLparInstalled = 0, - .xSysPartitioned = 0, - .xHwSyncedTBs = 0, - .xIntProcUtilHmt = 0, + .flags = 0, .xSpVpdFormat = 0, .xIntProcRatio = 0, .xPlicVrmIndex = 0, /* VRM index of PLIC */ diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c index e9fb98bf895..0b885300d1d 100644 --- a/arch/powerpc/platforms/iseries/lpevents.c +++ b/arch/powerpc/platforms/iseries/lpevents.c @@ -53,7 +53,7 @@ static struct HvLpEvent * get_next_hvlpevent(void) struct HvLpEvent * event; event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; - if (event->xFlags.xValid) { + if (hvlpevent_is_valid(event)) { /* rmb() needed only for weakly consistent machines (regatta) */ rmb(); /* Set pointer to next potential event */ @@ -84,7 +84,7 @@ int hvlpevent_is_pending(void) next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; - return next_event->xFlags.xValid | + return hvlpevent_is_valid(next_event) || hvlpevent_queue.xPlicOverflowIntPending; } @@ -101,18 +101,18 @@ static void hvlpevent_clear_valid(struct HvLpEvent * event) switch (extra) { case 3: tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign); - tmp->xFlags.xValid = 0; + hvlpevent_invalidate(tmp); case 2: tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign); - tmp->xFlags.xValid = 0; + hvlpevent_invalidate(tmp); case 1: tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign); - tmp->xFlags.xValid = 0; + hvlpevent_invalidate(tmp); } mb(); - event->xFlags.xValid = 0; + hvlpevent_invalidate(event); } void process_hvlpevents(struct pt_regs *regs) diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 49e7e4b8584..a41d8b78c0c 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -251,10 +251,7 @@ static struct pending_event *new_pending_event(void) } memset(ev, 0, sizeof(struct pending_event)); hev = &ev->event.hp_lp_event; - hev->xFlags.xValid = 1; - hev->xFlags.xAckType = HvLpEvent_AckType_ImmediateAck; - hev->xFlags.xAckInd = HvLpEvent_AckInd_DoAck; - hev->xFlags.xFunction = HvLpEvent_Function_Int; + hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DO_ACK | HV_LP_EVENT_INT; hev->xType = HvLpEvent_Type_MachineFac; hev->xSourceLp = HvLpConfig_getLpIndex(); hev->xTargetLp = primary_lp; @@ -518,17 +515,10 @@ static void handle_ack(struct io_mf_lp_event *event) static void hv_handler(struct HvLpEvent *event, struct pt_regs *regs) { if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) { - switch(event->xFlags.xFunction) { - case HvLpEvent_Function_Ack: + if (hvlpevent_is_ack(event)) handle_ack((struct io_mf_lp_event *)event); - break; - case HvLpEvent_Function_Int: + else handle_int((struct io_mf_lp_event *)event); - break; - default: - printk(KERN_ERR "mf.c: non ack/int event received\n"); - break; - } } else printk(KERN_ERR "mf.c: alien event received\n"); } diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index dafc518fbb8..a19833b880e 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -43,6 +43,7 @@ #include "irq.h" #include "pci.h" #include "call_pci.h" +#include "iommu.h" extern unsigned long io_page_mask; diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index 384360ee06e..ad36ab0639f 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -22,6 +22,8 @@ #include <asm/iseries/hv_lp_config.h> #include <asm/iseries/hv_call_xm.h> +#include "iommu.h" + struct device *iSeries_vio_dev = &vio_bus_device.dev; EXPORT_SYMBOL(iSeries_vio_dev); diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 84267269559..622a30149b4 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -270,7 +270,7 @@ static void handleMonitorEvent(struct HvLpEvent *event) * First see if this is just a normal monitor message from the * other partition */ - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + if (hvlpevent_is_int(event)) { remoteLp = event->xSourceLp; if (!viopathStatus[remoteLp].isActive) sendMonMsg(remoteLp); @@ -331,13 +331,12 @@ static void handleConfig(struct HvLpEvent *event) { if (!event) return; - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + if (hvlpevent_is_int(event)) { printk(VIOPATH_KERN_WARN "unexpected config request from partition %d", event->xSourceLp); - if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && - (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) { + if (hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); } @@ -377,7 +376,7 @@ static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs) int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK) >> VIOMAJOR_SUBTYPE_SHIFT; - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + if (hvlpevent_is_int(event)) { remoteLp = event->xSourceLp; /* * The isActive is checked because if the hosting partition @@ -436,8 +435,7 @@ static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs) "unexpected virtual io event subtype %d from partition %d\n", event->xSubtype, remoteLp); /* No handler. Ack if necessary */ - if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && - (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) { + if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); } diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 3b1a9d4fcbc..89c4c363616 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -278,7 +278,7 @@ static void __init l2cr_init(void) } #endif -void __init pmac_setup_arch(void) +static void __init pmac_setup_arch(void) { struct device_node *cpu, *ic; int *fp; diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 17cea7f2afd..83578313ee7 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -208,10 +208,11 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag) { while (dn) { if (PCI_DN(dn)) { - PCI_DN(dn)->eeh_mode |= mode_flag; - /* Mark the pci device driver too */ struct pci_dev *dev = PCI_DN(dn)->pcidev; + + PCI_DN(dn)->eeh_mode |= mode_flag; + if (dev && dev->driver) dev->error_state = pci_channel_io_frozen; diff --git a/arch/powerpc/platforms/pseries/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c index 4d584172055..22bfb5c89db 100644 --- a/arch/powerpc/platforms/pseries/hvcserver.c +++ b/arch/powerpc/platforms/pseries/hvcserver.c @@ -40,7 +40,7 @@ MODULE_VERSION(HVCS_ARCH_VERSION); * functions aren't performance sensitive, so this conversion isn't an * issue. */ -int hvcs_convert(long to_convert) +static int hvcs_convert(long to_convert) { switch (to_convert) { case H_Success: @@ -91,7 +91,7 @@ int hvcs_free_partner_info(struct list_head *head) EXPORT_SYMBOL(hvcs_free_partner_info); /* Helper function for hvcs_get_partner_info */ -int hvcs_next_partner(uint32_t unit_address, +static int hvcs_next_partner(uint32_t unit_address, unsigned long last_p_partition_ID, unsigned long last_p_unit_address, unsigned long *pi_buff) diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 169f9148789..48cfbfc43f9 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -51,8 +51,6 @@ #define DBG(fmt...) -extern int is_python(struct device_node *); - static void tce_build_pSeries(struct iommu_table *tbl, long index, long npages, unsigned long uaddr, enum dma_data_direction direction) diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index 2edc947f7c4..50643496eb6 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c @@ -192,7 +192,7 @@ struct file_operations scanlog_fops = { .release = scanlog_release, }; -int __init scanlog_init(void) +static int __init scanlog_init(void) { struct proc_dir_entry *ent; @@ -222,7 +222,7 @@ int __init scanlog_init(void) return 0; } -void __exit scanlog_cleanup(void) +static void __exit scanlog_cleanup(void) { if (proc_ppc64_scan_log_dump) { kfree(proc_ppc64_scan_log_dump->data); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 8903cf63236..68b7f086d63 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -86,7 +86,7 @@ static void pseries_dedicated_idle(void); struct mpic *pSeries_mpic; -void pSeries_show_cpuinfo(struct seq_file *m) +static void pSeries_show_cpuinfo(struct seq_file *m) { struct device_node *root; const char *model = ""; diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 25181c594d7..8e6b1ed1396 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -93,7 +93,7 @@ static int query_cpu_stopped(unsigned int pcpu) return cpu_status; } -int pSeries_cpu_disable(void) +static int pSeries_cpu_disable(void) { int cpu = smp_processor_id(); @@ -109,7 +109,7 @@ int pSeries_cpu_disable(void) return 0; } -void pSeries_cpu_die(unsigned int cpu) +static void pSeries_cpu_die(unsigned int cpu) { int tries; int cpu_status; @@ -282,7 +282,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) pcpu = get_hard_smp_processor_id(lcpu); /* Fixup atomic count: it exited inside IRQ handler. */ - paca[lcpu].__current->thread_info->preempt_count = 0; + task_thread_info(paca[lcpu].__current)->preempt_count = 0; /* * If the RTAS start-cpu token does not exist then presume the diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 0c0cfa32eb5..fd823c7c9ac 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -381,7 +381,7 @@ int xics_get_irq(struct pt_regs *regs) #ifdef CONFIG_SMP -irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) { int cpu = smp_processor_id(); diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index e00b46b9514..977de9db875 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -139,7 +139,6 @@ static void dart_build(struct iommu_table *tbl, long index, *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK); - rpn++; uaddr += DART_PAGE_SIZE; } diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 22612ed5379..7d02fa2a899 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -311,7 +311,7 @@ static void release_output_lock(void) } #endif -int xmon_core(struct pt_regs *regs, int fromipi) +static int xmon_core(struct pt_regs *regs, int fromipi) { int cmd = 0; unsigned long msr; @@ -528,7 +528,7 @@ xmon_irq(int irq, void *d, struct pt_regs *regs) return IRQ_HANDLED; } -int xmon_bpt(struct pt_regs *regs) +static int xmon_bpt(struct pt_regs *regs) { struct bpt *bp; unsigned long offset; @@ -554,7 +554,7 @@ int xmon_bpt(struct pt_regs *regs) return 1; } -int xmon_sstep(struct pt_regs *regs) +static int xmon_sstep(struct pt_regs *regs) { if (user_mode(regs)) return 0; @@ -562,7 +562,7 @@ int xmon_sstep(struct pt_regs *regs) return 1; } -int xmon_dabr_match(struct pt_regs *regs) +static int xmon_dabr_match(struct pt_regs *regs) { if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) return 0; @@ -572,7 +572,7 @@ int xmon_dabr_match(struct pt_regs *regs) return 1; } -int xmon_iabr_match(struct pt_regs *regs) +static int xmon_iabr_match(struct pt_regs *regs) { if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) return 0; @@ -582,7 +582,7 @@ int xmon_iabr_match(struct pt_regs *regs) return 1; } -int xmon_ipi(struct pt_regs *regs) +static int xmon_ipi(struct pt_regs *regs) { #ifdef CONFIG_SMP if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon)) @@ -591,7 +591,7 @@ int xmon_ipi(struct pt_regs *regs) return 0; } -int xmon_fault_handler(struct pt_regs *regs) +static int xmon_fault_handler(struct pt_regs *regs) { struct bpt *bp; unsigned long offset; diff --git a/arch/ppc/amiga/amiints.c b/arch/ppc/amiga/amiints.c index 91195e2ce38..5f35cf3986f 100644 --- a/arch/ppc/amiga/amiints.c +++ b/arch/ppc/amiga/amiints.c @@ -96,8 +96,8 @@ void amiga_init_IRQ(void) gayle.inten = GAYLE_IRQ_IDE; /* turn off all interrupts... */ - custom.intena = 0x7fff; - custom.intreq = 0x7fff; + amiga_custom.intena = 0x7fff; + amiga_custom.intreq = 0x7fff; #ifdef CONFIG_APUS /* Clear any inter-CPU interrupt requests. Circumvents bug in @@ -110,7 +110,7 @@ void amiga_init_IRQ(void) APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_IPLMASK); #endif /* ... and enable the master interrupt bit */ - custom.intena = IF_SETCLR | IF_INTEN; + amiga_custom.intena = IF_SETCLR | IF_INTEN; cia_init_IRQ(&ciaa_base); cia_init_IRQ(&ciab_base); @@ -151,7 +151,7 @@ void amiga_enable_irq(unsigned int irq) } /* enable the interrupt */ - custom.intena = IF_SETCLR | ami_intena_vals[irq]; + amiga_custom.intena = IF_SETCLR | ami_intena_vals[irq]; } void amiga_disable_irq(unsigned int irq) @@ -177,7 +177,7 @@ void amiga_disable_irq(unsigned int irq) } /* disable the interrupt */ - custom.intena = ami_intena_vals[irq]; + amiga_custom.intena = ami_intena_vals[irq]; } inline void amiga_do_irq(int irq, struct pt_regs *fp) @@ -196,7 +196,7 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp) kstat_cpu(0).irqs[irq]++; - custom.intreq = ami_intena_vals[irq]; + amiga_custom.intreq = ami_intena_vals[irq]; for (action = desc->action; action; action = action->next) action->handler(irq, action->dev_id, fp); @@ -208,40 +208,40 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp) static void ami_int1(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if serial transmit buffer empty, interrupt */ if (ints & IF_TBE) { - custom.intreq = IF_TBE; + amiga_custom.intreq = IF_TBE; amiga_do_irq(IRQ_AMIGA_TBE, fp); } /* if floppy disk transfer complete, interrupt */ if (ints & IF_DSKBLK) { - custom.intreq = IF_DSKBLK; + amiga_custom.intreq = IF_DSKBLK; amiga_do_irq(IRQ_AMIGA_DSKBLK, fp); } /* if software interrupt set, interrupt */ if (ints & IF_SOFT) { - custom.intreq = IF_SOFT; + amiga_custom.intreq = IF_SOFT; amiga_do_irq(IRQ_AMIGA_SOFT, fp); } } static void ami_int3(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if a blitter interrupt */ if (ints & IF_BLIT) { - custom.intreq = IF_BLIT; + amiga_custom.intreq = IF_BLIT; amiga_do_irq(IRQ_AMIGA_BLIT, fp); } /* if a copper interrupt */ if (ints & IF_COPER) { - custom.intreq = IF_COPER; + amiga_custom.intreq = IF_COPER; amiga_do_irq(IRQ_AMIGA_COPPER, fp); } @@ -252,36 +252,36 @@ static void ami_int3(int irq, void *dev_id, struct pt_regs *fp) static void ami_int4(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if audio 0 interrupt */ if (ints & IF_AUD0) { - custom.intreq = IF_AUD0; + amiga_custom.intreq = IF_AUD0; amiga_do_irq(IRQ_AMIGA_AUD0, fp); } /* if audio 1 interrupt */ if (ints & IF_AUD1) { - custom.intreq = IF_AUD1; + amiga_custom.intreq = IF_AUD1; amiga_do_irq(IRQ_AMIGA_AUD1, fp); } /* if audio 2 interrupt */ if (ints & IF_AUD2) { - custom.intreq = IF_AUD2; + amiga_custom.intreq = IF_AUD2; amiga_do_irq(IRQ_AMIGA_AUD2, fp); } /* if audio 3 interrupt */ if (ints & IF_AUD3) { - custom.intreq = IF_AUD3; + amiga_custom.intreq = IF_AUD3; amiga_do_irq(IRQ_AMIGA_AUD3, fp); } } static void ami_int5(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if serial receive buffer full interrupt */ if (ints & IF_RBF) { @@ -291,7 +291,7 @@ static void ami_int5(int irq, void *dev_id, struct pt_regs *fp) /* if a disk sync interrupt */ if (ints & IF_DSKSYN) { - custom.intreq = IF_DSKSYN; + amiga_custom.intreq = IF_DSKSYN; amiga_do_irq(IRQ_AMIGA_DSKSYN, fp); } } diff --git a/arch/ppc/amiga/cia.c b/arch/ppc/amiga/cia.c index ad961465b6c..4431c58f611 100644 --- a/arch/ppc/amiga/cia.c +++ b/arch/ppc/amiga/cia.c @@ -66,7 +66,7 @@ static unsigned char cia_set_irq_private(struct ciabase *base, else base->icr_data &= ~mask; if (base->icr_data & base->icr_mask) - custom.intreq = IF_SETCLR | base->int_mask; + amiga_custom.intreq = IF_SETCLR | base->int_mask; return old & base->icr_mask; } @@ -114,7 +114,7 @@ static unsigned char cia_able_irq_private(struct ciabase *base, base->icr_mask &= CIA_ICR_ALL; if (base->icr_data & base->icr_mask) - custom.intreq = IF_SETCLR | base->int_mask; + amiga_custom.intreq = IF_SETCLR | base->int_mask; return old; } @@ -145,7 +145,7 @@ static void cia_handler(int irq, void *dev_id, struct pt_regs *fp) irq = base->cia_irq; desc = irq_desc + irq; ints = cia_set_irq_private(base, CIA_ICR_ALL); - custom.intreq = base->int_mask; + amiga_custom.intreq = base->int_mask; for (i = 0; i < CIA_IRQS; i++, irq++) { if (ints & 1) { kstat_cpu(0).irqs[irq]++; @@ -174,5 +174,5 @@ void __init cia_init_IRQ(struct ciabase *base) action->name = base->name; setup_irq(base->handler_irq, &amiga_sys_irqaction[base->handler_irq-IRQ_AMIGA_AUTO]); - custom.intena = IF_SETCLR | base->int_mask; + amiga_custom.intena = IF_SETCLR | base->int_mask; } diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c index af881d7454d..60e2da1c92c 100644 --- a/arch/ppc/amiga/config.c +++ b/arch/ppc/amiga/config.c @@ -90,9 +90,6 @@ static void a3000_gettod (int *, int *, int *, int *, int *, int *); static void a2000_gettod (int *, int *, int *, int *, int *, int *); static int amiga_hwclk (int, struct hwclk_time *); static int amiga_set_clock_mmss (unsigned long); -#ifdef CONFIG_AMIGA_FLOPPY -extern void amiga_floppy_setup(char *, int *); -#endif static void amiga_reset (void); extern void amiga_init_sound(void); static void amiga_savekmsg_init(void); @@ -281,7 +278,7 @@ static void __init amiga_identify(void) case CS_OCS: case CS_ECS: case CS_AGA: - switch (custom.deniseid & 0xf) { + switch (amiga_custom.deniseid & 0xf) { case 0x0c: AMIGAHW_SET(DENISE_HR); break; @@ -294,7 +291,7 @@ static void __init amiga_identify(void) AMIGAHW_SET(DENISE); break; } - switch ((custom.vposr>>8) & 0x7f) { + switch ((amiga_custom.vposr>>8) & 0x7f) { case 0x00: AMIGAHW_SET(AGNUS_PAL); break; @@ -419,9 +416,6 @@ void __init config_amiga(void) mach_hwclk = amiga_hwclk; mach_set_clock_mmss = amiga_set_clock_mmss; -#ifdef CONFIG_AMIGA_FLOPPY - mach_floppy_setup = amiga_floppy_setup; -#endif mach_reset = amiga_reset; #ifdef CONFIG_HEARTBEAT mach_heartbeat = amiga_heartbeat; @@ -432,9 +426,9 @@ void __init config_amiga(void) amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */ /* clear all DMA bits */ - custom.dmacon = DMAF_ALL; + amiga_custom.dmacon = DMAF_ALL; /* ensure that the DMA master bit is set */ - custom.dmacon = DMAF_SETCLR | DMAF_MASTER; + amiga_custom.dmacon = DMAF_SETCLR | DMAF_MASTER; /* request all RAM */ for (i = 0; i < m68k_num_memory; i++) { @@ -753,9 +747,9 @@ static void amiga_savekmsg_init(void) static void amiga_serial_putc(char c) { - custom.serdat = (unsigned char)c | 0x100; + amiga_custom.serdat = (unsigned char)c | 0x100; mb(); - while (!(custom.serdatr & 0x2000)) + while (!(amiga_custom.serdatr & 0x2000)) ; } @@ -785,11 +779,11 @@ int amiga_serial_console_wait_key(struct console *co) { int ch; - while (!(custom.intreqr & IF_RBF)) + while (!(amiga_custom.intreqr & IF_RBF)) barrier(); - ch = custom.serdatr & 0xff; + ch = amiga_custom.serdatr & 0xff; /* clear the interrupt, so that another character can be read */ - custom.intreq = IF_RBF; + amiga_custom.intreq = IF_RBF; return ch; } diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index e6c1d615bb8..ca020130086 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -13,7 +13,6 @@ extra-$(CONFIG_POWER4) += idle_power4.o extra-y += vmlinux.lds obj-y := entry.o traps.o idle.o time.o misc.o \ - process.o \ setup.o \ ppc_htab.o obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c deleted file mode 100644 index 25cbdc8d294..00000000000 --- a/arch/ppc/kernel/process.c +++ /dev/null @@ -1,851 +0,0 @@ -/* - * arch/ppc/kernel/process.c - * - * Derived from "arch/i386/kernel/process.c" - * Copyright (C) 1995 Linus Torvalds - * - * Updated and modified by Cort Dougan (cort@cs.nmt.edu) and - * Paul Mackerras (paulus@cs.anu.edu.au) - * - * PowerPC version - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ - -#include <linux/config.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/stddef.h> -#include <linux/unistd.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <linux/user.h> -#include <linux/elf.h> -#include <linux/init.h> -#include <linux/prctl.h> -#include <linux/init_task.h> -#include <linux/module.h> -#include <linux/kallsyms.h> -#include <linux/mqueue.h> -#include <linux/hardirq.h> - -#include <asm/pgtable.h> -#include <asm/uaccess.h> -#include <asm/system.h> -#include <asm/io.h> -#include <asm/processor.h> -#include <asm/mmu.h> -#include <asm/prom.h> - -extern unsigned long _get_SP(void); - -struct task_struct *last_task_used_math = NULL; -struct task_struct *last_task_used_altivec = NULL; -struct task_struct *last_task_used_spe = NULL; - -static struct fs_struct init_fs = INIT_FS; -static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); -EXPORT_SYMBOL(init_mm); - -/* this is 8kB-aligned so we can get to the thread_info struct - at the base of it from the stack pointer with 1 integer instruction. */ -union thread_union init_thread_union - __attribute__((__section__(".data.init_task"))) = -{ INIT_THREAD_INFO(init_task) }; - -/* initial task structure */ -struct task_struct init_task = INIT_TASK(init_task); -EXPORT_SYMBOL(init_task); - -/* only used to get secondary processor up */ -struct task_struct *current_set[NR_CPUS] = {&init_task, }; - -#undef SHOW_TASK_SWITCHES -#undef CHECK_STACK - -#if defined(CHECK_STACK) -unsigned long -kernel_stack_top(struct task_struct *tsk) -{ - return ((unsigned long)tsk) + sizeof(union task_union); -} - -unsigned long -task_top(struct task_struct *tsk) -{ - return ((unsigned long)tsk) + sizeof(struct thread_info); -} - -/* check to make sure the kernel stack is healthy */ -int check_stack(struct task_struct *tsk) -{ - unsigned long stack_top = kernel_stack_top(tsk); - unsigned long tsk_top = task_top(tsk); - int ret = 0; - -#if 0 - /* check thread magic */ - if ( tsk->thread.magic != THREAD_MAGIC ) - { - ret |= 1; - printk("thread.magic bad: %08x\n", tsk->thread.magic); - } -#endif - - if ( !tsk ) - printk("check_stack(): tsk bad tsk %p\n",tsk); - - /* check if stored ksp is bad */ - if ( (tsk->thread.ksp > stack_top) || (tsk->thread.ksp < tsk_top) ) - { - printk("stack out of bounds: %s/%d\n" - " tsk_top %08lx ksp %08lx stack_top %08lx\n", - tsk->comm,tsk->pid, - tsk_top, tsk->thread.ksp, stack_top); - ret |= 2; - } - - /* check if stack ptr RIGHT NOW is bad */ - if ( (tsk == current) && ((_get_SP() > stack_top ) || (_get_SP() < tsk_top)) ) - { - printk("current stack ptr out of bounds: %s/%d\n" - " tsk_top %08lx sp %08lx stack_top %08lx\n", - current->comm,current->pid, - tsk_top, _get_SP(), stack_top); - ret |= 4; - } - -#if 0 - /* check amount of free stack */ - for ( i = (unsigned long *)task_top(tsk) ; i < kernel_stack_top(tsk) ; i++ ) - { - if ( !i ) - printk("check_stack(): i = %p\n", i); - if ( *i != 0 ) - { - /* only notify if it's less than 900 bytes */ - if ( (i - (unsigned long *)task_top(tsk)) < 900 ) - printk("%d bytes free on stack\n", - i - task_top(tsk)); - break; - } - } -#endif - - if (ret) - { - panic("bad kernel stack"); - } - return(ret); -} -#endif /* defined(CHECK_STACK) */ - -/* - * Make sure the floating-point register state in the - * the thread_struct is up to date for task tsk. - */ -void flush_fp_to_thread(struct task_struct *tsk) -{ - if (tsk->thread.regs) { - /* - * We need to disable preemption here because if we didn't, - * another process could get scheduled after the regs->msr - * test but before we have finished saving the FP registers - * to the thread_struct. That process could take over the - * FPU, and then when we get scheduled again we would store - * bogus values for the remaining FP registers. - */ - preempt_disable(); - if (tsk->thread.regs->msr & MSR_FP) { -#ifdef CONFIG_SMP - /* - * This should only ever be called for current or - * for a stopped child process. Since we save away - * the FP register state on context switch on SMP, - * there is something wrong if a stopped child appears - * to still have its FP state in the CPU registers. - */ - BUG_ON(tsk != current); -#endif - giveup_fpu(current); - } - preempt_enable(); - } -} - -void enable_kernel_fp(void) -{ - WARN_ON(preemptible()); - -#ifdef CONFIG_SMP - if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) - giveup_fpu(current); - else - giveup_fpu(NULL); /* just enables FP for kernel */ -#else - giveup_fpu(last_task_used_math); -#endif /* CONFIG_SMP */ -} -EXPORT_SYMBOL(enable_kernel_fp); - -int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) -{ - preempt_disable(); - if (tsk->thread.regs && (tsk->thread.regs->msr & MSR_FP)) - giveup_fpu(tsk); - preempt_enable(); - memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs)); - return 1; -} - -#ifdef CONFIG_ALTIVEC -void enable_kernel_altivec(void) -{ - WARN_ON(preemptible()); - -#ifdef CONFIG_SMP - if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) - giveup_altivec(current); - else - giveup_altivec(NULL); /* just enable AltiVec for kernel - force */ -#else - giveup_altivec(last_task_used_altivec); -#endif /* __SMP __ */ -} -EXPORT_SYMBOL(enable_kernel_altivec); - -/* - * Make sure the VMX/Altivec register state in the - * the thread_struct is up to date for task tsk. - */ -void flush_altivec_to_thread(struct task_struct *tsk) -{ - if (tsk->thread.regs) { - preempt_disable(); - if (tsk->thread.regs->msr & MSR_VEC) { -#ifdef CONFIG_SMP - BUG_ON(tsk != current); -#endif - giveup_altivec(current); - } - preempt_enable(); - } -} - -int dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) -{ - if (regs->msr & MSR_VEC) - giveup_altivec(current); - memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs)); - return 1; -} -#endif /* CONFIG_ALTIVEC */ - -#ifdef CONFIG_SPE -void -enable_kernel_spe(void) -{ - WARN_ON(preemptible()); - -#ifdef CONFIG_SMP - if (current->thread.regs && (current->thread.regs->msr & MSR_SPE)) - giveup_spe(current); - else - giveup_spe(NULL); /* just enable SPE for kernel - force */ -#else - giveup_spe(last_task_used_spe); -#endif /* __SMP __ */ -} -EXPORT_SYMBOL(enable_kernel_spe); - -void flush_spe_to_thread(struct task_struct *tsk) -{ - if (tsk->thread.regs) { - preempt_disable(); - if (tsk->thread.regs->msr & MSR_SPE) { -#ifdef CONFIG_SMP - BUG_ON(tsk != current); -#endif - giveup_spe(current); - } - preempt_enable(); - } -} - -int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) -{ - if (regs->msr & MSR_SPE) - giveup_spe(current); - /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */ - memcpy(evrregs, ¤t->thread.evr[0], sizeof(u32) * 35); - return 1; -} -#endif /* CONFIG_SPE */ - -struct task_struct *__switch_to(struct task_struct *prev, - struct task_struct *new) -{ - struct thread_struct *new_thread, *old_thread; - unsigned long s; - struct task_struct *last; - - local_irq_save(s); -#ifdef CHECK_STACK - check_stack(prev); - check_stack(new); -#endif - -#ifdef CONFIG_SMP - /* avoid complexity of lazy save/restore of fpu - * by just saving it every time we switch out if - * this task used the fpu during the last quantum. - * - * If it tries to use the fpu again, it'll trap and - * reload its fp regs. So we don't have to do a restore - * every switch, just a save. - * -- Cort - */ - if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP)) - giveup_fpu(prev); -#ifdef CONFIG_ALTIVEC - /* - * If the previous thread used altivec in the last quantum - * (thus changing altivec regs) then save them. - * We used to check the VRSAVE register but not all apps - * set it, so we don't rely on it now (and in fact we need - * to save & restore VSCR even if VRSAVE == 0). -- paulus - * - * On SMP we always save/restore altivec regs just to avoid the - * complexity of changing processors. - * -- Cort - */ - if ((prev->thread.regs && (prev->thread.regs->msr & MSR_VEC))) - giveup_altivec(prev); -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - /* - * If the previous thread used spe in the last quantum - * (thus changing spe regs) then save them. - * - * On SMP we always save/restore spe regs just to avoid the - * complexity of changing processors. - */ - if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE))) - giveup_spe(prev); -#endif /* CONFIG_SPE */ -#endif /* CONFIG_SMP */ - -#ifdef CONFIG_ALTIVEC - /* Avoid the trap. On smp this this never happens since - * we don't set last_task_used_altivec -- Cort - */ - if (new->thread.regs && last_task_used_altivec == new) - new->thread.regs->msr |= MSR_VEC; -#endif -#ifdef CONFIG_SPE - /* Avoid the trap. On smp this this never happens since - * we don't set last_task_used_spe - */ - if (new->thread.regs && last_task_used_spe == new) - new->thread.regs->msr |= MSR_SPE; -#endif /* CONFIG_SPE */ - new_thread = &new->thread; - old_thread = ¤t->thread; - last = _switch(old_thread, new_thread); - local_irq_restore(s); - return last; -} - -void show_regs(struct pt_regs * regs) -{ - int i, trap; - - printk("NIP: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx %s\n", - regs->nip, regs->link, regs->gpr[1], regs, regs->trap, - print_tainted()); - printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", - regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, - regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0, - regs->msr&MSR_IR ? 1 : 0, - regs->msr&MSR_DR ? 1 : 0); - trap = TRAP(regs); - if (trap == 0x300 || trap == 0x600) - printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr); - printk("TASK = %p[%d] '%s' THREAD: %p\n", - current, current->pid, current->comm, current->thread_info); - printk("Last syscall: %ld ", current->thread.last_syscall); - -#ifdef CONFIG_SMP - printk(" CPU: %d", smp_processor_id()); -#endif /* CONFIG_SMP */ - - for (i = 0; i < 32; i++) { - long r; - if ((i % 8) == 0) - printk("\n" KERN_INFO "GPR%02d: ", i); - if (__get_user(r, ®s->gpr[i])) - break; - printk("%08lX ", r); - if (i == 12 && !FULL_REGS(regs)) - break; - } - printk("\n"); -#ifdef CONFIG_KALLSYMS - /* - * Lookup NIP late so we have the best change of getting the - * above info out without failing - */ - printk("NIP [%08lx] ", regs->nip); - print_symbol("%s\n", regs->nip); - printk("LR [%08lx] ", regs->link); - print_symbol("%s\n", regs->link); -#endif - show_stack(current, (unsigned long *) regs->gpr[1]); -} - -void exit_thread(void) -{ - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif - preempt_enable(); -} - -void flush_thread(void) -{ - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif - preempt_enable(); -} - -void -release_thread(struct task_struct *t) -{ -} - -/* - * This gets called before we allocate a new thread and copy - * the current task into it. - */ -void prepare_to_copy(struct task_struct *tsk) -{ - struct pt_regs *regs = tsk->thread.regs; - - if (regs == NULL) - return; - preempt_disable(); - if (regs->msr & MSR_FP) - giveup_fpu(current); -#ifdef CONFIG_ALTIVEC - if (regs->msr & MSR_VEC) - giveup_altivec(current); -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - if (regs->msr & MSR_SPE) - giveup_spe(current); -#endif /* CONFIG_SPE */ - preempt_enable(); -} - -/* - * Copy a thread.. - */ -int -copy_thread(int nr, unsigned long clone_flags, unsigned long usp, - unsigned long unused, - struct task_struct *p, struct pt_regs *regs) -{ - struct pt_regs *childregs, *kregs; - extern void ret_from_fork(void); - unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE; - unsigned long childframe; - - CHECK_FULL_REGS(regs); - /* Copy registers */ - sp -= sizeof(struct pt_regs); - childregs = (struct pt_regs *) sp; - *childregs = *regs; - if ((childregs->msr & MSR_PR) == 0) { - /* for kernel thread, set `current' and stackptr in new task */ - childregs->gpr[1] = sp + sizeof(struct pt_regs); - childregs->gpr[2] = (unsigned long) p; - p->thread.regs = NULL; /* no user register state */ - } else { - childregs->gpr[1] = usp; - p->thread.regs = childregs; - if (clone_flags & CLONE_SETTLS) - childregs->gpr[2] = childregs->gpr[6]; - } - childregs->gpr[3] = 0; /* Result from fork() */ - sp -= STACK_FRAME_OVERHEAD; - childframe = sp; - - /* - * The way this works is that at some point in the future - * some task will call _switch to switch to the new task. - * That will pop off the stack frame created below and start - * the new task running at ret_from_fork. The new task will - * do some house keeping and then return from the fork or clone - * system call, using the stack frame created above. - */ - sp -= sizeof(struct pt_regs); - kregs = (struct pt_regs *) sp; - sp -= STACK_FRAME_OVERHEAD; - p->thread.ksp = sp; - kregs->nip = (unsigned long)ret_from_fork; - - p->thread.last_syscall = -1; - - return 0; -} - -/* - * Set up a thread for executing a new program - */ -void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp) -{ - set_fs(USER_DS); - memset(regs->gpr, 0, sizeof(regs->gpr)); - regs->ctr = 0; - regs->link = 0; - regs->xer = 0; - regs->ccr = 0; - regs->mq = 0; - regs->nip = nip; - regs->gpr[1] = sp; - regs->msr = MSR_USER; - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif - preempt_enable(); - memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); - current->thread.fpscr.val = 0; -#ifdef CONFIG_ALTIVEC - memset(current->thread.vr, 0, sizeof(current->thread.vr)); - memset(¤t->thread.vscr, 0, sizeof(current->thread.vscr)); - current->thread.vrsave = 0; - current->thread.used_vr = 0; -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - memset(current->thread.evr, 0, sizeof(current->thread.evr)); - current->thread.acc = 0; - current->thread.spefscr = 0; - current->thread.used_spe = 0; -#endif /* CONFIG_SPE */ -} - -#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \ - | PR_FP_EXC_RES | PR_FP_EXC_INV) - -int set_fpexc_mode(struct task_struct *tsk, unsigned int val) -{ - struct pt_regs *regs = tsk->thread.regs; - - /* This is a bit hairy. If we are an SPE enabled processor - * (have embedded fp) we store the IEEE exception enable flags in - * fpexc_mode. fpexc_mode is also used for setting FP exception - * mode (asyn, precise, disabled) for 'Classic' FP. */ - if (val & PR_FP_EXC_SW_ENABLE) { -#ifdef CONFIG_SPE - tsk->thread.fpexc_mode = val & - (PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT); -#else - return -EINVAL; -#endif - } else { - /* on a CONFIG_SPE this does not hurt us. The bits that - * __pack_fe01 use do not overlap with bits used for - * PR_FP_EXC_SW_ENABLE. Additionally, the MSR[FE0,FE1] bits - * on CONFIG_SPE implementations are reserved so writing to - * them does not change anything */ - if (val > PR_FP_EXC_PRECISE) - return -EINVAL; - tsk->thread.fpexc_mode = __pack_fe01(val); - if (regs != NULL && (regs->msr & MSR_FP) != 0) - regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1)) - | tsk->thread.fpexc_mode; - } - return 0; -} - -int get_fpexc_mode(struct task_struct *tsk, unsigned long adr) -{ - unsigned int val; - - if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) -#ifdef CONFIG_SPE - val = tsk->thread.fpexc_mode; -#else - return -EINVAL; -#endif - else - val = __unpack_fe01(tsk->thread.fpexc_mode); - return put_user(val, (unsigned int __user *) adr); -} - -int sys_clone(unsigned long clone_flags, unsigned long usp, - int __user *parent_tidp, void __user *child_threadptr, - int __user *child_tidp, int p6, - struct pt_regs *regs) -{ - CHECK_FULL_REGS(regs); - if (usp == 0) - usp = regs->gpr[1]; /* stack pointer for child */ - return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); -} - -int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, - unsigned long p4, unsigned long p5, unsigned long p6, - struct pt_regs *regs) -{ - CHECK_FULL_REGS(regs); - return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); -} - -int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, - unsigned long p4, unsigned long p5, unsigned long p6, - struct pt_regs *regs) -{ - CHECK_FULL_REGS(regs); - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], - regs, 0, NULL, NULL); -} - -int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, - unsigned long a3, unsigned long a4, unsigned long a5, - struct pt_regs *regs) -{ - int error; - char * filename; - - filename = getname((char __user *) a0); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - preempt_disable(); - if (regs->msr & MSR_FP) - giveup_fpu(current); -#ifdef CONFIG_ALTIVEC - if (regs->msr & MSR_VEC) - giveup_altivec(current); -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - if (regs->msr & MSR_SPE) - giveup_spe(current); -#endif /* CONFIG_SPE */ - preempt_enable(); - error = do_execve(filename, (char __user *__user *) a1, - (char __user *__user *) a2, regs); - if (error == 0) { - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - } - putname(filename); -out: - return error; -} - -void dump_stack(void) -{ - show_stack(current, NULL); -} - -EXPORT_SYMBOL(dump_stack); - -void show_stack(struct task_struct *tsk, unsigned long *stack) -{ - unsigned long sp, stack_top, prev_sp, ret; - int count = 0; - unsigned long next_exc = 0; - struct pt_regs *regs; - extern char ret_from_except, ret_from_except_full, ret_from_syscall; - - sp = (unsigned long) stack; - if (tsk == NULL) - tsk = current; - if (sp == 0) { - if (tsk == current) - asm("mr %0,1" : "=r" (sp)); - else - sp = tsk->thread.ksp; - } - - prev_sp = (unsigned long) (tsk->thread_info + 1); - stack_top = (unsigned long) tsk->thread_info + THREAD_SIZE; - while (count < 16 && sp > prev_sp && sp < stack_top && (sp & 3) == 0) { - if (count == 0) { - printk("Call trace:"); -#ifdef CONFIG_KALLSYMS - printk("\n"); -#endif - } else { - if (next_exc) { - ret = next_exc; - next_exc = 0; - } else - ret = *(unsigned long *)(sp + 4); - printk(" [%08lx] ", ret); -#ifdef CONFIG_KALLSYMS - print_symbol("%s", ret); - printk("\n"); -#endif - if (ret == (unsigned long) &ret_from_except - || ret == (unsigned long) &ret_from_except_full - || ret == (unsigned long) &ret_from_syscall) { - /* sp + 16 points to an exception frame */ - regs = (struct pt_regs *) (sp + 16); - if (sp + 16 + sizeof(*regs) <= stack_top) - next_exc = regs->nip; - } - } - ++count; - sp = *(unsigned long *)sp; - } -#ifndef CONFIG_KALLSYMS - if (count > 0) - printk("\n"); -#endif -} - -#if 0 -/* - * Low level print for debugging - Cort - */ -int __init ll_printk(const char *fmt, ...) -{ - va_list args; - char buf[256]; - int i; - - va_start(args, fmt); - i=vsprintf(buf,fmt,args); - ll_puts(buf); - va_end(args); - return i; -} - -int lines = 24, cols = 80; -int orig_x = 0, orig_y = 0; - -void puthex(unsigned long val) -{ - unsigned char buf[10]; - int i; - for (i = 7; i >= 0; i--) - { - buf[i] = "0123456789ABCDEF"[val & 0x0F]; - val >>= 4; - } - buf[8] = '\0'; - prom_print(buf); -} - -void __init ll_puts(const char *s) -{ - int x,y; - char *vidmem = (char *)/*(_ISA_MEM_BASE + 0xB8000) */0xD00B8000; - char c; - extern int mem_init_done; - - if ( mem_init_done ) /* assume this means we can printk */ - { - printk(s); - return; - } - -#if 0 - if ( have_of ) - { - prom_print(s); - return; - } -#endif - - /* - * can't ll_puts on chrp without openfirmware yet. - * vidmem just needs to be setup for it. - * -- Cort - */ - if ( _machine != _MACH_prep ) - return; - x = orig_x; - y = orig_y; - - while ( ( c = *s++ ) != '\0' ) { - if ( c == '\n' ) { - x = 0; - if ( ++y >= lines ) { - /*scroll();*/ - /*y--;*/ - y = 0; - } - } else { - vidmem [ ( x + cols * y ) * 2 ] = c; - if ( ++x >= cols ) { - x = 0; - if ( ++y >= lines ) { - /*scroll();*/ - /*y--;*/ - y = 0; - } - } - } - } - - orig_x = x; - orig_y = y; -} -#endif - -unsigned long get_wchan(struct task_struct *p) -{ - unsigned long ip, sp; - unsigned long stack_page = (unsigned long) p->thread_info; - int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - sp = p->thread.ksp; - do { - sp = *(unsigned long *)sp; - if (sp < stack_page || sp >= stack_page + 8188) - return 0; - if (count > 0) { - ip = *(unsigned long *)(sp + 4); - if (!in_sched_functions(ip)) - return ip; - } - } while (count++ < 16); - return 0; -} diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index becbfa39755..e55cdda6149 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -318,7 +318,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) p = fork_idle(cpu); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - p->thread_info->cpu = cpu; + task_thread_info(p)->cpu = cpu; idle_tasks[cpu] = p; } } @@ -369,7 +369,7 @@ int __cpu_up(unsigned int cpu) char buf[32]; int c; - secondary_ti = idle_tasks[cpu]->thread_info; + secondary_ti = task_thread_info(idle_tasks[cpu]); mb(); /* diff --git a/arch/ppc/platforms/apus_setup.c b/arch/ppc/platforms/apus_setup.c index 2f74fde98eb..c42c50073da 100644 --- a/arch/ppc/platforms/apus_setup.c +++ b/arch/ppc/platforms/apus_setup.c @@ -55,9 +55,6 @@ int (*mach_hwclk) (int, struct hwclk_time*) = NULL; int (*mach_set_clock_mmss) (unsigned long) = NULL; void (*mach_reset)( void ); long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ -#if defined(CONFIG_AMIGA_FLOPPY) -void (*mach_floppy_setup) (char *, int *) __initdata = NULL; -#endif #ifdef CONFIG_HEARTBEAT void (*mach_heartbeat) (int) = NULL; extern void apus_heartbeat (void); @@ -76,7 +73,6 @@ struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */ struct mem_info ramdisk; -extern void amiga_floppy_setup(char *, int *); extern void config_amiga(void); static int __60nsram = 0; @@ -305,16 +301,6 @@ void kbd_reset_setup(char *str, int *ints) { } -/*********************************************************** FLOPPY */ -#if defined(CONFIG_AMIGA_FLOPPY) -__init -void floppy_setup(char *str, int *ints) -{ - if (mach_floppy_setup) - mach_floppy_setup (str, ints); -} -#endif - /*********************************************************** MEMORY */ #define KMAP_MAX 32 unsigned long kmap_chunks[KMAP_MAX*3]; @@ -574,9 +560,9 @@ static __inline__ void ser_RTSon(void) int __debug_ser_out( unsigned char c ) { - custom.serdat = c | 0x100; + amiga_custom.serdat = c | 0x100; mb(); - while (!(custom.serdatr & 0x2000)) + while (!(amiga_custom.serdatr & 0x2000)) barrier(); return 1; } @@ -586,11 +572,11 @@ unsigned char __debug_ser_in( void ) unsigned char c; /* XXX: is that ok?? derived from amiga_ser.c... */ - while( !(custom.intreqr & IF_RBF) ) + while( !(amiga_custom.intreqr & IF_RBF) ) barrier(); - c = custom.serdatr; + c = amiga_custom.serdatr; /* clear the interrupt, so that another character can be read */ - custom.intreq = IF_RBF; + amiga_custom.intreq = IF_RBF; return c; } @@ -601,10 +587,10 @@ int __debug_serinit( void ) local_irq_save(flags); /* turn off Rx and Tx interrupts */ - custom.intena = IF_RBF | IF_TBE; + amiga_custom.intena = IF_RBF | IF_TBE; /* clear any pending interrupt */ - custom.intreq = IF_RBF | IF_TBE; + amiga_custom.intreq = IF_RBF | IF_TBE; local_irq_restore(flags); @@ -617,7 +603,7 @@ int __debug_serinit( void ) #ifdef CONFIG_KGDB /* turn Rx interrupts on for GDB */ - custom.intena = IF_SETCLR | IF_RBF; + amiga_custom.intena = IF_SETCLR | IF_RBF; ser_RTSon(); #endif diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index 2b483b4f160..9075a7538e2 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c @@ -99,7 +99,7 @@ static void remove_bpts(void); static void insert_bpts(void); static struct bpt *at_breakpoint(unsigned pc); static void bpt_cmds(void); -static void cacheflush(void); +void cacheflush(void); #ifdef CONFIG_SMP static void cpu_cmd(void); #endif /* CONFIG_SMP */ diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c index 03ba5893f17..1f451c2cb07 100644 --- a/arch/s390/kernel/binfmt_elf32.c +++ b/arch/s390/kernel/binfmt_elf32.c @@ -112,7 +112,7 @@ static inline int dump_regs32(struct pt_regs *ptregs, elf_gregset_t *regs) static inline int dump_task_regs32(struct task_struct *tsk, elf_gregset_t *regs) { - struct pt_regs *ptregs = __KSTK_PTREGS(tsk); + struct pt_regs *ptregs = task_pt_regs(tsk); int i; memcpy(®s->psw.mask, &ptregs->psw.mask, 4); diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 7dd58f8ac6b..2ff90a1a105 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -153,7 +153,7 @@ void show_regs(struct pt_regs *regs) { struct task_struct *tsk = current; - printk("CPU: %d %s\n", tsk->thread_info->cpu, print_tainted()); + printk("CPU: %d %s\n", task_thread_info(tsk)->cpu, print_tainted()); printk("Process %s (pid: %d, task: %p, ksp: %p)\n", current->comm, current->pid, (void *) tsk, (void *) tsk->thread.ksp); @@ -217,8 +217,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, struct pt_regs childregs; } *frame; - frame = ((struct fake_frame *) - (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; + frame = container_of(task_pt_regs(p), struct fake_frame, childregs); p->thread.ksp = (unsigned long) frame; /* Store access registers to kernel stack of new process. */ frame->childregs = *regs; @@ -358,11 +357,10 @@ unsigned long get_wchan(struct task_struct *p) unsigned long return_address; int count; - if (!p || p == current || p->state == TASK_RUNNING || !p->thread_info) + if (!p || p == current || p->state == TASK_RUNNING || !task_stack_page(p)) return 0; - low = (struct stack_frame *) p->thread_info; - high = (struct stack_frame *) - ((unsigned long) p->thread_info + THREAD_SIZE) - 1; + low = task_stack_page(p); + high = (struct stack_frame *) task_pt_regs(p); sf = (struct stack_frame *) (p->thread.ksp & PSW_ADDR_INSN); if (sf <= low || sf > high) return 0; diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index cc02232aa96..37dfe33dab7 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -52,7 +52,7 @@ FixPerRegisters(struct task_struct *task) struct pt_regs *regs; per_struct *per_info; - regs = __KSTK_PTREGS(task); + regs = task_pt_regs(task); per_info = (per_struct *) &task->thread.per_info; per_info->control_regs.bits.em_instruction_fetch = per_info->single_step | per_info->instruction_fetch; @@ -150,7 +150,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data) /* * psw and gprs are stored on the stack */ - tmp = *(addr_t *)((addr_t) &__KSTK_PTREGS(child)->psw + addr); + tmp = *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr); if (addr == (addr_t) &dummy->regs.psw.mask) /* Remove per bit from user psw. */ tmp &= ~PSW_MASK_PER; @@ -176,7 +176,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data) /* * orig_gpr2 is stored on the kernel stack */ - tmp = (addr_t) __KSTK_PTREGS(child)->orig_gpr2; + tmp = (addr_t) task_pt_regs(child)->orig_gpr2; } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { /* @@ -243,7 +243,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) high order bit but older gdb's rely on it */ data |= PSW_ADDR_AMODE; #endif - *(addr_t *)((addr_t) &__KSTK_PTREGS(child)->psw + addr) = data; + *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data; } else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) { /* @@ -267,7 +267,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) /* * orig_gpr2 is stored on the kernel stack */ - __KSTK_PTREGS(child)->orig_gpr2 = data; + task_pt_regs(child)->orig_gpr2 = data; } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { /* @@ -393,15 +393,15 @@ peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data) */ if (addr == (addr_t) &dummy32->regs.psw.mask) { /* Fake a 31 bit psw mask. */ - tmp = (__u32)(__KSTK_PTREGS(child)->psw.mask >> 32); + tmp = (__u32)(task_pt_regs(child)->psw.mask >> 32); tmp = PSW32_MASK_MERGE(PSW32_USER_BITS, tmp); } else if (addr == (addr_t) &dummy32->regs.psw.addr) { /* Fake a 31 bit psw address. */ - tmp = (__u32) __KSTK_PTREGS(child)->psw.addr | + tmp = (__u32) task_pt_regs(child)->psw.addr | PSW32_ADDR_AMODE31; } else { /* gpr 0-15 */ - tmp = *(__u32 *)((addr_t) &__KSTK_PTREGS(child)->psw + + tmp = *(__u32 *)((addr_t) &task_pt_regs(child)->psw + addr*2 + 4); } } else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) { @@ -415,7 +415,7 @@ peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data) /* * orig_gpr2 is stored on the kernel stack */ - tmp = *(__u32*)((addr_t) &__KSTK_PTREGS(child)->orig_gpr2 + 4); + tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4); } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { /* @@ -472,15 +472,15 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data) if (tmp != PSW32_MASK_MERGE(PSW32_USER_BITS, tmp)) /* Invalid psw mask. */ return -EINVAL; - __KSTK_PTREGS(child)->psw.mask = + task_pt_regs(child)->psw.mask = PSW_MASK_MERGE(PSW_USER32_BITS, (__u64) tmp << 32); } else if (addr == (addr_t) &dummy32->regs.psw.addr) { /* Build a 64 bit psw address from 31 bit address. */ - __KSTK_PTREGS(child)->psw.addr = + task_pt_regs(child)->psw.addr = (__u64) tmp & PSW32_ADDR_INSN; } else { /* gpr 0-15 */ - *(__u32*)((addr_t) &__KSTK_PTREGS(child)->psw + *(__u32*)((addr_t) &task_pt_regs(child)->psw + addr*2 + 4) = tmp; } } else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) { @@ -494,7 +494,7 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data) /* * orig_gpr2 is stored on the kernel stack */ - *(__u32*)((addr_t) &__KSTK_PTREGS(child)->orig_gpr2 + 4) = tmp; + *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp; } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { /* diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index e10f4ca0049..cbfcfd02a43 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -657,7 +657,7 @@ __cpu_up(unsigned int cpu) idle = current_set[cpu]; cpu_lowcore = lowcore_ptr[cpu]; cpu_lowcore->kernel_stack = (unsigned long) - idle->thread_info + (THREAD_SIZE); + task_stack_page(idle) + (THREAD_SIZE); sf = (struct stack_frame *) (cpu_lowcore->kernel_stack - sizeof(struct pt_regs) - sizeof(struct stack_frame)); diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index c36353e8c14..b0d8ca8e5ee 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -282,7 +282,7 @@ static inline void start_hz_timer(void) { if (!cpu_isset(smp_processor_id(), nohz_cpu_mask)) return; - account_ticks(__KSTK_PTREGS(current)); + account_ticks(task_pt_regs(current)); cpu_clear(smp_processor_id(), nohz_cpu_mask); } diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 95d10996861..5d21e9e6e7b 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -136,8 +136,8 @@ void show_trace(struct task_struct *task, unsigned long * stack) sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE, S390_lowcore.async_stack); if (task) - __show_trace(sp, (unsigned long) task->thread_info, - (unsigned long) task->thread_info + THREAD_SIZE); + __show_trace(sp, (unsigned long) task_stack_page(task), + (unsigned long) task_stack_page(task) + THREAD_SIZE); else __show_trace(sp, S390_lowcore.thread_info, S390_lowcore.thread_info + THREAD_SIZE); @@ -240,7 +240,7 @@ char *task_show_regs(struct task_struct *task, char *buffer) { struct pt_regs *regs; - regs = __KSTK_PTREGS(task); + regs = task_pt_regs(task); buffer += sprintf(buffer, "task: %p, ksp: %p\n", task, (void *)task->thread.ksp); buffer += sprintf(buffer, "User PSW : %p %p\n", diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 8a2bea34ddd..aac15e42d03 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -191,13 +191,8 @@ void flush_thread(void) { #if defined(CONFIG_SH_FPU) struct task_struct *tsk = current; - struct pt_regs *regs = (struct pt_regs *) - ((unsigned long)tsk->thread_info - + THREAD_SIZE - sizeof(struct pt_regs) - - sizeof(unsigned long)); - /* Forget lazy FPU state */ - clear_fpu(tsk, regs); + clear_fpu(tsk, task_pt_regs(tsk)); clear_used_math(); #endif } @@ -232,13 +227,7 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) { struct pt_regs ptregs; - ptregs = *(struct pt_regs *) - ((unsigned long)tsk->thread_info + THREAD_SIZE - - sizeof(struct pt_regs) -#ifdef CONFIG_SH_DSP - - sizeof(struct pt_dspregs) -#endif - - sizeof(unsigned long)); + ptregs = *task_pt_regs(tsk); elf_core_copy_regs(regs, &ptregs); return 1; @@ -252,11 +241,7 @@ dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu) #if defined(CONFIG_SH_FPU) fpvalid = !!tsk_used_math(tsk); if (fpvalid) { - struct pt_regs *regs = (struct pt_regs *) - ((unsigned long)tsk->thread_info - + THREAD_SIZE - sizeof(struct pt_regs) - - sizeof(unsigned long)); - unlazy_fpu(tsk, regs); + unlazy_fpu(tsk, task_pt_regs(tsk)); memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); } #endif @@ -279,18 +264,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, copy_to_stopped_child_used_math(p); #endif - childregs = ((struct pt_regs *) - (THREAD_SIZE + (unsigned long) p->thread_info) -#ifdef CONFIG_SH_DSP - - sizeof(struct pt_dspregs) -#endif - - sizeof(unsigned long)) - 1; + childregs = task_pt_regs(p); *childregs = *regs; if (user_mode(regs)) { childregs->regs[15] = usp; } else { - childregs->regs[15] = (unsigned long)p->thread_info + THREAD_SIZE; + childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE; } if (clone_flags & CLONE_SETTLS) { childregs->gbr = childregs->regs[0]; @@ -333,11 +313,7 @@ ubc_set_tracing(int asid, unsigned long pc) struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next) { #if defined(CONFIG_SH_FPU) - struct pt_regs *regs = (struct pt_regs *) - ((unsigned long)prev->thread_info - + THREAD_SIZE - sizeof(struct pt_regs) - - sizeof(unsigned long)); - unlazy_fpu(prev, regs); + unlazy_fpu(prev, task_pt_regs(prev)); #endif #ifdef CONFIG_PREEMPT @@ -346,13 +322,7 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne struct pt_regs *regs; local_irq_save(flags); - regs = (struct pt_regs *) - ((unsigned long)prev->thread_info - + THREAD_SIZE - sizeof(struct pt_regs) -#ifdef CONFIG_SH_DSP - - sizeof(struct pt_dspregs) -#endif - - sizeof(unsigned long)); + regs = task_pt_regs(prev); if (user_mode(regs) && regs->regs[15] >= 0xc0000000) { int offset = (int)regs->regs[15]; @@ -372,7 +342,7 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne */ asm volatile("ldc %0, r7_bank" : /* no output */ - : "r" (next->thread_info)); + : "r" (task_thread_info(next))); #ifdef CONFIG_MMU /* If no tasks are using the UBC, we're done */ diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index 1a8be06519e..3887b4f6feb 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -41,12 +41,7 @@ static inline int get_stack_long(struct task_struct *task, int offset) { unsigned char *stack; - stack = (unsigned char *) - task->thread_info + THREAD_SIZE - sizeof(struct pt_regs) -#ifdef CONFIG_SH_DSP - - sizeof(struct pt_dspregs) -#endif - - sizeof(unsigned long); + stack = (unsigned char *)task_pt_regs(task); stack += offset; return (*((int *)stack)); } @@ -59,12 +54,7 @@ static inline int put_stack_long(struct task_struct *task, int offset, { unsigned char *stack; - stack = (unsigned char *) - task->thread_info + THREAD_SIZE - sizeof(struct pt_regs) -#ifdef CONFIG_SH_DSP - - sizeof(struct pt_dspregs) -#endif - - sizeof(unsigned long); + stack = (unsigned char *)task_pt_regs(task); stack += offset; *(unsigned long *) stack = data; return 0; diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 59e49b18252..62c7d1c0ad7 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -103,7 +103,7 @@ int __cpu_up(unsigned int cpu) if (IS_ERR(tsk)) panic("Failed forking idle task for cpu %d\n", cpu); - tsk->thread_info->cpu = cpu; + task_thread_info(tsk)->cpu = cpu; cpu_set(cpu, cpu_online_map); diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c index 419b5a71044..1da9c61d682 100644 --- a/arch/sh64/kernel/process.c +++ b/arch/sh64/kernel/process.c @@ -744,7 +744,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, } #endif /* Copy from sh version */ - childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p->thread_info )) - 1; + childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1; *childregs = *regs; @@ -752,7 +752,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, childregs->regs[15] = usp; p->thread.uregs = childregs; } else { - childregs->regs[15] = (unsigned long)p->thread_info + THREAD_SIZE; + childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE; } childregs->regs[9] = 0; /* Set return value for child */ diff --git a/arch/sh64/lib/dbg.c b/arch/sh64/lib/dbg.c index 526fedae6db..58087331b8a 100644 --- a/arch/sh64/lib/dbg.c +++ b/arch/sh64/lib/dbg.c @@ -174,7 +174,7 @@ void evt_debug(int evt, int ret_addr, int event, int tra, struct pt_regs *regs) struct ring_node *rr; pid = current->pid; - stack_bottom = (unsigned long) current->thread_info; + stack_bottom = (unsigned long) task_stack_page(current); asm volatile("ori r15, 0, %0" : "=r" (sp)); rr = event_ring + event_ptr; rr->evt = evt; diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index ea864741146..fbb05a452e5 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -302,7 +302,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) int count = 0; if (tsk != NULL) - task_base = (unsigned long) tsk->thread_info; + task_base = (unsigned long) task_stack_page(tsk); else task_base = (unsigned long) current_thread_info(); @@ -337,7 +337,7 @@ EXPORT_SYMBOL(dump_stack); */ unsigned long thread_saved_pc(struct task_struct *tsk) { - return tsk->thread_info->kpc; + return task_thread_info(tsk)->kpc; } /* @@ -392,7 +392,7 @@ void flush_thread(void) /* We must fixup kregs as well. */ /* XXX This was not fixed for ti for a while, worked. Unused? */ current->thread.kregs = (struct pt_regs *) - ((char *)current->thread_info + (THREAD_SIZE - TRACEREG_SZ)); + (task_stack_page(current) + (THREAD_SIZE - TRACEREG_SZ)); } } @@ -459,7 +459,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long unused, struct task_struct *p, struct pt_regs *regs) { - struct thread_info *ti = p->thread_info; + struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs; char *new_stack; @@ -482,7 +482,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, * V V (stk.fr.) V (pt_regs) { (stk.fr.) } * +----- - - - - - ------+===========+============={+==========}+ */ - new_stack = (char*)ti + THREAD_SIZE; + new_stack = task_stack_page(p) + THREAD_SIZE; if (regs->psr & PSR_PS) new_stack -= STACKFRAME_SZ; new_stack -= STACKFRAME_SZ + TRACEREG_SZ; @@ -724,7 +724,7 @@ unsigned long get_wchan(struct task_struct *task) task->state == TASK_RUNNING) goto out; - fp = task->thread_info->ksp + bias; + fp = task_thread_info(task)->ksp + bias; do { /* Bogus frame pointer? */ if (fp < (task_base + sizeof(struct thread_info)) || diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index fc470c0e9dc..1baf13ed5c3 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -75,7 +75,7 @@ static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset, struct task_struct *tsk, long __user *addr) { struct pt_regs *cregs = tsk->thread.kregs; - struct thread_info *t = tsk->thread_info; + struct thread_info *t = task_thread_info(tsk); int v; if(offset >= 1024) @@ -170,7 +170,7 @@ static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset, struct task_struct *tsk) { struct pt_regs *cregs = tsk->thread.kregs; - struct thread_info *t = tsk->thread_info; + struct thread_info *t = task_thread_info(tsk); unsigned long value = regs->u_regs[UREG_I3]; if(offset >= 1024) diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index cc1fc898495..40d426cce82 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -200,7 +200,7 @@ void __init smp4d_boot_cpus(void) /* Cook up an idler for this guy. */ p = fork_idle(i); cpucount++; - current_set[i] = p->thread_info; + current_set[i] = task_thread_info(p); for (no = 0; !cpu_find_by_instance(no, NULL, &mid) && mid != i; no++) ; diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index f113422a372..a21f27d10e5 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -173,7 +173,7 @@ void __init smp4m_boot_cpus(void) /* Cook up an idler for this guy. */ p = fork_idle(i); cpucount++; - current_set[i] = p->thread_info; + current_set[i] = task_thread_info(p); /* See trampoline.S for details... */ entry += ((i-1) * 3); diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c index 3f451ae6648..41d45c298fb 100644 --- a/arch/sparc/kernel/traps.c +++ b/arch/sparc/kernel/traps.c @@ -291,7 +291,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, #ifndef CONFIG_SMP if(!fpt) { #else - if(!(fpt->thread_info->flags & _TIF_USEDFPU)) { + if(!(task_thread_info(fpt)->flags & _TIF_USEDFPU)) { #endif fpsave(&fake_regs[0], &fake_fsr, &fake_queue[0], &fake_depth); regs->psr &= ~PSR_EF; @@ -334,7 +334,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, /* nope, better SIGFPE the offending process... */ #ifdef CONFIG_SMP - fpt->thread_info->flags &= ~_TIF_USEDFPU; + task_thread_info(fpt)->flags &= ~_TIF_USEDFPU; #endif if(psr & PSR_PS) { /* The first fsr store/load we tried trapped, diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 02f9dec1d45..1dc3650c5ca 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -390,7 +390,7 @@ void show_regs32(struct pt_regs32 *regs) unsigned long thread_saved_pc(struct task_struct *tsk) { - struct thread_info *ti = tsk->thread_info; + struct thread_info *ti = task_thread_info(tsk); unsigned long ret = 0xdeadbeefUL; if (ti && ti->ksp) { @@ -616,11 +616,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long unused, struct task_struct *p, struct pt_regs *regs) { - struct thread_info *t = p->thread_info; + struct thread_info *t = task_thread_info(p); char *child_trap_frame; /* Calculate offset to stack_frame & pt_regs */ - child_trap_frame = ((char *)t) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ)); + child_trap_frame = task_stack_page(p) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ)); memcpy(child_trap_frame, (((struct sparc_stackf *)regs)-1), (TRACEREG_SZ+STACKFRAME_SZ)); t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) | @@ -845,9 +845,9 @@ unsigned long get_wchan(struct task_struct *task) task->state == TASK_RUNNING) goto out; - thread_info_base = (unsigned long) task->thread_info; + thread_info_base = (unsigned long) task_stack_page(task); bias = STACK_BIAS; - fp = task->thread_info->ksp + bias; + fp = task_thread_info(task)->ksp + bias; do { /* Bogus frame pointer? */ diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 84d3df2264c..3f9746f856d 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -296,7 +296,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) case PTRACE_GETREGS: { struct pt_regs32 __user *pregs = (struct pt_regs32 __user *) addr; - struct pt_regs *cregs = child->thread_info->kregs; + struct pt_regs *cregs = task_pt_regs(child); int rval; if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) || @@ -320,11 +320,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs) case PTRACE_GETREGS64: { struct pt_regs __user *pregs = (struct pt_regs __user *) addr; - struct pt_regs *cregs = child->thread_info->kregs; + struct pt_regs *cregs = task_pt_regs(child); unsigned long tpc = cregs->tpc; int rval; - if ((child->thread_info->flags & _TIF_32BIT) != 0) + if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) tpc &= 0xffffffff; if (__put_user(cregs->tstate, (&pregs->tstate)) || __put_user(tpc, (&pregs->tpc)) || @@ -348,7 +348,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) case PTRACE_SETREGS: { struct pt_regs32 __user *pregs = (struct pt_regs32 __user *) addr; - struct pt_regs *cregs = child->thread_info->kregs; + struct pt_regs *cregs = task_pt_regs(child); unsigned int psr, pc, npc, y; int i; @@ -381,7 +381,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) case PTRACE_SETREGS64: { struct pt_regs __user *pregs = (struct pt_regs __user *) addr; - struct pt_regs *cregs = child->thread_info->kregs; + struct pt_regs *cregs = task_pt_regs(child); unsigned long tstate, tpc, tnpc, y; int i; @@ -395,7 +395,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) pt_error_return(regs, EFAULT); goto out_tsk; } - if ((child->thread_info->flags & _TIF_32BIT) != 0) { + if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) { tpc &= 0xffffffff; tnpc &= 0xffffffff; } @@ -430,11 +430,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs) } fpq[16]; }; struct fps __user *fps = (struct fps __user *) addr; - unsigned long *fpregs = child->thread_info->fpregs; + unsigned long *fpregs = task_thread_info(child)->fpregs; if (copy_to_user(&fps->regs[0], fpregs, (32 * sizeof(unsigned int))) || - __put_user(child->thread_info->xfsr[0], (&fps->fsr)) || + __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) || __put_user(0, (&fps->fpqd)) || __put_user(0, (&fps->flags)) || __put_user(0, (&fps->extra)) || @@ -452,11 +452,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs) unsigned long fsr; }; struct fps __user *fps = (struct fps __user *) addr; - unsigned long *fpregs = child->thread_info->fpregs; + unsigned long *fpregs = task_thread_info(child)->fpregs; if (copy_to_user(&fps->regs[0], fpregs, (64 * sizeof(unsigned int))) || - __put_user(child->thread_info->xfsr[0], (&fps->fsr))) { + __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { pt_error_return(regs, EFAULT); goto out_tsk; } @@ -477,7 +477,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) } fpq[16]; }; struct fps __user *fps = (struct fps __user *) addr; - unsigned long *fpregs = child->thread_info->fpregs; + unsigned long *fpregs = task_thread_info(child)->fpregs; unsigned fsr; if (copy_from_user(fpregs, &fps->regs[0], @@ -486,11 +486,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs) pt_error_return(regs, EFAULT); goto out_tsk; } - child->thread_info->xfsr[0] &= 0xffffffff00000000UL; - child->thread_info->xfsr[0] |= fsr; - if (!(child->thread_info->fpsaved[0] & FPRS_FEF)) - child->thread_info->gsr[0] = 0; - child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL); + task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL; + task_thread_info(child)->xfsr[0] |= fsr; + if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) + task_thread_info(child)->gsr[0] = 0; + task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL); pt_succ_return(regs, 0); goto out_tsk; } @@ -501,17 +501,17 @@ asmlinkage void do_ptrace(struct pt_regs *regs) unsigned long fsr; }; struct fps __user *fps = (struct fps __user *) addr; - unsigned long *fpregs = child->thread_info->fpregs; + unsigned long *fpregs = task_thread_info(child)->fpregs; if (copy_from_user(fpregs, &fps->regs[0], (64 * sizeof(unsigned int))) || - __get_user(child->thread_info->xfsr[0], (&fps->fsr))) { + __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { pt_error_return(regs, EFAULT); goto out_tsk; } - if (!(child->thread_info->fpsaved[0] & FPRS_FEF)) - child->thread_info->gsr[0] = 0; - child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU); + if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) + task_thread_info(child)->gsr[0] = 0; + task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU); pt_succ_return(regs, 0); goto out_tsk; } @@ -562,8 +562,8 @@ asmlinkage void do_ptrace(struct pt_regs *regs) #ifdef DEBUG_PTRACE printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm, child->pid, child->exit_code, - child->thread_info->kregs->tpc, - child->thread_info->kregs->tnpc); + task_pt_regs(child)->tpc, + task_pt_regs(child)->tnpc); #endif wake_up_process(child); diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 48180531562..250745896ae 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -520,7 +520,7 @@ void __init setup_arch(char **cmdline_p) rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); #endif - init_task.thread_info->kregs = &fake_swapper_regs; + task_thread_info(&init_task)->kregs = &fake_swapper_regs; #ifdef CONFIG_IP_PNP if (!ic_set_manually) { diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 6efc03df51c..1fb6323e65a 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -335,7 +335,7 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu) p = fork_idle(cpu); callin_flag = 0; - cpu_new_thread = p->thread_info; + cpu_new_thread = task_thread_info(p); cpu_set(cpu, cpu_callout_map); cpu_find_by_mid(cpu, &cpu_node); diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 5570e7bb22b..8d44ae5a15e 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -1808,7 +1808,7 @@ static void user_instruction_dump (unsigned int __user *pc) void show_stack(struct task_struct *tsk, unsigned long *_ksp) { unsigned long pc, fp, thread_base, ksp; - struct thread_info *tp = tsk->thread_info; + void *tp = task_stack_page(tsk); struct reg_window *rw; int count = 0; @@ -1862,7 +1862,7 @@ static inline int is_kernel_stack(struct task_struct *task, return 0; } - thread_base = (unsigned long) task->thread_info; + thread_base = (unsigned long) task_stack_page(task); thread_end = thread_base + sizeof(union thread_union); if (rw_addr >= thread_base && rw_addr < thread_end && diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index d2d3f256778..7f13b85d265 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -107,7 +107,7 @@ void set_current(void *t) { struct task_struct *task = t; - cpu_tasks[task->thread_info->cpu] = ((struct cpu_task) + cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) { external_pid(task), task }); } diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 09790ccb161..dc41c6dc2f3 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -118,7 +118,7 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, handler = new_thread_handler; } - new_thread(p->thread_info, &p->thread.mode.skas.switch_buf, + new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, &p->thread.mode.skas.fork_buf, handler); return(0); } @@ -185,7 +185,7 @@ int start_uml_skas(void) init_task.thread.request.u.thread.proc = start_kernel_proc; init_task.thread.request.u.thread.arg = NULL; - return(start_idle_thread(init_task.thread_info, + return(start_idle_thread(task_stack_page(&init_task), &init_task.thread.mode.skas.switch_buf, &init_task.thread.mode.skas.fork_buf)); } diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c index 136e54c47d3..8f40e483873 100644 --- a/arch/um/kernel/tt/exec_kern.c +++ b/arch/um/kernel/tt/exec_kern.c @@ -39,7 +39,7 @@ void flush_thread_tt(void) do_exit(SIGKILL); } - new_pid = start_fork_tramp(current->thread_info, stack, 0, exec_tramp); + new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp); if(new_pid < 0){ printk(KERN_ERR "flush_thread : new thread failed, errno = %d\n", diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index 14d4622a5fb..62535303aa2 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -36,7 +36,7 @@ void switch_to_tt(void *prev, void *next) from = prev; to = next; - cpu = from->thread_info->cpu; + cpu = task_thread_info(from)->cpu; if(cpu == 0) forward_interrupts(to->thread.mode.tt.extern_pid); #ifdef CONFIG_SMP @@ -253,7 +253,7 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, clone_flags &= CLONE_VM; p->thread.temp_stack = stack; - new_pid = start_fork_tramp(p->thread_info, stack, clone_flags, tramp); + new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp); if(new_pid < 0){ printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", -new_pid); @@ -343,7 +343,7 @@ int do_proc_op(void *t, int proc_id) pid = thread->request.u.exec.pid; do_exec(thread->mode.tt.extern_pid, pid); thread->mode.tt.extern_pid = pid; - cpu_tasks[task->thread_info->cpu].pid = pid; + cpu_tasks[task_thread_info(task)->cpu].pid = pid; break; case OP_FORK: attach_process(thread->request.u.fork.pid); @@ -425,7 +425,7 @@ int start_uml_tt(void) int pages; pages = (1 << CONFIG_KERNEL_STACK_ORDER); - sp = (void *) ((unsigned long) init_task.thread_info) + + sp = task_stack_page(&init_task) + pages * PAGE_SIZE - sizeof(unsigned long); return(tracer(start_kernel_proc, sp)); } diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c index 062ffa0a999..eb909937958 100644 --- a/arch/v850/kernel/process.c +++ b/arch/v850/kernel/process.c @@ -114,7 +114,7 @@ int copy_thread (int nr, unsigned long clone_flags, struct task_struct *p, struct pt_regs *regs) { /* Start pushing stuff from the top of the child's kernel stack. */ - unsigned long orig_ksp = (unsigned long)p->thread_info + THREAD_SIZE; + unsigned long orig_ksp = task_tos(p); unsigned long ksp = orig_ksp; /* We push two `state save' stack fames (see entry.S) on the new kernel stack: diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c index 18492d02aaf..67e05750966 100644 --- a/arch/v850/kernel/ptrace.c +++ b/arch/v850/kernel/ptrace.c @@ -58,7 +58,7 @@ static v850_reg_t *reg_save_addr (unsigned reg_offs, struct task_struct *t) regs = thread_saved_regs (t); else /* Register saved during kernel entry (or not available). */ - regs = task_regs (t); + regs = task_pt_regs (t); return (v850_reg_t *)((char *)regs + reg_offs); } diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 2b760d0d9ce..029bddab045 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -197,8 +197,7 @@ static inline void elf_core_copy_regs(elf_gregset_t *elfregs, struct pt_regs *re static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs) { - struct pt_regs *pp = (struct pt_regs *)(t->thread.rsp0); - --pp; + struct pt_regs *pp = task_pt_regs(t); ELF_CORE_COPY_REGS((*elfregs), pp); /* fix wrong segments */ (*elfregs)[7] = t->thread.ds; @@ -217,7 +216,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr if (!tsk_used_math(tsk)) return 0; if (!regs) - regs = ((struct pt_regs *)tsk->thread.rsp0) - 1; + regs = task_pt_regs(tsk); if (tsk == current) unlazy_fpu(tsk); set_fs(KERNEL_DS); @@ -233,7 +232,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr static inline int elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu) { - struct pt_regs *regs = ((struct pt_regs *)(t->thread.rsp0))-1; + struct pt_regs *regs = task_pt_regs(t); if (!tsk_used_math(t)) return 0; if (t == current) diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c index ea4394e021d..23a4515a73b 100644 --- a/arch/x86_64/ia32/ptrace32.c +++ b/arch/x86_64/ia32/ptrace32.c @@ -41,7 +41,7 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) { int i; - __u64 *stack = (__u64 *)(child->thread.rsp0 - sizeof(struct pt_regs)); + __u64 *stack = (__u64 *)task_pt_regs(child); switch (regno) { case offsetof(struct user32, regs.fs): @@ -137,7 +137,7 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) static int getreg32(struct task_struct *child, unsigned regno, u32 *val) { - __u64 *stack = (__u64 *)(child->thread.rsp0 - sizeof(struct pt_regs)); + __u64 *stack = (__u64 *)task_pt_regs(child); switch (regno) { case offsetof(struct user32, regs.fs): @@ -238,7 +238,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) if (ret < 0) goto out; - childregs = (struct pt_regs *)(child->thread.rsp0 - sizeof(struct pt_regs)); + childregs = task_pt_regs(child); switch (request) { case PTRACE_PEEKDATA: diff --git a/arch/x86_64/kernel/i387.c b/arch/x86_64/kernel/i387.c index d9b22b633e3..a5d7e16b928 100644 --- a/arch/x86_64/kernel/i387.c +++ b/arch/x86_64/kernel/i387.c @@ -95,7 +95,7 @@ int save_i387(struct _fpstate __user *buf) if (!used_math()) return 0; clear_used_math(); /* trigger finit */ - if (tsk->thread_info->status & TS_USEDFPU) { + if (task_thread_info(tsk)->status & TS_USEDFPU) { err = save_i387_checking((struct i387_fxsave_struct __user *)buf); if (err) return err; stts(); diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c index b61965f0fb3..5ecd34ab8c2 100644 --- a/arch/x86_64/kernel/i8259.c +++ b/arch/x86_64/kernel/i8259.c @@ -133,7 +133,7 @@ static void end_8259A_irq (unsigned int irq) { if (irq > 256) { char var; - printk("return %p stack %p ti %p\n", __builtin_return_address(0), &var, current->thread_info); + printk("return %p stack %p ti %p\n", __builtin_return_address(0), &var, task_thread_info(current)); BUG(); } diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 669cf0ed326..8ded407e4a9 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -451,7 +451,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, struct task_struct *me = current; childregs = ((struct pt_regs *) - (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; + (THREAD_SIZE + task_stack_page(p))) - 1; *childregs = *regs; childregs->rax = 0; @@ -463,7 +463,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, p->thread.rsp0 = (unsigned long) (childregs+1); p->thread.userrsp = me->thread.userrsp; - set_ti_thread_flag(p->thread_info, TIF_FORK); + set_tsk_thread_flag(p, TIF_FORK); p->thread.fs = me->thread.fs; p->thread.gs = me->thread.gs; @@ -590,7 +590,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) write_pda(oldrsp, next->userrsp); write_pda(pcurrent, next_p); write_pda(kernelstack, - (unsigned long)next_p->thread_info + THREAD_SIZE - PDA_STACKOFFSET); + task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); /* * Now maybe reload the debug registers @@ -704,7 +704,7 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state==TASK_RUNNING) return 0; - stack = (unsigned long)p->thread_info; + stack = (unsigned long)task_stack_page(p); if (p->thread.rsp < stack || p->thread.rsp > stack+THREAD_SIZE) return 0; fp = *(u64 *)(p->thread.rsp); @@ -822,8 +822,7 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) { struct pt_regs *pp, ptregs; - pp = (struct pt_regs *)(tsk->thread.rsp0); - --pp; + pp = task_pt_regs(tsk); ptregs = *pp; ptregs.cs &= 0xffff; diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index 86248bc9303..53205622351 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -67,12 +67,6 @@ static inline unsigned long get_stack_long(struct task_struct *task, int offset) return (*((unsigned long *)stack)); } -static inline struct pt_regs *get_child_regs(struct task_struct *task) -{ - struct pt_regs *regs = (void *)task->thread.rsp0; - return regs - 1; -} - /* * this routine will put a word on the processes privileged stack. * the offset is how far from the base addr as stored in the TSS. @@ -170,7 +164,7 @@ static int is_at_popf(struct task_struct *child, struct pt_regs *regs) static void set_singlestep(struct task_struct *child) { - struct pt_regs *regs = get_child_regs(child); + struct pt_regs *regs = task_pt_regs(child); /* * Always set TIF_SINGLESTEP - this guarantees that @@ -208,7 +202,7 @@ static void clear_singlestep(struct task_struct *child) /* But touch TF only if it was set by us.. */ if (child->ptrace & PT_DTRACE) { - struct pt_regs *regs = get_child_regs(child); + struct pt_regs *regs = task_pt_regs(child); regs->eflags &= ~TRAP_FLAG; child->ptrace &= ~PT_DTRACE; } diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index c9e941ae501..a28756ef7ce 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -776,7 +776,7 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) if (c_idle.idle) { c_idle.idle->thread.rsp = (unsigned long) (((struct pt_regs *) - (THREAD_SIZE + (unsigned long) c_idle.idle->thread_info)) - 1); + (THREAD_SIZE + task_stack_page(c_idle.idle))) - 1); init_idle(c_idle.idle, cpu); goto do_rest; } @@ -814,7 +814,7 @@ do_rest: init_rsp = c_idle.idle->thread.rsp; per_cpu(init_tss,cpu).rsp0 = init_rsp; initial_code = start_secondary; - clear_ti_thread_flag(c_idle.idle->thread_info, TIF_FORK); + clear_tsk_thread_flag(c_idle.idle, TIF_FORK); printk(KERN_INFO "Booting processor %d/%d APIC 0x%x\n", cpu, cpus_weight(cpu_present_map), diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 2671fd46ea8..8bb0aeda78b 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -308,7 +308,7 @@ void show_registers(struct pt_regs *regs) printk("CPU %d ", cpu); __show_regs(regs); printk("Process %s (pid: %d, threadinfo %p, task %p)\n", - cur->comm, cur->pid, cur->thread_info, cur); + cur->comm, cur->pid, task_thread_info(cur), cur); /* * When in-kernel, we also print out the stack and code at the @@ -666,7 +666,7 @@ asmlinkage struct pt_regs *sync_regs(struct pt_regs *eregs) ; /* Exception from user space */ else if (user_mode(eregs)) - regs = ((struct pt_regs *)current->thread.rsp0) - 1; + regs = task_pt_regs(current); /* Exception from kernel and interrupts are enabled. Move to kernel process stack. */ else if (eregs->eflags & X86_EFLAGS_IF) @@ -912,7 +912,7 @@ asmlinkage void math_state_restore(void) if (!used_math()) init_fpu(me); restore_fpu_checking(&me->thread.i387.fxsave); - me->thread_info->status |= TS_USEDFPU; + task_thread_info(me)->status |= TS_USEDFPU; } void __init trap_init(void) diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 6a44b54ae81..f1f596644bf 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -145,7 +145,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, int user_mode = user_mode(regs); /* Set up new TSS. */ - tos = (unsigned long)p->thread_info + THREAD_SIZE; + tos = (unsigned long)task_stack_page(p) + THREAD_SIZE; if (user_mode) childregs = (struct pt_regs*)(tos - PT_USER_SIZE); else @@ -217,7 +217,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) unsigned long get_wchan(struct task_struct *p) { unsigned long sp, pc; - unsigned long stack_page = (unsigned long) p->thread_info; + unsigned long stack_page = (unsigned long) task_stack_page(p); int count = 0; if (!p || p == current || p->state == TASK_RUNNING) diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index ab5c4c65b5c..4cc85285a70 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -72,7 +72,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) struct pt_regs *regs; unsigned long tmp; - regs = xtensa_pt_regs(child); + regs = task_pt_regs(child); tmp = 0; /* Default return value. */ switch(addr) { @@ -149,7 +149,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_POKEUSR: { struct pt_regs *regs; - regs = xtensa_pt_regs(child); + regs = task_pt_regs(child); switch (addr) { case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: @@ -240,7 +240,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) * elf_gregset_t format. */ xtensa_gregset_t format; - struct pt_regs *regs = xtensa_pt_regs(child); + struct pt_regs *regs = task_pt_regs(child); do_copy_regs (&format, regs, child); @@ -257,7 +257,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) * values in the elf_gregset_t format. */ xtensa_gregset_t format; - struct pt_regs *regs = xtensa_pt_regs(child); + struct pt_regs *regs = task_pt_regs(child); if (copy_from_user(&format,(void *)data,sizeof(elf_gregset_t))){ ret = -EFAULT; @@ -281,7 +281,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) * elf_fpregset_t format. */ elf_fpregset_t fpregs; - struct pt_regs *regs = xtensa_pt_regs(child); + struct pt_regs *regs = task_pt_regs(child); do_save_fpregs (&fpregs, regs, child); @@ -299,7 +299,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) * values in the elf_fpregset_t format. */ elf_fpregset_t fpregs; - struct pt_regs *regs = xtensa_pt_regs(child); + struct pt_regs *regs = task_pt_regs(child); ret = 0; if (copy_from_user(&fpregs, (void *)data, sizeof(elf_fpregset_t))) { diff --git a/block/elevator.c b/block/elevator.c index 99a4d7b2f8a..1d0759178e4 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -610,23 +610,23 @@ void elv_completed_request(request_queue_t *q, struct request *rq) * request is released from the driver, io must be done */ if (blk_account_rq(rq)) { - struct request *first_rq = list_entry_rq(q->queue_head.next); - q->in_flight--; + if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn) + e->ops->elevator_completed_req_fn(q, rq); + } - /* - * Check if the queue is waiting for fs requests to be - * drained for flush sequence. - */ - if (q->ordseq && q->in_flight == 0 && + /* + * Check if the queue is waiting for fs requests to be + * drained for flush sequence. + */ + if (unlikely(q->ordseq)) { + struct request *first_rq = list_entry_rq(q->queue_head.next); + if (q->in_flight == 0 && blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN && blk_ordered_req_seq(first_rq) > QUEUE_ORDSEQ_DRAIN) { blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0); q->request_fn(q); } - - if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn) - e->ops->elevator_completed_req_fn(q, rq); } } diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 3c679d30b69..b6e29095621 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -194,6 +194,8 @@ static DECLARE_WAIT_QUEUE_HEAD(ms_wait); */ #define MAX_ERRORS 12 +#define custom amiga_custom + /* Prevent "aliased" accesses. */ static int fd_ref[4] = { 0,0,0,0 }; static int fd_device[4] = { 0, 0, 0, 0 }; @@ -1439,6 +1441,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, { int drive = iminor(inode) & 3; static struct floppy_struct getprm; + void __user *argp = (void __user *)param; switch(cmd){ case FDFMTBEG: @@ -1484,9 +1487,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, getprm.head=unit[drive].type->heads; getprm.sect=unit[drive].dtype->sects * unit[drive].type->sect_mult; getprm.size=unit[drive].blocks; - if (copy_to_user((void *)param, - (void *)&getprm, - sizeof(struct floppy_struct))) + if (copy_to_user(argp, &getprm, sizeof(struct floppy_struct))) return -EFAULT; break; case FDSETPRM: @@ -1498,8 +1499,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, break; #ifdef RAW_IOCTL case IOCTL_RAW_TRACK: - if (copy_to_user((void *)param, raw_buf, - unit[drive].type->read_size)) + if (copy_to_user(argp, raw_buf, unit[drive].type->read_size)) return -EFAULT; else return unit[drive].type->read_size; @@ -1654,12 +1654,6 @@ static struct block_device_operations floppy_fops = { .media_changed = amiga_floppy_change, }; -void __init amiga_floppy_setup (char *str, int *ints) -{ - printk (KERN_INFO "amiflop: Setting default df0 to %x\n", ints[1]); - fd_def_df0 = ints[1]; -} - static int __init fd_probe_drives(void) { int drive,drives,nomem; @@ -1845,4 +1839,18 @@ void cleanup_module(void) unregister_blkdev(FLOPPY_MAJOR, "fd"); } #endif + +#else +static int __init amiga_floppy_setup (char *str) +{ + int n; + if (!MACH_IS_AMIGA) + return 0; + if (!get_option(&str, &n)) + return 0; + printk (KERN_INFO "amiflop: Setting default df0 to %x\n", n); + fd_def_df0 = n; +} + +__setup("floppy=", amiga_floppy_setup); #endif diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 3aa68a5447d..f8ce235ccfc 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -1361,7 +1361,7 @@ static int floppy_revalidate(struct gendisk *disk) formats, for 'permanent user-defined' parameter: restore default_params[] here if flagged valid! */ if (default_params[drive].blocks == 0) - UDT = 0; + UDT = NULL; else UDT = &default_params[drive]; } @@ -1495,6 +1495,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, struct floppy_struct getprm; int settype; struct floppy_struct setprm; + void __user *argp = (void __user *)param; switch (cmd) { case FDGETPRM: @@ -1521,7 +1522,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, getprm.head = 2; getprm.track = dtp->blocks/dtp->spt/2; getprm.stretch = dtp->stretch; - if (copy_to_user((void *)param, &getprm, sizeof(getprm))) + if (copy_to_user(argp, &getprm, sizeof(getprm))) return -EFAULT; return 0; } @@ -1540,7 +1541,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, /* get the parameters from user space */ if (floppy->ref != 1 && floppy->ref != -1) return -EBUSY; - if (copy_from_user(&setprm, (void *) param, sizeof(setprm))) + if (copy_from_user(&setprm, argp, sizeof(setprm))) return -EFAULT; /* * first of all: check for floppy change and revalidate, @@ -1647,7 +1648,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, case FDFMTTRK: if (floppy->ref != 1 && floppy->ref != -1) return -EBUSY; - if (copy_from_user(&fmt_desc, (void *) param, sizeof(fmt_desc))) + if (copy_from_user(&fmt_desc, argp, sizeof(fmt_desc))) return -EFAULT; return do_format(drive, type, &fmt_desc); case FDCLRPRM: @@ -1950,14 +1951,20 @@ Enomem: return -ENOMEM; } - -void __init atari_floppy_setup( char *str, int *ints ) +#ifndef MODULE +static int __init atari_floppy_setup(char *str) { + int ints[3 + FD_MAX_UNITS]; int i; + + if (!MACH_IS_ATARI) + return 0; + + str = get_options(str, 3 + FD_MAX_UNITS, ints); if (ints[0] < 1) { printk(KERN_ERR "ataflop_setup: no arguments!\n" ); - return; + return 0; } else if (ints[0] > 2+FD_MAX_UNITS) { printk(KERN_ERR "ataflop_setup: too many arguments\n" ); @@ -1977,9 +1984,13 @@ void __init atari_floppy_setup( char *str, int *ints ) else UserSteprate[i-3] = ints[i]; } + return 1; } -static void atari_floppy_exit(void) +__setup("floppy=", atari_floppy_setup); +#endif + +static void __exit atari_floppy_exit(void) { int i; blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index d1aaf31bd97..f63e07bd9f9 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -293,6 +293,7 @@ static int send_request(struct request *req) u16 viocmd; HvLpEvent_Rc hvrc; struct vioblocklpevent *bevent; + struct HvLpEvent *hev; struct scatterlist sg[VIOMAXBLOCKDMA]; int sgindex; int statindex; @@ -347,22 +348,19 @@ static int send_request(struct request *req) * token so we can match the response up later */ memset(bevent, 0, sizeof(struct vioblocklpevent)); - bevent->event.xFlags.xValid = 1; - bevent->event.xFlags.xFunction = HvLpEvent_Function_Int; - bevent->event.xFlags.xAckInd = HvLpEvent_AckInd_DoAck; - bevent->event.xFlags.xAckType = HvLpEvent_AckType_ImmediateAck; - bevent->event.xType = HvLpEvent_Type_VirtualIo; - bevent->event.xSubtype = viocmd; - bevent->event.xSourceLp = HvLpConfig_getLpIndex(); - bevent->event.xTargetLp = viopath_hostLp; - bevent->event.xSizeMinus1 = + hev = &bevent->event; + hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DO_ACK | + HV_LP_EVENT_INT; + hev->xType = HvLpEvent_Type_VirtualIo; + hev->xSubtype = viocmd; + hev->xSourceLp = HvLpConfig_getLpIndex(); + hev->xTargetLp = viopath_hostLp; + hev->xSizeMinus1 = offsetof(struct vioblocklpevent, u.rw_data.dma_info) + (sizeof(bevent->u.rw_data.dma_info[0]) * nsg) - 1; - bevent->event.xSourceInstanceId = - viopath_sourceinst(viopath_hostLp); - bevent->event.xTargetInstanceId = - viopath_targetinst(viopath_hostLp); - bevent->event.xCorrelationToken = (u64)req; + hev->xSourceInstanceId = viopath_sourceinst(viopath_hostLp); + hev->xTargetInstanceId = viopath_targetinst(viopath_hostLp); + hev->xCorrelationToken = (u64)req; bevent->version = VIOVERSION; bevent->disk = DEVICE_NO(d); bevent->u.rw_data.offset = start; @@ -649,10 +647,10 @@ static void handle_block_event(struct HvLpEvent *event) /* Notification that a partition went away! */ return; /* First, we should NEVER get an int here...only acks */ - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + if (hvlpevent_is_int(event)) { printk(VIOD_KERN_WARNING "Yikes! got an int in viodasd event handler!\n"); - if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { + if (hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); } @@ -695,7 +693,7 @@ static void handle_block_event(struct HvLpEvent *event) default: printk(VIOD_KERN_WARNING "invalid subtype!"); - if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { + if (hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); } diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index b5191780ecc..193446e6a08 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -542,10 +542,10 @@ static void vio_handle_cd_event(struct HvLpEvent *event) /* Notification that a partition went away! */ return; /* First, we should NEVER get an int here...only acks */ - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + if (hvlpevent_is_int(event)) { printk(VIOCD_KERN_WARNING "Yikes! got an int in viocd event handler!\n"); - if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { + if (hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); } @@ -616,7 +616,7 @@ return_complete: printk(VIOCD_KERN_WARNING "message with invalid subtype %0x04X!\n", event->xSubtype & VIOMINOR_SUBTYPE_MASK); - if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { + if (hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); } diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 869518e4035..667a21c72ed 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -99,6 +99,7 @@ static char *serial_version = "4.30"; #define _INLINE_ inline #endif +#define custom amiga_custom static char *serial_name = "Amiga-builtin serial driver"; static struct tty_driver *serial_driver; @@ -1088,7 +1089,7 @@ static void rs_unthrottle(struct tty_struct * tty) */ static int get_serial_info(struct async_struct * info, - struct serial_struct * retinfo) + struct serial_struct __user * retinfo) { struct serial_struct tmp; struct serial_state *state = info->state; @@ -1112,7 +1113,7 @@ static int get_serial_info(struct async_struct * info, } static int set_serial_info(struct async_struct * info, - struct serial_struct * new_info) + struct serial_struct __user * new_info) { struct serial_struct new_serial; struct serial_state old_state, *state; @@ -1193,7 +1194,7 @@ check_and_exit: * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. */ -static int get_lsr_info(struct async_struct * info, unsigned int *value) +static int get_lsr_info(struct async_struct * info, unsigned int __user *value) { unsigned char status; unsigned int result; @@ -1284,6 +1285,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, struct async_struct * info = (struct async_struct *)tty->driver_data; struct async_icount cprev, cnow; /* kernel counter temps */ struct serial_icounter_struct icount; + void __user *argp = (void __user *)arg; unsigned long flags; if (serial_paranoia_check(info, tty->name, "rs_ioctl")) @@ -1298,19 +1300,17 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, switch (cmd) { case TIOCGSERIAL: - return get_serial_info(info, - (struct serial_struct *) arg); + return get_serial_info(info, argp); case TIOCSSERIAL: - return set_serial_info(info, - (struct serial_struct *) arg); + return set_serial_info(info, argp); case TIOCSERCONFIG: return 0; case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, (unsigned int *) arg); + return get_lsr_info(info, argp); case TIOCSERGSTRUCT: - if (copy_to_user((struct async_struct *) arg, + if (copy_to_user(argp, info, sizeof(struct async_struct))) return -EFAULT; return 0; @@ -1369,7 +1369,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, icount.brk = cnow.brk; icount.buf_overrun = cnow.buf_overrun; - if (copy_to_user((void *)arg, &icount, sizeof(icount))) + if (copy_to_user(argp, &icount, sizeof(icount))) return -EFAULT; return 0; case TIOCSERGWILD: diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index 8693835cb2d..e233cf280bc 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -165,7 +165,7 @@ static int dsp56k_reset(void) return 0; } -static int dsp56k_upload(u_char *bin, int len) +static int dsp56k_upload(u_char __user *bin, int len) { int i; u_char *p; @@ -199,7 +199,7 @@ static int dsp56k_upload(u_char *bin, int len) return 0; } -static ssize_t dsp56k_read(struct file *file, char *buf, size_t count, +static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; @@ -225,10 +225,10 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count, } case 2: /* 16 bit */ { - short *data; + short __user *data; count /= 2; - data = (short*) buf; + data = (short __user *) buf; handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE, put_user(dsp56k_host_interface.data.w[1], data+n++)); return 2*n; @@ -244,10 +244,10 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count, } case 4: /* 32 bit */ { - long *data; + long __user *data; count /= 4; - data = (long*) buf; + data = (long __user *) buf; handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE, put_user(dsp56k_host_interface.data.l, data+n++)); return 4*n; @@ -262,7 +262,7 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count, } } -static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count, +static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; @@ -287,10 +287,10 @@ static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count, } case 2: /* 16 bit */ { - const short *data; + const short __user *data; count /= 2; - data = (const short *)buf; + data = (const short __user *)buf; handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, get_user(dsp56k_host_interface.data.w[1], data+n++)); return 2*n; @@ -306,10 +306,10 @@ static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count, } case 4: /* 32 bit */ { - const long *data; + const long __user *data; count /= 4; - data = (const long *)buf; + data = (const long __user *)buf; handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, get_user(dsp56k_host_interface.data.l, data+n++)); return 4*n; @@ -328,6 +328,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int dev = iminor(inode) & 0x0f; + void __user *argp = (void __user *)arg; switch(dev) { @@ -336,9 +337,9 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, switch(cmd) { case DSP56K_UPLOAD: { - char *bin; + char __user *bin; int r, len; - struct dsp56k_upload *binary = (struct dsp56k_upload *) arg; + struct dsp56k_upload __user *binary = argp; if(get_user(len, &binary->len) < 0) return -EFAULT; @@ -372,7 +373,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, case DSP56K_HOST_FLAGS: { int dir, out, status; - struct dsp56k_host_flags *hf = (struct dsp56k_host_flags*) arg; + struct dsp56k_host_flags __user *hf = argp; if(get_user(dir, &hf->dir) < 0) return -EFAULT; diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 704c3c07f0a..29c41f4418c 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -534,7 +534,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, return virtr + wrote; } -#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) +#if defined(CONFIG_ISA) || !defined(__mc68000__) static ssize_t read_port(struct file * file, char __user * buf, size_t count, loff_t *ppos) { @@ -795,7 +795,7 @@ static struct file_operations null_fops = { .write = write_null, }; -#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) +#if defined(CONFIG_ISA) || !defined(__mc68000__) static struct file_operations port_fops = { .llseek = memory_lseek, .read = read_port, @@ -865,7 +865,7 @@ static int memory_open(struct inode * inode, struct file * filp) case 3: filp->f_op = &null_fops; break; -#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) +#if defined(CONFIG_ISA) || !defined(__mc68000__) case 4: filp->f_op = &port_fops; break; @@ -912,7 +912,7 @@ static const struct { {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, {3, "null", S_IRUGO | S_IWUGO, &null_fops}, -#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) +#if defined(CONFIG_ISA) || !defined(__mc68000__) {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, #endif {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, diff --git a/drivers/char/scc.h b/drivers/char/scc.h index 51810f72f1a..93998f5baff 100644 --- a/drivers/char/scc.h +++ b/drivers/char/scc.h @@ -399,7 +399,7 @@ struct scc_port { __asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\ } while (0) -extern unsigned char scc_shadow[2][16]; +static unsigned char scc_shadow[2][16]; /* The following functions should relax the somehow complicated * register access of the SCC. _SCCwrite() stores all written values diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index faee5e7acaf..4e536038874 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -476,19 +476,19 @@ static struct port_info *get_port_data(struct tty_struct *tty) */ static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp) { + struct HvLpEvent *hev = &viochar->event; + memset(viochar, 0, sizeof(struct viocharlpevent)); - viochar->event.xFlags.xValid = 1; - viochar->event.xFlags.xFunction = HvLpEvent_Function_Int; - viochar->event.xFlags.xAckInd = HvLpEvent_AckInd_NoAck; - viochar->event.xFlags.xAckType = HvLpEvent_AckType_DeferredAck; - viochar->event.xType = HvLpEvent_Type_VirtualIo; - viochar->event.xSubtype = viomajorsubtype_chario | viochardata; - viochar->event.xSourceLp = HvLpConfig_getLpIndex(); - viochar->event.xTargetLp = lp; - viochar->event.xSizeMinus1 = sizeof(struct viocharlpevent); - viochar->event.xSourceInstanceId = viopath_sourceinst(lp); - viochar->event.xTargetInstanceId = viopath_targetinst(lp); + hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK | + HV_LP_EVENT_INT; + hev->xType = HvLpEvent_Type_VirtualIo; + hev->xSubtype = viomajorsubtype_chario | viochardata; + hev->xSourceLp = HvLpConfig_getLpIndex(); + hev->xTargetLp = lp; + hev->xSizeMinus1 = sizeof(struct viocharlpevent); + hev->xSourceInstanceId = viopath_sourceinst(lp); + hev->xTargetInstanceId = viopath_targetinst(lp); } /* @@ -752,7 +752,7 @@ static void vioHandleOpenEvent(struct HvLpEvent *event) struct port_info *pi; int reject = 0; - if (event->xFlags.xFunction == HvLpEvent_Function_Ack) { + if (hvlpevent_is_ack(event)) { if (port >= VTTY_PORTS) return; @@ -788,7 +788,7 @@ static void vioHandleOpenEvent(struct HvLpEvent *event) } /* This had better require an ack, otherwise complain */ - if (event->xFlags.xAckInd != HvLpEvent_AckInd_DoAck) { + if (!hvlpevent_need_ack(event)) { printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n"); return; } @@ -856,7 +856,7 @@ static void vioHandleCloseEvent(struct HvLpEvent *event) struct viocharlpevent *cevent = (struct viocharlpevent *)event; u8 port = cevent->virtual_device; - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + if (hvlpevent_is_int(event)) { if (port >= VTTY_PORTS) { printk(VIOCONS_KERN_WARN "close message from invalid virtual device.\n"); @@ -1056,8 +1056,7 @@ static void vioHandleCharEvent(struct HvLpEvent *event) vioHandleConfig(event); break; default: - if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && - (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) { + if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); } diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index bcbaeb50bb9..8d50df4526a 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -55,22 +55,9 @@ #include <asm/io.h> #include <asm/bitops.h> -void ide_softirq_done(struct request *rq) -{ - request_queue_t *q = rq->q; - - add_disk_randomness(rq->rq_disk); - end_that_request_chunk(rq, 1, rq->data_len); - - spin_lock_irq(q->queue_lock); - end_that_request_last(rq, 1); - spin_unlock_irq(q->queue_lock); -} - int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, int nr_sectors) { - unsigned int nbytes; int ret = 1; BUG_ON(!(rq->flags & REQ_STARTED)); @@ -94,27 +81,12 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, HWGROUP(drive)->hwif->ide_dma_on(drive); } - /* - * For partial completions (or non fs/pc requests), use the regular - * direct completion path. Same thing for requests that failed, to - * preserve the ->errors value we use the normal completion path - * for those - */ - nbytes = nr_sectors << 9; - if (!rq->errors && rq_all_done(rq, nbytes)) { - rq->data_len = nbytes; + if (!end_that_request_first(rq, uptodate, nr_sectors)) { + add_disk_randomness(rq->rq_disk); blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; - blk_complete_request(rq); + end_that_request_last(rq, uptodate); ret = 0; - } else { - if (!end_that_request_first(rq, uptodate, nr_sectors)) { - add_disk_randomness(rq->rq_disk); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq, uptodate); - ret = 0; - } } return ret; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 7cb2d86601d..e7425546b4b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1011,8 +1011,6 @@ static int ide_init_queue(ide_drive_t *drive) blk_queue_max_hw_segments(q, max_sg_entries); blk_queue_max_phys_segments(q, max_sg_entries); - blk_queue_softirq_done(q, ide_softirq_done); - /* assign drive queue */ drive->queue = q; diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 362b33556b1..745979f33dc 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -159,7 +159,7 @@ struct input_event_compat { #ifdef CONFIG_X86_64 # define COMPAT_TEST is_compat_task() #elif defined(CONFIG_IA64) -# define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current)) +# define COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current)) #elif defined(CONFIG_S390) # define COMPAT_TEST test_thread_flag(TIF_31BIT) #elif defined(CONFIG_MIPS) diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index 8558a99f663..ec55a29fc86 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c @@ -64,8 +64,8 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp) if (amijoy[i]) { switch (i) { - case 0: data = ~custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break; - case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break; + case 0: data = ~amiga_custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break; + case 1: data = ~amiga_custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break; } input_regs(amijoy_dev[i], fp); diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c index d13d4c8fe3c..c8b2cc9f184 100644 --- a/drivers/input/mouse/amimouse.c +++ b/drivers/input/mouse/amimouse.c @@ -41,7 +41,7 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp) unsigned short joy0dat, potgor; int nx, ny, dx, dy; - joy0dat = custom.joy0dat; + joy0dat = amiga_custom.joy0dat; nx = joy0dat & 0xff; ny = joy0dat >> 8; @@ -57,7 +57,7 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp) amimouse_lastx = nx; amimouse_lasty = ny; - potgor = custom.potgor; + potgor = amiga_custom.potgor; input_regs(amimouse_dev, fp); @@ -77,7 +77,7 @@ static int amimouse_open(struct input_dev *dev) { unsigned short joy0dat; - joy0dat = custom.joy0dat; + joy0dat = amiga_custom.joy0dat; amimouse_lastx = joy0dat & 0xff; amimouse_lasty = joy0dat >> 8; diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c index 71aeb912ec6..d56d400b6aa 100644 --- a/drivers/macintosh/adb-iop.c +++ b/drivers/macintosh/adb-iop.c @@ -239,7 +239,7 @@ static int adb_iop_write(struct adb_request *req) local_irq_save(flags); - req->next = 0; + req->next = NULL; req->sent = 0; req->complete = 0; req->reply_len = 0; diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index e9a159ad302..2a2ffe06016 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c @@ -260,7 +260,7 @@ static int macii_write(struct adb_request *req) return -EINVAL; } - req->next = 0; + req->next = NULL; req->sent = 0; req->complete = 0; req->reply_len = 0; @@ -295,7 +295,7 @@ static void macii_poll(void) unsigned long flags; local_irq_save(flags); - if (via[IFR] & SR_INT) macii_interrupt(0, 0, 0); + if (via[IFR] & SR_INT) macii_interrupt(0, NULL, NULL); local_irq_restore(flags); } diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c index a1966975d58..0129fcc3b18 100644 --- a/drivers/macintosh/via-maciisi.c +++ b/drivers/macintosh/via-maciisi.c @@ -294,6 +294,24 @@ static void maciisi_sync(struct adb_request *req) printk(KERN_ERR "maciisi_send_request: poll timed out!\n"); } +int +maciisi_request(struct adb_request *req, void (*done)(struct adb_request *), + int nbytes, ...) +{ + va_list list; + int i; + + req->nbytes = nbytes; + req->done = done; + req->reply_expected = 0; + va_start(list, nbytes); + for (i = 0; i < nbytes; i++) + req->data[i++] = va_arg(list, int); + va_end(list); + + return maciisi_send_request(req, 1); +} + /* Enqueue a request, and run the queue if possible */ static int maciisi_write(struct adb_request* req) @@ -308,7 +326,7 @@ maciisi_write(struct adb_request* req) req->complete = 1; return -EINVAL; } - req->next = 0; + req->next = NULL; req->sent = 0; req->complete = 0; req->reply_len = 0; @@ -403,7 +421,7 @@ maciisi_poll(void) local_irq_save(flags); if (via[IFR] & SR_INT) { - maciisi_interrupt(0, 0, 0); + maciisi_interrupt(0, NULL, NULL); } else /* avoid calling this function too quickly in a loop */ udelay(ADB_DELAY); diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c index 6f80d76ac17..f08e52f2107 100644 --- a/drivers/macintosh/via-pmu68k.c +++ b/drivers/macintosh/via-pmu68k.c @@ -493,7 +493,7 @@ pmu_queue_request(struct adb_request *req) return -EINVAL; } - req->next = 0; + req->next = NULL; req->sent = 0; req->complete = 0; local_irq_save(flags); @@ -717,7 +717,7 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs) printk(KERN_ERR "PMU: extra ADB reply\n"); return; } - req_awaiting_reply = 0; + req_awaiting_reply = NULL; if (len <= 2) req->reply_len = 0; else { diff --git a/drivers/md/md.c b/drivers/md/md.c index 0302723fa21..1778104e106 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1238,6 +1238,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) mdk_rdev_t *same_pdev; char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; struct kobject *ko; + char *s; if (rdev->mddev) { MD_BUG(); @@ -1277,6 +1278,8 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) bdevname(rdev->bdev,b); if (kobject_set_name(&rdev->kobj, "dev-%s", b) < 0) return -ENOMEM; + while ( (s=strchr(rdev->kobj.k_name, '/')) != NULL) + *s = '!'; list_add(&rdev->same_set, &mddev->disks); rdev->mddev = mddev; diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index b42e0fbab59..aff83f96680 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -24,13 +24,14 @@ #include <linux/errno.h> #include <linux/interrupt.h> #include <linux/device.h> +#include <linux/mutex.h> #include <asm/dma.h> #include <asm/hardware.h> #include "ucb1x00.h" -static DECLARE_MUTEX(ucb1x00_sem); +static DEFINE_MUTEX(ucb1x00_mutex); static LIST_HEAD(ucb1x00_drivers); static LIST_HEAD(ucb1x00_devices); @@ -521,12 +522,12 @@ static int ucb1x00_probe(struct mcp *mcp) goto err_irq; INIT_LIST_HEAD(&ucb->devs); - down(&ucb1x00_sem); + mutex_lock(&ucb1x00_mutex); list_add(&ucb->node, &ucb1x00_devices); list_for_each_entry(drv, &ucb1x00_drivers, node) { ucb1x00_add_dev(ucb, drv); } - up(&ucb1x00_sem); + mutex_unlock(&ucb1x00_mutex); goto out; err_irq: @@ -544,13 +545,13 @@ static void ucb1x00_remove(struct mcp *mcp) struct ucb1x00 *ucb = mcp_get_drvdata(mcp); struct list_head *l, *n; - down(&ucb1x00_sem); + mutex_lock(&ucb1x00_mutex); list_del(&ucb->node); list_for_each_safe(l, n, &ucb->devs) { struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, dev_node); ucb1x00_remove_dev(dev); } - up(&ucb1x00_sem); + mutex_unlock(&ucb1x00_mutex); free_irq(ucb->irq, ucb); class_device_unregister(&ucb->cdev); @@ -561,12 +562,12 @@ int ucb1x00_register_driver(struct ucb1x00_driver *drv) struct ucb1x00 *ucb; INIT_LIST_HEAD(&drv->devs); - down(&ucb1x00_sem); + mutex_lock(&ucb1x00_mutex); list_add(&drv->node, &ucb1x00_drivers); list_for_each_entry(ucb, &ucb1x00_devices, node) { ucb1x00_add_dev(ucb, drv); } - up(&ucb1x00_sem); + mutex_unlock(&ucb1x00_mutex); return 0; } @@ -574,13 +575,13 @@ void ucb1x00_unregister_driver(struct ucb1x00_driver *drv) { struct list_head *n, *l; - down(&ucb1x00_sem); + mutex_lock(&ucb1x00_mutex); list_del(&drv->node); list_for_each_safe(l, n, &drv->devs) { struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, drv_node); ucb1x00_remove_dev(dev); } - up(&ucb1x00_sem); + mutex_unlock(&ucb1x00_mutex); } static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state) @@ -588,12 +589,12 @@ static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state) struct ucb1x00 *ucb = mcp_get_drvdata(mcp); struct ucb1x00_dev *dev; - down(&ucb1x00_sem); + mutex_lock(&ucb1x00_mutex); list_for_each_entry(dev, &ucb->devs, dev_node) { if (dev->drv->suspend) dev->drv->suspend(dev, state); } - up(&ucb1x00_sem); + mutex_unlock(&ucb1x00_mutex); return 0; } @@ -602,12 +603,12 @@ static int ucb1x00_resume(struct mcp *mcp) struct ucb1x00 *ucb = mcp_get_drvdata(mcp); struct ucb1x00_dev *dev; - down(&ucb1x00_sem); + mutex_lock(&ucb1x00_mutex); list_for_each_entry(dev, &ucb->devs, dev_node) { if (dev->drv->resume) dev->drv->resume(dev); } - up(&ucb1x00_sem); + mutex_unlock(&ucb1x00_mutex); return 0; } diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index f2c42b13945..9b7c37e0e57 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -28,6 +28,7 @@ #include <linux/kdev_t.h> #include <linux/blkdev.h> #include <linux/devfs_fs_kernel.h> +#include <linux/mutex.h> #include <linux/mmc/card.h> #include <linux/mmc/protocol.h> @@ -57,33 +58,33 @@ struct mmc_blk_data { unsigned int read_only; }; -static DECLARE_MUTEX(open_lock); +static DEFINE_MUTEX(open_lock); static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) { struct mmc_blk_data *md; - down(&open_lock); + mutex_lock(&open_lock); md = disk->private_data; if (md && md->usage == 0) md = NULL; if (md) md->usage++; - up(&open_lock); + mutex_unlock(&open_lock); return md; } static void mmc_blk_put(struct mmc_blk_data *md) { - down(&open_lock); + mutex_lock(&open_lock); md->usage--; if (md->usage == 0) { put_disk(md->disk); mmc_cleanup_queue(&md->queue); kfree(md); } - up(&open_lock); + mutex_unlock(&open_lock); } static int mmc_blk_open(struct inode *inode, struct file *filp) diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c index 08703d6f934..d8410634bca 100644 --- a/drivers/net/hplance.c +++ b/drivers/net/hplance.c @@ -150,7 +150,7 @@ static void __init hplance_init(struct net_device *dev, struct dio_dev *d) lp->lance.name = (char*)d->name; /* discards const, shut up gcc */ lp->lance.base = va; lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */ - lp->lance.lance_init_block = 0; /* LANCE addr of same RAM */ + lp->lance.lance_init_block = NULL; /* LANCE addr of same RAM */ lp->lance.busmaster_regval = LE_C3_BSWP; /* we're bigendian */ lp->lance.irq = d->ipl; lp->lance.writerap = hplance_writerap; diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 77eadf84cb2..f0f04be989d 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -590,9 +590,9 @@ static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs) { struct veth_lpevent *veth_event = (struct veth_lpevent *)event; - if (event->xFlags.xFunction == HvLpEvent_Function_Ack) + if (hvlpevent_is_ack(event)) veth_handle_ack(veth_event); - else if (event->xFlags.xFunction == HvLpEvent_Function_Int) + else veth_handle_int(veth_event); } diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index d8c99f038fa..06cb460361a 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -559,55 +559,52 @@ static void mac8390_no_reset(struct net_device *dev) /* directly from daynaport.c by Alan Cox */ static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count) { - volatile unsigned short *ptr; - unsigned short *target=to; + volatile unsigned char *ptr; + unsigned char *target=to; from<<=1; /* word, skip overhead */ - ptr=(unsigned short *)(dev->mem_start+from); + ptr=(unsigned char *)(dev->mem_start+from); /* Leading byte? */ if (from&2) { - *((char *)target)++ = *(((char *)ptr++)-1); + *target++ = ptr[-1]; + ptr += 2; count--; } while(count>=2) { - *target++=*ptr++; /* Copy and */ - ptr++; /* skip cruft */ + *(unsigned short *)target = *(unsigned short volatile *)ptr; + ptr += 4; /* skip cruft */ + target += 2; count-=2; } /* Trailing byte? */ if(count) - { - /* Big endian */ - unsigned short v=*ptr; - *((char *)target)=v>>8; - } + *target = *ptr; } static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count) { volatile unsigned short *ptr; - const unsigned short *src=from; + const unsigned char *src=from; to<<=1; /* word, skip overhead */ ptr=(unsigned short *)(dev->mem_start+to); /* Leading byte? */ if (to&2) { /* avoid a byte write (stomps on other data) */ - ptr[-1] = (ptr[-1]&0xFF00)|*((unsigned char *)src)++; + ptr[-1] = (ptr[-1]&0xFF00)|*src++; ptr++; count--; } while(count>=2) { - *ptr++=*src++; /* Copy and */ + *ptr++=*(unsigned short *)src; /* Copy and */ ptr++; /* skip cruft */ + src += 2; count-=2; } /* Trailing byte? */ if(count) { - /* Big endian */ - unsigned short v=*src; /* card doesn't like byte writes */ - *ptr=(*ptr&0x00FF)|(v&0xFF00); + *ptr=(*ptr&0x00FF)|(*src << 8); } } diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index 5c8fcd40ef4..01bdb233405 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -389,7 +389,7 @@ static int __init lance_probe( struct net_device *dev) dev->stop = &lance_close; dev->get_stats = &lance_get_stats; dev->set_multicast_list = &set_multicast_list; - dev->set_mac_address = 0; + dev->set_mac_address = NULL; // KLUDGE -- REMOVE ME set_bit(__LINK_STATE_PRESENT, &dev->state); diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index f062ea0f813..6e0c059df6a 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -45,7 +45,7 @@ obj-$(CONFIG_CYBERSTORMII_SCSI) += NCR53C9x.o cyberstormII.o obj-$(CONFIG_BLZ2060_SCSI) += NCR53C9x.o blz2060.o obj-$(CONFIG_BLZ1230_SCSI) += NCR53C9x.o blz1230.o obj-$(CONFIG_FASTLANE_SCSI) += NCR53C9x.o fastlane.o -obj-$(CONFIG_OKTAGON_SCSI) += NCR53C9x.o oktagon_esp.o oktagon_io.o +obj-$(CONFIG_OKTAGON_SCSI) += NCR53C9x.o oktagon_esp_mod.o obj-$(CONFIG_ATARI_SCSI) += atari_scsi.o obj-$(CONFIG_MAC_SCSI) += mac_scsi.o obj-$(CONFIG_SCSI_MAC_ESP) += mac_esp.o NCR53C9x.o @@ -164,6 +164,7 @@ CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m) zalon7xx-objs := zalon.o ncr53c8xx.o NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o libata-objs := libata-core.o libata-scsi.o +oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o # Files generated that shall be removed upon make clean clean-files := 53c7xx_d.h 53c700_d.h \ diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c index 640590bd014..c7dd0154d01 100644 --- a/drivers/scsi/NCR53C9x.c +++ b/drivers/scsi/NCR53C9x.c @@ -1799,6 +1799,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs) */ int oldphase, i = 0; /* or where we left off last time ?? esp->current_data ?? */ int fifocnt = 0; + unsigned char *p = phys_to_virt((unsigned long)SCptr->SCp.ptr); oldphase = esp_read(eregs->esp_status) & ESP_STAT_PMASK; @@ -1860,7 +1861,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs) /* read fifo */ for(j=0;j<fifocnt;j++) - SCptr->SCp.ptr[i++] = esp_read(eregs->esp_fdata); + p[i++] = esp_read(eregs->esp_fdata); ESPDATA(("(%d) ", i)); @@ -1882,7 +1883,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs) /* fill fifo */ for(j=0;j<this_count;j++) - esp_write(eregs->esp_fdata, SCptr->SCp.ptr[i++]); + esp_write(eregs->esp_fdata, p[i++]); /* how many left if this goes out ?? */ hmuch -= this_count; diff --git a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c index 763e409a1ff..3867ac2de4c 100644 --- a/drivers/scsi/blz1230.c +++ b/drivers/scsi/blz1230.c @@ -224,7 +224,7 @@ static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp) static void dma_dump_state(struct NCR_ESP *esp) { ESPLOG(("intreq:<%04x>, intena:<%04x>\n", - custom.intreqr, custom.intenar)); + amiga_custom.intreqr, amiga_custom.intenar)); } void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) @@ -298,7 +298,7 @@ static int dma_irq_p(struct NCR_ESP *esp) static int dma_ports_p(struct NCR_ESP *esp) { - return ((custom.intenar) & IF_PORTS); + return ((amiga_custom.intenar) & IF_PORTS); } static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) diff --git a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c index d72d05fffdf..4ebe69e3275 100644 --- a/drivers/scsi/blz2060.c +++ b/drivers/scsi/blz2060.c @@ -190,7 +190,7 @@ static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp) static void dma_dump_state(struct NCR_ESP *esp) { ESPLOG(("intreq:<%04x>, intena:<%04x>\n", - custom.intreqr, custom.intenar)); + amiga_custom.intreqr, amiga_custom.intenar)); } static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) @@ -251,7 +251,7 @@ static void dma_led_on(struct NCR_ESP *esp) static int dma_ports_p(struct NCR_ESP *esp) { - return ((custom.intenar) & IF_PORTS); + return ((amiga_custom.intenar) & IF_PORTS); } static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) diff --git a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c index f9b940e5643..a4a4fac5c0a 100644 --- a/drivers/scsi/cyberstorm.c +++ b/drivers/scsi/cyberstorm.c @@ -223,7 +223,7 @@ static void dma_dump_state(struct NCR_ESP *esp) esp->esp_id, ((struct cyber_dma_registers *) (esp->dregs))->cond_reg)); ESPLOG(("intreq:<%04x>, intena:<%04x>\n", - custom.intreqr, custom.intenar)); + amiga_custom.intreqr, amiga_custom.intenar)); } static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) @@ -322,7 +322,7 @@ static void dma_led_on(struct NCR_ESP *esp) static int dma_ports_p(struct NCR_ESP *esp) { - return ((custom.intenar) & IF_PORTS); + return ((amiga_custom.intenar) & IF_PORTS); } static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) diff --git a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c index a3caabfd755..3a803d73bc5 100644 --- a/drivers/scsi/cyberstormII.c +++ b/drivers/scsi/cyberstormII.c @@ -200,7 +200,7 @@ static void dma_dump_state(struct NCR_ESP *esp) esp->esp_id, ((struct cyberII_dma_registers *) (esp->dregs))->cond_reg)); ESPLOG(("intreq:<%04x>, intena:<%04x>\n", - custom.intreqr, custom.intenar)); + amiga_custom.intreqr, amiga_custom.intenar)); } static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) @@ -259,7 +259,7 @@ static void dma_led_on(struct NCR_ESP *esp) static int dma_ports_p(struct NCR_ESP *esp) { - return ((custom.intenar) & IF_PORTS); + return ((amiga_custom.intenar) & IF_PORTS); } static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) diff --git a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c index ccee68b52f7..8ae9c406a83 100644 --- a/drivers/scsi/fastlane.c +++ b/drivers/scsi/fastlane.c @@ -268,7 +268,7 @@ static void dma_dump_state(struct NCR_ESP *esp) esp->esp_id, ((struct fastlane_dma_registers *) (esp->dregs))->cond_reg)); ESPLOG(("intreq:<%04x>, intena:<%04x>\n", - custom.intreqr, custom.intenar)); + amiga_custom.intreqr, amiga_custom.intenar)); } static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) @@ -368,7 +368,7 @@ static void dma_led_on(struct NCR_ESP *esp) static int dma_ports_p(struct NCR_ESP *esp) { - return ((custom.intenar) & IF_PORTS); + return ((amiga_custom.intenar) & IF_PORTS); } static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) diff --git a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c index 5d9c9ada814..dee426f8c07 100644 --- a/drivers/scsi/oktagon_esp.c +++ b/drivers/scsi/oktagon_esp.c @@ -490,7 +490,7 @@ static void dma_led_on(struct NCR_ESP *esp) static int dma_ports_p(struct NCR_ESP *esp) { - return ((custom.intenar) & IF_PORTS); + return ((amiga_custom.intenar) & IF_PORTS); } static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index fd63add6a57..fb53eeaee61 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -465,7 +465,7 @@ wd33c93_execute(struct Scsi_Host *instance) */ cmd = (struct scsi_cmnd *) hostdata->input_Q; - prev = 0; + prev = NULL; while (cmd) { if (!(hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))) break; @@ -1569,7 +1569,7 @@ wd33c93_abort(struct scsi_cmnd * cmd) */ tmp = (struct scsi_cmnd *) hostdata->input_Q; - prev = 0; + prev = NULL; while (tmp) { if (tmp == cmd) { if (prev) diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index d549e215f3c..2c42a812655 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -590,6 +590,8 @@ static u_short maxfmode, chipset; #define highw(x) ((u_long)(x)>>16 & 0xffff) #define loww(x) ((u_long)(x) & 0xffff) +#define custom amiga_custom + #define VBlankOn() custom.intena = IF_SETCLR|IF_COPER #define VBlankOff() custom.intena = IF_COPER @@ -1164,8 +1166,8 @@ static void ami_update_display(void); static void ami_init_display(void); static void ami_do_blank(void); static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix); -static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data); -static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data); +static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data); +static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data); static int ami_get_cursorstate(struct fb_cursorstate *state); static int ami_set_cursorstate(struct fb_cursorstate *state); static void ami_set_sprite(void); @@ -2179,6 +2181,7 @@ static int amifb_ioctl(struct inode *inode, struct file *file, struct fb_var_cursorinfo var; struct fb_cursorstate state; } crsr; + void __user *argp = (void __user *)arg; int i; switch (cmd) { @@ -2186,33 +2189,32 @@ static int amifb_ioctl(struct inode *inode, struct file *file, i = ami_get_fix_cursorinfo(&crsr.fix); if (i) return i; - return copy_to_user((void *)arg, &crsr.fix, + return copy_to_user(argp, &crsr.fix, sizeof(crsr.fix)) ? -EFAULT : 0; case FBIOGET_VCURSORINFO: i = ami_get_var_cursorinfo(&crsr.var, - ((struct fb_var_cursorinfo *)arg)->data); + ((struct fb_var_cursorinfo __user *)arg)->data); if (i) return i; - return copy_to_user((void *)arg, &crsr.var, + return copy_to_user(argp, &crsr.var, sizeof(crsr.var)) ? -EFAULT : 0; case FBIOPUT_VCURSORINFO: - if (copy_from_user(&crsr.var, (void *)arg, - sizeof(crsr.var))) + if (copy_from_user(&crsr.var, argp, sizeof(crsr.var))) return -EFAULT; return ami_set_var_cursorinfo(&crsr.var, - ((struct fb_var_cursorinfo *)arg)->data); + ((struct fb_var_cursorinfo __user *)arg)->data); case FBIOGET_CURSORSTATE: i = ami_get_cursorstate(&crsr.state); if (i) return i; - return copy_to_user((void *)arg, &crsr.state, + return copy_to_user(argp, &crsr.state, sizeof(crsr.state)) ? -EFAULT : 0; case FBIOPUT_CURSORSTATE: - if (copy_from_user(&crsr.state, (void *)arg, + if (copy_from_user(&crsr.state, argp, sizeof(crsr.state))) return -EFAULT; return ami_set_cursorstate(&crsr.state); @@ -3325,7 +3327,7 @@ static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix) return 0; } -static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data) +static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data) { struct amifb_par *par = ¤tpar; register u_short *lspr, *sspr; @@ -3347,14 +3349,14 @@ static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data) var->yspot = par->crsr.spot_y; if (size > var->height*var->width) return -ENAMETOOLONG; - if (!access_ok(VERIFY_WRITE, (void *)data, size)) + if (!access_ok(VERIFY_WRITE, data, size)) return -EFAULT; delta = 1<<par->crsr.fmode; lspr = lofsprite + (delta<<1); if (par->bplcon0 & BPC0_LACE) sspr = shfsprite + (delta<<1); else - sspr = 0; + sspr = NULL; for (height = (short)var->height-1; height >= 0; height--) { bits = 0; words = delta; datawords = 0; for (width = (short)var->width-1; width >= 0; width--) { @@ -3400,7 +3402,7 @@ static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data) return 0; } -static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data) +static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data) { struct amifb_par *par = ¤tpar; register u_short *lspr, *sspr; @@ -3427,7 +3429,7 @@ static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data) return -EINVAL; if (!var->height) return -EINVAL; - if (!access_ok(VERIFY_READ, (void *)data, var->width*var->height)) + if (!access_ok(VERIFY_READ, data, var->width*var->height)) return -EFAULT; delta = 1<<fmode; lofsprite = shfsprite = (u_short *)spritememory; @@ -3442,13 +3444,13 @@ static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data) if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE) return -EINVAL; memset(lspr, 0, (var->height+2)<<fmode<<2); - sspr = 0; + sspr = NULL; } for (height = (short)var->height-1; height >= 0; height--) { bits = 16; words = delta; datawords = 0; for (width = (short)var->width-1; width >= 0; width--) { unsigned long tdata = 0; - get_user(tdata, (char *)data); + get_user(tdata, data); data++; #ifdef __mc68000__ asm volatile ( diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index e370125e4fb..ed81005cbdb 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -3501,7 +3501,7 @@ err_release_mem: static int __devinit atyfb_atari_probe(void) { - struct aty_par *par; + struct atyfb_par *par; struct fb_info *info; int m64_num; u32 clock_r; diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index cfc748e9427..e6cbd9de944 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -609,18 +609,19 @@ void __init macfb_setup(char *options) } } -void __init macfb_init(void) +static int __init macfb_init(void) { int video_cmap_len, video_is_nubus = 0; struct nubus_dev* ndev = NULL; char *option = NULL; + int err; if (fb_get_options("macfb", &option)) return -ENODEV; macfb_setup(option); if (!MACH_IS_MAC) - return; + return -ENODEV; /* There can only be one internal video controller anyway so we're not too worried about this */ @@ -958,11 +959,11 @@ void __init macfb_init(void) fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0); - if (register_framebuffer(&fb_info) < 0) - return; - - printk("fb%d: %s frame buffer device\n", - fb_info.node, fb_info.fix.id); + err = register_framebuffer(&fb_info); + if (!err) + printk("fb%d: %s frame buffer device\n", + fb_info.node, fb_info.fix.id); + return err; } module_init(macfb_init); diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index 1a409c2c320..7aa2d3de6d3 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c @@ -45,7 +45,7 @@ proc_bus_zorro_lseek(struct file *file, loff_t off, int whence) } static ssize_t -proc_bus_zorro_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos) +proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { struct inode *ino = file->f_dentry->d_inode; struct proc_dir_entry *dp = PDE(ino); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index f0b7256b2f8..5dd0207ffd4 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -122,6 +122,7 @@ #include <linux/dvb/dmx.h> #include <linux/dvb/frontend.h> #include <linux/dvb/video.h> +#include <linux/lp.h> /* Aiee. Someone does not find a difference between int and long */ #define EXT2_IOC32_GETFLAGS _IOR('f', 1, int) @@ -2735,6 +2736,20 @@ static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned lon } #endif +static int +lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct compat_timeval *tc = (struct compat_timeval *)arg; + struct timeval *tn = compat_alloc_user_space(sizeof(struct timeval)); + struct timeval ts; + if (get_user(ts.tv_sec, &tc->tv_sec) || + get_user(ts.tv_usec, &tc->tv_usec) || + put_user(ts.tv_sec, &tn->tv_sec) || + put_user(ts.tv_usec, &tn->tv_usec)) + return -EFAULT; + return sys_ioctl(fd, cmd, (unsigned long)tn); +} + #define HANDLE_IOCTL(cmd,handler) \ { (cmd), (ioctl_trans_handler_t)(handler) }, @@ -2962,6 +2977,20 @@ HANDLE_IOCTL(DMX_GET_EVENT, do_dmx_get_event) HANDLE_IOCTL(VIDEO_GET_EVENT, do_video_get_event) HANDLE_IOCTL(VIDEO_STILLPICTURE, do_video_stillpicture) HANDLE_IOCTL(VIDEO_SET_SPU_PALETTE, do_video_set_spu_palette) + +/* parport */ +COMPATIBLE_IOCTL(LPTIME) +COMPATIBLE_IOCTL(LPCHAR) +COMPATIBLE_IOCTL(LPABORTOPEN) +COMPATIBLE_IOCTL(LPCAREFUL) +COMPATIBLE_IOCTL(LPWAIT) +COMPATIBLE_IOCTL(LPSETIRQ) +COMPATIBLE_IOCTL(LPGETSTATUS) +COMPATIBLE_IOCTL(LPGETSTATUS) +COMPATIBLE_IOCTL(LPRESET) +/*LPGETSTATS not implemented, but no kernels seem to compile it in anyways*/ +COMPATIBLE_IOCTL(LPGETFLAGS) +HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_trans) }; int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 94d3cdfbf9b..d1db8c17a74 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -40,11 +40,10 @@ #include "xfs_rw.h" #include "xfs_iomap.h" #include <linux/mpage.h> +#include <linux/pagevec.h> #include <linux/writeback.h> STATIC void xfs_count_page_state(struct page *, int *, int *, int *); -STATIC void xfs_convert_page(struct inode *, struct page *, xfs_iomap_t *, - struct writeback_control *wbc, void *, int, int); #if defined(XFS_RW_TRACE) void @@ -55,17 +54,15 @@ xfs_page_trace( int mask) { xfs_inode_t *ip; - bhv_desc_t *bdp; vnode_t *vp = LINVFS_GET_VP(inode); loff_t isize = i_size_read(inode); - loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; + loff_t offset = page_offset(page); int delalloc = -1, unmapped = -1, unwritten = -1; if (page_has_buffers(page)) xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); - bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops); - ip = XFS_BHVTOI(bdp); + ip = xfs_vtoi(vp); if (!ip->i_rwtrace) return; @@ -103,15 +100,56 @@ xfs_finish_ioend( queue_work(xfsdatad_workqueue, &ioend->io_work); } +/* + * We're now finished for good with this ioend structure. + * Update the page state via the associated buffer_heads, + * release holds on the inode and bio, and finally free + * up memory. Do not use the ioend after this. + */ STATIC void xfs_destroy_ioend( xfs_ioend_t *ioend) { + struct buffer_head *bh, *next; + + for (bh = ioend->io_buffer_head; bh; bh = next) { + next = bh->b_private; + bh->b_end_io(bh, ioend->io_uptodate); + } + vn_iowake(ioend->io_vnode); mempool_free(ioend, xfs_ioend_pool); } /* + * Buffered IO write completion for delayed allocate extents. + * TODO: Update ondisk isize now that we know the file data + * has been flushed (i.e. the notorious "NULL file" problem). + */ +STATIC void +xfs_end_bio_delalloc( + void *data) +{ + xfs_ioend_t *ioend = data; + + xfs_destroy_ioend(ioend); +} + +/* + * Buffered IO write completion for regular, written extents. + */ +STATIC void +xfs_end_bio_written( + void *data) +{ + xfs_ioend_t *ioend = data; + + xfs_destroy_ioend(ioend); +} + +/* + * IO write completion for unwritten extents. + * * Issue transactions to convert a buffer range from unwritten * to written extents. */ @@ -123,21 +161,10 @@ xfs_end_bio_unwritten( vnode_t *vp = ioend->io_vnode; xfs_off_t offset = ioend->io_offset; size_t size = ioend->io_size; - struct buffer_head *bh, *next; int error; if (ioend->io_uptodate) VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error); - - /* ioend->io_buffer_head is only non-NULL for buffered I/O */ - for (bh = ioend->io_buffer_head; bh; bh = next) { - next = bh->b_private; - - bh->b_end_io = NULL; - clear_buffer_unwritten(bh); - end_buffer_async_write(bh, ioend->io_uptodate); - } - xfs_destroy_ioend(ioend); } @@ -149,7 +176,8 @@ xfs_end_bio_unwritten( */ STATIC xfs_ioend_t * xfs_alloc_ioend( - struct inode *inode) + struct inode *inode, + unsigned int type) { xfs_ioend_t *ioend; @@ -162,45 +190,25 @@ xfs_alloc_ioend( */ atomic_set(&ioend->io_remaining, 1); ioend->io_uptodate = 1; /* cleared if any I/O fails */ + ioend->io_list = NULL; + ioend->io_type = type; ioend->io_vnode = LINVFS_GET_VP(inode); ioend->io_buffer_head = NULL; + ioend->io_buffer_tail = NULL; atomic_inc(&ioend->io_vnode->v_iocount); ioend->io_offset = 0; ioend->io_size = 0; - INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten, ioend); + if (type == IOMAP_UNWRITTEN) + INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten, ioend); + else if (type == IOMAP_DELAY) + INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc, ioend); + else + INIT_WORK(&ioend->io_work, xfs_end_bio_written, ioend); return ioend; } -void -linvfs_unwritten_done( - struct buffer_head *bh, - int uptodate) -{ - xfs_ioend_t *ioend = bh->b_private; - static spinlock_t unwritten_done_lock = SPIN_LOCK_UNLOCKED; - unsigned long flags; - - ASSERT(buffer_unwritten(bh)); - bh->b_end_io = NULL; - - if (!uptodate) - ioend->io_uptodate = 0; - - /* - * Deep magic here. We reuse b_private in the buffer_heads to build - * a chain for completing the I/O from user context after we've issued - * a transaction to convert the unwritten extent. - */ - spin_lock_irqsave(&unwritten_done_lock, flags); - bh->b_private = ioend->io_buffer_head; - ioend->io_buffer_head = bh; - spin_unlock_irqrestore(&unwritten_done_lock, flags); - - xfs_finish_ioend(ioend); -} - STATIC int xfs_map_blocks( struct inode *inode, @@ -218,138 +226,260 @@ xfs_map_blocks( return -error; } +STATIC inline int +xfs_iomap_valid( + xfs_iomap_t *iomapp, + loff_t offset) +{ + return offset >= iomapp->iomap_offset && + offset < iomapp->iomap_offset + iomapp->iomap_bsize; +} + /* - * Finds the corresponding mapping in block @map array of the - * given @offset within a @page. + * BIO completion handler for buffered IO. */ -STATIC xfs_iomap_t * -xfs_offset_to_map( +STATIC int +xfs_end_bio( + struct bio *bio, + unsigned int bytes_done, + int error) +{ + xfs_ioend_t *ioend = bio->bi_private; + + if (bio->bi_size) + return 1; + + ASSERT(ioend); + ASSERT(atomic_read(&bio->bi_cnt) >= 1); + + /* Toss bio and pass work off to an xfsdatad thread */ + if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + ioend->io_uptodate = 0; + bio->bi_private = NULL; + bio->bi_end_io = NULL; + + bio_put(bio); + xfs_finish_ioend(ioend); + return 0; +} + +STATIC void +xfs_submit_ioend_bio( + xfs_ioend_t *ioend, + struct bio *bio) +{ + atomic_inc(&ioend->io_remaining); + + bio->bi_private = ioend; + bio->bi_end_io = xfs_end_bio; + + submit_bio(WRITE, bio); + ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP)); + bio_put(bio); +} + +STATIC struct bio * +xfs_alloc_ioend_bio( + struct buffer_head *bh) +{ + struct bio *bio; + int nvecs = bio_get_nr_vecs(bh->b_bdev); + + do { + bio = bio_alloc(GFP_NOIO, nvecs); + nvecs >>= 1; + } while (!bio); + + ASSERT(bio->bi_private == NULL); + bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9); + bio->bi_bdev = bh->b_bdev; + bio_get(bio); + return bio; +} + +STATIC void +xfs_start_buffer_writeback( + struct buffer_head *bh) +{ + ASSERT(buffer_mapped(bh)); + ASSERT(buffer_locked(bh)); + ASSERT(!buffer_delay(bh)); + ASSERT(!buffer_unwritten(bh)); + + mark_buffer_async_write(bh); + set_buffer_uptodate(bh); + clear_buffer_dirty(bh); +} + +STATIC void +xfs_start_page_writeback( struct page *page, - xfs_iomap_t *iomapp, - unsigned long offset) + struct writeback_control *wbc, + int clear_dirty, + int buffers) +{ + ASSERT(PageLocked(page)); + ASSERT(!PageWriteback(page)); + set_page_writeback(page); + if (clear_dirty) + clear_page_dirty(page); + unlock_page(page); + if (!buffers) { + end_page_writeback(page); + wbc->pages_skipped++; /* We didn't write this page */ + } +} + +static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh) +{ + return bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh)); +} + +/* + * Submit all of the bios for all of the ioends we have saved up, + * covering the initial writepage page and also any probed pages. + */ +STATIC void +xfs_submit_ioend( + xfs_ioend_t *ioend) +{ + xfs_ioend_t *next; + struct buffer_head *bh; + struct bio *bio; + sector_t lastblock = 0; + + do { + next = ioend->io_list; + bio = NULL; + + for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) { + xfs_start_buffer_writeback(bh); + + if (!bio) { + retry: + bio = xfs_alloc_ioend_bio(bh); + } else if (bh->b_blocknr != lastblock + 1) { + xfs_submit_ioend_bio(ioend, bio); + goto retry; + } + + if (bio_add_buffer(bio, bh) != bh->b_size) { + xfs_submit_ioend_bio(ioend, bio); + goto retry; + } + + lastblock = bh->b_blocknr; + } + if (bio) + xfs_submit_ioend_bio(ioend, bio); + xfs_finish_ioend(ioend); + } while ((ioend = next) != NULL); +} + +/* + * Cancel submission of all buffer_heads so far in this endio. + * Toss the endio too. Only ever called for the initial page + * in a writepage request, so only ever one page. + */ +STATIC void +xfs_cancel_ioend( + xfs_ioend_t *ioend) +{ + xfs_ioend_t *next; + struct buffer_head *bh, *next_bh; + + do { + next = ioend->io_list; + bh = ioend->io_buffer_head; + do { + next_bh = bh->b_private; + clear_buffer_async_write(bh); + unlock_buffer(bh); + } while ((bh = next_bh) != NULL); + + vn_iowake(ioend->io_vnode); + mempool_free(ioend, xfs_ioend_pool); + } while ((ioend = next) != NULL); +} + +/* + * Test to see if we've been building up a completion structure for + * earlier buffers -- if so, we try to append to this ioend if we + * can, otherwise we finish off any current ioend and start another. + * Return true if we've finished the given ioend. + */ +STATIC void +xfs_add_to_ioend( + struct inode *inode, + struct buffer_head *bh, + xfs_off_t offset, + unsigned int type, + xfs_ioend_t **result, + int need_ioend) { - loff_t full_offset; /* offset from start of file */ + xfs_ioend_t *ioend = *result; - ASSERT(offset < PAGE_CACHE_SIZE); + if (!ioend || need_ioend || type != ioend->io_type) { + xfs_ioend_t *previous = *result; - full_offset = page->index; /* NB: using 64bit number */ - full_offset <<= PAGE_CACHE_SHIFT; /* offset from file start */ - full_offset += offset; /* offset from page start */ + ioend = xfs_alloc_ioend(inode, type); + ioend->io_offset = offset; + ioend->io_buffer_head = bh; + ioend->io_buffer_tail = bh; + if (previous) + previous->io_list = ioend; + *result = ioend; + } else { + ioend->io_buffer_tail->b_private = bh; + ioend->io_buffer_tail = bh; + } - if (full_offset < iomapp->iomap_offset) - return NULL; - if (iomapp->iomap_offset + (iomapp->iomap_bsize -1) >= full_offset) - return iomapp; - return NULL; + bh->b_private = NULL; + ioend->io_size += bh->b_size; } STATIC void xfs_map_at_offset( - struct page *page, struct buffer_head *bh, - unsigned long offset, + loff_t offset, int block_bits, xfs_iomap_t *iomapp) { xfs_daddr_t bn; - loff_t delta; int sector_shift; ASSERT(!(iomapp->iomap_flags & IOMAP_HOLE)); ASSERT(!(iomapp->iomap_flags & IOMAP_DELAY)); ASSERT(iomapp->iomap_bn != IOMAP_DADDR_NULL); - delta = page->index; - delta <<= PAGE_CACHE_SHIFT; - delta += offset; - delta -= iomapp->iomap_offset; - delta >>= block_bits; - sector_shift = block_bits - BBSHIFT; - bn = iomapp->iomap_bn >> sector_shift; - bn += delta; - BUG_ON(!bn && !(iomapp->iomap_flags & IOMAP_REALTIME)); + bn = (iomapp->iomap_bn >> sector_shift) + + ((offset - iomapp->iomap_offset) >> block_bits); + + ASSERT(bn || (iomapp->iomap_flags & IOMAP_REALTIME)); ASSERT((bn << sector_shift) >= iomapp->iomap_bn); lock_buffer(bh); bh->b_blocknr = bn; - bh->b_bdev = iomapp->iomap_target->pbr_bdev; + bh->b_bdev = iomapp->iomap_target->bt_bdev; set_buffer_mapped(bh); clear_buffer_delay(bh); + clear_buffer_unwritten(bh); } /* - * Look for a page at index which is unlocked and contains our - * unwritten extent flagged buffers at its head. Returns page - * locked and with an extra reference count, and length of the - * unwritten extent component on this page that we can write, - * in units of filesystem blocks. - */ -STATIC struct page * -xfs_probe_unwritten_page( - struct address_space *mapping, - pgoff_t index, - xfs_iomap_t *iomapp, - xfs_ioend_t *ioend, - unsigned long max_offset, - unsigned long *fsbs, - unsigned int bbits) -{ - struct page *page; - - page = find_trylock_page(mapping, index); - if (!page) - return NULL; - if (PageWriteback(page)) - goto out; - - if (page->mapping && page_has_buffers(page)) { - struct buffer_head *bh, *head; - unsigned long p_offset = 0; - - *fsbs = 0; - bh = head = page_buffers(page); - do { - if (!buffer_unwritten(bh) || !buffer_uptodate(bh)) - break; - if (!xfs_offset_to_map(page, iomapp, p_offset)) - break; - if (p_offset >= max_offset) - break; - xfs_map_at_offset(page, bh, p_offset, bbits, iomapp); - set_buffer_unwritten_io(bh); - bh->b_private = ioend; - p_offset += bh->b_size; - (*fsbs)++; - } while ((bh = bh->b_this_page) != head); - - if (p_offset) - return page; - } - -out: - unlock_page(page); - return NULL; -} - -/* - * Look for a page at index which is unlocked and not mapped - * yet - clustering for mmap write case. + * Look for a page at index that is suitable for clustering. */ STATIC unsigned int -xfs_probe_unmapped_page( - struct address_space *mapping, - pgoff_t index, - unsigned int pg_offset) +xfs_probe_page( + struct page *page, + unsigned int pg_offset, + int mapped) { - struct page *page; int ret = 0; - page = find_trylock_page(mapping, index); - if (!page) - return 0; if (PageWriteback(page)) - goto out; + return 0; if (page->mapping && PageDirty(page)) { if (page_has_buffers(page)) { @@ -357,79 +487,101 @@ xfs_probe_unmapped_page( bh = head = page_buffers(page); do { - if (buffer_mapped(bh) || !buffer_uptodate(bh)) + if (!buffer_uptodate(bh)) + break; + if (mapped != buffer_mapped(bh)) break; ret += bh->b_size; if (ret >= pg_offset) break; } while ((bh = bh->b_this_page) != head); } else - ret = PAGE_CACHE_SIZE; + ret = mapped ? 0 : PAGE_CACHE_SIZE; } -out: - unlock_page(page); return ret; } -STATIC unsigned int -xfs_probe_unmapped_cluster( +STATIC size_t +xfs_probe_cluster( struct inode *inode, struct page *startpage, struct buffer_head *bh, - struct buffer_head *head) + struct buffer_head *head, + int mapped) { + struct pagevec pvec; pgoff_t tindex, tlast, tloff; - unsigned int pg_offset, len, total = 0; - struct address_space *mapping = inode->i_mapping; + size_t total = 0; + int done = 0, i; /* First sum forwards in this page */ do { - if (buffer_mapped(bh)) - break; + if (mapped != buffer_mapped(bh)) + return total; total += bh->b_size; } while ((bh = bh->b_this_page) != head); - /* If we reached the end of the page, sum forwards in - * following pages. - */ - if (bh == head) { - tlast = i_size_read(inode) >> PAGE_CACHE_SHIFT; - /* Prune this back to avoid pathological behavior */ - tloff = min(tlast, startpage->index + 64); - for (tindex = startpage->index + 1; tindex < tloff; tindex++) { - len = xfs_probe_unmapped_page(mapping, tindex, - PAGE_CACHE_SIZE); - if (!len) - return total; + /* if we reached the end of the page, sum forwards in following pages */ + tlast = i_size_read(inode) >> PAGE_CACHE_SHIFT; + tindex = startpage->index + 1; + + /* Prune this back to avoid pathological behavior */ + tloff = min(tlast, startpage->index + 64); + + pagevec_init(&pvec, 0); + while (!done && tindex <= tloff) { + unsigned len = min_t(pgoff_t, PAGEVEC_SIZE, tlast - tindex + 1); + + if (!pagevec_lookup(&pvec, inode->i_mapping, tindex, len)) + break; + + for (i = 0; i < pagevec_count(&pvec); i++) { + struct page *page = pvec.pages[i]; + size_t pg_offset, len = 0; + + if (tindex == tlast) { + pg_offset = + i_size_read(inode) & (PAGE_CACHE_SIZE - 1); + if (!pg_offset) { + done = 1; + break; + } + } else + pg_offset = PAGE_CACHE_SIZE; + + if (page->index == tindex && !TestSetPageLocked(page)) { + len = xfs_probe_page(page, pg_offset, mapped); + unlock_page(page); + } + + if (!len) { + done = 1; + break; + } + total += len; + tindex++; } - if (tindex == tlast && - (pg_offset = i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) { - total += xfs_probe_unmapped_page(mapping, - tindex, pg_offset); - } + + pagevec_release(&pvec); + cond_resched(); } + return total; } /* - * Probe for a given page (index) in the inode and test if it is delayed - * and without unwritten buffers. Returns page locked and with an extra - * reference count. + * Test if a given page is suitable for writing as part of an unwritten + * or delayed allocate extent. */ -STATIC struct page * -xfs_probe_delalloc_page( - struct inode *inode, - pgoff_t index) +STATIC int +xfs_is_delayed_page( + struct page *page, + unsigned int type) { - struct page *page; - - page = find_trylock_page(inode->i_mapping, index); - if (!page) - return NULL; if (PageWriteback(page)) - goto out; + return 0; if (page->mapping && page_has_buffers(page)) { struct buffer_head *bh, *head; @@ -437,243 +589,156 @@ xfs_probe_delalloc_page( bh = head = page_buffers(page); do { - if (buffer_unwritten(bh)) { - acceptable = 0; + if (buffer_unwritten(bh)) + acceptable = (type == IOMAP_UNWRITTEN); + else if (buffer_delay(bh)) + acceptable = (type == IOMAP_DELAY); + else if (buffer_mapped(bh)) + acceptable = (type == 0); + else break; - } else if (buffer_delay(bh)) { - acceptable = 1; - } } while ((bh = bh->b_this_page) != head); if (acceptable) - return page; - } - -out: - unlock_page(page); - return NULL; -} - -STATIC int -xfs_map_unwritten( - struct inode *inode, - struct page *start_page, - struct buffer_head *head, - struct buffer_head *curr, - unsigned long p_offset, - int block_bits, - xfs_iomap_t *iomapp, - struct writeback_control *wbc, - int startio, - int all_bh) -{ - struct buffer_head *bh = curr; - xfs_iomap_t *tmp; - xfs_ioend_t *ioend; - loff_t offset; - unsigned long nblocks = 0; - - offset = start_page->index; - offset <<= PAGE_CACHE_SHIFT; - offset += p_offset; - - ioend = xfs_alloc_ioend(inode); - - /* First map forwards in the page consecutive buffers - * covering this unwritten extent - */ - do { - if (!buffer_unwritten(bh)) - break; - tmp = xfs_offset_to_map(start_page, iomapp, p_offset); - if (!tmp) - break; - xfs_map_at_offset(start_page, bh, p_offset, block_bits, iomapp); - set_buffer_unwritten_io(bh); - bh->b_private = ioend; - p_offset += bh->b_size; - nblocks++; - } while ((bh = bh->b_this_page) != head); - - atomic_add(nblocks, &ioend->io_remaining); - - /* If we reached the end of the page, map forwards in any - * following pages which are also covered by this extent. - */ - if (bh == head) { - struct address_space *mapping = inode->i_mapping; - pgoff_t tindex, tloff, tlast; - unsigned long bs; - unsigned int pg_offset, bbits = inode->i_blkbits; - struct page *page; - - tlast = i_size_read(inode) >> PAGE_CACHE_SHIFT; - tloff = (iomapp->iomap_offset + iomapp->iomap_bsize) >> PAGE_CACHE_SHIFT; - tloff = min(tlast, tloff); - for (tindex = start_page->index + 1; tindex < tloff; tindex++) { - page = xfs_probe_unwritten_page(mapping, - tindex, iomapp, ioend, - PAGE_CACHE_SIZE, &bs, bbits); - if (!page) - break; - nblocks += bs; - atomic_add(bs, &ioend->io_remaining); - xfs_convert_page(inode, page, iomapp, wbc, ioend, - startio, all_bh); - /* stop if converting the next page might add - * enough blocks that the corresponding byte - * count won't fit in our ulong page buf length */ - if (nblocks >= ((ULONG_MAX - PAGE_SIZE) >> block_bits)) - goto enough; - } - - if (tindex == tlast && - (pg_offset = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1)))) { - page = xfs_probe_unwritten_page(mapping, - tindex, iomapp, ioend, - pg_offset, &bs, bbits); - if (page) { - nblocks += bs; - atomic_add(bs, &ioend->io_remaining); - xfs_convert_page(inode, page, iomapp, wbc, ioend, - startio, all_bh); - if (nblocks >= ((ULONG_MAX - PAGE_SIZE) >> block_bits)) - goto enough; - } - } + return 1; } -enough: - ioend->io_size = (xfs_off_t)nblocks << block_bits; - ioend->io_offset = offset; - xfs_finish_ioend(ioend); return 0; } -STATIC void -xfs_submit_page( - struct page *page, - struct writeback_control *wbc, - struct buffer_head *bh_arr[], - int bh_count, - int probed_page, - int clear_dirty) -{ - struct buffer_head *bh; - int i; - - BUG_ON(PageWriteback(page)); - if (bh_count) - set_page_writeback(page); - if (clear_dirty) - clear_page_dirty(page); - unlock_page(page); - - if (bh_count) { - for (i = 0; i < bh_count; i++) { - bh = bh_arr[i]; - mark_buffer_async_write(bh); - if (buffer_unwritten(bh)) - set_buffer_unwritten_io(bh); - set_buffer_uptodate(bh); - clear_buffer_dirty(bh); - } - - for (i = 0; i < bh_count; i++) - submit_bh(WRITE, bh_arr[i]); - - if (probed_page && clear_dirty) - wbc->nr_to_write--; /* Wrote an "extra" page */ - } -} - /* * Allocate & map buffers for page given the extent map. Write it out. * except for the original page of a writepage, this is called on * delalloc/unwritten pages only, for the original page it is possible * that the page has no mapping at all. */ -STATIC void +STATIC int xfs_convert_page( struct inode *inode, struct page *page, - xfs_iomap_t *iomapp, + loff_t tindex, + xfs_iomap_t *mp, + xfs_ioend_t **ioendp, struct writeback_control *wbc, - void *private, int startio, int all_bh) { - struct buffer_head *bh_arr[MAX_BUF_PER_PAGE], *bh, *head; - xfs_iomap_t *mp = iomapp, *tmp; - unsigned long offset, end_offset; - int index = 0; + struct buffer_head *bh, *head; + xfs_off_t end_offset; + unsigned long p_offset; + unsigned int type; int bbits = inode->i_blkbits; int len, page_dirty; + int count = 0, done = 0, uptodate = 1; + xfs_off_t offset = page_offset(page); - end_offset = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1)); + if (page->index != tindex) + goto fail; + if (TestSetPageLocked(page)) + goto fail; + if (PageWriteback(page)) + goto fail_unlock_page; + if (page->mapping != inode->i_mapping) + goto fail_unlock_page; + if (!xfs_is_delayed_page(page, (*ioendp)->io_type)) + goto fail_unlock_page; /* * page_dirty is initially a count of buffers on the page before * EOF and is decrememted as we move each into a cleanable state. + * + * Derivation: + * + * End offset is the highest offset that this page should represent. + * If we are on the last page, (end_offset & (PAGE_CACHE_SIZE - 1)) + * will evaluate non-zero and be less than PAGE_CACHE_SIZE and + * hence give us the correct page_dirty count. On any other page, + * it will be zero and in that case we need page_dirty to be the + * count of buffers on the page. */ + end_offset = min_t(unsigned long long, + (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, + i_size_read(inode)); + len = 1 << inode->i_blkbits; - end_offset = max(end_offset, PAGE_CACHE_SIZE); - end_offset = roundup(end_offset, len); - page_dirty = end_offset / len; + p_offset = min_t(unsigned long, end_offset & (PAGE_CACHE_SIZE - 1), + PAGE_CACHE_SIZE); + p_offset = p_offset ? roundup(p_offset, len) : PAGE_CACHE_SIZE; + page_dirty = p_offset / len; - offset = 0; bh = head = page_buffers(page); do { if (offset >= end_offset) break; - if (!(PageUptodate(page) || buffer_uptodate(bh))) + if (!buffer_uptodate(bh)) + uptodate = 0; + if (!(PageUptodate(page) || buffer_uptodate(bh))) { + done = 1; continue; - if (buffer_mapped(bh) && all_bh && - !(buffer_unwritten(bh) || buffer_delay(bh))) { + } + + if (buffer_unwritten(bh) || buffer_delay(bh)) { + if (buffer_unwritten(bh)) + type = IOMAP_UNWRITTEN; + else + type = IOMAP_DELAY; + + if (!xfs_iomap_valid(mp, offset)) { + done = 1; + continue; + } + + ASSERT(!(mp->iomap_flags & IOMAP_HOLE)); + ASSERT(!(mp->iomap_flags & IOMAP_DELAY)); + + xfs_map_at_offset(bh, offset, bbits, mp); if (startio) { + xfs_add_to_ioend(inode, bh, offset, + type, ioendp, done); + } else { + set_buffer_dirty(bh); + unlock_buffer(bh); + mark_buffer_dirty(bh); + } + page_dirty--; + count++; + } else { + type = 0; + if (buffer_mapped(bh) && all_bh && startio) { lock_buffer(bh); - bh_arr[index++] = bh; + xfs_add_to_ioend(inode, bh, offset, + type, ioendp, done); + count++; page_dirty--; + } else { + done = 1; } - continue; } - tmp = xfs_offset_to_map(page, mp, offset); - if (!tmp) - continue; - ASSERT(!(tmp->iomap_flags & IOMAP_HOLE)); - ASSERT(!(tmp->iomap_flags & IOMAP_DELAY)); + } while (offset += len, (bh = bh->b_this_page) != head); - /* If this is a new unwritten extent buffer (i.e. one - * that we haven't passed in private data for, we must - * now map this buffer too. - */ - if (buffer_unwritten(bh) && !bh->b_end_io) { - ASSERT(tmp->iomap_flags & IOMAP_UNWRITTEN); - xfs_map_unwritten(inode, page, head, bh, offset, - bbits, tmp, wbc, startio, all_bh); - } else if (! (buffer_unwritten(bh) && buffer_locked(bh))) { - xfs_map_at_offset(page, bh, offset, bbits, tmp); - if (buffer_unwritten(bh)) { - set_buffer_unwritten_io(bh); - bh->b_private = private; - ASSERT(private); + if (uptodate && bh == head) + SetPageUptodate(page); + + if (startio) { + if (count) { + struct backing_dev_info *bdi; + + bdi = inode->i_mapping->backing_dev_info; + if (bdi_write_congested(bdi)) { + wbc->encountered_congestion = 1; + done = 1; + } else if (--wbc->nr_to_write <= 0) { + done = 1; } } - if (startio) { - bh_arr[index++] = bh; - } else { - set_buffer_dirty(bh); - unlock_buffer(bh); - mark_buffer_dirty(bh); - } - page_dirty--; - } while (offset += len, (bh = bh->b_this_page) != head); - - if (startio && index) { - xfs_submit_page(page, wbc, bh_arr, index, 1, !page_dirty); - } else { - unlock_page(page); + xfs_start_page_writeback(page, wbc, !page_dirty, count); } + + return done; + fail_unlock_page: + unlock_page(page); + fail: + return 1; } /* @@ -685,19 +750,31 @@ xfs_cluster_write( struct inode *inode, pgoff_t tindex, xfs_iomap_t *iomapp, + xfs_ioend_t **ioendp, struct writeback_control *wbc, int startio, int all_bh, pgoff_t tlast) { - struct page *page; + struct pagevec pvec; + int done = 0, i; - for (; tindex <= tlast; tindex++) { - page = xfs_probe_delalloc_page(inode, tindex); - if (!page) + pagevec_init(&pvec, 0); + while (!done && tindex <= tlast) { + unsigned len = min_t(pgoff_t, PAGEVEC_SIZE, tlast - tindex + 1); + + if (!pagevec_lookup(&pvec, inode->i_mapping, tindex, len)) break; - xfs_convert_page(inode, page, iomapp, wbc, NULL, - startio, all_bh); + + for (i = 0; i < pagevec_count(&pvec); i++) { + done = xfs_convert_page(inode, pvec.pages[i], tindex++, + iomapp, ioendp, wbc, startio, all_bh); + if (done) + break; + } + + pagevec_release(&pvec); + cond_resched(); } } @@ -728,18 +805,22 @@ xfs_page_state_convert( int startio, int unmapped) /* also implies page uptodate */ { - struct buffer_head *bh_arr[MAX_BUF_PER_PAGE], *bh, *head; - xfs_iomap_t *iomp, iomap; + struct buffer_head *bh, *head; + xfs_iomap_t iomap; + xfs_ioend_t *ioend = NULL, *iohead = NULL; loff_t offset; unsigned long p_offset = 0; + unsigned int type; __uint64_t end_offset; pgoff_t end_index, last_index, tlast; - int len, err, i, cnt = 0, uptodate = 1; - int flags; - int page_dirty; + ssize_t size, len; + int flags, err, iomap_valid = 0, uptodate = 1; + int page_dirty, count = 0, trylock_flag = 0; + int all_bh = unmapped; /* wait for other IO threads? */ - flags = (startio && wbc->sync_mode != WB_SYNC_NONE) ? 0 : BMAPI_TRYLOCK; + if (startio && (wbc->sync_mode == WB_SYNC_NONE && wbc->nonblocking)) + trylock_flag |= BMAPI_TRYLOCK; /* Is this page beyond the end of the file? */ offset = i_size_read(inode); @@ -754,161 +835,173 @@ xfs_page_state_convert( } } - end_offset = min_t(unsigned long long, - (loff_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset); - offset = (loff_t)page->index << PAGE_CACHE_SHIFT; - /* * page_dirty is initially a count of buffers on the page before * EOF and is decrememted as we move each into a cleanable state. - */ + * + * Derivation: + * + * End offset is the highest offset that this page should represent. + * If we are on the last page, (end_offset & (PAGE_CACHE_SIZE - 1)) + * will evaluate non-zero and be less than PAGE_CACHE_SIZE and + * hence give us the correct page_dirty count. On any other page, + * it will be zero and in that case we need page_dirty to be the + * count of buffers on the page. + */ + end_offset = min_t(unsigned long long, + (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset); len = 1 << inode->i_blkbits; - p_offset = max(p_offset, PAGE_CACHE_SIZE); - p_offset = roundup(p_offset, len); + p_offset = min_t(unsigned long, end_offset & (PAGE_CACHE_SIZE - 1), + PAGE_CACHE_SIZE); + p_offset = p_offset ? roundup(p_offset, len) : PAGE_CACHE_SIZE; page_dirty = p_offset / len; - iomp = NULL; - p_offset = 0; bh = head = page_buffers(page); + offset = page_offset(page); + flags = -1; + type = 0; + + /* TODO: cleanup count and page_dirty */ do { if (offset >= end_offset) break; if (!buffer_uptodate(bh)) uptodate = 0; - if (!(PageUptodate(page) || buffer_uptodate(bh)) && !startio) + if (!(PageUptodate(page) || buffer_uptodate(bh)) && !startio) { + /* + * the iomap is actually still valid, but the ioend + * isn't. shouldn't happen too often. + */ + iomap_valid = 0; continue; - - if (iomp) { - iomp = xfs_offset_to_map(page, &iomap, p_offset); } + if (iomap_valid) + iomap_valid = xfs_iomap_valid(&iomap, offset); + /* * First case, map an unwritten extent and prepare for * extent state conversion transaction on completion. - */ - if (buffer_unwritten(bh)) { - if (!startio) - continue; - if (!iomp) { - err = xfs_map_blocks(inode, offset, len, &iomap, - BMAPI_WRITE|BMAPI_IGNSTATE); - if (err) { - goto error; - } - iomp = xfs_offset_to_map(page, &iomap, - p_offset); + * + * Second case, allocate space for a delalloc buffer. + * We can return EAGAIN here in the release page case. + * + * Third case, an unmapped buffer was found, and we are + * in a path where we need to write the whole page out. + */ + if (buffer_unwritten(bh) || buffer_delay(bh) || + ((buffer_uptodate(bh) || PageUptodate(page)) && + !buffer_mapped(bh) && (unmapped || startio))) { + /* + * Make sure we don't use a read-only iomap + */ + if (flags == BMAPI_READ) + iomap_valid = 0; + + if (buffer_unwritten(bh)) { + type = IOMAP_UNWRITTEN; + flags = BMAPI_WRITE|BMAPI_IGNSTATE; + } else if (buffer_delay(bh)) { + type = IOMAP_DELAY; + flags = BMAPI_ALLOCATE; + if (!startio) + flags |= trylock_flag; + } else { + type = IOMAP_NEW; + flags = BMAPI_WRITE|BMAPI_MMAP; } - if (iomp) { - if (!bh->b_end_io) { - err = xfs_map_unwritten(inode, page, - head, bh, p_offset, - inode->i_blkbits, iomp, - wbc, startio, unmapped); - if (err) { - goto error; - } + + if (!iomap_valid) { + if (type == IOMAP_NEW) { + size = xfs_probe_cluster(inode, + page, bh, head, 0); } else { - set_bit(BH_Lock, &bh->b_state); + size = len; } - BUG_ON(!buffer_locked(bh)); - bh_arr[cnt++] = bh; - page_dirty--; - } - /* - * Second case, allocate space for a delalloc buffer. - * We can return EAGAIN here in the release page case. - */ - } else if (buffer_delay(bh)) { - if (!iomp) { - err = xfs_map_blocks(inode, offset, len, &iomap, - BMAPI_ALLOCATE | flags); - if (err) { + + err = xfs_map_blocks(inode, offset, size, + &iomap, flags); + if (err) goto error; - } - iomp = xfs_offset_to_map(page, &iomap, - p_offset); + iomap_valid = xfs_iomap_valid(&iomap, offset); } - if (iomp) { - xfs_map_at_offset(page, bh, p_offset, - inode->i_blkbits, iomp); + if (iomap_valid) { + xfs_map_at_offset(bh, offset, + inode->i_blkbits, &iomap); if (startio) { - bh_arr[cnt++] = bh; + xfs_add_to_ioend(inode, bh, offset, + type, &ioend, + !iomap_valid); } else { set_buffer_dirty(bh); unlock_buffer(bh); mark_buffer_dirty(bh); } page_dirty--; + count++; + } + } else if (buffer_uptodate(bh) && startio) { + /* + * we got here because the buffer is already mapped. + * That means it must already have extents allocated + * underneath it. Map the extent by reading it. + */ + if (!iomap_valid || type != 0) { + flags = BMAPI_READ; + size = xfs_probe_cluster(inode, page, bh, + head, 1); + err = xfs_map_blocks(inode, offset, size, + &iomap, flags); + if (err) + goto error; + iomap_valid = xfs_iomap_valid(&iomap, offset); } - } else if ((buffer_uptodate(bh) || PageUptodate(page)) && - (unmapped || startio)) { - if (!buffer_mapped(bh)) { - int size; - - /* - * Getting here implies an unmapped buffer - * was found, and we are in a path where we - * need to write the whole page out. - */ - if (!iomp) { - size = xfs_probe_unmapped_cluster( - inode, page, bh, head); - err = xfs_map_blocks(inode, offset, - size, &iomap, - BMAPI_WRITE|BMAPI_MMAP); - if (err) { - goto error; - } - iomp = xfs_offset_to_map(page, &iomap, - p_offset); - } - if (iomp) { - xfs_map_at_offset(page, - bh, p_offset, - inode->i_blkbits, iomp); - if (startio) { - bh_arr[cnt++] = bh; - } else { - set_buffer_dirty(bh); - unlock_buffer(bh); - mark_buffer_dirty(bh); - } - page_dirty--; - } - } else if (startio) { - if (buffer_uptodate(bh) && - !test_and_set_bit(BH_Lock, &bh->b_state)) { - bh_arr[cnt++] = bh; - page_dirty--; - } + type = 0; + if (!test_and_set_bit(BH_Lock, &bh->b_state)) { + ASSERT(buffer_mapped(bh)); + if (iomap_valid) + all_bh = 1; + xfs_add_to_ioend(inode, bh, offset, type, + &ioend, !iomap_valid); + page_dirty--; + count++; + } else { + iomap_valid = 0; } + } else if ((buffer_uptodate(bh) || PageUptodate(page)) && + (unmapped || startio)) { + iomap_valid = 0; } - } while (offset += len, p_offset += len, - ((bh = bh->b_this_page) != head)); + + if (!iohead) + iohead = ioend; + + } while (offset += len, ((bh = bh->b_this_page) != head)); if (uptodate && bh == head) SetPageUptodate(page); - if (startio) { - xfs_submit_page(page, wbc, bh_arr, cnt, 0, !page_dirty); - } + if (startio) + xfs_start_page_writeback(page, wbc, 1, count); - if (iomp) { - offset = (iomp->iomap_offset + iomp->iomap_bsize - 1) >> + if (ioend && iomap_valid) { + offset = (iomap.iomap_offset + iomap.iomap_bsize - 1) >> PAGE_CACHE_SHIFT; tlast = min_t(pgoff_t, offset, last_index); - xfs_cluster_write(inode, page->index + 1, iomp, wbc, - startio, unmapped, tlast); + xfs_cluster_write(inode, page->index + 1, &iomap, &ioend, + wbc, startio, all_bh, tlast); } + if (iohead) + xfs_submit_ioend(iohead); + return page_dirty; error: - for (i = 0; i < cnt; i++) { - unlock_buffer(bh_arr[i]); - } + if (iohead) + xfs_cancel_ioend(iohead); /* * If it's delalloc and we have nowhere to put it, @@ -916,9 +1009,8 @@ error: * us to try again. */ if (err != -EAGAIN) { - if (!unmapped) { + if (!unmapped) block_invalidatepage(page, 0); - } ClearPageUptodate(page); } return err; @@ -982,7 +1074,7 @@ __linvfs_get_block( } /* If this is a realtime file, data might be on a new device */ - bh_result->b_bdev = iomap.iomap_target->pbr_bdev; + bh_result->b_bdev = iomap.iomap_target->bt_bdev; /* If we previously allocated a block out beyond eof and * we are now coming back to use it then we will need to @@ -1094,10 +1186,10 @@ linvfs_direct_IO( if (error) return -error; - iocb->private = xfs_alloc_ioend(inode); + iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN); ret = blockdev_direct_IO_own_locking(rw, iocb, inode, - iomap.iomap_target->pbr_bdev, + iomap.iomap_target->bt_bdev, iov, offset, nr_segs, linvfs_get_blocks_direct, linvfs_end_io_direct); diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 4720758a9ad..55339dd5a30 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h @@ -23,14 +23,24 @@ extern mempool_t *xfs_ioend_pool; typedef void (*xfs_ioend_func_t)(void *); +/* + * xfs_ioend struct manages large extent writes for XFS. + * It can manage several multi-page bio's at once. + */ typedef struct xfs_ioend { + struct xfs_ioend *io_list; /* next ioend in chain */ + unsigned int io_type; /* delalloc / unwritten */ unsigned int io_uptodate; /* I/O status register */ atomic_t io_remaining; /* hold count */ struct vnode *io_vnode; /* file being written to */ struct buffer_head *io_buffer_head;/* buffer linked list head */ + struct buffer_head *io_buffer_tail;/* buffer linked list tail */ size_t io_size; /* size of the extent */ xfs_off_t io_offset; /* offset in the file */ struct work_struct io_work; /* xfsdatad work queue */ } xfs_ioend_t; +extern struct address_space_operations linvfs_aops; +extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int); + #endif /* __XFS_IOPS_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 6fe21d2b884..e44b7c1a3a3 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -31,76 +31,77 @@ #include <linux/kthread.h> #include "xfs_linux.h" -STATIC kmem_cache_t *pagebuf_zone; -STATIC kmem_shaker_t pagebuf_shake; +STATIC kmem_zone_t *xfs_buf_zone; +STATIC kmem_shaker_t xfs_buf_shake; +STATIC int xfsbufd(void *); STATIC int xfsbufd_wakeup(int, gfp_t); -STATIC void pagebuf_delwri_queue(xfs_buf_t *, int); +STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int); STATIC struct workqueue_struct *xfslogd_workqueue; struct workqueue_struct *xfsdatad_workqueue; -#ifdef PAGEBUF_TRACE +#ifdef XFS_BUF_TRACE void -pagebuf_trace( - xfs_buf_t *pb, +xfs_buf_trace( + xfs_buf_t *bp, char *id, void *data, void *ra) { - ktrace_enter(pagebuf_trace_buf, - pb, id, - (void *)(unsigned long)pb->pb_flags, - (void *)(unsigned long)pb->pb_hold.counter, - (void *)(unsigned long)pb->pb_sema.count.counter, + ktrace_enter(xfs_buf_trace_buf, + bp, id, + (void *)(unsigned long)bp->b_flags, + (void *)(unsigned long)bp->b_hold.counter, + (void *)(unsigned long)bp->b_sema.count.counter, (void *)current, data, ra, - (void *)(unsigned long)((pb->pb_file_offset>>32) & 0xffffffff), - (void *)(unsigned long)(pb->pb_file_offset & 0xffffffff), - (void *)(unsigned long)pb->pb_buffer_length, + (void *)(unsigned long)((bp->b_file_offset>>32) & 0xffffffff), + (void *)(unsigned long)(bp->b_file_offset & 0xffffffff), + (void *)(unsigned long)bp->b_buffer_length, NULL, NULL, NULL, NULL, NULL); } -ktrace_t *pagebuf_trace_buf; -#define PAGEBUF_TRACE_SIZE 4096 -#define PB_TRACE(pb, id, data) \ - pagebuf_trace(pb, id, (void *)data, (void *)__builtin_return_address(0)) +ktrace_t *xfs_buf_trace_buf; +#define XFS_BUF_TRACE_SIZE 4096 +#define XB_TRACE(bp, id, data) \ + xfs_buf_trace(bp, id, (void *)data, (void *)__builtin_return_address(0)) #else -#define PB_TRACE(pb, id, data) do { } while (0) +#define XB_TRACE(bp, id, data) do { } while (0) #endif -#ifdef PAGEBUF_LOCK_TRACKING -# define PB_SET_OWNER(pb) ((pb)->pb_last_holder = current->pid) -# define PB_CLEAR_OWNER(pb) ((pb)->pb_last_holder = -1) -# define PB_GET_OWNER(pb) ((pb)->pb_last_holder) +#ifdef XFS_BUF_LOCK_TRACKING +# define XB_SET_OWNER(bp) ((bp)->b_last_holder = current->pid) +# define XB_CLEAR_OWNER(bp) ((bp)->b_last_holder = -1) +# define XB_GET_OWNER(bp) ((bp)->b_last_holder) #else -# define PB_SET_OWNER(pb) do { } while (0) -# define PB_CLEAR_OWNER(pb) do { } while (0) -# define PB_GET_OWNER(pb) do { } while (0) +# define XB_SET_OWNER(bp) do { } while (0) +# define XB_CLEAR_OWNER(bp) do { } while (0) +# define XB_GET_OWNER(bp) do { } while (0) #endif -#define pb_to_gfp(flags) \ - ((((flags) & PBF_READ_AHEAD) ? __GFP_NORETRY : \ - ((flags) & PBF_DONT_BLOCK) ? GFP_NOFS : GFP_KERNEL) | __GFP_NOWARN) +#define xb_to_gfp(flags) \ + ((((flags) & XBF_READ_AHEAD) ? __GFP_NORETRY : \ + ((flags) & XBF_DONT_BLOCK) ? GFP_NOFS : GFP_KERNEL) | __GFP_NOWARN) -#define pb_to_km(flags) \ - (((flags) & PBF_DONT_BLOCK) ? KM_NOFS : KM_SLEEP) +#define xb_to_km(flags) \ + (((flags) & XBF_DONT_BLOCK) ? KM_NOFS : KM_SLEEP) -#define pagebuf_allocate(flags) \ - kmem_zone_alloc(pagebuf_zone, pb_to_km(flags)) -#define pagebuf_deallocate(pb) \ - kmem_zone_free(pagebuf_zone, (pb)); +#define xfs_buf_allocate(flags) \ + kmem_zone_alloc(xfs_buf_zone, xb_to_km(flags)) +#define xfs_buf_deallocate(bp) \ + kmem_zone_free(xfs_buf_zone, (bp)); /* - * Page Region interfaces. + * Page Region interfaces. * - * For pages in filesystems where the blocksize is smaller than the - * pagesize, we use the page->private field (long) to hold a bitmap - * of uptodate regions within the page. + * For pages in filesystems where the blocksize is smaller than the + * pagesize, we use the page->private field (long) to hold a bitmap + * of uptodate regions within the page. * - * Each such region is "bytes per page / bits per long" bytes long. + * Each such region is "bytes per page / bits per long" bytes long. * - * NBPPR == number-of-bytes-per-page-region - * BTOPR == bytes-to-page-region (rounded up) - * BTOPRT == bytes-to-page-region-truncated (rounded down) + * NBPPR == number-of-bytes-per-page-region + * BTOPR == bytes-to-page-region (rounded up) + * BTOPRT == bytes-to-page-region-truncated (rounded down) */ #if (BITS_PER_LONG == 32) #define PRSHIFT (PAGE_CACHE_SHIFT - 5) /* (32 == 1<<5) */ @@ -159,7 +160,7 @@ test_page_region( } /* - * Mapping of multi-page buffers into contiguous virtual space + * Mapping of multi-page buffers into contiguous virtual space */ typedef struct a_list { @@ -172,7 +173,7 @@ STATIC int as_list_len; STATIC DEFINE_SPINLOCK(as_lock); /* - * Try to batch vunmaps because they are costly. + * Try to batch vunmaps because they are costly. */ STATIC void free_address( @@ -215,83 +216,83 @@ purge_addresses(void) } /* - * Internal pagebuf object manipulation + * Internal xfs_buf_t object manipulation */ STATIC void -_pagebuf_initialize( - xfs_buf_t *pb, +_xfs_buf_initialize( + xfs_buf_t *bp, xfs_buftarg_t *target, - loff_t range_base, + xfs_off_t range_base, size_t range_length, - page_buf_flags_t flags) + xfs_buf_flags_t flags) { /* - * We don't want certain flags to appear in pb->pb_flags. + * We don't want certain flags to appear in b_flags. */ - flags &= ~(PBF_LOCK|PBF_MAPPED|PBF_DONT_BLOCK|PBF_READ_AHEAD); - - memset(pb, 0, sizeof(xfs_buf_t)); - atomic_set(&pb->pb_hold, 1); - init_MUTEX_LOCKED(&pb->pb_iodonesema); - INIT_LIST_HEAD(&pb->pb_list); - INIT_LIST_HEAD(&pb->pb_hash_list); - init_MUTEX_LOCKED(&pb->pb_sema); /* held, no waiters */ - PB_SET_OWNER(pb); - pb->pb_target = target; - pb->pb_file_offset = range_base; + flags &= ~(XBF_LOCK|XBF_MAPPED|XBF_DONT_BLOCK|XBF_READ_AHEAD); + + memset(bp, 0, sizeof(xfs_buf_t)); + atomic_set(&bp->b_hold, 1); + init_MUTEX_LOCKED(&bp->b_iodonesema); + INIT_LIST_HEAD(&bp->b_list); + INIT_LIST_HEAD(&bp->b_hash_list); + init_MUTEX_LOCKED(&bp->b_sema); /* held, no waiters */ + XB_SET_OWNER(bp); + bp->b_target = target; + bp->b_file_offset = range_base; /* * Set buffer_length and count_desired to the same value initially. * I/O routines should use count_desired, which will be the same in * most cases but may be reset (e.g. XFS recovery). */ - pb->pb_buffer_length = pb->pb_count_desired = range_length; - pb->pb_flags = flags; - pb->pb_bn = XFS_BUF_DADDR_NULL; - atomic_set(&pb->pb_pin_count, 0); - init_waitqueue_head(&pb->pb_waiters); - - XFS_STATS_INC(pb_create); - PB_TRACE(pb, "initialize", target); + bp->b_buffer_length = bp->b_count_desired = range_length; + bp->b_flags = flags; + bp->b_bn = XFS_BUF_DADDR_NULL; + atomic_set(&bp->b_pin_count, 0); + init_waitqueue_head(&bp->b_waiters); + + XFS_STATS_INC(xb_create); + XB_TRACE(bp, "initialize", target); } /* - * Allocate a page array capable of holding a specified number - * of pages, and point the page buf at it. + * Allocate a page array capable of holding a specified number + * of pages, and point the page buf at it. */ STATIC int -_pagebuf_get_pages( - xfs_buf_t *pb, +_xfs_buf_get_pages( + xfs_buf_t *bp, int page_count, - page_buf_flags_t flags) + xfs_buf_flags_t flags) { /* Make sure that we have a page list */ - if (pb->pb_pages == NULL) { - pb->pb_offset = page_buf_poff(pb->pb_file_offset); - pb->pb_page_count = page_count; - if (page_count <= PB_PAGES) { - pb->pb_pages = pb->pb_page_array; + if (bp->b_pages == NULL) { + bp->b_offset = xfs_buf_poff(bp->b_file_offset); + bp->b_page_count = page_count; + if (page_count <= XB_PAGES) { + bp->b_pages = bp->b_page_array; } else { - pb->pb_pages = kmem_alloc(sizeof(struct page *) * - page_count, pb_to_km(flags)); - if (pb->pb_pages == NULL) + bp->b_pages = kmem_alloc(sizeof(struct page *) * + page_count, xb_to_km(flags)); + if (bp->b_pages == NULL) return -ENOMEM; } - memset(pb->pb_pages, 0, sizeof(struct page *) * page_count); + memset(bp->b_pages, 0, sizeof(struct page *) * page_count); } return 0; } /* - * Frees pb_pages if it was malloced. + * Frees b_pages if it was allocated. */ STATIC void -_pagebuf_free_pages( +_xfs_buf_free_pages( xfs_buf_t *bp) { - if (bp->pb_pages != bp->pb_page_array) { - kmem_free(bp->pb_pages, - bp->pb_page_count * sizeof(struct page *)); + if (bp->b_pages != bp->b_page_array) { + kmem_free(bp->b_pages, + bp->b_page_count * sizeof(struct page *)); } } @@ -299,79 +300,79 @@ _pagebuf_free_pages( * Releases the specified buffer. * * The modification state of any associated pages is left unchanged. - * The buffer most not be on any hash - use pagebuf_rele instead for + * The buffer most not be on any hash - use xfs_buf_rele instead for * hashed and refcounted buffers */ void -pagebuf_free( +xfs_buf_free( xfs_buf_t *bp) { - PB_TRACE(bp, "free", 0); + XB_TRACE(bp, "free", 0); - ASSERT(list_empty(&bp->pb_hash_list)); + ASSERT(list_empty(&bp->b_hash_list)); - if (bp->pb_flags & _PBF_PAGE_CACHE) { + if (bp->b_flags & _XBF_PAGE_CACHE) { uint i; - if ((bp->pb_flags & PBF_MAPPED) && (bp->pb_page_count > 1)) - free_address(bp->pb_addr - bp->pb_offset); + if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1)) + free_address(bp->b_addr - bp->b_offset); - for (i = 0; i < bp->pb_page_count; i++) - page_cache_release(bp->pb_pages[i]); - _pagebuf_free_pages(bp); - } else if (bp->pb_flags & _PBF_KMEM_ALLOC) { + for (i = 0; i < bp->b_page_count; i++) + page_cache_release(bp->b_pages[i]); + _xfs_buf_free_pages(bp); + } else if (bp->b_flags & _XBF_KMEM_ALLOC) { /* - * XXX(hch): bp->pb_count_desired might be incorrect (see - * pagebuf_associate_memory for details), but fortunately + * XXX(hch): bp->b_count_desired might be incorrect (see + * xfs_buf_associate_memory for details), but fortunately * the Linux version of kmem_free ignores the len argument.. */ - kmem_free(bp->pb_addr, bp->pb_count_desired); - _pagebuf_free_pages(bp); + kmem_free(bp->b_addr, bp->b_count_desired); + _xfs_buf_free_pages(bp); } - pagebuf_deallocate(bp); + xfs_buf_deallocate(bp); } /* * Finds all pages for buffer in question and builds it's page list. */ STATIC int -_pagebuf_lookup_pages( +_xfs_buf_lookup_pages( xfs_buf_t *bp, uint flags) { - struct address_space *mapping = bp->pb_target->pbr_mapping; - size_t blocksize = bp->pb_target->pbr_bsize; - size_t size = bp->pb_count_desired; + struct address_space *mapping = bp->b_target->bt_mapping; + size_t blocksize = bp->b_target->bt_bsize; + size_t size = bp->b_count_desired; size_t nbytes, offset; - gfp_t gfp_mask = pb_to_gfp(flags); + gfp_t gfp_mask = xb_to_gfp(flags); unsigned short page_count, i; pgoff_t first; - loff_t end; + xfs_off_t end; int error; - end = bp->pb_file_offset + bp->pb_buffer_length; - page_count = page_buf_btoc(end) - page_buf_btoct(bp->pb_file_offset); + end = bp->b_file_offset + bp->b_buffer_length; + page_count = xfs_buf_btoc(end) - xfs_buf_btoct(bp->b_file_offset); - error = _pagebuf_get_pages(bp, page_count, flags); + error = _xfs_buf_get_pages(bp, page_count, flags); if (unlikely(error)) return error; - bp->pb_flags |= _PBF_PAGE_CACHE; + bp->b_flags |= _XBF_PAGE_CACHE; - offset = bp->pb_offset; - first = bp->pb_file_offset >> PAGE_CACHE_SHIFT; + offset = bp->b_offset; + first = bp->b_file_offset >> PAGE_CACHE_SHIFT; - for (i = 0; i < bp->pb_page_count; i++) { + for (i = 0; i < bp->b_page_count; i++) { struct page *page; uint retries = 0; retry: page = find_or_create_page(mapping, first + i, gfp_mask); if (unlikely(page == NULL)) { - if (flags & PBF_READ_AHEAD) { - bp->pb_page_count = i; - for (i = 0; i < bp->pb_page_count; i++) - unlock_page(bp->pb_pages[i]); + if (flags & XBF_READ_AHEAD) { + bp->b_page_count = i; + for (i = 0; i < bp->b_page_count; i++) + unlock_page(bp->b_pages[i]); return -ENOMEM; } @@ -387,13 +388,13 @@ _pagebuf_lookup_pages( "deadlock in %s (mode:0x%x)\n", __FUNCTION__, gfp_mask); - XFS_STATS_INC(pb_page_retries); + XFS_STATS_INC(xb_page_retries); xfsbufd_wakeup(0, gfp_mask); blk_congestion_wait(WRITE, HZ/50); goto retry; } - XFS_STATS_INC(pb_page_found); + XFS_STATS_INC(xb_page_found); nbytes = min_t(size_t, size, PAGE_CACHE_SIZE - offset); size -= nbytes; @@ -401,27 +402,27 @@ _pagebuf_lookup_pages( if (!PageUptodate(page)) { page_count--; if (blocksize >= PAGE_CACHE_SIZE) { - if (flags & PBF_READ) - bp->pb_locked = 1; + if (flags & XBF_READ) + bp->b_locked = 1; } else if (!PagePrivate(page)) { if (test_page_region(page, offset, nbytes)) page_count++; } } - bp->pb_pages[i] = page; + bp->b_pages[i] = page; offset = 0; } - if (!bp->pb_locked) { - for (i = 0; i < bp->pb_page_count; i++) - unlock_page(bp->pb_pages[i]); + if (!bp->b_locked) { + for (i = 0; i < bp->b_page_count; i++) + unlock_page(bp->b_pages[i]); } - if (page_count == bp->pb_page_count) - bp->pb_flags |= PBF_DONE; + if (page_count == bp->b_page_count) + bp->b_flags |= XBF_DONE; - PB_TRACE(bp, "lookup_pages", (long)page_count); + XB_TRACE(bp, "lookup_pages", (long)page_count); return error; } @@ -429,23 +430,23 @@ _pagebuf_lookup_pages( * Map buffer into kernel address-space if nessecary. */ STATIC int -_pagebuf_map_pages( +_xfs_buf_map_pages( xfs_buf_t *bp, uint flags) { /* A single page buffer is always mappable */ - if (bp->pb_page_count == 1) { - bp->pb_addr = page_address(bp->pb_pages[0]) + bp->pb_offset; - bp->pb_flags |= PBF_MAPPED; - } else if (flags & PBF_MAPPED) { + if (bp->b_page_count == 1) { + bp->b_addr = page_address(bp->b_pages[0]) + bp->b_offset; + bp->b_flags |= XBF_MAPPED; + } else if (flags & XBF_MAPPED) { if (as_list_len > 64) purge_addresses(); - bp->pb_addr = vmap(bp->pb_pages, bp->pb_page_count, - VM_MAP, PAGE_KERNEL); - if (unlikely(bp->pb_addr == NULL)) + bp->b_addr = vmap(bp->b_pages, bp->b_page_count, + VM_MAP, PAGE_KERNEL); + if (unlikely(bp->b_addr == NULL)) return -ENOMEM; - bp->pb_addr += bp->pb_offset; - bp->pb_flags |= PBF_MAPPED; + bp->b_addr += bp->b_offset; + bp->b_flags |= XBF_MAPPED; } return 0; @@ -456,9 +457,7 @@ _pagebuf_map_pages( */ /* - * _pagebuf_find - * - * Looks up, and creates if absent, a lockable buffer for + * Look up, and creates if absent, a lockable buffer for * a given range of an inode. The buffer is returned * locked. If other overlapping buffers exist, they are * released before the new buffer is created and locked, @@ -466,55 +465,55 @@ _pagebuf_map_pages( * are unlocked. No I/O is implied by this call. */ xfs_buf_t * -_pagebuf_find( +_xfs_buf_find( xfs_buftarg_t *btp, /* block device target */ - loff_t ioff, /* starting offset of range */ + xfs_off_t ioff, /* starting offset of range */ size_t isize, /* length of range */ - page_buf_flags_t flags, /* PBF_TRYLOCK */ - xfs_buf_t *new_pb)/* newly allocated buffer */ + xfs_buf_flags_t flags, + xfs_buf_t *new_bp) { - loff_t range_base; + xfs_off_t range_base; size_t range_length; xfs_bufhash_t *hash; - xfs_buf_t *pb, *n; + xfs_buf_t *bp, *n; range_base = (ioff << BBSHIFT); range_length = (isize << BBSHIFT); /* Check for IOs smaller than the sector size / not sector aligned */ - ASSERT(!(range_length < (1 << btp->pbr_sshift))); - ASSERT(!(range_base & (loff_t)btp->pbr_smask)); + ASSERT(!(range_length < (1 << btp->bt_sshift))); + ASSERT(!(range_base & (xfs_off_t)btp->bt_smask)); hash = &btp->bt_hash[hash_long((unsigned long)ioff, btp->bt_hashshift)]; spin_lock(&hash->bh_lock); - list_for_each_entry_safe(pb, n, &hash->bh_list, pb_hash_list) { - ASSERT(btp == pb->pb_target); - if (pb->pb_file_offset == range_base && - pb->pb_buffer_length == range_length) { + list_for_each_entry_safe(bp, n, &hash->bh_list, b_hash_list) { + ASSERT(btp == bp->b_target); + if (bp->b_file_offset == range_base && + bp->b_buffer_length == range_length) { /* - * If we look at something bring it to the + * If we look at something, bring it to the * front of the list for next time. */ - atomic_inc(&pb->pb_hold); - list_move(&pb->pb_hash_list, &hash->bh_list); + atomic_inc(&bp->b_hold); + list_move(&bp->b_hash_list, &hash->bh_list); goto found; } } /* No match found */ - if (new_pb) { - _pagebuf_initialize(new_pb, btp, range_base, + if (new_bp) { + _xfs_buf_initialize(new_bp, btp, range_base, range_length, flags); - new_pb->pb_hash = hash; - list_add(&new_pb->pb_hash_list, &hash->bh_list); + new_bp->b_hash = hash; + list_add(&new_bp->b_hash_list, &hash->bh_list); } else { - XFS_STATS_INC(pb_miss_locked); + XFS_STATS_INC(xb_miss_locked); } spin_unlock(&hash->bh_lock); - return new_pb; + return new_bp; found: spin_unlock(&hash->bh_lock); @@ -523,74 +522,72 @@ found: * if this does not work then we need to drop the * spinlock and do a hard attempt on the semaphore. */ - if (down_trylock(&pb->pb_sema)) { - if (!(flags & PBF_TRYLOCK)) { + if (down_trylock(&bp->b_sema)) { + if (!(flags & XBF_TRYLOCK)) { /* wait for buffer ownership */ - PB_TRACE(pb, "get_lock", 0); - pagebuf_lock(pb); - XFS_STATS_INC(pb_get_locked_waited); + XB_TRACE(bp, "get_lock", 0); + xfs_buf_lock(bp); + XFS_STATS_INC(xb_get_locked_waited); } else { /* We asked for a trylock and failed, no need * to look at file offset and length here, we - * know that this pagebuf at least overlaps our - * pagebuf and is locked, therefore our buffer - * either does not exist, or is this buffer + * know that this buffer at least overlaps our + * buffer and is locked, therefore our buffer + * either does not exist, or is this buffer. */ - - pagebuf_rele(pb); - XFS_STATS_INC(pb_busy_locked); - return (NULL); + xfs_buf_rele(bp); + XFS_STATS_INC(xb_busy_locked); + return NULL; } } else { /* trylock worked */ - PB_SET_OWNER(pb); + XB_SET_OWNER(bp); } - if (pb->pb_flags & PBF_STALE) { - ASSERT((pb->pb_flags & _PBF_DELWRI_Q) == 0); - pb->pb_flags &= PBF_MAPPED; + if (bp->b_flags & XBF_STALE) { + ASSERT((bp->b_flags & _XBF_DELWRI_Q) == 0); + bp->b_flags &= XBF_MAPPED; } - PB_TRACE(pb, "got_lock", 0); - XFS_STATS_INC(pb_get_locked); - return (pb); + XB_TRACE(bp, "got_lock", 0); + XFS_STATS_INC(xb_get_locked); + return bp; } /* - * xfs_buf_get_flags assembles a buffer covering the specified range. - * + * Assembles a buffer covering the specified range. * Storage in memory for all portions of the buffer will be allocated, * although backing storage may not be. */ xfs_buf_t * -xfs_buf_get_flags( /* allocate a buffer */ +xfs_buf_get_flags( xfs_buftarg_t *target,/* target for buffer */ - loff_t ioff, /* starting offset of range */ + xfs_off_t ioff, /* starting offset of range */ size_t isize, /* length of range */ - page_buf_flags_t flags) /* PBF_TRYLOCK */ + xfs_buf_flags_t flags) { - xfs_buf_t *pb, *new_pb; + xfs_buf_t *bp, *new_bp; int error = 0, i; - new_pb = pagebuf_allocate(flags); - if (unlikely(!new_pb)) + new_bp = xfs_buf_allocate(flags); + if (unlikely(!new_bp)) return NULL; - pb = _pagebuf_find(target, ioff, isize, flags, new_pb); - if (pb == new_pb) { - error = _pagebuf_lookup_pages(pb, flags); + bp = _xfs_buf_find(target, ioff, isize, flags, new_bp); + if (bp == new_bp) { + error = _xfs_buf_lookup_pages(bp, flags); if (error) goto no_buffer; } else { - pagebuf_deallocate(new_pb); - if (unlikely(pb == NULL)) + xfs_buf_deallocate(new_bp); + if (unlikely(bp == NULL)) return NULL; } - for (i = 0; i < pb->pb_page_count; i++) - mark_page_accessed(pb->pb_pages[i]); + for (i = 0; i < bp->b_page_count; i++) + mark_page_accessed(bp->b_pages[i]); - if (!(pb->pb_flags & PBF_MAPPED)) { - error = _pagebuf_map_pages(pb, flags); + if (!(bp->b_flags & XBF_MAPPED)) { + error = _xfs_buf_map_pages(bp, flags); if (unlikely(error)) { printk(KERN_WARNING "%s: failed to map pages\n", __FUNCTION__); @@ -598,97 +595,97 @@ xfs_buf_get_flags( /* allocate a buffer */ } } - XFS_STATS_INC(pb_get); + XFS_STATS_INC(xb_get); /* * Always fill in the block number now, the mapped cases can do * their own overlay of this later. */ - pb->pb_bn = ioff; - pb->pb_count_desired = pb->pb_buffer_length; + bp->b_bn = ioff; + bp->b_count_desired = bp->b_buffer_length; - PB_TRACE(pb, "get", (unsigned long)flags); - return pb; + XB_TRACE(bp, "get", (unsigned long)flags); + return bp; no_buffer: - if (flags & (PBF_LOCK | PBF_TRYLOCK)) - pagebuf_unlock(pb); - pagebuf_rele(pb); + if (flags & (XBF_LOCK | XBF_TRYLOCK)) + xfs_buf_unlock(bp); + xfs_buf_rele(bp); return NULL; } xfs_buf_t * xfs_buf_read_flags( xfs_buftarg_t *target, - loff_t ioff, + xfs_off_t ioff, size_t isize, - page_buf_flags_t flags) + xfs_buf_flags_t flags) { - xfs_buf_t *pb; - - flags |= PBF_READ; - - pb = xfs_buf_get_flags(target, ioff, isize, flags); - if (pb) { - if (!XFS_BUF_ISDONE(pb)) { - PB_TRACE(pb, "read", (unsigned long)flags); - XFS_STATS_INC(pb_get_read); - pagebuf_iostart(pb, flags); - } else if (flags & PBF_ASYNC) { - PB_TRACE(pb, "read_async", (unsigned long)flags); + xfs_buf_t *bp; + + flags |= XBF_READ; + + bp = xfs_buf_get_flags(target, ioff, isize, flags); + if (bp) { + if (!XFS_BUF_ISDONE(bp)) { + XB_TRACE(bp, "read", (unsigned long)flags); + XFS_STATS_INC(xb_get_read); + xfs_buf_iostart(bp, flags); + } else if (flags & XBF_ASYNC) { + XB_TRACE(bp, "read_async", (unsigned long)flags); /* * Read ahead call which is already satisfied, * drop the buffer */ goto no_buffer; } else { - PB_TRACE(pb, "read_done", (unsigned long)flags); + XB_TRACE(bp, "read_done", (unsigned long)flags); /* We do not want read in the flags */ - pb->pb_flags &= ~PBF_READ; + bp->b_flags &= ~XBF_READ; } } - return pb; + return bp; no_buffer: - if (flags & (PBF_LOCK | PBF_TRYLOCK)) - pagebuf_unlock(pb); - pagebuf_rele(pb); + if (flags & (XBF_LOCK | XBF_TRYLOCK)) + xfs_buf_unlock(bp); + xfs_buf_rele(bp); return NULL; } /* - * If we are not low on memory then do the readahead in a deadlock - * safe manner. + * If we are not low on memory then do the readahead in a deadlock + * safe manner. */ void -pagebuf_readahead( +xfs_buf_readahead( xfs_buftarg_t *target, - loff_t ioff, + xfs_off_t ioff, size_t isize, - page_buf_flags_t flags) + xfs_buf_flags_t flags) { struct backing_dev_info *bdi; - bdi = target->pbr_mapping->backing_dev_info; + bdi = target->bt_mapping->backing_dev_info; if (bdi_read_congested(bdi)) return; - flags |= (PBF_TRYLOCK|PBF_ASYNC|PBF_READ_AHEAD); + flags |= (XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD); xfs_buf_read_flags(target, ioff, isize, flags); } xfs_buf_t * -pagebuf_get_empty( +xfs_buf_get_empty( size_t len, xfs_buftarg_t *target) { - xfs_buf_t *pb; + xfs_buf_t *bp; - pb = pagebuf_allocate(0); - if (pb) - _pagebuf_initialize(pb, target, 0, len, 0); - return pb; + bp = xfs_buf_allocate(0); + if (bp) + _xfs_buf_initialize(bp, target, 0, len, 0); + return bp; } static inline struct page * @@ -704,8 +701,8 @@ mem_to_page( } int -pagebuf_associate_memory( - xfs_buf_t *pb, +xfs_buf_associate_memory( + xfs_buf_t *bp, void *mem, size_t len) { @@ -722,40 +719,40 @@ pagebuf_associate_memory( page_count++; /* Free any previous set of page pointers */ - if (pb->pb_pages) - _pagebuf_free_pages(pb); + if (bp->b_pages) + _xfs_buf_free_pages(bp); - pb->pb_pages = NULL; - pb->pb_addr = mem; + bp->b_pages = NULL; + bp->b_addr = mem; - rval = _pagebuf_get_pages(pb, page_count, 0); + rval = _xfs_buf_get_pages(bp, page_count, 0); if (rval) return rval; - pb->pb_offset = offset; + bp->b_offset = offset; ptr = (size_t) mem & PAGE_CACHE_MASK; end = PAGE_CACHE_ALIGN((size_t) mem + len); end_cur = end; /* set up first page */ - pb->pb_pages[0] = mem_to_page(mem); + bp->b_pages[0] = mem_to_page(mem); ptr += PAGE_CACHE_SIZE; - pb->pb_page_count = ++i; + bp->b_page_count = ++i; while (ptr < end) { - pb->pb_pages[i] = mem_to_page((void *)ptr); - pb->pb_page_count = ++i; + bp->b_pages[i] = mem_to_page((void *)ptr); + bp->b_page_count = ++i; ptr += PAGE_CACHE_SIZE; } - pb->pb_locked = 0; + bp->b_locked = 0; - pb->pb_count_desired = pb->pb_buffer_length = len; - pb->pb_flags |= PBF_MAPPED; + bp->b_count_desired = bp->b_buffer_length = len; + bp->b_flags |= XBF_MAPPED; return 0; } xfs_buf_t * -pagebuf_get_no_daddr( +xfs_buf_get_noaddr( size_t len, xfs_buftarg_t *target) { @@ -764,10 +761,10 @@ pagebuf_get_no_daddr( void *data; int error; - bp = pagebuf_allocate(0); + bp = xfs_buf_allocate(0); if (unlikely(bp == NULL)) goto fail; - _pagebuf_initialize(bp, target, 0, len, 0); + _xfs_buf_initialize(bp, target, 0, len, 0); try_again: data = kmem_alloc(malloc_len, KM_SLEEP | KM_MAYFAIL); @@ -776,78 +773,73 @@ pagebuf_get_no_daddr( /* check whether alignment matches.. */ if ((__psunsigned_t)data != - ((__psunsigned_t)data & ~target->pbr_smask)) { + ((__psunsigned_t)data & ~target->bt_smask)) { /* .. else double the size and try again */ kmem_free(data, malloc_len); malloc_len <<= 1; goto try_again; } - error = pagebuf_associate_memory(bp, data, len); + error = xfs_buf_associate_memory(bp, data, len); if (error) goto fail_free_mem; - bp->pb_flags |= _PBF_KMEM_ALLOC; + bp->b_flags |= _XBF_KMEM_ALLOC; - pagebuf_unlock(bp); + xfs_buf_unlock(bp); - PB_TRACE(bp, "no_daddr", data); + XB_TRACE(bp, "no_daddr", data); return bp; fail_free_mem: kmem_free(data, malloc_len); fail_free_buf: - pagebuf_free(bp); + xfs_buf_free(bp); fail: return NULL; } /* - * pagebuf_hold - * * Increment reference count on buffer, to hold the buffer concurrently * with another thread which may release (free) the buffer asynchronously. - * * Must hold the buffer already to call this function. */ void -pagebuf_hold( - xfs_buf_t *pb) +xfs_buf_hold( + xfs_buf_t *bp) { - atomic_inc(&pb->pb_hold); - PB_TRACE(pb, "hold", 0); + atomic_inc(&bp->b_hold); + XB_TRACE(bp, "hold", 0); } /* - * pagebuf_rele - * - * pagebuf_rele releases a hold on the specified buffer. If the - * the hold count is 1, pagebuf_rele calls pagebuf_free. + * Releases a hold on the specified buffer. If the + * the hold count is 1, calls xfs_buf_free. */ void -pagebuf_rele( - xfs_buf_t *pb) +xfs_buf_rele( + xfs_buf_t *bp) { - xfs_bufhash_t *hash = pb->pb_hash; + xfs_bufhash_t *hash = bp->b_hash; - PB_TRACE(pb, "rele", pb->pb_relse); + XB_TRACE(bp, "rele", bp->b_relse); - if (atomic_dec_and_lock(&pb->pb_hold, &hash->bh_lock)) { - if (pb->pb_relse) { - atomic_inc(&pb->pb_hold); + if (atomic_dec_and_lock(&bp->b_hold, &hash->bh_lock)) { + if (bp->b_relse) { + atomic_inc(&bp->b_hold); spin_unlock(&hash->bh_lock); - (*(pb->pb_relse)) (pb); - } else if (pb->pb_flags & PBF_FS_MANAGED) { + (*(bp->b_relse)) (bp); + } else if (bp->b_flags & XBF_FS_MANAGED) { spin_unlock(&hash->bh_lock); } else { - ASSERT(!(pb->pb_flags & (PBF_DELWRI|_PBF_DELWRI_Q))); - list_del_init(&pb->pb_hash_list); + ASSERT(!(bp->b_flags & (XBF_DELWRI|_XBF_DELWRI_Q))); + list_del_init(&bp->b_hash_list); spin_unlock(&hash->bh_lock); - pagebuf_free(pb); + xfs_buf_free(bp); } } else { /* * Catch reference count leaks */ - ASSERT(atomic_read(&pb->pb_hold) >= 0); + ASSERT(atomic_read(&bp->b_hold) >= 0); } } @@ -863,168 +855,122 @@ pagebuf_rele( */ /* - * pagebuf_cond_lock - * - * pagebuf_cond_lock locks a buffer object, if it is not already locked. - * Note that this in no way - * locks the underlying pages, so it is only useful for synchronizing - * concurrent use of page buffer objects, not for synchronizing independent - * access to the underlying pages. + * Locks a buffer object, if it is not already locked. + * Note that this in no way locks the underlying pages, so it is only + * useful for synchronizing concurrent use of buffer objects, not for + * synchronizing independent access to the underlying pages. */ int -pagebuf_cond_lock( /* lock buffer, if not locked */ - /* returns -EBUSY if locked) */ - xfs_buf_t *pb) +xfs_buf_cond_lock( + xfs_buf_t *bp) { int locked; - locked = down_trylock(&pb->pb_sema) == 0; + locked = down_trylock(&bp->b_sema) == 0; if (locked) { - PB_SET_OWNER(pb); + XB_SET_OWNER(bp); } - PB_TRACE(pb, "cond_lock", (long)locked); - return(locked ? 0 : -EBUSY); + XB_TRACE(bp, "cond_lock", (long)locked); + return locked ? 0 : -EBUSY; } #if defined(DEBUG) || defined(XFS_BLI_TRACE) -/* - * pagebuf_lock_value - * - * Return lock value for a pagebuf - */ int -pagebuf_lock_value( - xfs_buf_t *pb) +xfs_buf_lock_value( + xfs_buf_t *bp) { - return(atomic_read(&pb->pb_sema.count)); + return atomic_read(&bp->b_sema.count); } #endif /* - * pagebuf_lock - * - * pagebuf_lock locks a buffer object. Note that this in no way - * locks the underlying pages, so it is only useful for synchronizing - * concurrent use of page buffer objects, not for synchronizing independent - * access to the underlying pages. + * Locks a buffer object. + * Note that this in no way locks the underlying pages, so it is only + * useful for synchronizing concurrent use of buffer objects, not for + * synchronizing independent access to the underlying pages. */ -int -pagebuf_lock( - xfs_buf_t *pb) +void +xfs_buf_lock( + xfs_buf_t *bp) { - PB_TRACE(pb, "lock", 0); - if (atomic_read(&pb->pb_io_remaining)) - blk_run_address_space(pb->pb_target->pbr_mapping); - down(&pb->pb_sema); - PB_SET_OWNER(pb); - PB_TRACE(pb, "locked", 0); - return 0; + XB_TRACE(bp, "lock", 0); + if (atomic_read(&bp->b_io_remaining)) + blk_run_address_space(bp->b_target->bt_mapping); + down(&bp->b_sema); + XB_SET_OWNER(bp); + XB_TRACE(bp, "locked", 0); } /* - * pagebuf_unlock - * - * pagebuf_unlock releases the lock on the buffer object created by - * pagebuf_lock or pagebuf_cond_lock (not any pinning of underlying pages - * created by pagebuf_pin). - * + * Releases the lock on the buffer object. * If the buffer is marked delwri but is not queued, do so before we - * unlock the buffer as we need to set flags correctly. We also need to + * unlock the buffer as we need to set flags correctly. We also need to * take a reference for the delwri queue because the unlocker is going to * drop their's and they don't know we just queued it. */ void -pagebuf_unlock( /* unlock buffer */ - xfs_buf_t *pb) /* buffer to unlock */ +xfs_buf_unlock( + xfs_buf_t *bp) { - if ((pb->pb_flags & (PBF_DELWRI|_PBF_DELWRI_Q)) == PBF_DELWRI) { - atomic_inc(&pb->pb_hold); - pb->pb_flags |= PBF_ASYNC; - pagebuf_delwri_queue(pb, 0); + if ((bp->b_flags & (XBF_DELWRI|_XBF_DELWRI_Q)) == XBF_DELWRI) { + atomic_inc(&bp->b_hold); + bp->b_flags |= XBF_ASYNC; + xfs_buf_delwri_queue(bp, 0); } - PB_CLEAR_OWNER(pb); - up(&pb->pb_sema); - PB_TRACE(pb, "unlock", 0); + XB_CLEAR_OWNER(bp); + up(&bp->b_sema); + XB_TRACE(bp, "unlock", 0); } /* * Pinning Buffer Storage in Memory - */ - -/* - * pagebuf_pin - * - * pagebuf_pin locks all of the memory represented by a buffer in - * memory. Multiple calls to pagebuf_pin and pagebuf_unpin, for - * the same or different buffers affecting a given page, will - * properly count the number of outstanding "pin" requests. The - * buffer may be released after the pagebuf_pin and a different - * buffer used when calling pagebuf_unpin, if desired. - * pagebuf_pin should be used by the file system when it wants be - * assured that no attempt will be made to force the affected - * memory to disk. It does not assure that a given logical page - * will not be moved to a different physical page. + * Ensure that no attempt to force a buffer to disk will succeed. */ void -pagebuf_pin( - xfs_buf_t *pb) +xfs_buf_pin( + xfs_buf_t *bp) { - atomic_inc(&pb->pb_pin_count); - PB_TRACE(pb, "pin", (long)pb->pb_pin_count.counter); + atomic_inc(&bp->b_pin_count); + XB_TRACE(bp, "pin", (long)bp->b_pin_count.counter); } -/* - * pagebuf_unpin - * - * pagebuf_unpin reverses the locking of memory performed by - * pagebuf_pin. Note that both functions affected the logical - * pages associated with the buffer, not the buffer itself. - */ void -pagebuf_unpin( - xfs_buf_t *pb) +xfs_buf_unpin( + xfs_buf_t *bp) { - if (atomic_dec_and_test(&pb->pb_pin_count)) { - wake_up_all(&pb->pb_waiters); - } - PB_TRACE(pb, "unpin", (long)pb->pb_pin_count.counter); + if (atomic_dec_and_test(&bp->b_pin_count)) + wake_up_all(&bp->b_waiters); + XB_TRACE(bp, "unpin", (long)bp->b_pin_count.counter); } int -pagebuf_ispin( - xfs_buf_t *pb) +xfs_buf_ispin( + xfs_buf_t *bp) { - return atomic_read(&pb->pb_pin_count); + return atomic_read(&bp->b_pin_count); } -/* - * pagebuf_wait_unpin - * - * pagebuf_wait_unpin waits until all of the memory associated - * with the buffer is not longer locked in memory. It returns - * immediately if none of the affected pages are locked. - */ -static inline void -_pagebuf_wait_unpin( - xfs_buf_t *pb) +STATIC void +xfs_buf_wait_unpin( + xfs_buf_t *bp) { DECLARE_WAITQUEUE (wait, current); - if (atomic_read(&pb->pb_pin_count) == 0) + if (atomic_read(&bp->b_pin_count) == 0) return; - add_wait_queue(&pb->pb_waiters, &wait); + add_wait_queue(&bp->b_waiters, &wait); for (;;) { set_current_state(TASK_UNINTERRUPTIBLE); - if (atomic_read(&pb->pb_pin_count) == 0) + if (atomic_read(&bp->b_pin_count) == 0) break; - if (atomic_read(&pb->pb_io_remaining)) - blk_run_address_space(pb->pb_target->pbr_mapping); + if (atomic_read(&bp->b_io_remaining)) + blk_run_address_space(bp->b_target->bt_mapping); schedule(); } - remove_wait_queue(&pb->pb_waiters, &wait); + remove_wait_queue(&bp->b_waiters, &wait); set_current_state(TASK_RUNNING); } @@ -1032,241 +978,216 @@ _pagebuf_wait_unpin( * Buffer Utility Routines */ -/* - * pagebuf_iodone - * - * pagebuf_iodone marks a buffer for which I/O is in progress - * done with respect to that I/O. The pb_iodone routine, if - * present, will be called as a side-effect. - */ STATIC void -pagebuf_iodone_work( +xfs_buf_iodone_work( void *v) { xfs_buf_t *bp = (xfs_buf_t *)v; - if (bp->pb_iodone) - (*(bp->pb_iodone))(bp); - else if (bp->pb_flags & PBF_ASYNC) + if (bp->b_iodone) + (*(bp->b_iodone))(bp); + else if (bp->b_flags & XBF_ASYNC) xfs_buf_relse(bp); } void -pagebuf_iodone( - xfs_buf_t *pb, +xfs_buf_ioend( + xfs_buf_t *bp, int schedule) { - pb->pb_flags &= ~(PBF_READ | PBF_WRITE); - if (pb->pb_error == 0) - pb->pb_flags |= PBF_DONE; + bp->b_flags &= ~(XBF_READ | XBF_WRITE); + if (bp->b_error == 0) + bp->b_flags |= XBF_DONE; - PB_TRACE(pb, "iodone", pb->pb_iodone); + XB_TRACE(bp, "iodone", bp->b_iodone); - if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) { + if ((bp->b_iodone) || (bp->b_flags & XBF_ASYNC)) { if (schedule) { - INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb); - queue_work(xfslogd_workqueue, &pb->pb_iodone_work); + INIT_WORK(&bp->b_iodone_work, xfs_buf_iodone_work, bp); + queue_work(xfslogd_workqueue, &bp->b_iodone_work); } else { - pagebuf_iodone_work(pb); + xfs_buf_iodone_work(bp); } } else { - up(&pb->pb_iodonesema); + up(&bp->b_iodonesema); } } -/* - * pagebuf_ioerror - * - * pagebuf_ioerror sets the error code for a buffer. - */ void -pagebuf_ioerror( /* mark/clear buffer error flag */ - xfs_buf_t *pb, /* buffer to mark */ - int error) /* error to store (0 if none) */ +xfs_buf_ioerror( + xfs_buf_t *bp, + int error) { ASSERT(error >= 0 && error <= 0xffff); - pb->pb_error = (unsigned short)error; - PB_TRACE(pb, "ioerror", (unsigned long)error); + bp->b_error = (unsigned short)error; + XB_TRACE(bp, "ioerror", (unsigned long)error); } /* - * pagebuf_iostart - * - * pagebuf_iostart initiates I/O on a buffer, based on the flags supplied. - * If necessary, it will arrange for any disk space allocation required, - * and it will break up the request if the block mappings require it. - * The pb_iodone routine in the buffer supplied will only be called + * Initiate I/O on a buffer, based on the flags supplied. + * The b_iodone routine in the buffer supplied will only be called * when all of the subsidiary I/O requests, if any, have been completed. - * pagebuf_iostart calls the pagebuf_ioinitiate routine or - * pagebuf_iorequest, if the former routine is not defined, to start - * the I/O on a given low-level request. */ int -pagebuf_iostart( /* start I/O on a buffer */ - xfs_buf_t *pb, /* buffer to start */ - page_buf_flags_t flags) /* PBF_LOCK, PBF_ASYNC, PBF_READ, */ - /* PBF_WRITE, PBF_DELWRI, */ - /* PBF_DONT_BLOCK */ +xfs_buf_iostart( + xfs_buf_t *bp, + xfs_buf_flags_t flags) { int status = 0; - PB_TRACE(pb, "iostart", (unsigned long)flags); + XB_TRACE(bp, "iostart", (unsigned long)flags); - if (flags & PBF_DELWRI) { - pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC); - pb->pb_flags |= flags & (PBF_DELWRI | PBF_ASYNC); - pagebuf_delwri_queue(pb, 1); + if (flags & XBF_DELWRI) { + bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC); + bp->b_flags |= flags & (XBF_DELWRI | XBF_ASYNC); + xfs_buf_delwri_queue(bp, 1); return status; } - pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | PBF_DELWRI | \ - PBF_READ_AHEAD | _PBF_RUN_QUEUES); - pb->pb_flags |= flags & (PBF_READ | PBF_WRITE | PBF_ASYNC | \ - PBF_READ_AHEAD | _PBF_RUN_QUEUES); + bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC | XBF_DELWRI | \ + XBF_READ_AHEAD | _XBF_RUN_QUEUES); + bp->b_flags |= flags & (XBF_READ | XBF_WRITE | XBF_ASYNC | \ + XBF_READ_AHEAD | _XBF_RUN_QUEUES); - BUG_ON(pb->pb_bn == XFS_BUF_DADDR_NULL); + BUG_ON(bp->b_bn == XFS_BUF_DADDR_NULL); /* For writes allow an alternate strategy routine to precede * the actual I/O request (which may not be issued at all in * a shutdown situation, for example). */ - status = (flags & PBF_WRITE) ? - pagebuf_iostrategy(pb) : pagebuf_iorequest(pb); + status = (flags & XBF_WRITE) ? + xfs_buf_iostrategy(bp) : xfs_buf_iorequest(bp); /* Wait for I/O if we are not an async request. * Note: async I/O request completion will release the buffer, * and that can already be done by this point. So using the * buffer pointer from here on, after async I/O, is invalid. */ - if (!status && !(flags & PBF_ASYNC)) - status = pagebuf_iowait(pb); + if (!status && !(flags & XBF_ASYNC)) + status = xfs_buf_iowait(bp); return status; } -/* - * Helper routine for pagebuf_iorequest - */ - STATIC __inline__ int -_pagebuf_iolocked( - xfs_buf_t *pb) +_xfs_buf_iolocked( + xfs_buf_t *bp) { - ASSERT(pb->pb_flags & (PBF_READ|PBF_WRITE)); - if (pb->pb_flags & PBF_READ) - return pb->pb_locked; + ASSERT(bp->b_flags & (XBF_READ | XBF_WRITE)); + if (bp->b_flags & XBF_READ) + return bp->b_locked; return 0; } STATIC __inline__ void -_pagebuf_iodone( - xfs_buf_t *pb, +_xfs_buf_ioend( + xfs_buf_t *bp, int schedule) { - if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { - pb->pb_locked = 0; - pagebuf_iodone(pb, schedule); + if (atomic_dec_and_test(&bp->b_io_remaining) == 1) { + bp->b_locked = 0; + xfs_buf_ioend(bp, schedule); } } STATIC int -bio_end_io_pagebuf( +xfs_buf_bio_end_io( struct bio *bio, unsigned int bytes_done, int error) { - xfs_buf_t *pb = (xfs_buf_t *)bio->bi_private; - unsigned int blocksize = pb->pb_target->pbr_bsize; + xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private; + unsigned int blocksize = bp->b_target->bt_bsize; struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; if (bio->bi_size) return 1; if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) - pb->pb_error = EIO; + bp->b_error = EIO; do { struct page *page = bvec->bv_page; - if (unlikely(pb->pb_error)) { - if (pb->pb_flags & PBF_READ) + if (unlikely(bp->b_error)) { + if (bp->b_flags & XBF_READ) ClearPageUptodate(page); SetPageError(page); - } else if (blocksize == PAGE_CACHE_SIZE) { + } else if (blocksize >= PAGE_CACHE_SIZE) { SetPageUptodate(page); } else if (!PagePrivate(page) && - (pb->pb_flags & _PBF_PAGE_CACHE)) { + (bp->b_flags & _XBF_PAGE_CACHE)) { set_page_region(page, bvec->bv_offset, bvec->bv_len); } if (--bvec >= bio->bi_io_vec) prefetchw(&bvec->bv_page->flags); - if (_pagebuf_iolocked(pb)) { + if (_xfs_buf_iolocked(bp)) { unlock_page(page); } } while (bvec >= bio->bi_io_vec); - _pagebuf_iodone(pb, 1); + _xfs_buf_ioend(bp, 1); bio_put(bio); return 0; } STATIC void -_pagebuf_ioapply( - xfs_buf_t *pb) +_xfs_buf_ioapply( + xfs_buf_t *bp) { int i, rw, map_i, total_nr_pages, nr_pages; struct bio *bio; - int offset = pb->pb_offset; - int size = pb->pb_count_desired; - sector_t sector = pb->pb_bn; - unsigned int blocksize = pb->pb_target->pbr_bsize; - int locking = _pagebuf_iolocked(pb); + int offset = bp->b_offset; + int size = bp->b_count_desired; + sector_t sector = bp->b_bn; + unsigned int blocksize = bp->b_target->bt_bsize; + int locking = _xfs_buf_iolocked(bp); - total_nr_pages = pb->pb_page_count; + total_nr_pages = bp->b_page_count; map_i = 0; - if (pb->pb_flags & _PBF_RUN_QUEUES) { - pb->pb_flags &= ~_PBF_RUN_QUEUES; - rw = (pb->pb_flags & PBF_READ) ? READ_SYNC : WRITE_SYNC; + if (bp->b_flags & _XBF_RUN_QUEUES) { + bp->b_flags &= ~_XBF_RUN_QUEUES; + rw = (bp->b_flags & XBF_READ) ? READ_SYNC : WRITE_SYNC; } else { - rw = (pb->pb_flags & PBF_READ) ? READ : WRITE; + rw = (bp->b_flags & XBF_READ) ? READ : WRITE; } - if (pb->pb_flags & PBF_ORDERED) { - ASSERT(!(pb->pb_flags & PBF_READ)); + if (bp->b_flags & XBF_ORDERED) { + ASSERT(!(bp->b_flags & XBF_READ)); rw = WRITE_BARRIER; } - /* Special code path for reading a sub page size pagebuf in -- + /* Special code path for reading a sub page size buffer in -- * we populate up the whole page, and hence the other metadata * in the same page. This optimization is only valid when the - * filesystem block size and the page size are equal. + * filesystem block size is not smaller than the page size. */ - if ((pb->pb_buffer_length < PAGE_CACHE_SIZE) && - (pb->pb_flags & PBF_READ) && locking && - (blocksize == PAGE_CACHE_SIZE)) { + if ((bp->b_buffer_length < PAGE_CACHE_SIZE) && + (bp->b_flags & XBF_READ) && locking && + (blocksize >= PAGE_CACHE_SIZE)) { bio = bio_alloc(GFP_NOIO, 1); - bio->bi_bdev = pb->pb_target->pbr_bdev; + bio->bi_bdev = bp->b_target->bt_bdev; bio->bi_sector = sector - (offset >> BBSHIFT); - bio->bi_end_io = bio_end_io_pagebuf; - bio->bi_private = pb; + bio->bi_end_io = xfs_buf_bio_end_io; + bio->bi_private = bp; - bio_add_page(bio, pb->pb_pages[0], PAGE_CACHE_SIZE, 0); + bio_add_page(bio, bp->b_pages[0], PAGE_CACHE_SIZE, 0); size = 0; - atomic_inc(&pb->pb_io_remaining); + atomic_inc(&bp->b_io_remaining); goto submit_io; } /* Lock down the pages which we need to for the request */ - if (locking && (pb->pb_flags & PBF_WRITE) && (pb->pb_locked == 0)) { + if (locking && (bp->b_flags & XBF_WRITE) && (bp->b_locked == 0)) { for (i = 0; size; i++) { int nbytes = PAGE_CACHE_SIZE - offset; - struct page *page = pb->pb_pages[i]; + struct page *page = bp->b_pages[i]; if (nbytes > size) nbytes = size; @@ -1276,30 +1197,30 @@ _pagebuf_ioapply( size -= nbytes; offset = 0; } - offset = pb->pb_offset; - size = pb->pb_count_desired; + offset = bp->b_offset; + size = bp->b_count_desired; } next_chunk: - atomic_inc(&pb->pb_io_remaining); + atomic_inc(&bp->b_io_remaining); nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - BBSHIFT); if (nr_pages > total_nr_pages) nr_pages = total_nr_pages; bio = bio_alloc(GFP_NOIO, nr_pages); - bio->bi_bdev = pb->pb_target->pbr_bdev; + bio->bi_bdev = bp->b_target->bt_bdev; bio->bi_sector = sector; - bio->bi_end_io = bio_end_io_pagebuf; - bio->bi_private = pb; + bio->bi_end_io = xfs_buf_bio_end_io; + bio->bi_private = bp; for (; size && nr_pages; nr_pages--, map_i++) { - int nbytes = PAGE_CACHE_SIZE - offset; + int rbytes, nbytes = PAGE_CACHE_SIZE - offset; if (nbytes > size) nbytes = size; - if (bio_add_page(bio, pb->pb_pages[map_i], - nbytes, offset) < nbytes) + rbytes = bio_add_page(bio, bp->b_pages[map_i], nbytes, offset); + if (rbytes < nbytes) break; offset = 0; @@ -1315,107 +1236,102 @@ submit_io: goto next_chunk; } else { bio_put(bio); - pagebuf_ioerror(pb, EIO); + xfs_buf_ioerror(bp, EIO); } } -/* - * pagebuf_iorequest -- the core I/O request routine. - */ int -pagebuf_iorequest( /* start real I/O */ - xfs_buf_t *pb) /* buffer to convey to device */ +xfs_buf_iorequest( + xfs_buf_t *bp) { - PB_TRACE(pb, "iorequest", 0); + XB_TRACE(bp, "iorequest", 0); - if (pb->pb_flags & PBF_DELWRI) { - pagebuf_delwri_queue(pb, 1); + if (bp->b_flags & XBF_DELWRI) { + xfs_buf_delwri_queue(bp, 1); return 0; } - if (pb->pb_flags & PBF_WRITE) { - _pagebuf_wait_unpin(pb); + if (bp->b_flags & XBF_WRITE) { + xfs_buf_wait_unpin(bp); } - pagebuf_hold(pb); + xfs_buf_hold(bp); /* Set the count to 1 initially, this will stop an I/O * completion callout which happens before we have started - * all the I/O from calling pagebuf_iodone too early. + * all the I/O from calling xfs_buf_ioend too early. */ - atomic_set(&pb->pb_io_remaining, 1); - _pagebuf_ioapply(pb); - _pagebuf_iodone(pb, 0); + atomic_set(&bp->b_io_remaining, 1); + _xfs_buf_ioapply(bp); + _xfs_buf_ioend(bp, 0); - pagebuf_rele(pb); + xfs_buf_rele(bp); return 0; } /* - * pagebuf_iowait - * - * pagebuf_iowait waits for I/O to complete on the buffer supplied. - * It returns immediately if no I/O is pending. In any case, it returns - * the error code, if any, or 0 if there is no error. + * Waits for I/O to complete on the buffer supplied. + * It returns immediately if no I/O is pending. + * It returns the I/O error code, if any, or 0 if there was no error. */ int -pagebuf_iowait( - xfs_buf_t *pb) +xfs_buf_iowait( + xfs_buf_t *bp) { - PB_TRACE(pb, "iowait", 0); - if (atomic_read(&pb->pb_io_remaining)) - blk_run_address_space(pb->pb_target->pbr_mapping); - down(&pb->pb_iodonesema); - PB_TRACE(pb, "iowaited", (long)pb->pb_error); - return pb->pb_error; + XB_TRACE(bp, "iowait", 0); + if (atomic_read(&bp->b_io_remaining)) + blk_run_address_space(bp->b_target->bt_mapping); + down(&bp->b_iodonesema); + XB_TRACE(bp, "iowaited", (long)bp->b_error); + return bp->b_error; } -caddr_t -pagebuf_offset( - xfs_buf_t *pb, +xfs_caddr_t +xfs_buf_offset( + xfs_buf_t *bp, size_t offset) { struct page *page; - offset += pb->pb_offset; + if (bp->b_flags & XBF_MAPPED) + return XFS_BUF_PTR(bp) + offset; - page = pb->pb_pages[offset >> PAGE_CACHE_SHIFT]; - return (caddr_t) page_address(page) + (offset & (PAGE_CACHE_SIZE - 1)); + offset += bp->b_offset; + page = bp->b_pages[offset >> PAGE_CACHE_SHIFT]; + return (xfs_caddr_t)page_address(page) + (offset & (PAGE_CACHE_SIZE-1)); } /* - * pagebuf_iomove - * * Move data into or out of a buffer. */ void -pagebuf_iomove( - xfs_buf_t *pb, /* buffer to process */ +xfs_buf_iomove( + xfs_buf_t *bp, /* buffer to process */ size_t boff, /* starting buffer offset */ size_t bsize, /* length to copy */ caddr_t data, /* data address */ - page_buf_rw_t mode) /* read/write flag */ + xfs_buf_rw_t mode) /* read/write/zero flag */ { size_t bend, cpoff, csize; struct page *page; bend = boff + bsize; while (boff < bend) { - page = pb->pb_pages[page_buf_btoct(boff + pb->pb_offset)]; - cpoff = page_buf_poff(boff + pb->pb_offset); + page = bp->b_pages[xfs_buf_btoct(boff + bp->b_offset)]; + cpoff = xfs_buf_poff(boff + bp->b_offset); csize = min_t(size_t, - PAGE_CACHE_SIZE-cpoff, pb->pb_count_desired-boff); + PAGE_CACHE_SIZE-cpoff, bp->b_count_desired-boff); ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE)); switch (mode) { - case PBRW_ZERO: + case XBRW_ZERO: memset(page_address(page) + cpoff, 0, csize); break; - case PBRW_READ: + case XBRW_READ: memcpy(data, page_address(page) + cpoff, csize); break; - case PBRW_WRITE: + case XBRW_WRITE: memcpy(page_address(page) + cpoff, data, csize); } @@ -1425,12 +1341,12 @@ pagebuf_iomove( } /* - * Handling of buftargs. + * Handling of buffer targets (buftargs). */ /* - * Wait for any bufs with callbacks that have been submitted but - * have not yet returned... walk the hash list for the target. + * Wait for any bufs with callbacks that have been submitted but + * have not yet returned... walk the hash list for the target. */ void xfs_wait_buftarg( @@ -1444,15 +1360,15 @@ xfs_wait_buftarg( hash = &btp->bt_hash[i]; again: spin_lock(&hash->bh_lock); - list_for_each_entry_safe(bp, n, &hash->bh_list, pb_hash_list) { - ASSERT(btp == bp->pb_target); - if (!(bp->pb_flags & PBF_FS_MANAGED)) { + list_for_each_entry_safe(bp, n, &hash->bh_list, b_hash_list) { + ASSERT(btp == bp->b_target); + if (!(bp->b_flags & XBF_FS_MANAGED)) { spin_unlock(&hash->bh_lock); /* * Catch superblock reference count leaks * immediately */ - BUG_ON(bp->pb_bn == 0); + BUG_ON(bp->b_bn == 0); delay(100); goto again; } @@ -1462,9 +1378,9 @@ again: } /* - * Allocate buffer hash table for a given target. - * For devices containing metadata (i.e. not the log/realtime devices) - * we need to allocate a much larger hash table. + * Allocate buffer hash table for a given target. + * For devices containing metadata (i.e. not the log/realtime devices) + * we need to allocate a much larger hash table. */ STATIC void xfs_alloc_bufhash( @@ -1487,11 +1403,34 @@ STATIC void xfs_free_bufhash( xfs_buftarg_t *btp) { - kmem_free(btp->bt_hash, - (1 << btp->bt_hashshift) * sizeof(xfs_bufhash_t)); + kmem_free(btp->bt_hash, (1<<btp->bt_hashshift) * sizeof(xfs_bufhash_t)); btp->bt_hash = NULL; } +/* + * buftarg list for delwrite queue processing + */ +STATIC LIST_HEAD(xfs_buftarg_list); +STATIC DEFINE_SPINLOCK(xfs_buftarg_lock); + +STATIC void +xfs_register_buftarg( + xfs_buftarg_t *btp) +{ + spin_lock(&xfs_buftarg_lock); + list_add(&btp->bt_list, &xfs_buftarg_list); + spin_unlock(&xfs_buftarg_lock); +} + +STATIC void +xfs_unregister_buftarg( + xfs_buftarg_t *btp) +{ + spin_lock(&xfs_buftarg_lock); + list_del(&btp->bt_list); + spin_unlock(&xfs_buftarg_lock); +} + void xfs_free_buftarg( xfs_buftarg_t *btp, @@ -1499,9 +1438,16 @@ xfs_free_buftarg( { xfs_flush_buftarg(btp, 1); if (external) - xfs_blkdev_put(btp->pbr_bdev); + xfs_blkdev_put(btp->bt_bdev); xfs_free_bufhash(btp); - iput(btp->pbr_mapping->host); + iput(btp->bt_mapping->host); + + /* Unregister the buftarg first so that we don't get a + * wakeup finding a non-existent task + */ + xfs_unregister_buftarg(btp); + kthread_stop(btp->bt_task); + kmem_free(btp, sizeof(*btp)); } @@ -1512,11 +1458,11 @@ xfs_setsize_buftarg_flags( unsigned int sectorsize, int verbose) { - btp->pbr_bsize = blocksize; - btp->pbr_sshift = ffs(sectorsize) - 1; - btp->pbr_smask = sectorsize - 1; + btp->bt_bsize = blocksize; + btp->bt_sshift = ffs(sectorsize) - 1; + btp->bt_smask = sectorsize - 1; - if (set_blocksize(btp->pbr_bdev, sectorsize)) { + if (set_blocksize(btp->bt_bdev, sectorsize)) { printk(KERN_WARNING "XFS: Cannot set_blocksize to %u on device %s\n", sectorsize, XFS_BUFTARG_NAME(btp)); @@ -1536,10 +1482,10 @@ xfs_setsize_buftarg_flags( } /* -* When allocating the initial buffer target we have not yet -* read in the superblock, so don't know what sized sectors -* are being used is at this early stage. Play safe. -*/ + * When allocating the initial buffer target we have not yet + * read in the superblock, so don't know what sized sectors + * are being used is at this early stage. Play safe. + */ STATIC int xfs_setsize_buftarg_early( xfs_buftarg_t *btp, @@ -1587,10 +1533,30 @@ xfs_mapping_buftarg( mapping->a_ops = &mapping_aops; mapping->backing_dev_info = bdi; mapping_set_gfp_mask(mapping, GFP_NOFS); - btp->pbr_mapping = mapping; + btp->bt_mapping = mapping; return 0; } +STATIC int +xfs_alloc_delwrite_queue( + xfs_buftarg_t *btp) +{ + int error = 0; + + INIT_LIST_HEAD(&btp->bt_list); + INIT_LIST_HEAD(&btp->bt_delwrite_queue); + spinlock_init(&btp->bt_delwrite_lock, "delwri_lock"); + btp->bt_flags = 0; + btp->bt_task = kthread_run(xfsbufd, btp, "xfsbufd"); + if (IS_ERR(btp->bt_task)) { + error = PTR_ERR(btp->bt_task); + goto out_error; + } + xfs_register_buftarg(btp); +out_error: + return error; +} + xfs_buftarg_t * xfs_alloc_buftarg( struct block_device *bdev, @@ -1600,12 +1566,14 @@ xfs_alloc_buftarg( btp = kmem_zalloc(sizeof(*btp), KM_SLEEP); - btp->pbr_dev = bdev->bd_dev; - btp->pbr_bdev = bdev; + btp->bt_dev = bdev->bd_dev; + btp->bt_bdev = bdev; if (xfs_setsize_buftarg_early(btp, bdev)) goto error; if (xfs_mapping_buftarg(btp, bdev)) goto error; + if (xfs_alloc_delwrite_queue(btp)) + goto error; xfs_alloc_bufhash(btp, external); return btp; @@ -1616,83 +1584,81 @@ error: /* - * Pagebuf delayed write buffer handling + * Delayed write buffer handling */ - -STATIC LIST_HEAD(pbd_delwrite_queue); -STATIC DEFINE_SPINLOCK(pbd_delwrite_lock); - STATIC void -pagebuf_delwri_queue( - xfs_buf_t *pb, +xfs_buf_delwri_queue( + xfs_buf_t *bp, int unlock) { - PB_TRACE(pb, "delwri_q", (long)unlock); - ASSERT((pb->pb_flags & (PBF_DELWRI|PBF_ASYNC)) == - (PBF_DELWRI|PBF_ASYNC)); + struct list_head *dwq = &bp->b_target->bt_delwrite_queue; + spinlock_t *dwlk = &bp->b_target->bt_delwrite_lock; + + XB_TRACE(bp, "delwri_q", (long)unlock); + ASSERT((bp->b_flags&(XBF_DELWRI|XBF_ASYNC)) == (XBF_DELWRI|XBF_ASYNC)); - spin_lock(&pbd_delwrite_lock); + spin_lock(dwlk); /* If already in the queue, dequeue and place at tail */ - if (!list_empty(&pb->pb_list)) { - ASSERT(pb->pb_flags & _PBF_DELWRI_Q); - if (unlock) { - atomic_dec(&pb->pb_hold); - } - list_del(&pb->pb_list); + if (!list_empty(&bp->b_list)) { + ASSERT(bp->b_flags & _XBF_DELWRI_Q); + if (unlock) + atomic_dec(&bp->b_hold); + list_del(&bp->b_list); } - pb->pb_flags |= _PBF_DELWRI_Q; - list_add_tail(&pb->pb_list, &pbd_delwrite_queue); - pb->pb_queuetime = jiffies; - spin_unlock(&pbd_delwrite_lock); + bp->b_flags |= _XBF_DELWRI_Q; + list_add_tail(&bp->b_list, dwq); + bp->b_queuetime = jiffies; + spin_unlock(dwlk); if (unlock) - pagebuf_unlock(pb); + xfs_buf_unlock(bp); } void -pagebuf_delwri_dequeue( - xfs_buf_t *pb) +xfs_buf_delwri_dequeue( + xfs_buf_t *bp) { + spinlock_t *dwlk = &bp->b_target->bt_delwrite_lock; int dequeued = 0; - spin_lock(&pbd_delwrite_lock); - if ((pb->pb_flags & PBF_DELWRI) && !list_empty(&pb->pb_list)) { - ASSERT(pb->pb_flags & _PBF_DELWRI_Q); - list_del_init(&pb->pb_list); + spin_lock(dwlk); + if ((bp->b_flags & XBF_DELWRI) && !list_empty(&bp->b_list)) { + ASSERT(bp->b_flags & _XBF_DELWRI_Q); + list_del_init(&bp->b_list); dequeued = 1; } - pb->pb_flags &= ~(PBF_DELWRI|_PBF_DELWRI_Q); - spin_unlock(&pbd_delwrite_lock); + bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q); + spin_unlock(dwlk); if (dequeued) - pagebuf_rele(pb); + xfs_buf_rele(bp); - PB_TRACE(pb, "delwri_dq", (long)dequeued); + XB_TRACE(bp, "delwri_dq", (long)dequeued); } STATIC void -pagebuf_runall_queues( +xfs_buf_runall_queues( struct workqueue_struct *queue) { flush_workqueue(queue); } -/* Defines for pagebuf daemon */ -STATIC struct task_struct *xfsbufd_task; -STATIC int xfsbufd_force_flush; -STATIC int xfsbufd_force_sleep; - STATIC int xfsbufd_wakeup( int priority, gfp_t mask) { - if (xfsbufd_force_sleep) - return 0; - xfsbufd_force_flush = 1; - barrier(); - wake_up_process(xfsbufd_task); + xfs_buftarg_t *btp; + + spin_lock(&xfs_buftarg_lock); + list_for_each_entry(btp, &xfs_buftarg_list, bt_list) { + if (test_bit(XBT_FORCE_SLEEP, &btp->bt_flags)) + continue; + set_bit(XBT_FORCE_FLUSH, &btp->bt_flags); + wake_up_process(btp->bt_task); + } + spin_unlock(&xfs_buftarg_lock); return 0; } @@ -1702,67 +1668,70 @@ xfsbufd( { struct list_head tmp; unsigned long age; - xfs_buftarg_t *target; - xfs_buf_t *pb, *n; + xfs_buftarg_t *target = (xfs_buftarg_t *)data; + xfs_buf_t *bp, *n; + struct list_head *dwq = &target->bt_delwrite_queue; + spinlock_t *dwlk = &target->bt_delwrite_lock; current->flags |= PF_MEMALLOC; INIT_LIST_HEAD(&tmp); do { if (unlikely(freezing(current))) { - xfsbufd_force_sleep = 1; + set_bit(XBT_FORCE_SLEEP, &target->bt_flags); refrigerator(); } else { - xfsbufd_force_sleep = 0; + clear_bit(XBT_FORCE_SLEEP, &target->bt_flags); } schedule_timeout_interruptible( xfs_buf_timer_centisecs * msecs_to_jiffies(10)); age = xfs_buf_age_centisecs * msecs_to_jiffies(10); - spin_lock(&pbd_delwrite_lock); - list_for_each_entry_safe(pb, n, &pbd_delwrite_queue, pb_list) { - PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb)); - ASSERT(pb->pb_flags & PBF_DELWRI); - - if (!pagebuf_ispin(pb) && !pagebuf_cond_lock(pb)) { - if (!xfsbufd_force_flush && + spin_lock(dwlk); + list_for_each_entry_safe(bp, n, dwq, b_list) { + XB_TRACE(bp, "walkq1", (long)xfs_buf_ispin(bp)); + ASSERT(bp->b_flags & XBF_DELWRI); + + if (!xfs_buf_ispin(bp) && !xfs_buf_cond_lock(bp)) { + if (!test_bit(XBT_FORCE_FLUSH, + &target->bt_flags) && time_before(jiffies, - pb->pb_queuetime + age)) { - pagebuf_unlock(pb); + bp->b_queuetime + age)) { + xfs_buf_unlock(bp); break; } - pb->pb_flags &= ~(PBF_DELWRI|_PBF_DELWRI_Q); - pb->pb_flags |= PBF_WRITE; - list_move(&pb->pb_list, &tmp); + bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q); + bp->b_flags |= XBF_WRITE; + list_move(&bp->b_list, &tmp); } } - spin_unlock(&pbd_delwrite_lock); + spin_unlock(dwlk); while (!list_empty(&tmp)) { - pb = list_entry(tmp.next, xfs_buf_t, pb_list); - target = pb->pb_target; + bp = list_entry(tmp.next, xfs_buf_t, b_list); + ASSERT(target == bp->b_target); - list_del_init(&pb->pb_list); - pagebuf_iostrategy(pb); + list_del_init(&bp->b_list); + xfs_buf_iostrategy(bp); - blk_run_address_space(target->pbr_mapping); + blk_run_address_space(target->bt_mapping); } if (as_list_len > 0) purge_addresses(); - xfsbufd_force_flush = 0; + clear_bit(XBT_FORCE_FLUSH, &target->bt_flags); } while (!kthread_should_stop()); return 0; } /* - * Go through all incore buffers, and release buffers if they belong to - * the given device. This is used in filesystem error handling to - * preserve the consistency of its metadata. + * Go through all incore buffers, and release buffers if they belong to + * the given device. This is used in filesystem error handling to + * preserve the consistency of its metadata. */ int xfs_flush_buftarg( @@ -1770,73 +1739,72 @@ xfs_flush_buftarg( int wait) { struct list_head tmp; - xfs_buf_t *pb, *n; + xfs_buf_t *bp, *n; int pincount = 0; + struct list_head *dwq = &target->bt_delwrite_queue; + spinlock_t *dwlk = &target->bt_delwrite_lock; - pagebuf_runall_queues(xfsdatad_workqueue); - pagebuf_runall_queues(xfslogd_workqueue); + xfs_buf_runall_queues(xfsdatad_workqueue); + xfs_buf_runall_queues(xfslogd_workqueue); INIT_LIST_HEAD(&tmp); - spin_lock(&pbd_delwrite_lock); - list_for_each_entry_safe(pb, n, &pbd_delwrite_queue, pb_list) { - - if (pb->pb_target != target) - continue; - - ASSERT(pb->pb_flags & (PBF_DELWRI|_PBF_DELWRI_Q)); - PB_TRACE(pb, "walkq2", (long)pagebuf_ispin(pb)); - if (pagebuf_ispin(pb)) { + spin_lock(dwlk); + list_for_each_entry_safe(bp, n, dwq, b_list) { + ASSERT(bp->b_target == target); + ASSERT(bp->b_flags & (XBF_DELWRI | _XBF_DELWRI_Q)); + XB_TRACE(bp, "walkq2", (long)xfs_buf_ispin(bp)); + if (xfs_buf_ispin(bp)) { pincount++; continue; } - list_move(&pb->pb_list, &tmp); + list_move(&bp->b_list, &tmp); } - spin_unlock(&pbd_delwrite_lock); + spin_unlock(dwlk); /* * Dropped the delayed write list lock, now walk the temporary list */ - list_for_each_entry_safe(pb, n, &tmp, pb_list) { - pagebuf_lock(pb); - pb->pb_flags &= ~(PBF_DELWRI|_PBF_DELWRI_Q); - pb->pb_flags |= PBF_WRITE; + list_for_each_entry_safe(bp, n, &tmp, b_list) { + xfs_buf_lock(bp); + bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q); + bp->b_flags |= XBF_WRITE; if (wait) - pb->pb_flags &= ~PBF_ASYNC; + bp->b_flags &= ~XBF_ASYNC; else - list_del_init(&pb->pb_list); + list_del_init(&bp->b_list); - pagebuf_iostrategy(pb); + xfs_buf_iostrategy(bp); } /* * Remaining list items must be flushed before returning */ while (!list_empty(&tmp)) { - pb = list_entry(tmp.next, xfs_buf_t, pb_list); + bp = list_entry(tmp.next, xfs_buf_t, b_list); - list_del_init(&pb->pb_list); - xfs_iowait(pb); - xfs_buf_relse(pb); + list_del_init(&bp->b_list); + xfs_iowait(bp); + xfs_buf_relse(bp); } if (wait) - blk_run_address_space(target->pbr_mapping); + blk_run_address_space(target->bt_mapping); return pincount; } int __init -pagebuf_init(void) +xfs_buf_init(void) { int error = -ENOMEM; -#ifdef PAGEBUF_TRACE - pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP); +#ifdef XFS_BUF_TRACE + xfs_buf_trace_buf = ktrace_alloc(XFS_BUF_TRACE_SIZE, KM_SLEEP); #endif - pagebuf_zone = kmem_zone_init(sizeof(xfs_buf_t), "xfs_buf"); - if (!pagebuf_zone) + xfs_buf_zone = kmem_zone_init(sizeof(xfs_buf_t), "xfs_buf"); + if (!xfs_buf_zone) goto out_free_trace_buf; xfslogd_workqueue = create_workqueue("xfslogd"); @@ -1847,42 +1815,33 @@ pagebuf_init(void) if (!xfsdatad_workqueue) goto out_destroy_xfslogd_workqueue; - xfsbufd_task = kthread_run(xfsbufd, NULL, "xfsbufd"); - if (IS_ERR(xfsbufd_task)) { - error = PTR_ERR(xfsbufd_task); + xfs_buf_shake = kmem_shake_register(xfsbufd_wakeup); + if (!xfs_buf_shake) goto out_destroy_xfsdatad_workqueue; - } - - pagebuf_shake = kmem_shake_register(xfsbufd_wakeup); - if (!pagebuf_shake) - goto out_stop_xfsbufd; return 0; - out_stop_xfsbufd: - kthread_stop(xfsbufd_task); out_destroy_xfsdatad_workqueue: destroy_workqueue(xfsdatad_workqueue); out_destroy_xfslogd_workqueue: destroy_workqueue(xfslogd_workqueue); out_free_buf_zone: - kmem_zone_destroy(pagebuf_zone); + kmem_zone_destroy(xfs_buf_zone); out_free_trace_buf: -#ifdef PAGEBUF_TRACE - ktrace_free(pagebuf_trace_buf); +#ifdef XFS_BUF_TRACE + ktrace_free(xfs_buf_trace_buf); #endif return error; } void -pagebuf_terminate(void) +xfs_buf_terminate(void) { - kmem_shake_deregister(pagebuf_shake); - kthread_stop(xfsbufd_task); + kmem_shake_deregister(xfs_buf_shake); destroy_workqueue(xfsdatad_workqueue); destroy_workqueue(xfslogd_workqueue); - kmem_zone_destroy(pagebuf_zone); -#ifdef PAGEBUF_TRACE - ktrace_free(pagebuf_trace_buf); + kmem_zone_destroy(xfs_buf_zone); +#ifdef XFS_BUF_TRACE + ktrace_free(xfs_buf_trace_buf); #endif } diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index 237a35b915d..4dd6592d5a4 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h @@ -32,44 +32,47 @@ * Base types */ -#define XFS_BUF_DADDR_NULL ((xfs_daddr_t) (-1LL)) - -#define page_buf_ctob(pp) ((pp) * PAGE_CACHE_SIZE) -#define page_buf_btoc(dd) (((dd) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) -#define page_buf_btoct(dd) ((dd) >> PAGE_CACHE_SHIFT) -#define page_buf_poff(aa) ((aa) & ~PAGE_CACHE_MASK) - -typedef enum page_buf_rw_e { - PBRW_READ = 1, /* transfer into target memory */ - PBRW_WRITE = 2, /* transfer from target memory */ - PBRW_ZERO = 3 /* Zero target memory */ -} page_buf_rw_t; - - -typedef enum page_buf_flags_e { /* pb_flags values */ - PBF_READ = (1 << 0), /* buffer intended for reading from device */ - PBF_WRITE = (1 << 1), /* buffer intended for writing to device */ - PBF_MAPPED = (1 << 2), /* buffer mapped (pb_addr valid) */ - PBF_ASYNC = (1 << 4), /* initiator will not wait for completion */ - PBF_DONE = (1 << 5), /* all pages in the buffer uptodate */ - PBF_DELWRI = (1 << 6), /* buffer has dirty pages */ - PBF_STALE = (1 << 7), /* buffer has been staled, do not find it */ - PBF_FS_MANAGED = (1 << 8), /* filesystem controls freeing memory */ - PBF_ORDERED = (1 << 11), /* use ordered writes */ - PBF_READ_AHEAD = (1 << 12), /* asynchronous read-ahead */ +#define XFS_BUF_DADDR_NULL ((xfs_daddr_t) (-1LL)) + +#define xfs_buf_ctob(pp) ((pp) * PAGE_CACHE_SIZE) +#define xfs_buf_btoc(dd) (((dd) + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT) +#define xfs_buf_btoct(dd) ((dd) >> PAGE_CACHE_SHIFT) +#define xfs_buf_poff(aa) ((aa) & ~PAGE_CACHE_MASK) + +typedef enum { + XBRW_READ = 1, /* transfer into target memory */ + XBRW_WRITE = 2, /* transfer from target memory */ + XBRW_ZERO = 3, /* Zero target memory */ +} xfs_buf_rw_t; + +typedef enum { + XBF_READ = (1 << 0), /* buffer intended for reading from device */ + XBF_WRITE = (1 << 1), /* buffer intended for writing to device */ + XBF_MAPPED = (1 << 2), /* buffer mapped (b_addr valid) */ + XBF_ASYNC = (1 << 4), /* initiator will not wait for completion */ + XBF_DONE = (1 << 5), /* all pages in the buffer uptodate */ + XBF_DELWRI = (1 << 6), /* buffer has dirty pages */ + XBF_STALE = (1 << 7), /* buffer has been staled, do not find it */ + XBF_FS_MANAGED = (1 << 8), /* filesystem controls freeing memory */ + XBF_ORDERED = (1 << 11), /* use ordered writes */ + XBF_READ_AHEAD = (1 << 12), /* asynchronous read-ahead */ /* flags used only as arguments to access routines */ - PBF_LOCK = (1 << 14), /* lock requested */ - PBF_TRYLOCK = (1 << 15), /* lock requested, but do not wait */ - PBF_DONT_BLOCK = (1 << 16), /* do not block in current thread */ + XBF_LOCK = (1 << 14), /* lock requested */ + XBF_TRYLOCK = (1 << 15), /* lock requested, but do not wait */ + XBF_DONT_BLOCK = (1 << 16), /* do not block in current thread */ /* flags used only internally */ - _PBF_PAGE_CACHE = (1 << 17),/* backed by pagecache */ - _PBF_KMEM_ALLOC = (1 << 18),/* backed by kmem_alloc() */ - _PBF_RUN_QUEUES = (1 << 19),/* run block device task queue */ - _PBF_DELWRI_Q = (1 << 21), /* buffer on delwri queue */ -} page_buf_flags_t; + _XBF_PAGE_CACHE = (1 << 17),/* backed by pagecache */ + _XBF_KMEM_ALLOC = (1 << 18),/* backed by kmem_alloc() */ + _XBF_RUN_QUEUES = (1 << 19),/* run block device task queue */ + _XBF_DELWRI_Q = (1 << 21), /* buffer on delwri queue */ +} xfs_buf_flags_t; +typedef enum { + XBT_FORCE_SLEEP = (0 << 1), + XBT_FORCE_FLUSH = (1 << 1), +} xfs_buftarg_flags_t; typedef struct xfs_bufhash { struct list_head bh_list; @@ -77,477 +80,350 @@ typedef struct xfs_bufhash { } xfs_bufhash_t; typedef struct xfs_buftarg { - dev_t pbr_dev; - struct block_device *pbr_bdev; - struct address_space *pbr_mapping; - unsigned int pbr_bsize; - unsigned int pbr_sshift; - size_t pbr_smask; - - /* per-device buffer hash table */ + dev_t bt_dev; + struct block_device *bt_bdev; + struct address_space *bt_mapping; + unsigned int bt_bsize; + unsigned int bt_sshift; + size_t bt_smask; + + /* per device buffer hash table */ uint bt_hashmask; uint bt_hashshift; xfs_bufhash_t *bt_hash; + + /* per device delwri queue */ + struct task_struct *bt_task; + struct list_head bt_list; + struct list_head bt_delwrite_queue; + spinlock_t bt_delwrite_lock; + unsigned long bt_flags; } xfs_buftarg_t; /* - * xfs_buf_t: Buffer structure for page cache-based buffers + * xfs_buf_t: Buffer structure for pagecache-based buffers + * + * This buffer structure is used by the pagecache buffer management routines + * to refer to an assembly of pages forming a logical buffer. * - * This buffer structure is used by the page cache buffer management routines - * to refer to an assembly of pages forming a logical buffer. The actual I/O - * is performed with buffer_head structures, as required by drivers. - * - * The buffer structure is used on temporary basis only, and discarded when - * released. The real data storage is recorded in the page cache. Metadata is + * The buffer structure is used on a temporary basis only, and discarded when + * released. The real data storage is recorded in the pagecache. Buffers are * hashed to the block device on which the file system resides. */ struct xfs_buf; +typedef void (*xfs_buf_iodone_t)(struct xfs_buf *); +typedef void (*xfs_buf_relse_t)(struct xfs_buf *); +typedef int (*xfs_buf_bdstrat_t)(struct xfs_buf *); -/* call-back function on I/O completion */ -typedef void (*page_buf_iodone_t)(struct xfs_buf *); -/* call-back function on I/O completion */ -typedef void (*page_buf_relse_t)(struct xfs_buf *); -/* pre-write function */ -typedef int (*page_buf_bdstrat_t)(struct xfs_buf *); - -#define PB_PAGES 2 +#define XB_PAGES 2 typedef struct xfs_buf { - struct semaphore pb_sema; /* semaphore for lockables */ - unsigned long pb_queuetime; /* time buffer was queued */ - atomic_t pb_pin_count; /* pin count */ - wait_queue_head_t pb_waiters; /* unpin waiters */ - struct list_head pb_list; - page_buf_flags_t pb_flags; /* status flags */ - struct list_head pb_hash_list; /* hash table list */ - xfs_bufhash_t *pb_hash; /* hash table list start */ - xfs_buftarg_t *pb_target; /* buffer target (device) */ - atomic_t pb_hold; /* reference count */ - xfs_daddr_t pb_bn; /* block number for I/O */ - loff_t pb_file_offset; /* offset in file */ - size_t pb_buffer_length; /* size of buffer in bytes */ - size_t pb_count_desired; /* desired transfer size */ - void *pb_addr; /* virtual address of buffer */ - struct work_struct pb_iodone_work; - atomic_t pb_io_remaining;/* #outstanding I/O requests */ - page_buf_iodone_t pb_iodone; /* I/O completion function */ - page_buf_relse_t pb_relse; /* releasing function */ - page_buf_bdstrat_t pb_strat; /* pre-write function */ - struct semaphore pb_iodonesema; /* Semaphore for I/O waiters */ - void *pb_fspriv; - void *pb_fspriv2; - void *pb_fspriv3; - unsigned short pb_error; /* error code on I/O */ - unsigned short pb_locked; /* page array is locked */ - unsigned int pb_page_count; /* size of page array */ - unsigned int pb_offset; /* page offset in first page */ - struct page **pb_pages; /* array of page pointers */ - struct page *pb_page_array[PB_PAGES]; /* inline pages */ -#ifdef PAGEBUF_LOCK_TRACKING - int pb_last_holder; + struct semaphore b_sema; /* semaphore for lockables */ + unsigned long b_queuetime; /* time buffer was queued */ + atomic_t b_pin_count; /* pin count */ + wait_queue_head_t b_waiters; /* unpin waiters */ + struct list_head b_list; + xfs_buf_flags_t b_flags; /* status flags */ + struct list_head b_hash_list; /* hash table list */ + xfs_bufhash_t *b_hash; /* hash table list start */ + xfs_buftarg_t *b_target; /* buffer target (device) */ + atomic_t b_hold; /* reference count */ + xfs_daddr_t b_bn; /* block number for I/O */ + xfs_off_t b_file_offset; /* offset in file */ + size_t b_buffer_length;/* size of buffer in bytes */ + size_t b_count_desired;/* desired transfer size */ + void *b_addr; /* virtual address of buffer */ + struct work_struct b_iodone_work; + atomic_t b_io_remaining; /* #outstanding I/O requests */ + xfs_buf_iodone_t b_iodone; /* I/O completion function */ + xfs_buf_relse_t b_relse; /* releasing function */ + xfs_buf_bdstrat_t b_strat; /* pre-write function */ + struct semaphore b_iodonesema; /* Semaphore for I/O waiters */ + void *b_fspriv; + void *b_fspriv2; + void *b_fspriv3; + unsigned short b_error; /* error code on I/O */ + unsigned short b_locked; /* page array is locked */ + unsigned int b_page_count; /* size of page array */ + unsigned int b_offset; /* page offset in first page */ + struct page **b_pages; /* array of page pointers */ + struct page *b_page_array[XB_PAGES]; /* inline pages */ +#ifdef XFS_BUF_LOCK_TRACKING + int b_last_holder; #endif } xfs_buf_t; /* Finding and Reading Buffers */ - -extern xfs_buf_t *_pagebuf_find( /* find buffer for block if */ - /* the block is in memory */ - xfs_buftarg_t *, /* inode for block */ - loff_t, /* starting offset of range */ - size_t, /* length of range */ - page_buf_flags_t, /* PBF_LOCK */ - xfs_buf_t *); /* newly allocated buffer */ - +extern xfs_buf_t *_xfs_buf_find(xfs_buftarg_t *, xfs_off_t, size_t, + xfs_buf_flags_t, xfs_buf_t *); #define xfs_incore(buftarg,blkno,len,lockit) \ - _pagebuf_find(buftarg, blkno ,len, lockit, NULL) - -extern xfs_buf_t *xfs_buf_get_flags( /* allocate a buffer */ - xfs_buftarg_t *, /* inode for buffer */ - loff_t, /* starting offset of range */ - size_t, /* length of range */ - page_buf_flags_t); /* PBF_LOCK, PBF_READ, */ - /* PBF_ASYNC */ + _xfs_buf_find(buftarg, blkno ,len, lockit, NULL) +extern xfs_buf_t *xfs_buf_get_flags(xfs_buftarg_t *, xfs_off_t, size_t, + xfs_buf_flags_t); #define xfs_buf_get(target, blkno, len, flags) \ - xfs_buf_get_flags((target), (blkno), (len), PBF_LOCK | PBF_MAPPED) - -extern xfs_buf_t *xfs_buf_read_flags( /* allocate and read a buffer */ - xfs_buftarg_t *, /* inode for buffer */ - loff_t, /* starting offset of range */ - size_t, /* length of range */ - page_buf_flags_t); /* PBF_LOCK, PBF_ASYNC */ + xfs_buf_get_flags((target), (blkno), (len), XBF_LOCK | XBF_MAPPED) +extern xfs_buf_t *xfs_buf_read_flags(xfs_buftarg_t *, xfs_off_t, size_t, + xfs_buf_flags_t); #define xfs_buf_read(target, blkno, len, flags) \ - xfs_buf_read_flags((target), (blkno), (len), PBF_LOCK | PBF_MAPPED) - -extern xfs_buf_t *pagebuf_get_empty( /* allocate pagebuf struct with */ - /* no memory or disk address */ - size_t len, - xfs_buftarg_t *); /* mount point "fake" inode */ - -extern xfs_buf_t *pagebuf_get_no_daddr(/* allocate pagebuf struct */ - /* without disk address */ - size_t len, - xfs_buftarg_t *); /* mount point "fake" inode */ - -extern int pagebuf_associate_memory( - xfs_buf_t *, - void *, - size_t); - -extern void pagebuf_hold( /* increment reference count */ - xfs_buf_t *); /* buffer to hold */ + xfs_buf_read_flags((target), (blkno), (len), XBF_LOCK | XBF_MAPPED) -extern void pagebuf_readahead( /* read ahead into cache */ - xfs_buftarg_t *, /* target for buffer (or NULL) */ - loff_t, /* starting offset of range */ - size_t, /* length of range */ - page_buf_flags_t); /* additional read flags */ +extern xfs_buf_t *xfs_buf_get_empty(size_t, xfs_buftarg_t *); +extern xfs_buf_t *xfs_buf_get_noaddr(size_t, xfs_buftarg_t *); +extern int xfs_buf_associate_memory(xfs_buf_t *, void *, size_t); +extern void xfs_buf_hold(xfs_buf_t *); +extern void xfs_buf_readahead(xfs_buftarg_t *, xfs_off_t, size_t, + xfs_buf_flags_t); /* Releasing Buffers */ - -extern void pagebuf_free( /* deallocate a buffer */ - xfs_buf_t *); /* buffer to deallocate */ - -extern void pagebuf_rele( /* release hold on a buffer */ - xfs_buf_t *); /* buffer to release */ +extern void xfs_buf_free(xfs_buf_t *); +extern void xfs_buf_rele(xfs_buf_t *); /* Locking and Unlocking Buffers */ - -extern int pagebuf_cond_lock( /* lock buffer, if not locked */ - /* (returns -EBUSY if locked) */ - xfs_buf_t *); /* buffer to lock */ - -extern int pagebuf_lock_value( /* return count on lock */ - xfs_buf_t *); /* buffer to check */ - -extern int pagebuf_lock( /* lock buffer */ - xfs_buf_t *); /* buffer to lock */ - -extern void pagebuf_unlock( /* unlock buffer */ - xfs_buf_t *); /* buffer to unlock */ +extern int xfs_buf_cond_lock(xfs_buf_t *); +extern int xfs_buf_lock_value(xfs_buf_t *); +extern void xfs_buf_lock(xfs_buf_t *); +extern void xfs_buf_unlock(xfs_buf_t *); /* Buffer Read and Write Routines */ - -extern void pagebuf_iodone( /* mark buffer I/O complete */ - xfs_buf_t *, /* buffer to mark */ - int); /* run completion locally, or in - * a helper thread. */ - -extern void pagebuf_ioerror( /* mark buffer in error (or not) */ - xfs_buf_t *, /* buffer to mark */ - int); /* error to store (0 if none) */ - -extern int pagebuf_iostart( /* start I/O on a buffer */ - xfs_buf_t *, /* buffer to start */ - page_buf_flags_t); /* PBF_LOCK, PBF_ASYNC, */ - /* PBF_READ, PBF_WRITE, */ - /* PBF_DELWRI */ - -extern int pagebuf_iorequest( /* start real I/O */ - xfs_buf_t *); /* buffer to convey to device */ - -extern int pagebuf_iowait( /* wait for buffer I/O done */ - xfs_buf_t *); /* buffer to wait on */ - -extern void pagebuf_iomove( /* move data in/out of pagebuf */ - xfs_buf_t *, /* buffer to manipulate */ - size_t, /* starting buffer offset */ - size_t, /* length in buffer */ - caddr_t, /* data pointer */ - page_buf_rw_t); /* direction */ - -static inline int pagebuf_iostrategy(xfs_buf_t *pb) +extern void xfs_buf_ioend(xfs_buf_t *, int); +extern void xfs_buf_ioerror(xfs_buf_t *, int); +extern int xfs_buf_iostart(xfs_buf_t *, xfs_buf_flags_t); +extern int xfs_buf_iorequest(xfs_buf_t *); +extern int xfs_buf_iowait(xfs_buf_t *); +extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, xfs_caddr_t, + xfs_buf_rw_t); + +static inline int xfs_buf_iostrategy(xfs_buf_t *bp) { - return pb->pb_strat ? pb->pb_strat(pb) : pagebuf_iorequest(pb); + return bp->b_strat ? bp->b_strat(bp) : xfs_buf_iorequest(bp); } -static inline int pagebuf_geterror(xfs_buf_t *pb) +static inline int xfs_buf_geterror(xfs_buf_t *bp) { - return pb ? pb->pb_error : ENOMEM; + return bp ? bp->b_error : ENOMEM; } /* Buffer Utility Routines */ - -extern caddr_t pagebuf_offset( /* pointer at offset in buffer */ - xfs_buf_t *, /* buffer to offset into */ - size_t); /* offset */ +extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t); /* Pinning Buffer Storage in Memory */ - -extern void pagebuf_pin( /* pin buffer in memory */ - xfs_buf_t *); /* buffer to pin */ - -extern void pagebuf_unpin( /* unpin buffered data */ - xfs_buf_t *); /* buffer to unpin */ - -extern int pagebuf_ispin( /* check if buffer is pinned */ - xfs_buf_t *); /* buffer to check */ +extern void xfs_buf_pin(xfs_buf_t *); +extern void xfs_buf_unpin(xfs_buf_t *); +extern int xfs_buf_ispin(xfs_buf_t *); /* Delayed Write Buffer Routines */ - -extern void pagebuf_delwri_dequeue(xfs_buf_t *); +extern void xfs_buf_delwri_dequeue(xfs_buf_t *); /* Buffer Daemon Setup Routines */ +extern int xfs_buf_init(void); +extern void xfs_buf_terminate(void); -extern int pagebuf_init(void); -extern void pagebuf_terminate(void); - - -#ifdef PAGEBUF_TRACE -extern ktrace_t *pagebuf_trace_buf; -extern void pagebuf_trace( - xfs_buf_t *, /* buffer being traced */ - char *, /* description of operation */ - void *, /* arbitrary diagnostic value */ - void *); /* return address */ +#ifdef XFS_BUF_TRACE +extern ktrace_t *xfs_buf_trace_buf; +extern void xfs_buf_trace(xfs_buf_t *, char *, void *, void *); #else -# define pagebuf_trace(pb, id, ptr, ra) do { } while (0) +#define xfs_buf_trace(bp,id,ptr,ra) do { } while (0) #endif -#define pagebuf_target_name(target) \ - ({ char __b[BDEVNAME_SIZE]; bdevname((target)->pbr_bdev, __b); __b; }) +#define xfs_buf_target_name(target) \ + ({ char __b[BDEVNAME_SIZE]; bdevname((target)->bt_bdev, __b); __b; }) +#define XFS_B_ASYNC XBF_ASYNC +#define XFS_B_DELWRI XBF_DELWRI +#define XFS_B_READ XBF_READ +#define XFS_B_WRITE XBF_WRITE +#define XFS_B_STALE XBF_STALE -/* These are just for xfs_syncsub... it sets an internal variable - * then passes it to VOP_FLUSH_PAGES or adds the flags to a newly gotten buf_t - */ -#define XFS_B_ASYNC PBF_ASYNC -#define XFS_B_DELWRI PBF_DELWRI -#define XFS_B_READ PBF_READ -#define XFS_B_WRITE PBF_WRITE -#define XFS_B_STALE PBF_STALE - -#define XFS_BUF_TRYLOCK PBF_TRYLOCK -#define XFS_INCORE_TRYLOCK PBF_TRYLOCK -#define XFS_BUF_LOCK PBF_LOCK -#define XFS_BUF_MAPPED PBF_MAPPED - -#define BUF_BUSY PBF_DONT_BLOCK - -#define XFS_BUF_BFLAGS(x) ((x)->pb_flags) -#define XFS_BUF_ZEROFLAGS(x) \ - ((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_DELWRI)) - -#define XFS_BUF_STALE(x) ((x)->pb_flags |= XFS_B_STALE) -#define XFS_BUF_UNSTALE(x) ((x)->pb_flags &= ~XFS_B_STALE) -#define XFS_BUF_ISSTALE(x) ((x)->pb_flags & XFS_B_STALE) -#define XFS_BUF_SUPER_STALE(x) do { \ - XFS_BUF_STALE(x); \ - pagebuf_delwri_dequeue(x); \ - XFS_BUF_DONE(x); \ - } while (0) +#define XFS_BUF_TRYLOCK XBF_TRYLOCK +#define XFS_INCORE_TRYLOCK XBF_TRYLOCK +#define XFS_BUF_LOCK XBF_LOCK +#define XFS_BUF_MAPPED XBF_MAPPED -#define XFS_BUF_MANAGE PBF_FS_MANAGED -#define XFS_BUF_UNMANAGE(x) ((x)->pb_flags &= ~PBF_FS_MANAGED) - -#define XFS_BUF_DELAYWRITE(x) ((x)->pb_flags |= PBF_DELWRI) -#define XFS_BUF_UNDELAYWRITE(x) pagebuf_delwri_dequeue(x) -#define XFS_BUF_ISDELAYWRITE(x) ((x)->pb_flags & PBF_DELWRI) - -#define XFS_BUF_ERROR(x,no) pagebuf_ioerror(x,no) -#define XFS_BUF_GETERROR(x) pagebuf_geterror(x) -#define XFS_BUF_ISERROR(x) (pagebuf_geterror(x)?1:0) - -#define XFS_BUF_DONE(x) ((x)->pb_flags |= PBF_DONE) -#define XFS_BUF_UNDONE(x) ((x)->pb_flags &= ~PBF_DONE) -#define XFS_BUF_ISDONE(x) ((x)->pb_flags & PBF_DONE) - -#define XFS_BUF_BUSY(x) do { } while (0) -#define XFS_BUF_UNBUSY(x) do { } while (0) -#define XFS_BUF_ISBUSY(x) (1) - -#define XFS_BUF_ASYNC(x) ((x)->pb_flags |= PBF_ASYNC) -#define XFS_BUF_UNASYNC(x) ((x)->pb_flags &= ~PBF_ASYNC) -#define XFS_BUF_ISASYNC(x) ((x)->pb_flags & PBF_ASYNC) - -#define XFS_BUF_ORDERED(x) ((x)->pb_flags |= PBF_ORDERED) -#define XFS_BUF_UNORDERED(x) ((x)->pb_flags &= ~PBF_ORDERED) -#define XFS_BUF_ISORDERED(x) ((x)->pb_flags & PBF_ORDERED) - -#define XFS_BUF_SHUT(x) printk("XFS_BUF_SHUT not implemented yet\n") -#define XFS_BUF_UNSHUT(x) printk("XFS_BUF_UNSHUT not implemented yet\n") -#define XFS_BUF_ISSHUT(x) (0) - -#define XFS_BUF_HOLD(x) pagebuf_hold(x) -#define XFS_BUF_READ(x) ((x)->pb_flags |= PBF_READ) -#define XFS_BUF_UNREAD(x) ((x)->pb_flags &= ~PBF_READ) -#define XFS_BUF_ISREAD(x) ((x)->pb_flags & PBF_READ) - -#define XFS_BUF_WRITE(x) ((x)->pb_flags |= PBF_WRITE) -#define XFS_BUF_UNWRITE(x) ((x)->pb_flags &= ~PBF_WRITE) -#define XFS_BUF_ISWRITE(x) ((x)->pb_flags & PBF_WRITE) - -#define XFS_BUF_ISUNINITIAL(x) (0) -#define XFS_BUF_UNUNINITIAL(x) (0) - -#define XFS_BUF_BP_ISMAPPED(bp) 1 - -#define XFS_BUF_IODONE_FUNC(buf) (buf)->pb_iodone -#define XFS_BUF_SET_IODONE_FUNC(buf, func) \ - (buf)->pb_iodone = (func) -#define XFS_BUF_CLR_IODONE_FUNC(buf) \ - (buf)->pb_iodone = NULL -#define XFS_BUF_SET_BDSTRAT_FUNC(buf, func) \ - (buf)->pb_strat = (func) -#define XFS_BUF_CLR_BDSTRAT_FUNC(buf) \ - (buf)->pb_strat = NULL - -#define XFS_BUF_FSPRIVATE(buf, type) \ - ((type)(buf)->pb_fspriv) -#define XFS_BUF_SET_FSPRIVATE(buf, value) \ - (buf)->pb_fspriv = (void *)(value) -#define XFS_BUF_FSPRIVATE2(buf, type) \ - ((type)(buf)->pb_fspriv2) -#define XFS_BUF_SET_FSPRIVATE2(buf, value) \ - (buf)->pb_fspriv2 = (void *)(value) -#define XFS_BUF_FSPRIVATE3(buf, type) \ - ((type)(buf)->pb_fspriv3) -#define XFS_BUF_SET_FSPRIVATE3(buf, value) \ - (buf)->pb_fspriv3 = (void *)(value) -#define XFS_BUF_SET_START(buf) - -#define XFS_BUF_SET_BRELSE_FUNC(buf, value) \ - (buf)->pb_relse = (value) - -#define XFS_BUF_PTR(bp) (xfs_caddr_t)((bp)->pb_addr) - -static inline xfs_caddr_t xfs_buf_offset(xfs_buf_t *bp, size_t offset) -{ - if (bp->pb_flags & PBF_MAPPED) - return XFS_BUF_PTR(bp) + offset; - return (xfs_caddr_t) pagebuf_offset(bp, offset); -} +#define BUF_BUSY XBF_DONT_BLOCK + +#define XFS_BUF_BFLAGS(bp) ((bp)->b_flags) +#define XFS_BUF_ZEROFLAGS(bp) \ + ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI)) + +#define XFS_BUF_STALE(bp) ((bp)->b_flags |= XFS_B_STALE) +#define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XFS_B_STALE) +#define XFS_BUF_ISSTALE(bp) ((bp)->b_flags & XFS_B_STALE) +#define XFS_BUF_SUPER_STALE(bp) do { \ + XFS_BUF_STALE(bp); \ + xfs_buf_delwri_dequeue(bp); \ + XFS_BUF_DONE(bp); \ + } while (0) -#define XFS_BUF_SET_PTR(bp, val, count) \ - pagebuf_associate_memory(bp, val, count) -#define XFS_BUF_ADDR(bp) ((bp)->pb_bn) -#define XFS_BUF_SET_ADDR(bp, blk) \ - ((bp)->pb_bn = (xfs_daddr_t)(blk)) -#define XFS_BUF_OFFSET(bp) ((bp)->pb_file_offset) -#define XFS_BUF_SET_OFFSET(bp, off) \ - ((bp)->pb_file_offset = (off)) -#define XFS_BUF_COUNT(bp) ((bp)->pb_count_desired) -#define XFS_BUF_SET_COUNT(bp, cnt) \ - ((bp)->pb_count_desired = (cnt)) -#define XFS_BUF_SIZE(bp) ((bp)->pb_buffer_length) -#define XFS_BUF_SET_SIZE(bp, cnt) \ - ((bp)->pb_buffer_length = (cnt)) -#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) -#define XFS_BUF_SET_VTYPE(bp, type) -#define XFS_BUF_SET_REF(bp, ref) - -#define XFS_BUF_ISPINNED(bp) pagebuf_ispin(bp) - -#define XFS_BUF_VALUSEMA(bp) pagebuf_lock_value(bp) -#define XFS_BUF_CPSEMA(bp) (pagebuf_cond_lock(bp) == 0) -#define XFS_BUF_VSEMA(bp) pagebuf_unlock(bp) -#define XFS_BUF_PSEMA(bp,x) pagebuf_lock(bp) -#define XFS_BUF_V_IODONESEMA(bp) up(&bp->pb_iodonesema); - -/* setup the buffer target from a buftarg structure */ -#define XFS_BUF_SET_TARGET(bp, target) \ - (bp)->pb_target = (target) -#define XFS_BUF_TARGET(bp) ((bp)->pb_target) -#define XFS_BUFTARG_NAME(target) \ - pagebuf_target_name(target) - -#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) -#define XFS_BUF_SET_VTYPE(bp, type) -#define XFS_BUF_SET_REF(bp, ref) - -static inline int xfs_bawrite(void *mp, xfs_buf_t *bp) +#define XFS_BUF_MANAGE XBF_FS_MANAGED +#define XFS_BUF_UNMANAGE(bp) ((bp)->b_flags &= ~XBF_FS_MANAGED) + +#define XFS_BUF_DELAYWRITE(bp) ((bp)->b_flags |= XBF_DELWRI) +#define XFS_BUF_UNDELAYWRITE(bp) xfs_buf_delwri_dequeue(bp) +#define XFS_BUF_ISDELAYWRITE(bp) ((bp)->b_flags & XBF_DELWRI) + +#define XFS_BUF_ERROR(bp,no) xfs_buf_ioerror(bp,no) +#define XFS_BUF_GETERROR(bp) xfs_buf_geterror(bp) +#define XFS_BUF_ISERROR(bp) (xfs_buf_geterror(bp) ? 1 : 0) + +#define XFS_BUF_DONE(bp) ((bp)->b_flags |= XBF_DONE) +#define XFS_BUF_UNDONE(bp) ((bp)->b_flags &= ~XBF_DONE) +#define XFS_BUF_ISDONE(bp) ((bp)->b_flags & XBF_DONE) + +#define XFS_BUF_BUSY(bp) do { } while (0) +#define XFS_BUF_UNBUSY(bp) do { } while (0) +#define XFS_BUF_ISBUSY(bp) (1) + +#define XFS_BUF_ASYNC(bp) ((bp)->b_flags |= XBF_ASYNC) +#define XFS_BUF_UNASYNC(bp) ((bp)->b_flags &= ~XBF_ASYNC) +#define XFS_BUF_ISASYNC(bp) ((bp)->b_flags & XBF_ASYNC) + +#define XFS_BUF_ORDERED(bp) ((bp)->b_flags |= XBF_ORDERED) +#define XFS_BUF_UNORDERED(bp) ((bp)->b_flags &= ~XBF_ORDERED) +#define XFS_BUF_ISORDERED(bp) ((bp)->b_flags & XBF_ORDERED) + +#define XFS_BUF_SHUT(bp) do { } while (0) +#define XFS_BUF_UNSHUT(bp) do { } while (0) +#define XFS_BUF_ISSHUT(bp) (0) + +#define XFS_BUF_HOLD(bp) xfs_buf_hold(bp) +#define XFS_BUF_READ(bp) ((bp)->b_flags |= XBF_READ) +#define XFS_BUF_UNREAD(bp) ((bp)->b_flags &= ~XBF_READ) +#define XFS_BUF_ISREAD(bp) ((bp)->b_flags & XBF_READ) + +#define XFS_BUF_WRITE(bp) ((bp)->b_flags |= XBF_WRITE) +#define XFS_BUF_UNWRITE(bp) ((bp)->b_flags &= ~XBF_WRITE) +#define XFS_BUF_ISWRITE(bp) ((bp)->b_flags & XBF_WRITE) + +#define XFS_BUF_ISUNINITIAL(bp) (0) +#define XFS_BUF_UNUNINITIAL(bp) (0) + +#define XFS_BUF_BP_ISMAPPED(bp) (1) + +#define XFS_BUF_IODONE_FUNC(bp) ((bp)->b_iodone) +#define XFS_BUF_SET_IODONE_FUNC(bp, func) ((bp)->b_iodone = (func)) +#define XFS_BUF_CLR_IODONE_FUNC(bp) ((bp)->b_iodone = NULL) +#define XFS_BUF_SET_BDSTRAT_FUNC(bp, func) ((bp)->b_strat = (func)) +#define XFS_BUF_CLR_BDSTRAT_FUNC(bp) ((bp)->b_strat = NULL) + +#define XFS_BUF_FSPRIVATE(bp, type) ((type)(bp)->b_fspriv) +#define XFS_BUF_SET_FSPRIVATE(bp, val) ((bp)->b_fspriv = (void*)(val)) +#define XFS_BUF_FSPRIVATE2(bp, type) ((type)(bp)->b_fspriv2) +#define XFS_BUF_SET_FSPRIVATE2(bp, val) ((bp)->b_fspriv2 = (void*)(val)) +#define XFS_BUF_FSPRIVATE3(bp, type) ((type)(bp)->b_fspriv3) +#define XFS_BUF_SET_FSPRIVATE3(bp, val) ((bp)->b_fspriv3 = (void*)(val)) +#define XFS_BUF_SET_START(bp) do { } while (0) +#define XFS_BUF_SET_BRELSE_FUNC(bp, func) ((bp)->b_relse = (func)) + +#define XFS_BUF_PTR(bp) (xfs_caddr_t)((bp)->b_addr) +#define XFS_BUF_SET_PTR(bp, val, cnt) xfs_buf_associate_memory(bp, val, cnt) +#define XFS_BUF_ADDR(bp) ((bp)->b_bn) +#define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_bn = (xfs_daddr_t)(bno)) +#define XFS_BUF_OFFSET(bp) ((bp)->b_file_offset) +#define XFS_BUF_SET_OFFSET(bp, off) ((bp)->b_file_offset = (off)) +#define XFS_BUF_COUNT(bp) ((bp)->b_count_desired) +#define XFS_BUF_SET_COUNT(bp, cnt) ((bp)->b_count_desired = (cnt)) +#define XFS_BUF_SIZE(bp) ((bp)->b_buffer_length) +#define XFS_BUF_SET_SIZE(bp, cnt) ((bp)->b_buffer_length = (cnt)) + +#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) do { } while (0) +#define XFS_BUF_SET_VTYPE(bp, type) do { } while (0) +#define XFS_BUF_SET_REF(bp, ref) do { } while (0) + +#define XFS_BUF_ISPINNED(bp) xfs_buf_ispin(bp) + +#define XFS_BUF_VALUSEMA(bp) xfs_buf_lock_value(bp) +#define XFS_BUF_CPSEMA(bp) (xfs_buf_cond_lock(bp) == 0) +#define XFS_BUF_VSEMA(bp) xfs_buf_unlock(bp) +#define XFS_BUF_PSEMA(bp,x) xfs_buf_lock(bp) +#define XFS_BUF_V_IODONESEMA(bp) up(&bp->b_iodonesema); + +#define XFS_BUF_SET_TARGET(bp, target) ((bp)->b_target = (target)) +#define XFS_BUF_TARGET(bp) ((bp)->b_target) +#define XFS_BUFTARG_NAME(target) xfs_buf_target_name(target) + +static inline int xfs_bawrite(void *mp, xfs_buf_t *bp) { - bp->pb_fspriv3 = mp; - bp->pb_strat = xfs_bdstrat_cb; - pagebuf_delwri_dequeue(bp); - return pagebuf_iostart(bp, PBF_WRITE | PBF_ASYNC | _PBF_RUN_QUEUES); + bp->b_fspriv3 = mp; + bp->b_strat = xfs_bdstrat_cb; + xfs_buf_delwri_dequeue(bp); + return xfs_buf_iostart(bp, XBF_WRITE | XBF_ASYNC | _XBF_RUN_QUEUES); } -static inline void xfs_buf_relse(xfs_buf_t *bp) +static inline void xfs_buf_relse(xfs_buf_t *bp) { - if (!bp->pb_relse) - pagebuf_unlock(bp); - pagebuf_rele(bp); + if (!bp->b_relse) + xfs_buf_unlock(bp); + xfs_buf_rele(bp); } -#define xfs_bpin(bp) pagebuf_pin(bp) -#define xfs_bunpin(bp) pagebuf_unpin(bp) +#define xfs_bpin(bp) xfs_buf_pin(bp) +#define xfs_bunpin(bp) xfs_buf_unpin(bp) #define xfs_buftrace(id, bp) \ - pagebuf_trace(bp, id, NULL, (void *)__builtin_return_address(0)) + xfs_buf_trace(bp, id, NULL, (void *)__builtin_return_address(0)) -#define xfs_biodone(pb) \ - pagebuf_iodone(pb, 0) +#define xfs_biodone(bp) xfs_buf_ioend(bp, 0) -#define xfs_biomove(pb, off, len, data, rw) \ - pagebuf_iomove((pb), (off), (len), (data), \ - ((rw) == XFS_B_WRITE) ? PBRW_WRITE : PBRW_READ) +#define xfs_biomove(bp, off, len, data, rw) \ + xfs_buf_iomove((bp), (off), (len), (data), \ + ((rw) == XFS_B_WRITE) ? XBRW_WRITE : XBRW_READ) -#define xfs_biozero(pb, off, len) \ - pagebuf_iomove((pb), (off), (len), NULL, PBRW_ZERO) +#define xfs_biozero(bp, off, len) \ + xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO) -static inline int XFS_bwrite(xfs_buf_t *pb) +static inline int XFS_bwrite(xfs_buf_t *bp) { - int iowait = (pb->pb_flags & PBF_ASYNC) == 0; + int iowait = (bp->b_flags & XBF_ASYNC) == 0; int error = 0; if (!iowait) - pb->pb_flags |= _PBF_RUN_QUEUES; + bp->b_flags |= _XBF_RUN_QUEUES; - pagebuf_delwri_dequeue(pb); - pagebuf_iostrategy(pb); + xfs_buf_delwri_dequeue(bp); + xfs_buf_iostrategy(bp); if (iowait) { - error = pagebuf_iowait(pb); - xfs_buf_relse(pb); + error = xfs_buf_iowait(bp); + xfs_buf_relse(bp); } return error; } -#define XFS_bdwrite(pb) \ - pagebuf_iostart(pb, PBF_DELWRI | PBF_ASYNC) +#define XFS_bdwrite(bp) xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC) static inline int xfs_bdwrite(void *mp, xfs_buf_t *bp) { - bp->pb_strat = xfs_bdstrat_cb; - bp->pb_fspriv3 = mp; - - return pagebuf_iostart(bp, PBF_DELWRI | PBF_ASYNC); + bp->b_strat = xfs_bdstrat_cb; + bp->b_fspriv3 = mp; + return xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC); } -#define XFS_bdstrat(bp) pagebuf_iorequest(bp) +#define XFS_bdstrat(bp) xfs_buf_iorequest(bp) -#define xfs_iowait(pb) pagebuf_iowait(pb) +#define xfs_iowait(bp) xfs_buf_iowait(bp) #define xfs_baread(target, rablkno, ralen) \ - pagebuf_readahead((target), (rablkno), (ralen), PBF_DONT_BLOCK) - -#define xfs_buf_get_empty(len, target) pagebuf_get_empty((len), (target)) -#define xfs_buf_get_noaddr(len, target) pagebuf_get_no_daddr((len), (target)) -#define xfs_buf_free(bp) pagebuf_free(bp) + xfs_buf_readahead((target), (rablkno), (ralen), XBF_DONT_BLOCK) /* * Handling of buftargs. */ - extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int); extern void xfs_free_buftarg(xfs_buftarg_t *, int); extern void xfs_wait_buftarg(xfs_buftarg_t *); extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int); extern int xfs_flush_buftarg(xfs_buftarg_t *, int); -#define xfs_getsize_buftarg(buftarg) \ - block_size((buftarg)->pbr_bdev) -#define xfs_readonly_buftarg(buftarg) \ - bdev_read_only((buftarg)->pbr_bdev) -#define xfs_binval(buftarg) \ - xfs_flush_buftarg(buftarg, 1) -#define XFS_bflush(buftarg) \ - xfs_flush_buftarg(buftarg, 1) +#define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev) +#define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev) + +#define xfs_binval(buftarg) xfs_flush_buftarg(buftarg, 1) +#define XFS_bflush(buftarg) xfs_flush_buftarg(buftarg, 1) #endif /* __XFS_BUF_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 06111d0bbae..ced4404339c 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -509,16 +509,14 @@ linvfs_open_exec( vnode_t *vp = LINVFS_GET_VP(inode); xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); int error = 0; - bhv_desc_t *bdp; xfs_inode_t *ip; if (vp->v_vfsp->vfs_flag & VFS_DMI) { - bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops); - if (!bdp) { + ip = xfs_vtoi(vp); + if (!ip) { error = -EINVAL; goto open_exec_out; } - ip = XFS_BHVTOI(bdp); if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)) { error = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, 0, 0, 0, NULL); diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 21667ba6dcd..4db47790415 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -146,13 +146,10 @@ xfs_find_handle( if (cmd != XFS_IOC_PATH_TO_FSHANDLE) { xfs_inode_t *ip; - bhv_desc_t *bhv; int lock_mode; /* need to get access to the xfs_inode to read the generation */ - bhv = vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops); - ASSERT(bhv); - ip = XFS_BHVTOI(bhv); + ip = xfs_vtoi(vp); ASSERT(ip); lock_mode = xfs_ilock_map_shared(ip); @@ -751,9 +748,8 @@ xfs_ioctl( (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? mp->m_rtdev_targp : mp->m_ddev_targp; - da.d_mem = da.d_miniosz = 1 << target->pbr_sshift; - /* The size dio will do in one go */ - da.d_maxiosz = 64 * PAGE_CACHE_SIZE; + da.d_mem = da.d_miniosz = 1 << target->bt_sshift; + da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1); if (copy_to_user(arg, &da, sizeof(da))) return -XFS_ERROR(EFAULT); diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 9b8ee3470ec..4bd3d03b23e 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -54,11 +54,46 @@ #include <linux/capability.h> #include <linux/xattr.h> #include <linux/namei.h> +#include <linux/security.h> #define IS_NOATIME(inode) ((inode->i_sb->s_flags & MS_NOATIME) || \ (S_ISDIR(inode->i_mode) && inode->i_sb->s_flags & MS_NODIRATIME)) /* + * Get a XFS inode from a given vnode. + */ +xfs_inode_t * +xfs_vtoi( + struct vnode *vp) +{ + bhv_desc_t *bdp; + + bdp = bhv_lookup_range(VN_BHV_HEAD(vp), + VNODE_POSITION_XFS, VNODE_POSITION_XFS); + if (unlikely(bdp == NULL)) + return NULL; + return XFS_BHVTOI(bdp); +} + +/* + * Bring the atime in the XFS inode uptodate. + * Used before logging the inode to disk or when the Linux inode goes away. + */ +void +xfs_synchronize_atime( + xfs_inode_t *ip) +{ + vnode_t *vp; + + vp = XFS_ITOV_NULL(ip); + if (vp) { + struct inode *inode = &vp->v_inode; + ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; + ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec; + } +} + +/* * Change the requested timestamp in the given inode. * We don't lock across timestamp updates, and we don't log them but * we do record the fact that there is dirty information in core. @@ -77,23 +112,6 @@ xfs_ichgtime( struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip)); timespec_t tv; - /* - * We're not supposed to change timestamps in readonly-mounted - * filesystems. Throw it away if anyone asks us. - */ - if (unlikely(IS_RDONLY(inode))) - return; - - /* - * Don't update access timestamps on reads if mounted "noatime". - * Throw it away if anyone asks us. - */ - if (unlikely( - (ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) && - (flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG)) == - XFS_ICHGTIME_ACC)) - return; - nanotime(&tv); if (flags & XFS_ICHGTIME_MOD) { inode->i_mtime = tv; @@ -130,8 +148,6 @@ xfs_ichgtime( * Variant on the above which avoids querying the system clock * in situations where we know the Linux inode timestamps have * just been updated (and so we can update our inode cheaply). - * We also skip the readonly and noatime checks here, they are - * also catered for already. */ void xfs_ichgtime_fast( @@ -142,20 +158,16 @@ xfs_ichgtime_fast( timespec_t *tvp; /* - * We're not supposed to change timestamps in readonly-mounted - * filesystems. Throw it away if anyone asks us. + * Atime updates for read() & friends are handled lazily now, and + * explicit updates must go through xfs_ichgtime() */ - if (unlikely(IS_RDONLY(inode))) - return; + ASSERT((flags & XFS_ICHGTIME_ACC) == 0); /* - * Don't update access timestamps on reads if mounted "noatime". - * Throw it away if anyone asks us. + * We're not supposed to change timestamps in readonly-mounted + * filesystems. Throw it away if anyone asks us. */ - if (unlikely( - (ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) && - ((flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG)) == - XFS_ICHGTIME_ACC))) + if (unlikely(IS_RDONLY(inode))) return; if (flags & XFS_ICHGTIME_MOD) { @@ -163,11 +175,6 @@ xfs_ichgtime_fast( ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec; ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec; } - if (flags & XFS_ICHGTIME_ACC) { - tvp = &inode->i_atime; - ip->i_d.di_atime.t_sec = (__int32_t)tvp->tv_sec; - ip->i_d.di_atime.t_nsec = (__int32_t)tvp->tv_nsec; - } if (flags & XFS_ICHGTIME_CHG) { tvp = &inode->i_ctime; ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec; @@ -214,6 +221,39 @@ validate_fields( } /* + * Hook in SELinux. This is not quite correct yet, what we really need + * here (as we do for default ACLs) is a mechanism by which creation of + * these attrs can be journalled at inode creation time (along with the + * inode, of course, such that log replay can't cause these to be lost). + */ +STATIC int +linvfs_init_security( + struct vnode *vp, + struct inode *dir) +{ + struct inode *ip = LINVFS_GET_IP(vp); + size_t length; + void *value; + char *name; + int error; + + error = security_inode_init_security(ip, dir, &name, &value, &length); + if (error) { + if (error == -EOPNOTSUPP) + return 0; + return -error; + } + + VOP_ATTR_SET(vp, name, value, length, ATTR_SECURE, NULL, error); + if (!error) + VMODIFY(vp); + + kfree(name); + kfree(value); + return error; +} + +/* * Determine whether a process has a valid fs_struct (kernel daemons * like knfsd don't have an fs_struct). * @@ -278,6 +318,9 @@ linvfs_mknod( break; } + if (!error) + error = linvfs_init_security(vp, dir); + if (default_acl) { if (!error) { error = _ACL_INHERIT(vp, &va, default_acl); @@ -294,8 +337,6 @@ linvfs_mknod( teardown.d_inode = ip = LINVFS_GET_IP(vp); teardown.d_name = dentry->d_name; - vn_mark_bad(vp); - if (S_ISDIR(mode)) VOP_RMDIR(dvp, &teardown, NULL, err2); else @@ -506,7 +547,7 @@ linvfs_follow_link( ASSERT(dentry); ASSERT(nd); - link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL); + link = (char *)kmalloc(MAXPATHLEN+1, GFP_KERNEL); if (!link) { nd_set_link(nd, ERR_PTR(-ENOMEM)); return NULL; @@ -522,12 +563,12 @@ linvfs_follow_link( vp = LINVFS_GET_VP(dentry->d_inode); iov.iov_base = link; - iov.iov_len = MAXNAMELEN; + iov.iov_len = MAXPATHLEN; uio->uio_iov = &iov; uio->uio_offset = 0; uio->uio_segflg = UIO_SYSSPACE; - uio->uio_resid = MAXNAMELEN; + uio->uio_resid = MAXPATHLEN; uio->uio_iovcnt = 1; VOP_READLINK(vp, uio, 0, NULL, error); @@ -535,7 +576,7 @@ linvfs_follow_link( kfree(link); link = ERR_PTR(-error); } else { - link[MAXNAMELEN - uio->uio_resid] = '\0'; + link[MAXPATHLEN - uio->uio_resid] = '\0'; } kfree(uio); diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index ee784b63acb..6899a6b4a50 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h @@ -26,11 +26,6 @@ extern struct file_operations linvfs_file_operations; extern struct file_operations linvfs_invis_file_operations; extern struct file_operations linvfs_dir_operations; -extern struct address_space_operations linvfs_aops; - -extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int); -extern void linvfs_unwritten_done(struct buffer_head *, int); - extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *, int, unsigned int, void __user *); diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index d8e21ba0ccc..67389b74552 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -110,10 +110,6 @@ * delalloc and these ondisk-uninitialised buffers. */ BUFFER_FNS(PrivateStart, unwritten); -static inline void set_buffer_unwritten_io(struct buffer_head *bh) -{ - bh->b_end_io = linvfs_unwritten_done; -} #define restricted_chown xfs_params.restrict_chown.val #define irix_sgid_inherit xfs_params.sgid_inherit.val @@ -232,7 +228,7 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh) #define xfs_itruncate_data(ip, off) \ (-vmtruncate(LINVFS_GET_IP(XFS_ITOV(ip)), (off))) #define xfs_statvfs_fsid(statp, mp) \ - ({ u64 id = huge_encode_dev((mp)->m_dev); \ + ({ u64 id = huge_encode_dev((mp)->m_ddev_targp->bt_dev); \ __kernel_fsid_t *fsid = &(statp)->f_fsid; \ (fsid->val[0] = (u32)id, fsid->val[1] = (u32)(id >> 32)); }) diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 885dfafeabe..e0ab45fbfeb 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -233,8 +233,8 @@ xfs_read( xfs_buftarg_t *target = (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? mp->m_rtdev_targp : mp->m_ddev_targp; - if ((*offset & target->pbr_smask) || - (size & target->pbr_smask)) { + if ((*offset & target->bt_smask) || + (size & target->bt_smask)) { if (*offset == ip->i_d.di_size) { return (0); } @@ -281,9 +281,6 @@ xfs_read( xfs_iunlock(ip, XFS_IOLOCK_SHARED); - if (likely(!(ioflags & IO_INVIS))) - xfs_ichgtime_fast(ip, inode, XFS_ICHGTIME_ACC); - unlock_isem: if (unlikely(ioflags & IO_ISDIRECT)) mutex_unlock(&inode->i_mutex); @@ -346,9 +343,6 @@ xfs_sendfile( if (ret > 0) XFS_STATS_ADD(xs_read_bytes, ret); - if (likely(!(ioflags & IO_INVIS))) - xfs_ichgtime_fast(ip, LINVFS_GET_IP(vp), XFS_ICHGTIME_ACC); - return ret; } @@ -362,7 +356,6 @@ STATIC int /* error (positive) */ xfs_zero_last_block( struct inode *ip, xfs_iocore_t *io, - xfs_off_t offset, xfs_fsize_t isize, xfs_fsize_t end_size) { @@ -371,19 +364,16 @@ xfs_zero_last_block( int nimaps; int zero_offset; int zero_len; - int isize_fsb_offset; int error = 0; xfs_bmbt_irec_t imap; loff_t loff; - size_t lsize; ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0); - ASSERT(offset > isize); mp = io->io_mount; - isize_fsb_offset = XFS_B_FSB_OFFSET(mp, isize); - if (isize_fsb_offset == 0) { + zero_offset = XFS_B_FSB_OFFSET(mp, isize); + if (zero_offset == 0) { /* * There are no extra bytes in the last block on disk to * zero, so return. @@ -413,10 +403,8 @@ xfs_zero_last_block( */ XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD); loff = XFS_FSB_TO_B(mp, last_fsb); - lsize = XFS_FSB_TO_B(mp, 1); - zero_offset = isize_fsb_offset; - zero_len = mp->m_sb.sb_blocksize - isize_fsb_offset; + zero_len = mp->m_sb.sb_blocksize - zero_offset; error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size); @@ -447,20 +435,17 @@ xfs_zero_eof( struct inode *ip = LINVFS_GET_IP(vp); xfs_fileoff_t start_zero_fsb; xfs_fileoff_t end_zero_fsb; - xfs_fileoff_t prev_zero_fsb; xfs_fileoff_t zero_count_fsb; xfs_fileoff_t last_fsb; xfs_extlen_t buf_len_fsb; - xfs_extlen_t prev_zero_count; xfs_mount_t *mp; int nimaps; int error = 0; xfs_bmbt_irec_t imap; - loff_t loff; - size_t lsize; ASSERT(ismrlocked(io->io_lock, MR_UPDATE)); ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); + ASSERT(offset > isize); mp = io->io_mount; @@ -468,7 +453,7 @@ xfs_zero_eof( * First handle zeroing the block on which isize resides. * We only zero a part of that block so it is handled specially. */ - error = xfs_zero_last_block(ip, io, offset, isize, end_size); + error = xfs_zero_last_block(ip, io, isize, end_size); if (error) { ASSERT(ismrlocked(io->io_lock, MR_UPDATE)); ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); @@ -496,8 +481,6 @@ xfs_zero_eof( } ASSERT(start_zero_fsb <= end_zero_fsb); - prev_zero_fsb = NULLFILEOFF; - prev_zero_count = 0; while (start_zero_fsb <= end_zero_fsb) { nimaps = 1; zero_count_fsb = end_zero_fsb - start_zero_fsb + 1; @@ -519,10 +502,7 @@ xfs_zero_eof( * that sits on a hole and sets the page as P_HOLE * and calls remapf if it is a mapped file. */ - prev_zero_fsb = NULLFILEOFF; - prev_zero_count = 0; - start_zero_fsb = imap.br_startoff + - imap.br_blockcount; + start_zero_fsb = imap.br_startoff + imap.br_blockcount; ASSERT(start_zero_fsb <= (end_zero_fsb + 1)); continue; } @@ -543,17 +523,15 @@ xfs_zero_eof( */ XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); - loff = XFS_FSB_TO_B(mp, start_zero_fsb); - lsize = XFS_FSB_TO_B(mp, buf_len_fsb); - - error = xfs_iozero(ip, loff, lsize, end_size); + error = xfs_iozero(ip, + XFS_FSB_TO_B(mp, start_zero_fsb), + XFS_FSB_TO_B(mp, buf_len_fsb), + end_size); if (error) { goto out_lock; } - prev_zero_fsb = start_zero_fsb; - prev_zero_count = buf_len_fsb; start_zero_fsb = imap.br_startoff + buf_len_fsb; ASSERT(start_zero_fsb <= (end_zero_fsb + 1)); @@ -640,7 +618,7 @@ xfs_write( (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? mp->m_rtdev_targp : mp->m_ddev_targp; - if ((pos & target->pbr_smask) || (count & target->pbr_smask)) + if ((pos & target->bt_smask) || (count & target->bt_smask)) return XFS_ERROR(-EINVAL); if (!VN_CACHED(vp) && pos < i_size_read(inode)) @@ -831,6 +809,10 @@ retry: goto retry; } + isize = i_size_read(inode); + if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize)) + *offset = isize; + if (*offset > xip->i_d.di_size) { xfs_ilock(xip, XFS_ILOCK_EXCL); if (*offset > xip->i_d.di_size) { @@ -956,7 +938,7 @@ xfs_bdstrat_cb(struct xfs_buf *bp) mp = XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *); if (!XFS_FORCED_SHUTDOWN(mp)) { - pagebuf_iorequest(bp); + xfs_buf_iorequest(bp); return 0; } else { xfs_buftrace("XFS__BDSTRAT IOERROR", bp); @@ -1009,7 +991,7 @@ xfsbdstrat( * if (XFS_BUF_IS_GRIO(bp)) { */ - pagebuf_iorequest(bp); + xfs_buf_iorequest(bp); return 0; } diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c index 6c40a74be7c..8955720a2c6 100644 --- a/fs/xfs/linux-2.6/xfs_stats.c +++ b/fs/xfs/linux-2.6/xfs_stats.c @@ -34,7 +34,7 @@ xfs_read_xfsstats( __uint64_t xs_write_bytes = 0; __uint64_t xs_read_bytes = 0; - static struct xstats_entry { + static const struct xstats_entry { char *desc; int endpoint; } xstats[] = { diff --git a/fs/xfs/linux-2.6/xfs_stats.h b/fs/xfs/linux-2.6/xfs_stats.h index 50027c4a561..8ba7a2fa6c1 100644 --- a/fs/xfs/linux-2.6/xfs_stats.h +++ b/fs/xfs/linux-2.6/xfs_stats.h @@ -109,15 +109,15 @@ struct xfsstats { __uint32_t vn_remove; /* # times vn_remove called */ __uint32_t vn_free; /* # times vn_free called */ #define XFSSTAT_END_BUF (XFSSTAT_END_VNODE_OPS+9) - __uint32_t pb_get; - __uint32_t pb_create; - __uint32_t pb_get_locked; - __uint32_t pb_get_locked_waited; - __uint32_t pb_busy_locked; - __uint32_t pb_miss_locked; - __uint32_t pb_page_retries; - __uint32_t pb_page_found; - __uint32_t pb_get_read; + __uint32_t xb_get; + __uint32_t xb_create; + __uint32_t xb_get_locked; + __uint32_t xb_get_locked_waited; + __uint32_t xb_busy_locked; + __uint32_t xb_miss_locked; + __uint32_t xb_page_retries; + __uint32_t xb_page_found; + __uint32_t xb_get_read; /* Extra precision counters */ __uint64_t xs_xstrat_bytes; __uint64_t xs_write_bytes; diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 6116b5bf433..f22e426d9e4 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -306,13 +306,15 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp) xfs_fs_cmn_err(CE_NOTE, mp, "Disabling barriers, not supported with external log device"); mp->m_flags &= ~XFS_MOUNT_BARRIER; + return; } - if (mp->m_ddev_targp->pbr_bdev->bd_disk->queue->ordered == + if (mp->m_ddev_targp->bt_bdev->bd_disk->queue->ordered == QUEUE_ORDERED_NONE) { xfs_fs_cmn_err(CE_NOTE, mp, "Disabling barriers, not supported by the underlying device"); mp->m_flags &= ~XFS_MOUNT_BARRIER; + return; } error = xfs_barrier_test(mp); @@ -320,6 +322,7 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp) xfs_fs_cmn_err(CE_NOTE, mp, "Disabling barriers, trial barrier write failed"); mp->m_flags &= ~XFS_MOUNT_BARRIER; + return; } } @@ -327,7 +330,7 @@ void xfs_blkdev_issue_flush( xfs_buftarg_t *buftarg) { - blkdev_issue_flush(buftarg->pbr_bdev, NULL); + blkdev_issue_flush(buftarg->bt_bdev, NULL); } STATIC struct inode * @@ -576,7 +579,7 @@ xfssyncd( timeleft = schedule_timeout_interruptible(timeleft); /* swsusp */ try_to_freeze(); - if (kthread_should_stop()) + if (kthread_should_stop() && list_empty(&vfsp->vfs_sync_list)) break; spin_lock(&vfsp->vfs_sync_lock); @@ -966,9 +969,9 @@ init_xfs_fs( void ) if (error < 0) goto undo_zones; - error = pagebuf_init(); + error = xfs_buf_init(); if (error < 0) - goto undo_pagebuf; + goto undo_buffers; vn_init(); xfs_init(); @@ -982,9 +985,9 @@ init_xfs_fs( void ) return 0; undo_register: - pagebuf_terminate(); + xfs_buf_terminate(); -undo_pagebuf: +undo_buffers: linvfs_destroy_zones(); undo_zones: @@ -998,7 +1001,7 @@ exit_xfs_fs( void ) XFS_DM_EXIT(&xfs_fs_type); unregister_filesystem(&xfs_fs_type); xfs_cleanup(); - pagebuf_terminate(); + xfs_buf_terminate(); linvfs_destroy_zones(); ktrace_uninit(); } diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index e9bbcb4d624..260dd8415dd 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -106,7 +106,6 @@ vn_revalidate_core( inode->i_blocks = vap->va_nblocks; inode->i_mtime = vap->va_mtime; inode->i_ctime = vap->va_ctime; - inode->i_atime = vap->va_atime; inode->i_blksize = vap->va_blocksize; if (vap->va_xflags & XFS_XFLAG_IMMUTABLE) inode->i_flags |= S_IMMUTABLE; diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index f2bbb327c08..0fe2419461d 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -566,6 +566,25 @@ static inline int VN_BAD(struct vnode *vp) } /* + * Extracting atime values in various formats + */ +static inline void vn_atime_to_bstime(struct vnode *vp, xfs_bstime_t *bs_atime) +{ + bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec; + bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec; +} + +static inline void vn_atime_to_timespec(struct vnode *vp, struct timespec *ts) +{ + *ts = vp->v_inode.i_atime; +} + +static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt) +{ + *tt = vp->v_inode.i_atime.tv_sec; +} + +/* * Some useful predicates. */ #define VN_MAPPED(vp) mapping_mapped(LINVFS_GET_IP(vp)->i_mapping) diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 2f69822344e..2ec6b441849 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c @@ -239,7 +239,7 @@ xfs_qm_dquot_logitem_pushbuf( * trying to duplicate our effort. */ ASSERT(qip->qli_pushbuf_flag != 0); - ASSERT(qip->qli_push_owner == get_thread_id()); + ASSERT(qip->qli_push_owner == current_pid()); /* * If flushlock isn't locked anymore, chances are that the @@ -333,7 +333,7 @@ xfs_qm_dquot_logitem_trylock( qip->qli_pushbuf_flag = 1; ASSERT(qip->qli_format.qlf_blkno == dqp->q_blkno); #ifdef DEBUG - qip->qli_push_owner = get_thread_id(); + qip->qli_push_owner = current_pid(); #endif /* * The dquot is left locked. diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index bb6991a7a61..7dcdd0640c3 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -1392,11 +1392,12 @@ xfs_qm_qino_alloc( { xfs_trans_t *tp; int error; - unsigned long s; + unsigned long s; cred_t zerocr; + xfs_inode_t zeroino; int committed; - tp = xfs_trans_alloc(mp,XFS_TRANS_QM_QINOCREATE); + tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QINOCREATE); if ((error = xfs_trans_reserve(tp, XFS_QM_QINOCREATE_SPACE_RES(mp), XFS_CREATE_LOG_RES(mp), 0, @@ -1406,8 +1407,9 @@ xfs_qm_qino_alloc( return (error); } memset(&zerocr, 0, sizeof(zerocr)); + memset(&zeroino, 0, sizeof(zeroino)); - if ((error = xfs_dir_ialloc(&tp, mp->m_rootip, S_IFREG, 1, 0, + if ((error = xfs_dir_ialloc(&tp, &zeroino, S_IFREG, 1, 0, &zerocr, 0, 1, ip, &committed))) { xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); @@ -1918,9 +1920,7 @@ xfs_qm_quotacheck( * at this point (because we intentionally didn't in dqget_noattach). */ if (error) { - xfs_qm_dqpurge_all(mp, - XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA| - XFS_QMOPT_PQUOTA|XFS_QMOPT_QUOTAOFF); + xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_QUOTAOFF); goto error_return; } /* @@ -2743,6 +2743,7 @@ xfs_qm_vop_dqattach_and_dqmod_newinode( xfs_dqunlock(udqp); ASSERT(ip->i_udquot == NULL); ip->i_udquot = udqp; + ASSERT(XFS_IS_UQUOTA_ON(tp->t_mountp)); ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id)); xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1); } @@ -2752,7 +2753,10 @@ xfs_qm_vop_dqattach_and_dqmod_newinode( xfs_dqunlock(gdqp); ASSERT(ip->i_gdquot == NULL); ip->i_gdquot = gdqp; - ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id)); + ASSERT(XFS_IS_OQUOTA_ON(tp->t_mountp)); + ASSERT((XFS_IS_GQUOTA_ON(tp->t_mountp) ? + ip->i_d.di_gid : ip->i_d.di_projid) == + be32_to_cpu(gdqp->q_core.d_id)); xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1); } } diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index bb6dc91ea26..b08b3d9345b 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c @@ -27,45 +27,12 @@ static DEFINE_SPINLOCK(xfs_err_lock); /* Translate from CE_FOO to KERN_FOO, err_level(CE_FOO) == KERN_FOO */ #define XFS_MAX_ERR_LEVEL 7 #define XFS_ERR_MASK ((1 << 3) - 1) -static char *err_level[XFS_MAX_ERR_LEVEL+1] = +static const char * const err_level[XFS_MAX_ERR_LEVEL+1] = {KERN_EMERG, KERN_ALERT, KERN_CRIT, KERN_ERR, KERN_WARNING, KERN_NOTICE, KERN_INFO, KERN_DEBUG}; void -assfail(char *a, char *f, int l) -{ - printk("XFS assertion failed: %s, file: %s, line: %d\n", a, f, l); - BUG(); -} - -#if ((defined(DEBUG) || defined(INDUCE_IO_ERRROR)) && !defined(NO_WANT_RANDOM)) - -unsigned long -random(void) -{ - static unsigned long RandomValue = 1; - /* cycles pseudo-randomly through all values between 1 and 2^31 - 2 */ - register long rv = RandomValue; - register long lo; - register long hi; - - hi = rv / 127773; - lo = rv % 127773; - rv = 16807 * lo - 2836 * hi; - if( rv <= 0 ) rv += 2147483647; - return( RandomValue = rv ); -} - -int -get_thread_id(void) -{ - return current->pid; -} - -#endif /* DEBUG || INDUCE_IO_ERRROR || !NO_WANT_RANDOM */ - -void cmn_err(register int level, char *fmt, ...) { char *fp = fmt; @@ -90,7 +57,6 @@ cmn_err(register int level, char *fmt, ...) BUG(); } - void icmn_err(register int level, char *fmt, va_list ap) { @@ -109,3 +75,27 @@ icmn_err(register int level, char *fmt, va_list ap) if (level == CE_PANIC) BUG(); } + +void +assfail(char *expr, char *file, int line) +{ + printk("Assertion failed: %s, file: %s, line: %d\n", expr, file, line); + BUG(); +} + +#if ((defined(DEBUG) || defined(INDUCE_IO_ERRROR)) && !defined(NO_WANT_RANDOM)) +unsigned long random(void) +{ + static unsigned long RandomValue = 1; + /* cycles pseudo-randomly through all values between 1 and 2^31 - 2 */ + register long rv = RandomValue; + register long lo; + register long hi; + + hi = rv / 127773; + lo = rv % 127773; + rv = 16807 * lo - 2836 * hi; + if (rv <= 0) rv += 2147483647; + return RandomValue = rv; +} +#endif /* DEBUG || INDUCE_IO_ERRROR || !NO_WANT_RANDOM */ diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h index aff558664c3..e3bf58112e7 100644 --- a/fs/xfs/support/debug.h +++ b/fs/xfs/support/debug.h @@ -31,24 +31,23 @@ extern void icmn_err(int, char *, va_list) __attribute__ ((format (printf, 2, 0))); extern void cmn_err(int, char *, ...) __attribute__ ((format (printf, 2, 3))); +extern void assfail(char *expr, char *f, int l); -#ifndef STATIC -# define STATIC static -#endif +#define prdev(fmt,targ,args...) \ + printk("Device %s - " fmt "\n", XFS_BUFTARG_NAME(targ), ## args) -#ifdef DEBUG -# define ASSERT(EX) ((EX) ? ((void)0) : assfail(#EX, __FILE__, __LINE__)) -#else -# define ASSERT(x) ((void)0) -#endif +#define ASSERT_ALWAYS(expr) \ + (unlikely((expr) != 0) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) -extern void assfail(char *, char *, int); -#ifdef DEBUG +#ifndef DEBUG +# define ASSERT(expr) ((void)0) +#else +# define ASSERT(expr) ASSERT_ALWAYS(expr) extern unsigned long random(void); -extern int get_thread_id(void); #endif -#define ASSERT_ALWAYS(EX) ((EX)?((void)0):assfail(#EX, __FILE__, __LINE__)) -#define debug_stop_all_cpus(param) /* param is "cpumask_t *" */ +#ifndef STATIC +# define STATIC static +#endif #endif /* __XFS_SUPPORT_DEBUG_H__ */ diff --git a/fs/xfs/support/uuid.c b/fs/xfs/support/uuid.c index 69ec4f540c3..a3d565a6773 100644 --- a/fs/xfs/support/uuid.c +++ b/fs/xfs/support/uuid.c @@ -27,6 +27,16 @@ uuid_init(void) mutex_init(&uuid_monitor); } + +/* IRIX interpretation of an uuid_t */ +typedef struct { + __be32 uu_timelow; + __be16 uu_timemid; + __be16 uu_timehi; + __be16 uu_clockseq; + __be16 uu_node[3]; +} xfs_uu_t; + /* * uuid_getnodeuniq - obtain the node unique fields of a UUID. * @@ -36,16 +46,11 @@ uuid_init(void) void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]) { - char *uu = (char *)uuid; - - /* on IRIX, this function assumes big-endian fields within - * the uuid, so we use INT_GET to get the same result on - * little-endian systems - */ + xfs_uu_t *uup = (xfs_uu_t *)uuid; - fsid[0] = (INT_GET(*(u_int16_t*)(uu+8), ARCH_CONVERT) << 16) + - INT_GET(*(u_int16_t*)(uu+4), ARCH_CONVERT); - fsid[1] = INT_GET(*(u_int32_t*)(uu ), ARCH_CONVERT); + fsid[0] = (be16_to_cpu(uup->uu_clockseq) << 16) | + be16_to_cpu(uup->uu_timemid); + fsid[1] = be16_to_cpu(uup->uu_timelow); } void diff --git a/fs/xfs/xfs_arch.h b/fs/xfs/xfs_arch.h index 68e5051d8e2..c4836890b72 100644 --- a/fs/xfs/xfs_arch.h +++ b/fs/xfs/xfs_arch.h @@ -40,6 +40,22 @@ #undef XFS_NATIVE_HOST #endif +#ifdef XFS_NATIVE_HOST +#define cpu_to_be16(val) ((__be16)(val)) +#define cpu_to_be32(val) ((__be32)(val)) +#define cpu_to_be64(val) ((__be64)(val)) +#define be16_to_cpu(val) ((__uint16_t)(val)) +#define be32_to_cpu(val) ((__uint32_t)(val)) +#define be64_to_cpu(val) ((__uint64_t)(val)) +#else +#define cpu_to_be16(val) (__swab16((__uint16_t)(val))) +#define cpu_to_be32(val) (__swab32((__uint32_t)(val))) +#define cpu_to_be64(val) (__swab64((__uint64_t)(val))) +#define be16_to_cpu(val) (__swab16((__be16)(val))) +#define be32_to_cpu(val) (__swab32((__be32)(val))) +#define be64_to_cpu(val) (__swab64((__be64)(val))) +#endif + #endif /* __KERNEL__ */ /* do we need conversion? */ @@ -186,7 +202,7 @@ static inline void be64_add(__be64 *a, __s64 b) */ #define XFS_GET_DIR_INO4(di) \ - (((u32)(di).i[0] << 24) | ((di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3])) + (((__u32)(di).i[0] << 24) | ((di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3])) #define XFS_PUT_DIR_INO4(from, di) \ do { \ @@ -197,9 +213,9 @@ do { \ } while (0) #define XFS_DI_HI(di) \ - (((u32)(di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3])) + (((__u32)(di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3])) #define XFS_DI_LO(di) \ - (((u32)(di).i[4] << 24) | ((di).i[5] << 16) | ((di).i[6] << 8) | ((di).i[7])) + (((__u32)(di).i[4] << 24) | ((di).i[5] << 16) | ((di).i[6] << 8) | ((di).i[7])) #define XFS_GET_DIR_INO8(di) \ (((xfs_ino_t)XFS_DI_LO(di) & 0xffffffffULL) | \ diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 1c7421840c1..fe91eac4e2a 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -128,7 +128,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) return (offset >= minforkoff) ? minforkoff : 0; } - if (unlikely(mp->m_flags & XFS_MOUNT_COMPAT_ATTR)) { + if (!(mp->m_flags & XFS_MOUNT_ATTR2)) { if (bytes <= XFS_IFORK_ASIZE(dp)) return mp->m_attroffset >> 3; return 0; @@ -157,7 +157,7 @@ xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp) { unsigned long s; - if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR) && + if ((mp->m_flags & XFS_MOUNT_ATTR2) && !(XFS_SB_VERSION_HASATTR2(&mp->m_sb))) { s = XFS_SB_LOCK(mp); if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb)) { @@ -311,7 +311,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) */ totsize -= size; if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname && - !(mp->m_flags & XFS_MOUNT_COMPAT_ATTR)) { + (mp->m_flags & XFS_MOUNT_ATTR2)) { /* * Last attribute now removed, revert to original * inode format making all literal area available @@ -330,7 +330,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); ASSERT(dp->i_d.di_forkoff); ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname || - (mp->m_flags & XFS_MOUNT_COMPAT_ATTR)); + !(mp->m_flags & XFS_MOUNT_ATTR2)); dp->i_afp->if_ext_max = XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); dp->i_df.if_ext_max = @@ -739,7 +739,7 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp) + name_loc->namelen + INT_GET(name_loc->valuelen, ARCH_CONVERT); } - if (!(dp->i_mount->m_flags & XFS_MOUNT_COMPAT_ATTR) && + if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) && (bytes == sizeof(struct xfs_attr_sf_hdr))) return(-1); return(xfs_attr_shortform_bytesfit(dp, bytes)); @@ -778,7 +778,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) goto out; if (forkoff == -1) { - ASSERT(!(dp->i_mount->m_flags & XFS_MOUNT_COMPAT_ATTR)); + ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); /* * Last attribute was removed, revert to original diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h index f6143ff251a..541e34109bb 100644 --- a/fs/xfs/xfs_attr_leaf.h +++ b/fs/xfs/xfs_attr_leaf.h @@ -63,7 +63,7 @@ struct xfs_trans; * the leaf_entry. The namespaces are independent only because we also look * at the namespace bit when we are looking for a matching attribute name. * - * We also store a "incomplete" bit in the leaf_entry. It shows that an + * We also store an "incomplete" bit in the leaf_entry. It shows that an * attribute is in the middle of being created and should not be shown to * the user if we crash during the time that the bit is set. We clear the * bit when we have finished setting up the attribute. We do this because @@ -72,42 +72,48 @@ struct xfs_trans; */ #define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */ +typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */ + __uint16_t base; /* base of free region */ + __uint16_t size; /* length of free region */ +} xfs_attr_leaf_map_t; + +typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */ + xfs_da_blkinfo_t info; /* block type, links, etc. */ + __uint16_t count; /* count of active leaf_entry's */ + __uint16_t usedbytes; /* num bytes of names/values stored */ + __uint16_t firstused; /* first used byte in name area */ + __uint8_t holes; /* != 0 if blk needs compaction */ + __uint8_t pad1; + xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE]; + /* N largest free regions */ +} xfs_attr_leaf_hdr_t; + +typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */ + xfs_dahash_t hashval; /* hash value of name */ + __uint16_t nameidx; /* index into buffer of name/value */ + __uint8_t flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */ + __uint8_t pad2; /* unused pad byte */ +} xfs_attr_leaf_entry_t; + +typedef struct xfs_attr_leaf_name_local { + __uint16_t valuelen; /* number of bytes in value */ + __uint8_t namelen; /* length of name bytes */ + __uint8_t nameval[1]; /* name/value bytes */ +} xfs_attr_leaf_name_local_t; + +typedef struct xfs_attr_leaf_name_remote { + xfs_dablk_t valueblk; /* block number of value bytes */ + __uint32_t valuelen; /* number of bytes in value */ + __uint8_t namelen; /* length of name bytes */ + __uint8_t name[1]; /* name bytes */ +} xfs_attr_leaf_name_remote_t; + typedef struct xfs_attr_leafblock { - struct xfs_attr_leaf_hdr { /* constant-structure header block */ - xfs_da_blkinfo_t info; /* block type, links, etc. */ - __uint16_t count; /* count of active leaf_entry's */ - __uint16_t usedbytes; /* num bytes of names/values stored */ - __uint16_t firstused; /* first used byte in name area */ - __uint8_t holes; /* != 0 if blk needs compaction */ - __uint8_t pad1; - struct xfs_attr_leaf_map { /* RLE map of free bytes */ - __uint16_t base; /* base of free region */ - __uint16_t size; /* length of free region */ - } freemap[XFS_ATTR_LEAF_MAPSIZE]; /* N largest free regions */ - } hdr; - struct xfs_attr_leaf_entry { /* sorted on key, not name */ - xfs_dahash_t hashval; /* hash value of name */ - __uint16_t nameidx; /* index into buffer of name/value */ - __uint8_t flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */ - __uint8_t pad2; /* unused pad byte */ - } entries[1]; /* variable sized array */ - struct xfs_attr_leaf_name_local { - __uint16_t valuelen; /* number of bytes in value */ - __uint8_t namelen; /* length of name bytes */ - __uint8_t nameval[1]; /* name/value bytes */ - } namelist; /* grows from bottom of buf */ - struct xfs_attr_leaf_name_remote { - xfs_dablk_t valueblk; /* block number of value bytes */ - __uint32_t valuelen; /* number of bytes in value */ - __uint8_t namelen; /* length of name bytes */ - __uint8_t name[1]; /* name bytes */ - } valuelist; /* grows from bottom of buf */ + xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */ + xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */ + xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */ + xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */ } xfs_attr_leafblock_t; -typedef struct xfs_attr_leaf_hdr xfs_attr_leaf_hdr_t; -typedef struct xfs_attr_leaf_map xfs_attr_leaf_map_t; -typedef struct xfs_attr_leaf_entry xfs_attr_leaf_entry_t; -typedef struct xfs_attr_leaf_name_local xfs_attr_leaf_name_local_t; -typedef struct xfs_attr_leaf_name_remote xfs_attr_leaf_name_remote_t; /* * Flags used in the leaf_entry[i].flags field. @@ -150,7 +156,8 @@ xfs_attr_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx) (leafp))[INT_GET((leafp)->entries[idx].nameidx, ARCH_CONVERT)]; } -#define XFS_ATTR_LEAF_NAME(leafp,idx) xfs_attr_leaf_name(leafp,idx) +#define XFS_ATTR_LEAF_NAME(leafp,idx) \ + xfs_attr_leaf_name(leafp,idx) static inline char *xfs_attr_leaf_name(xfs_attr_leafblock_t *leafp, int idx) { return (&((char *) diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index e415a4698e9..70625e577c7 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2146,13 +2146,176 @@ xfs_bmap_add_extent_hole_real( return 0; /* keep gcc quite */ } +/* + * Adjust the size of the new extent based on di_extsize and rt extsize. + */ +STATIC int +xfs_bmap_extsize_align( + xfs_mount_t *mp, + xfs_bmbt_irec_t *gotp, /* next extent pointer */ + xfs_bmbt_irec_t *prevp, /* previous extent pointer */ + xfs_extlen_t extsz, /* align to this extent size */ + int rt, /* is this a realtime inode? */ + int eof, /* is extent at end-of-file? */ + int delay, /* creating delalloc extent? */ + int convert, /* overwriting unwritten extent? */ + xfs_fileoff_t *offp, /* in/out: aligned offset */ + xfs_extlen_t *lenp) /* in/out: aligned length */ +{ + xfs_fileoff_t orig_off; /* original offset */ + xfs_extlen_t orig_alen; /* original length */ + xfs_fileoff_t orig_end; /* original off+len */ + xfs_fileoff_t nexto; /* next file offset */ + xfs_fileoff_t prevo; /* previous file offset */ + xfs_fileoff_t align_off; /* temp for offset */ + xfs_extlen_t align_alen; /* temp for length */ + xfs_extlen_t temp; /* temp for calculations */ + + if (convert) + return 0; + + orig_off = align_off = *offp; + orig_alen = align_alen = *lenp; + orig_end = orig_off + orig_alen; + + /* + * If this request overlaps an existing extent, then don't + * attempt to perform any additional alignment. + */ + if (!delay && !eof && + (orig_off >= gotp->br_startoff) && + (orig_end <= gotp->br_startoff + gotp->br_blockcount)) { + return 0; + } + + /* + * If the file offset is unaligned vs. the extent size + * we need to align it. This will be possible unless + * the file was previously written with a kernel that didn't + * perform this alignment, or if a truncate shot us in the + * foot. + */ + temp = do_mod(orig_off, extsz); + if (temp) { + align_alen += temp; + align_off -= temp; + } + /* + * Same adjustment for the end of the requested area. + */ + if ((temp = (align_alen % extsz))) { + align_alen += extsz - temp; + } + /* + * If the previous block overlaps with this proposed allocation + * then move the start forward without adjusting the length. + */ + if (prevp->br_startoff != NULLFILEOFF) { + if (prevp->br_startblock == HOLESTARTBLOCK) + prevo = prevp->br_startoff; + else + prevo = prevp->br_startoff + prevp->br_blockcount; + } else + prevo = 0; + if (align_off != orig_off && align_off < prevo) + align_off = prevo; + /* + * If the next block overlaps with this proposed allocation + * then move the start back without adjusting the length, + * but not before offset 0. + * This may of course make the start overlap previous block, + * and if we hit the offset 0 limit then the next block + * can still overlap too. + */ + if (!eof && gotp->br_startoff != NULLFILEOFF) { + if ((delay && gotp->br_startblock == HOLESTARTBLOCK) || + (!delay && gotp->br_startblock == DELAYSTARTBLOCK)) + nexto = gotp->br_startoff + gotp->br_blockcount; + else + nexto = gotp->br_startoff; + } else + nexto = NULLFILEOFF; + if (!eof && + align_off + align_alen != orig_end && + align_off + align_alen > nexto) + align_off = nexto > align_alen ? nexto - align_alen : 0; + /* + * If we're now overlapping the next or previous extent that + * means we can't fit an extsz piece in this hole. Just move + * the start forward to the first valid spot and set + * the length so we hit the end. + */ + if (align_off != orig_off && align_off < prevo) + align_off = prevo; + if (align_off + align_alen != orig_end && + align_off + align_alen > nexto && + nexto != NULLFILEOFF) { + ASSERT(nexto > prevo); + align_alen = nexto - align_off; + } + + /* + * If realtime, and the result isn't a multiple of the realtime + * extent size we need to remove blocks until it is. + */ + if (rt && (temp = (align_alen % mp->m_sb.sb_rextsize))) { + /* + * We're not covering the original request, or + * we won't be able to once we fix the length. + */ + if (orig_off < align_off || + orig_end > align_off + align_alen || + align_alen - temp < orig_alen) + return XFS_ERROR(EINVAL); + /* + * Try to fix it by moving the start up. + */ + if (align_off + temp <= orig_off) { + align_alen -= temp; + align_off += temp; + } + /* + * Try to fix it by moving the end in. + */ + else if (align_off + align_alen - temp >= orig_end) + align_alen -= temp; + /* + * Set the start to the minimum then trim the length. + */ + else { + align_alen -= orig_off - align_off; + align_off = orig_off; + align_alen -= align_alen % mp->m_sb.sb_rextsize; + } + /* + * Result doesn't cover the request, fail it. + */ + if (orig_off < align_off || orig_end > align_off + align_alen) + return XFS_ERROR(EINVAL); + } else { + ASSERT(orig_off >= align_off); + ASSERT(orig_end <= align_off + align_alen); + } + +#ifdef DEBUG + if (!eof && gotp->br_startoff != NULLFILEOFF) + ASSERT(align_off + align_alen <= gotp->br_startoff); + if (prevp->br_startoff != NULLFILEOFF) + ASSERT(align_off >= prevp->br_startoff + prevp->br_blockcount); +#endif + + *lenp = align_alen; + *offp = align_off; + return 0; +} + #define XFS_ALLOC_GAP_UNITS 4 /* * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. * It figures out where to ask the underlying allocator to put the new extent. */ -STATIC int /* error */ +STATIC int xfs_bmap_alloc( xfs_bmalloca_t *ap) /* bmap alloc argument struct */ { @@ -2163,10 +2326,10 @@ xfs_bmap_alloc( xfs_mount_t *mp; /* mount point structure */ int nullfb; /* true if ap->firstblock isn't set */ int rt; /* true if inode is realtime */ -#ifdef __KERNEL__ - xfs_extlen_t prod=0; /* product factor for allocators */ - xfs_extlen_t ralen=0; /* realtime allocation length */ -#endif + xfs_extlen_t prod = 0; /* product factor for allocators */ + xfs_extlen_t ralen = 0; /* realtime allocation length */ + xfs_extlen_t align; /* minimum allocation alignment */ + xfs_rtblock_t rtx; #define ISVALID(x,y) \ (rt ? \ @@ -2182,125 +2345,25 @@ xfs_bmap_alloc( nullfb = ap->firstblock == NULLFSBLOCK; rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata; fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); -#ifdef __KERNEL__ if (rt) { - xfs_extlen_t extsz; /* file extent size for rt */ - xfs_fileoff_t nexto; /* next file offset */ - xfs_extlen_t orig_alen; /* original ap->alen */ - xfs_fileoff_t orig_end; /* original off+len */ - xfs_fileoff_t orig_off; /* original ap->off */ - xfs_extlen_t mod_off; /* modulus calculations */ - xfs_fileoff_t prevo; /* previous file offset */ - xfs_rtblock_t rtx; /* realtime extent number */ - xfs_extlen_t temp; /* temp for rt calculations */ - - /* - * Set prod to match the realtime extent size. - */ - if (!(extsz = ap->ip->i_d.di_extsize)) - extsz = mp->m_sb.sb_rextsize; - prod = extsz / mp->m_sb.sb_rextsize; - orig_off = ap->off; - orig_alen = ap->alen; - orig_end = orig_off + orig_alen; - /* - * If the file offset is unaligned vs. the extent size - * we need to align it. This will be possible unless - * the file was previously written with a kernel that didn't - * perform this alignment. - */ - mod_off = do_mod(orig_off, extsz); - if (mod_off) { - ap->alen += mod_off; - ap->off -= mod_off; - } - /* - * Same adjustment for the end of the requested area. - */ - if ((temp = (ap->alen % extsz))) - ap->alen += extsz - temp; - /* - * If the previous block overlaps with this proposed allocation - * then move the start forward without adjusting the length. - */ - prevo = - ap->prevp->br_startoff == NULLFILEOFF ? - 0 : - (ap->prevp->br_startoff + - ap->prevp->br_blockcount); - if (ap->off != orig_off && ap->off < prevo) - ap->off = prevo; - /* - * If the next block overlaps with this proposed allocation - * then move the start back without adjusting the length, - * but not before offset 0. - * This may of course make the start overlap previous block, - * and if we hit the offset 0 limit then the next block - * can still overlap too. - */ - nexto = (ap->eof || ap->gotp->br_startoff == NULLFILEOFF) ? - NULLFILEOFF : ap->gotp->br_startoff; - if (!ap->eof && - ap->off + ap->alen != orig_end && - ap->off + ap->alen > nexto) - ap->off = nexto > ap->alen ? nexto - ap->alen : 0; - /* - * If we're now overlapping the next or previous extent that - * means we can't fit an extsz piece in this hole. Just move - * the start forward to the first valid spot and set - * the length so we hit the end. - */ - if ((ap->off != orig_off && ap->off < prevo) || - (ap->off + ap->alen != orig_end && - ap->off + ap->alen > nexto)) { - ap->off = prevo; - ap->alen = nexto - prevo; - } - /* - * If the result isn't a multiple of rtextents we need to - * remove blocks until it is. - */ - if ((temp = (ap->alen % mp->m_sb.sb_rextsize))) { - /* - * We're not covering the original request, or - * we won't be able to once we fix the length. - */ - if (orig_off < ap->off || - orig_end > ap->off + ap->alen || - ap->alen - temp < orig_alen) - return XFS_ERROR(EINVAL); - /* - * Try to fix it by moving the start up. - */ - if (ap->off + temp <= orig_off) { - ap->alen -= temp; - ap->off += temp; - } - /* - * Try to fix it by moving the end in. - */ - else if (ap->off + ap->alen - temp >= orig_end) - ap->alen -= temp; - /* - * Set the start to the minimum then trim the length. - */ - else { - ap->alen -= orig_off - ap->off; - ap->off = orig_off; - ap->alen -= ap->alen % mp->m_sb.sb_rextsize; - } - /* - * Result doesn't cover the request, fail it. - */ - if (orig_off < ap->off || orig_end > ap->off + ap->alen) - return XFS_ERROR(EINVAL); - } + align = ap->ip->i_d.di_extsize ? + ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize; + /* Set prod to match the extent size */ + prod = align / mp->m_sb.sb_rextsize; + + error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp, + align, rt, ap->eof, 0, + ap->conv, &ap->off, &ap->alen); + if (error) + return error; + ASSERT(ap->alen); ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0); + /* * If the offset & length are not perfectly aligned * then kill prod, it will just get us in trouble. */ - if (do_mod(ap->off, extsz) || ap->alen % extsz) + if (do_mod(ap->off, align) || ap->alen % align) prod = 1; /* * Set ralen to be the actual requested length in rtextents. @@ -2326,15 +2389,24 @@ xfs_bmap_alloc( ap->rval = rtx * mp->m_sb.sb_rextsize; } else ap->rval = 0; + } else { + align = (ap->userdata && ap->ip->i_d.di_extsize && + (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ? + ap->ip->i_d.di_extsize : 0; + if (unlikely(align)) { + error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp, + align, rt, + ap->eof, 0, ap->conv, + &ap->off, &ap->alen); + ASSERT(!error); + ASSERT(ap->alen); + } + if (nullfb) + ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino); + else + ap->rval = ap->firstblock; } -#else - if (rt) - ap->rval = 0; -#endif /* __KERNEL__ */ - else if (nullfb) - ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino); - else - ap->rval = ap->firstblock; + /* * If allocating at eof, and there's a previous real block, * try to use it's last block as our starting point. @@ -2598,11 +2670,12 @@ xfs_bmap_alloc( args.total = ap->total; args.minlen = ap->minlen; } - if (ap->ip->i_d.di_extsize) { + if (unlikely(ap->userdata && ap->ip->i_d.di_extsize && + (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE))) { args.prod = ap->ip->i_d.di_extsize; if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod))) args.mod = (xfs_extlen_t)(args.prod - args.mod); - } else if (mp->m_sb.sb_blocksize >= NBPP) { + } else if (unlikely(mp->m_sb.sb_blocksize >= NBPP)) { args.prod = 1; args.mod = 0; } else { @@ -3580,14 +3653,16 @@ xfs_bmap_search_extents( ep = xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp, lastxp, gotp, prevp); - rt = ip->i_d.di_flags & XFS_DIFLAG_REALTIME; - if(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM)) { + rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); + if (unlikely(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM))) { cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld " "start_block : %llx start_off : %llx blkcnt : %llx " "extent-state : %x \n", - (ip->i_mount)->m_fsname,(long long)ip->i_ino, - gotp->br_startblock, gotp->br_startoff, - gotp->br_blockcount,gotp->br_state); + (ip->i_mount)->m_fsname, (long long)ip->i_ino, + (unsigned long long)gotp->br_startblock, + (unsigned long long)gotp->br_startoff, + (unsigned long long)gotp->br_blockcount, + gotp->br_state); } return ep; } @@ -3875,7 +3950,7 @@ xfs_bmap_add_attrfork( ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size); if (!ip->i_d.di_forkoff) ip->i_d.di_forkoff = mp->m_attroffset >> 3; - else if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR)) + else if (mp->m_flags & XFS_MOUNT_ATTR2) version = 2; break; default: @@ -4023,13 +4098,13 @@ xfs_bmap_compute_maxlevels( */ if (whichfork == XFS_DATA_FORK) { maxleafents = MAXEXTNUM; - sz = (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) ? - mp->m_attroffset : XFS_BMDR_SPACE_CALC(MINDBTPTRS); + sz = (mp->m_flags & XFS_MOUNT_ATTR2) ? + XFS_BMDR_SPACE_CALC(MINDBTPTRS) : mp->m_attroffset; } else { maxleafents = MAXAEXTNUM; - sz = (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) ? - mp->m_sb.sb_inodesize - mp->m_attroffset : - XFS_BMDR_SPACE_CALC(MINABTPTRS); + sz = (mp->m_flags & XFS_MOUNT_ATTR2) ? + XFS_BMDR_SPACE_CALC(MINABTPTRS) : + mp->m_sb.sb_inodesize - mp->m_attroffset; } maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0); minleafrecs = mp->m_bmap_dmnr[0]; @@ -4418,8 +4493,8 @@ xfs_bmap_read_extents( num_recs = be16_to_cpu(block->bb_numrecs); if (unlikely(i + num_recs > room)) { ASSERT(i + num_recs <= room); - xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt dinode %Lu, (btree extents). Unmount and run xfs_repair.", + xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + "corrupt dinode %Lu, (btree extents).", (unsigned long long) ip->i_ino); XFS_ERROR_REPORT("xfs_bmap_read_extents(1)", XFS_ERRLEVEL_LOW, @@ -4590,6 +4665,7 @@ xfs_bmapi( char contig; /* allocation must be one extent */ char delay; /* this request is for delayed alloc */ char exact; /* don't do all of wasdelayed extent */ + char convert; /* unwritten extent I/O completion */ xfs_bmbt_rec_t *ep; /* extent list entry pointer */ int error; /* error return */ xfs_bmbt_irec_t got; /* current extent list record */ @@ -4643,7 +4719,7 @@ xfs_bmapi( } if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); - rt = XFS_IS_REALTIME_INODE(ip); + rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(ifp->if_ext_max == XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); @@ -4654,6 +4730,7 @@ xfs_bmapi( delay = (flags & XFS_BMAPI_DELAY) != 0; trim = (flags & XFS_BMAPI_ENTIRE) == 0; userdata = (flags & XFS_BMAPI_METADATA) == 0; + convert = (flags & XFS_BMAPI_CONVERT) != 0; exact = (flags & XFS_BMAPI_EXACT) != 0; rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0; contig = (flags & XFS_BMAPI_CONTIG) != 0; @@ -4748,15 +4825,25 @@ xfs_bmapi( } minlen = contig ? alen : 1; if (delay) { - xfs_extlen_t extsz = 0; + xfs_extlen_t extsz; /* Figure out the extent size, adjust alen */ if (rt) { if (!(extsz = ip->i_d.di_extsize)) extsz = mp->m_sb.sb_rextsize; - alen = roundup(alen, extsz); - extsz = alen / mp->m_sb.sb_rextsize; + } else { + extsz = ip->i_d.di_extsize; } + if (extsz) { + error = xfs_bmap_extsize_align(mp, + &got, &prev, extsz, + rt, eof, delay, convert, + &aoff, &alen); + ASSERT(!error); + } + + if (rt) + extsz = alen / mp->m_sb.sb_rextsize; /* * Make a transaction-less quota reservation for @@ -4785,32 +4872,33 @@ xfs_bmapi( xfs_bmap_worst_indlen(ip, alen); ASSERT(indlen > 0); - if (rt) + if (rt) { error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, -(extsz), rsvd); - else + } else { error = xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, -(alen), rsvd); + } if (!error) { error = xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, -(indlen), rsvd); - if (error && rt) { - xfs_mod_incore_sb(ip->i_mount, + if (error && rt) + xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, rsvd); - } else if (error) { - xfs_mod_incore_sb(ip->i_mount, + else if (error) + xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, alen, rsvd); - } } if (error) { - if (XFS_IS_QUOTA_ON(ip->i_mount)) + if (XFS_IS_QUOTA_ON(mp)) /* unreserve the blocks now */ + (void) XFS_TRANS_UNRESERVE_QUOTA_NBLKS( mp, NULL, ip, (long)alen, 0, rt ? @@ -4849,6 +4937,7 @@ xfs_bmapi( bma.firstblock = *firstblock; bma.alen = alen; bma.off = aoff; + bma.conv = convert; bma.wasdel = wasdelay; bma.minlen = minlen; bma.low = flist->xbf_low; @@ -5270,8 +5359,7 @@ xfs_bunmapi( return 0; } XFS_STATS_INC(xs_blk_unmap); - isrt = (whichfork == XFS_DATA_FORK) && - (ip->i_d.di_flags & XFS_DIFLAG_REALTIME); + isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); start = bno; bno = start + len - 1; ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, @@ -5443,7 +5531,7 @@ xfs_bunmapi( } if (wasdel) { ASSERT(STARTBLOCKVAL(del.br_startblock) > 0); - /* Update realtim/data freespace, unreserve quota */ + /* Update realtime/data freespace, unreserve quota */ if (isrt) { xfs_filblks_t rtexts; @@ -5451,14 +5539,14 @@ xfs_bunmapi( do_div(rtexts, mp->m_sb.sb_rextsize); xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, (int)rtexts, rsvd); - XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip, - -((long)del.br_blockcount), 0, + (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, + NULL, ip, -((long)del.br_blockcount), 0, XFS_QMOPT_RES_RTBLKS); } else { xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)del.br_blockcount, rsvd); - XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip, - -((long)del.br_blockcount), 0, + (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, + NULL, ip, -((long)del.br_blockcount), 0, XFS_QMOPT_RES_REGBLKS); } ip->i_delayed_blks -= del.br_blockcount; @@ -5652,7 +5740,9 @@ xfs_getbmap( ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) return XFS_ERROR(EINVAL); if (whichfork == XFS_DATA_FORK) { - if (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC) { + if ((ip->i_d.di_extsize && (ip->i_d.di_flags & + (XFS_DIFLAG_REALTIME|XFS_DIFLAG_EXTSIZE))) || + ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){ prealloced = 1; fixlen = XFS_MAXIOFFSET(mp); } else { diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 2e0717a0130..12cc63dfc2c 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h @@ -62,6 +62,10 @@ typedef struct xfs_bmap_free #define XFS_BMAPI_IGSTATE 0x200 /* Ignore state - */ /* combine contig. space */ #define XFS_BMAPI_CONTIG 0x400 /* must allocate only one extent */ +/* XFS_BMAPI_DIRECT_IO 0x800 */ +#define XFS_BMAPI_CONVERT 0x1000 /* unwritten extent conversion - */ + /* need write cache flushing and no */ + /* additional allocation alignments */ #define XFS_BMAPI_AFLAG(w) xfs_bmapi_aflag(w) static inline int xfs_bmapi_aflag(int w) @@ -101,7 +105,8 @@ typedef struct xfs_bmalloca { char wasdel; /* replacing a delayed allocation */ char userdata;/* set if is user data */ char low; /* low on space, using seq'l ags */ - char aeof; /* allocated space at eof */ + char aeof; /* allocated space at eof */ + char conv; /* overwriting unwritten extents */ } xfs_bmalloca_t; #ifdef __KERNEL__ diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h index 328a528b926..f57cc9ac875 100644 --- a/fs/xfs/xfs_clnt.h +++ b/fs/xfs/xfs_clnt.h @@ -57,7 +57,7 @@ struct xfs_mount_args { /* * XFS mount option flags -- args->flags1 */ -#define XFSMNT_COMPAT_ATTR 0x00000001 /* do not use ATTR2 format */ +#define XFSMNT_ATTR2 0x00000001 /* allow ATTR2 EA format */ #define XFSMNT_WSYNC 0x00000002 /* safe mode nfs mount * compatible */ #define XFSMNT_INO64 0x00000004 /* move inode numbers up diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 070259a4254..c6191d00ad2 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -60,8 +60,6 @@ xfs_swapext( xfs_bstat_t *sbp; struct file *fp = NULL, *tfp = NULL; vnode_t *vp, *tvp; - bhv_desc_t *bdp, *tbdp; - vn_bhv_head_t *bhp, *tbhp; static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL; int ilf_fields, tilf_fields; int error = 0; @@ -90,13 +88,10 @@ xfs_swapext( goto error0; } - bhp = VN_BHV_HEAD(vp); - bdp = vn_bhv_lookup(bhp, &xfs_vnodeops); - if (bdp == NULL) { + ip = xfs_vtoi(vp); + if (ip == NULL) { error = XFS_ERROR(EBADF); goto error0; - } else { - ip = XFS_BHVTOI(bdp); } if (((tfp = fget((int)sxp->sx_fdtmp)) == NULL) || @@ -105,13 +100,10 @@ xfs_swapext( goto error0; } - tbhp = VN_BHV_HEAD(tvp); - tbdp = vn_bhv_lookup(tbhp, &xfs_vnodeops); - if (tbdp == NULL) { + tip = xfs_vtoi(tvp); + if (tip == NULL) { error = XFS_ERROR(EBADF); goto error0; - } else { - tip = XFS_BHVTOI(tbdp); } if (ip->i_mount != tip->i_mount) { diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h index c5a0e537ff1..79d0d9e1fba 100644 --- a/fs/xfs/xfs_dinode.h +++ b/fs/xfs/xfs_dinode.h @@ -199,10 +199,16 @@ typedef enum xfs_dinode_fmt #define XFS_DFORK_DSIZE(dip,mp) \ XFS_CFORK_DSIZE_DISK(&(dip)->di_core, mp) +#define XFS_DFORK_DSIZE_HOST(dip,mp) \ + XFS_CFORK_DSIZE(&(dip)->di_core, mp) #define XFS_DFORK_ASIZE(dip,mp) \ XFS_CFORK_ASIZE_DISK(&(dip)->di_core, mp) +#define XFS_DFORK_ASIZE_HOST(dip,mp) \ + XFS_CFORK_ASIZE(&(dip)->di_core, mp) #define XFS_DFORK_SIZE(dip,mp,w) \ XFS_CFORK_SIZE_DISK(&(dip)->di_core, mp, w) +#define XFS_DFORK_SIZE_HOST(dip,mp,w) \ + XFS_CFORK_SIZE(&(dip)->di_core, mp, w) #define XFS_DFORK_Q(dip) XFS_CFORK_Q_DISK(&(dip)->di_core) #define XFS_DFORK_BOFF(dip) XFS_CFORK_BOFF_DISK(&(dip)->di_core) @@ -216,6 +222,7 @@ typedef enum xfs_dinode_fmt #define XFS_CFORK_FMT_SET(dcp,w,n) \ ((w) == XFS_DATA_FORK ? \ ((dcp)->di_format = (n)) : ((dcp)->di_aformat = (n))) +#define XFS_DFORK_FORMAT(dip,w) XFS_CFORK_FORMAT(&(dip)->di_core, w) #define XFS_CFORK_NEXTENTS_DISK(dcp,w) \ ((w) == XFS_DATA_FORK ? \ @@ -223,13 +230,13 @@ typedef enum xfs_dinode_fmt INT_GET((dcp)->di_anextents, ARCH_CONVERT)) #define XFS_CFORK_NEXTENTS(dcp,w) \ ((w) == XFS_DATA_FORK ? (dcp)->di_nextents : (dcp)->di_anextents) +#define XFS_DFORK_NEXTENTS(dip,w) XFS_CFORK_NEXTENTS_DISK(&(dip)->di_core, w) +#define XFS_DFORK_NEXTENTS_HOST(dip,w) XFS_CFORK_NEXTENTS(&(dip)->di_core, w) #define XFS_CFORK_NEXT_SET(dcp,w,n) \ ((w) == XFS_DATA_FORK ? \ ((dcp)->di_nextents = (n)) : ((dcp)->di_anextents = (n))) -#define XFS_DFORK_NEXTENTS(dip,w) XFS_CFORK_NEXTENTS_DISK(&(dip)->di_core, w) - #define XFS_BUF_TO_DINODE(bp) ((xfs_dinode_t *)XFS_BUF_PTR(bp)) /* @@ -246,8 +253,10 @@ typedef enum xfs_dinode_fmt #define XFS_DIFLAG_NOATIME_BIT 6 /* do not update atime */ #define XFS_DIFLAG_NODUMP_BIT 7 /* do not dump */ #define XFS_DIFLAG_RTINHERIT_BIT 8 /* create with realtime bit set */ -#define XFS_DIFLAG_PROJINHERIT_BIT 9 /* create with parents projid */ -#define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */ +#define XFS_DIFLAG_PROJINHERIT_BIT 9 /* create with parents projid */ +#define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */ +#define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */ +#define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */ #define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT) #define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT) #define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT) @@ -259,11 +268,14 @@ typedef enum xfs_dinode_fmt #define XFS_DIFLAG_RTINHERIT (1 << XFS_DIFLAG_RTINHERIT_BIT) #define XFS_DIFLAG_PROJINHERIT (1 << XFS_DIFLAG_PROJINHERIT_BIT) #define XFS_DIFLAG_NOSYMLINKS (1 << XFS_DIFLAG_NOSYMLINKS_BIT) +#define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT) +#define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT) #define XFS_DIFLAG_ANY \ (XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \ XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \ XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \ - XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS) + XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \ + XFS_DIFLAG_EXTSZINHERIT) #endif /* __XFS_DINODE_H__ */ diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c index 3dd30391f55..bb87d2a700a 100644 --- a/fs/xfs/xfs_dir.c +++ b/fs/xfs/xfs_dir.c @@ -176,7 +176,7 @@ xfs_dir_mount(xfs_mount_t *mp) uint shortcount, leafcount, count; mp->m_dirversion = 1; - if (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) { + if (!(mp->m_flags & XFS_MOUNT_ATTR2)) { shortcount = (mp->m_attroffset - (uint)sizeof(xfs_dir_sf_hdr_t)) / (uint)sizeof(xfs_dir_sf_entry_t); diff --git a/fs/xfs/xfs_dir.h b/fs/xfs/xfs_dir.h index 488defe86ba..8cc8afb9f6c 100644 --- a/fs/xfs/xfs_dir.h +++ b/fs/xfs/xfs_dir.h @@ -135,6 +135,8 @@ void xfs_dir_startup(void); /* called exactly once */ ((mp)->m_dirops.xd_shortform_to_single(args)) #define XFS_DIR_IS_V1(mp) ((mp)->m_dirversion == 1) +#define XFS_DIR_IS_V2(mp) ((mp)->m_dirversion == 2) extern xfs_dirops_t xfsv1_dirops; +extern xfs_dirops_t xfsv2_dirops; #endif /* __XFS_DIR_H__ */ diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index 7e24ffeda9e..3158f5dc431 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -72,9 +72,6 @@ typedef struct xfs_dir2_put_args { struct uio *uio; /* uio control structure */ } xfs_dir2_put_args_t; -#define XFS_DIR_IS_V2(mp) ((mp)->m_dirversion == 2) -extern xfs_dirops_t xfsv2_dirops; - /* * Other interfaces used by the rest of the dir v2 code. */ diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h index ab6b09eef9a..eb8cd9a4667 100644 --- a/fs/xfs/xfs_dir_leaf.h +++ b/fs/xfs/xfs_dir_leaf.h @@ -67,34 +67,38 @@ struct xfs_trans; */ #define XFS_DIR_LEAF_MAPSIZE 3 /* how many freespace slots */ +typedef struct xfs_dir_leaf_map { /* RLE map of free bytes */ + __uint16_t base; /* base of free region */ + __uint16_t size; /* run length of free region */ +} xfs_dir_leaf_map_t; + +typedef struct xfs_dir_leaf_hdr { /* constant-structure header block */ + xfs_da_blkinfo_t info; /* block type, links, etc. */ + __uint16_t count; /* count of active leaf_entry's */ + __uint16_t namebytes; /* num bytes of name strings stored */ + __uint16_t firstused; /* first used byte in name area */ + __uint8_t holes; /* != 0 if blk needs compaction */ + __uint8_t pad1; + xfs_dir_leaf_map_t freemap[XFS_DIR_LEAF_MAPSIZE]; +} xfs_dir_leaf_hdr_t; + +typedef struct xfs_dir_leaf_entry { /* sorted on key, not name */ + xfs_dahash_t hashval; /* hash value of name */ + __uint16_t nameidx; /* index into buffer of name */ + __uint8_t namelen; /* length of name string */ + __uint8_t pad2; +} xfs_dir_leaf_entry_t; + +typedef struct xfs_dir_leaf_name { + xfs_dir_ino_t inumber; /* inode number for this key */ + __uint8_t name[1]; /* name string itself */ +} xfs_dir_leaf_name_t; + typedef struct xfs_dir_leafblock { - struct xfs_dir_leaf_hdr { /* constant-structure header block */ - xfs_da_blkinfo_t info; /* block type, links, etc. */ - __uint16_t count; /* count of active leaf_entry's */ - __uint16_t namebytes; /* num bytes of name strings stored */ - __uint16_t firstused; /* first used byte in name area */ - __uint8_t holes; /* != 0 if blk needs compaction */ - __uint8_t pad1; - struct xfs_dir_leaf_map {/* RLE map of free bytes */ - __uint16_t base; /* base of free region */ - __uint16_t size; /* run length of free region */ - } freemap[XFS_DIR_LEAF_MAPSIZE]; /* N largest free regions */ - } hdr; - struct xfs_dir_leaf_entry { /* sorted on key, not name */ - xfs_dahash_t hashval; /* hash value of name */ - __uint16_t nameidx; /* index into buffer of name */ - __uint8_t namelen; /* length of name string */ - __uint8_t pad2; - } entries[1]; /* var sized array */ - struct xfs_dir_leaf_name { - xfs_dir_ino_t inumber; /* inode number for this key */ - __uint8_t name[1]; /* name string itself */ - } namelist[1]; /* grows from bottom of buf */ + xfs_dir_leaf_hdr_t hdr; /* constant-structure header block */ + xfs_dir_leaf_entry_t entries[1]; /* var sized array */ + xfs_dir_leaf_name_t namelist[1]; /* grows from bottom of buf */ } xfs_dir_leafblock_t; -typedef struct xfs_dir_leaf_hdr xfs_dir_leaf_hdr_t; -typedef struct xfs_dir_leaf_map xfs_dir_leaf_map_t; -typedef struct xfs_dir_leaf_entry xfs_dir_leaf_entry_t; -typedef struct xfs_dir_leaf_name xfs_dir_leaf_name_t; /* * Length of name for which a 512-byte block filesystem @@ -126,11 +130,10 @@ typedef union { #define XFS_PUT_COOKIE(c,mp,bno,entry,hash) \ ((c).s.be = XFS_DA_MAKE_BNOENTRY(mp, bno, entry), (c).s.h = (hash)) -typedef struct xfs_dir_put_args -{ +typedef struct xfs_dir_put_args { xfs_dircook_t cook; /* cookie of (next) entry */ xfs_intino_t ino; /* inode number */ - struct xfs_dirent *dbp; /* buffer pointer */ + struct xfs_dirent *dbp; /* buffer pointer */ char *name; /* directory entry name */ int namelen; /* length of name */ int done; /* output: set if value was stored */ @@ -138,7 +141,8 @@ typedef struct xfs_dir_put_args struct uio *uio; /* uio control structure */ } xfs_dir_put_args_t; -#define XFS_DIR_LEAF_ENTSIZE_BYNAME(len) xfs_dir_leaf_entsize_byname(len) +#define XFS_DIR_LEAF_ENTSIZE_BYNAME(len) \ + xfs_dir_leaf_entsize_byname(len) static inline int xfs_dir_leaf_entsize_byname(int len) { return (uint)sizeof(xfs_dir_leaf_name_t)-1 + len; diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index d7b6b5d1670..2a21c502401 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -54,7 +54,6 @@ xfs_error_trap(int e) if (e != xfs_etrap[i]) continue; cmn_err(CE_NOTE, "xfs_error_trap: error %d", e); - debug_stop_all_cpus((void *)-1LL); BUG(); break; } diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 06d8a8426c1..26b8e709a56 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -18,9 +18,6 @@ #ifndef __XFS_ERROR_H__ #define __XFS_ERROR_H__ -#define prdev(fmt,targ,args...) \ - printk("XFS: device %s - " fmt "\n", XFS_BUFTARG_NAME(targ), ## args) - #define XFS_ERECOVER 1 /* Failure to recover log */ #define XFS_ELOGSTAT 2 /* Failure to stat log in user space */ #define XFS_ENOLOGSPACE 3 /* Reservation too large */ @@ -182,8 +179,11 @@ extern int xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud); struct xfs_mount; /* PRINTFLIKE4 */ extern void xfs_cmn_err(int panic_tag, int level, struct xfs_mount *mp, - char *fmt, ...); + char *fmt, ...); /* PRINTFLIKE3 */ extern void xfs_fs_cmn_err(int level, struct xfs_mount *mp, char *fmt, ...); +#define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \ + xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args) + #endif /* __XFS_ERROR_H__ */ diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h index ba096f80f48..14010f1fa82 100644 --- a/fs/xfs/xfs_fs.h +++ b/fs/xfs/xfs_fs.h @@ -3,15 +3,15 @@ * All Rights Reserved. * * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -65,6 +65,8 @@ struct fsxattr { #define XFS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */ #define XFS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */ #define XFS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */ +#define XFS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */ +#define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */ #define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ /* diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index d1236d6f404..163031c1e39 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -540,6 +540,32 @@ xfs_reserve_blocks( return(0); } +void +xfs_fs_log_dummy(xfs_mount_t *mp) +{ + xfs_trans_t *tp; + xfs_inode_t *ip; + + + tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1); + atomic_inc(&mp->m_active_trans); + if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) { + xfs_trans_cancel(tp, 0); + return; + } + + ip = mp->m_rootip; + xfs_ilock(ip, XFS_ILOCK_EXCL); + + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + xfs_trans_ihold(tp, ip); + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + xfs_trans_set_sync(tp); + xfs_trans_commit(tp, 0, NULL); + + xfs_iunlock(ip, XFS_ILOCK_EXCL); +} + int xfs_fs_goingdown( xfs_mount_t *mp, diff --git a/fs/xfs/xfs_fsops.h b/fs/xfs/xfs_fsops.h index f32713f14f9..300d0c9d61a 100644 --- a/fs/xfs/xfs_fsops.h +++ b/fs/xfs/xfs_fsops.h @@ -25,5 +25,6 @@ extern int xfs_fs_counts(xfs_mount_t *mp, xfs_fsop_counts_t *cnt); extern int xfs_reserve_blocks(xfs_mount_t *mp, __uint64_t *inval, xfs_fsop_resblks_t *outval); extern int xfs_fs_goingdown(xfs_mount_t *mp, __uint32_t inflags); +extern void xfs_fs_log_dummy(xfs_mount_t *mp); #endif /* __XFS_FSOPS_H__ */ diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index fc19eedbd11..8e380a1fb79 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -493,7 +493,6 @@ xfs_iget( retry: if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) { - bhv_desc_t *bdp; xfs_inode_t *ip; vp = LINVFS_GET_VP(inode); @@ -517,14 +516,12 @@ retry: * to wait for the inode to go away. */ if (is_bad_inode(inode) || - ((bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), - &xfs_vnodeops)) == NULL)) { + ((ip = xfs_vtoi(vp)) == NULL)) { iput(inode); delay(1); goto retry; } - ip = XFS_BHVTOI(bdp); if (lock_flags != 0) xfs_ilock(ip, lock_flags); XFS_STATS_INC(xs_ig_found); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index df0d4572d70..1d7f5a7e063 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -404,9 +404,8 @@ xfs_iformat( INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) + INT_GET(dip->di_core.di_anextents, ARCH_CONVERT) > INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT))) { - xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt dinode %Lu, extent total = %d, nblocks = %Lu." - " Unmount and run xfs_repair.", + xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + "corrupt dinode %Lu, extent total = %d, nblocks = %Lu.", (unsigned long long)ip->i_ino, (int)(INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) + INT_GET(dip->di_core.di_anextents, ARCH_CONVERT)), @@ -418,9 +417,8 @@ xfs_iformat( } if (unlikely(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT) > ip->i_mount->m_sb.sb_inodesize)) { - xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt dinode %Lu, forkoff = 0x%x." - " Unmount and run xfs_repair.", + xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + "corrupt dinode %Lu, forkoff = 0x%x.", (unsigned long long)ip->i_ino, (int)(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT))); XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW, @@ -451,8 +449,9 @@ xfs_iformat( * no local regular files yet */ if (unlikely((INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & S_IFMT) == S_IFREG)) { - xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode (local format for regular file) %Lu. Unmount and run xfs_repair.", + xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + "corrupt inode %Lu " + "(local format for regular file).", (unsigned long long) ip->i_ino); XFS_CORRUPTION_ERROR("xfs_iformat(4)", XFS_ERRLEVEL_LOW, @@ -462,8 +461,9 @@ xfs_iformat( di_size = INT_GET(dip->di_core.di_size, ARCH_CONVERT); if (unlikely(di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) { - xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu (bad size %Ld for local inode). Unmount and run xfs_repair.", + xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + "corrupt inode %Lu " + "(bad size %Ld for local inode).", (unsigned long long) ip->i_ino, (long long) di_size); XFS_CORRUPTION_ERROR("xfs_iformat(5)", @@ -551,8 +551,9 @@ xfs_iformat_local( * kmem_alloc() or memcpy() below. */ if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) { - xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu (bad size %d for local fork, size = %d). Unmount and run xfs_repair.", + xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + "corrupt inode %Lu " + "(bad size %d for local fork, size = %d).", (unsigned long long) ip->i_ino, size, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)); XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW, @@ -610,8 +611,8 @@ xfs_iformat_extents( * kmem_alloc() or memcpy() below. */ if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) { - xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu ((a)extents = %d). Unmount and run xfs_repair.", + xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + "corrupt inode %Lu ((a)extents = %d).", (unsigned long long) ip->i_ino, nex); XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); @@ -692,8 +693,8 @@ xfs_iformat_btree( || XFS_BMDR_SPACE_CALC(nrecs) > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork) || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) { - xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu (btree). Unmount and run xfs_repair.", + xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + "corrupt inode %Lu (btree).", (unsigned long long) ip->i_ino); XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW, ip->i_mount); @@ -809,6 +810,10 @@ _xfs_dic2xflags( flags |= XFS_XFLAG_PROJINHERIT; if (di_flags & XFS_DIFLAG_NOSYMLINKS) flags |= XFS_XFLAG_NOSYMLINKS; + if (di_flags & XFS_DIFLAG_EXTSIZE) + flags |= XFS_XFLAG_EXTSIZE; + if (di_flags & XFS_DIFLAG_EXTSZINHERIT) + flags |= XFS_XFLAG_EXTSZINHERIT; } return flags; @@ -1192,11 +1197,19 @@ xfs_ialloc( if ((mode & S_IFMT) == S_IFDIR) { if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) di_flags |= XFS_DIFLAG_RTINHERIT; - } else { + if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) { + di_flags |= XFS_DIFLAG_EXTSZINHERIT; + ip->i_d.di_extsize = pip->i_d.di_extsize; + } + } else if ((mode & S_IFMT) == S_IFREG) { if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) { di_flags |= XFS_DIFLAG_REALTIME; ip->i_iocore.io_flags |= XFS_IOCORE_RT; } + if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) { + di_flags |= XFS_DIFLAG_EXTSIZE; + ip->i_d.di_extsize = pip->i_d.di_extsize; + } } if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) && xfs_inherit_noatime) @@ -1262,7 +1275,7 @@ xfs_isize_check( if ((ip->i_d.di_mode & S_IFMT) != S_IFREG) return; - if ( ip->i_d.di_flags & XFS_DIFLAG_REALTIME ) + if (ip->i_d.di_flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_EXTSIZE)) return; nimaps = 2; @@ -1765,22 +1778,19 @@ xfs_igrow_start( xfs_fsize_t new_size, cred_t *credp) { - xfs_fsize_t isize; int error; ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0); ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0); ASSERT(new_size > ip->i_d.di_size); - error = 0; - isize = ip->i_d.di_size; /* * Zero any pages that may have been created by * xfs_write_file() beyond the end of the file * and any blocks between the old and new file sizes. */ - error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size, isize, - new_size); + error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size, + ip->i_d.di_size, new_size); return error; } @@ -3355,6 +3365,11 @@ xfs_iflush_int( ip->i_update_core = 0; SYNCHRONIZE(); + /* + * Make sure to get the latest atime from the Linux inode. + */ + xfs_synchronize_atime(ip); + if (XFS_TEST_ERROR(INT_GET(dip->di_core.di_magic,ARCH_CONVERT) != XFS_DINODE_MAGIC, mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) { xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 124d30e6143..1cfbcf18ce8 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -436,6 +436,10 @@ void xfs_ichgtime(xfs_inode_t *, int); xfs_fsize_t xfs_file_last_byte(xfs_inode_t *); void xfs_lock_inodes(xfs_inode_t **, int, int, uint); +xfs_inode_t *xfs_vtoi(struct vnode *vp); + +void xfs_synchronize_atime(xfs_inode_t *); + #define xfs_ipincount(ip) ((unsigned int) atomic_read(&ip->i_pincount)) #ifdef DEBUG diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 7f3363c621e..36aa1fcb90a 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -271,6 +271,11 @@ xfs_inode_item_format( if (ip->i_update_size) ip->i_update_size = 0; + /* + * Make sure to get the latest atime from the Linux inode. + */ + xfs_synchronize_atime(ip); + vecp->i_addr = (xfs_caddr_t)&ip->i_d; vecp->i_len = sizeof(xfs_dinode_core_t); XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ICORE); @@ -603,7 +608,7 @@ xfs_inode_item_trylock( if (iip->ili_pushbuf_flag == 0) { iip->ili_pushbuf_flag = 1; #ifdef DEBUG - iip->ili_push_owner = get_thread_id(); + iip->ili_push_owner = current_pid(); #endif /* * Inode is left locked in shared mode. @@ -782,7 +787,7 @@ xfs_inode_item_pushbuf( * trying to duplicate our effort. */ ASSERT(iip->ili_pushbuf_flag != 0); - ASSERT(iip->ili_push_owner == get_thread_id()); + ASSERT(iip->ili_push_owner == current_pid()); /* * If flushlock isn't locked anymore, chances are that the diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index ca7afc83a89..788917f355c 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -262,7 +262,7 @@ phase2: case BMAPI_WRITE: /* If we found an extent, return it */ if (nimaps && - (imap.br_startblock != HOLESTARTBLOCK) && + (imap.br_startblock != HOLESTARTBLOCK) && (imap.br_startblock != DELAYSTARTBLOCK)) { xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, offset, count, iomapp, &imap, flags); @@ -317,6 +317,58 @@ out: } STATIC int +xfs_iomap_eof_align_last_fsb( + xfs_mount_t *mp, + xfs_iocore_t *io, + xfs_fsize_t isize, + xfs_extlen_t extsize, + xfs_fileoff_t *last_fsb) +{ + xfs_fileoff_t new_last_fsb = 0; + xfs_extlen_t align; + int eof, error; + + if (io->io_flags & XFS_IOCORE_RT) + ; + /* + * If mounted with the "-o swalloc" option, roundup the allocation + * request to a stripe width boundary if the file size is >= + * stripe width and we are allocating past the allocation eof. + */ + else if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC) && + (isize >= XFS_FSB_TO_B(mp, mp->m_swidth))) + new_last_fsb = roundup_64(*last_fsb, mp->m_swidth); + /* + * Roundup the allocation request to a stripe unit (m_dalign) boundary + * if the file size is >= stripe unit size, and we are allocating past + * the allocation eof. + */ + else if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign))) + new_last_fsb = roundup_64(*last_fsb, mp->m_dalign); + + /* + * Always round up the allocation request to an extent boundary + * (when file on a real-time subvolume or has di_extsize hint). + */ + if (extsize) { + if (new_last_fsb) + align = roundup_64(new_last_fsb, extsize); + else + align = extsize; + new_last_fsb = roundup_64(*last_fsb, align); + } + + if (new_last_fsb) { + error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof); + if (error) + return error; + if (eof) + *last_fsb = new_last_fsb; + } + return 0; +} + +STATIC int xfs_flush_space( xfs_inode_t *ip, int *fsynced, @@ -362,19 +414,20 @@ xfs_iomap_write_direct( xfs_iocore_t *io = &ip->i_iocore; xfs_fileoff_t offset_fsb; xfs_fileoff_t last_fsb; - xfs_filblks_t count_fsb; + xfs_filblks_t count_fsb, resaligned; xfs_fsblock_t firstfsb; + xfs_extlen_t extsz, temp; + xfs_fsize_t isize; int nimaps; - int error; int bmapi_flag; int quota_flag; int rt; xfs_trans_t *tp; xfs_bmbt_irec_t imap; xfs_bmap_free_t free_list; - xfs_filblks_t qblocks, resblks; + uint qblocks, resblks, resrtextents; int committed; - int resrtextents; + int error; /* * Make sure that the dquots are there. This doesn't hold @@ -384,37 +437,52 @@ xfs_iomap_write_direct( if (error) return XFS_ERROR(error); - offset_fsb = XFS_B_TO_FSBT(mp, offset); - last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); - count_fsb = last_fsb - offset_fsb; - if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) { - xfs_fileoff_t map_last_fsb; - - map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; - if (map_last_fsb < last_fsb) { - last_fsb = map_last_fsb; - count_fsb = last_fsb - offset_fsb; - } - ASSERT(count_fsb > 0); + rt = XFS_IS_REALTIME_INODE(ip); + if (unlikely(rt)) { + if (!(extsz = ip->i_d.di_extsize)) + extsz = mp->m_sb.sb_rextsize; + } else { + extsz = ip->i_d.di_extsize; } - /* - * Determine if reserving space on the data or realtime partition. - */ - if ((rt = XFS_IS_REALTIME_INODE(ip))) { - xfs_extlen_t extsz; + isize = ip->i_d.di_size; + if (io->io_new_size > isize) + isize = io->io_new_size; - if (!(extsz = ip->i_d.di_extsize)) - extsz = mp->m_sb.sb_rextsize; - resrtextents = qblocks = (count_fsb + extsz - 1); - do_div(resrtextents, mp->m_sb.sb_rextsize); - resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); - quota_flag = XFS_QMOPT_RES_RTBLKS; + offset_fsb = XFS_B_TO_FSBT(mp, offset); + last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); + if ((offset + count) > isize) { + error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz, + &last_fsb); + if (error) + goto error_out; } else { - resrtextents = 0; - resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, count_fsb); - quota_flag = XFS_QMOPT_RES_REGBLKS; + if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) + last_fsb = MIN(last_fsb, (xfs_fileoff_t) + ret_imap->br_blockcount + + ret_imap->br_startoff); } + count_fsb = last_fsb - offset_fsb; + ASSERT(count_fsb > 0); + + resaligned = count_fsb; + if (unlikely(extsz)) { + if ((temp = do_mod(offset_fsb, extsz))) + resaligned += temp; + if ((temp = do_mod(resaligned, extsz))) + resaligned += extsz - temp; + } + + if (unlikely(rt)) { + resrtextents = qblocks = resaligned; + resrtextents /= mp->m_sb.sb_rextsize; + resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); + quota_flag = XFS_QMOPT_RES_RTBLKS; + } else { + resrtextents = 0; + resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned); + quota_flag = XFS_QMOPT_RES_REGBLKS; + } /* * Allocate and setup the transaction @@ -425,7 +493,6 @@ xfs_iomap_write_direct( XFS_WRITE_LOG_RES(mp), resrtextents, XFS_TRANS_PERM_LOG_RES, XFS_WRITE_LOG_COUNT); - /* * Check for running out of space, note: need lock to return */ @@ -435,20 +502,20 @@ xfs_iomap_write_direct( if (error) goto error_out; - if (XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag)) { - error = (EDQUOT); + error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, + qblocks, 0, quota_flag); + if (error) goto error1; - } - bmapi_flag = XFS_BMAPI_WRITE; xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_ihold(tp, ip); - if (!(flags & BMAPI_MMAP) && (offset < ip->i_d.di_size || rt)) + bmapi_flag = XFS_BMAPI_WRITE; + if ((flags & BMAPI_DIRECT) && (offset < ip->i_d.di_size || extsz)) bmapi_flag |= XFS_BMAPI_PREALLOC; /* - * Issue the bmapi() call to allocate the blocks + * Issue the xfs_bmapi() call to allocate the blocks */ XFS_BMAP_INIT(&free_list, &firstfsb); nimaps = 1; @@ -483,8 +550,10 @@ xfs_iomap_write_direct( "extent-state : %x \n", (ip->i_mount)->m_fsname, (long long)ip->i_ino, - ret_imap->br_startblock, ret_imap->br_startoff, - ret_imap->br_blockcount,ret_imap->br_state); + (unsigned long long)ret_imap->br_startblock, + (unsigned long long)ret_imap->br_startoff, + (unsigned long long)ret_imap->br_blockcount, + ret_imap->br_state); } return 0; @@ -500,6 +569,63 @@ error_out: return XFS_ERROR(error); } +/* + * If the caller is doing a write at the end of the file, + * then extend the allocation out to the file system's write + * iosize. We clean up any extra space left over when the + * file is closed in xfs_inactive(). + * + * For sync writes, we are flushing delayed allocate space to + * try to make additional space available for allocation near + * the filesystem full boundary - preallocation hurts in that + * situation, of course. + */ +STATIC int +xfs_iomap_eof_want_preallocate( + xfs_mount_t *mp, + xfs_iocore_t *io, + xfs_fsize_t isize, + xfs_off_t offset, + size_t count, + int ioflag, + xfs_bmbt_irec_t *imap, + int nimaps, + int *prealloc) +{ + xfs_fileoff_t start_fsb; + xfs_filblks_t count_fsb; + xfs_fsblock_t firstblock; + int n, error, imaps; + + *prealloc = 0; + if ((ioflag & BMAPI_SYNC) || (offset + count) <= isize) + return 0; + + /* + * If there are any real blocks past eof, then don't + * do any speculative allocation. + */ + start_fsb = XFS_B_TO_FSBT(mp, ((xfs_ufsize_t)(offset + count - 1))); + count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); + while (count_fsb > 0) { + imaps = nimaps; + firstblock = NULLFSBLOCK; + error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, + 0, &firstblock, 0, imap, &imaps, NULL); + if (error) + return error; + for (n = 0; n < imaps; n++) { + if ((imap[n].br_startblock != HOLESTARTBLOCK) && + (imap[n].br_startblock != DELAYSTARTBLOCK)) + return 0; + start_fsb += imap[n].br_blockcount; + count_fsb -= imap[n].br_blockcount; + } + } + *prealloc = 1; + return 0; +} + int xfs_iomap_write_delay( xfs_inode_t *ip, @@ -513,13 +639,15 @@ xfs_iomap_write_delay( xfs_iocore_t *io = &ip->i_iocore; xfs_fileoff_t offset_fsb; xfs_fileoff_t last_fsb; - xfs_fsize_t isize; + xfs_off_t aligned_offset; + xfs_fileoff_t ioalign; xfs_fsblock_t firstblock; + xfs_extlen_t extsz; + xfs_fsize_t isize; int nimaps; - int error; xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; - int aeof; - int fsynced = 0; + int prealloc, fsynced = 0; + int error; ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0); @@ -527,152 +655,57 @@ xfs_iomap_write_delay( * Make sure that the dquots are there. This doesn't hold * the ilock across a disk read. */ - error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED); if (error) return XFS_ERROR(error); + if (XFS_IS_REALTIME_INODE(ip)) { + if (!(extsz = ip->i_d.di_extsize)) + extsz = mp->m_sb.sb_rextsize; + } else { + extsz = ip->i_d.di_extsize; + } + + offset_fsb = XFS_B_TO_FSBT(mp, offset); + retry: isize = ip->i_d.di_size; - if (io->io_new_size > isize) { + if (io->io_new_size > isize) isize = io->io_new_size; - } - aeof = 0; - offset_fsb = XFS_B_TO_FSBT(mp, offset); - last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); - /* - * If the caller is doing a write at the end of the file, - * then extend the allocation (and the buffer used for the write) - * out to the file system's write iosize. We clean up any extra - * space left over when the file is closed in xfs_inactive(). - * - * For sync writes, we are flushing delayed allocate space to - * try to make additional space available for allocation near - * the filesystem full boundary - preallocation hurts in that - * situation, of course. - */ - if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) { - xfs_off_t aligned_offset; - xfs_filblks_t count_fsb; - unsigned int iosize; - xfs_fileoff_t ioalign; - int n; - xfs_fileoff_t start_fsb; + error = xfs_iomap_eof_want_preallocate(mp, io, isize, offset, count, + ioflag, imap, XFS_WRITE_IMAPS, &prealloc); + if (error) + return error; - /* - * If there are any real blocks past eof, then don't - * do any speculative allocation. - */ - start_fsb = XFS_B_TO_FSBT(mp, - ((xfs_ufsize_t)(offset + count - 1))); - count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); - while (count_fsb > 0) { - nimaps = XFS_WRITE_IMAPS; - error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, - 0, &firstblock, 0, imap, &nimaps, NULL); - if (error) { - return error; - } - for (n = 0; n < nimaps; n++) { - if ( !(io->io_flags & XFS_IOCORE_RT) && - !imap[n].br_startblock) { - cmn_err(CE_PANIC,"Access to block " - "zero: fs <%s> inode: %lld " - "start_block : %llx start_off " - ": %llx blkcnt : %llx " - "extent-state : %x \n", - (ip->i_mount)->m_fsname, - (long long)ip->i_ino, - imap[n].br_startblock, - imap[n].br_startoff, - imap[n].br_blockcount, - imap[n].br_state); - } - if ((imap[n].br_startblock != HOLESTARTBLOCK) && - (imap[n].br_startblock != DELAYSTARTBLOCK)) { - goto write_map; - } - start_fsb += imap[n].br_blockcount; - count_fsb -= imap[n].br_blockcount; - } - } - iosize = mp->m_writeio_blocks; + if (prealloc) { aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); ioalign = XFS_B_TO_FSBT(mp, aligned_offset); - last_fsb = ioalign + iosize; - aeof = 1; + last_fsb = ioalign + mp->m_writeio_blocks; + } else { + last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); } -write_map: - nimaps = XFS_WRITE_IMAPS; - firstblock = NULLFSBLOCK; - /* - * If mounted with the "-o swalloc" option, roundup the allocation - * request to a stripe width boundary if the file size is >= - * stripe width and we are allocating past the allocation eof. - */ - if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_swidth - && (mp->m_flags & XFS_MOUNT_SWALLOC) - && (isize >= XFS_FSB_TO_B(mp, mp->m_swidth)) && aeof) { - int eof; - xfs_fileoff_t new_last_fsb; - - new_last_fsb = roundup_64(last_fsb, mp->m_swidth); - error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof); - if (error) { - return error; - } - if (eof) { - last_fsb = new_last_fsb; - } - /* - * Roundup the allocation request to a stripe unit (m_dalign) boundary - * if the file size is >= stripe unit size, and we are allocating past - * the allocation eof. - */ - } else if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_dalign && - (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)) && aeof) { - int eof; - xfs_fileoff_t new_last_fsb; - new_last_fsb = roundup_64(last_fsb, mp->m_dalign); - error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof); - if (error) { - return error; - } - if (eof) { - last_fsb = new_last_fsb; - } - /* - * Round up the allocation request to a real-time extent boundary - * if the file is on the real-time subvolume. - */ - } else if (io->io_flags & XFS_IOCORE_RT && aeof) { - int eof; - xfs_fileoff_t new_last_fsb; - - new_last_fsb = roundup_64(last_fsb, mp->m_sb.sb_rextsize); - error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof); - if (error) { + if (prealloc || extsz) { + error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz, + &last_fsb); + if (error) return error; - } - if (eof) - last_fsb = new_last_fsb; } + + nimaps = XFS_WRITE_IMAPS; + firstblock = NULLFSBLOCK; error = xfs_bmapi(NULL, ip, offset_fsb, (xfs_filblks_t)(last_fsb - offset_fsb), XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, &nimaps, NULL); - /* - * This can be EDQUOT, if nimaps == 0 - */ - if (error && (error != ENOSPC)) { + if (error && (error != ENOSPC)) return XFS_ERROR(error); - } + /* * If bmapi returned us nothing, and if we didn't get back EDQUOT, - * then we must have run out of space. + * then we must have run out of space - flush delalloc, and retry.. */ if (nimaps == 0) { xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE, @@ -684,17 +717,21 @@ write_map: goto retry; } - *ret_imap = imap[0]; - *nmaps = 1; - if ( !(io->io_flags & XFS_IOCORE_RT) && !ret_imap->br_startblock) { + if (!(io->io_flags & XFS_IOCORE_RT) && !ret_imap->br_startblock) { cmn_err(CE_PANIC,"Access to block zero: fs <%s> inode: %lld " "start_block : %llx start_off : %llx blkcnt : %llx " "extent-state : %x \n", (ip->i_mount)->m_fsname, (long long)ip->i_ino, - ret_imap->br_startblock, ret_imap->br_startoff, - ret_imap->br_blockcount,ret_imap->br_state); + (unsigned long long)ret_imap->br_startblock, + (unsigned long long)ret_imap->br_startoff, + (unsigned long long)ret_imap->br_blockcount, + ret_imap->br_state); } + + *ret_imap = imap[0]; + *nmaps = 1; + return 0; } @@ -820,17 +857,21 @@ xfs_iomap_write_allocate( */ for (i = 0; i < nimaps; i++) { - if ( !(io->io_flags & XFS_IOCORE_RT) && - !imap[i].br_startblock) { + if (!(io->io_flags & XFS_IOCORE_RT) && + !imap[i].br_startblock) { cmn_err(CE_PANIC,"Access to block zero: " "fs <%s> inode: %lld " - "start_block : %llx start_off : %llx " + "start_block : %llx start_off : %llx " "blkcnt : %llx extent-state : %x \n", (ip->i_mount)->m_fsname, (long long)ip->i_ino, - imap[i].br_startblock, - imap[i].br_startoff, - imap[i].br_blockcount,imap[i].br_state); + (unsigned long long) + imap[i].br_startblock, + (unsigned long long) + imap[i].br_startoff, + (unsigned long long) + imap[i].br_blockcount, + imap[i].br_state); } if ((offset_fsb >= imap[i].br_startoff) && (offset_fsb < (imap[i].br_startoff + @@ -867,17 +908,17 @@ xfs_iomap_write_unwritten( { xfs_mount_t *mp = ip->i_mount; xfs_iocore_t *io = &ip->i_iocore; - xfs_trans_t *tp; xfs_fileoff_t offset_fsb; xfs_filblks_t count_fsb; xfs_filblks_t numblks_fsb; - xfs_bmbt_irec_t imap; + xfs_fsblock_t firstfsb; + int nimaps; + xfs_trans_t *tp; + xfs_bmbt_irec_t imap; + xfs_bmap_free_t free_list; + uint resblks; int committed; int error; - int nres; - int nimaps; - xfs_fsblock_t firstfsb; - xfs_bmap_free_t free_list; xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN, &ip->i_iocore, offset, count); @@ -886,9 +927,9 @@ xfs_iomap_write_unwritten( count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb); - do { - nres = XFS_DIOSTRAT_SPACE_RES(mp, 0); + resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1; + do { /* * set up a transaction to convert the range of extents * from unwritten to real. Do allocations in a loop until @@ -896,7 +937,7 @@ xfs_iomap_write_unwritten( */ tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); - error = xfs_trans_reserve(tp, nres, + error = xfs_trans_reserve(tp, resblks, XFS_WRITE_LOG_RES(mp), 0, XFS_TRANS_PERM_LOG_RES, XFS_WRITE_LOG_COUNT); @@ -915,7 +956,7 @@ xfs_iomap_write_unwritten( XFS_BMAP_INIT(&free_list, &firstfsb); nimaps = 1; error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, - XFS_BMAPI_WRITE, &firstfsb, + XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb, 1, &imap, &nimaps, &free_list); if (error) goto error_on_bmapi_transaction; @@ -929,15 +970,17 @@ xfs_iomap_write_unwritten( xfs_iunlock(ip, XFS_ILOCK_EXCL); if (error) goto error0; - + if ( !(io->io_flags & XFS_IOCORE_RT) && !imap.br_startblock) { cmn_err(CE_PANIC,"Access to block zero: fs <%s> " "inode: %lld start_block : %llx start_off : " "%llx blkcnt : %llx extent-state : %x \n", (ip->i_mount)->m_fsname, (long long)ip->i_ino, - imap.br_startblock,imap.br_startoff, - imap.br_blockcount,imap.br_state); + (unsigned long long)imap.br_startblock, + (unsigned long long)imap.br_startoff, + (unsigned long long)imap.br_blockcount, + imap.br_state); } if ((numblks_fsb = imap.br_blockcount) == 0) { diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index f63646ead81..c59450e1be4 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -56,6 +56,7 @@ xfs_bulkstat_one_iget( { xfs_dinode_core_t *dic; /* dinode core info pointer */ xfs_inode_t *ip; /* incore inode pointer */ + vnode_t *vp; int error; error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno); @@ -72,6 +73,7 @@ xfs_bulkstat_one_iget( goto out_iput; } + vp = XFS_ITOV(ip); dic = &ip->i_d; /* xfs_iget returns the following without needing @@ -84,8 +86,7 @@ xfs_bulkstat_one_iget( buf->bs_uid = dic->di_uid; buf->bs_gid = dic->di_gid; buf->bs_size = dic->di_size; - buf->bs_atime.tv_sec = dic->di_atime.t_sec; - buf->bs_atime.tv_nsec = dic->di_atime.t_nsec; + vn_atime_to_bstime(vp, &buf->bs_atime); buf->bs_mtime.tv_sec = dic->di_mtime.t_sec; buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec; buf->bs_ctime.tv_sec = dic->di_ctime.t_sec; diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 29af51275ca..3d9a36e7736 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -178,6 +178,83 @@ xlog_trace_iclog(xlog_in_core_t *iclog, uint state) #define xlog_trace_iclog(iclog,state) #endif /* XFS_LOG_TRACE */ + +static void +xlog_ins_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic) +{ + if (*qp) { + tic->t_next = (*qp); + tic->t_prev = (*qp)->t_prev; + (*qp)->t_prev->t_next = tic; + (*qp)->t_prev = tic; + } else { + tic->t_prev = tic->t_next = tic; + *qp = tic; + } + + tic->t_flags |= XLOG_TIC_IN_Q; +} + +static void +xlog_del_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic) +{ + if (tic == tic->t_next) { + *qp = NULL; + } else { + *qp = tic->t_next; + tic->t_next->t_prev = tic->t_prev; + tic->t_prev->t_next = tic->t_next; + } + + tic->t_next = tic->t_prev = NULL; + tic->t_flags &= ~XLOG_TIC_IN_Q; +} + +static void +xlog_grant_sub_space(struct log *log, int bytes) +{ + log->l_grant_write_bytes -= bytes; + if (log->l_grant_write_bytes < 0) { + log->l_grant_write_bytes += log->l_logsize; + log->l_grant_write_cycle--; + } + + log->l_grant_reserve_bytes -= bytes; + if ((log)->l_grant_reserve_bytes < 0) { + log->l_grant_reserve_bytes += log->l_logsize; + log->l_grant_reserve_cycle--; + } + +} + +static void +xlog_grant_add_space_write(struct log *log, int bytes) +{ + log->l_grant_write_bytes += bytes; + if (log->l_grant_write_bytes > log->l_logsize) { + log->l_grant_write_bytes -= log->l_logsize; + log->l_grant_write_cycle++; + } +} + +static void +xlog_grant_add_space_reserve(struct log *log, int bytes) +{ + log->l_grant_reserve_bytes += bytes; + if (log->l_grant_reserve_bytes > log->l_logsize) { + log->l_grant_reserve_bytes -= log->l_logsize; + log->l_grant_reserve_cycle++; + } +} + +static inline void +xlog_grant_add_space(struct log *log, int bytes) +{ + xlog_grant_add_space_write(log, bytes); + xlog_grant_add_space_reserve(log, bytes); +} + + /* * NOTES: * @@ -428,7 +505,7 @@ xfs_log_mount(xfs_mount_t *mp, if (readonly) vfsp->vfs_flag &= ~VFS_RDONLY; - error = xlog_recover(mp->m_log, readonly); + error = xlog_recover(mp->m_log); if (readonly) vfsp->vfs_flag |= VFS_RDONLY; @@ -1320,8 +1397,7 @@ xlog_sync(xlog_t *log, /* move grant heads by roundoff in sync */ s = GRANT_LOCK(log); - XLOG_GRANT_ADD_SPACE(log, roundoff, 'w'); - XLOG_GRANT_ADD_SPACE(log, roundoff, 'r'); + xlog_grant_add_space(log, roundoff); GRANT_UNLOCK(log, s); /* put cycle number in every block */ @@ -1515,7 +1591,6 @@ xlog_state_finish_copy(xlog_t *log, * print out info relating to regions written which consume * the reservation */ -#if defined(XFS_LOG_RES_DEBUG) STATIC void xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket) { @@ -1605,11 +1680,11 @@ xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket) ticket->t_res_arr_sum, ticket->t_res_o_flow, ticket->t_res_num_ophdrs, ophdr_spc, ticket->t_res_arr_sum + - ticket->t_res_o_flow + ophdr_spc, + ticket->t_res_o_flow + ophdr_spc, ticket->t_res_num); for (i = 0; i < ticket->t_res_num; i++) { - uint r_type = ticket->t_res_arr[i].r_type; + uint r_type = ticket->t_res_arr[i].r_type; cmn_err(CE_WARN, "region[%u]: %s - %u bytes\n", i, @@ -1618,9 +1693,6 @@ xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket) ticket->t_res_arr[i].r_len); } } -#else -#define xlog_print_tic_res(mp, ticket) -#endif /* * Write some region out to in-core log @@ -2389,7 +2461,7 @@ xlog_grant_log_space(xlog_t *log, /* something is already sleeping; insert new transaction at end */ if (log->l_reserve_headq) { - XLOG_INS_TICKETQ(log->l_reserve_headq, tic); + xlog_ins_ticketq(&log->l_reserve_headq, tic); xlog_trace_loggrant(log, tic, "xlog_grant_log_space: sleep 1"); /* @@ -2422,7 +2494,7 @@ redo: log->l_grant_reserve_bytes); if (free_bytes < need_bytes) { if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) - XLOG_INS_TICKETQ(log->l_reserve_headq, tic); + xlog_ins_ticketq(&log->l_reserve_headq, tic); xlog_trace_loggrant(log, tic, "xlog_grant_log_space: sleep 2"); XFS_STATS_INC(xs_sleep_logspace); @@ -2439,11 +2511,10 @@ redo: s = GRANT_LOCK(log); goto redo; } else if (tic->t_flags & XLOG_TIC_IN_Q) - XLOG_DEL_TICKETQ(log->l_reserve_headq, tic); + xlog_del_ticketq(&log->l_reserve_headq, tic); /* we've got enough space */ - XLOG_GRANT_ADD_SPACE(log, need_bytes, 'w'); - XLOG_GRANT_ADD_SPACE(log, need_bytes, 'r'); + xlog_grant_add_space(log, need_bytes); #ifdef DEBUG tail_lsn = log->l_tail_lsn; /* @@ -2464,7 +2535,7 @@ redo: error_return: if (tic->t_flags & XLOG_TIC_IN_Q) - XLOG_DEL_TICKETQ(log->l_reserve_headq, tic); + xlog_del_ticketq(&log->l_reserve_headq, tic); xlog_trace_loggrant(log, tic, "xlog_grant_log_space: err_ret"); /* * If we are failing, make sure the ticket doesn't have any @@ -2533,7 +2604,7 @@ xlog_regrant_write_log_space(xlog_t *log, if (ntic != log->l_write_headq) { if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) - XLOG_INS_TICKETQ(log->l_write_headq, tic); + xlog_ins_ticketq(&log->l_write_headq, tic); xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: sleep 1"); @@ -2565,7 +2636,7 @@ redo: log->l_grant_write_bytes); if (free_bytes < need_bytes) { if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) - XLOG_INS_TICKETQ(log->l_write_headq, tic); + xlog_ins_ticketq(&log->l_write_headq, tic); XFS_STATS_INC(xs_sleep_logspace); sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s); @@ -2581,9 +2652,10 @@ redo: s = GRANT_LOCK(log); goto redo; } else if (tic->t_flags & XLOG_TIC_IN_Q) - XLOG_DEL_TICKETQ(log->l_write_headq, tic); + xlog_del_ticketq(&log->l_write_headq, tic); - XLOG_GRANT_ADD_SPACE(log, need_bytes, 'w'); /* we've got enough space */ + /* we've got enough space */ + xlog_grant_add_space_write(log, need_bytes); #ifdef DEBUG tail_lsn = log->l_tail_lsn; if (CYCLE_LSN(tail_lsn) != log->l_grant_write_cycle) { @@ -2600,7 +2672,7 @@ redo: error_return: if (tic->t_flags & XLOG_TIC_IN_Q) - XLOG_DEL_TICKETQ(log->l_reserve_headq, tic); + xlog_del_ticketq(&log->l_reserve_headq, tic); xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: err_ret"); /* * If we are failing, make sure the ticket doesn't have any @@ -2633,8 +2705,7 @@ xlog_regrant_reserve_log_space(xlog_t *log, ticket->t_cnt--; s = GRANT_LOCK(log); - XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'w'); - XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'r'); + xlog_grant_sub_space(log, ticket->t_curr_res); ticket->t_curr_res = ticket->t_unit_res; XLOG_TIC_RESET_RES(ticket); xlog_trace_loggrant(log, ticket, @@ -2647,7 +2718,7 @@ xlog_regrant_reserve_log_space(xlog_t *log, return; } - XLOG_GRANT_ADD_SPACE(log, ticket->t_unit_res, 'r'); + xlog_grant_add_space_reserve(log, ticket->t_unit_res); xlog_trace_loggrant(log, ticket, "xlog_regrant_reserve_log_space: exit"); xlog_verify_grant_head(log, 0); @@ -2683,8 +2754,7 @@ xlog_ungrant_log_space(xlog_t *log, s = GRANT_LOCK(log); xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: enter"); - XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'w'); - XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'r'); + xlog_grant_sub_space(log, ticket->t_curr_res); xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: sub current"); @@ -2693,8 +2763,7 @@ xlog_ungrant_log_space(xlog_t *log, */ if (ticket->t_cnt > 0) { ASSERT(ticket->t_flags & XLOG_TIC_PERM_RESERV); - XLOG_GRANT_SUB_SPACE(log, ticket->t_unit_res*ticket->t_cnt,'w'); - XLOG_GRANT_SUB_SPACE(log, ticket->t_unit_res*ticket->t_cnt,'r'); + xlog_grant_sub_space(log, ticket->t_unit_res*ticket->t_cnt); } xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: exit"); diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index f40d4391fcf..4b2ac88dbb8 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h @@ -96,7 +96,6 @@ static inline xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2) /* Region types for iovec's i_type */ -#if defined(XFS_LOG_RES_DEBUG) #define XLOG_REG_TYPE_BFORMAT 1 #define XLOG_REG_TYPE_BCHUNK 2 #define XLOG_REG_TYPE_EFI_FORMAT 3 @@ -117,21 +116,13 @@ static inline xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2) #define XLOG_REG_TYPE_COMMIT 18 #define XLOG_REG_TYPE_TRANSHDR 19 #define XLOG_REG_TYPE_MAX 19 -#endif -#if defined(XFS_LOG_RES_DEBUG) #define XLOG_VEC_SET_TYPE(vecp, t) ((vecp)->i_type = (t)) -#else -#define XLOG_VEC_SET_TYPE(vecp, t) -#endif - typedef struct xfs_log_iovec { xfs_caddr_t i_addr; /* beginning address of region */ int i_len; /* length in bytes of region */ -#if defined(XFS_LOG_RES_DEBUG) - uint i_type; /* type of region */ -#endif + uint i_type; /* type of region */ } xfs_log_iovec_t; typedef void* xfs_log_ticket_t; diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 4518b188ade..34bcbf50789 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -253,7 +253,6 @@ typedef __uint32_t xlog_tid_t; /* Ticket reservation region accounting */ -#if defined(XFS_LOG_RES_DEBUG) #define XLOG_TIC_LEN_MAX 15 #define XLOG_TIC_RESET_RES(t) ((t)->t_res_num = \ (t)->t_res_arr_sum = (t)->t_res_num_ophdrs = 0) @@ -278,15 +277,9 @@ typedef __uint32_t xlog_tid_t; * we don't care about. */ typedef struct xlog_res { - uint r_len; - uint r_type; + uint r_len; /* region length :4 */ + uint r_type; /* region's transaction type :4 */ } xlog_res_t; -#else -#define XLOG_TIC_RESET_RES(t) -#define XLOG_TIC_ADD_OPHDR(t) -#define XLOG_TIC_ADD_REGION(t, len, type) -#endif - typedef struct xlog_ticket { sv_t t_sema; /* sleep on this semaphore : 20 */ @@ -301,14 +294,12 @@ typedef struct xlog_ticket { char t_flags; /* properties of reservation : 1 */ uint t_trans_type; /* transaction type : 4 */ -#if defined (XFS_LOG_RES_DEBUG) /* reservation array fields */ uint t_res_num; /* num in array : 4 */ - xlog_res_t t_res_arr[XLOG_TIC_LEN_MAX]; /* array of res : X */ uint t_res_num_ophdrs; /* num op hdrs : 4 */ uint t_res_arr_sum; /* array sum : 4 */ uint t_res_o_flow; /* sum overflow : 4 */ -#endif + xlog_res_t t_res_arr[XLOG_TIC_LEN_MAX]; /* array of res : 8 * 15 */ } xlog_ticket_t; #endif @@ -494,71 +485,13 @@ typedef struct log { #define XLOG_FORCED_SHUTDOWN(log) ((log)->l_flags & XLOG_IO_ERROR) -#define XLOG_GRANT_SUB_SPACE(log,bytes,type) \ - { \ - if (type == 'w') { \ - (log)->l_grant_write_bytes -= (bytes); \ - if ((log)->l_grant_write_bytes < 0) { \ - (log)->l_grant_write_bytes += (log)->l_logsize; \ - (log)->l_grant_write_cycle--; \ - } \ - } else { \ - (log)->l_grant_reserve_bytes -= (bytes); \ - if ((log)->l_grant_reserve_bytes < 0) { \ - (log)->l_grant_reserve_bytes += (log)->l_logsize;\ - (log)->l_grant_reserve_cycle--; \ - } \ - } \ - } -#define XLOG_GRANT_ADD_SPACE(log,bytes,type) \ - { \ - if (type == 'w') { \ - (log)->l_grant_write_bytes += (bytes); \ - if ((log)->l_grant_write_bytes > (log)->l_logsize) { \ - (log)->l_grant_write_bytes -= (log)->l_logsize; \ - (log)->l_grant_write_cycle++; \ - } \ - } else { \ - (log)->l_grant_reserve_bytes += (bytes); \ - if ((log)->l_grant_reserve_bytes > (log)->l_logsize) { \ - (log)->l_grant_reserve_bytes -= (log)->l_logsize;\ - (log)->l_grant_reserve_cycle++; \ - } \ - } \ - } -#define XLOG_INS_TICKETQ(q, tic) \ - { \ - if (q) { \ - (tic)->t_next = (q); \ - (tic)->t_prev = (q)->t_prev; \ - (q)->t_prev->t_next = (tic); \ - (q)->t_prev = (tic); \ - } else { \ - (tic)->t_prev = (tic)->t_next = (tic); \ - (q) = (tic); \ - } \ - (tic)->t_flags |= XLOG_TIC_IN_Q; \ - } -#define XLOG_DEL_TICKETQ(q, tic) \ - { \ - if ((tic) == (tic)->t_next) { \ - (q) = NULL; \ - } else { \ - (q) = (tic)->t_next; \ - (tic)->t_next->t_prev = (tic)->t_prev; \ - (tic)->t_prev->t_next = (tic)->t_next; \ - } \ - (tic)->t_next = (tic)->t_prev = NULL; \ - (tic)->t_flags &= ~XLOG_TIC_IN_Q; \ - } /* common routines */ extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp); extern int xlog_find_tail(xlog_t *log, xfs_daddr_t *head_blk, - xfs_daddr_t *tail_blk, - int readonly); -extern int xlog_recover(xlog_t *log, int readonly); + xfs_daddr_t *tail_blk); +extern int xlog_recover(xlog_t *log); extern int xlog_recover_finish(xlog_t *log, int mfsi_flags); extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int); extern void xlog_recover_process_iunlinks(xlog_t *log); diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 8ab7df76806..7d46cbd6a07 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -783,8 +783,7 @@ int xlog_find_tail( xlog_t *log, xfs_daddr_t *head_blk, - xfs_daddr_t *tail_blk, - int readonly) + xfs_daddr_t *tail_blk) { xlog_rec_header_t *rhead; xlog_op_header_t *op_head; @@ -2563,10 +2562,12 @@ xlog_recover_do_quotaoff_trans( /* * The logitem format's flag tells us if this was user quotaoff, - * group quotaoff or both. + * group/project quotaoff or both. */ if (qoff_f->qf_flags & XFS_UQUOTA_ACCT) log->l_quotaoffs_flag |= XFS_DQ_USER; + if (qoff_f->qf_flags & XFS_PQUOTA_ACCT) + log->l_quotaoffs_flag |= XFS_DQ_PROJ; if (qoff_f->qf_flags & XFS_GQUOTA_ACCT) log->l_quotaoffs_flag |= XFS_DQ_GROUP; @@ -3890,14 +3891,13 @@ xlog_do_recover( */ int xlog_recover( - xlog_t *log, - int readonly) + xlog_t *log) { xfs_daddr_t head_blk, tail_blk; int error; /* find the tail of the log */ - if ((error = xlog_find_tail(log, &head_blk, &tail_blk, readonly))) + if ((error = xlog_find_tail(log, &head_blk, &tail_blk))) return error; if (tail_blk != head_blk) { diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 303af86739b..6088e14f84e 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -51,7 +51,7 @@ STATIC int xfs_uuid_mount(xfs_mount_t *); STATIC void xfs_uuid_unmount(xfs_mount_t *mp); STATIC void xfs_unmountfs_wait(xfs_mount_t *); -static struct { +static const struct { short offset; short type; /* 0 = integer * 1 = binary / string (no translation) @@ -1077,8 +1077,7 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) xfs_iflush_all(mp); - XFS_QM_DQPURGEALL(mp, - XFS_QMOPT_UQUOTA | XFS_QMOPT_GQUOTA | XFS_QMOPT_UMOUNTING); + XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING); /* * Flush out the log synchronously so that we know for sure diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 3432fd5a398..cd3cf9613a0 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -308,7 +308,6 @@ typedef struct xfs_mount { xfs_buftarg_t *m_ddev_targp; /* saves taking the address */ xfs_buftarg_t *m_logdev_targp;/* ptr to log device */ xfs_buftarg_t *m_rtdev_targp; /* ptr to rt device */ -#define m_dev m_ddev_targp->pbr_dev __uint8_t m_dircook_elog; /* log d-cookie entry bits */ __uint8_t m_blkbit_log; /* blocklog + NBBY */ __uint8_t m_blkbb_log; /* blocklog - BBSHIFT */ @@ -393,7 +392,7 @@ typedef struct xfs_mount { user */ #define XFS_MOUNT_NOALIGN (1ULL << 7) /* turn off stripe alignment allocations */ -#define XFS_MOUNT_COMPAT_ATTR (1ULL << 8) /* do not use attr2 format */ +#define XFS_MOUNT_ATTR2 (1ULL << 8) /* allow use of attr2 format */ /* (1ULL << 9) -- currently unused */ #define XFS_MOUNT_NORECOVERY (1ULL << 10) /* no recovery - dirty fs */ #define XFS_MOUNT_SHARED (1ULL << 11) /* shared mount */ diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index 4d4e8f4e768..81a05cfd77d 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c @@ -243,7 +243,6 @@ xfs_rename( xfs_inode_t *inodes[4]; int target_ip_dropped = 0; /* dropped target_ip link? */ vnode_t *src_dir_vp; - bhv_desc_t *target_dir_bdp; int spaceres; int target_link_zero = 0; int num_inodes; @@ -260,14 +259,12 @@ xfs_rename( * Find the XFS behavior descriptor for the target directory * vnode since it was not handed to us. */ - target_dir_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(target_dir_vp), - &xfs_vnodeops); - if (target_dir_bdp == NULL) { + target_dp = xfs_vtoi(target_dir_vp); + if (target_dp == NULL) { return XFS_ERROR(EXDEV); } src_dp = XFS_BHVTOI(src_dir_bdp); - target_dp = XFS_BHVTOI(target_dir_bdp); mp = src_dp->i_mount; if (DM_EVENT_ENABLED(src_dir_vp->v_vfsp, src_dp, DM_EVENT_RENAME) || diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index c4b20872f07..a59c102cf21 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -238,6 +238,7 @@ xfs_bioerror_relse( } return (EIO); } + /* * Prints out an ALERT message about I/O error. */ @@ -252,11 +253,9 @@ xfs_ioerror_alert( "I/O error in filesystem (\"%s\") meta-data dev %s block 0x%llx" " (\"%s\") error %d buf count %zd", (!mp || !mp->m_fsname) ? "(fs name not set)" : mp->m_fsname, - XFS_BUFTARG_NAME(bp->pb_target), - (__uint64_t)blkno, - func, - XFS_BUF_GETERROR(bp), - XFS_BUF_COUNT(bp)); + XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)), + (__uint64_t)blkno, func, + XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp)); } /* diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h index 4a17d335f89..bf168a91ddb 100644 --- a/fs/xfs/xfs_sb.h +++ b/fs/xfs/xfs_sb.h @@ -68,18 +68,6 @@ struct xfs_mount; (XFS_SB_VERSION_NUMBITS | \ XFS_SB_VERSION_OKREALFBITS | \ XFS_SB_VERSION_OKSASHFBITS) -#define XFS_SB_VERSION_MKFS(ia,dia,extflag,dirv2,na,sflag,morebits) \ - (((ia) || (dia) || (extflag) || (dirv2) || (na) || (sflag) || \ - (morebits)) ? \ - (XFS_SB_VERSION_4 | \ - ((ia) ? XFS_SB_VERSION_ALIGNBIT : 0) | \ - ((dia) ? XFS_SB_VERSION_DALIGNBIT : 0) | \ - ((extflag) ? XFS_SB_VERSION_EXTFLGBIT : 0) | \ - ((dirv2) ? XFS_SB_VERSION_DIRV2BIT : 0) | \ - ((na) ? XFS_SB_VERSION_LOGV2BIT : 0) | \ - ((sflag) ? XFS_SB_VERSION_SECTORBIT : 0) | \ - ((morebits) ? XFS_SB_VERSION_MOREBITSBIT : 0)) : \ - XFS_SB_VERSION_1) /* * There are two words to hold XFS "feature" bits: the original @@ -105,11 +93,6 @@ struct xfs_mount; (XFS_SB_VERSION2_OKREALFBITS | \ XFS_SB_VERSION2_OKSASHFBITS ) -/* - * mkfs macro to set up sb_features2 word - */ -#define XFS_SB_VERSION2_MKFS(resvd1, sbcntr) 0 - typedef struct xfs_sb { __uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */ diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 279e043d732..d3d714e6b32 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -1014,6 +1014,7 @@ xfs_trans_cancel( xfs_log_item_t *lip; int i; #endif + xfs_mount_t *mp = tp->t_mountp; /* * See if the caller is being too lazy to figure out if @@ -1026,9 +1027,10 @@ xfs_trans_cancel( * filesystem. This happens in paths where we detect * corruption and decide to give up. */ - if ((tp->t_flags & XFS_TRANS_DIRTY) && - !XFS_FORCED_SHUTDOWN(tp->t_mountp)) - xfs_force_shutdown(tp->t_mountp, XFS_CORRUPT_INCORE); + if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) { + XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp); + xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); + } #ifdef DEBUG if (!(flags & XFS_TRANS_ABORT)) { licp = &(tp->t_items); @@ -1040,7 +1042,7 @@ xfs_trans_cancel( } lip = lidp->lid_item; - if (!XFS_FORCED_SHUTDOWN(tp->t_mountp)) + if (!XFS_FORCED_SHUTDOWN(mp)) ASSERT(!(lip->li_type == XFS_LI_EFD)); } licp = licp->lic_next; @@ -1048,7 +1050,7 @@ xfs_trans_cancel( } #endif xfs_trans_unreserve_and_mod_sb(tp); - XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(tp->t_mountp, tp); + XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp); if (tp->t_ticket) { if (flags & XFS_TRANS_RELEASE_LOG_RES) { @@ -1057,7 +1059,7 @@ xfs_trans_cancel( } else { log_flags = 0; } - xfs_log_done(tp->t_mountp, tp->t_ticket, NULL, log_flags); + xfs_log_done(mp, tp->t_ticket, NULL, log_flags); } /* mark this thread as no longer being in a transaction */ diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index a889963fdd1..d77901c07f6 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -973,7 +973,6 @@ void xfs_trans_bhold(xfs_trans_t *, struct xfs_buf *); void xfs_trans_bhold_release(xfs_trans_t *, struct xfs_buf *); void xfs_trans_binval(xfs_trans_t *, struct xfs_buf *); void xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *); -void xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *); void xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *); void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint); void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index fefe1d60377..34654ec6ae1 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c @@ -55,16 +55,13 @@ xfs_get_dir_entry( xfs_inode_t **ipp) { vnode_t *vp; - bhv_desc_t *bdp; vp = VNAME_TO_VNODE(dentry); - bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops); - if (!bdp) { - *ipp = NULL; + + *ipp = xfs_vtoi(vp); + if (!*ipp) return XFS_ERROR(ENOENT); - } VN_HOLD(vp); - *ipp = XFS_BHVTOI(bdp); return 0; } diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 7bdbd991ab1..b6ad370fab3 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -53,6 +53,7 @@ #include "xfs_acl.h" #include "xfs_attr.h" #include "xfs_clnt.h" +#include "xfs_fsops.h" STATIC int xfs_sync(bhv_desc_t *, int, cred_t *); @@ -290,8 +291,8 @@ xfs_start_flags( mp->m_flags |= XFS_MOUNT_IDELETE; if (ap->flags & XFSMNT_DIRSYNC) mp->m_flags |= XFS_MOUNT_DIRSYNC; - if (ap->flags & XFSMNT_COMPAT_ATTR) - mp->m_flags |= XFS_MOUNT_COMPAT_ATTR; + if (ap->flags & XFSMNT_ATTR2) + mp->m_flags |= XFS_MOUNT_ATTR2; if (ap->flags2 & XFSMNT2_COMPAT_IOSIZE) mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE; @@ -312,6 +313,8 @@ xfs_start_flags( mp->m_flags |= XFS_MOUNT_NOUUID; if (ap->flags & XFSMNT_BARRIER) mp->m_flags |= XFS_MOUNT_BARRIER; + else + mp->m_flags &= ~XFS_MOUNT_BARRIER; return 0; } @@ -330,10 +333,11 @@ xfs_finish_flags( /* Fail a mount where the logbuf is smaller then the log stripe */ if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) { - if ((ap->logbufsize == -1) && + if ((ap->logbufsize <= 0) && (mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE)) { mp->m_logbsize = mp->m_sb.sb_logsunit; - } else if (ap->logbufsize < mp->m_sb.sb_logsunit) { + } else if (ap->logbufsize > 0 && + ap->logbufsize < mp->m_sb.sb_logsunit) { cmn_err(CE_WARN, "XFS: logbuf size must be greater than or equal to log stripe size"); return XFS_ERROR(EINVAL); @@ -347,6 +351,10 @@ xfs_finish_flags( } } + if (XFS_SB_VERSION_HASATTR2(&mp->m_sb)) { + mp->m_flags |= XFS_MOUNT_ATTR2; + } + /* * prohibit r/w mounts of read-only filesystems */ @@ -382,10 +390,6 @@ xfs_finish_flags( return XFS_ERROR(EINVAL); } - if (XFS_SB_VERSION_HASATTR2(&mp->m_sb)) { - mp->m_flags &= ~XFS_MOUNT_COMPAT_ATTR; - } - return 0; } @@ -504,13 +508,13 @@ xfs_mount( if (error) goto error2; + if ((mp->m_flags & XFS_MOUNT_BARRIER) && !(vfsp->vfs_flag & VFS_RDONLY)) + xfs_mountfs_check_barriers(mp); + error = XFS_IOINIT(vfsp, args, flags); if (error) goto error2; - if ((args->flags & XFSMNT_BARRIER) && - !(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)) - xfs_mountfs_check_barriers(mp); return 0; error2: @@ -655,6 +659,11 @@ xfs_mntupdate( else mp->m_flags &= ~XFS_MOUNT_NOATIME; + if (args->flags & XFSMNT_BARRIER) + mp->m_flags |= XFS_MOUNT_BARRIER; + else + mp->m_flags &= ~XFS_MOUNT_BARRIER; + if ((vfsp->vfs_flag & VFS_RDONLY) && !(*flags & MS_RDONLY)) { vfsp->vfs_flag &= ~VFS_RDONLY; @@ -1634,6 +1643,7 @@ xfs_vget( #define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */ #define MNTOPT_BARRIER "barrier" /* use writer barriers for log write and * unwritten extent conversion */ +#define MNTOPT_NOBARRIER "nobarrier" /* .. disable */ #define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */ #define MNTOPT_64BITINODE "inode64" /* inodes can be allocated anywhere */ #define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */ @@ -1680,7 +1690,6 @@ xfs_parseargs( int iosize; args->flags2 |= XFSMNT2_COMPAT_IOSIZE; - args->flags |= XFSMNT_COMPAT_ATTR; #if 0 /* XXX: off by default, until some remaining issues ironed out */ args->flags |= XFSMNT_IDELETE; /* default to on */ @@ -1806,6 +1815,8 @@ xfs_parseargs( args->flags |= XFSMNT_NOUUID; } else if (!strcmp(this_char, MNTOPT_BARRIER)) { args->flags |= XFSMNT_BARRIER; + } else if (!strcmp(this_char, MNTOPT_NOBARRIER)) { + args->flags &= ~XFSMNT_BARRIER; } else if (!strcmp(this_char, MNTOPT_IKEEP)) { args->flags &= ~XFSMNT_IDELETE; } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) { @@ -1815,9 +1826,9 @@ xfs_parseargs( } else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) { args->flags2 |= XFSMNT2_COMPAT_IOSIZE; } else if (!strcmp(this_char, MNTOPT_ATTR2)) { - args->flags &= ~XFSMNT_COMPAT_ATTR; + args->flags |= XFSMNT_ATTR2; } else if (!strcmp(this_char, MNTOPT_NOATTR2)) { - args->flags |= XFSMNT_COMPAT_ATTR; + args->flags &= ~XFSMNT_ATTR2; } else if (!strcmp(this_char, "osyncisdsync")) { /* no-op, this is now the default */ printk("XFS: osyncisdsync is now the default, option is deprecated.\n"); @@ -1892,7 +1903,6 @@ xfs_showargs( { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID }, { XFS_MOUNT_NORECOVERY, "," MNTOPT_NORECOVERY }, { XFS_MOUNT_OSYNCISOSYNC, "," MNTOPT_OSYNCISOSYNC }, - { XFS_MOUNT_BARRIER, "," MNTOPT_BARRIER }, { XFS_MOUNT_IDELETE, "," MNTOPT_NOIKEEP }, { 0, NULL } }; @@ -1914,33 +1924,28 @@ xfs_showargs( if (mp->m_logbufs > 0) seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs); - if (mp->m_logbsize > 0) seq_printf(m, "," MNTOPT_LOGBSIZE "=%dk", mp->m_logbsize >> 10); if (mp->m_logname) seq_printf(m, "," MNTOPT_LOGDEV "=%s", mp->m_logname); - if (mp->m_rtname) seq_printf(m, "," MNTOPT_RTDEV "=%s", mp->m_rtname); if (mp->m_dalign > 0) seq_printf(m, "," MNTOPT_SUNIT "=%d", (int)XFS_FSB_TO_BB(mp, mp->m_dalign)); - if (mp->m_swidth > 0) seq_printf(m, "," MNTOPT_SWIDTH "=%d", (int)XFS_FSB_TO_BB(mp, mp->m_swidth)); - if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR)) - seq_printf(m, "," MNTOPT_ATTR2); - if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE)) seq_printf(m, "," MNTOPT_LARGEIO); + if (mp->m_flags & XFS_MOUNT_BARRIER) + seq_printf(m, "," MNTOPT_BARRIER); if (!(vfsp->vfs_flag & VFS_32BITINODES)) seq_printf(m, "," MNTOPT_64BITINODE); - if (vfsp->vfs_flag & VFS_GRPID) seq_printf(m, "," MNTOPT_GRPID); @@ -1959,6 +1964,7 @@ xfs_freeze( /* Push the superblock and write an unmount record */ xfs_log_unmount_write(mp); xfs_unmountfs_writesb(mp); + xfs_fs_log_dummy(mp); } diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index e92cacde02f..8076cc981e1 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -185,8 +185,7 @@ xfs_getattr( break; } - vap->va_atime.tv_sec = ip->i_d.di_atime.t_sec; - vap->va_atime.tv_nsec = ip->i_d.di_atime.t_nsec; + vn_atime_to_timespec(vp, &vap->va_atime); vap->va_mtime.tv_sec = ip->i_d.di_mtime.t_sec; vap->va_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; vap->va_ctime.tv_sec = ip->i_d.di_ctime.t_sec; @@ -544,24 +543,6 @@ xfs_setattr( } /* - * Can't set extent size unless the file is marked, or - * about to be marked as a realtime file. - * - * This check will be removed when fixed size extents - * with buffered data writes is implemented. - * - */ - if ((mask & XFS_AT_EXTSIZE) && - ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != - vap->va_extsize) && - (!((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) || - ((mask & XFS_AT_XFLAGS) && - (vap->va_xflags & XFS_XFLAG_REALTIME))))) { - code = XFS_ERROR(EINVAL); - goto error_return; - } - - /* * Can't change realtime flag if any extents are allocated. */ if ((ip->i_d.di_nextents || ip->i_delayed_blks) && @@ -823,13 +804,17 @@ xfs_setattr( di_flags |= XFS_DIFLAG_RTINHERIT; if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS) di_flags |= XFS_DIFLAG_NOSYMLINKS; - } else { + if (vap->va_xflags & XFS_XFLAG_EXTSZINHERIT) + di_flags |= XFS_DIFLAG_EXTSZINHERIT; + } else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) { if (vap->va_xflags & XFS_XFLAG_REALTIME) { di_flags |= XFS_DIFLAG_REALTIME; ip->i_iocore.io_flags |= XFS_IOCORE_RT; } else { ip->i_iocore.io_flags &= ~XFS_IOCORE_RT; } + if (vap->va_xflags & XFS_XFLAG_EXTSIZE) + di_flags |= XFS_DIFLAG_EXTSIZE; } ip->i_d.di_flags = di_flags; } @@ -999,10 +984,6 @@ xfs_readlink( goto error_return; } - if (!(ioflags & IO_INVIS)) { - xfs_ichgtime(ip, XFS_ICHGTIME_ACC); - } - /* * See if the symlink is stored inline. */ @@ -1234,7 +1215,8 @@ xfs_inactive_free_eofblocks( xfs_iunlock(ip, XFS_ILOCK_SHARED); if (!error && (nimaps != 0) && - (imap.br_startblock != HOLESTARTBLOCK)) { + (imap.br_startblock != HOLESTARTBLOCK || + ip->i_delayed_blks)) { /* * Attach the dquots to the inode up front. */ @@ -1569,9 +1551,11 @@ xfs_release( if (ip->i_d.di_nlink != 0) { if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && - ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) && + ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 || + ip->i_delayed_blks > 0)) && (ip->i_df.if_flags & XFS_IFEXTENTS)) && - (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)))) { + (!(ip->i_d.di_flags & + (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) { if ((error = xfs_inactive_free_eofblocks(mp, ip))) return (error); /* Update linux inode block count after free above */ @@ -1628,7 +1612,8 @@ xfs_inactive( * only one with a reference to the inode. */ truncate = ((ip->i_d.di_nlink == 0) && - ((ip->i_d.di_size != 0) || (ip->i_d.di_nextents > 0)) && + ((ip->i_d.di_size != 0) || (ip->i_d.di_nextents > 0) || + (ip->i_delayed_blks > 0)) && ((ip->i_d.di_mode & S_IFMT) == S_IFREG)); mp = ip->i_mount; @@ -1646,10 +1631,12 @@ xfs_inactive( if (ip->i_d.di_nlink != 0) { if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && - ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) && - (ip->i_df.if_flags & XFS_IFEXTENTS)) && - (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)) || - (ip->i_delayed_blks != 0))) { + ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 || + ip->i_delayed_blks > 0)) && + (ip->i_df.if_flags & XFS_IFEXTENTS) && + (!(ip->i_d.di_flags & + (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || + (ip->i_delayed_blks != 0)))) { if ((error = xfs_inactive_free_eofblocks(mp, ip))) return (VN_INACTIVE_CACHE); /* Update linux inode block count after free above */ @@ -2593,7 +2580,6 @@ xfs_link( int cancel_flags; int committed; vnode_t *target_dir_vp; - bhv_desc_t *src_bdp; int resblks; char *target_name = VNAME(dentry); int target_namelen; @@ -2606,8 +2592,7 @@ xfs_link( if (VN_ISDIR(src_vp)) return XFS_ERROR(EPERM); - src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops); - sip = XFS_BHVTOI(src_bdp); + sip = xfs_vtoi(src_vp); tdp = XFS_BHVTOI(target_dir_bdp); mp = tdp->i_mount; if (XFS_FORCED_SHUTDOWN(mp)) @@ -3240,7 +3225,6 @@ xfs_readdir( xfs_trans_t *tp = NULL; int error = 0; uint lock_mode; - xfs_off_t start_offset; vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__, (inst_t *)__return_address); @@ -3251,11 +3235,7 @@ xfs_readdir( } lock_mode = xfs_ilock_map_shared(dp); - start_offset = uiop->uio_offset; error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp); - if (start_offset != uiop->uio_offset) { - xfs_ichgtime(dp, XFS_ICHGTIME_ACC); - } xfs_iunlock_map_shared(dp, lock_mode); return error; } @@ -3832,7 +3812,12 @@ xfs_reclaim( vn_iowait(vp); ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); - ASSERT(VN_CACHED(vp) == 0); + + /* + * Make sure the atime in the XFS inode is correct before freeing the + * Linux inode. + */ + xfs_synchronize_atime(ip); /* If we have nothing to flush with this inode then complete the * teardown now, otherwise break the link between the xfs inode @@ -4002,42 +3987,36 @@ xfs_alloc_file_space( int alloc_type, int attr_flags) { + xfs_mount_t *mp = ip->i_mount; + xfs_off_t count; xfs_filblks_t allocated_fsb; xfs_filblks_t allocatesize_fsb; - int committed; - xfs_off_t count; - xfs_filblks_t datablocks; - int error; + xfs_extlen_t extsz, temp; + xfs_fileoff_t startoffset_fsb; xfs_fsblock_t firstfsb; - xfs_bmap_free_t free_list; - xfs_bmbt_irec_t *imapp; - xfs_bmbt_irec_t imaps[1]; - xfs_mount_t *mp; - int numrtextents; - int reccount; - uint resblks; + int nimaps; + int bmapi_flag; + int quota_flag; int rt; - int rtextsize; - xfs_fileoff_t startoffset_fsb; xfs_trans_t *tp; - int xfs_bmapi_flags; + xfs_bmbt_irec_t imaps[1], *imapp; + xfs_bmap_free_t free_list; + uint qblocks, resblks, resrtextents; + int committed; + int error; vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); - mp = ip->i_mount; if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); - /* - * determine if this is a realtime file - */ - if ((rt = XFS_IS_REALTIME_INODE(ip)) != 0) { - if (ip->i_d.di_extsize) - rtextsize = ip->i_d.di_extsize; - else - rtextsize = mp->m_sb.sb_rextsize; - } else - rtextsize = 0; + rt = XFS_IS_REALTIME_INODE(ip); + if (unlikely(rt)) { + if (!(extsz = ip->i_d.di_extsize)) + extsz = mp->m_sb.sb_rextsize; + } else { + extsz = ip->i_d.di_extsize; + } if ((error = XFS_QM_DQATTACH(mp, ip, 0))) return error; @@ -4048,8 +4027,8 @@ xfs_alloc_file_space( count = len; error = 0; imapp = &imaps[0]; - reccount = 1; - xfs_bmapi_flags = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0); + nimaps = 1; + bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0); startoffset_fsb = XFS_B_TO_FSBT(mp, offset); allocatesize_fsb = XFS_B_TO_FSB(mp, count); @@ -4070,43 +4049,51 @@ xfs_alloc_file_space( } /* - * allocate file space until done or until there is an error + * Allocate file space until done or until there is an error */ retry: while (allocatesize_fsb && !error) { + xfs_fileoff_t s, e; + /* - * determine if reserving space on - * the data or realtime partition. + * Determine space reservations for data/realtime. */ - if (rt) { - xfs_fileoff_t s, e; - + if (unlikely(extsz)) { s = startoffset_fsb; - do_div(s, rtextsize); - s *= rtextsize; - e = roundup_64(startoffset_fsb + allocatesize_fsb, - rtextsize); - numrtextents = (int)(e - s) / mp->m_sb.sb_rextsize; - datablocks = 0; + do_div(s, extsz); + s *= extsz; + e = startoffset_fsb + allocatesize_fsb; + if ((temp = do_mod(startoffset_fsb, extsz))) + e += temp; + if ((temp = do_mod(e, extsz))) + e += extsz - temp; + } else { + s = 0; + e = allocatesize_fsb; + } + + if (unlikely(rt)) { + resrtextents = qblocks = (uint)(e - s); + resrtextents /= mp->m_sb.sb_rextsize; + resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); + quota_flag = XFS_QMOPT_RES_RTBLKS; } else { - datablocks = allocatesize_fsb; - numrtextents = 0; + resrtextents = 0; + resblks = qblocks = \ + XFS_DIOSTRAT_SPACE_RES(mp, (uint)(e - s)); + quota_flag = XFS_QMOPT_RES_REGBLKS; } /* - * allocate and setup the transaction + * Allocate and setup the transaction. */ tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); - resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); - error = xfs_trans_reserve(tp, - resblks, - XFS_WRITE_LOG_RES(mp), - numrtextents, + error = xfs_trans_reserve(tp, resblks, + XFS_WRITE_LOG_RES(mp), resrtextents, XFS_TRANS_PERM_LOG_RES, XFS_WRITE_LOG_COUNT); - /* - * check for running out of space + * Check for running out of space */ if (error) { /* @@ -4117,8 +4104,8 @@ retry: break; } xfs_ilock(ip, XFS_ILOCK_EXCL); - error = XFS_TRANS_RESERVE_QUOTA(mp, tp, - ip->i_udquot, ip->i_gdquot, resblks, 0, 0); + error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, + qblocks, 0, quota_flag); if (error) goto error1; @@ -4126,19 +4113,19 @@ retry: xfs_trans_ihold(tp, ip); /* - * issue the bmapi() call to allocate the blocks + * Issue the xfs_bmapi() call to allocate the blocks */ XFS_BMAP_INIT(&free_list, &firstfsb); error = xfs_bmapi(tp, ip, startoffset_fsb, - allocatesize_fsb, xfs_bmapi_flags, - &firstfsb, 0, imapp, &reccount, + allocatesize_fsb, bmapi_flag, + &firstfsb, 0, imapp, &nimaps, &free_list); if (error) { goto error0; } /* - * complete the transaction + * Complete the transaction */ error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); if (error) { @@ -4153,7 +4140,7 @@ retry: allocated_fsb = imapp->br_blockcount; - if (reccount == 0) { + if (nimaps == 0) { error = XFS_ERROR(ENOSPC); break; } @@ -4176,9 +4163,11 @@ dmapi_enospc_check: return error; - error0: +error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */ xfs_bmap_cancel(&free_list); - error1: + XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag); + +error1: /* Just cancel transaction */ xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); xfs_iunlock(ip, XFS_ILOCK_EXCL); goto dmapi_enospc_check; @@ -4423,8 +4412,8 @@ xfs_free_file_space( } xfs_ilock(ip, XFS_ILOCK_EXCL); error = XFS_TRANS_RESERVE_QUOTA(mp, tp, - ip->i_udquot, ip->i_gdquot, resblks, 0, rt ? - XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); + ip->i_udquot, ip->i_gdquot, resblks, 0, + XFS_QMOPT_RES_REGBLKS); if (error) goto error1; diff --git a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h index a714d0cdc20..6f92482cc96 100644 --- a/include/asm-alpha/mmu_context.h +++ b/include/asm-alpha/mmu_context.h @@ -156,7 +156,7 @@ ev5_switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm, /* Always update the PCB ASN. Another thread may have allocated a new mm->context (via flush_tlb_mm) without the ASN serial number wrapping. We have no way to detect when this is needed. */ - next->thread_info->pcb.asn = mmc & HARDWARE_ASN_MASK; + task_thread_info(next)->pcb.asn = mmc & HARDWARE_ASN_MASK; } __EXTERN_INLINE void @@ -235,7 +235,7 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm) if (cpu_online(i)) mm->context[i] = 0; if (tsk != current) - tsk->thread_info->pcb.ptbr + task_thread_info(tsk)->pcb.ptbr = ((unsigned long)mm->pgd - IDENT_ADDR) >> PAGE_SHIFT; return 0; } @@ -249,7 +249,7 @@ destroy_context(struct mm_struct *mm) static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { - tsk->thread_info->pcb.ptbr + task_thread_info(tsk)->pcb.ptbr = ((unsigned long)mm->pgd - IDENT_ADDR) >> PAGE_SHIFT; } diff --git a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h index bb1a7a3abb8..425b7b6d28c 100644 --- a/include/asm-alpha/processor.h +++ b/include/asm-alpha/processor.h @@ -52,19 +52,10 @@ extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); unsigned long get_wchan(struct task_struct *p); -/* See arch/alpha/kernel/ptrace.c for details. */ -#define PT_REG(reg) \ - (PAGE_SIZE*2 - sizeof(struct pt_regs) + offsetof(struct pt_regs, reg)) - -#define SW_REG(reg) \ - (PAGE_SIZE*2 - sizeof(struct pt_regs) - sizeof(struct switch_stack) \ - + offsetof(struct switch_stack, reg)) - -#define KSTK_EIP(tsk) \ - (*(unsigned long *)(PT_REG(pc) + (unsigned long) ((tsk)->thread_info))) +#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) #define KSTK_ESP(tsk) \ - ((tsk) == current ? rdusp() : (tsk)->thread_info->pcb.usp) + ((tsk) == current ? rdusp() : task_thread_info(tsk)->pcb.usp) #define cpu_relax() barrier() diff --git a/include/asm-alpha/ptrace.h b/include/asm-alpha/ptrace.h index 072375c135b..9933b8b3612 100644 --- a/include/asm-alpha/ptrace.h +++ b/include/asm-alpha/ptrace.h @@ -75,10 +75,10 @@ struct switch_stack { #define profile_pc(regs) instruction_pointer(regs) extern void show_regs(struct pt_regs *); -#define alpha_task_regs(task) \ - ((struct pt_regs *) ((long) (task)->thread_info + 2*PAGE_SIZE) - 1) +#define task_pt_regs(task) \ + ((struct pt_regs *) (task_stack_page(task) + 2*PAGE_SIZE) - 1) -#define force_successful_syscall_return() (alpha_task_regs(current)->r0 = 0) +#define force_successful_syscall_return() (task_pt_regs(current)->r0 = 0) #endif diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h index 050e86d1289..cc9c7e8cced 100644 --- a/include/asm-alpha/system.h +++ b/include/asm-alpha/system.h @@ -131,15 +131,25 @@ struct el_common_EV6_mcheck { extern void halt(void) __attribute__((noreturn)); #define __halt() __asm__ __volatile__ ("call_pal %0 #halt" : : "i" (PAL_halt)) -#define switch_to(P,N,L) \ - do { \ - (L) = alpha_switch_to(virt_to_phys(&(N)->thread_info->pcb), (P)); \ - check_mmu_context(); \ +#define switch_to(P,N,L) \ + do { \ + (L) = alpha_switch_to(virt_to_phys(&task_thread_info(N)->pcb), (P)); \ + check_mmu_context(); \ } while (0) struct task_struct; extern struct task_struct *alpha_switch_to(unsigned long, struct task_struct*); +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} + #define imb() \ __asm__ __volatile__ ("call_pal %0 #imb" : : "i" (PAL_imb) : "memory") diff --git a/include/asm-alpha/thread_info.h b/include/asm-alpha/thread_info.h index d51491ed00b..69ffd93f8e2 100644 --- a/include/asm-alpha/thread_info.h +++ b/include/asm-alpha/thread_info.h @@ -54,8 +54,6 @@ register struct thread_info *__current_thread_info __asm__("$8"); #define alloc_thread_info(tsk) \ ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #endif /* __ASSEMBLY__ */ diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h index 7d4118e0905..31290694648 100644 --- a/include/asm-arm/processor.h +++ b/include/asm-arm/processor.h @@ -85,9 +85,11 @@ unsigned long get_wchan(struct task_struct *p); */ extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); -#define KSTK_REGS(tsk) (((struct pt_regs *)(THREAD_START_SP + (unsigned long)(tsk)->thread_info)) - 1) -#define KSTK_EIP(tsk) KSTK_REGS(tsk)->ARM_pc -#define KSTK_ESP(tsk) KSTK_REGS(tsk)->ARM_sp +#define task_pt_regs(p) \ + ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) + +#define KSTK_EIP(tsk) task_pt_regs(tsk)->ARM_pc +#define KSTK_ESP(tsk) task_pt_regs(tsk)->ARM_sp /* * Prefetching support - only ARMv5. diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h index 5621d61ebc0..eb2de8c1051 100644 --- a/include/asm-arm/system.h +++ b/include/asm-arm/system.h @@ -168,10 +168,20 @@ extern struct task_struct *__switch_to(struct task_struct *, struct thread_info #define switch_to(prev,next,last) \ do { \ - last = __switch_to(prev,prev->thread_info,next->thread_info); \ + last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \ } while (0) /* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} + +/* * CPU interrupt mask handling. */ #if __LINUX_ARM_ARCH__ >= 6 diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h index 7c98557b717..33a33cbb632 100644 --- a/include/asm-arm/thread_info.h +++ b/include/asm-arm/thread_info.h @@ -96,13 +96,10 @@ static inline struct thread_info *current_thread_info(void) extern struct thread_info *alloc_thread_info(struct task_struct *task); extern void free_thread_info(struct thread_info *); -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) - #define thread_saved_pc(tsk) \ - ((unsigned long)(pc_pointer((tsk)->thread_info->cpu_context.pc))) + ((unsigned long)(pc_pointer(task_thread_info(tsk)->cpu_context.pc))) #define thread_saved_fp(tsk) \ - ((unsigned long)((tsk)->thread_info->cpu_context.fp)) + ((unsigned long)(task_thread_info(tsk)->cpu_context.fp)) extern void iwmmxt_task_disable(struct thread_info *); extern void iwmmxt_task_copy(struct thread_info *, void *); diff --git a/include/asm-arm26/system.h b/include/asm-arm26/system.h index f23fac1938f..ca4ccfc4b57 100644 --- a/include/asm-arm26/system.h +++ b/include/asm-arm26/system.h @@ -111,10 +111,20 @@ extern struct task_struct *__switch_to(struct task_struct *, struct thread_info #define switch_to(prev,next,last) \ do { \ - last = __switch_to(prev,prev->thread_info,next->thread_info); \ + last = __switch_to(prev,task_thread_info(prev),task_thread_info(next)); \ } while (0) /* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} + +/* * Save the current interrupt enable state & disable IRQs */ #define local_irq_save(x) \ diff --git a/include/asm-arm26/thread_info.h b/include/asm-arm26/thread_info.h index aff3e5699c6..a65e58a0a76 100644 --- a/include/asm-arm26/thread_info.h +++ b/include/asm-arm26/thread_info.h @@ -82,18 +82,15 @@ static inline struct thread_info *current_thread_info(void) /* FIXME - PAGE_SIZE < 32K */ #define THREAD_SIZE (8*32768) // FIXME - this needs attention (see kernel/fork.c which gets a nice div by zero if this is lower than 8*32768 -#define __get_user_regs(x) (((struct pt_regs *)((unsigned long)(x) + THREAD_SIZE - 8)) - 1) +#define task_pt_regs(task) ((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE - 8) - 1) extern struct thread_info *alloc_thread_info(struct task_struct *task); extern void free_thread_info(struct thread_info *); -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) - #define thread_saved_pc(tsk) \ - ((unsigned long)(pc_pointer((tsk)->thread_info->cpu_context.pc))) + ((unsigned long)(pc_pointer(task_thread_info(tsk)->cpu_context.pc))) #define thread_saved_fp(tsk) \ - ((unsigned long)((tsk)->thread_info->cpu_context.fp)) + ((unsigned long)(task_thread_info(tsk)->cpu_context.fp)) #else /* !__ASSEMBLY__ */ diff --git a/include/asm-cris/arch-v10/processor.h b/include/asm-cris/arch-v10/processor.h index e23df8dc96e..cc692c7a066 100644 --- a/include/asm-cris/arch-v10/processor.h +++ b/include/asm-cris/arch-v10/processor.h @@ -40,7 +40,7 @@ struct thread_struct { #define KSTK_EIP(tsk) \ ({ \ unsigned long eip = 0; \ - unsigned long regs = (unsigned long)user_regs(tsk); \ + unsigned long regs = (unsigned long)task_pt_regs(tsk); \ if (regs > PAGE_SIZE && \ virt_addr_valid(regs)) \ eip = ((struct pt_regs *)regs)->irp; \ diff --git a/include/asm-cris/arch-v32/processor.h b/include/asm-cris/arch-v32/processor.h index 8c939bf2798..32bf2e538ce 100644 --- a/include/asm-cris/arch-v32/processor.h +++ b/include/asm-cris/arch-v32/processor.h @@ -36,7 +36,7 @@ struct thread_struct { #define KSTK_EIP(tsk) \ ({ \ unsigned long eip = 0; \ - unsigned long regs = (unsigned long)user_regs(tsk); \ + unsigned long regs = (unsigned long)task_pt_regs(tsk); \ if (regs > PAGE_SIZE && virt_addr_valid(regs)) \ eip = ((struct pt_regs *)regs)->erp; \ eip; \ diff --git a/include/asm-cris/processor.h b/include/asm-cris/processor.h index dce41009eeb..961e2bceadb 100644 --- a/include/asm-cris/processor.h +++ b/include/asm-cris/processor.h @@ -45,7 +45,8 @@ struct task_struct; * Dito but for the currently running task */ -#define current_regs() user_regs(current->thread_info) +#define task_pt_regs(task) user_regs(task_thread_info(task)) +#define current_regs() task_pt_regs(current) static inline void prepare_to_copy(struct task_struct *tsk) { diff --git a/include/asm-cris/thread_info.h b/include/asm-cris/thread_info.h index cef0140fc10..7ad853c3f74 100644 --- a/include/asm-cris/thread_info.h +++ b/include/asm-cris/thread_info.h @@ -69,8 +69,6 @@ struct thread_info { /* thread information allocation */ #define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-frv/thread_info.h b/include/asm-frv/thread_info.h index 60f6b2aee76..a5576e02dd1 100644 --- a/include/asm-frv/thread_info.h +++ b/include/asm-frv/thread_info.h @@ -110,8 +110,6 @@ register struct thread_info *__current_thread_info asm("gr15"); #endif #define free_thread_info(info) kfree(info) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #else /* !__ASSEMBLY__ */ diff --git a/include/asm-h8300/thread_info.h b/include/asm-h8300/thread_info.h index bfcc755c3bb..45f09dc9caf 100644 --- a/include/asm-h8300/thread_info.h +++ b/include/asm-h8300/thread_info.h @@ -69,8 +69,6 @@ static inline struct thread_info *current_thread_info(void) #define alloc_thread_info(tsk) ((struct thread_info *) \ __get_free_pages(GFP_KERNEL, 1)) #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #endif /* __ASSEMBLY__ */ /* diff --git a/include/asm-i386/i387.h b/include/asm-i386/i387.h index 6747006743f..152d0baa576 100644 --- a/include/asm-i386/i387.h +++ b/include/asm-i386/i387.h @@ -49,19 +49,19 @@ static inline void __save_init_fpu( struct task_struct *tsk ) X86_FEATURE_FXSR, "m" (tsk->thread.i387.fxsave) :"memory"); - tsk->thread_info->status &= ~TS_USEDFPU; + task_thread_info(tsk)->status &= ~TS_USEDFPU; } #define __unlazy_fpu( tsk ) do { \ - if ((tsk)->thread_info->status & TS_USEDFPU) \ + if (task_thread_info(tsk)->status & TS_USEDFPU) \ save_init_fpu( tsk ); \ } while (0) #define __clear_fpu( tsk ) \ do { \ - if ((tsk)->thread_info->status & TS_USEDFPU) { \ + if (task_thread_info(tsk)->status & TS_USEDFPU) { \ asm volatile("fnclex ; fwait"); \ - (tsk)->thread_info->status &= ~TS_USEDFPU; \ + task_thread_info(tsk)->status &= ~TS_USEDFPU; \ stts(); \ } \ } while (0) diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 13ecf66b098..feca5d961e2 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -561,10 +561,20 @@ unsigned long get_wchan(struct task_struct *p); (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \ }) +/* + * The below -8 is to reserve 8 bytes on top of the ring0 stack. + * This is necessary to guarantee that the entire "struct pt_regs" + * is accessable even if the CPU haven't stored the SS/ESP registers + * on the stack (interrupt gate does not save these registers + * when switching to the same priv ring). + * Therefore beware: accessing the xss/esp fields of the + * "struct pt_regs" is possible, but they may contain the + * completely wrong values. + */ #define task_pt_regs(task) \ ({ \ struct pt_regs *__regs__; \ - __regs__ = (struct pt_regs *)KSTK_TOP((task)->thread_info); \ + __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \ __regs__ - 1; \ }) diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index 9c0593b7a94..36a92ed6a9d 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h @@ -548,6 +548,15 @@ void enable_hlt(void); extern int es7000_plat; void cpu_idle_wait(void); +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible: + */ +static inline void sched_cacheflush(void) +{ + wbinvd(); +} + extern unsigned long arch_align_stack(unsigned long sp); #endif diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h index 8fbf791651b..2493e77e8c3 100644 --- a/include/asm-i386/thread_info.h +++ b/include/asm-i386/thread_info.h @@ -111,8 +111,6 @@ register unsigned long current_stack_pointer asm("esp") __attribute_used__; #endif #define free_thread_info(info) kfree(info) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #else /* !__ASSEMBLY__ */ diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h index 0ec27c9e8e4..d7e19eb344b 100644 --- a/include/asm-i386/topology.h +++ b/include/asm-i386/topology.h @@ -72,7 +72,6 @@ static inline int node_to_first_cpu(int node) .max_interval = 32, \ .busy_factor = 32, \ .imbalance_pct = 125, \ - .cache_hot_time = (10*1000000), \ .cache_nice_tries = 1, \ .busy_idx = 3, \ .idle_idx = 1, \ diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h index aaf11f4e916..c0b19106665 100644 --- a/include/asm-ia64/compat.h +++ b/include/asm-ia64/compat.h @@ -192,7 +192,7 @@ compat_ptr (compat_uptr_t uptr) static __inline__ void __user * compat_alloc_user_space (long len) { - struct pt_regs *regs = ia64_task_regs(current); + struct pt_regs *regs = task_pt_regs(current); return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); } diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h index 94e07e72739..8c648bf72bb 100644 --- a/include/asm-ia64/processor.h +++ b/include/asm-ia64/processor.h @@ -352,7 +352,7 @@ extern unsigned long get_wchan (struct task_struct *p); /* Return instruction pointer of blocked task TSK. */ #define KSTK_EIP(tsk) \ ({ \ - struct pt_regs *_regs = ia64_task_regs(tsk); \ + struct pt_regs *_regs = task_pt_regs(tsk); \ _regs->cr_iip + ia64_psr(_regs)->ri; \ }) diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h index 2c703d6e0c8..9471cdc3f4c 100644 --- a/include/asm-ia64/ptrace.h +++ b/include/asm-ia64/ptrace.h @@ -248,7 +248,7 @@ struct switch_stack { }) /* given a pointer to a task_struct, return the user's pt_regs */ -# define ia64_task_regs(t) (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1) +# define task_pt_regs(t) (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1) # define ia64_psr(regs) ((struct ia64_psr *) &(regs)->cr_ipsr) # define user_mode(regs) (((struct ia64_psr *) &(regs)->cr_ipsr)->cpl != 0) # define user_stack(task,regs) ((long) regs - (long) task == IA64_STK_OFFSET - sizeof(*regs)) @@ -271,7 +271,7 @@ struct switch_stack { * * On ia64, we can clear the user's pt_regs->r8 to force a successful syscall. */ -# define force_successful_syscall_return() (ia64_task_regs(current)->r8 = 0) +# define force_successful_syscall_return() (task_pt_regs(current)->r8 = 0) struct task_struct; /* forward decl */ struct unw_frame_info; /* forward decl */ diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h index 635235fa1e3..80c5a234e25 100644 --- a/include/asm-ia64/system.h +++ b/include/asm-ia64/system.h @@ -219,14 +219,14 @@ extern void ia64_load_extra (struct task_struct *task); #define IA64_HAS_EXTRA_STATE(t) \ ((t)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID) \ - || IS_IA32_PROCESS(ia64_task_regs(t)) || PERFMON_IS_SYSWIDE()) + || IS_IA32_PROCESS(task_pt_regs(t)) || PERFMON_IS_SYSWIDE()) #define __switch_to(prev,next,last) do { \ if (IA64_HAS_EXTRA_STATE(prev)) \ ia64_save_extra(prev); \ if (IA64_HAS_EXTRA_STATE(next)) \ ia64_load_extra(next); \ - ia64_psr(ia64_task_regs(next))->dfh = !ia64_is_local_fpu_owner(next); \ + ia64_psr(task_pt_regs(next))->dfh = !ia64_is_local_fpu_owner(next); \ (last) = ia64_switch_to((next)); \ } while (0) @@ -238,8 +238,8 @@ extern void ia64_load_extra (struct task_struct *task); * the latest fph state from another CPU. In other words: eager save, lazy restore. */ # define switch_to(prev,next,last) do { \ - if (ia64_psr(ia64_task_regs(prev))->mfh && ia64_is_local_fpu_owner(prev)) { \ - ia64_psr(ia64_task_regs(prev))->mfh = 0; \ + if (ia64_psr(task_pt_regs(prev))->mfh && ia64_is_local_fpu_owner(prev)) { \ + ia64_psr(task_pt_regs(prev))->mfh = 0; \ (prev)->thread.flags |= IA64_THREAD_FPH_VALID; \ __ia64_save_fpu((prev)->thread.fph); \ } \ @@ -279,6 +279,7 @@ extern void ia64_load_extra (struct task_struct *task); #define ia64_platform_is(x) (strcmp(x, platform_name) == 0) void cpu_idle_wait(void); +void sched_cacheflush(void); #define arch_align_stack(x) (x) diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h index 171b2207bde..653bb7f9a75 100644 --- a/include/asm-ia64/thread_info.h +++ b/include/asm-ia64/thread_info.h @@ -57,11 +57,20 @@ struct thread_info { /* how to get the thread information struct from C */ #define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE)) #define alloc_thread_info(tsk) ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE)) +#define task_thread_info(tsk) ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE)) #else #define current_thread_info() ((struct thread_info *) 0) #define alloc_thread_info(tsk) ((struct thread_info *) 0) +#define task_thread_info(tsk) ((struct thread_info *) 0) #endif #define free_thread_info(ti) /* nothing */ +#define task_stack_page(tsk) ((void *)(tsk)) + +#define __HAVE_THREAD_FUNCTIONS +#define setup_thread_stack(p, org) \ + *task_thread_info(p) = *task_thread_info(org); \ + task_thread_info(p)->task = (p); +#define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET) #define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR #define alloc_task_struct() ((task_t *)__get_free_pages(GFP_KERNEL, KERNEL_STACK_SIZE_ORDER)) diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h index f7c330467e7..d8aae4da397 100644 --- a/include/asm-ia64/topology.h +++ b/include/asm-ia64/topology.h @@ -55,7 +55,6 @@ void build_cpu_to_node_map(void); .max_interval = 4, \ .busy_factor = 64, \ .imbalance_pct = 125, \ - .cache_hot_time = (10*1000000), \ .per_cpu_gain = 100, \ .cache_nice_tries = 2, \ .busy_idx = 2, \ @@ -81,7 +80,6 @@ void build_cpu_to_node_map(void); .max_interval = 8*(min(num_online_cpus(), 32)), \ .busy_factor = 64, \ .imbalance_pct = 125, \ - .cache_hot_time = (10*1000000), \ .cache_nice_tries = 2, \ .busy_idx = 3, \ .idle_idx = 2, \ diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h index 55cd7ecfde4..0d058b2d844 100644 --- a/include/asm-m32r/ptrace.h +++ b/include/asm-m32r/ptrace.h @@ -163,6 +163,9 @@ extern void show_regs(struct pt_regs *); extern void withdraw_debug_trap(struct pt_regs *regs); +#define task_pt_regs(task) \ + ((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1) + #endif /* __KERNEL */ #endif /* _ASM_M32R_PTRACE_H */ diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h index dcf619a0a0b..06c12a037cb 100644 --- a/include/asm-m32r/system.h +++ b/include/asm-m32r/system.h @@ -68,6 +68,16 @@ last = __last; \ } while(0) +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} + /* Interrupt Control */ #if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104) #define local_irq_enable() \ diff --git a/include/asm-m32r/thread_info.h b/include/asm-m32r/thread_info.h index 0f589363f61..22aff3222d2 100644 --- a/include/asm-m32r/thread_info.h +++ b/include/asm-m32r/thread_info.h @@ -110,8 +110,6 @@ static inline struct thread_info *current_thread_info(void) #endif #define free_thread_info(info) kfree(info) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #define TI_FLAG_FAULT_CODE_SHIFT 28 diff --git a/include/asm-m68k/amigahw.h b/include/asm-m68k/amigahw.h index 3ae5d8d55ba..a16fe4e5a28 100644 --- a/include/asm-m68k/amigahw.h +++ b/include/asm-m68k/amigahw.h @@ -274,7 +274,7 @@ struct CIA { #define ZTWO_VADDR(x) (((unsigned long)(x))+zTwoBase) #define CUSTOM_PHYSADDR (0xdff000) -#define custom ((*(volatile struct CUSTOM *)(zTwoBase+CUSTOM_PHYSADDR))) +#define amiga_custom ((*(volatile struct CUSTOM *)(zTwoBase+CUSTOM_PHYSADDR))) #define CIAA_PHYSADDR (0xbfe001) #define CIAB_PHYSADDR (0xbfd000) @@ -294,12 +294,12 @@ static inline void amifb_video_off(void) { if (amiga_chipset == CS_ECS || amiga_chipset == CS_AGA) { /* program Denise/Lisa for a higher maximum play rate */ - custom.htotal = 113; /* 31 kHz */ - custom.vtotal = 223; /* 70 Hz */ - custom.beamcon0 = 0x4390; /* HARDDIS, VAR{BEAM,VSY,HSY,CSY}EN */ + amiga_custom.htotal = 113; /* 31 kHz */ + amiga_custom.vtotal = 223; /* 70 Hz */ + amiga_custom.beamcon0 = 0x4390; /* HARDDIS, VAR{BEAM,VSY,HSY,CSY}EN */ /* suspend the monitor */ - custom.hsstrt = custom.hsstop = 116; - custom.vsstrt = custom.vsstop = 226; + amiga_custom.hsstrt = amiga_custom.hsstop = 116; + amiga_custom.vsstrt = amiga_custom.vsstop = 226; amiga_audio_min_period = 57; } } diff --git a/include/asm-m68k/amigaints.h b/include/asm-m68k/amigaints.h index 2aff4cfbf7b..aa968d014bb 100644 --- a/include/asm-m68k/amigaints.h +++ b/include/asm-m68k/amigaints.h @@ -109,8 +109,6 @@ extern void amiga_do_irq(int irq, struct pt_regs *fp); extern void amiga_do_irq_list(int irq, struct pt_regs *fp); -extern unsigned short amiga_intena_vals[]; - /* CIA interrupt control register bits */ #define CIA_ICR_TA 0x01 diff --git a/include/asm-m68k/checksum.h b/include/asm-m68k/checksum.h index 78860c20db0..17280ef719f 100644 --- a/include/asm-m68k/checksum.h +++ b/include/asm-m68k/checksum.h @@ -25,7 +25,7 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) * better 64-bit) boundary */ -extern unsigned int csum_partial_copy_from_user(const unsigned char *src, +extern unsigned int csum_partial_copy_from_user(const unsigned char __user *src, unsigned char *dst, int len, int sum, int *csum_err); diff --git a/include/asm-m68k/dsp56k.h b/include/asm-m68k/dsp56k.h index ab3dd33e23a..2d8c0c9f794 100644 --- a/include/asm-m68k/dsp56k.h +++ b/include/asm-m68k/dsp56k.h @@ -13,7 +13,7 @@ /* Used for uploading DSP binary code */ struct dsp56k_upload { int len; - char *bin; + char __user *bin; }; /* For the DSP host flags */ diff --git a/include/asm-m68k/floppy.h b/include/asm-m68k/floppy.h index c6e708dd9f6..63a05ed95c1 100644 --- a/include/asm-m68k/floppy.h +++ b/include/asm-m68k/floppy.h @@ -46,7 +46,7 @@ asmlinkage irqreturn_t floppy_hardint(int irq, void *dev_id, static int virtual_dma_count=0; static int virtual_dma_residue=0; -static char *virtual_dma_addr=0; +static char *virtual_dma_addr=NULL; static int virtual_dma_mode=0; static int doing_pdma=0; diff --git a/include/asm-m68k/hardirq.h b/include/asm-m68k/hardirq.h index 728318bf7f0..5e1c5826c83 100644 --- a/include/asm-m68k/hardirq.h +++ b/include/asm-m68k/hardirq.h @@ -14,13 +14,4 @@ typedef struct { #define HARDIRQ_BITS 8 -/* - * The hardirq mask has to be large enough to have - * space for potentially all IRQ sources in the system - * nesting on a single CPU: - */ -#if (1 << HARDIRQ_BITS) < NR_IRQS -# error HARDIRQ_BITS is too low! -#endif - #endif diff --git a/include/asm-m68k/io.h b/include/asm-m68k/io.h index 6bb8b0d8f99..dcfaa352d34 100644 --- a/include/asm-m68k/io.h +++ b/include/asm-m68k/io.h @@ -24,6 +24,7 @@ #ifdef __KERNEL__ #include <linux/config.h> +#include <linux/compiler.h> #include <asm/raw_io.h> #include <asm/virtconvert.h> @@ -120,68 +121,68 @@ extern int isa_sex; * be compiled in so the case statement will be optimised away */ -static inline u8 *isa_itb(unsigned long addr) +static inline u8 __iomem *isa_itb(unsigned long addr) { switch(ISA_TYPE) { #ifdef CONFIG_Q40 - case Q40_ISA: return (u8 *)Q40_ISA_IO_B(addr); + case Q40_ISA: return (u8 __iomem *)Q40_ISA_IO_B(addr); #endif #ifdef CONFIG_GG2 - case GG2_ISA: return (u8 *)GG2_ISA_IO_B(addr); + case GG2_ISA: return (u8 __iomem *)GG2_ISA_IO_B(addr); #endif #ifdef CONFIG_AMIGA_PCMCIA - case AG_ISA: return (u8 *)AG_ISA_IO_B(addr); + case AG_ISA: return (u8 __iomem *)AG_ISA_IO_B(addr); #endif - default: return 0; /* avoid warnings, just in case */ + default: return NULL; /* avoid warnings, just in case */ } } -static inline u16 *isa_itw(unsigned long addr) +static inline u16 __iomem *isa_itw(unsigned long addr) { switch(ISA_TYPE) { #ifdef CONFIG_Q40 - case Q40_ISA: return (u16 *)Q40_ISA_IO_W(addr); + case Q40_ISA: return (u16 __iomem *)Q40_ISA_IO_W(addr); #endif #ifdef CONFIG_GG2 - case GG2_ISA: return (u16 *)GG2_ISA_IO_W(addr); + case GG2_ISA: return (u16 __iomem *)GG2_ISA_IO_W(addr); #endif #ifdef CONFIG_AMIGA_PCMCIA - case AG_ISA: return (u16 *)AG_ISA_IO_W(addr); + case AG_ISA: return (u16 __iomem *)AG_ISA_IO_W(addr); #endif - default: return 0; /* avoid warnings, just in case */ + default: return NULL; /* avoid warnings, just in case */ } } -static inline u8 *isa_mtb(unsigned long addr) +static inline u8 __iomem *isa_mtb(unsigned long addr) { switch(ISA_TYPE) { #ifdef CONFIG_Q40 - case Q40_ISA: return (u8 *)Q40_ISA_MEM_B(addr); + case Q40_ISA: return (u8 __iomem *)Q40_ISA_MEM_B(addr); #endif #ifdef CONFIG_GG2 - case GG2_ISA: return (u8 *)GG2_ISA_MEM_B(addr); + case GG2_ISA: return (u8 __iomem *)GG2_ISA_MEM_B(addr); #endif #ifdef CONFIG_AMIGA_PCMCIA - case AG_ISA: return (u8 *)addr; + case AG_ISA: return (u8 __iomem *)addr; #endif - default: return 0; /* avoid warnings, just in case */ + default: return NULL; /* avoid warnings, just in case */ } } -static inline u16 *isa_mtw(unsigned long addr) +static inline u16 __iomem *isa_mtw(unsigned long addr) { switch(ISA_TYPE) { #ifdef CONFIG_Q40 - case Q40_ISA: return (u16 *)Q40_ISA_MEM_W(addr); + case Q40_ISA: return (u16 __iomem *)Q40_ISA_MEM_W(addr); #endif #ifdef CONFIG_GG2 - case GG2_ISA: return (u16 *)GG2_ISA_MEM_W(addr); + case GG2_ISA: return (u16 __iomem *)GG2_ISA_MEM_W(addr); #endif #ifdef CONFIG_AMIGA_PCMCIA - case AG_ISA: return (u16 *)addr; + case AG_ISA: return (u16 __iomem *)addr; #endif - default: return 0; /* avoid warnings, just in case */ + default: return NULL; /* avoid warnings, just in case */ } } @@ -326,20 +327,20 @@ static inline void isa_delay(void) #define mmiowb() -static inline void *ioremap(unsigned long physaddr, unsigned long size) +static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size) { return __ioremap(physaddr, size, IOMAP_NOCACHE_SER); } -static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size) +static inline void __iomem *ioremap_nocache(unsigned long physaddr, unsigned long size) { return __ioremap(physaddr, size, IOMAP_NOCACHE_SER); } -static inline void *ioremap_writethrough(unsigned long physaddr, +static inline void __iomem *ioremap_writethrough(unsigned long physaddr, unsigned long size) { return __ioremap(physaddr, size, IOMAP_WRITETHROUGH); } -static inline void *ioremap_fullcache(unsigned long physaddr, +static inline void __iomem *ioremap_fullcache(unsigned long physaddr, unsigned long size) { return __ioremap(physaddr, size, IOMAP_FULL_CACHING); diff --git a/include/asm-m68k/irq.h b/include/asm-m68k/irq.h index 127ad190cf2..325c86f8512 100644 --- a/include/asm-m68k/irq.h +++ b/include/asm-m68k/irq.h @@ -23,6 +23,15 @@ #endif /* + * The hardirq mask has to be large enough to have + * space for potentially all IRQ sources in the system + * nesting on a single CPU: + */ +#if (1 << HARDIRQ_BITS) < NR_IRQS +# error HARDIRQ_BITS is too low! +#endif + +/* * Interrupt source definitions * General interrupt sources are the level 1-7. * Adding an interrupt service routine for one of these sources diff --git a/include/asm-m68k/machdep.h b/include/asm-m68k/machdep.h index a0dd5c47002..7d3fee34236 100644 --- a/include/asm-m68k/machdep.h +++ b/include/asm-m68k/machdep.h @@ -34,7 +34,6 @@ extern void (*mach_power_off)( void ); extern unsigned long (*mach_hd_init) (unsigned long, unsigned long); extern void (*mach_hd_setup)(char *, int *); extern long mach_max_dma_address; -extern void (*mach_floppy_setup)(char *, int *); extern void (*mach_heartbeat) (int); extern void (*mach_l2_flush) (int); extern void (*mach_beep) (unsigned int, unsigned int); diff --git a/include/asm-m68k/raw_io.h b/include/asm-m68k/raw_io.h index 041f0a87b25..5439bcaa57c 100644 --- a/include/asm-m68k/raw_io.h +++ b/include/asm-m68k/raw_io.h @@ -19,9 +19,9 @@ #define IOMAP_NOCACHE_NONSER 2 #define IOMAP_WRITETHROUGH 3 -extern void iounmap(void *addr); +extern void iounmap(void __iomem *addr); -extern void *__ioremap(unsigned long physaddr, unsigned long size, +extern void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag); extern void __iounmap(void *addr, unsigned long size); @@ -30,21 +30,21 @@ extern void __iounmap(void *addr, unsigned long size); * two accesses to memory, which may be undesirable for some devices. */ #define in_8(addr) \ - ({ u8 __v = (*(volatile u8 *) (addr)); __v; }) + ({ u8 __v = (*(__force volatile u8 *) (addr)); __v; }) #define in_be16(addr) \ - ({ u16 __v = (*(volatile u16 *) (addr)); __v; }) + ({ u16 __v = (*(__force volatile u16 *) (addr)); __v; }) #define in_be32(addr) \ - ({ u32 __v = (*(volatile u32 *) (addr)); __v; }) + ({ u32 __v = (*(__force volatile u32 *) (addr)); __v; }) #define in_le16(addr) \ - ({ u16 __v = le16_to_cpu(*(volatile u16 *) (addr)); __v; }) + ({ u16 __v = le16_to_cpu(*(__force volatile u16 *) (addr)); __v; }) #define in_le32(addr) \ - ({ u32 __v = le32_to_cpu(*(volatile u32 *) (addr)); __v; }) + ({ u32 __v = le32_to_cpu(*(__force volatile u32 *) (addr)); __v; }) -#define out_8(addr,b) (void)((*(volatile u8 *) (addr)) = (b)) -#define out_be16(addr,w) (void)((*(volatile u16 *) (addr)) = (w)) -#define out_be32(addr,l) (void)((*(volatile u32 *) (addr)) = (l)) -#define out_le16(addr,w) (void)((*(volatile u16 *) (addr)) = cpu_to_le16(w)) -#define out_le32(addr,l) (void)((*(volatile u32 *) (addr)) = cpu_to_le32(l)) +#define out_8(addr,b) (void)((*(__force volatile u8 *) (addr)) = (b)) +#define out_be16(addr,w) (void)((*(__force volatile u16 *) (addr)) = (w)) +#define out_be32(addr,l) (void)((*(__force volatile u32 *) (addr)) = (l)) +#define out_le16(addr,w) (void)((*(__force volatile u16 *) (addr)) = cpu_to_le16(w)) +#define out_le32(addr,l) (void)((*(__force volatile u32 *) (addr)) = cpu_to_le32(l)) #define raw_inb in_8 #define raw_inw in_be16 @@ -54,7 +54,7 @@ extern void __iounmap(void *addr, unsigned long size); #define raw_outw(val,port) out_be16((port),(val)) #define raw_outl(val,port) out_be32((port),(val)) -static inline void raw_insb(volatile u8 *port, u8 *buf, unsigned int len) +static inline void raw_insb(volatile u8 __iomem *port, u8 *buf, unsigned int len) { unsigned int i; @@ -62,7 +62,7 @@ static inline void raw_insb(volatile u8 *port, u8 *buf, unsigned int len) *buf++ = in_8(port); } -static inline void raw_outsb(volatile u8 *port, const u8 *buf, +static inline void raw_outsb(volatile u8 __iomem *port, const u8 *buf, unsigned int len) { unsigned int i; @@ -71,7 +71,7 @@ static inline void raw_outsb(volatile u8 *port, const u8 *buf, out_8(port, *buf++); } -static inline void raw_insw(volatile u16 *port, u16 *buf, unsigned int nr) +static inline void raw_insw(volatile u16 __iomem *port, u16 *buf, unsigned int nr) { unsigned int tmp; @@ -110,7 +110,7 @@ static inline void raw_insw(volatile u16 *port, u16 *buf, unsigned int nr) } } -static inline void raw_outsw(volatile u16 *port, const u16 *buf, +static inline void raw_outsw(volatile u16 __iomem *port, const u16 *buf, unsigned int nr) { unsigned int tmp; @@ -150,7 +150,7 @@ static inline void raw_outsw(volatile u16 *port, const u16 *buf, } } -static inline void raw_insl(volatile u32 *port, u32 *buf, unsigned int nr) +static inline void raw_insl(volatile u32 __iomem *port, u32 *buf, unsigned int nr) { unsigned int tmp; @@ -189,7 +189,7 @@ static inline void raw_insl(volatile u32 *port, u32 *buf, unsigned int nr) } } -static inline void raw_outsl(volatile u32 *port, const u32 *buf, +static inline void raw_outsl(volatile u32 __iomem *port, const u32 *buf, unsigned int nr) { unsigned int tmp; @@ -230,7 +230,7 @@ static inline void raw_outsl(volatile u32 *port, const u32 *buf, } -static inline void raw_insw_swapw(volatile u16 *port, u16 *buf, +static inline void raw_insw_swapw(volatile u16 __iomem *port, u16 *buf, unsigned int nr) { if ((nr) % 8) @@ -283,7 +283,7 @@ static inline void raw_insw_swapw(volatile u16 *port, u16 *buf, : "d0", "a0", "a1", "d6"); } -static inline void raw_outsw_swapw(volatile u16 *port, const u16 *buf, +static inline void raw_outsw_swapw(volatile u16 __iomem *port, const u16 *buf, unsigned int nr) { if ((nr) % 8) diff --git a/include/asm-m68k/signal.h b/include/asm-m68k/signal.h index a0cdf908237..b7b7ea20caa 100644 --- a/include/asm-m68k/signal.h +++ b/include/asm-m68k/signal.h @@ -144,7 +144,7 @@ struct sigaction { #endif /* __KERNEL__ */ typedef struct sigaltstack { - void *ss_sp; + void __user *ss_sp; int ss_flags; size_t ss_size; } stack_t; diff --git a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h index e974bb07204..5156a28a18d 100644 --- a/include/asm-m68k/sun3_pgtable.h +++ b/include/asm-m68k/sun3_pgtable.h @@ -211,7 +211,7 @@ static inline unsigned long pte_to_pgoff(pte_t pte) return pte.pte & SUN3_PAGE_PGNUM_MASK; } -static inline pte_t pgoff_to_pte(inline unsigned off) +static inline pte_t pgoff_to_pte(unsigned off) { pte_t pte = { off + SUN3_PAGE_ACCESSED }; return pte; diff --git a/include/asm-m68k/sun3ints.h b/include/asm-m68k/sun3ints.h index fd838eb1421..bd038fccb64 100644 --- a/include/asm-m68k/sun3ints.h +++ b/include/asm-m68k/sun3ints.h @@ -31,7 +31,6 @@ int sun3_request_irq(unsigned int irq, ); extern void sun3_init_IRQ (void); extern irqreturn_t (*sun3_default_handler[]) (int, void *, struct pt_regs *); -extern irqreturn_t (*sun3_inthandler[]) (int, void *, struct pt_regs *); extern void sun3_free_irq (unsigned int irq, void *dev_id); extern void sun3_enable_interrupts (void); extern void sun3_disable_interrupts (void); diff --git a/include/asm-m68k/sun3xflop.h b/include/asm-m68k/sun3xflop.h index fda1eccf10a..98a9f79dab2 100644 --- a/include/asm-m68k/sun3xflop.h +++ b/include/asm-m68k/sun3xflop.h @@ -208,7 +208,7 @@ static int sun3xflop_request_irq(void) if(!once) { once = 1; - error = request_irq(FLOPPY_IRQ, sun3xflop_hardint, SA_INTERRUPT, "floppy", 0); + error = request_irq(FLOPPY_IRQ, sun3xflop_hardint, SA_INTERRUPT, "floppy", NULL); return ((error == 0) ? 0 : -1); } else return 0; } @@ -238,7 +238,7 @@ static int sun3xflop_init(void) *sun3x_fdc.fcr_r = 0; /* Success... */ - floppy_set_flags(0, 1, FD_BROKEN_DCL); // I don't know how to detect this. + floppy_set_flags(NULL, 1, FD_BROKEN_DCL); // I don't know how to detect this. allowed_drive_mask = 0x01; return (int) SUN3X_FDC; } diff --git a/include/asm-m68k/thread_info.h b/include/asm-m68k/thread_info.h index 9532ca3c45c..c4d622a57df 100644 --- a/include/asm-m68k/thread_info.h +++ b/include/asm-m68k/thread_info.h @@ -37,6 +37,7 @@ struct thread_info { #define init_stack (init_thread_union.stack) #define task_thread_info(tsk) (&(tsk)->thread.info) +#define task_stack_page(tsk) ((void *)(tsk)->thread_info) #define current_thread_info() task_thread_info(current) #define __HAVE_THREAD_FUNCTIONS diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h index f5cedf19cf6..2ffd87b0a76 100644 --- a/include/asm-m68k/uaccess.h +++ b/include/asm-m68k/uaccess.h @@ -42,6 +42,7 @@ struct exception_table_entry ({ \ int __pu_err; \ typeof(*(ptr)) __pu_val = (x); \ + __chk_user_ptr(ptr); \ switch (sizeof (*(ptr))) { \ case 1: \ __put_user_asm(__pu_err, __pu_val, ptr, b); \ @@ -91,6 +92,7 @@ __asm__ __volatile__ \ ({ \ int __gu_err; \ typeof(*(ptr)) __gu_val; \ + __chk_user_ptr(ptr); \ switch (sizeof(*(ptr))) { \ case 1: \ __get_user_asm(__gu_err, __gu_val, ptr, b, "=d"); \ @@ -105,7 +107,7 @@ __asm__ __volatile__ \ __gu_err = __constant_copy_from_user(&__gu_val, ptr, 8); \ break; \ default: \ - __gu_val = 0; \ + __gu_val = (typeof(*(ptr)))0; \ __gu_err = __get_user_bad(); \ break; \ } \ @@ -134,7 +136,7 @@ __asm__ __volatile__ \ : "m"(*(ptr)), "i" (-EFAULT), "0"(0)) static inline unsigned long -__generic_copy_from_user(void *to, const void *from, unsigned long n) +__generic_copy_from_user(void *to, const void __user *from, unsigned long n) { unsigned long tmp; __asm__ __volatile__ @@ -189,7 +191,7 @@ __generic_copy_from_user(void *to, const void *from, unsigned long n) } static inline unsigned long -__generic_copy_to_user(void *to, const void *from, unsigned long n) +__generic_copy_to_user(void __user *to, const void *from, unsigned long n) { unsigned long tmp; __asm__ __volatile__ @@ -264,7 +266,7 @@ __generic_copy_to_user(void *to, const void *from, unsigned long n) : "d0", "memory") static inline unsigned long -__constant_copy_from_user(void *to, const void *from, unsigned long n) +__constant_copy_from_user(void *to, const void __user *from, unsigned long n) { switch (n) { case 0: @@ -520,7 +522,7 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n) #define __copy_from_user_inatomic __copy_from_user static inline unsigned long -__constant_copy_to_user(void *to, const void *from, unsigned long n) +__constant_copy_to_user(void __user *to, const void *from, unsigned long n) { switch (n) { case 0: @@ -766,7 +768,7 @@ __constant_copy_to_user(void *to, const void *from, unsigned long n) */ static inline long -strncpy_from_user(char *dst, const char *src, long count) +strncpy_from_user(char *dst, const char __user *src, long count) { long res; if (count == 0) return count; @@ -799,11 +801,11 @@ strncpy_from_user(char *dst, const char *src, long count) * * Return 0 on exception, a value greater than N if too long */ -static inline long strnlen_user(const char *src, long n) +static inline long strnlen_user(const char __user *src, long n) { long res; - res = -(long)src; + res = -(unsigned long)src; __asm__ __volatile__ ("1:\n" " tstl %2\n" @@ -842,7 +844,7 @@ static inline long strnlen_user(const char *src, long n) */ static inline unsigned long -clear_user(void *to, unsigned long n) +clear_user(void __user *to, unsigned long n) { __asm__ __volatile__ (" tstl %1\n" diff --git a/include/asm-m68k/zorro.h b/include/asm-m68k/zorro.h index cf816588bed..5ce97c22b58 100644 --- a/include/asm-m68k/zorro.h +++ b/include/asm-m68k/zorro.h @@ -15,24 +15,24 @@ #define z_memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) #define z_memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) -static inline void *z_remap_nocache_ser(unsigned long physaddr, +static inline void __iomem *z_remap_nocache_ser(unsigned long physaddr, unsigned long size) { return __ioremap(physaddr, size, IOMAP_NOCACHE_SER); } -static inline void *z_remap_nocache_nonser(unsigned long physaddr, +static inline void __iomem *z_remap_nocache_nonser(unsigned long physaddr, unsigned long size) { return __ioremap(physaddr, size, IOMAP_NOCACHE_NONSER); } -static inline void *z_remap_writethrough(unsigned long physaddr, +static inline void __iomem *z_remap_writethrough(unsigned long physaddr, unsigned long size) { return __ioremap(physaddr, size, IOMAP_WRITETHROUGH); } -static inline void *z_remap_fullcache(unsigned long physaddr, +static inline void __iomem *z_remap_fullcache(unsigned long physaddr, unsigned long size) { return __ioremap(physaddr, size, IOMAP_FULL_CACHING); diff --git a/include/asm-m68knommu/machdep.h b/include/asm-m68knommu/machdep.h index 5a9f9c297f7..27c90afd333 100644 --- a/include/asm-m68knommu/machdep.h +++ b/include/asm-m68knommu/machdep.h @@ -38,7 +38,6 @@ extern void (*mach_power_off)( void ); extern unsigned long (*mach_hd_init) (unsigned long, unsigned long); extern void (*mach_hd_setup)(char *, int *); extern long mach_max_dma_address; -extern void (*mach_floppy_setup)(char *, int *); extern void (*mach_floppy_eject)(void); extern void (*mach_heartbeat) (int); extern void (*mach_l2_flush) (int); diff --git a/include/asm-m68knommu/thread_info.h b/include/asm-m68knommu/thread_info.h index 7b9a3fa3af5..b8f009edf2b 100644 --- a/include/asm-m68knommu/thread_info.h +++ b/include/asm-m68knommu/thread_info.h @@ -75,8 +75,6 @@ static inline struct thread_info *current_thread_info(void) #define alloc_thread_info(tsk) ((struct thread_info *) \ __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER)) #define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_SIZE_ORDER) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #endif /* __ASSEMBLY__ */ #define PREEMPT_ACTIVE 0x4000000 diff --git a/include/asm-mips/mach-ip27/topology.h b/include/asm-mips/mach-ip27/topology.h index 82141c711c3..59d26b52ba3 100644 --- a/include/asm-mips/mach-ip27/topology.h +++ b/include/asm-mips/mach-ip27/topology.h @@ -27,7 +27,6 @@ extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES]; .max_interval = 32, \ .busy_factor = 32, \ .imbalance_pct = 125, \ - .cache_hot_time = (10*1000), \ .cache_nice_tries = 1, \ .per_cpu_gain = 100, \ .flags = SD_LOAD_BALANCE \ diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h index de53055a62a..39d2bd50fec 100644 --- a/include/asm-mips/processor.h +++ b/include/asm-mips/processor.h @@ -200,11 +200,11 @@ extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long unsigned long get_wchan(struct task_struct *p); -#define __PT_REG(reg) ((long)&((struct pt_regs *)0)->reg - sizeof(struct pt_regs)) -#define __KSTK_TOS(tsk) ((unsigned long)(tsk->thread_info) + THREAD_SIZE - 32) -#define KSTK_EIP(tsk) (*(unsigned long *)(__KSTK_TOS(tsk) + __PT_REG(cp0_epc))) -#define KSTK_ESP(tsk) (*(unsigned long *)(__KSTK_TOS(tsk) + __PT_REG(regs[29]))) -#define KSTK_STATUS(tsk) (*(unsigned long *)(__KSTK_TOS(tsk) + __PT_REG(cp0_status))) +#define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + THREAD_SIZE - 32) +#define task_pt_regs(tsk) ((struct pt_regs *)__KSTK_TOS(tsk) - 1) +#define KSTK_EIP(tsk) (task_pt_regs(tsk)->cp0_epc) +#define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[29]) +#define KSTK_STATUS(tsk) (task_pt_regs(tsk)->cp0_status) #define cpu_relax() barrier() diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index 330c4e497af..e8e5d414337 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h @@ -159,11 +159,21 @@ struct task_struct; do { \ if (cpu_has_dsp) \ __save_dsp(prev); \ - (last) = resume(prev, next, next->thread_info); \ + (last) = resume(prev, next, task_thread_info(next)); \ if (cpu_has_dsp) \ __restore_dsp(current); \ } while(0) +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} + static inline unsigned long __xchg_u32(volatile int * m, unsigned int val) { __u32 retval; diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h index e6c24472e03..1612b3fe108 100644 --- a/include/asm-mips/thread_info.h +++ b/include/asm-mips/thread_info.h @@ -97,8 +97,6 @@ register struct thread_info *__current_thread_info __asm__("$28"); #endif #define free_thread_info(info) kfree(info) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-parisc/system.h b/include/asm-parisc/system.h index f3928d3a80c..a5a973c0c07 100644 --- a/include/asm-parisc/system.h +++ b/include/asm-parisc/system.h @@ -49,6 +49,15 @@ extern struct task_struct *_switch_to(struct task_struct *, struct task_struct * (last) = _switch_to(prev, next); \ } while(0) +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} /* interrupt control */ diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h index 57bbb76cb6c..ac32f140b83 100644 --- a/include/asm-parisc/thread_info.h +++ b/include/asm-parisc/thread_info.h @@ -43,9 +43,6 @@ struct thread_info { #define alloc_thread_info(tsk) ((struct thread_info *) \ __get_free_pages(GFP_KERNEL, THREAD_ORDER)) #define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) - /* how to get the thread information struct from C */ #define current_thread_info() ((struct thread_info *)mfctl(30)) diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index 8a8393e5077..d5677cbec20 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h @@ -64,25 +64,6 @@ extern void iommu_free_table(struct device_node *dn); #endif /* CONFIG_PPC_MULTIPLATFORM */ -#ifdef CONFIG_PPC_PSERIES - -/* Creates table for an individual device node */ -extern void iommu_devnode_init_pSeries(struct device_node *dn); - -#endif /* CONFIG_PPC_PSERIES */ - -#ifdef CONFIG_PPC_ISERIES - -/* Creates table for an individual device node */ -extern void iommu_devnode_init_iSeries(struct device_node *dn); -/* Get table parameters from HV */ -extern void iommu_table_getparms_iSeries(unsigned long busno, - unsigned char slotno, - unsigned char virtbus, - struct iommu_table* tbl); - -#endif /* CONFIG_PPC_ISERIES */ - /* Initializes an iommu_table based in values set in the passed-in * structure */ diff --git a/include/asm-powerpc/iseries/hv_call.h b/include/asm-powerpc/iseries/hv_call.h index e9f831c9a5e..162d653ad51 100644 --- a/include/asm-powerpc/iseries/hv_call.h +++ b/include/asm-powerpc/iseries/hv_call.h @@ -1,5 +1,4 @@ /* - * HvCall.h * Copyright (C) 2001 Mike Corrigan IBM Corporation * * This program is free software; you can redistribute it and/or modify @@ -15,8 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* + * * This file contains the "hypervisor call" interface which is used to * drive the hypervisor from the OS. */ diff --git a/include/asm-powerpc/iseries/hv_call_event.h b/include/asm-powerpc/iseries/hv_call_event.h index 46763a30590..4cec4762076 100644 --- a/include/asm-powerpc/iseries/hv_call_event.h +++ b/include/asm-powerpc/iseries/hv_call_event.h @@ -1,5 +1,4 @@ /* - * HvCallEvent.h * Copyright (C) 2001 Mike Corrigan IBM Corporation * * This program is free software; you can redistribute it and/or modify @@ -15,8 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* + * * This file contains the "hypervisor call" interface which is used to * drive the hypervisor from the OS. */ @@ -33,32 +31,9 @@ typedef u8 HvLpEvent_Type; typedef u8 HvLpEvent_AckInd; typedef u8 HvLpEvent_AckType; -struct HvCallEvent_PackedParms { - u8 xAckType:1; - u8 xAckInd:1; - u8 xRsvd:1; - u8 xTargetLp:5; - u8 xType; - u16 xSubtype; - HvLpInstanceId xSourceInstId; - HvLpInstanceId xTargetInstId; -}; - typedef u8 HvLpDma_Direction; typedef u8 HvLpDma_AddressType; -struct HvCallEvent_PackedDmaParms { - u8 xDirection:1; - u8 xLocalAddrType:1; - u8 xRemoteAddrType:1; - u8 xRsvd1:5; - HvLpIndex xRemoteLp; - u8 xType; - u8 xRsvd2; - HvLpInstanceId xLocalInstId; - HvLpInstanceId xRemoteInstId; -}; - typedef u64 HvLpEvent_Rc; typedef u64 HvLpDma_Rc; @@ -92,11 +67,8 @@ static inline void HvCallEvent_setInterLpQueueIndex(u8 queueIndex) static inline void HvCallEvent_setLpEventStack(u8 queueIndex, char *eventStackAddr, u32 eventStackSize) { - u64 abs_addr; - - abs_addr = virt_to_abs(eventStackAddr); - HvCall3(HvCallEventSetLpEventStack, queueIndex, abs_addr, - eventStackSize); + HvCall3(HvCallEventSetLpEventStack, queueIndex, + virt_to_abs(eventStackAddr), eventStackSize); } static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex, @@ -108,14 +80,7 @@ static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex, static inline HvLpEvent_Rc HvCallEvent_signalLpEvent(struct HvLpEvent *event) { - u64 abs_addr; - -#ifdef DEBUG_SENDEVENT - printk("HvCallEvent_signalLpEvent: *event = %016lx\n ", - (unsigned long)event); -#endif - abs_addr = virt_to_abs(event); - return HvCall1(HvCallEventSignalLpEvent, abs_addr); + return HvCall1(HvCallEventSignalLpEvent, virt_to_abs(event)); } static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp, @@ -127,17 +92,21 @@ static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp, { /* Pack the misc bits into a single Dword to pass to PLIC */ union { - struct HvCallEvent_PackedParms parms; + struct { + u8 ack_and_target; + u8 type; + u16 subtype; + HvLpInstanceId src_inst; + HvLpInstanceId target_inst; + } parms; u64 dword; } packed; - packed.parms.xAckType = ackType; - packed.parms.xAckInd = ackInd; - packed.parms.xRsvd = 0; - packed.parms.xTargetLp = targetLp; - packed.parms.xType = type; - packed.parms.xSubtype = subtype; - packed.parms.xSourceInstId = sourceInstanceId; - packed.parms.xTargetInstId = targetInstanceId; + + packed.parms.ack_and_target = (ackType << 7) | (ackInd << 6) | targetLp; + packed.parms.type = type; + packed.parms.subtype = subtype; + packed.parms.src_inst = sourceInstanceId; + packed.parms.target_inst = targetInstanceId; return HvCall7(HvCallEventSignalLpEventParms, packed.dword, correlationToken, eventData1, eventData2, @@ -146,18 +115,12 @@ static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp, static inline HvLpEvent_Rc HvCallEvent_ackLpEvent(struct HvLpEvent *event) { - u64 abs_addr; - - abs_addr = virt_to_abs(event); - return HvCall1(HvCallEventAckLpEvent, abs_addr); + return HvCall1(HvCallEventAckLpEvent, virt_to_abs(event)); } static inline HvLpEvent_Rc HvCallEvent_cancelLpEvent(struct HvLpEvent *event) { - u64 abs_addr; - - abs_addr = virt_to_abs(event); - return HvCall1(HvCallEventCancelLpEvent, abs_addr); + return HvCall1(HvCallEventCancelLpEvent, virt_to_abs(event)); } static inline HvLpInstanceId HvCallEvent_getSourceLpInstanceId( @@ -195,59 +158,34 @@ static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type, { /* Pack the misc bits into a single Dword to pass to PLIC */ union { - struct HvCallEvent_PackedDmaParms parms; + struct { + u8 flags; + HvLpIndex remote; + u8 type; + u8 reserved; + HvLpInstanceId local_inst; + HvLpInstanceId remote_inst; + } parms; u64 dword; } packed; - packed.parms.xDirection = direction; - packed.parms.xLocalAddrType = localAddressType; - packed.parms.xRemoteAddrType = remoteAddressType; - packed.parms.xRsvd1 = 0; - packed.parms.xRemoteLp = remoteLp; - packed.parms.xType = type; - packed.parms.xRsvd2 = 0; - packed.parms.xLocalInstId = localInstanceId; - packed.parms.xRemoteInstId = remoteInstanceId; + packed.parms.flags = (direction << 7) | + (localAddressType << 6) | (remoteAddressType << 5); + packed.parms.remote = remoteLp; + packed.parms.type = type; + packed.parms.reserved = 0; + packed.parms.local_inst = localInstanceId; + packed.parms.remote_inst = remoteInstanceId; return HvCall4(HvCallEventDmaBufList, packed.dword, localBufList, remoteBufList, transferLength); } -static inline HvLpDma_Rc HvCallEvent_dmaSingle(HvLpEvent_Type type, - HvLpIndex remoteLp, HvLpDma_Direction direction, - HvLpInstanceId localInstanceId, - HvLpInstanceId remoteInstanceId, - HvLpDma_AddressType localAddressType, - HvLpDma_AddressType remoteAddressType, - u64 localAddrOrTce, u64 remoteAddrOrTce, u32 transferLength) -{ - /* Pack the misc bits into a single Dword to pass to PLIC */ - union { - struct HvCallEvent_PackedDmaParms parms; - u64 dword; - } packed; - - packed.parms.xDirection = direction; - packed.parms.xLocalAddrType = localAddressType; - packed.parms.xRemoteAddrType = remoteAddressType; - packed.parms.xRsvd1 = 0; - packed.parms.xRemoteLp = remoteLp; - packed.parms.xType = type; - packed.parms.xRsvd2 = 0; - packed.parms.xLocalInstId = localInstanceId; - packed.parms.xRemoteInstId = remoteInstanceId; - - return (HvLpDma_Rc)HvCall4(HvCallEventDmaSingle, packed.dword, - localAddrOrTce, remoteAddrOrTce, transferLength); -} - static inline HvLpDma_Rc HvCallEvent_dmaToSp(void *local, u32 remote, u32 length, HvLpDma_Direction dir) { - u64 abs_addr; - - abs_addr = virt_to_abs(local); - return HvCall4(HvCallEventDmaToSp, abs_addr, remote, length, dir); + return HvCall4(HvCallEventDmaToSp, virt_to_abs(local), remote, + length, dir); } #endif /* _ASM_POWERPC_ISERIES_HV_CALL_EVENT_H */ diff --git a/include/asm-powerpc/iseries/hv_call_sc.h b/include/asm-powerpc/iseries/hv_call_sc.h index dec7e9d9ab7..f5d21095925 100644 --- a/include/asm-powerpc/iseries/hv_call_sc.h +++ b/include/asm-powerpc/iseries/hv_call_sc.h @@ -1,5 +1,4 @@ /* - * HvCallSc.h * Copyright (C) 2001 Mike Corrigan IBM Corporation * * This program is free software; you can redistribute it and/or modify diff --git a/include/asm-powerpc/iseries/hv_lp_config.h b/include/asm-powerpc/iseries/hv_lp_config.h index bc00f036bca..df8b2073971 100644 --- a/include/asm-powerpc/iseries/hv_lp_config.h +++ b/include/asm-powerpc/iseries/hv_lp_config.h @@ -1,5 +1,4 @@ /* - * HvLpConfig.h * Copyright (C) 2001 Mike Corrigan IBM Corporation * * This program is free software; you can redistribute it and/or modify diff --git a/include/asm-powerpc/iseries/hv_lp_event.h b/include/asm-powerpc/iseries/hv_lp_event.h index 499ab1ad018..4065a4de493 100644 --- a/include/asm-powerpc/iseries/hv_lp_event.h +++ b/include/asm-powerpc/iseries/hv_lp_event.h @@ -1,5 +1,4 @@ /* - * HvLpEvent.h * Copyright (C) 2001 Mike Corrigan IBM Corporation * * This program is free software; you can redistribute it and/or modify @@ -32,17 +31,8 @@ * partitions through PLIC. */ -struct HvEventFlags { - u8 xValid:1; /* Indicates a valid request x00-x00 */ - u8 xRsvd1:4; /* Reserved ... */ - u8 xAckType:1; /* Immediate or deferred ... */ - u8 xAckInd:1; /* Indicates if ACK required ... */ - u8 xFunction:1; /* Interrupt or Acknowledge ... */ -}; - - struct HvLpEvent { - struct HvEventFlags xFlags; /* Event flags x00-x00 */ + u8 flags; /* Event flags x00-x00 */ u8 xType; /* Type of message x01-x01 */ u16 xSubtype; /* Subtype for event x02-x03 */ u8 xSourceLp; /* Source LP x04-x04 */ @@ -126,6 +116,11 @@ extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex); #define HvLpEvent_AckType_ImmediateAck 0 #define HvLpEvent_AckType_DeferredAck 1 +#define HV_LP_EVENT_INT 0x01 +#define HV_LP_EVENT_DO_ACK 0x02 +#define HV_LP_EVENT_DEFERRED_ACK 0x04 +#define HV_LP_EVENT_VALID 0x80 + #define HvLpDma_Direction_LocalToRemote 0 #define HvLpDma_Direction_RemoteToLocal 1 @@ -139,4 +134,29 @@ extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex); #define HvLpDma_Rc_InvalidAddress 4 #define HvLpDma_Rc_InvalidLength 5 +static inline int hvlpevent_is_valid(struct HvLpEvent *h) +{ + return h->flags & HV_LP_EVENT_VALID; +} + +static inline void hvlpevent_invalidate(struct HvLpEvent *h) +{ + h->flags &= ~ HV_LP_EVENT_VALID; +} + +static inline int hvlpevent_is_int(struct HvLpEvent *h) +{ + return h->flags & HV_LP_EVENT_INT; +} + +static inline int hvlpevent_is_ack(struct HvLpEvent *h) +{ + return !hvlpevent_is_int(h); +} + +static inline int hvlpevent_need_ack(struct HvLpEvent *h) +{ + return h->flags & HV_LP_EVENT_DO_ACK; +} + #endif /* _ASM_POWERPC_ISERIES_HV_LP_EVENT_H */ diff --git a/include/asm-powerpc/iseries/hv_types.h b/include/asm-powerpc/iseries/hv_types.h index c38f7e3d01d..c3e6d2a1d1c 100644 --- a/include/asm-powerpc/iseries/hv_types.h +++ b/include/asm-powerpc/iseries/hv_types.h @@ -1,5 +1,4 @@ /* - * HvTypes.h * Copyright (C) 2001 Mike Corrigan IBM Corporation * * This program is free software; you can redistribute it and/or modify diff --git a/include/asm-powerpc/iseries/iseries_io.h b/include/asm-powerpc/iseries/iseries_io.h index 56b2113ff0f..496aa852b61 100644 --- a/include/asm-powerpc/iseries/iseries_io.h +++ b/include/asm-powerpc/iseries/iseries_io.h @@ -6,7 +6,7 @@ #ifdef CONFIG_PPC_ISERIES #include <linux/types.h> /* - * File iSeries_io.h created by Allan Trautman on Thu Dec 28 2000. + * Created by Allan Trautman on Thu Dec 28 2000. * * Remaps the io.h for the iSeries Io * Copyright (C) 2000 Allan H Trautman, IBM Corporation @@ -32,6 +32,7 @@ * End Change Activity */ +#ifdef CONFIG_PCI extern u8 iSeries_Read_Byte(const volatile void __iomem * IoAddress); extern u16 iSeries_Read_Word(const volatile void __iomem * IoAddress); extern u32 iSeries_Read_Long(const volatile void __iomem * IoAddress); @@ -44,6 +45,17 @@ extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t n); extern void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *source, size_t n); +#else +static inline u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) +{ + return 0xff; +} + +static inline void iSeries_Write_Byte(u8 IoData, + volatile void __iomem *IoAddress) +{ +} +#endif /* CONFIG_PCI */ #endif /* CONFIG_PPC_ISERIES */ #endif /* _ASM_POWERPC_ISERIES_ISERIES_IO_H */ diff --git a/include/asm-powerpc/iseries/it_exp_vpd_panel.h b/include/asm-powerpc/iseries/it_exp_vpd_panel.h index 66a17a230c5..304a609ae21 100644 --- a/include/asm-powerpc/iseries/it_exp_vpd_panel.h +++ b/include/asm-powerpc/iseries/it_exp_vpd_panel.h @@ -1,5 +1,4 @@ /* - * ItExtVpdPanel.h * Copyright (C) 2002 Dave Boutcher IBM Corporation * * This program is free software; you can redistribute it and/or modify diff --git a/include/asm-powerpc/iseries/it_lp_naca.h b/include/asm-powerpc/iseries/it_lp_naca.h index c3ef1de45d8..4fdcf052927 100644 --- a/include/asm-powerpc/iseries/it_lp_naca.h +++ b/include/asm-powerpc/iseries/it_lp_naca.h @@ -1,5 +1,4 @@ /* - * ItLpNaca.h * Copyright (C) 2001 Mike Corrigan IBM Corporation * * This program is free software; you can redistribute it and/or modify @@ -37,17 +36,13 @@ struct ItLpNaca { u8 xLpIndex; // LP Index x0B-x0B u16 xMaxLpQueues; // Number of allocated queues x0C-x0D u16 xLpQueueOffset; // Offset to start of LP queues x0E-x0F - u8 xPirEnvironMode:8; // Piranha or hardware x10-x10 - u8 xPirConsoleMode:8; // Piranha console indicator x11-x11 - u8 xPirDasdMode:8; // Piranha dasd indicator x12-x12 + u8 xPirEnvironMode; // Piranha or hardware x10-x10 + u8 xPirConsoleMode; // Piranha console indicator x11-x11 + u8 xPirDasdMode; // Piranha dasd indicator x12-x12 u8 xRsvd1_0[5]; // Reserved for Piranha related x13-x17 - u8 xLparInstalled:1; // Is LPAR installed on system x18-x1F - u8 xSysPartitioned:1; // Is the system partitioned ... - u8 xHwSyncedTBs:1; // Hardware synced TBs ... - u8 xIntProcUtilHmt:1; // Utilize HMT for interrupts ... - u8 xRsvd1_1:4; // Reserved ... - u8 xSpVpdFormat:8; // VPD areas are in CSP format ... - u8 xIntProcRatio:8; // Ratio of int procs to procs ... + u8 flags; // flags, see below x18-x1F + u8 xSpVpdFormat; // VPD areas are in CSP format ... + u8 xIntProcRatio; // Ratio of int procs to procs ... u8 xRsvd1_2[5]; // Reserved ... u16 xRsvd1_3; // Reserved x20-x21 u16 xPlicVrmIndex; // VRM index of PLIC x22-x23 @@ -77,4 +72,9 @@ struct ItLpNaca { extern struct ItLpNaca itLpNaca; +#define ITLPNACA_LPAR 0x80 /* Is LPAR installed on the system */ +#define ITLPNACA_PARTITIONED 0x40 /* Is the system partitioned */ +#define ITLPNACA_HWSYNCEDTBS 0x20 /* Hardware synced TBs */ +#define ITLPNACA_HMTINT 0x10 /* Utilize MHT for interrupts */ + #endif /* _ASM_POWERPC_ISERIES_IT_LP_NACA_H */ diff --git a/include/asm-powerpc/iseries/it_lp_queue.h b/include/asm-powerpc/iseries/it_lp_queue.h index a60d03afbf9..b7c6fc12cce 100644 --- a/include/asm-powerpc/iseries/it_lp_queue.h +++ b/include/asm-powerpc/iseries/it_lp_queue.h @@ -1,5 +1,4 @@ /* - * ItLpQueue.h * Copyright (C) 2001 Mike Corrigan IBM Corporation * * This program is free software; you can redistribute it and/or modify diff --git a/include/asm-powerpc/iseries/it_lp_reg_save.h b/include/asm-powerpc/iseries/it_lp_reg_save.h index 81824e1bb76..5403b756f65 100644 --- a/include/asm-powerpc/iseries/it_lp_reg_save.h +++ b/include/asm-powerpc/iseries/it_lp_reg_save.h @@ -1,5 +1,4 @@ /* - * ItLpRegSave.h * Copyright (C) 2001 Mike Corrigan IBM Corporation * * This program is free software; you can redistribute it and/or modify @@ -83,4 +82,4 @@ struct ItLpRegSave { extern struct ItLpRegSave iseries_reg_save[]; -#endif /* _ITLPREGSAVE_H */ +#endif /* _ASM_POWERPC_ISERIES_IT_LP_REG_SAVE_H */ diff --git a/include/asm-powerpc/iseries/lpar_map.h b/include/asm-powerpc/iseries/lpar_map.h index 84fc321615b..2ec384d66ab 100644 --- a/include/asm-powerpc/iseries/lpar_map.h +++ b/include/asm-powerpc/iseries/lpar_map.h @@ -1,5 +1,4 @@ /* - * LparMap.h * Copyright (C) 2001 Mike Corrigan IBM Corporation * * This program is free software; you can redistribute it and/or modify diff --git a/include/asm-powerpc/iseries/mf.h b/include/asm-powerpc/iseries/mf.h index e7bd57a03fb..857e5202fc7 100644 --- a/include/asm-powerpc/iseries/mf.h +++ b/include/asm-powerpc/iseries/mf.h @@ -1,5 +1,4 @@ /* - * mf.h * Copyright (C) 2001 Troy D. Armstrong IBM Corporation * Copyright (C) 2004 Stephen Rothwell IBM Corporation * diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h index 7e3a469420d..72a97d37aac 100644 --- a/include/asm-powerpc/iseries/vio.h +++ b/include/asm-powerpc/iseries/vio.h @@ -1,5 +1,4 @@ /* -*- linux-c -*- - * drivers/char/vio.h * * iSeries Virtual I/O Message Path header * diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h index b0d816fe2e2..38de92d41a1 100644 --- a/include/asm-powerpc/pci-bridge.h +++ b/include/asm-powerpc/pci-bridge.h @@ -142,8 +142,6 @@ void pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus); extern int pcibios_remove_root_bus(struct pci_controller *phb); -extern void phbs_remap_io(void); - static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus) { struct device_node *busdn = bus->sysdata; diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index 0c58e32a957..9b822afa7d0 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h @@ -133,6 +133,14 @@ extern int fix_alignment(struct pt_regs *); extern void cvt_fd(float *from, double *to, struct thread_struct *thread); extern void cvt_df(double *from, float *to, struct thread_struct *thread); +#ifndef CONFIG_SMP +extern void discard_lazy_cpu_state(void); +#else +static inline void discard_lazy_cpu_state(void) +{ +} +#endif + #ifdef CONFIG_ALTIVEC extern void flush_altivec_to_thread(struct task_struct *); #else @@ -175,6 +183,16 @@ struct thread_struct; extern struct task_struct *_switch(struct thread_struct *prev, struct thread_struct *next); +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} + extern unsigned int rtas_data; extern int mem_init_done; /* set on boot once kmalloc can be called */ extern unsigned long memory_limit; diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h index ac1e80e6033..7e09d7cda93 100644 --- a/include/asm-powerpc/thread_info.h +++ b/include/asm-powerpc/thread_info.h @@ -89,9 +89,6 @@ struct thread_info { #endif /* THREAD_SHIFT < PAGE_SHIFT */ -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) - /* how to get the thread information struct from C */ static inline struct thread_info *current_thread_info(void) { diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h index 9f3d4da261c..1e19cd00af2 100644 --- a/include/asm-powerpc/topology.h +++ b/include/asm-powerpc/topology.h @@ -39,7 +39,6 @@ static inline int node_to_first_cpu(int node) .max_interval = 32, \ .busy_factor = 32, \ .imbalance_pct = 125, \ - .cache_hot_time = (10*1000000), \ .cache_nice_tries = 1, \ .per_cpu_gain = 100, \ .busy_idx = 3, \ diff --git a/include/asm-ppc/system.h b/include/asm-ppc/system.h index bd99cb53a19..fb49c0c49ea 100644 --- a/include/asm-ppc/system.h +++ b/include/asm-ppc/system.h @@ -4,7 +4,6 @@ #ifndef __PPC_SYSTEM_H #define __PPC_SYSTEM_H -#include <linux/config.h> #include <linux/kernel.h> #include <asm/atomic.h> @@ -39,7 +38,7 @@ #ifdef CONFIG_SMP #define smp_mb() mb() #define smp_rmb() rmb() -#define smp_wmb() wmb() +#define smp_wmb() __asm__ __volatile__ ("eieio" : : : "memory") #define smp_read_barrier_depends() read_barrier_depends() #else #define smp_mb() barrier() @@ -74,6 +73,7 @@ extern void chrp_nvram_init(void); extern void read_rtc_time(void); extern void pmac_find_display(void); extern void giveup_fpu(struct task_struct *); +extern void disable_kernel_fp(void); extern void enable_kernel_fp(void); extern void flush_fp_to_thread(struct task_struct *); extern void enable_kernel_altivec(void); @@ -86,6 +86,14 @@ extern int fix_alignment(struct pt_regs *); extern void cvt_fd(float *from, double *to, struct thread_struct *thread); extern void cvt_df(double *from, float *to, struct thread_struct *thread); +#ifndef CONFIG_SMP +extern void discard_lazy_cpu_state(void); +#else +static inline void discard_lazy_cpu_state(void) +{ +} +#endif + #ifdef CONFIG_ALTIVEC extern void flush_altivec_to_thread(struct task_struct *); #else @@ -123,6 +131,16 @@ extern struct task_struct *__switch_to(struct task_struct *, struct task_struct *); #define switch_to(prev, next, last) ((last) = __switch_to((prev), (next))) +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} + struct thread_struct; extern struct task_struct *_switch(struct thread_struct *prev, struct thread_struct *next); diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h index 372d51cccd5..710646e64f7 100644 --- a/include/asm-s390/elf.h +++ b/include/asm-s390/elf.h @@ -163,7 +163,7 @@ static inline int dump_regs(struct pt_regs *ptregs, elf_gregset_t *regs) static inline int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) { - struct pt_regs *ptregs = __KSTK_PTREGS(tsk); + struct pt_regs *ptregs = task_pt_regs(tsk); memcpy(®s->psw, &ptregs->psw, sizeof(regs->psw)+sizeof(regs->gprs)); memcpy(regs->acrs, tsk->thread.acrs, sizeof(regs->acrs)); regs->orig_gpr2 = ptregs->orig_gpr2; diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h index 4ec652ebb3b..c5cbc4bd841 100644 --- a/include/asm-s390/processor.h +++ b/include/asm-s390/processor.h @@ -191,10 +191,10 @@ extern void show_registers(struct pt_regs *regs); extern void show_trace(struct task_struct *task, unsigned long *sp); unsigned long get_wchan(struct task_struct *p); -#define __KSTK_PTREGS(tsk) ((struct pt_regs *) \ - ((unsigned long) tsk->thread_info + THREAD_SIZE - sizeof(struct pt_regs))) -#define KSTK_EIP(tsk) (__KSTK_PTREGS(tsk)->psw.addr) -#define KSTK_ESP(tsk) (__KSTK_PTREGS(tsk)->gprs[15]) +#define task_pt_regs(tsk) ((struct pt_regs *) \ + (task_stack_page(tsk) + THREAD_SIZE) - 1) +#define KSTK_EIP(tsk) (task_pt_regs(tsk)->psw.addr) +#define KSTK_ESP(tsk) (task_pt_regs(tsk)->gprs[15]) /* * Give up the time slice of the virtual PU. diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index 864cae7e1fd..c7c3a9ad593 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h @@ -104,6 +104,16 @@ static inline void restore_access_regs(unsigned int *acrs) prev = __switch_to(prev,next); \ } while (0) +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} + #ifdef CONFIG_VIRT_CPU_ACCOUNTING extern void account_user_vtime(struct task_struct *); extern void account_system_vtime(struct task_struct *); diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h index 6c18a3f2431..f3797a52c4e 100644 --- a/include/asm-s390/thread_info.h +++ b/include/asm-s390/thread_info.h @@ -81,8 +81,6 @@ static inline struct thread_info *current_thread_info(void) #define alloc_thread_info(tsk) ((struct thread_info *) \ __get_free_pages(GFP_KERNEL,THREAD_ORDER)) #define free_thread_info(ti) free_pages((unsigned long) (ti),THREAD_ORDER) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #endif diff --git a/include/asm-sh/ptrace.h b/include/asm-sh/ptrace.h index 0f75e16a741..792fc35bd62 100644 --- a/include/asm-sh/ptrace.h +++ b/include/asm-sh/ptrace.h @@ -91,6 +91,16 @@ struct pt_dspregs { #define instruction_pointer(regs) ((regs)->pc) extern void show_regs(struct pt_regs *); +#ifdef CONFIG_SH_DSP +#define task_pt_regs(task) \ + ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \ + - sizeof(struct pt_dspregs) - sizeof(unsigned long)) - 1) +#else +#define task_pt_regs(task) \ + ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \ + - sizeof(unsigned long)) - 1) +#endif + static inline unsigned long profile_pc(struct pt_regs *regs) { unsigned long pc = instruction_pointer(regs); diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h index 28a3c2d8bcd..bb0330499bd 100644 --- a/include/asm-sh/system.h +++ b/include/asm-sh/system.h @@ -57,6 +57,16 @@ last = __last; \ } while (0) +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} + #define nop() __asm__ __volatile__ ("nop") diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h index 46080cefaff..85f0c11b431 100644 --- a/include/asm-sh/thread_info.h +++ b/include/asm-sh/thread_info.h @@ -60,8 +60,6 @@ static inline struct thread_info *current_thread_info(void) #define THREAD_SIZE (2*PAGE_SIZE) #define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #else /* !__ASSEMBLY__ */ diff --git a/include/asm-sh64/thread_info.h b/include/asm-sh64/thread_info.h index 10f024c6a2e..1f825cb163c 100644 --- a/include/asm-sh64/thread_info.h +++ b/include/asm-sh64/thread_info.h @@ -66,8 +66,6 @@ static inline struct thread_info *current_thread_info(void) #define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #endif /* __ASSEMBLY__ */ diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h index 1f6b71f9e1b..58dd162927b 100644 --- a/include/asm-sparc/system.h +++ b/include/asm-sparc/system.h @@ -155,7 +155,7 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr, "here:\n" \ : "=&r" (last) \ : "r" (&(current_set[hard_smp_processor_id()])), \ - "r" ((next)->thread_info), \ + "r" (task_thread_info(next)), \ "i" (TI_KPSR), \ "i" (TI_KSP), \ "i" (TI_TASK) \ @@ -166,6 +166,16 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr, } while(0) /* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} + +/* * Changing the IRQ level on the Sparc. */ extern void local_irq_restore(unsigned long); diff --git a/include/asm-sparc/thread_info.h b/include/asm-sparc/thread_info.h index ff6ccb3d24c..65f060b040a 100644 --- a/include/asm-sparc/thread_info.h +++ b/include/asm-sparc/thread_info.h @@ -92,9 +92,6 @@ BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info, void) BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *) #define free_thread_info(ti) BTFIXUP_CALL(free_thread_info)(ti) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) - #endif /* __ASSEMBLY__ */ /* diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h index 91458118277..69539a8ab83 100644 --- a/include/asm-sparc64/elf.h +++ b/include/asm-sparc64/elf.h @@ -119,7 +119,7 @@ typedef struct { #endif #define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs) \ - ({ ELF_CORE_COPY_REGS((*(__elf_regs)), (__tsk)->thread_info->kregs); 1; }) + ({ ELF_CORE_COPY_REGS((*(__elf_regs)), task_pt_regs(__tsk)); 1; }) /* * This is used to ensure we don't load something for the wrong architecture. diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h index 08ba72d7722..57ee7b30618 100644 --- a/include/asm-sparc64/mmu_context.h +++ b/include/asm-sparc64/mmu_context.h @@ -60,7 +60,7 @@ do { \ register unsigned long pgd_cache asm("o4"); \ paddr = __pa((__mm)->pgd); \ pgd_cache = 0UL; \ - if ((__tsk)->thread_info->flags & _TIF_32BIT) \ + if (task_thread_info(__tsk)->flags & _TIF_32BIT) \ pgd_cache = get_pgd_cache((__mm)->pgd); \ __asm__ __volatile__("wrpr %%g0, 0x494, %%pstate\n\t" \ "mov %3, %%g4\n\t" \ diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h index 3169f3e2237..cd8d9b4c865 100644 --- a/include/asm-sparc64/processor.h +++ b/include/asm-sparc64/processor.h @@ -186,8 +186,9 @@ extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); extern unsigned long get_wchan(struct task_struct *task); -#define KSTK_EIP(tsk) ((tsk)->thread_info->kregs->tpc) -#define KSTK_ESP(tsk) ((tsk)->thread_info->kregs->u_regs[UREG_FP]) +#define task_pt_regs(tsk) (task_thread_info(tsk)->kregs) +#define KSTK_EIP(tsk) (task_pt_regs(tsk)->tpc) +#define KSTK_ESP(tsk) (task_pt_regs(tsk)->u_regs[UREG_FP]) #define cpu_relax() barrier() diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h index 309f1466b6f..af254e58183 100644 --- a/include/asm-sparc64/system.h +++ b/include/asm-sparc64/system.h @@ -208,7 +208,7 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \ /* If you are tempted to conditionalize the following */ \ /* so that ASI is only written if it changes, think again. */ \ __asm__ __volatile__("wr %%g0, %0, %%asi" \ - : : "r" (__thread_flag_byte_ptr(next->thread_info)[TI_FLAG_BYTE_CURRENT_DS]));\ + : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\ __asm__ __volatile__( \ "mov %%g4, %%g7\n\t" \ "wrpr %%g0, 0x95, %%pstate\n\t" \ @@ -238,7 +238,7 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \ "b,a ret_from_syscall\n\t" \ "1:\n\t" \ : "=&r" (last) \ - : "0" (next->thread_info), \ + : "0" (task_thread_info(next)), \ "i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_NEW_CHILD), \ "i" (TI_CWP), "i" (TI_TASK) \ : "cc", \ @@ -253,6 +253,16 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \ } \ } while(0) +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} + static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val) { unsigned long tmp1, tmp2; diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h index 97267f059ef..705c71972c3 100644 --- a/include/asm-um/thread_info.h +++ b/include/asm-um/thread_info.h @@ -56,9 +56,6 @@ static inline struct thread_info *current_thread_info(void) ((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL)) #define free_thread_info(ti) kfree(ti) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) - #endif #define PREEMPT_ACTIVE 0x10000000 diff --git a/include/asm-v850/processor.h b/include/asm-v850/processor.h index 98f929427d3..2d31308935a 100644 --- a/include/asm-v850/processor.h +++ b/include/asm-v850/processor.h @@ -98,10 +98,10 @@ unsigned long get_wchan (struct task_struct *p); /* Return some info about the user process TASK. */ -#define task_tos(task) ((unsigned long)(task)->thread_info + THREAD_SIZE) -#define task_regs(task) ((struct pt_regs *)task_tos (task) - 1) -#define task_sp(task) (task_regs (task)->gpr[GPR_SP]) -#define task_pc(task) (task_regs (task)->pc) +#define task_tos(task) ((unsigned long)task_stack_page(task) + THREAD_SIZE) +#define task_pt_regs(task) ((struct pt_regs *)task_tos (task) - 1) +#define task_sp(task) (task_pt_regs (task)->gpr[GPR_SP]) +#define task_pc(task) (task_pt_regs (task)->pc) /* Grotty old names for some. */ #define KSTK_EIP(task) task_pc (task) #define KSTK_ESP(task) task_sp (task) diff --git a/include/asm-v850/thread_info.h b/include/asm-v850/thread_info.h index e4cfad94a55..82b8f284620 100644 --- a/include/asm-v850/thread_info.h +++ b/include/asm-v850/thread_info.h @@ -58,8 +58,6 @@ struct thread_info { #define alloc_thread_info(tsk) ((struct thread_info *) \ __get_free_pages(GFP_KERNEL, 1)) #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #endif /* __ASSEMBLY__ */ diff --git a/include/asm-x86_64/compat.h b/include/asm-x86_64/compat.h index 3863a7da372..b37ab8218ef 100644 --- a/include/asm-x86_64/compat.h +++ b/include/asm-x86_64/compat.h @@ -198,7 +198,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) static __inline__ void __user *compat_alloc_user_space(long len) { - struct pt_regs *regs = (void *)current->thread.rsp0 - sizeof(struct pt_regs); + struct pt_regs *regs = task_pt_regs(current); return (void __user *)regs->rsp - len; } diff --git a/include/asm-x86_64/i387.h b/include/asm-x86_64/i387.h index 57f7e143384..876eb9a2fe7 100644 --- a/include/asm-x86_64/i387.h +++ b/include/asm-x86_64/i387.h @@ -30,7 +30,7 @@ extern int save_i387(struct _fpstate __user *buf); */ #define unlazy_fpu(tsk) do { \ - if ((tsk)->thread_info->status & TS_USEDFPU) \ + if (task_thread_info(tsk)->status & TS_USEDFPU) \ save_init_fpu(tsk); \ } while (0) @@ -46,9 +46,9 @@ static inline void tolerant_fwait(void) } #define clear_fpu(tsk) do { \ - if ((tsk)->thread_info->status & TS_USEDFPU) { \ + if (task_thread_info(tsk)->status & TS_USEDFPU) { \ tolerant_fwait(); \ - (tsk)->thread_info->status &= ~TS_USEDFPU; \ + task_thread_info(tsk)->status &= ~TS_USEDFPU; \ stts(); \ } \ } while (0) @@ -170,10 +170,10 @@ static inline void kernel_fpu_end(void) preempt_enable(); } -static inline void save_init_fpu( struct task_struct *tsk ) +static inline void save_init_fpu(struct task_struct *tsk) { __fxsave_clear(tsk); - tsk->thread_info->status &= ~TS_USEDFPU; + task_thread_info(tsk)->status &= ~TS_USEDFPU; stts(); } diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index 394dd729752..87a282b1043 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h @@ -321,8 +321,8 @@ extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); #define thread_saved_pc(t) (*(unsigned long *)((t)->thread.rsp - 8)) extern unsigned long get_wchan(struct task_struct *p); -#define KSTK_EIP(tsk) \ - (((struct pt_regs *)(tsk->thread.rsp0 - sizeof(struct pt_regs)))->rip) +#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.rsp0 - 1) +#define KSTK_EIP(tsk) (task_pt_regs(tsk)->rip) #define KSTK_ESP(tsk) -1 /* sorry. doesn't work for syscall. */ diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h index 38c1e8a69c9..0eacbefb7dd 100644 --- a/include/asm-x86_64/system.h +++ b/include/asm-x86_64/system.h @@ -193,6 +193,15 @@ static inline void write_cr4(unsigned long val) #define wbinvd() \ __asm__ __volatile__ ("wbinvd": : :"memory"); +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + */ +static inline void sched_cacheflush(void) +{ + wbinvd(); +} + #endif /* __KERNEL__ */ #define nop() __asm__ __volatile__ ("nop") diff --git a/include/asm-x86_64/thread_info.h b/include/asm-x86_64/thread_info.h index eb7c5fda187..4ac0e0a3693 100644 --- a/include/asm-x86_64/thread_info.h +++ b/include/asm-x86_64/thread_info.h @@ -76,8 +76,6 @@ static inline struct thread_info *stack_thread_info(void) #define alloc_thread_info(tsk) \ ((struct thread_info *) __get_free_pages(GFP_KERNEL,THREAD_ORDER)) #define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #else /* !__ASSEMBLY__ */ diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h index 7d82bc56b9f..2fa7f27381b 100644 --- a/include/asm-x86_64/topology.h +++ b/include/asm-x86_64/topology.h @@ -39,7 +39,6 @@ extern int __node_distance(int, int); .max_interval = 32, \ .busy_factor = 32, \ .imbalance_pct = 125, \ - .cache_hot_time = (10*1000000), \ .cache_nice_tries = 2, \ .busy_idx = 3, \ .idle_idx = 2, \ diff --git a/include/asm-xtensa/processor.h b/include/asm-xtensa/processor.h index 9cab5e4298b..d1d72ad36f0 100644 --- a/include/asm-xtensa/processor.h +++ b/include/asm-xtensa/processor.h @@ -184,12 +184,12 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); #define release_segments(mm) do { } while(0) #define forget_segments() do { } while (0) -#define thread_saved_pc(tsk) (xtensa_pt_regs(tsk)->pc) +#define thread_saved_pc(tsk) (task_pt_regs(tsk)->pc) extern unsigned long get_wchan(struct task_struct *p); -#define KSTK_EIP(tsk) (xtensa_pt_regs(tsk)->pc) -#define KSTK_ESP(tsk) (xtensa_pt_regs(tsk)->areg[1]) +#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) +#define KSTK_ESP(tsk) (task_pt_regs(tsk)->areg[1]) #define cpu_relax() do { } while (0) diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h index aa4fd7fb3ce..a5ac71a5205 100644 --- a/include/asm-xtensa/ptrace.h +++ b/include/asm-xtensa/ptrace.h @@ -113,8 +113,8 @@ struct pt_regs { }; #ifdef __KERNEL__ -# define xtensa_pt_regs(tsk) ((struct pt_regs*) \ - (((long)(tsk)->thread_info + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4)) - 1) +# define task_pt_regs(tsk) ((struct pt_regs*) \ + (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1) # define user_mode(regs) (((regs)->ps & 0x00000020)!=0) # define instruction_pointer(regs) ((regs)->pc) extern void show_regs(struct pt_regs *); diff --git a/include/asm-xtensa/thread_info.h b/include/asm-xtensa/thread_info.h index af208d41fd8..5ae34ab7159 100644 --- a/include/asm-xtensa/thread_info.h +++ b/include/asm-xtensa/thread_info.h @@ -93,8 +93,6 @@ static inline struct thread_info *current_thread_info(void) /* thread information allocation */ #define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) #else /* !__ASSEMBLY__ */ diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index cf5cfdf8d61..089bfb1fa01 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -49,8 +49,6 @@ struct hrtimer_base; * struct hrtimer - the basic hrtimer structure * * @node: red black tree node for time ordered insertion - * @list: list head for easier access to the time ordered list, - * without walking the red black tree. * @expires: the absolute expiry time in the hrtimers internal * representation. The time is related to the clock on * which the timer is based. @@ -63,7 +61,6 @@ struct hrtimer_base; */ struct hrtimer { struct rb_node node; - struct list_head list; ktime_t expires; enum hrtimer_state state; int (*function)(void *); @@ -78,7 +75,7 @@ struct hrtimer { * to a base on another cpu. * @lock: lock protecting the base and associated timers * @active: red black tree root node for the active timers - * @pending: list of pending timers for simple time ordered access + * @first: pointer to the timer node which expires first * @resolution: the resolution of the clock, in nanoseconds * @get_time: function to retrieve the current time of the clock * @curr_timer: the timer which is executing a callback right now @@ -87,8 +84,8 @@ struct hrtimer_base { clockid_t index; spinlock_t lock; struct rb_root active; - struct list_head pending; - unsigned long resolution; + struct rb_node *first; + ktime_t resolution; ktime_t (*get_time)(void); struct hrtimer *curr_timer; }; @@ -125,8 +122,7 @@ static inline int hrtimer_active(const struct hrtimer *timer) } /* Forward a hrtimer so it expires after now: */ -extern unsigned long hrtimer_forward(struct hrtimer *timer, - const ktime_t interval); +extern unsigned long hrtimer_forward(struct hrtimer *timer, ktime_t interval); /* Precise sleep: */ extern long hrtimer_nanosleep(struct timespec *rqtp, diff --git a/include/linux/ide.h b/include/linux/ide.h index 9a8c05dbe4f..f2e1b5b2289 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1002,7 +1002,6 @@ extern int noautodma; extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs); extern int __ide_end_request (ide_drive_t *drive, struct request *rq, int uptodate, int nrsecs); -extern void ide_softirq_done(struct request *rq); /* * This is used on exit from the driver to designate the next irq handler diff --git a/include/linux/ktime.h b/include/linux/ktime.h index 222a047cc14..1bd6552cc34 100644 --- a/include/linux/ktime.h +++ b/include/linux/ktime.h @@ -272,8 +272,8 @@ static inline u64 ktime_to_ns(const ktime_t kt) * idea of the (in)accuracy of timers. Timer values are rounded up to * this resolution values. */ -#define KTIME_REALTIME_RES (NSEC_PER_SEC/HZ) -#define KTIME_MONOTONIC_RES (NSEC_PER_SEC/HZ) +#define KTIME_REALTIME_RES (ktime_t){ .tv64 = TICK_NSEC } +#define KTIME_MONOTONIC_RES (ktime_t){ .tv64 = TICK_NSEC } /* Get the monotonic time in timespec format: */ extern void ktime_get_ts(struct timespec *ts); diff --git a/include/linux/sched.h b/include/linux/sched.h index 3b74c4bf293..a72e1713542 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -631,7 +631,14 @@ struct sched_domain { extern void partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2); -#endif /* CONFIG_SMP */ + +/* + * Maximum cache size the migration-costs auto-tuning code will + * search from: + */ +extern unsigned int max_cache_size; + +#endif /* CONFIG_SMP */ struct io_context; /* See blkdev.h */ @@ -689,9 +696,12 @@ struct task_struct { int lock_depth; /* BKL lock depth */ -#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW) +#if defined(CONFIG_SMP) + int last_waker_cpu; /* CPU that last woke this task up */ +#if defined(__ARCH_WANT_UNLOCKED_CTXSW) int oncpu; #endif +#endif int prio, static_prio; struct list_head run_list; prio_array_t *array; @@ -1230,6 +1240,7 @@ static inline void task_unlock(struct task_struct *p) #ifndef __HAVE_THREAD_FUNCTIONS #define task_thread_info(task) (task)->thread_info +#define task_stack_page(task) ((void*)((task)->thread_info)) static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) { diff --git a/include/linux/topology.h b/include/linux/topology.h index 3df1d474e5c..315a5163d6a 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -86,7 +86,6 @@ .max_interval = 2, \ .busy_factor = 8, \ .imbalance_pct = 110, \ - .cache_hot_time = 0, \ .cache_nice_tries = 0, \ .per_cpu_gain = 25, \ .busy_idx = 0, \ @@ -117,7 +116,6 @@ .max_interval = 4, \ .busy_factor = 64, \ .imbalance_pct = 125, \ - .cache_hot_time = (5*1000000/2), \ .cache_nice_tries = 1, \ .per_cpu_gain = 100, \ .busy_idx = 2, \ diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index f073a2461fa..04ccab099e8 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -275,7 +275,7 @@ void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags) * The number of overruns is added to the overrun field. */ unsigned long -hrtimer_forward(struct hrtimer *timer, const ktime_t interval) +hrtimer_forward(struct hrtimer *timer, ktime_t interval) { unsigned long orun = 1; ktime_t delta, now; @@ -287,6 +287,9 @@ hrtimer_forward(struct hrtimer *timer, const ktime_t interval) if (delta.tv64 < 0) return 0; + if (interval.tv64 < timer->base->resolution.tv64) + interval.tv64 = timer->base->resolution.tv64; + if (unlikely(delta.tv64 >= interval.tv64)) { nsec_t incr = ktime_to_ns(interval); @@ -314,7 +317,6 @@ hrtimer_forward(struct hrtimer *timer, const ktime_t interval) static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) { struct rb_node **link = &base->active.rb_node; - struct list_head *prev = &base->pending; struct rb_node *parent = NULL; struct hrtimer *entry; @@ -330,22 +332,23 @@ static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) */ if (timer->expires.tv64 < entry->expires.tv64) link = &(*link)->rb_left; - else { + else link = &(*link)->rb_right; - prev = &entry->list; - } } /* - * Insert the timer to the rbtree and to the sorted list: + * Insert the timer to the rbtree and check whether it + * replaces the first pending timer */ rb_link_node(&timer->node, parent, link); rb_insert_color(&timer->node, &base->active); - list_add(&timer->list, prev); timer->state = HRTIMER_PENDING; -} + if (!base->first || timer->expires.tv64 < + rb_entry(base->first, struct hrtimer, node)->expires.tv64) + base->first = &timer->node; +} /* * __remove_hrtimer - internal function to remove a timer @@ -355,9 +358,11 @@ static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) { /* - * Remove the timer from the sorted list and from the rbtree: + * Remove the timer from the rbtree and replace the + * first entry pointer if necessary. */ - list_del(&timer->list); + if (base->first == &timer->node) + base->first = rb_next(&timer->node); rb_erase(&timer->node, &base->active); } @@ -516,9 +521,8 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp) { struct hrtimer_base *bases; - tp->tv_sec = 0; bases = per_cpu(hrtimer_bases, raw_smp_processor_id()); - tp->tv_nsec = bases[which_clock].resolution; + *tp = ktime_to_timespec(bases[which_clock].resolution); return 0; } @@ -529,16 +533,17 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp) static inline void run_hrtimer_queue(struct hrtimer_base *base) { ktime_t now = base->get_time(); + struct rb_node *node; spin_lock_irq(&base->lock); - while (!list_empty(&base->pending)) { + while ((node = base->first)) { struct hrtimer *timer; int (*fn)(void *); int restart; void *data; - timer = list_entry(base->pending.next, struct hrtimer, list); + timer = rb_entry(node, struct hrtimer, node); if (now.tv64 <= timer->expires.tv64) break; @@ -732,7 +737,6 @@ static void __devinit init_hrtimers_cpu(int cpu) for (i = 0; i < MAX_HRTIMER_BASES; i++) { spin_lock_init(&base->lock); - INIT_LIST_HEAD(&base->pending); base++; } } diff --git a/kernel/sched.c b/kernel/sched.c index c0c60c926d5..c9dec2aa197 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -34,6 +34,7 @@ #include <linux/notifier.h> #include <linux/profile.h> #include <linux/suspend.h> +#include <linux/vmalloc.h> #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/smp.h> @@ -1289,6 +1290,9 @@ static int try_to_wake_up(task_t *p, unsigned int state, int sync) } } + if (p->last_waker_cpu != this_cpu) + goto out_set_cpu; + if (unlikely(!cpu_isset(this_cpu, p->cpus_allowed))) goto out_set_cpu; @@ -1359,6 +1363,8 @@ out_set_cpu: cpu = task_cpu(p); } + p->last_waker_cpu = this_cpu; + out_activate: #endif /* CONFIG_SMP */ if (old_state == TASK_UNINTERRUPTIBLE) { @@ -1440,9 +1446,12 @@ void fastcall sched_fork(task_t *p, int clone_flags) #ifdef CONFIG_SCHEDSTATS memset(&p->sched_info, 0, sizeof(p->sched_info)); #endif -#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW) +#if defined(CONFIG_SMP) + p->last_waker_cpu = cpu; +#if defined(__ARCH_WANT_UNLOCKED_CTXSW) p->oncpu = 0; #endif +#endif #ifdef CONFIG_PREEMPT /* Want to start with kernel preemption disabled. */ task_thread_info(p)->preempt_count = 1; @@ -5082,7 +5091,470 @@ static void init_sched_build_groups(struct sched_group groups[], cpumask_t span, #define SD_NODES_PER_DOMAIN 16 +/* + * Self-tuning task migration cost measurement between source and target CPUs. + * + * This is done by measuring the cost of manipulating buffers of varying + * sizes. For a given buffer-size here are the steps that are taken: + * + * 1) the source CPU reads+dirties a shared buffer + * 2) the target CPU reads+dirties the same shared buffer + * + * We measure how long they take, in the following 4 scenarios: + * + * - source: CPU1, target: CPU2 | cost1 + * - source: CPU2, target: CPU1 | cost2 + * - source: CPU1, target: CPU1 | cost3 + * - source: CPU2, target: CPU2 | cost4 + * + * We then calculate the cost3+cost4-cost1-cost2 difference - this is + * the cost of migration. + * + * We then start off from a small buffer-size and iterate up to larger + * buffer sizes, in 5% steps - measuring each buffer-size separately, and + * doing a maximum search for the cost. (The maximum cost for a migration + * normally occurs when the working set size is around the effective cache + * size.) + */ +#define SEARCH_SCOPE 2 +#define MIN_CACHE_SIZE (64*1024U) +#define DEFAULT_CACHE_SIZE (5*1024*1024U) +#define ITERATIONS 2 +#define SIZE_THRESH 130 +#define COST_THRESH 130 + +/* + * The migration cost is a function of 'domain distance'. Domain + * distance is the number of steps a CPU has to iterate down its + * domain tree to share a domain with the other CPU. The farther + * two CPUs are from each other, the larger the distance gets. + * + * Note that we use the distance only to cache measurement results, + * the distance value is not used numerically otherwise. When two + * CPUs have the same distance it is assumed that the migration + * cost is the same. (this is a simplification but quite practical) + */ +#define MAX_DOMAIN_DISTANCE 32 + +static unsigned long long migration_cost[MAX_DOMAIN_DISTANCE] = + { [ 0 ... MAX_DOMAIN_DISTANCE-1 ] = -1LL }; + +/* + * Allow override of migration cost - in units of microseconds. + * E.g. migration_cost=1000,2000,3000 will set up a level-1 cost + * of 1 msec, level-2 cost of 2 msecs and level3 cost of 3 msecs: + */ +static int __init migration_cost_setup(char *str) +{ + int ints[MAX_DOMAIN_DISTANCE+1], i; + + str = get_options(str, ARRAY_SIZE(ints), ints); + + printk("#ints: %d\n", ints[0]); + for (i = 1; i <= ints[0]; i++) { + migration_cost[i-1] = (unsigned long long)ints[i]*1000; + printk("migration_cost[%d]: %Ld\n", i-1, migration_cost[i-1]); + } + return 1; +} + +__setup ("migration_cost=", migration_cost_setup); + +/* + * Global multiplier (divisor) for migration-cutoff values, + * in percentiles. E.g. use a value of 150 to get 1.5 times + * longer cache-hot cutoff times. + * + * (We scale it from 100 to 128 to long long handling easier.) + */ + +#define MIGRATION_FACTOR_SCALE 128 + +static unsigned int migration_factor = MIGRATION_FACTOR_SCALE; + +static int __init setup_migration_factor(char *str) +{ + get_option(&str, &migration_factor); + migration_factor = migration_factor * MIGRATION_FACTOR_SCALE / 100; + return 1; +} + +__setup("migration_factor=", setup_migration_factor); + +/* + * Estimated distance of two CPUs, measured via the number of domains + * we have to pass for the two CPUs to be in the same span: + */ +static unsigned long domain_distance(int cpu1, int cpu2) +{ + unsigned long distance = 0; + struct sched_domain *sd; + + for_each_domain(cpu1, sd) { + WARN_ON(!cpu_isset(cpu1, sd->span)); + if (cpu_isset(cpu2, sd->span)) + return distance; + distance++; + } + if (distance >= MAX_DOMAIN_DISTANCE) { + WARN_ON(1); + distance = MAX_DOMAIN_DISTANCE-1; + } + + return distance; +} + +static unsigned int migration_debug; + +static int __init setup_migration_debug(char *str) +{ + get_option(&str, &migration_debug); + return 1; +} + +__setup("migration_debug=", setup_migration_debug); + +/* + * Maximum cache-size that the scheduler should try to measure. + * Architectures with larger caches should tune this up during + * bootup. Gets used in the domain-setup code (i.e. during SMP + * bootup). + */ +unsigned int max_cache_size; + +static int __init setup_max_cache_size(char *str) +{ + get_option(&str, &max_cache_size); + return 1; +} + +__setup("max_cache_size=", setup_max_cache_size); + +/* + * Dirty a big buffer in a hard-to-predict (for the L2 cache) way. This + * is the operation that is timed, so we try to generate unpredictable + * cachemisses that still end up filling the L2 cache: + */ +static void touch_cache(void *__cache, unsigned long __size) +{ + unsigned long size = __size/sizeof(long), chunk1 = size/3, + chunk2 = 2*size/3; + unsigned long *cache = __cache; + int i; + + for (i = 0; i < size/6; i += 8) { + switch (i % 6) { + case 0: cache[i]++; + case 1: cache[size-1-i]++; + case 2: cache[chunk1-i]++; + case 3: cache[chunk1+i]++; + case 4: cache[chunk2-i]++; + case 5: cache[chunk2+i]++; + } + } +} + +/* + * Measure the cache-cost of one task migration. Returns in units of nsec. + */ +static unsigned long long measure_one(void *cache, unsigned long size, + int source, int target) +{ + cpumask_t mask, saved_mask; + unsigned long long t0, t1, t2, t3, cost; + + saved_mask = current->cpus_allowed; + + /* + * Flush source caches to RAM and invalidate them: + */ + sched_cacheflush(); + + /* + * Migrate to the source CPU: + */ + mask = cpumask_of_cpu(source); + set_cpus_allowed(current, mask); + WARN_ON(smp_processor_id() != source); + + /* + * Dirty the working set: + */ + t0 = sched_clock(); + touch_cache(cache, size); + t1 = sched_clock(); + + /* + * Migrate to the target CPU, dirty the L2 cache and access + * the shared buffer. (which represents the working set + * of a migrated task.) + */ + mask = cpumask_of_cpu(target); + set_cpus_allowed(current, mask); + WARN_ON(smp_processor_id() != target); + + t2 = sched_clock(); + touch_cache(cache, size); + t3 = sched_clock(); + + cost = t1-t0 + t3-t2; + + if (migration_debug >= 2) + printk("[%d->%d]: %8Ld %8Ld %8Ld => %10Ld.\n", + source, target, t1-t0, t1-t0, t3-t2, cost); + /* + * Flush target caches to RAM and invalidate them: + */ + sched_cacheflush(); + + set_cpus_allowed(current, saved_mask); + + return cost; +} + +/* + * Measure a series of task migrations and return the average + * result. Since this code runs early during bootup the system + * is 'undisturbed' and the average latency makes sense. + * + * The algorithm in essence auto-detects the relevant cache-size, + * so it will properly detect different cachesizes for different + * cache-hierarchies, depending on how the CPUs are connected. + * + * Architectures can prime the upper limit of the search range via + * max_cache_size, otherwise the search range defaults to 20MB...64K. + */ +static unsigned long long +measure_cost(int cpu1, int cpu2, void *cache, unsigned int size) +{ + unsigned long long cost1, cost2; + int i; + + /* + * Measure the migration cost of 'size' bytes, over an + * average of 10 runs: + * + * (We perturb the cache size by a small (0..4k) + * value to compensate size/alignment related artifacts. + * We also subtract the cost of the operation done on + * the same CPU.) + */ + cost1 = 0; + + /* + * dry run, to make sure we start off cache-cold on cpu1, + * and to get any vmalloc pagefaults in advance: + */ + measure_one(cache, size, cpu1, cpu2); + for (i = 0; i < ITERATIONS; i++) + cost1 += measure_one(cache, size - i*1024, cpu1, cpu2); + + measure_one(cache, size, cpu2, cpu1); + for (i = 0; i < ITERATIONS; i++) + cost1 += measure_one(cache, size - i*1024, cpu2, cpu1); + + /* + * (We measure the non-migrating [cached] cost on both + * cpu1 and cpu2, to handle CPUs with different speeds) + */ + cost2 = 0; + + measure_one(cache, size, cpu1, cpu1); + for (i = 0; i < ITERATIONS; i++) + cost2 += measure_one(cache, size - i*1024, cpu1, cpu1); + + measure_one(cache, size, cpu2, cpu2); + for (i = 0; i < ITERATIONS; i++) + cost2 += measure_one(cache, size - i*1024, cpu2, cpu2); + + /* + * Get the per-iteration migration cost: + */ + do_div(cost1, 2*ITERATIONS); + do_div(cost2, 2*ITERATIONS); + + return cost1 - cost2; +} + +static unsigned long long measure_migration_cost(int cpu1, int cpu2) +{ + unsigned long long max_cost = 0, fluct = 0, avg_fluct = 0; + unsigned int max_size, size, size_found = 0; + long long cost = 0, prev_cost; + void *cache; + + /* + * Search from max_cache_size*5 down to 64K - the real relevant + * cachesize has to lie somewhere inbetween. + */ + if (max_cache_size) { + max_size = max(max_cache_size * SEARCH_SCOPE, MIN_CACHE_SIZE); + size = max(max_cache_size / SEARCH_SCOPE, MIN_CACHE_SIZE); + } else { + /* + * Since we have no estimation about the relevant + * search range + */ + max_size = DEFAULT_CACHE_SIZE * SEARCH_SCOPE; + size = MIN_CACHE_SIZE; + } + + if (!cpu_online(cpu1) || !cpu_online(cpu2)) { + printk("cpu %d and %d not both online!\n", cpu1, cpu2); + return 0; + } + + /* + * Allocate the working set: + */ + cache = vmalloc(max_size); + if (!cache) { + printk("could not vmalloc %d bytes for cache!\n", 2*max_size); + return 1000000; // return 1 msec on very small boxen + } + + while (size <= max_size) { + prev_cost = cost; + cost = measure_cost(cpu1, cpu2, cache, size); + + /* + * Update the max: + */ + if (cost > 0) { + if (max_cost < cost) { + max_cost = cost; + size_found = size; + } + } + /* + * Calculate average fluctuation, we use this to prevent + * noise from triggering an early break out of the loop: + */ + fluct = abs(cost - prev_cost); + avg_fluct = (avg_fluct + fluct)/2; + + if (migration_debug) + printk("-> [%d][%d][%7d] %3ld.%ld [%3ld.%ld] (%ld): (%8Ld %8Ld)\n", + cpu1, cpu2, size, + (long)cost / 1000000, + ((long)cost / 100000) % 10, + (long)max_cost / 1000000, + ((long)max_cost / 100000) % 10, + domain_distance(cpu1, cpu2), + cost, avg_fluct); + + /* + * If we iterated at least 20% past the previous maximum, + * and the cost has dropped by more than 20% already, + * (taking fluctuations into account) then we assume to + * have found the maximum and break out of the loop early: + */ + if (size_found && (size*100 > size_found*SIZE_THRESH)) + if (cost+avg_fluct <= 0 || + max_cost*100 > (cost+avg_fluct)*COST_THRESH) { + + if (migration_debug) + printk("-> found max.\n"); + break; + } + /* + * Increase the cachesize in 5% steps: + */ + size = size * 20 / 19; + } + + if (migration_debug) + printk("[%d][%d] working set size found: %d, cost: %Ld\n", + cpu1, cpu2, size_found, max_cost); + + vfree(cache); + + /* + * A task is considered 'cache cold' if at least 2 times + * the worst-case cost of migration has passed. + * + * (this limit is only listened to if the load-balancing + * situation is 'nice' - if there is a large imbalance we + * ignore it for the sake of CPU utilization and + * processing fairness.) + */ + return 2 * max_cost * migration_factor / MIGRATION_FACTOR_SCALE; +} + +static void calibrate_migration_costs(const cpumask_t *cpu_map) +{ + int cpu1 = -1, cpu2 = -1, cpu, orig_cpu = raw_smp_processor_id(); + unsigned long j0, j1, distance, max_distance = 0; + struct sched_domain *sd; + + j0 = jiffies; + + /* + * First pass - calculate the cacheflush times: + */ + for_each_cpu_mask(cpu1, *cpu_map) { + for_each_cpu_mask(cpu2, *cpu_map) { + if (cpu1 == cpu2) + continue; + distance = domain_distance(cpu1, cpu2); + max_distance = max(max_distance, distance); + /* + * No result cached yet? + */ + if (migration_cost[distance] == -1LL) + migration_cost[distance] = + measure_migration_cost(cpu1, cpu2); + } + } + /* + * Second pass - update the sched domain hierarchy with + * the new cache-hot-time estimations: + */ + for_each_cpu_mask(cpu, *cpu_map) { + distance = 0; + for_each_domain(cpu, sd) { + sd->cache_hot_time = migration_cost[distance]; + distance++; + } + } + /* + * Print the matrix: + */ + if (migration_debug) + printk("migration: max_cache_size: %d, cpu: %d MHz:\n", + max_cache_size, +#ifdef CONFIG_X86 + cpu_khz/1000 +#else + -1 +#endif + ); + printk("migration_cost="); + for (distance = 0; distance <= max_distance; distance++) { + if (distance) + printk(","); + printk("%ld", (long)migration_cost[distance] / 1000); + } + printk("\n"); + j1 = jiffies; + if (migration_debug) + printk("migration: %ld seconds\n", (j1-j0)/HZ); + + /* + * Move back to the original CPU. NUMA-Q gets confused + * if we migrate to another quad during bootup. + */ + if (raw_smp_processor_id() != orig_cpu) { + cpumask_t mask = cpumask_of_cpu(orig_cpu), + saved_mask = current->cpus_allowed; + + set_cpus_allowed(current, mask); + set_cpus_allowed(current, saved_mask); + } +} + #ifdef CONFIG_NUMA + /** * find_next_best_node - find the next node to include in a sched_domain * @node: node whose sched_domain we're building @@ -5448,6 +5920,10 @@ next_sg: #endif cpu_attach_domain(sd, i); } + /* + * Tune cache-hot values: + */ + calibrate_migration_costs(cpu_map); } /* * Set up scheduler domains and groups. Callers must hold the hotplug lock. diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 1850d0aef4a..b62cab575a8 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -208,6 +208,8 @@ static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd, page = vm_normal_page(vma, addr, *pte); if (!page) continue; + if (PageReserved(page)) + continue; nid = page_to_nid(page); if (node_isset(nid, *nodes) == !!(flags & MPOL_MF_INVERT)) continue; @@ -290,7 +292,7 @@ static inline int check_pgd_range(struct vm_area_struct *vma, static inline int vma_migratable(struct vm_area_struct *vma) { if (vma->vm_flags & ( - VM_LOCKED|VM_IO|VM_HUGETLB|VM_PFNMAP)) + VM_LOCKED|VM_IO|VM_HUGETLB|VM_PFNMAP|VM_RESERVED)) return 0; return 1; } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d41a0662d4d..8c960b46959 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1742,7 +1742,7 @@ void __devinit memmap_init_zone(unsigned long size, int nid, unsigned long zone, unsigned long end_pfn = start_pfn + size; unsigned long pfn; - for (pfn = start_pfn; pfn < end_pfn; pfn++, page++) { + for (pfn = start_pfn; pfn < end_pfn; pfn++) { if (!early_pfn_valid(pfn)) continue; page = pfn_to_page(pfn); diff --git a/mm/swap.c b/mm/swap.c index ee6d71ccfa5..cbb48e721ab 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -384,6 +384,8 @@ unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping, return pagevec_count(pvec); } +EXPORT_SYMBOL(pagevec_lookup); + unsigned pagevec_lookup_tag(struct pagevec *pvec, struct address_space *mapping, pgoff_t *index, int tag, unsigned nr_pages) { diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c index cdc6d431972..f9d6a9cc91c 100644 --- a/mm/tiny-shmem.c +++ b/mm/tiny-shmem.c @@ -90,7 +90,7 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) file->f_mode = FMODE_WRITE | FMODE_READ; /* notify everyone as to the change of file size */ - error = do_truncate(dentry, size, file); + error = do_truncate(dentry, size, 0, file); if (error < 0) goto close_file; diff --git a/sound/oss/dmasound/dmasound.h b/sound/oss/dmasound/dmasound.h index 222014cafc1..a1b0b92af4b 100644 --- a/sound/oss/dmasound/dmasound.h +++ b/sound/oss/dmasound/dmasound.h @@ -270,7 +270,6 @@ extern int dmasound_catchRadius; #define SW_INPUT_VOLUME_SCALE 4 #define SW_INPUT_VOLUME_DEFAULT (128 / SW_INPUT_VOLUME_SCALE) -extern int expand_bal; /* Balance factor for expanding (not volume!) */ extern int expand_read_bal; /* Balance factor for reading */ extern uint software_input_volume; /* software implemented recording volume! */ diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c index 59eb53f8931..dc31373069a 100644 --- a/sound/oss/dmasound/dmasound_atari.c +++ b/sound/oss/dmasound/dmasound_atari.c @@ -67,46 +67,46 @@ static int expand_data; /* Data for expanding */ * ++geert: split in even more functions (one per format) */ -static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); @@ -151,7 +151,7 @@ static int FalconStateInfo(char *buffer, size_t space); /*** Translations ************************************************************/ -static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -176,7 +176,7 @@ static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -194,7 +194,7 @@ static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -217,8 +217,9 @@ static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount, used = count*2; while (count > 0) { u_short data; - if (get_user(data, ((u_short *)userPtr)++)) + if (get_user(data, (u_short __user *)userPtr)) return -EFAULT; + userPtr += 2; *p++ = data ^ 0x8080; count--; } @@ -228,7 +229,7 @@ static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -240,8 +241,9 @@ static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount, used = count*2; while (count > 0) { u_short data; - if (get_user(data, ((u_short *)userPtr)++)) + if (get_user(data, (u_short __user *)userPtr)) return -EFAULT; + userPtr += 2; *p++ = data; *p++ = data; count--; @@ -259,7 +261,7 @@ static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -271,8 +273,9 @@ static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount, used = count*2; while (count > 0) { u_short data; - if (get_user(data, ((u_short *)userPtr)++)) + if (get_user(data, (u_short __user *)userPtr)) return -EFAULT; + userPtr += 2; data ^= 0x8000; *p++ = data; *p++ = data; @@ -284,9 +287,10 @@ static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount, count = min_t(unsigned long, userCount, frameLeft)>>2; used = count*4; while (count > 0) { - u_long data; - if (get_user(data, ((u_int *)userPtr)++)) + u_int data; + if (get_user(data, (u_int __user *)userPtr)) return -EFAULT; + userPtr += 4; *p++ = data ^ 0x80008000; count--; } @@ -296,7 +300,7 @@ static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -309,8 +313,9 @@ static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount, used = count*2; while (count > 0) { u_short data; - if (get_user(data, ((u_short *)userPtr)++)) + if (get_user(data, (u_short __user *)userPtr)) return -EFAULT; + userPtr += 2; data = le2be16(data); *p++ = data; *p++ = data; @@ -323,8 +328,9 @@ static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount, used = count*4; while (count > 0) { u_long data; - if (get_user(data, ((u_int *)userPtr)++)) + if (get_user(data, (u_int __user *)userPtr)) return -EFAULT; + userPtr += 4; data = le2be16dbl(data); *p++ = data; count--; @@ -335,7 +341,7 @@ static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount, +static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -348,8 +354,9 @@ static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount, used = count*2; while (count > 0) { u_short data; - if (get_user(data, ((u_short *)userPtr)++)) + if (get_user(data, (u_short __user *)userPtr)) return -EFAULT; + userPtr += 2; data = le2be16(data) ^ 0x8000; *p++ = data; *p++ = data; @@ -361,8 +368,9 @@ static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount, used = count; while (count > 0) { u_long data; - if (get_user(data, ((u_int *)userPtr)++)) + if (get_user(data, (u_int __user *)userPtr)) return -EFAULT; + userPtr += 4; data = le2be16dbl(data) ^ 0x80008000; *p++ = data; count--; @@ -373,7 +381,7 @@ static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -435,7 +443,7 @@ static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -470,8 +478,9 @@ static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount, if (bal < 0) { if (userCount < 2) break; - if (get_user(data, ((u_short *)userPtr)++)) + if (get_user(data, (u_short __user *)userPtr)) return -EFAULT; + userPtr += 2; userCount -= 2; bal += hSpeed; } @@ -488,7 +497,7 @@ static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -524,8 +533,9 @@ static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount, if (bal < 0) { if (userCount < 2) break; - if (get_user(data, ((u_short *)userPtr)++)) + if (get_user(data, (u_short __user *)userPtr)) return -EFAULT; + userPtr += 2; data ^= 0x8080; userCount -= 2; bal += hSpeed; @@ -543,7 +553,7 @@ static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -561,8 +571,9 @@ static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount, if (bal < 0) { if (userCount < 2) break; - if (get_user(data, ((u_short *)userPtr)++)) + if (get_user(data, (u_short __user *)userPtr)) return -EFAULT; + userPtr += 2; userCount -= 2; bal += hSpeed; } @@ -579,8 +590,9 @@ static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount, if (bal < 0) { if (userCount < 4) break; - if (get_user(data, ((u_int *)userPtr)++)) + if (get_user(data, (u_int __user *)userPtr)) return -EFAULT; + userPtr += 4; userCount -= 4; bal += hSpeed; } @@ -597,7 +609,7 @@ static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -615,8 +627,9 @@ static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount, if (bal < 0) { if (userCount < 2) break; - if (get_user(data, ((u_short *)userPtr)++)) + if (get_user(data, (u_short __user *)userPtr)) return -EFAULT; + userPtr += 2; data ^= 0x8000; userCount -= 2; bal += hSpeed; @@ -634,8 +647,9 @@ static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount, if (bal < 0) { if (userCount < 4) break; - if (get_user(data, ((u_int *)userPtr)++)) + if (get_user(data, (u_int __user *)userPtr)) return -EFAULT; + userPtr += 4; data ^= 0x80008000; userCount -= 4; bal += hSpeed; @@ -653,7 +667,7 @@ static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -671,8 +685,9 @@ static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount, if (bal < 0) { if (userCount < 2) break; - if (get_user(data, ((u_short *)userPtr)++)) + if (get_user(data, (u_short __user *)userPtr)) return -EFAULT; + userPtr += 2; data = le2be16(data); userCount -= 2; bal += hSpeed; @@ -690,8 +705,9 @@ static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount, if (bal < 0) { if (userCount < 4) break; - if (get_user(data, ((u_int *)userPtr)++)) + if (get_user(data, (u_int __user *)userPtr)) return -EFAULT; + userPtr += 4; data = le2be16dbl(data); userCount -= 4; bal += hSpeed; @@ -709,7 +725,7 @@ static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount, } -static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount, +static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -727,8 +743,9 @@ static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount, if (bal < 0) { if (userCount < 2) break; - if (get_user(data, ((u_short *)userPtr)++)) + if (get_user(data, (u_short __user *)userPtr)) return -EFAULT; + userPtr += 2; data = le2be16(data) ^ 0x8000; userCount -= 2; bal += hSpeed; @@ -746,8 +763,9 @@ static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount, if (bal < 0) { if (userCount < 4) break; - if (get_user(data, ((u_int *)userPtr)++)) + if (get_user(data, (u_int __user *)userPtr)) return -EFAULT; + userPtr += 4; data = le2be16dbl(data) ^ 0x80008000; userCount -= 4; bal += hSpeed; diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c index d59f60b2641..494070a3f87 100644 --- a/sound/oss/dmasound/dmasound_paula.c +++ b/sound/oss/dmasound/dmasound_paula.c @@ -34,6 +34,7 @@ #define DMASOUND_PAULA_REVISION 0 #define DMASOUND_PAULA_EDITION 4 +#define custom amiga_custom /* * The minimum period for audio depends on htotal (for OCS/ECS/AGA) * (Imported from arch/m68k/amiga/amisound.c) @@ -156,7 +157,7 @@ static int AmiStateInfo(char *buffer, size_t space); * Native format */ -static ssize_t ami_ct_s8(const u_char *userPtr, size_t userCount, +static ssize_t ami_ct_s8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { ssize_t count, used; @@ -189,7 +190,7 @@ static ssize_t ami_ct_s8(const u_char *userPtr, size_t userCount, */ #define GENERATE_AMI_CT8(funcname, convsample) \ -static ssize_t funcname(const u_char *userPtr, size_t userCount, \ +static ssize_t funcname(const u_char __user *userPtr, size_t userCount, \ u_char frame[], ssize_t *frameUsed, \ ssize_t frameLeft) \ { \ @@ -240,10 +241,11 @@ GENERATE_AMI_CT8(ami_ct_u8, AMI_CT_U8) */ #define GENERATE_AMI_CT_16(funcname, convsample) \ -static ssize_t funcname(const u_char *userPtr, size_t userCount, \ +static ssize_t funcname(const u_char __user *userPtr, size_t userCount, \ u_char frame[], ssize_t *frameUsed, \ ssize_t frameLeft) \ { \ + const u_short __user *ptr = (const u_short __user *)userPtr; \ ssize_t count, used; \ u_short data; \ \ @@ -253,7 +255,7 @@ static ssize_t funcname(const u_char *userPtr, size_t userCount, \ count = min_t(size_t, userCount, frameLeft)>>1 & ~1; \ used = count*2; \ while (count > 0) { \ - if (get_user(data, ((u_short *)userPtr)++)) \ + if (get_user(data, ptr++)) \ return -EFAULT; \ data = convsample(data); \ *high++ = data>>8; \ @@ -268,12 +270,12 @@ static ssize_t funcname(const u_char *userPtr, size_t userCount, \ count = min_t(size_t, userCount, frameLeft)>>2 & ~1; \ used = count*4; \ while (count > 0) { \ - if (get_user(data, ((u_short *)userPtr)++)) \ + if (get_user(data, ptr++)) \ return -EFAULT; \ data = convsample(data); \ *lefth++ = data>>8; \ *leftl++ = (data>>2) & 0x3f; \ - if (get_user(data, ((u_short *)userPtr)++)) \ + if (get_user(data, ptr++)) \ return -EFAULT; \ data = convsample(data); \ *righth++ = data>>8; \ diff --git a/sound/oss/dmasound/dmasound_q40.c b/sound/oss/dmasound/dmasound_q40.c index 1ddaa6284b0..e2081f32b0c 100644 --- a/sound/oss/dmasound/dmasound_q40.c +++ b/sound/oss/dmasound/dmasound_q40.c @@ -58,7 +58,7 @@ static void Q40Interrupt(void); /* userCount, frameUsed, frameLeft == byte counts */ -static ssize_t q40_ct_law(const u_char *userPtr, size_t userCount, +static ssize_t q40_ct_law(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -79,7 +79,7 @@ static ssize_t q40_ct_law(const u_char *userPtr, size_t userCount, } -static ssize_t q40_ct_s8(const u_char *userPtr, size_t userCount, +static ssize_t q40_ct_s8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -98,7 +98,7 @@ static ssize_t q40_ct_s8(const u_char *userPtr, size_t userCount, return used; } -static ssize_t q40_ct_u8(const u_char *userPtr, size_t userCount, +static ssize_t q40_ct_u8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -114,7 +114,7 @@ static ssize_t q40_ct_u8(const u_char *userPtr, size_t userCount, /* a bit too complicated to optimise right now ..*/ -static ssize_t q40_ctx_law(const u_char *userPtr, size_t userCount, +static ssize_t q40_ctx_law(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -152,7 +152,7 @@ static ssize_t q40_ctx_law(const u_char *userPtr, size_t userCount, } -static ssize_t q40_ctx_s8(const u_char *userPtr, size_t userCount, +static ssize_t q40_ctx_s8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -189,7 +189,7 @@ static ssize_t q40_ctx_s8(const u_char *userPtr, size_t userCount, } -static ssize_t q40_ctx_u8(const u_char *userPtr, size_t userCount, +static ssize_t q40_ctx_u8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -224,7 +224,7 @@ static ssize_t q40_ctx_u8(const u_char *userPtr, size_t userCount, } /* compressing versions */ -static ssize_t q40_ctc_law(const u_char *userPtr, size_t userCount, +static ssize_t q40_ctc_law(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -265,7 +265,7 @@ static ssize_t q40_ctc_law(const u_char *userPtr, size_t userCount, } -static ssize_t q40_ctc_s8(const u_char *userPtr, size_t userCount, +static ssize_t q40_ctc_s8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { @@ -304,7 +304,7 @@ static ssize_t q40_ctc_s8(const u_char *userPtr, size_t userCount, } -static ssize_t q40_ctc_u8(const u_char *userPtr, size_t userCount, +static ssize_t q40_ctc_u8(const u_char __user *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { diff --git a/sound/oss/dmasound/trans_16.c b/sound/oss/dmasound/trans_16.c index 23562e94780..ca973ac2a30 100644 --- a/sound/oss/dmasound/trans_16.c +++ b/sound/oss/dmasound/trans_16.c @@ -17,6 +17,7 @@ #include <asm/uaccess.h> #include "dmasound.h" +extern int expand_bal; /* Balance factor for expanding (not volume!) */ static short dmasound_alaw2dma16[] ; static short dmasound_ulaw2dma16[] ; |