diff --git a/[refs] b/[refs] index 50ed10e73ba3..9381335fdbf2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 422e6c4bc4b48c15b3cb57a1ca71431abfc57e54 +refs/heads/master: 997772884036e6e121de39322179989154437d9f diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index f1bc3dc6b369..560ecce38ff5 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -4292,7 +4292,10 @@ S: Maintained F: net/sched/sch_netem.c NETERION 10GbE DRIVERS (s2io/vxge) -M: Jon Mason +M: Ramkrishna Vepa +M: Sivakumar Subramani +M: Sreenivasa Honnur +M: Jon Mason L: netdev@vger.kernel.org W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous diff --git a/trunk/Makefile b/trunk/Makefile index d6592b63c8cb..504f788773e5 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 38 -EXTRAVERSION = +EXTRAVERSION = -rc8 NAME = Flesh-Eating Bats with Fangs # *DOCUMENTATION* diff --git a/trunk/arch/alpha/kernel/osf_sys.c b/trunk/arch/alpha/kernel/osf_sys.c index 376f22130791..fe698b5045e9 100644 --- a/trunk/arch/alpha/kernel/osf_sys.c +++ b/trunk/arch/alpha/kernel/osf_sys.c @@ -230,24 +230,44 @@ linux_to_osf_statfs(struct kstatfs *linux_stat, struct osf_statfs __user *osf_st return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0; } -SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname, - struct osf_statfs __user *, buffer, unsigned long, bufsiz) +static int +do_osf_statfs(struct path *path, struct osf_statfs __user *buffer, + unsigned long bufsiz) { struct kstatfs linux_stat; - int error = user_statfs(pathname, &linux_stat); + int error = vfs_statfs(path, &linux_stat); if (!error) error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); return error; } +SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname, + struct osf_statfs __user *, buffer, unsigned long, bufsiz) +{ + struct path path; + int retval; + + retval = user_path(pathname, &path); + if (!retval) { + retval = do_osf_statfs(&path, buffer, bufsiz); + path_put(&path); + } + return retval; +} + SYSCALL_DEFINE3(osf_fstatfs, unsigned long, fd, struct osf_statfs __user *, buffer, unsigned long, bufsiz) { - struct kstatfs linux_stat; - int error = fd_statfs(fd, &linux_stat); - if (!error) - error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); - return error; + struct file *file; + int retval; + + retval = -EBADF; + file = fget(fd); + if (file) { + retval = do_osf_statfs(&file->f_path, buffer, bufsiz); + fput(file); + } + return retval; } /* diff --git a/trunk/arch/alpha/kernel/sys_titan.c b/trunk/arch/alpha/kernel/sys_titan.c index 8c13a0c77830..f6c108a3d673 100644 --- a/trunk/arch/alpha/kernel/sys_titan.c +++ b/trunk/arch/alpha/kernel/sys_titan.c @@ -149,7 +149,6 @@ static int titan_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity, bool force) { - unsigned int irq = d->irq; spin_lock(&titan_irq_lock); titan_cpu_set_irq_affinity(irq - 16, *affinity); titan_update_irq_hw(titan_cached_irq_mask); diff --git a/trunk/arch/ia64/include/asm/xen/hypercall.h b/trunk/arch/ia64/include/asm/xen/hypercall.h index ed28bcd5bb85..96fc62366aa4 100644 --- a/trunk/arch/ia64/include/asm/xen/hypercall.h +++ b/trunk/arch/ia64/include/asm/xen/hypercall.h @@ -107,7 +107,7 @@ extern unsigned long __hypercall(unsigned long a1, unsigned long a2, static inline int xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg) { - return _hypercall2(int, sched_op, cmd, arg); + return _hypercall2(int, sched_op_new, cmd, arg); } static inline long diff --git a/trunk/arch/ia64/xen/suspend.c b/trunk/arch/ia64/xen/suspend.c index 419c8620945a..fd66b048c6fa 100644 --- a/trunk/arch/ia64/xen/suspend.c +++ b/trunk/arch/ia64/xen/suspend.c @@ -37,14 +37,19 @@ xen_mm_unpin_all(void) /* nothing */ } +void xen_pre_device_suspend(void) +{ + /* nothing */ +} + void -xen_arch_pre_suspend() +xen_pre_suspend() { /* nothing */ } void -xen_arch_post_suspend(int suspend_cancelled) +xen_post_suspend(int suspend_cancelled) { if (suspend_cancelled) return; diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index d88983516e26..f5ecc0566bc2 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -4,7 +4,6 @@ config MIPS select HAVE_GENERIC_DMA_COHERENT select HAVE_IDE select HAVE_OPROFILE - select HAVE_IRQ_WORK select HAVE_PERF_EVENTS select PERF_USE_VMALLOC select HAVE_ARCH_KGDB @@ -209,7 +208,6 @@ config MACH_JZ4740 select ARCH_REQUIRE_GPIOLIB select SYS_HAS_EARLY_PRINTK select HAVE_PWM - select HAVE_CLK config LASAT bool "LASAT Networks platforms" @@ -335,8 +333,6 @@ config PNX8550_STB810 config PMC_MSP bool "PMC-Sierra MSP chipsets" depends on EXPERIMENTAL - select CEVT_R4K - select CSRC_R4K select DMA_NONCOHERENT select SWAP_IO_SPACE select NO_EXCEPT_FILL diff --git a/trunk/arch/mips/alchemy/mtx-1/board_setup.c b/trunk/arch/mips/alchemy/mtx-1/board_setup.c index 40b84b991191..6398fa95905c 100644 --- a/trunk/arch/mips/alchemy/mtx-1/board_setup.c +++ b/trunk/arch/mips/alchemy/mtx-1/board_setup.c @@ -54,8 +54,8 @@ int mtx1_pci_idsel(unsigned int devsel, int assert); static void mtx1_reset(char *c) { - /* Jump to the reset vector */ - __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); + /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ + au_writel(0x00000000, 0xAE00001C); } static void mtx1_power_off(void) diff --git a/trunk/arch/mips/alchemy/mtx-1/platform.c b/trunk/arch/mips/alchemy/mtx-1/platform.c index 956f946218c5..e30e42add697 100644 --- a/trunk/arch/mips/alchemy/mtx-1/platform.c +++ b/trunk/arch/mips/alchemy/mtx-1/platform.c @@ -28,8 +28,6 @@ #include #include -#include - static struct gpio_keys_button mtx1_gpio_button[] = { { .gpio = 207, @@ -142,17 +140,10 @@ static struct __initdata platform_device * mtx1_devs[] = { &mtx1_mtd, }; -static struct au1000_eth_platform_data mtx1_au1000_eth0_pdata = { - .phy_search_highest_addr = 1, - .phy1_search_mac0 = 1, -}; - static int __init mtx1_register_devices(void) { int rc; - au1xxx_override_eth_cfg(0, &mtx1_au1000_eth0_pdata); - rc = gpio_request(mtx1_gpio_button[0].gpio, mtx1_gpio_button[0].desc); if (rc < 0) { diff --git a/trunk/arch/mips/alchemy/xxs1500/board_setup.c b/trunk/arch/mips/alchemy/xxs1500/board_setup.c index 80c521e5290d..b43c918925d3 100644 --- a/trunk/arch/mips/alchemy/xxs1500/board_setup.c +++ b/trunk/arch/mips/alchemy/xxs1500/board_setup.c @@ -36,8 +36,8 @@ static void xxs1500_reset(char *c) { - /* Jump to the reset vector */ - __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); + /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ + au_writel(0x00000000, 0xAE00001C); } static void xxs1500_power_off(void) diff --git a/trunk/arch/mips/include/asm/perf_event.h b/trunk/arch/mips/include/asm/perf_event.h index d0c77496c728..e00007cf8162 100644 --- a/trunk/arch/mips/include/asm/perf_event.h +++ b/trunk/arch/mips/include/asm/perf_event.h @@ -11,5 +11,15 @@ #ifndef __MIPS_PERF_EVENT_H__ #define __MIPS_PERF_EVENT_H__ -/* Leave it empty here. The file is required by linux/perf_event.h */ + +/* + * MIPS performance counters do not raise NMI upon overflow, a regular + * interrupt will be signaled. Hence we can do the pending perf event + * work at the tail of the irq handler. + */ +static inline void +set_perf_event_pending(void) +{ +} + #endif /* __MIPS_PERF_EVENT_H__ */ diff --git a/trunk/arch/mips/kernel/ftrace.c b/trunk/arch/mips/kernel/ftrace.c index 94ca2b018af7..5a84a1f11231 100644 --- a/trunk/arch/mips/kernel/ftrace.c +++ b/trunk/arch/mips/kernel/ftrace.c @@ -17,13 +17,29 @@ #include #include -#include +/* + * If the Instruction Pointer is in module space (0xc0000000), return true; + * otherwise, it is in kernel space (0x80000000), return false. + * + * FIXME: This will not work when the kernel space and module space are the + * same. If they are the same, we need to modify scripts/recordmcount.pl, + * ftrace_make_nop/call() and the other related parts to ensure the + * enabling/disabling of the calling site to _mcount is right for both kernel + * and module. + */ + +static inline int in_module(unsigned long ip) +{ + return ip & 0x40000000; +} #ifdef CONFIG_DYNAMIC_FTRACE #define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */ #define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */ +#define INSN_B_1F_4 0x10000004 /* b 1f; offset = 4 */ +#define INSN_B_1F_5 0x10000005 /* b 1f; offset = 5 */ #define INSN_NOP 0x00000000 /* nop */ #define INSN_JAL(addr) \ ((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK))) @@ -53,20 +69,6 @@ static inline void ftrace_dyn_arch_init_insns(void) #endif } -/* - * Check if the address is in kernel space - * - * Clone core_kernel_text() from kernel/extable.c, but doesn't call - * init_kernel_text() for Ftrace doesn't trace functions in init sections. - */ -static inline int in_kernel_space(unsigned long ip) -{ - if (ip >= (unsigned long)_stext && - ip <= (unsigned long)_etext) - return 1; - return 0; -} - static int ftrace_modify_code(unsigned long ip, unsigned int new_code) { int faulted; @@ -82,42 +84,6 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code) return 0; } -/* - * The details about the calling site of mcount on MIPS - * - * 1. For kernel: - * - * move at, ra - * jal _mcount --> nop - * - * 2. For modules: - * - * 2.1 For KBUILD_MCOUNT_RA_ADDRESS and CONFIG_32BIT - * - * lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) - * addiu v1, v1, low_16bit_of_mcount - * move at, ra - * move $12, ra_address - * jalr v1 - * sub sp, sp, 8 - * 1: offset = 5 instructions - * 2.2 For the Other situations - * - * lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) - * addiu v1, v1, low_16bit_of_mcount - * move at, ra - * jalr v1 - * nop | move $12, ra_address | sub sp, sp, 8 - * 1: offset = 4 instructions - */ - -#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) -#define MCOUNT_OFFSET_INSNS 5 -#else -#define MCOUNT_OFFSET_INSNS 4 -#endif -#define INSN_B_1F (0x10000000 | MCOUNT_OFFSET_INSNS) - int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { @@ -125,11 +91,39 @@ int ftrace_make_nop(struct module *mod, unsigned long ip = rec->ip; /* - * If ip is in kernel space, no long call, otherwise, long call is - * needed. + * We have compiled module with -mlong-calls, but compiled the kernel + * without it, we need to cope with them respectively. */ - new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F; - + if (in_module(ip)) { +#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) + /* + * lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) + * addiu v1, v1, low_16bit_of_mcount + * move at, ra + * move $12, ra_address + * jalr v1 + * sub sp, sp, 8 + * 1: offset = 5 instructions + */ + new = INSN_B_1F_5; +#else + /* + * lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) + * addiu v1, v1, low_16bit_of_mcount + * move at, ra + * jalr v1 + * nop | move $12, ra_address | sub sp, sp, 8 + * 1: offset = 4 instructions + */ + new = INSN_B_1F_4; +#endif + } else { + /* + * move at, ra + * jal _mcount --> nop + */ + new = INSN_NOP; + } return ftrace_modify_code(ip, new); } @@ -138,8 +132,8 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) unsigned int new; unsigned long ip = rec->ip; - new = in_kernel_space(ip) ? insn_jal_ftrace_caller : - insn_lui_v1_hi16_mcount; + /* ip, module: 0xc0000000, kernel: 0x80000000 */ + new = in_module(ip) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller; return ftrace_modify_code(ip, new); } @@ -196,25 +190,29 @@ int ftrace_disable_ftrace_graph_caller(void) #define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ #define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ -unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long - old_parent_ra, unsigned long parent_ra_addr, unsigned long fp) +unsigned long ftrace_get_parent_addr(unsigned long self_addr, + unsigned long parent, + unsigned long parent_addr, + unsigned long fp) { - unsigned long sp, ip, tmp; + unsigned long sp, ip, ra; unsigned int code; int faulted; /* - * For module, move the ip from the return address after the - * instruction "lui v1, hi_16bit_of_mcount"(offset is 24), but for - * kernel, move after the instruction "move ra, at"(offset is 16) + * For module, move the ip from calling site of mcount to the + * instruction "lui v1, hi_16bit_of_mcount"(offset is 20), but for + * kernel, move to the instruction "move ra, at"(offset is 12) */ - ip = self_ra - (in_kernel_space(self_ra) ? 16 : 24); + ip = self_addr - (in_module(self_addr) ? 20 : 12); /* * search the text until finding the non-store instruction or "s{d,w} * ra, offset(sp)" instruction */ do { + ip -= 4; + /* get the code at "ip": code = *(unsigned int *)ip; */ safe_load_code(code, ip, faulted); @@ -226,20 +224,18 @@ unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long * store the ra on the stack */ if ((code & S_R_SP) != S_R_SP) - return parent_ra_addr; + return parent_addr; - /* Move to the next instruction */ - ip -= 4; - } while ((code & S_RA_SP) != S_RA_SP); + } while (((code & S_RA_SP) != S_RA_SP)); sp = fp + (code & OFFSET_MASK); - /* tmp = *(unsigned long *)sp; */ - safe_load_stack(tmp, sp, faulted); + /* ra = *(unsigned long *)sp; */ + safe_load_stack(ra, sp, faulted); if (unlikely(faulted)) return 0; - if (tmp == old_parent_ra) + if (ra == parent) return sp; return 0; } @@ -250,21 +246,21 @@ unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long * Hook the return address and push it in the stack of return addrs * in current thread info. */ -void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra, +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, unsigned long fp) { - unsigned long old_parent_ra; + unsigned long old; struct ftrace_graph_ent trace; unsigned long return_hooker = (unsigned long) &return_to_handler; - int faulted, insns; + int faulted; if (unlikely(atomic_read(¤t->tracing_graph_pause))) return; /* - * "parent_ra_addr" is the stack address saved the return address of - * the caller of _mcount. + * "parent" is the stack address saved the return address of the caller + * of _mcount. * * if the gcc < 4.5, a leaf function does not save the return address * in the stack address, so, we "emulate" one in _mcount's stack space, @@ -279,44 +275,37 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra, * do it in ftrace_graph_caller of mcount.S. */ - /* old_parent_ra = *parent_ra_addr; */ - safe_load_stack(old_parent_ra, parent_ra_addr, faulted); + /* old = *parent; */ + safe_load_stack(old, parent, faulted); if (unlikely(faulted)) goto out; #ifndef KBUILD_MCOUNT_RA_ADDRESS - parent_ra_addr = (unsigned long *)ftrace_get_parent_ra_addr(self_ra, - old_parent_ra, (unsigned long)parent_ra_addr, fp); + parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old, + (unsigned long)parent, fp); /* * If fails when getting the stack address of the non-leaf function's * ra, stop function graph tracer and return */ - if (parent_ra_addr == 0) + if (parent == 0) goto out; #endif - /* *parent_ra_addr = return_hooker; */ - safe_store_stack(return_hooker, parent_ra_addr, faulted); + /* *parent = return_hooker; */ + safe_store_stack(return_hooker, parent, faulted); if (unlikely(faulted)) goto out; - if (ftrace_push_return_trace(old_parent_ra, self_ra, &trace.depth, fp) - == -EBUSY) { - *parent_ra_addr = old_parent_ra; + if (ftrace_push_return_trace(old, self_addr, &trace.depth, fp) == + -EBUSY) { + *parent = old; return; } - /* - * Get the recorded ip of the current mcount calling site in the - * __mcount_loc section, which will be used to filter the function - * entries configured through the tracing/set_graph_function interface. - */ - - insns = in_kernel_space(self_ra) ? 2 : MCOUNT_OFFSET_INSNS + 1; - trace.func = self_ra - (MCOUNT_INSN_SIZE * insns); + trace.func = self_addr; /* Only trace if the calling function expects to */ if (!ftrace_graph_entry(&trace)) { current->curr_ret_stack--; - *parent_ra_addr = old_parent_ra; + *parent = old; } return; out: diff --git a/trunk/arch/mips/kernel/perf_event.c b/trunk/arch/mips/kernel/perf_event.c index a8244854d3dc..2b7f3f703b83 100644 --- a/trunk/arch/mips/kernel/perf_event.c +++ b/trunk/arch/mips/kernel/perf_event.c @@ -161,6 +161,41 @@ mipspmu_event_set_period(struct perf_event *event, return ret; } +static int mipspmu_enable(struct perf_event *event) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct hw_perf_event *hwc = &event->hw; + int idx; + int err = 0; + + /* To look for a free counter for this event. */ + idx = mipspmu->alloc_counter(cpuc, hwc); + if (idx < 0) { + err = idx; + goto out; + } + + /* + * If there is an event in the counter we are going to use then + * make sure it is disabled. + */ + event->hw.idx = idx; + mipspmu->disable_event(idx); + cpuc->events[idx] = event; + + /* Set the period for the event. */ + mipspmu_event_set_period(event, hwc, idx); + + /* Enable the event. */ + mipspmu->enable_event(hwc, idx); + + /* Propagate our changes to the userspace mapping. */ + perf_event_update_userpage(event); + +out: + return err; +} + static void mipspmu_event_update(struct perf_event *event, struct hw_perf_event *hwc, int idx) @@ -169,7 +204,7 @@ static void mipspmu_event_update(struct perf_event *event, unsigned long flags; int shift = 64 - TOTAL_BITS; s64 prev_raw_count, new_raw_count; - u64 delta; + s64 delta; again: prev_raw_count = local64_read(&hwc->prev_count); @@ -196,90 +231,32 @@ static void mipspmu_event_update(struct perf_event *event, return; } -static void mipspmu_start(struct perf_event *event, int flags) -{ - struct hw_perf_event *hwc = &event->hw; - - if (!mipspmu) - return; - - if (flags & PERF_EF_RELOAD) - WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); - - hwc->state = 0; - - /* Set the period for the event. */ - mipspmu_event_set_period(event, hwc, hwc->idx); - - /* Enable the event. */ - mipspmu->enable_event(hwc, hwc->idx); -} - -static void mipspmu_stop(struct perf_event *event, int flags) -{ - struct hw_perf_event *hwc = &event->hw; - - if (!mipspmu) - return; - - if (!(hwc->state & PERF_HES_STOPPED)) { - /* We are working on a local event. */ - mipspmu->disable_event(hwc->idx); - barrier(); - mipspmu_event_update(event, hwc, hwc->idx); - hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; - } -} - -static int mipspmu_add(struct perf_event *event, int flags) +static void mipspmu_disable(struct perf_event *event) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; - int idx; - int err = 0; + int idx = hwc->idx; - perf_pmu_disable(event->pmu); - /* To look for a free counter for this event. */ - idx = mipspmu->alloc_counter(cpuc, hwc); - if (idx < 0) { - err = idx; - goto out; - } + WARN_ON(idx < 0 || idx >= mipspmu->num_counters); - /* - * If there is an event in the counter we are going to use then - * make sure it is disabled. - */ - event->hw.idx = idx; + /* We are working on a local event. */ mipspmu->disable_event(idx); - cpuc->events[idx] = event; - hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; - if (flags & PERF_EF_START) - mipspmu_start(event, PERF_EF_RELOAD); + barrier(); - /* Propagate our changes to the userspace mapping. */ - perf_event_update_userpage(event); + mipspmu_event_update(event, hwc, idx); + cpuc->events[idx] = NULL; + clear_bit(idx, cpuc->used_mask); -out: - perf_pmu_enable(event->pmu); - return err; + perf_event_update_userpage(event); } -static void mipspmu_del(struct perf_event *event, int flags) +static void mipspmu_unthrottle(struct perf_event *event) { - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; - int idx = hwc->idx; - WARN_ON(idx < 0 || idx >= mipspmu->num_counters); - - mipspmu_stop(event, PERF_EF_UPDATE); - cpuc->events[idx] = NULL; - clear_bit(idx, cpuc->used_mask); - - perf_event_update_userpage(event); + mipspmu->enable_event(hwc, hwc->idx); } static void mipspmu_read(struct perf_event *event) @@ -293,17 +270,12 @@ static void mipspmu_read(struct perf_event *event) mipspmu_event_update(event, hwc, hwc->idx); } -static void mipspmu_enable(struct pmu *pmu) -{ - if (mipspmu) - mipspmu->start(); -} - -static void mipspmu_disable(struct pmu *pmu) -{ - if (mipspmu) - mipspmu->stop(); -} +static struct pmu pmu = { + .enable = mipspmu_enable, + .disable = mipspmu_disable, + .unthrottle = mipspmu_unthrottle, + .read = mipspmu_read, +}; static atomic_t active_events = ATOMIC_INIT(0); static DEFINE_MUTEX(pmu_reserve_mutex); @@ -346,82 +318,6 @@ static void mipspmu_free_irq(void) perf_irq = save_perf_irq; } -/* - * mipsxx/rm9000/loongson2 have different performance counters, they have - * specific low-level init routines. - */ -static void reset_counters(void *arg); -static int __hw_perf_event_init(struct perf_event *event); - -static void hw_perf_event_destroy(struct perf_event *event) -{ - if (atomic_dec_and_mutex_lock(&active_events, - &pmu_reserve_mutex)) { - /* - * We must not call the destroy function with interrupts - * disabled. - */ - on_each_cpu(reset_counters, - (void *)(long)mipspmu->num_counters, 1); - mipspmu_free_irq(); - mutex_unlock(&pmu_reserve_mutex); - } -} - -static int mipspmu_event_init(struct perf_event *event) -{ - int err = 0; - - switch (event->attr.type) { - case PERF_TYPE_RAW: - case PERF_TYPE_HARDWARE: - case PERF_TYPE_HW_CACHE: - break; - - default: - return -ENOENT; - } - - if (!mipspmu || event->cpu >= nr_cpumask_bits || - (event->cpu >= 0 && !cpu_online(event->cpu))) - return -ENODEV; - - if (!atomic_inc_not_zero(&active_events)) { - if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) { - atomic_dec(&active_events); - return -ENOSPC; - } - - mutex_lock(&pmu_reserve_mutex); - if (atomic_read(&active_events) == 0) - err = mipspmu_get_irq(); - - if (!err) - atomic_inc(&active_events); - mutex_unlock(&pmu_reserve_mutex); - } - - if (err) - return err; - - err = __hw_perf_event_init(event); - if (err) - hw_perf_event_destroy(event); - - return err; -} - -static struct pmu pmu = { - .pmu_enable = mipspmu_enable, - .pmu_disable = mipspmu_disable, - .event_init = mipspmu_event_init, - .add = mipspmu_add, - .del = mipspmu_del, - .start = mipspmu_start, - .stop = mipspmu_stop, - .read = mipspmu_read, -}; - static inline unsigned int mipspmu_perf_event_encode(const struct mips_perf_event *pev) { @@ -486,9 +382,8 @@ static int validate_event(struct cpu_hw_events *cpuc, { struct hw_perf_event fake_hwc = event->hw; - /* Allow mixed event group. So return 1 to pass validation. */ - if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF) - return 1; + if (event->pmu && event->pmu != &pmu) + return 0; return mipspmu->alloc_counter(cpuc, &fake_hwc) >= 0; } @@ -514,6 +409,73 @@ static int validate_group(struct perf_event *event) return 0; } +/* + * mipsxx/rm9000/loongson2 have different performance counters, they have + * specific low-level init routines. + */ +static void reset_counters(void *arg); +static int __hw_perf_event_init(struct perf_event *event); + +static void hw_perf_event_destroy(struct perf_event *event) +{ + if (atomic_dec_and_mutex_lock(&active_events, + &pmu_reserve_mutex)) { + /* + * We must not call the destroy function with interrupts + * disabled. + */ + on_each_cpu(reset_counters, + (void *)(long)mipspmu->num_counters, 1); + mipspmu_free_irq(); + mutex_unlock(&pmu_reserve_mutex); + } +} + +const struct pmu *hw_perf_event_init(struct perf_event *event) +{ + int err = 0; + + if (!mipspmu || event->cpu >= nr_cpumask_bits || + (event->cpu >= 0 && !cpu_online(event->cpu))) + return ERR_PTR(-ENODEV); + + if (!atomic_inc_not_zero(&active_events)) { + if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) { + atomic_dec(&active_events); + return ERR_PTR(-ENOSPC); + } + + mutex_lock(&pmu_reserve_mutex); + if (atomic_read(&active_events) == 0) + err = mipspmu_get_irq(); + + if (!err) + atomic_inc(&active_events); + mutex_unlock(&pmu_reserve_mutex); + } + + if (err) + return ERR_PTR(err); + + err = __hw_perf_event_init(event); + if (err) + hw_perf_event_destroy(event); + + return err ? ERR_PTR(err) : &pmu; +} + +void hw_perf_enable(void) +{ + if (mipspmu) + mipspmu->start(); +} + +void hw_perf_disable(void) +{ + if (mipspmu) + mipspmu->stop(); +} + /* This is needed by specific irq handlers in perf_event_*.c */ static void handle_associated_event(struct cpu_hw_events *cpuc, @@ -534,13 +496,21 @@ handle_associated_event(struct cpu_hw_events *cpuc, #include "perf_event_mipsxx.c" /* Callchain handling code. */ +static inline void +callchain_store(struct perf_callchain_entry *entry, + u64 ip) +{ + if (entry->nr < PERF_MAX_STACK_DEPTH) + entry->ip[entry->nr++] = ip; +} /* * Leave userspace callchain empty for now. When we find a way to trace * the user stack callchains, we add here. */ -void perf_callchain_user(struct perf_callchain_entry *entry, - struct pt_regs *regs) +static void +perf_callchain_user(struct pt_regs *regs, + struct perf_callchain_entry *entry) { } @@ -553,21 +523,23 @@ static void save_raw_perf_callchain(struct perf_callchain_entry *entry, while (!kstack_end(sp)) { addr = *sp++; if (__kernel_text_address(addr)) { - perf_callchain_store(entry, addr); + callchain_store(entry, addr); if (entry->nr >= PERF_MAX_STACK_DEPTH) break; } } } -void perf_callchain_kernel(struct perf_callchain_entry *entry, - struct pt_regs *regs) +static void +perf_callchain_kernel(struct pt_regs *regs, + struct perf_callchain_entry *entry) { unsigned long sp = regs->regs[29]; #ifdef CONFIG_KALLSYMS unsigned long ra = regs->regs[31]; unsigned long pc = regs->cp0_epc; + callchain_store(entry, PERF_CONTEXT_KERNEL); if (raw_show_trace || !__kernel_text_address(pc)) { unsigned long stack_page = (unsigned long)task_stack_page(current); @@ -577,12 +549,53 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry, return; } do { - perf_callchain_store(entry, pc); + callchain_store(entry, pc); if (entry->nr >= PERF_MAX_STACK_DEPTH) break; pc = unwind_stack(current, &sp, pc, &ra); } while (pc); #else + callchain_store(entry, PERF_CONTEXT_KERNEL); save_raw_perf_callchain(entry, sp); #endif } + +static void +perf_do_callchain(struct pt_regs *regs, + struct perf_callchain_entry *entry) +{ + int is_user; + + if (!regs) + return; + + is_user = user_mode(regs); + + if (!current || !current->pid) + return; + + if (is_user && current->state != TASK_RUNNING) + return; + + if (!is_user) { + perf_callchain_kernel(regs, entry); + if (current->mm) + regs = task_pt_regs(current); + else + regs = NULL; + } + if (regs) + perf_callchain_user(regs, entry); +} + +static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry); + +struct perf_callchain_entry * +perf_callchain(struct pt_regs *regs) +{ + struct perf_callchain_entry *entry = &__get_cpu_var(pmc_irq_entry); + + entry->nr = 0; + perf_do_callchain(regs, entry); + return entry; +} diff --git a/trunk/arch/mips/kernel/perf_event_mipsxx.c b/trunk/arch/mips/kernel/perf_event_mipsxx.c index d9a7db78ed62..183e0d226669 100644 --- a/trunk/arch/mips/kernel/perf_event_mipsxx.c +++ b/trunk/arch/mips/kernel/perf_event_mipsxx.c @@ -696,7 +696,7 @@ static int mipsxx_pmu_handle_shared_irq(void) * interrupt, not NMI. */ if (handled == IRQ_HANDLED) - irq_work_run(); + perf_event_do_pending(); #ifdef CONFIG_MIPS_MT_SMP read_unlock(&pmuint_rwlock); @@ -1045,8 +1045,6 @@ init_hw_perf_events(void) "CPU, irq %d%s\n", mipspmu->name, counters, irq, irq < 0 ? " (share with timer interrupt)" : ""); - perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); - return 0; } early_initcall(init_hw_perf_events); diff --git a/trunk/arch/mips/kernel/signal.c b/trunk/arch/mips/kernel/signal.c index dbbe0ce48d89..5922342bca39 100644 --- a/trunk/arch/mips/kernel/signal.c +++ b/trunk/arch/mips/kernel/signal.c @@ -84,7 +84,7 @@ static int protected_save_fp_context(struct sigcontext __user *sc) static int protected_restore_fp_context(struct sigcontext __user *sc) { - int err, tmp __maybe_unused; + int err, tmp; while (1) { lock_fpu_owner(); own_fpu_inatomic(0); diff --git a/trunk/arch/mips/kernel/signal32.c b/trunk/arch/mips/kernel/signal32.c index aae986613795..a0ed0e052b2e 100644 --- a/trunk/arch/mips/kernel/signal32.c +++ b/trunk/arch/mips/kernel/signal32.c @@ -115,7 +115,7 @@ static int protected_save_fp_context32(struct sigcontext32 __user *sc) static int protected_restore_fp_context32(struct sigcontext32 __user *sc) { - int err, tmp __maybe_unused; + int err, tmp; while (1) { lock_fpu_owner(); own_fpu_inatomic(0); diff --git a/trunk/arch/mips/kernel/smp.c b/trunk/arch/mips/kernel/smp.c index 32a256101082..383aeb95cb49 100644 --- a/trunk/arch/mips/kernel/smp.c +++ b/trunk/arch/mips/kernel/smp.c @@ -193,22 +193,6 @@ void __devinit smp_prepare_boot_cpu(void) */ static struct task_struct *cpu_idle_thread[NR_CPUS]; -struct create_idle { - struct work_struct work; - struct task_struct *idle; - struct completion done; - int cpu; -}; - -static void __cpuinit do_fork_idle(struct work_struct *work) -{ - struct create_idle *c_idle = - container_of(work, struct create_idle, work); - - c_idle->idle = fork_idle(c_idle->cpu); - complete(&c_idle->done); -} - int __cpuinit __cpu_up(unsigned int cpu) { struct task_struct *idle; @@ -219,19 +203,8 @@ int __cpuinit __cpu_up(unsigned int cpu) * Linux can schedule processes on this slave. */ if (!cpu_idle_thread[cpu]) { - /* - * Schedule work item to avoid forking user task - * Ported from arch/x86/kernel/smpboot.c - */ - struct create_idle c_idle = { - .cpu = cpu, - .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), - }; - - INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle); - schedule_work(&c_idle.work); - wait_for_completion(&c_idle.done); - idle = cpu_idle_thread[cpu] = c_idle.idle; + idle = fork_idle(cpu); + cpu_idle_thread[cpu] = idle; if (IS_ERR(idle)) panic(KERN_ERR "Fork failed for CPU %d", cpu); diff --git a/trunk/arch/mips/kernel/syscall.c b/trunk/arch/mips/kernel/syscall.c index 58beabf50b3c..1dc6edff45e0 100644 --- a/trunk/arch/mips/kernel/syscall.c +++ b/trunk/arch/mips/kernel/syscall.c @@ -383,11 +383,12 @@ save_static_function(sys_sysmips); static int __used noinline _sys_sysmips(nabi_no_regargs struct pt_regs regs) { - long cmd, arg1, arg2; + long cmd, arg1, arg2, arg3; cmd = regs.regs[4]; arg1 = regs.regs[5]; arg2 = regs.regs[6]; + arg3 = regs.regs[7]; switch (cmd) { case MIPS_ATOMIC_SET: @@ -404,7 +405,7 @@ _sys_sysmips(nabi_no_regargs struct pt_regs regs) if (arg1 & 2) set_thread_flag(TIF_LOGADE); else - clear_thread_flag(TIF_LOGADE); + clear_thread_flag(TIF_FIXADE); return 0; diff --git a/trunk/arch/mips/kernel/vpe.c b/trunk/arch/mips/kernel/vpe.c index ab52b7cf3b6b..6a1fdfef8fde 100644 --- a/trunk/arch/mips/kernel/vpe.c +++ b/trunk/arch/mips/kernel/vpe.c @@ -148,9 +148,9 @@ struct { spinlock_t tc_list_lock; struct list_head tc_list; /* Thread contexts */ } vpecontrol = { - .vpe_list_lock = __SPIN_LOCK_UNLOCKED(vpe_list_lock), + .vpe_list_lock = SPIN_LOCK_UNLOCKED, .vpe_list = LIST_HEAD_INIT(vpecontrol.vpe_list), - .tc_list_lock = __SPIN_LOCK_UNLOCKED(tc_list_lock), + .tc_list_lock = SPIN_LOCK_UNLOCKED, .tc_list = LIST_HEAD_INIT(vpecontrol.tc_list) }; diff --git a/trunk/arch/mips/loongson/Kconfig b/trunk/arch/mips/loongson/Kconfig index aca93eed8779..6e1b77fec7ea 100644 --- a/trunk/arch/mips/loongson/Kconfig +++ b/trunk/arch/mips/loongson/Kconfig @@ -1,7 +1,6 @@ -if MACH_LOONGSON - choice prompt "Machine Type" + depends on MACH_LOONGSON config LEMOTE_FULOONG2E bool "Lemote Fuloong(2e) mini-PC" @@ -88,5 +87,3 @@ config LOONGSON_UART_BASE config LOONGSON_MC146818 bool default n - -endif # MACH_LOONGSON diff --git a/trunk/arch/mips/loongson/common/cmdline.c b/trunk/arch/mips/loongson/common/cmdline.c index 353e1d2e41a5..1a06defc4f7f 100644 --- a/trunk/arch/mips/loongson/common/cmdline.c +++ b/trunk/arch/mips/loongson/common/cmdline.c @@ -44,5 +44,10 @@ void __init prom_init_cmdline(void) strcat(arcs_cmdline, " "); } + if ((strstr(arcs_cmdline, "console=")) == NULL) + strcat(arcs_cmdline, " console=ttyS0,115200"); + if ((strstr(arcs_cmdline, "root=")) == NULL) + strcat(arcs_cmdline, " root=/dev/hda1"); + prom_init_machtype(); } diff --git a/trunk/arch/mips/loongson/common/machtype.c b/trunk/arch/mips/loongson/common/machtype.c index 2efd5d9dee27..81fbe6b73f91 100644 --- a/trunk/arch/mips/loongson/common/machtype.c +++ b/trunk/arch/mips/loongson/common/machtype.c @@ -41,7 +41,7 @@ void __weak __init mach_prom_init_machtype(void) void __init prom_init_machtype(void) { - char *p, str[MACHTYPE_LEN + 1]; + char *p, str[MACHTYPE_LEN]; int machtype = MACH_LEMOTE_FL2E; mips_machtype = LOONGSON_MACHTYPE; @@ -53,7 +53,6 @@ void __init prom_init_machtype(void) } p += strlen("machtype="); strncpy(str, p, MACHTYPE_LEN); - str[MACHTYPE_LEN] = '\0'; p = strstr(str, " "); if (p) *p = '\0'; diff --git a/trunk/arch/mips/math-emu/ieee754int.h b/trunk/arch/mips/math-emu/ieee754int.h index 2a7d43f4f161..2701d9500959 100644 --- a/trunk/arch/mips/math-emu/ieee754int.h +++ b/trunk/arch/mips/math-emu/ieee754int.h @@ -70,7 +70,7 @@ #define COMPXSP \ - unsigned xm; int xe; int xs __maybe_unused; int xc + unsigned xm; int xe; int xs; int xc #define COMPYSP \ unsigned ym; int ye; int ys; int yc @@ -104,7 +104,7 @@ #define COMPXDP \ -u64 xm; int xe; int xs __maybe_unused; int xc +u64 xm; int xe; int xs; int xc #define COMPYDP \ u64 ym; int ye; int ys; int yc diff --git a/trunk/arch/mips/mm/init.c b/trunk/arch/mips/mm/init.c index 279599e9a779..2efcbd24c82f 100644 --- a/trunk/arch/mips/mm/init.c +++ b/trunk/arch/mips/mm/init.c @@ -324,7 +324,7 @@ int page_is_ram(unsigned long pagenr) void __init paging_init(void) { unsigned long max_zone_pfns[MAX_NR_ZONES]; - unsigned long lastpfn __maybe_unused; + unsigned long lastpfn; pagetable_init(); diff --git a/trunk/arch/mips/mm/tlbex.c b/trunk/arch/mips/mm/tlbex.c index 04f9e17db9d0..083d3412d0bc 100644 --- a/trunk/arch/mips/mm/tlbex.c +++ b/trunk/arch/mips/mm/tlbex.c @@ -109,8 +109,6 @@ static bool scratchpad_available(void) static int scratchpad_offset(int i) { BUG(); - /* Really unreachable, but evidently some GCC want this. */ - return 0; } #endif /* diff --git a/trunk/arch/mips/pci/ops-pmcmsp.c b/trunk/arch/mips/pci/ops-pmcmsp.c index 68798f869c0f..b7c03d80c88c 100644 --- a/trunk/arch/mips/pci/ops-pmcmsp.c +++ b/trunk/arch/mips/pci/ops-pmcmsp.c @@ -308,7 +308,7 @@ static struct resource pci_mem_resource = { * RETURNS: PCIBIOS_SUCCESSFUL - success * ****************************************************************************/ -static irqreturn_t bpci_interrupt(int irq, void *dev_id) +static int bpci_interrupt(int irq, void *dev_id) { struct msp_pci_regs *preg = (void *)PCI_BASE_REG; unsigned int stat = preg->if_status; @@ -326,7 +326,7 @@ static irqreturn_t bpci_interrupt(int irq, void *dev_id) /* write to clear all asserted interrupts */ preg->if_status = stat; - return IRQ_HANDLED; + return PCIBIOS_SUCCESSFUL; } /***************************************************************************** diff --git a/trunk/arch/mips/pmc-sierra/Kconfig b/trunk/arch/mips/pmc-sierra/Kconfig index 8d798497c614..c139988bb85d 100644 --- a/trunk/arch/mips/pmc-sierra/Kconfig +++ b/trunk/arch/mips/pmc-sierra/Kconfig @@ -4,11 +4,15 @@ choice config PMC_MSP4200_EVAL bool "PMC-Sierra MSP4200 Eval Board" + select CEVT_R4K + select CSRC_R4K select IRQ_MSP_SLP select HW_HAS_PCI config PMC_MSP4200_GW bool "PMC-Sierra MSP4200 VoIP Gateway" + select CEVT_R4K + select CSRC_R4K select IRQ_MSP_SLP select HW_HAS_PCI diff --git a/trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c index 01df84ce31e2..cca64e15f57f 100644 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c +++ b/trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c @@ -81,7 +81,7 @@ void __init plat_time_init(void) mips_hpt_frequency = cpu_rate/2; } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int __init get_c0_compare_int(void) { return MSP_INT_VPE0_TIMER; } diff --git a/trunk/arch/mn10300/include/asm/atomic.h b/trunk/arch/mn10300/include/asm/atomic.h index 9d773a639513..92d2f9298e38 100644 --- a/trunk/arch/mn10300/include/asm/atomic.h +++ b/trunk/arch/mn10300/include/asm/atomic.h @@ -139,7 +139,7 @@ static inline unsigned long __cmpxchg(volatile unsigned long *m, * Atomically reads the value of @v. Note that the guaranteed * useful range of an atomic_t is only 24 bits. */ -#define atomic_read(v) (ACCESS_ONCE((v)->counter)) +#define atomic_read(v) ((v)->counter) /** * atomic_set - set atomic variable diff --git a/trunk/arch/mn10300/include/asm/uaccess.h b/trunk/arch/mn10300/include/asm/uaccess.h index 3d6e60dad9d9..679dee0bbd08 100644 --- a/trunk/arch/mn10300/include/asm/uaccess.h +++ b/trunk/arch/mn10300/include/asm/uaccess.h @@ -160,10 +160,9 @@ struct __large_struct { unsigned long buf[100]; }; #define __get_user_check(x, ptr, size) \ ({ \ - const __typeof__(ptr) __guc_ptr = (ptr); \ int _e; \ - if (likely(__access_ok((unsigned long) __guc_ptr, (size)))) \ - _e = __get_user_nocheck((x), __guc_ptr, (size)); \ + if (likely(__access_ok((unsigned long) (ptr), (size)))) \ + _e = __get_user_nocheck((x), (ptr), (size)); \ else { \ _e = -EFAULT; \ (x) = (__typeof__(x))0; \ diff --git a/trunk/arch/mn10300/mm/cache-inv-icache.c b/trunk/arch/mn10300/mm/cache-inv-icache.c index a6b63dde603d..a8933a60b2d4 100644 --- a/trunk/arch/mn10300/mm/cache-inv-icache.c +++ b/trunk/arch/mn10300/mm/cache-inv-icache.c @@ -69,7 +69,7 @@ static void flush_icache_page_range(unsigned long start, unsigned long end) /* invalidate the icache coverage on that region */ mn10300_local_icache_inv_range2(addr + off, size); - smp_cache_call(SMP_ICACHE_INV_RANGE, start, end); + smp_cache_call(SMP_ICACHE_INV_FLUSH_RANGE, start, end); } /** @@ -101,7 +101,7 @@ void flush_icache_range(unsigned long start, unsigned long end) * directly */ start_page = (start >= 0x80000000UL) ? start : 0x80000000UL; mn10300_icache_inv_range(start_page, end); - smp_cache_call(SMP_ICACHE_INV_RANGE, start, end); + smp_cache_call(SMP_ICACHE_INV_FLUSH_RANGE, start, end); if (start_page == start) goto done; end = start_page; diff --git a/trunk/arch/parisc/hpux/sys_hpux.c b/trunk/arch/parisc/hpux/sys_hpux.c index 6ab9580b0b00..30394081d9b6 100644 --- a/trunk/arch/parisc/hpux/sys_hpux.c +++ b/trunk/arch/parisc/hpux/sys_hpux.c @@ -185,21 +185,26 @@ struct hpux_statfs { int16_t f_pad; }; -static int do_statfs_hpux(struct kstatfs *st, struct hpux_statfs __user *p) +static int do_statfs_hpux(struct path *path, struct hpux_statfs *buf) { - struct hpux_statfs buf; - memset(&buf, 0, sizeof(buf)); - buf.f_type = st->f_type; - buf.f_bsize = st->f_bsize; - buf.f_blocks = st->f_blocks; - buf.f_bfree = st->f_bfree; - buf.f_bavail = st->f_bavail; - buf.f_files = st->f_files; - buf.f_ffree = st->f_ffree; - buf.f_fsid[0] = st->f_fsid.val[0]; - buf.f_fsid[1] = st->f_fsid.val[1]; - if (copy_to_user(p, &buf, sizeof(buf))) - return -EFAULT; + struct kstatfs st; + int retval; + + retval = vfs_statfs(path, &st); + if (retval) + return retval; + + memset(buf, 0, sizeof(*buf)); + buf->f_type = st.f_type; + buf->f_bsize = st.f_bsize; + buf->f_blocks = st.f_blocks; + buf->f_bfree = st.f_bfree; + buf->f_bavail = st.f_bavail; + buf->f_files = st.f_files; + buf->f_ffree = st.f_ffree; + buf->f_fsid[0] = st.f_fsid.val[0]; + buf->f_fsid[1] = st.f_fsid.val[1]; + return 0; } @@ -207,19 +212,35 @@ static int do_statfs_hpux(struct kstatfs *st, struct hpux_statfs __user *p) asmlinkage long hpux_statfs(const char __user *pathname, struct hpux_statfs __user *buf) { - struct kstatfs st; - int error = user_statfs(pathname, &st); - if (!error) - error = do_statfs_hpux(&st, buf); + struct path path; + int error; + + error = user_path(pathname, &path); + if (!error) { + struct hpux_statfs tmp; + error = do_statfs_hpux(&path, &tmp); + if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) + error = -EFAULT; + path_put(&path); + } return error; } asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf) { - struct kstatfs st; - int error = fd_statfs(fd, &st); - if (!error) - error = do_statfs_hpux(&st, buf); + struct file *file; + struct hpux_statfs tmp; + int error; + + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = do_statfs_hpux(&file->f_path, &tmp); + if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) + error = -EFAULT; + fput(file); + out: return error; } diff --git a/trunk/arch/powerpc/include/asm/lppaca.h b/trunk/arch/powerpc/include/asm/lppaca.h index 26b8c807f8f1..380d48bacd16 100644 --- a/trunk/arch/powerpc/include/asm/lppaca.h +++ b/trunk/arch/powerpc/include/asm/lppaca.h @@ -33,25 +33,9 @@ // //---------------------------------------------------------------------------- #include -#include #include #include -/* - * We only have to have statically allocated lppaca structs on - * legacy iSeries, which supports at most 64 cpus. - */ -#ifdef CONFIG_PPC_ISERIES -#if NR_CPUS < 64 -#define NR_LPPACAS NR_CPUS -#else -#define NR_LPPACAS 64 -#endif -#else /* not iSeries */ -#define NR_LPPACAS 1 -#endif - - /* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k * alignment is sufficient to prevent this */ struct lppaca { diff --git a/trunk/arch/powerpc/kernel/paca.c b/trunk/arch/powerpc/kernel/paca.c index f4adf89d7614..ebf9846f3c3b 100644 --- a/trunk/arch/powerpc/kernel/paca.c +++ b/trunk/arch/powerpc/kernel/paca.c @@ -26,6 +26,20 @@ extern unsigned long __toc_start; #ifdef CONFIG_PPC_BOOK3S +/* + * We only have to have statically allocated lppaca structs on + * legacy iSeries, which supports at most 64 cpus. + */ +#ifdef CONFIG_PPC_ISERIES +#if NR_CPUS < 64 +#define NR_LPPACAS NR_CPUS +#else +#define NR_LPPACAS 64 +#endif +#else /* not iSeries */ +#define NR_LPPACAS 1 +#endif + /* * The structure which the hypervisor knows about - this structure * should not cross a page boundary. The vpa_init/register_vpa call diff --git a/trunk/arch/powerpc/mm/numa.c b/trunk/arch/powerpc/mm/numa.c index 0dc95c0aa3be..fd4812329570 100644 --- a/trunk/arch/powerpc/mm/numa.c +++ b/trunk/arch/powerpc/mm/numa.c @@ -1516,8 +1516,7 @@ int start_topology_update(void) { int rc = 0; - /* Disabled until races with load balancing are fixed */ - if (0 && firmware_has_feature(FW_FEATURE_VPHN) && + if (firmware_has_feature(FW_FEATURE_VPHN) && get_lppaca()->shared_proc) { vphn_enabled = 1; setup_cpu_associativity_change_counters(); diff --git a/trunk/arch/powerpc/platforms/cell/spufs/syscalls.c b/trunk/arch/powerpc/platforms/cell/spufs/syscalls.c index a3d2ce54ea2e..187a7d32f86a 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/syscalls.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/syscalls.c @@ -70,7 +70,7 @@ static long do_spu_create(const char __user *pathname, unsigned int flags, if (!IS_ERR(tmp)) { struct nameidata nd; - ret = kern_path_parent(tmp, &nd); + ret = path_lookup(tmp, LOOKUP_PARENT, &nd); if (!ret) { nd.flags |= LOOKUP_OPEN | LOOKUP_CREATE; ret = spufs_create(&nd, flags, mode, neighbor); diff --git a/trunk/arch/powerpc/platforms/iseries/dt.c b/trunk/arch/powerpc/platforms/iseries/dt.c index f0491cc28900..fdb7384c0c4f 100644 --- a/trunk/arch/powerpc/platforms/iseries/dt.c +++ b/trunk/arch/powerpc/platforms/iseries/dt.c @@ -242,8 +242,8 @@ static void __init dt_cpus(struct iseries_flat_dt *dt) pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */ pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); - for (i = 0; i < NR_LPPACAS; i++) { - if (lppaca[i].dyn_proc_status >= 2) + for (i = 0; i < NR_CPUS; i++) { + if (lppaca_of(i).dyn_proc_status >= 2) continue; snprintf(p, 32 - (p - buf), "@%d", i); @@ -251,7 +251,7 @@ static void __init dt_cpus(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", device_type_cpu); - index = lppaca[i].dyn_hv_phys_proc_index; + index = lppaca_of(i).dyn_hv_phys_proc_index; d = &xIoHriProcessorVpd[index]; dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); diff --git a/trunk/arch/powerpc/platforms/iseries/setup.c b/trunk/arch/powerpc/platforms/iseries/setup.c index 2946ae10fbfd..b0863410517f 100644 --- a/trunk/arch/powerpc/platforms/iseries/setup.c +++ b/trunk/arch/powerpc/platforms/iseries/setup.c @@ -680,7 +680,6 @@ void * __init iSeries_early_setup(void) * on but calling this function multiple times is fine. */ identify_cpu(0, mfspr(SPRN_PVR)); - initialise_paca(&boot_paca, 0); powerpc_firmware_features |= FW_FEATURE_ISERIES; powerpc_firmware_features |= FW_FEATURE_LPAR; diff --git a/trunk/arch/um/drivers/mconsole_kern.c b/trunk/arch/um/drivers/mconsole_kern.c index c70e047eed72..975613b23dcf 100644 --- a/trunk/arch/um/drivers/mconsole_kern.c +++ b/trunk/arch/um/drivers/mconsole_kern.c @@ -124,18 +124,35 @@ void mconsole_log(struct mc_request *req) #if 0 void mconsole_proc(struct mc_request *req) { + struct nameidata nd; struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt; struct file *file; - int n; + int n, err; char *ptr = req->request.data, *buf; mm_segment_t old_fs = get_fs(); ptr += strlen("proc"); ptr = skip_spaces(ptr); - file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY); + err = vfs_path_lookup(mnt->mnt_root, mnt, ptr, LOOKUP_FOLLOW, &nd); + if (err) { + mconsole_reply(req, "Failed to look up file", 1, 0); + goto out; + } + + err = may_open(&nd.path, MAY_READ, O_RDONLY); + if (result) { + mconsole_reply(req, "Failed to open file", 1, 0); + path_put(&nd.path); + goto out; + } + + file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY, + current_cred()); + err = PTR_ERR(file); if (IS_ERR(file)) { mconsole_reply(req, "Failed to open file", 1, 0); + path_put(&nd.path); goto out; } diff --git a/trunk/arch/x86/boot/compressed/mkpiggy.c b/trunk/arch/x86/boot/compressed/mkpiggy.c index 46a823882437..646aa78ba5fd 100644 --- a/trunk/arch/x86/boot/compressed/mkpiggy.c +++ b/trunk/arch/x86/boot/compressed/mkpiggy.c @@ -62,12 +62,7 @@ int main(int argc, char *argv[]) if (fseek(f, -4L, SEEK_END)) { perror(argv[1]); } - - if (fread(&olen, sizeof(olen), 1, f) != 1) { - perror(argv[1]); - return 1; - } - + fread(&olen, sizeof olen, 1, f); ilen = ftell(f); olen = getle32(&olen); fclose(f); diff --git a/trunk/arch/x86/ia32/ia32entry.S b/trunk/arch/x86/ia32/ia32entry.S index 98d353edfff3..518bb99c3394 100644 --- a/trunk/arch/x86/ia32/ia32entry.S +++ b/trunk/arch/x86/ia32/ia32entry.S @@ -851,6 +851,4 @@ ia32_sys_call_table: .quad sys_fanotify_init .quad sys32_fanotify_mark .quad sys_prlimit64 /* 340 */ - .quad sys_name_to_handle_at - .quad compat_sys_open_by_handle_at ia32_syscall_end: diff --git a/trunk/arch/x86/include/asm/ce4100.h b/trunk/arch/x86/include/asm/ce4100.h deleted file mode 100644 index e656ad8c0a2e..000000000000 --- a/trunk/arch/x86/include/asm/ce4100.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_CE4100_H_ -#define _ASM_CE4100_H_ - -int ce4100_pci_init(void); - -#endif diff --git a/trunk/arch/x86/include/asm/unistd_32.h b/trunk/arch/x86/include/asm/unistd_32.h index f4c4973fc2ac..b766a5e8ba0e 100644 --- a/trunk/arch/x86/include/asm/unistd_32.h +++ b/trunk/arch/x86/include/asm/unistd_32.h @@ -346,12 +346,10 @@ #define __NR_fanotify_init 338 #define __NR_fanotify_mark 339 #define __NR_prlimit64 340 -#define __NR_name_to_handle_at 341 -#define __NR_open_by_handle_at 342 #ifdef __KERNEL__ -#define NR_syscalls 343 +#define NR_syscalls 341 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/trunk/arch/x86/include/asm/unistd_64.h b/trunk/arch/x86/include/asm/unistd_64.h index 81a3d5b70235..363e9b8a715b 100644 --- a/trunk/arch/x86/include/asm/unistd_64.h +++ b/trunk/arch/x86/include/asm/unistd_64.h @@ -669,10 +669,6 @@ __SYSCALL(__NR_fanotify_init, sys_fanotify_init) __SYSCALL(__NR_fanotify_mark, sys_fanotify_mark) #define __NR_prlimit64 302 __SYSCALL(__NR_prlimit64, sys_prlimit64) -#define __NR_name_to_handle_at 303 -__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at) -#define __NR_open_by_handle_at 304 -__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at) #ifndef __NO_STUBS #define __ARCH_WANT_OLD_READDIR diff --git a/trunk/arch/x86/include/asm/uv/uv_bau.h b/trunk/arch/x86/include/asm/uv/uv_bau.h index 3e094af443c3..ce1d54c8a433 100644 --- a/trunk/arch/x86/include/asm/uv/uv_bau.h +++ b/trunk/arch/x86/include/asm/uv/uv_bau.h @@ -176,7 +176,7 @@ struct bau_msg_payload { struct bau_msg_header { unsigned int dest_subnodeid:6; /* must be 0x10, for the LB */ /* bits 5:0 */ - unsigned int base_dest_nodeid:15; /* nasid of the */ + unsigned int base_dest_nodeid:15; /* nasid (pnode<<1) of */ /* bits 20:6 */ /* first bit in uvhub map */ unsigned int command:8; /* message type */ /* bits 28:21 */ diff --git a/trunk/arch/x86/include/asm/xen/hypercall.h b/trunk/arch/x86/include/asm/xen/hypercall.h index 8508bfe52296..a3c28ae4025b 100644 --- a/trunk/arch/x86/include/asm/xen/hypercall.h +++ b/trunk/arch/x86/include/asm/xen/hypercall.h @@ -287,7 +287,7 @@ HYPERVISOR_fpu_taskswitch(int set) static inline int HYPERVISOR_sched_op(int cmd, void *arg) { - return _hypercall2(int, sched_op, cmd, arg); + return _hypercall2(int, sched_op_new, cmd, arg); } static inline long @@ -422,17 +422,10 @@ HYPERVISOR_set_segment_base(int reg, unsigned long value) #endif static inline int -HYPERVISOR_suspend(unsigned long start_info_mfn) +HYPERVISOR_suspend(unsigned long srec) { - struct sched_shutdown r = { .reason = SHUTDOWN_suspend }; - - /* - * For a PV guest the tools require that the start_info mfn be - * present in rdx/edx when the hypercall is made. Per the - * hypercall calling convention this is the third hypercall - * argument, which is start_info_mfn here. - */ - return _hypercall3(int, sched_op, SCHEDOP_shutdown, &r, start_info_mfn); + return _hypercall3(int, sched_op, SCHEDOP_shutdown, + SHUTDOWN_suspend, srec); } static inline int diff --git a/trunk/arch/x86/include/asm/xen/page.h b/trunk/arch/x86/include/asm/xen/page.h index c61934fbf22a..f25bdf238a33 100644 --- a/trunk/arch/x86/include/asm/xen/page.h +++ b/trunk/arch/x86/include/asm/xen/page.h @@ -29,10 +29,8 @@ typedef struct xpaddr { /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/ #define INVALID_P2M_ENTRY (~0UL) -#define FOREIGN_FRAME_BIT (1UL<<(BITS_PER_LONG-1)) -#define IDENTITY_FRAME_BIT (1UL<<(BITS_PER_LONG-2)) +#define FOREIGN_FRAME_BIT (1UL<<31) #define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT) -#define IDENTITY_FRAME(m) ((m) | IDENTITY_FRAME_BIT) /* Maximum amount of memory we can handle in a domain in pages */ #define MAX_DOMAIN_PAGES \ @@ -43,18 +41,12 @@ extern unsigned int machine_to_phys_order; extern unsigned long get_phys_to_machine(unsigned long pfn); extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn); -extern bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn); -extern unsigned long set_phys_range_identity(unsigned long pfn_s, - unsigned long pfn_e); extern int m2p_add_override(unsigned long mfn, struct page *page); extern int m2p_remove_override(struct page *page); extern struct page *m2p_find_override(unsigned long mfn); extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); -#ifdef CONFIG_XEN_DEBUG_FS -extern int p2m_dump_show(struct seq_file *m, void *v); -#endif static inline unsigned long pfn_to_mfn(unsigned long pfn) { unsigned long mfn; @@ -65,7 +57,7 @@ static inline unsigned long pfn_to_mfn(unsigned long pfn) mfn = get_phys_to_machine(pfn); if (mfn != INVALID_P2M_ENTRY) - mfn &= ~(FOREIGN_FRAME_BIT | IDENTITY_FRAME_BIT); + mfn &= ~FOREIGN_FRAME_BIT; return mfn; } @@ -81,44 +73,25 @@ static inline int phys_to_machine_mapping_valid(unsigned long pfn) static inline unsigned long mfn_to_pfn(unsigned long mfn) { unsigned long pfn; - int ret = 0; if (xen_feature(XENFEAT_auto_translated_physmap)) return mfn; - if (unlikely((mfn >> machine_to_phys_order) != 0)) { - pfn = ~0; - goto try_override; - } pfn = 0; /* * The array access can fail (e.g., device space beyond end of RAM). * In such cases it doesn't matter what we return (we return garbage), * but we must handle the fault without crashing! */ - ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); -try_override: - /* ret might be < 0 if there are no entries in the m2p for mfn */ - if (ret < 0) - pfn = ~0; - else if (get_phys_to_machine(pfn) != mfn) - /* - * If this appears to be a foreign mfn (because the pfn - * doesn't map back to the mfn), then check the local override - * table to see if there's a better pfn to use. - * - * m2p_find_override_pfn returns ~0 if it doesn't find anything. - */ - pfn = m2p_find_override_pfn(mfn, ~0); - - /* - * pfn is ~0 if there are no entries in the m2p for mfn or if the - * entry doesn't map back to the mfn and m2p_override doesn't have a - * valid entry for it. + __get_user(pfn, &machine_to_phys_mapping[mfn]); + + /* + * If this appears to be a foreign mfn (because the pfn + * doesn't map back to the mfn), then check the local override + * table to see if there's a better pfn to use. */ - if (pfn == ~0 && - get_phys_to_machine(mfn) == IDENTITY_FRAME(mfn)) - pfn = mfn; + if (get_phys_to_machine(pfn) != mfn) + pfn = m2p_find_override_pfn(mfn, pfn); return pfn; } diff --git a/trunk/arch/x86/include/asm/xen/pci.h b/trunk/arch/x86/include/asm/xen/pci.h index aa8620989162..2329b3eaf8d3 100644 --- a/trunk/arch/x86/include/asm/xen/pci.h +++ b/trunk/arch/x86/include/asm/xen/pci.h @@ -27,16 +27,16 @@ static inline void __init xen_setup_pirqs(void) * its own functions. */ struct xen_pci_frontend_ops { - int (*enable_msi)(struct pci_dev *dev, int vectors[]); + int (*enable_msi)(struct pci_dev *dev, int **vectors); void (*disable_msi)(struct pci_dev *dev); - int (*enable_msix)(struct pci_dev *dev, int vectors[], int nvec); + int (*enable_msix)(struct pci_dev *dev, int **vectors, int nvec); void (*disable_msix)(struct pci_dev *dev); }; extern struct xen_pci_frontend_ops *xen_pci_frontend; static inline int xen_pci_frontend_enable_msi(struct pci_dev *dev, - int vectors[]) + int **vectors) { if (xen_pci_frontend && xen_pci_frontend->enable_msi) return xen_pci_frontend->enable_msi(dev, vectors); @@ -48,7 +48,7 @@ static inline void xen_pci_frontend_disable_msi(struct pci_dev *dev) xen_pci_frontend->disable_msi(dev); } static inline int xen_pci_frontend_enable_msix(struct pci_dev *dev, - int vectors[], int nvec) + int **vectors, int nvec) { if (xen_pci_frontend && xen_pci_frontend->enable_msix) return xen_pci_frontend->enable_msix(dev, vectors, nvec); diff --git a/trunk/arch/x86/kernel/check.c b/trunk/arch/x86/kernel/check.c index 452932d34730..13a389179514 100644 --- a/trunk/arch/x86/kernel/check.c +++ b/trunk/arch/x86/kernel/check.c @@ -106,8 +106,8 @@ void __init setup_bios_corruption_check(void) addr += size; } - if (num_scan_areas) - printk(KERN_INFO "Scanning %d areas for low memory corruption\n", num_scan_areas); + printk(KERN_INFO "Scanning %d areas for low memory corruption\n", + num_scan_areas); } @@ -143,12 +143,12 @@ static void check_corruption(struct work_struct *dummy) { check_for_bios_corruption(); schedule_delayed_work(&bios_check_work, - round_jiffies_relative(corruption_check_period*HZ)); + round_jiffies_relative(corruption_check_period*HZ)); } static int start_periodic_check_for_corruption(void) { - if (!num_scan_areas || !memory_corruption_check || corruption_check_period == 0) + if (!memory_corruption_check || corruption_check_period == 0) return 0; printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n", diff --git a/trunk/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c b/trunk/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c index 4a5a42b842ad..4f6f679f2799 100644 --- a/trunk/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c +++ b/trunk/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c @@ -195,7 +195,7 @@ static unsigned int pcc_get_freq(unsigned int cpu) cmd_incomplete: iowrite16(0, &pcch_hdr->status); spin_unlock(&pcc_lock); - return 0; + return -EINVAL; } static int pcc_cpufreq_target(struct cpufreq_policy *policy, diff --git a/trunk/arch/x86/kernel/syscall_table_32.S b/trunk/arch/x86/kernel/syscall_table_32.S index c314b2199efd..b35786dc9b8f 100644 --- a/trunk/arch/x86/kernel/syscall_table_32.S +++ b/trunk/arch/x86/kernel/syscall_table_32.S @@ -340,5 +340,3 @@ ENTRY(sys_call_table) .long sys_fanotify_init .long sys_fanotify_mark .long sys_prlimit64 /* 340 */ - .long sys_name_to_handle_at - .long sys_open_by_handle_at diff --git a/trunk/arch/x86/mm/fault.c b/trunk/arch/x86/mm/fault.c index 20e3f8702d1e..7d90ceb882a4 100644 --- a/trunk/arch/x86/mm/fault.c +++ b/trunk/arch/x86/mm/fault.c @@ -229,14 +229,15 @@ void vmalloc_sync_all(void) for (address = VMALLOC_START & PMD_MASK; address >= TASK_SIZE && address < FIXADDR_TOP; address += PMD_SIZE) { + + unsigned long flags; struct page *page; - spin_lock(&pgd_lock); + spin_lock_irqsave(&pgd_lock, flags); list_for_each_entry(page, &pgd_list, lru) { spinlock_t *pgt_lock; pmd_t *ret; - /* the pgt_lock only for Xen */ pgt_lock = &pgd_page_get_mm(page)->page_table_lock; spin_lock(pgt_lock); @@ -246,7 +247,7 @@ void vmalloc_sync_all(void) if (!ret) break; } - spin_unlock(&pgd_lock); + spin_unlock_irqrestore(&pgd_lock, flags); } } @@ -827,13 +828,6 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, unsigned long address, unsigned int fault) { if (fault & VM_FAULT_OOM) { - /* Kernel mode? Handle exceptions or die: */ - if (!(error_code & PF_USER)) { - up_read(¤t->mm->mmap_sem); - no_context(regs, error_code, address); - return; - } - out_of_memory(regs, error_code, address); } else { if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON| diff --git a/trunk/arch/x86/mm/init_64.c b/trunk/arch/x86/mm/init_64.c index c14a5422e152..71a59296af80 100644 --- a/trunk/arch/x86/mm/init_64.c +++ b/trunk/arch/x86/mm/init_64.c @@ -105,18 +105,18 @@ void sync_global_pgds(unsigned long start, unsigned long end) for (address = start; address <= end; address += PGDIR_SIZE) { const pgd_t *pgd_ref = pgd_offset_k(address); + unsigned long flags; struct page *page; if (pgd_none(*pgd_ref)) continue; - spin_lock(&pgd_lock); + spin_lock_irqsave(&pgd_lock, flags); list_for_each_entry(page, &pgd_list, lru) { pgd_t *pgd; spinlock_t *pgt_lock; pgd = (pgd_t *)page_address(page) + pgd_index(address); - /* the pgt_lock only for Xen */ pgt_lock = &pgd_page_get_mm(page)->page_table_lock; spin_lock(pgt_lock); @@ -128,7 +128,7 @@ void sync_global_pgds(unsigned long start, unsigned long end) spin_unlock(pgt_lock); } - spin_unlock(&pgd_lock); + spin_unlock_irqrestore(&pgd_lock, flags); } } diff --git a/trunk/arch/x86/mm/numa_64.c b/trunk/arch/x86/mm/numa_64.c index 1337c51b07d7..95ea1551eebc 100644 --- a/trunk/arch/x86/mm/numa_64.c +++ b/trunk/arch/x86/mm/numa_64.c @@ -780,7 +780,11 @@ void __cpuinit numa_add_cpu(int cpu) int physnid; int nid = NUMA_NO_NODE; - nid = early_cpu_to_node(cpu); + apicid = early_per_cpu(x86_cpu_to_apicid, cpu); + if (apicid != BAD_APICID) + nid = apicid_to_node[apicid]; + if (nid == NUMA_NO_NODE) + nid = early_cpu_to_node(cpu); BUG_ON(nid == NUMA_NO_NODE || !node_online(nid)); /* diff --git a/trunk/arch/x86/mm/pageattr.c b/trunk/arch/x86/mm/pageattr.c index 90825f2eb0f4..d343b3c81f3c 100644 --- a/trunk/arch/x86/mm/pageattr.c +++ b/trunk/arch/x86/mm/pageattr.c @@ -57,10 +57,12 @@ static unsigned long direct_pages_count[PG_LEVEL_NUM]; void update_page_count(int level, unsigned long pages) { + unsigned long flags; + /* Protect against CPA */ - spin_lock(&pgd_lock); + spin_lock_irqsave(&pgd_lock, flags); direct_pages_count[level] += pages; - spin_unlock(&pgd_lock); + spin_unlock_irqrestore(&pgd_lock, flags); } static void split_page_count(int level) @@ -392,7 +394,7 @@ static int try_preserve_large_page(pte_t *kpte, unsigned long address, struct cpa_data *cpa) { - unsigned long nextpage_addr, numpages, pmask, psize, addr, pfn; + unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn; pte_t new_pte, old_pte, *tmp; pgprot_t old_prot, new_prot, req_prot; int i, do_split = 1; @@ -401,7 +403,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, if (cpa->force_split) return 1; - spin_lock(&pgd_lock); + spin_lock_irqsave(&pgd_lock, flags); /* * Check for races, another CPU might have split this page * up already: @@ -496,14 +498,14 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, } out_unlock: - spin_unlock(&pgd_lock); + spin_unlock_irqrestore(&pgd_lock, flags); return do_split; } static int split_large_page(pte_t *kpte, unsigned long address) { - unsigned long pfn, pfninc = 1; + unsigned long flags, pfn, pfninc = 1; unsigned int i, level; pte_t *pbase, *tmp; pgprot_t ref_prot; @@ -517,7 +519,7 @@ static int split_large_page(pte_t *kpte, unsigned long address) if (!base) return -ENOMEM; - spin_lock(&pgd_lock); + spin_lock_irqsave(&pgd_lock, flags); /* * Check for races, another CPU might have split this page * up for us already: @@ -589,7 +591,7 @@ static int split_large_page(pte_t *kpte, unsigned long address) */ if (base) __free_page(base); - spin_unlock(&pgd_lock); + spin_unlock_irqrestore(&pgd_lock, flags); return 0; } diff --git a/trunk/arch/x86/mm/pgtable.c b/trunk/arch/x86/mm/pgtable.c index 0113d19c8aa6..500242d3c96d 100644 --- a/trunk/arch/x86/mm/pgtable.c +++ b/trunk/arch/x86/mm/pgtable.c @@ -121,12 +121,14 @@ static void pgd_ctor(struct mm_struct *mm, pgd_t *pgd) static void pgd_dtor(pgd_t *pgd) { + unsigned long flags; /* can be called from interrupt context */ + if (SHARED_KERNEL_PMD) return; - spin_lock(&pgd_lock); + spin_lock_irqsave(&pgd_lock, flags); pgd_list_del(pgd); - spin_unlock(&pgd_lock); + spin_unlock_irqrestore(&pgd_lock, flags); } /* @@ -258,6 +260,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm) { pgd_t *pgd; pmd_t *pmds[PREALLOCATED_PMDS]; + unsigned long flags; pgd = (pgd_t *)__get_free_page(PGALLOC_GFP); @@ -277,12 +280,12 @@ pgd_t *pgd_alloc(struct mm_struct *mm) * respect to anything walking the pgd_list, so that they * never see a partially populated pgd. */ - spin_lock(&pgd_lock); + spin_lock_irqsave(&pgd_lock, flags); pgd_ctor(mm, pgd); pgd_prepopulate_pmd(mm, pgd, pmds); - spin_unlock(&pgd_lock); + spin_unlock_irqrestore(&pgd_lock, flags); return pgd; diff --git a/trunk/arch/x86/pci/ce4100.c b/trunk/arch/x86/pci/ce4100.c index 9260b3eb18d4..85b68ef5e809 100644 --- a/trunk/arch/x86/pci/ce4100.c +++ b/trunk/arch/x86/pci/ce4100.c @@ -34,7 +34,6 @@ #include #include -#include #include struct sim_reg { @@ -307,10 +306,10 @@ struct pci_raw_ops ce4100_pci_conf = { .write = ce4100_conf_write, }; -int __init ce4100_pci_init(void) +static int __init ce4100_pci_init(void) { init_sim_regs(); raw_pci_ops = &ce4100_pci_conf; - /* Indicate caller that it should invoke pci_legacy_init() */ - return 1; + return 0; } +subsys_initcall(ce4100_pci_init); diff --git a/trunk/arch/x86/pci/xen.c b/trunk/arch/x86/pci/xen.c index 8c4085a95ef1..25cd4a07d09f 100644 --- a/trunk/arch/x86/pci/xen.c +++ b/trunk/arch/x86/pci/xen.c @@ -20,8 +20,7 @@ #include #ifdef CONFIG_ACPI -static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, - int trigger, int polarity) +static int xen_hvm_register_pirq(u32 gsi, int triggering) { int rc, irq; struct physdev_map_pirq map_irq; @@ -42,7 +41,7 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, return -1; } - if (trigger == ACPI_EDGE_SENSITIVE) { + if (triggering == ACPI_EDGE_SENSITIVE) { shareable = 0; name = "ioapic-edge"; } else { @@ -56,6 +55,12 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, return irq; } + +static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, + int trigger, int polarity) +{ + return xen_hvm_register_pirq(gsi, trigger); +} #endif #if defined(CONFIG_PCI_MSI) @@ -86,7 +91,7 @@ static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq, static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { - int irq, pirq; + int irq, pirq, ret = 0; struct msi_desc *msidesc; struct msi_msg msg; @@ -94,32 +99,39 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) __read_msi_msg(msidesc, &msg); pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); - if (msg.data != XEN_PIRQ_MSI_DATA || - xen_irq_from_pirq(pirq) < 0) { - pirq = xen_allocate_pirq_msi(dev, msidesc); - if (pirq < 0) + if (xen_irq_from_pirq(pirq) >= 0 && msg.data == XEN_PIRQ_MSI_DATA) { + xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? + "msi-x" : "msi", &irq, &pirq, XEN_ALLOC_IRQ); + if (irq < 0) goto error; - xen_msi_compose_msg(dev, pirq, &msg); - __write_msi_msg(msidesc, &msg); - dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); - } else { - dev_dbg(&dev->dev, - "xen: msi already bound to pirq=%d\n", pirq); + ret = set_irq_msi(irq, msidesc); + if (ret < 0) + goto error_while; + printk(KERN_DEBUG "xen: msi already setup: msi --> irq=%d" + " pirq=%d\n", irq, pirq); + return 0; } - irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0, - (type == PCI_CAP_ID_MSIX) ? - "msi-x" : "msi"); - if (irq < 0) + xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? + "msi-x" : "msi", &irq, &pirq, (XEN_ALLOC_IRQ | XEN_ALLOC_PIRQ)); + if (irq < 0 || pirq < 0) goto error; - dev_dbg(&dev->dev, - "xen: msi --> pirq=%d --> irq=%d\n", pirq, irq); + printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq); + xen_msi_compose_msg(dev, pirq, &msg); + ret = set_irq_msi(irq, msidesc); + if (ret < 0) + goto error_while; + write_msi_msg(irq, &msg); } return 0; +error_while: + unbind_from_irqhandler(irq, NULL); error: - dev_err(&dev->dev, - "Xen PCI frontend has not registered MSI/MSI-X support!\n"); - return -ENODEV; + if (ret == -ENODEV) + dev_err(&dev->dev, "Xen PCI frontend has not registered" \ + " MSI/MSI-X support!\n"); + + return ret; } /* @@ -138,26 +150,35 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) return -ENOMEM; if (type == PCI_CAP_ID_MSIX) - ret = xen_pci_frontend_enable_msix(dev, v, nvec); + ret = xen_pci_frontend_enable_msix(dev, &v, nvec); else - ret = xen_pci_frontend_enable_msi(dev, v); + ret = xen_pci_frontend_enable_msi(dev, &v); if (ret) goto error; i = 0; list_for_each_entry(msidesc, &dev->msi_list, list) { - irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0, - (type == PCI_CAP_ID_MSIX) ? - "pcifront-msi-x" : - "pcifront-msi"); - if (irq < 0) + irq = xen_allocate_pirq(v[i], 0, /* not sharable */ + (type == PCI_CAP_ID_MSIX) ? + "pcifront-msi-x" : "pcifront-msi"); + if (irq < 0) { + ret = -1; goto free; + } + + ret = set_irq_msi(irq, msidesc); + if (ret) + goto error_while; i++; } kfree(v); return 0; +error_while: + unbind_from_irqhandler(irq, NULL); error: - dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n"); + if (ret == -ENODEV) + dev_err(&dev->dev, "Xen PCI frontend has not registered" \ + " MSI/MSI-X support!\n"); free: kfree(v); return ret; @@ -172,9 +193,6 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev) xen_pci_frontend_disable_msix(dev); else xen_pci_frontend_disable_msi(dev); - - /* Free the IRQ's and the msidesc using the generic code. */ - default_teardown_msi_irqs(dev); } static void xen_teardown_msi_irq(unsigned int irq) @@ -182,82 +200,47 @@ static void xen_teardown_msi_irq(unsigned int irq) xen_destroy_irq(irq); } -#ifdef CONFIG_XEN_DOM0 static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { - int ret = 0; + int irq, ret; struct msi_desc *msidesc; list_for_each_entry(msidesc, &dev->msi_list, list) { - struct physdev_map_pirq map_irq; - - memset(&map_irq, 0, sizeof(map_irq)); - map_irq.domid = DOMID_SELF; - map_irq.type = MAP_PIRQ_TYPE_MSI; - map_irq.index = -1; - map_irq.pirq = -1; - map_irq.bus = dev->bus->number; - map_irq.devfn = dev->devfn; - - if (type == PCI_CAP_ID_MSIX) { - int pos; - u32 table_offset, bir; - - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - - pci_read_config_dword(dev, pos + PCI_MSIX_TABLE, - &table_offset); - bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - - map_irq.table_base = pci_resource_start(dev, bir); - map_irq.entry_nr = msidesc->msi_attrib.entry_nr; - } - - ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); - if (ret) { - dev_warn(&dev->dev, "xen map irq failed %d\n", ret); - goto out; - } + irq = xen_create_msi_irq(dev, msidesc, type); + if (irq < 0) + return -1; - ret = xen_bind_pirq_msi_to_irq(dev, msidesc, - map_irq.pirq, map_irq.index, - (type == PCI_CAP_ID_MSIX) ? - "msi-x" : "msi"); - if (ret < 0) - goto out; + ret = set_irq_msi(irq, msidesc); + if (ret) + goto error; } - ret = 0; -out: + return 0; + +error: + xen_destroy_irq(irq); return ret; } #endif -#endif static int xen_pcifront_enable_irq(struct pci_dev *dev) { int rc; int share = 1; - u8 gsi; - rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi); - if (rc < 0) { - dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n", - rc); - return rc; - } + dev_info(&dev->dev, "Xen PCI enabling IRQ: %d\n", dev->irq); - if (gsi < NR_IRQS_LEGACY) + if (dev->irq < 0) + return -EINVAL; + + if (dev->irq < NR_IRQS_LEGACY) share = 0; - rc = xen_allocate_pirq(gsi, share, "pcifront"); + rc = xen_allocate_pirq(dev->irq, share, "pcifront"); if (rc < 0) { - dev_warn(&dev->dev, "Xen PCI: failed to register GSI%d: %d\n", - gsi, rc); + dev_warn(&dev->dev, "Xen PCI IRQ: %d, failed to register:%d\n", + dev->irq, rc); return rc; } - - dev->irq = rc; - dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq); return 0; } diff --git a/trunk/arch/x86/platform/ce4100/ce4100.c b/trunk/arch/x86/platform/ce4100/ce4100.c index cd6f184c3b3f..d2c0d51a7178 100644 --- a/trunk/arch/x86/platform/ce4100/ce4100.c +++ b/trunk/arch/x86/platform/ce4100/ce4100.c @@ -15,7 +15,6 @@ #include #include -#include #include #include @@ -130,5 +129,4 @@ void __init x86_ce4100_early_setup(void) x86_init.resources.probe_roms = x86_init_noop; x86_init.mpparse.get_smp_config = x86_init_uint_noop; x86_init.mpparse.find_smp_config = sdv_find_smp_config; - x86_init.pci.init = ce4100_pci_init; } diff --git a/trunk/arch/x86/platform/uv/tlb_uv.c b/trunk/arch/x86/platform/uv/tlb_uv.c index a7b38d35c29a..df58e9cad96a 100644 --- a/trunk/arch/x86/platform/uv/tlb_uv.c +++ b/trunk/arch/x86/platform/uv/tlb_uv.c @@ -1364,11 +1364,11 @@ uv_activation_descriptor_init(int node, int pnode) memset(bd2, 0, sizeof(struct bau_desc)); bd2->header.sw_ack_flag = 1; /* - * base_dest_nodeid is the nasid of the first uvhub + * base_dest_nodeid is the nasid (pnode<<1) of the first uvhub * in the partition. The bit map will indicate uvhub numbers, * which are 0-N in a partition. Pnodes are unique system-wide. */ - bd2->header.base_dest_nodeid = UV_PNODE_TO_NASID(uv_partition_base_pnode); + bd2->header.base_dest_nodeid = uv_partition_base_pnode << 1; bd2->header.dest_subnodeid = 0x10; /* the LB */ bd2->header.command = UV_NET_ENDPOINT_INTD; bd2->header.int_both = 1; diff --git a/trunk/arch/x86/xen/Kconfig b/trunk/arch/x86/xen/Kconfig index e4343fe488ed..5b54892e4bc3 100644 --- a/trunk/arch/x86/xen/Kconfig +++ b/trunk/arch/x86/xen/Kconfig @@ -48,11 +48,3 @@ config XEN_DEBUG_FS help Enable statistics output and various tuning options in debugfs. Enabling this option may incur a significant performance overhead. - -config XEN_DEBUG - bool "Enable Xen debug checks" - depends on XEN - default n - help - Enable various WARN_ON checks in the Xen MMU code. - Enabling this option WILL incur a significant performance overhead. diff --git a/trunk/arch/x86/xen/enlighten.c b/trunk/arch/x86/xen/enlighten.c index 49dbd78ec3cb..50542efe45fb 100644 --- a/trunk/arch/x86/xen/enlighten.c +++ b/trunk/arch/x86/xen/enlighten.c @@ -1284,14 +1284,15 @@ static int init_hvm_pv_info(int *major, int *minor) xen_setup_features(); - pv_info.name = "Xen HVM"; + pv_info = xen_info; + pv_info.kernel_rpl = 0; xen_domain_type = XEN_HVM_DOMAIN; return 0; } -void __ref xen_hvm_init_shared_info(void) +void xen_hvm_init_shared_info(void) { int cpu; struct xen_add_to_physmap xatp; @@ -1330,8 +1331,6 @@ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self, switch (action) { case CPU_UP_PREPARE: per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; - if (xen_have_vector_callback) - xen_init_lock_cpu(cpu); break; default: break; @@ -1356,7 +1355,6 @@ static void __init xen_hvm_guest_init(void) if (xen_feature(XENFEAT_hvm_callback_vector)) xen_have_vector_callback = 1; - xen_hvm_smp_init(); register_cpu_notifier(&xen_hvm_cpu_notifier); xen_unplug_emulated_devices(); have_vcpu_info_placement = 0; diff --git a/trunk/arch/x86/xen/mmu.c b/trunk/arch/x86/xen/mmu.c index 832765c0fb8c..5e92b61ad574 100644 --- a/trunk/arch/x86/xen/mmu.c +++ b/trunk/arch/x86/xen/mmu.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include @@ -417,12 +416,8 @@ static pteval_t pte_pfn_to_mfn(pteval_t val) if (val & _PAGE_PRESENT) { unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT; pteval_t flags = val & PTE_FLAGS_MASK; - unsigned long mfn; + unsigned long mfn = pfn_to_mfn(pfn); - if (!xen_feature(XENFEAT_auto_translated_physmap)) - mfn = get_phys_to_machine(pfn); - else - mfn = pfn; /* * If there's no mfn for the pfn, then just create an * empty non-present pte. Unfortunately this loses @@ -432,18 +427,8 @@ static pteval_t pte_pfn_to_mfn(pteval_t val) if (unlikely(mfn == INVALID_P2M_ENTRY)) { mfn = 0; flags = 0; - } else { - /* - * Paramount to do this test _after_ the - * INVALID_P2M_ENTRY as INVALID_P2M_ENTRY & - * IDENTITY_FRAME_BIT resolves to true. - */ - mfn &= ~FOREIGN_FRAME_BIT; - if (mfn & IDENTITY_FRAME_BIT) { - mfn &= ~IDENTITY_FRAME_BIT; - flags |= _PAGE_IOMAP; - } } + val = ((pteval_t)mfn << PAGE_SHIFT) | flags; } @@ -547,41 +532,6 @@ pte_t xen_make_pte(pteval_t pte) } PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte); -#ifdef CONFIG_XEN_DEBUG -pte_t xen_make_pte_debug(pteval_t pte) -{ - phys_addr_t addr = (pte & PTE_PFN_MASK); - phys_addr_t other_addr; - bool io_page = false; - pte_t _pte; - - if (pte & _PAGE_IOMAP) - io_page = true; - - _pte = xen_make_pte(pte); - - if (!addr) - return _pte; - - if (io_page && - (xen_initial_domain() || addr >= ISA_END_ADDRESS)) { - other_addr = pfn_to_mfn(addr >> PAGE_SHIFT) << PAGE_SHIFT; - WARN(addr != other_addr, - "0x%lx is using VM_IO, but it is 0x%lx!\n", - (unsigned long)addr, (unsigned long)other_addr); - } else { - pteval_t iomap_set = (_pte.pte & PTE_FLAGS_MASK) & _PAGE_IOMAP; - other_addr = (_pte.pte & PTE_PFN_MASK); - WARN((addr == other_addr) && (!io_page) && (!iomap_set), - "0x%lx is missing VM_IO (and wasn't fixed)!\n", - (unsigned long)addr); - } - - return _pte; -} -PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_debug); -#endif - pgd_t xen_make_pgd(pgdval_t pgd) { pgd = pte_pfn_to_mfn(pgd); @@ -1036,9 +986,10 @@ static void xen_pgd_pin(struct mm_struct *mm) */ void xen_mm_pin_all(void) { + unsigned long flags; struct page *page; - spin_lock(&pgd_lock); + spin_lock_irqsave(&pgd_lock, flags); list_for_each_entry(page, &pgd_list, lru) { if (!PagePinned(page)) { @@ -1047,7 +998,7 @@ void xen_mm_pin_all(void) } } - spin_unlock(&pgd_lock); + spin_unlock_irqrestore(&pgd_lock, flags); } /* @@ -1148,9 +1099,10 @@ static void xen_pgd_unpin(struct mm_struct *mm) */ void xen_mm_unpin_all(void) { + unsigned long flags; struct page *page; - spin_lock(&pgd_lock); + spin_lock_irqsave(&pgd_lock, flags); list_for_each_entry(page, &pgd_list, lru) { if (PageSavePinned(page)) { @@ -1160,7 +1112,7 @@ void xen_mm_unpin_all(void) } } - spin_unlock(&pgd_lock); + spin_unlock_irqrestore(&pgd_lock, flags); } void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next) @@ -1990,9 +1942,6 @@ __init void xen_ident_map_ISA(void) static __init void xen_post_allocator_init(void) { -#ifdef CONFIG_XEN_DEBUG - pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug); -#endif pv_mmu_ops.set_pte = xen_set_pte; pv_mmu_ops.set_pmd = xen_set_pmd; pv_mmu_ops.set_pud = xen_set_pud; @@ -2125,7 +2074,7 @@ static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order, in_frames[i] = virt_to_mfn(vaddr); MULTI_update_va_mapping(mcs.mc, vaddr, VOID_PTE, 0); - __set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY); + set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY); if (out_frames) out_frames[i] = virt_to_pfn(vaddr); @@ -2404,18 +2353,6 @@ EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); #ifdef CONFIG_XEN_DEBUG_FS -static int p2m_dump_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, p2m_dump_show, NULL); -} - -static const struct file_operations p2m_dump_fops = { - .open = p2m_dump_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - static struct dentry *d_mmu_debug; static int __init xen_mmu_debugfs(void) @@ -2471,7 +2408,6 @@ static int __init xen_mmu_debugfs(void) debugfs_create_u32("prot_commit_batched", 0444, d_mmu_debug, &mmu_stats.prot_commit_batched); - debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops); return 0; } fs_initcall(xen_mmu_debugfs); diff --git a/trunk/arch/x86/xen/p2m.c b/trunk/arch/x86/xen/p2m.c index 215a3ce61068..fd12d7ce7ff9 100644 --- a/trunk/arch/x86/xen/p2m.c +++ b/trunk/arch/x86/xen/p2m.c @@ -23,129 +23,6 @@ * P2M_PER_PAGE depends on the architecture, as a mfn is always * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to * 512 and 1024 entries respectively. - * - * In short, these structures contain the Machine Frame Number (MFN) of the PFN. - * - * However not all entries are filled with MFNs. Specifically for all other - * leaf entries, or for the top root, or middle one, for which there is a void - * entry, we assume it is "missing". So (for example) - * pfn_to_mfn(0x90909090)=INVALID_P2M_ENTRY. - * - * We also have the possibility of setting 1-1 mappings on certain regions, so - * that: - * pfn_to_mfn(0xc0000)=0xc0000 - * - * The benefit of this is, that we can assume for non-RAM regions (think - * PCI BARs, or ACPI spaces), we can create mappings easily b/c we - * get the PFN value to match the MFN. - * - * For this to work efficiently we have one new page p2m_identity and - * allocate (via reserved_brk) any other pages we need to cover the sides - * (1GB or 4MB boundary violations). All entries in p2m_identity are set to - * INVALID_P2M_ENTRY type (Xen toolstack only recognizes that and MFNs, - * no other fancy value). - * - * On lookup we spot that the entry points to p2m_identity and return the - * identity value instead of dereferencing and returning INVALID_P2M_ENTRY. - * If the entry points to an allocated page, we just proceed as before and - * return the PFN. If the PFN has IDENTITY_FRAME_BIT set we unmask that in - * appropriate functions (pfn_to_mfn). - * - * The reason for having the IDENTITY_FRAME_BIT instead of just returning the - * PFN is that we could find ourselves where pfn_to_mfn(pfn)==pfn for a - * non-identity pfn. To protect ourselves against we elect to set (and get) the - * IDENTITY_FRAME_BIT on all identity mapped PFNs. - * - * This simplistic diagram is used to explain the more subtle piece of code. - * There is also a digram of the P2M at the end that can help. - * Imagine your E820 looking as so: - * - * 1GB 2GB - * /-------------------+---------\/----\ /----------\ /---+-----\ - * | System RAM | Sys RAM ||ACPI| | reserved | | Sys RAM | - * \-------------------+---------/\----/ \----------/ \---+-----/ - * ^- 1029MB ^- 2001MB - * - * [1029MB = 263424 (0x40500), 2001MB = 512256 (0x7D100), - * 2048MB = 524288 (0x80000)] - * - * And dom0_mem=max:3GB,1GB is passed in to the guest, meaning memory past 1GB - * is actually not present (would have to kick the balloon driver to put it in). - * - * When we are told to set the PFNs for identity mapping (see patch: "xen/setup: - * Set identity mapping for non-RAM E820 and E820 gaps.") we pass in the start - * of the PFN and the end PFN (263424 and 512256 respectively). The first step - * is to reserve_brk a top leaf page if the p2m[1] is missing. The top leaf page - * covers 512^2 of page estate (1GB) and in case the start or end PFN is not - * aligned on 512^2*PAGE_SIZE (1GB) we loop on aligned 1GB PFNs from start pfn - * to end pfn. We reserve_brk top leaf pages if they are missing (means they - * point to p2m_mid_missing). - * - * With the E820 example above, 263424 is not 1GB aligned so we allocate a - * reserve_brk page which will cover the PFNs estate from 0x40000 to 0x80000. - * Each entry in the allocate page is "missing" (points to p2m_missing). - * - * Next stage is to determine if we need to do a more granular boundary check - * on the 4MB (or 2MB depending on architecture) off the start and end pfn's. - * We check if the start pfn and end pfn violate that boundary check, and if - * so reserve_brk a middle (p2m[x][y]) leaf page. This way we have a much finer - * granularity of setting which PFNs are missing and which ones are identity. - * In our example 263424 and 512256 both fail the check so we reserve_brk two - * pages. Populate them with INVALID_P2M_ENTRY (so they both have "missing" - * values) and assign them to p2m[1][2] and p2m[1][488] respectively. - * - * At this point we would at minimum reserve_brk one page, but could be up to - * three. Each call to set_phys_range_identity has at maximum a three page - * cost. If we were to query the P2M at this stage, all those entries from - * start PFN through end PFN (so 1029MB -> 2001MB) would return - * INVALID_P2M_ENTRY ("missing"). - * - * The next step is to walk from the start pfn to the end pfn setting - * the IDENTITY_FRAME_BIT on each PFN. This is done in set_phys_range_identity. - * If we find that the middle leaf is pointing to p2m_missing we can swap it - * over to p2m_identity - this way covering 4MB (or 2MB) PFN space. At this - * point we do not need to worry about boundary aligment (so no need to - * reserve_brk a middle page, figure out which PFNs are "missing" and which - * ones are identity), as that has been done earlier. If we find that the - * middle leaf is not occupied by p2m_identity or p2m_missing, we dereference - * that page (which covers 512 PFNs) and set the appropriate PFN with - * IDENTITY_FRAME_BIT. In our example 263424 and 512256 end up there, and we - * set from p2m[1][2][256->511] and p2m[1][488][0->256] with - * IDENTITY_FRAME_BIT set. - * - * All other regions that are void (or not filled) either point to p2m_missing - * (considered missing) or have the default value of INVALID_P2M_ENTRY (also - * considered missing). In our case, p2m[1][2][0->255] and p2m[1][488][257->511] - * contain the INVALID_P2M_ENTRY value and are considered "missing." - * - * This is what the p2m ends up looking (for the E820 above) with this - * fabulous drawing: - * - * p2m /--------------\ - * /-----\ | &mfn_list[0],| /-----------------\ - * | 0 |------>| &mfn_list[1],| /---------------\ | ~0, ~0, .. | - * |-----| | ..., ~0, ~0 | | ~0, ~0, [x]---+----->| IDENTITY [@256] | - * | 1 |---\ \--------------/ | [p2m_identity]+\ | IDENTITY [@257] | - * |-----| \ | [p2m_identity]+\\ | .... | - * | 2 |--\ \-------------------->| ... | \\ \----------------/ - * |-----| \ \---------------/ \\ - * | 3 |\ \ \\ p2m_identity - * |-----| \ \-------------------->/---------------\ /-----------------\ - * | .. +->+ | [p2m_identity]+-->| ~0, ~0, ~0, ... | - * \-----/ / | [p2m_identity]+-->| ..., ~0 | - * / /---------------\ | .... | \-----------------/ - * / | IDENTITY[@0] | /-+-[x], ~0, ~0.. | - * / | IDENTITY[@256]|<----/ \---------------/ - * / | ~0, ~0, .... | - * | \---------------/ - * | - * p2m_missing p2m_missing - * /------------------\ /------------\ - * | [p2m_mid_missing]+---->| ~0, ~0, ~0 | - * | [p2m_mid_missing]+---->| ..., ~0 | - * \------------------/ \------------/ - * - * where ~0 is INVALID_P2M_ENTRY. IDENTITY is (PFN | IDENTITY_BIT) */ #include @@ -153,7 +30,6 @@ #include #include #include -#include #include #include @@ -183,15 +59,9 @@ static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE); static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE); static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE); -static RESERVE_BRK_ARRAY(unsigned long, p2m_identity, P2M_PER_PAGE); - RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); -/* We might hit two boundary violations at the start and end, at max each - * boundary violation will require three middle nodes. */ -RESERVE_BRK(p2m_mid_identity, PAGE_SIZE * 2 * 3); - static inline unsigned p2m_top_index(unsigned long pfn) { BUG_ON(pfn >= MAX_P2M_PFN); @@ -266,7 +136,7 @@ static void p2m_init(unsigned long *p2m) * - After resume we're called from within stop_machine, but the mfn * tree should alreay be completely allocated. */ -void __ref xen_build_mfn_list_list(void) +void xen_build_mfn_list_list(void) { unsigned long pfn; @@ -351,9 +221,6 @@ void __init xen_build_dynamic_phys_to_machine(void) p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE); p2m_top_init(p2m_top); - p2m_identity = extend_brk(PAGE_SIZE, PAGE_SIZE); - p2m_init(p2m_identity); - /* * The domain builder gives us a pre-constructed p2m array in * mfn_list for all the pages initially given to us, so we just @@ -399,14 +266,6 @@ unsigned long get_phys_to_machine(unsigned long pfn) mididx = p2m_mid_index(pfn); idx = p2m_index(pfn); - /* - * The INVALID_P2M_ENTRY is filled in both p2m_*identity - * and in p2m_*missing, so returning the INVALID_P2M_ENTRY - * would be wrong. - */ - if (p2m_top[topidx][mididx] == p2m_identity) - return IDENTITY_FRAME(pfn); - return p2m_top[topidx][mididx][idx]; } EXPORT_SYMBOL_GPL(get_phys_to_machine); @@ -476,11 +335,9 @@ static bool alloc_p2m(unsigned long pfn) p2m_top_mfn_p[topidx] = mid_mfn; } - if (p2m_top[topidx][mididx] == p2m_identity || - p2m_top[topidx][mididx] == p2m_missing) { + if (p2m_top[topidx][mididx] == p2m_missing) { /* p2m leaf page is missing */ unsigned long *p2m; - unsigned long *p2m_orig = p2m_top[topidx][mididx]; p2m = alloc_p2m_page(); if (!p2m) @@ -488,7 +345,7 @@ static bool alloc_p2m(unsigned long pfn) p2m_init(p2m); - if (cmpxchg(&mid[mididx], p2m_orig, p2m) != p2m_orig) + if (cmpxchg(&mid[mididx], p2m_missing, p2m) != p2m_missing) free_p2m_page(p2m); else mid_mfn[mididx] = virt_to_mfn(p2m); @@ -497,91 +354,11 @@ static bool alloc_p2m(unsigned long pfn) return true; } -bool __early_alloc_p2m(unsigned long pfn) -{ - unsigned topidx, mididx, idx; - - topidx = p2m_top_index(pfn); - mididx = p2m_mid_index(pfn); - idx = p2m_index(pfn); - - /* Pfff.. No boundary cross-over, lets get out. */ - if (!idx) - return false; - - WARN(p2m_top[topidx][mididx] == p2m_identity, - "P2M[%d][%d] == IDENTITY, should be MISSING (or alloced)!\n", - topidx, mididx); - - /* - * Could be done by xen_build_dynamic_phys_to_machine.. - */ - if (p2m_top[topidx][mididx] != p2m_missing) - return false; - - /* Boundary cross-over for the edges: */ - if (idx) { - unsigned long *p2m = extend_brk(PAGE_SIZE, PAGE_SIZE); - - p2m_init(p2m); - - p2m_top[topidx][mididx] = p2m; - - } - return idx != 0; -} -unsigned long set_phys_range_identity(unsigned long pfn_s, - unsigned long pfn_e) -{ - unsigned long pfn; - - if (unlikely(pfn_s >= MAX_P2M_PFN || pfn_e >= MAX_P2M_PFN)) - return 0; - - if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) - return pfn_e - pfn_s; - - if (pfn_s > pfn_e) - return 0; - - for (pfn = (pfn_s & ~(P2M_MID_PER_PAGE * P2M_PER_PAGE - 1)); - pfn < ALIGN(pfn_e, (P2M_MID_PER_PAGE * P2M_PER_PAGE)); - pfn += P2M_MID_PER_PAGE * P2M_PER_PAGE) - { - unsigned topidx = p2m_top_index(pfn); - if (p2m_top[topidx] == p2m_mid_missing) { - unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE); - - p2m_mid_init(mid); - - p2m_top[topidx] = mid; - } - } - - __early_alloc_p2m(pfn_s); - __early_alloc_p2m(pfn_e); - - for (pfn = pfn_s; pfn < pfn_e; pfn++) - if (!__set_phys_to_machine(pfn, IDENTITY_FRAME(pfn))) - break; - - if (!WARN((pfn - pfn_s) != (pfn_e - pfn_s), - "Identity mapping failed. We are %ld short of 1-1 mappings!\n", - (pfn_e - pfn_s) - (pfn - pfn_s))) - printk(KERN_DEBUG "1-1 mapping on %lx->%lx\n", pfn_s, pfn); - - return pfn - pfn_s; -} - /* Try to install p2m mapping; fail if intermediate bits missing */ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) { unsigned topidx, mididx, idx; - if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { - BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); - return true; - } if (unlikely(pfn >= MAX_P2M_PFN)) { BUG_ON(mfn != INVALID_P2M_ENTRY); return true; @@ -591,21 +368,6 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) mididx = p2m_mid_index(pfn); idx = p2m_index(pfn); - /* For sparse holes were the p2m leaf has real PFN along with - * PCI holes, stick in the PFN as the MFN value. - */ - if (mfn != INVALID_P2M_ENTRY && (mfn & IDENTITY_FRAME_BIT)) { - if (p2m_top[topidx][mididx] == p2m_identity) - return true; - - /* Swap over from MISSING to IDENTITY if needed. */ - if (p2m_top[topidx][mididx] == p2m_missing) { - WARN_ON(cmpxchg(&p2m_top[topidx][mididx], p2m_missing, - p2m_identity) != p2m_missing); - return true; - } - } - if (p2m_top[topidx][mididx] == p2m_missing) return mfn == INVALID_P2M_ENTRY; @@ -616,6 +378,11 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) { + if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { + BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); + return true; + } + if (unlikely(!__set_phys_to_machine(pfn, mfn))) { if (!alloc_p2m(pfn)) return false; @@ -654,7 +421,7 @@ int m2p_add_override(unsigned long mfn, struct page *page) { unsigned long flags; unsigned long pfn; - unsigned long uninitialized_var(address); + unsigned long address; unsigned level; pte_t *ptep = NULL; @@ -688,7 +455,7 @@ int m2p_remove_override(struct page *page) unsigned long flags; unsigned long mfn; unsigned long pfn; - unsigned long uninitialized_var(address); + unsigned long address; unsigned level; pte_t *ptep = NULL; @@ -753,80 +520,3 @@ unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn) return ret; } EXPORT_SYMBOL_GPL(m2p_find_override_pfn); - -#ifdef CONFIG_XEN_DEBUG_FS - -int p2m_dump_show(struct seq_file *m, void *v) -{ - static const char * const level_name[] = { "top", "middle", - "entry", "abnormal" }; - static const char * const type_name[] = { "identity", "missing", - "pfn", "abnormal"}; -#define TYPE_IDENTITY 0 -#define TYPE_MISSING 1 -#define TYPE_PFN 2 -#define TYPE_UNKNOWN 3 - unsigned long pfn, prev_pfn_type = 0, prev_pfn_level = 0; - unsigned int uninitialized_var(prev_level); - unsigned int uninitialized_var(prev_type); - - if (!p2m_top) - return 0; - - for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn++) { - unsigned topidx = p2m_top_index(pfn); - unsigned mididx = p2m_mid_index(pfn); - unsigned idx = p2m_index(pfn); - unsigned lvl, type; - - lvl = 4; - type = TYPE_UNKNOWN; - if (p2m_top[topidx] == p2m_mid_missing) { - lvl = 0; type = TYPE_MISSING; - } else if (p2m_top[topidx] == NULL) { - lvl = 0; type = TYPE_UNKNOWN; - } else if (p2m_top[topidx][mididx] == NULL) { - lvl = 1; type = TYPE_UNKNOWN; - } else if (p2m_top[topidx][mididx] == p2m_identity) { - lvl = 1; type = TYPE_IDENTITY; - } else if (p2m_top[topidx][mididx] == p2m_missing) { - lvl = 1; type = TYPE_MISSING; - } else if (p2m_top[topidx][mididx][idx] == 0) { - lvl = 2; type = TYPE_UNKNOWN; - } else if (p2m_top[topidx][mididx][idx] == IDENTITY_FRAME(pfn)) { - lvl = 2; type = TYPE_IDENTITY; - } else if (p2m_top[topidx][mididx][idx] == INVALID_P2M_ENTRY) { - lvl = 2; type = TYPE_MISSING; - } else if (p2m_top[topidx][mididx][idx] == pfn) { - lvl = 2; type = TYPE_PFN; - } else if (p2m_top[topidx][mididx][idx] != pfn) { - lvl = 2; type = TYPE_PFN; - } - if (pfn == 0) { - prev_level = lvl; - prev_type = type; - } - if (pfn == MAX_DOMAIN_PAGES-1) { - lvl = 3; - type = TYPE_UNKNOWN; - } - if (prev_type != type) { - seq_printf(m, " [0x%lx->0x%lx] %s\n", - prev_pfn_type, pfn, type_name[prev_type]); - prev_pfn_type = pfn; - prev_type = type; - } - if (prev_level != lvl) { - seq_printf(m, " [0x%lx->0x%lx] level %s\n", - prev_pfn_level, pfn, level_name[prev_level]); - prev_pfn_level = pfn; - prev_level = lvl; - } - } - return 0; -#undef TYPE_IDENTITY -#undef TYPE_MISSING -#undef TYPE_PFN -#undef TYPE_UNKNOWN -} -#endif diff --git a/trunk/arch/x86/xen/setup.c b/trunk/arch/x86/xen/setup.c index fa0269a99377..a8a66a50d446 100644 --- a/trunk/arch/x86/xen/setup.c +++ b/trunk/arch/x86/xen/setup.c @@ -52,8 +52,6 @@ phys_addr_t xen_extra_mem_start, xen_extra_mem_size; static __init void xen_add_extra_mem(unsigned long pages) { - unsigned long pfn; - u64 size = (u64)pages * PAGE_SIZE; u64 extra_start = xen_extra_mem_start + xen_extra_mem_size; @@ -68,9 +66,6 @@ static __init void xen_add_extra_mem(unsigned long pages) xen_extra_mem_size += size; xen_max_p2m_pfn = PFN_DOWN(extra_start + size); - - for (pfn = PFN_DOWN(extra_start); pfn <= xen_max_p2m_pfn; pfn++) - __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); } static unsigned long __init xen_release_chunk(phys_addr_t start_addr, @@ -109,7 +104,7 @@ static unsigned long __init xen_release_chunk(phys_addr_t start_addr, WARN(ret != 1, "Failed to release memory %lx-%lx err=%d\n", start, end, ret); if (ret == 1) { - __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); + set_phys_to_machine(pfn, INVALID_P2M_ENTRY); len++; } } @@ -143,55 +138,12 @@ static unsigned long __init xen_return_unused_memory(unsigned long max_pfn, return released; } -static unsigned long __init xen_set_identity(const struct e820entry *list, - ssize_t map_size) -{ - phys_addr_t last = xen_initial_domain() ? 0 : ISA_END_ADDRESS; - phys_addr_t start_pci = last; - const struct e820entry *entry; - unsigned long identity = 0; - int i; - - for (i = 0, entry = list; i < map_size; i++, entry++) { - phys_addr_t start = entry->addr; - phys_addr_t end = start + entry->size; - - if (start < last) - start = last; - - if (end <= start) - continue; - - /* Skip over the 1MB region. */ - if (last > end) - continue; - - if (entry->type == E820_RAM) { - if (start > start_pci) - identity += set_phys_range_identity( - PFN_UP(start_pci), PFN_DOWN(start)); - - /* Without saving 'last' we would gooble RAM too - * at the end of the loop. */ - last = end; - start_pci = end; - continue; - } - start_pci = min(start, start_pci); - last = end; - } - if (last > start_pci) - identity += set_phys_range_identity( - PFN_UP(start_pci), PFN_DOWN(last)); - return identity; -} /** * machine_specific_memory_setup - Hook for machine specific memory setup. **/ char * __init xen_memory_setup(void) { static struct e820entry map[E820MAX] __initdata; - static struct e820entry map_raw[E820MAX] __initdata; unsigned long max_pfn = xen_start_info->nr_pages; unsigned long long mem_end; @@ -199,7 +151,6 @@ char * __init xen_memory_setup(void) struct xen_memory_map memmap; unsigned long extra_pages = 0; unsigned long extra_limit; - unsigned long identity_pages = 0; int i; int op; @@ -225,7 +176,6 @@ char * __init xen_memory_setup(void) } BUG_ON(rc); - memcpy(map_raw, map, sizeof(map)); e820.nr_map = 0; xen_extra_mem_start = mem_end; for (i = 0; i < memmap.nr_entries; i++) { @@ -244,15 +194,6 @@ char * __init xen_memory_setup(void) end -= delta; extra_pages += PFN_DOWN(delta); - /* - * Set RAM below 4GB that is not for us to be unusable. - * This prevents "System RAM" address space from being - * used as potential resource for I/O address (happens - * when 'allocate_resource' is called). - */ - if (delta && - (xen_initial_domain() && end < 0x100000000ULL)) - e820_add_region(end, delta, E820_UNUSABLE); } if (map[i].size > 0 && end > xen_extra_mem_start) @@ -310,13 +251,6 @@ char * __init xen_memory_setup(void) xen_add_extra_mem(extra_pages); - /* - * Set P2M for all non-RAM pages and E820 gaps to be identity - * type PFNs. We supply it with the non-sanitized version - * of the E820. - */ - identity_pages = xen_set_identity(map_raw, memmap.nr_entries); - printk(KERN_INFO "Set %ld page(s) to 1-1 mapping.\n", identity_pages); return "Xen"; } diff --git a/trunk/arch/x86/xen/smp.c b/trunk/arch/x86/xen/smp.c index 30612441ed99..72a4c7959045 100644 --- a/trunk/arch/x86/xen/smp.c +++ b/trunk/arch/x86/xen/smp.c @@ -509,41 +509,3 @@ void __init xen_smp_init(void) xen_fill_possible_map(); xen_init_spinlocks(); } - -static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus) -{ - native_smp_prepare_cpus(max_cpus); - WARN_ON(xen_smp_intr_init(0)); - - if (!xen_have_vector_callback) - return; - xen_init_lock_cpu(0); - xen_init_spinlocks(); -} - -static int __cpuinit xen_hvm_cpu_up(unsigned int cpu) -{ - int rc; - rc = native_cpu_up(cpu); - WARN_ON (xen_smp_intr_init(cpu)); - return rc; -} - -static void xen_hvm_cpu_die(unsigned int cpu) -{ - unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), NULL); - unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL); - unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL); - unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL); - native_cpu_die(cpu); -} - -void __init xen_hvm_smp_init(void) -{ - smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus; - smp_ops.smp_send_reschedule = xen_smp_send_reschedule; - smp_ops.cpu_up = xen_hvm_cpu_up; - smp_ops.cpu_die = xen_hvm_cpu_die; - smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi; - smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi; -} diff --git a/trunk/arch/x86/xen/suspend.c b/trunk/arch/x86/xen/suspend.c index 45329c8c226e..9bbd63a129b5 100644 --- a/trunk/arch/x86/xen/suspend.c +++ b/trunk/arch/x86/xen/suspend.c @@ -12,7 +12,7 @@ #include "xen-ops.h" #include "mmu.h" -void xen_arch_pre_suspend(void) +void xen_pre_suspend(void) { xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn); xen_start_info->console.domU.mfn = @@ -26,9 +26,8 @@ void xen_arch_pre_suspend(void) BUG(); } -void xen_arch_hvm_post_suspend(int suspend_cancelled) +void xen_hvm_post_suspend(int suspend_cancelled) { -#ifdef CONFIG_XEN_PVHVM int cpu; xen_hvm_init_shared_info(); xen_callback_vector(); @@ -38,10 +37,9 @@ void xen_arch_hvm_post_suspend(int suspend_cancelled) xen_setup_runstate_info(cpu); } } -#endif } -void xen_arch_post_suspend(int suspend_cancelled) +void xen_post_suspend(int suspend_cancelled) { xen_build_mfn_list_list(); diff --git a/trunk/arch/x86/xen/time.c b/trunk/arch/x86/xen/time.c index 2e2d370a47b1..067759e3d6a5 100644 --- a/trunk/arch/x86/xen/time.c +++ b/trunk/arch/x86/xen/time.c @@ -397,9 +397,7 @@ void xen_setup_timer(int cpu) name = ""; irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, - IRQF_DISABLED|IRQF_PERCPU| - IRQF_NOBALANCING|IRQF_TIMER| - IRQF_FORCE_RESUME, + IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER, name, NULL); evt = &per_cpu(xen_clock_events, cpu); diff --git a/trunk/arch/x86/xen/xen-ops.h b/trunk/arch/x86/xen/xen-ops.h index 3112f55638c4..9d41bf985757 100644 --- a/trunk/arch/x86/xen/xen-ops.h +++ b/trunk/arch/x86/xen/xen-ops.h @@ -64,12 +64,10 @@ void xen_setup_vcpu_info_placement(void); #ifdef CONFIG_SMP void xen_smp_init(void); -void __init xen_hvm_smp_init(void); extern cpumask_var_t xen_cpu_initialized_map; #else static inline void xen_smp_init(void) {} -static inline void xen_hvm_smp_init(void) {} #endif #ifdef CONFIG_PARAVIRT_SPINLOCKS diff --git a/trunk/block/blk-lib.c b/trunk/block/blk-lib.c index bd3e8df4d5e2..eec78becb355 100644 --- a/trunk/block/blk-lib.c +++ b/trunk/block/blk-lib.c @@ -109,6 +109,7 @@ struct bio_batch atomic_t done; unsigned long flags; struct completion *wait; + bio_end_io_t *end_io; }; static void bio_batch_end_io(struct bio *bio, int err) @@ -121,9 +122,12 @@ static void bio_batch_end_io(struct bio *bio, int err) else clear_bit(BIO_UPTODATE, &bb->flags); } - if (bb) - if (atomic_dec_and_test(&bb->done)) - complete(bb->wait); + if (bb) { + if (bb->end_io) + bb->end_io(bio, err); + atomic_inc(&bb->done); + complete(bb->wait); + } bio_put(bio); } @@ -146,12 +150,13 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, int ret; struct bio *bio; struct bio_batch bb; - unsigned int sz; + unsigned int sz, issued = 0; DECLARE_COMPLETION_ONSTACK(wait); - atomic_set(&bb.done, 1); + atomic_set(&bb.done, 0); bb.flags = 1 << BIO_UPTODATE; bb.wait = &wait; + bb.end_io = NULL; submit: ret = 0; @@ -180,12 +185,12 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, break; } ret = 0; - atomic_inc(&bb.done); + issued++; submit_bio(WRITE, bio); } /* Wait for bios in-flight */ - if (!atomic_dec_and_test(&bb.done)) + while (issued != atomic_read(&bb.done)) wait_for_completion(&wait); if (!test_bit(BIO_UPTODATE, &bb.flags)) diff --git a/trunk/drivers/block/xen-blkfront.c b/trunk/drivers/block/xen-blkfront.c index 9cb8668ff5f4..d7aa39e349a6 100644 --- a/trunk/drivers/block/xen-blkfront.c +++ b/trunk/drivers/block/xen-blkfront.c @@ -120,10 +120,6 @@ static DEFINE_SPINLOCK(minor_lock); #define EXTENDED (1<shadow[id].request = req; ring_req->id = id; - ring_req->u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req); + ring_req->sector_number = (blkif_sector_t)blk_rq_pos(req); ring_req->handle = info->handle; ring_req->operation = rq_data_dir(req) ? @@ -321,7 +317,7 @@ static int blkif_queue_request(struct request *req) rq_data_dir(req) ); info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn); - ring_req->u.rw.seg[i] = + ring_req->seg[i] = (struct blkif_request_segment) { .gref = ref, .first_sect = fsect, @@ -438,65 +434,6 @@ static void xlvbd_flush(struct blkfront_info *info) info->feature_flush ? "enabled" : "disabled"); } -static int xen_translate_vdev(int vdevice, int *minor, unsigned int *offset) -{ - int major; - major = BLKIF_MAJOR(vdevice); - *minor = BLKIF_MINOR(vdevice); - switch (major) { - case XEN_IDE0_MAJOR: - *offset = (*minor / 64) + EMULATED_HD_DISK_NAME_OFFSET; - *minor = ((*minor / 64) * PARTS_PER_DISK) + - EMULATED_HD_DISK_MINOR_OFFSET; - break; - case XEN_IDE1_MAJOR: - *offset = (*minor / 64) + 2 + EMULATED_HD_DISK_NAME_OFFSET; - *minor = (((*minor / 64) + 2) * PARTS_PER_DISK) + - EMULATED_HD_DISK_MINOR_OFFSET; - break; - case XEN_SCSI_DISK0_MAJOR: - *offset = (*minor / PARTS_PER_DISK) + EMULATED_SD_DISK_NAME_OFFSET; - *minor = *minor + EMULATED_SD_DISK_MINOR_OFFSET; - break; - case XEN_SCSI_DISK1_MAJOR: - case XEN_SCSI_DISK2_MAJOR: - case XEN_SCSI_DISK3_MAJOR: - case XEN_SCSI_DISK4_MAJOR: - case XEN_SCSI_DISK5_MAJOR: - case XEN_SCSI_DISK6_MAJOR: - case XEN_SCSI_DISK7_MAJOR: - *offset = (*minor / PARTS_PER_DISK) + - ((major - XEN_SCSI_DISK1_MAJOR + 1) * 16) + - EMULATED_SD_DISK_NAME_OFFSET; - *minor = *minor + - ((major - XEN_SCSI_DISK1_MAJOR + 1) * 16 * PARTS_PER_DISK) + - EMULATED_SD_DISK_MINOR_OFFSET; - break; - case XEN_SCSI_DISK8_MAJOR: - case XEN_SCSI_DISK9_MAJOR: - case XEN_SCSI_DISK10_MAJOR: - case XEN_SCSI_DISK11_MAJOR: - case XEN_SCSI_DISK12_MAJOR: - case XEN_SCSI_DISK13_MAJOR: - case XEN_SCSI_DISK14_MAJOR: - case XEN_SCSI_DISK15_MAJOR: - *offset = (*minor / PARTS_PER_DISK) + - ((major - XEN_SCSI_DISK8_MAJOR + 8) * 16) + - EMULATED_SD_DISK_NAME_OFFSET; - *minor = *minor + - ((major - XEN_SCSI_DISK8_MAJOR + 8) * 16 * PARTS_PER_DISK) + - EMULATED_SD_DISK_MINOR_OFFSET; - break; - case XENVBD_MAJOR: - *offset = *minor / PARTS_PER_DISK; - break; - default: - printk(KERN_WARNING "blkfront: your disk configuration is " - "incorrect, please use an xvd device instead\n"); - return -ENODEV; - } - return 0; -} static int xlvbd_alloc_gendisk(blkif_sector_t capacity, struct blkfront_info *info, @@ -504,7 +441,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, { struct gendisk *gd; int nr_minors = 1; - int err; + int err = -ENODEV; unsigned int offset; int minor; int nr_parts; @@ -519,20 +456,12 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, } if (!VDEV_IS_EXTENDED(info->vdevice)) { - err = xen_translate_vdev(info->vdevice, &minor, &offset); - if (err) - return err; - nr_parts = PARTS_PER_DISK; + minor = BLKIF_MINOR(info->vdevice); + nr_parts = PARTS_PER_DISK; } else { minor = BLKIF_MINOR_EXT(info->vdevice); nr_parts = PARTS_PER_EXT_DISK; - offset = minor / nr_parts; - if (xen_hvm_domain() && offset <= EMULATED_HD_DISK_NAME_OFFSET + 4) - printk(KERN_WARNING "blkfront: vdevice 0x%x might conflict with " - "emulated IDE disks,\n\t choose an xvd device name" - "from xvde on\n", info->vdevice); } - err = -ENODEV; if ((minor % nr_parts) == 0) nr_minors = nr_parts; @@ -546,6 +475,8 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, if (gd == NULL) goto release; + offset = minor / nr_parts; + if (nr_minors > 1) { if (offset < 26) sprintf(gd->disk_name, "%s%c", DEV_NAME, 'a' + offset); @@ -684,7 +615,7 @@ static void blkif_completion(struct blk_shadow *s) { int i; for (i = 0; i < s->req.nr_segments; i++) - gnttab_end_foreign_access(s->req.u.rw.seg[i].gref, 0, 0UL); + gnttab_end_foreign_access(s->req.seg[i].gref, 0, 0UL); } static irqreturn_t blkif_interrupt(int irq, void *dev_id) @@ -1001,7 +932,7 @@ static int blkif_recover(struct blkfront_info *info) /* Rewrite any grant references invalidated by susp/resume. */ for (j = 0; j < req->nr_segments; j++) gnttab_grant_foreign_access_ref( - req->u.rw.seg[j].gref, + req->seg[j].gref, info->xbdev->otherend_id, pfn_to_mfn(info->shadow[req->id].frame[j]), rq_data_dir(info->shadow[req->id].request)); diff --git a/trunk/drivers/char/ipmi/ipmi_si_intf.c b/trunk/drivers/char/ipmi/ipmi_si_intf.c index 62787e30d508..7855f9f45b8e 100644 --- a/trunk/drivers/char/ipmi/ipmi_si_intf.c +++ b/trunk/drivers/char/ipmi/ipmi_si_intf.c @@ -900,14 +900,6 @@ static void sender(void *send_info, printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); #endif - /* - * last_timeout_jiffies is updated here to avoid - * smi_timeout() handler passing very large time_diff - * value to smi_event_handler() that causes - * the send command to abort. - */ - smi_info->last_timeout_jiffies = jiffies; - mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES); if (smi_info->thread) diff --git a/trunk/drivers/gpio/ml_ioh_gpio.c b/trunk/drivers/gpio/ml_ioh_gpio.c index 7f6f01a4b145..cead8e6ff345 100644 --- a/trunk/drivers/gpio/ml_ioh_gpio.c +++ b/trunk/drivers/gpio/ml_ioh_gpio.c @@ -326,7 +326,6 @@ static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = { { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) }, { 0, } }; -MODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id); static struct pci_driver ioh_gpio_driver = { .name = "ml_ioh_gpio", diff --git a/trunk/drivers/gpio/pch_gpio.c b/trunk/drivers/gpio/pch_gpio.c index 2c6af8705103..0eba0a75c804 100644 --- a/trunk/drivers/gpio/pch_gpio.c +++ b/trunk/drivers/gpio/pch_gpio.c @@ -286,7 +286,6 @@ static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, { 0, } }; -MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id); static struct pci_driver pch_gpio_driver = { .name = "pch_gpio", diff --git a/trunk/drivers/gpu/drm/i915/i915_reg.h b/trunk/drivers/gpu/drm/i915/i915_reg.h index 2abe240dae58..3e6f486f4605 100644 --- a/trunk/drivers/gpu/drm/i915/i915_reg.h +++ b/trunk/drivers/gpu/drm/i915/i915_reg.h @@ -1553,17 +1553,7 @@ /* Backlight control */ #define BLC_PWM_CTL 0x61254 -#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) #define BLC_PWM_CTL2 0x61250 /* 965+ only */ -#define BLM_COMBINATION_MODE (1 << 30) -/* - * This is the most significant 15 bits of the number of backlight cycles in a - * complete cycle of the modulated backlight control. - * - * The actual value is this field multiplied by two. - */ -#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) -#define BLM_LEGACY_MODE (1 << 16) /* * This is the number of cycles out of the backlight modulation cycle for which * the backlight is on. diff --git a/trunk/drivers/gpu/drm/i915/intel_panel.c b/trunk/drivers/gpu/drm/i915/intel_panel.c index f8f86e57df22..d860abeda70f 100644 --- a/trunk/drivers/gpu/drm/i915/intel_panel.c +++ b/trunk/drivers/gpu/drm/i915/intel_panel.c @@ -30,8 +30,6 @@ #include "intel_drv.h" -#define PCI_LBPC 0xf4 /* legacy/combination backlight modes */ - void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -112,19 +110,6 @@ intel_pch_panel_fitting(struct drm_device *dev, dev_priv->pch_pf_size = (width << 16) | height; } -static int is_backlight_combination_mode(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (INTEL_INFO(dev)->gen >= 4) - return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE; - - if (IS_GEN2(dev)) - return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE; - - return 0; -} - static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv) { u32 val; @@ -181,9 +166,6 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev) if (INTEL_INFO(dev)->gen < 4) max &= ~1; } - - if (is_backlight_combination_mode(dev)) - max *= 0xff; } DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); @@ -201,14 +183,6 @@ u32 intel_panel_get_backlight(struct drm_device *dev) val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; if (IS_PINEVIEW(dev)) val >>= 1; - - if (is_backlight_combination_mode(dev)){ - u8 lbpc; - - val &= ~1; - pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); - val *= lbpc; - } } DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); @@ -231,16 +205,6 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level) if (HAS_PCH_SPLIT(dev)) return intel_pch_panel_set_backlight(dev, level); - - if (is_backlight_combination_mode(dev)){ - u32 max = intel_panel_get_max_backlight(dev); - u8 lbpc; - - lbpc = level * 0xfe / max + 1; - level /= lbpc; - pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); - } - tmp = I915_READ(BLC_PWM_CTL); if (IS_PINEVIEW(dev)) { tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1); diff --git a/trunk/drivers/gpu/drm/radeon/evergreen.c b/trunk/drivers/gpu/drm/radeon/evergreen.c index 6140ea1de45a..d270b3ff896b 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen.c @@ -2194,6 +2194,7 @@ int evergreen_mc_init(struct radeon_device *rdev) rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; } rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; r700_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); @@ -2933,7 +2934,7 @@ static int evergreen_startup(struct radeon_device *rdev) /* XXX: ontario has problems blitting to gart at the moment */ if (rdev->family == CHIP_PALM) { rdev->asic->copy = NULL; - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; } /* allocate wb buffer */ diff --git a/trunk/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/trunk/drivers/gpu/drm/radeon/evergreen_blit_kms.c index 2be698e78ff2..2adfb03f479b 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen_blit_kms.c @@ -623,7 +623,7 @@ int evergreen_blit_init(struct radeon_device *rdev) dev_err(rdev->dev, "(%d) pin blit object failed\n", r); return r; } - radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + rdev->mc.active_vram_size = rdev->mc.real_vram_size; return 0; } @@ -631,7 +631,7 @@ void evergreen_blit_fini(struct radeon_device *rdev) { int r; - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; if (rdev->r600_blit.shader_obj == NULL) return; /* If we can't reserve the bo, unref should be enough to destroy diff --git a/trunk/drivers/gpu/drm/radeon/r100.c b/trunk/drivers/gpu/drm/radeon/r100.c index e372f9e1e5ce..93fa735c8c1a 100644 --- a/trunk/drivers/gpu/drm/radeon/r100.c +++ b/trunk/drivers/gpu/drm/radeon/r100.c @@ -70,6 +70,23 @@ MODULE_FIRMWARE(FIRMWARE_R520); void r100_pre_page_flip(struct radeon_device *rdev, int crtc) { + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; + u32 tmp; + + /* make sure flip is at vb rather than hb */ + tmp = RREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset); + tmp &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; + /* make sure pending bit is asserted */ + tmp |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; + WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, tmp); + + /* set pageflip to happen as late as possible in the vblank interval. + * same field for crtc1/2 + */ + tmp = RREG32(RADEON_CRTC_GEN_CNTL); + tmp &= ~RADEON_CRTC_VSTAT_MODE_MASK; + WREG32(RADEON_CRTC_GEN_CNTL, tmp); + /* enable the pflip int */ radeon_irq_kms_pflip_irq_get(rdev, crtc); } @@ -1024,7 +1041,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) return r; } rdev->cp.ready = true; - radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + rdev->mc.active_vram_size = rdev->mc.real_vram_size; return 0; } @@ -1042,7 +1059,7 @@ void r100_cp_fini(struct radeon_device *rdev) void r100_cp_disable(struct radeon_device *rdev) { /* Disable ring */ - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; rdev->cp.ready = false; WREG32(RADEON_CP_CSQ_MODE, 0); WREG32(RADEON_CP_CSQ_CNTL, 0); @@ -2312,6 +2329,7 @@ void r100_vram_init_sizes(struct radeon_device *rdev) /* FIXME we don't use the second aperture yet when we could use it */ if (rdev->mc.visible_vram_size > rdev->mc.aper_size) rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); if (rdev->flags & RADEON_IS_IGP) { uint32_t tom; diff --git a/trunk/drivers/gpu/drm/radeon/r600.c b/trunk/drivers/gpu/drm/radeon/r600.c index 9b3fad23b76c..de88624d5f87 100644 --- a/trunk/drivers/gpu/drm/radeon/r600.c +++ b/trunk/drivers/gpu/drm/radeon/r600.c @@ -1255,6 +1255,7 @@ int r600_mc_init(struct radeon_device *rdev) rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; r600_vram_gtt_location(rdev, &rdev->mc); if (rdev->flags & RADEON_IS_IGP) { @@ -1936,7 +1937,7 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) */ void r600_cp_stop(struct radeon_device *rdev) { - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); WREG32(SCRATCH_UMSK, 0); } diff --git a/trunk/drivers/gpu/drm/radeon/r600_blit_kms.c b/trunk/drivers/gpu/drm/radeon/r600_blit_kms.c index df68d91e8190..41f7aafc97c4 100644 --- a/trunk/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/trunk/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -558,7 +558,7 @@ int r600_blit_init(struct radeon_device *rdev) dev_err(rdev->dev, "(%d) pin blit object failed\n", r); return r; } - radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + rdev->mc.active_vram_size = rdev->mc.real_vram_size; return 0; } @@ -566,7 +566,7 @@ void r600_blit_fini(struct radeon_device *rdev) { int r; - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; if (rdev->r600_blit.shader_obj == NULL) return; /* If we can't reserve the bo, unref should be enough to destroy diff --git a/trunk/drivers/gpu/drm/radeon/radeon.h b/trunk/drivers/gpu/drm/radeon/radeon.h index 6b3429495118..56c48b67ef3d 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon.h +++ b/trunk/drivers/gpu/drm/radeon/radeon.h @@ -345,6 +345,7 @@ struct radeon_mc { * about vram size near mc fb location */ u64 mc_vram_size; u64 visible_vram_size; + u64 active_vram_size; u64 gtt_size; u64 gtt_start; u64 gtt_end; @@ -1447,7 +1448,6 @@ extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *m extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); extern int radeon_resume_kms(struct drm_device *dev); extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state); -extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size); /* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */ extern bool r600_card_posted(struct radeon_device *rdev); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_asic.c b/trunk/drivers/gpu/drm/radeon/radeon_asic.c index 793c5e6026ad..e75d63b8e21d 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_asic.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_asic.c @@ -834,9 +834,6 @@ static struct radeon_asic sumo_asic = { .pm_finish = &evergreen_pm_finish, .pm_init_profile = &rs780_pm_init_profile, .pm_get_dynpm_state = &r600_pm_get_dynpm_state, - .pre_page_flip = &evergreen_pre_page_flip, - .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, }; static struct radeon_asic btc_asic = { diff --git a/trunk/drivers/gpu/drm/radeon/radeon_gem.c b/trunk/drivers/gpu/drm/radeon/radeon_gem.c index 1fe95dfe48c9..df95eb83dac6 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_gem.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_gem.c @@ -156,12 +156,9 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_info *args = data; - struct ttm_mem_type_manager *man; - - man = &rdev->mman.bdev.man[TTM_PL_VRAM]; args->vram_size = rdev->mc.real_vram_size; - args->vram_visible = (u64)man->size << PAGE_SHIFT; + args->vram_visible = rdev->mc.real_vram_size; if (rdev->stollen_vga_memory) args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory); args->vram_visible -= radeon_fbdev_total_size(rdev); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 78968b738e88..cf0638c3b7c7 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -443,7 +443,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, (target_fb->bits_per_pixel * 8)); crtc_pitch |= crtc_pitch << 16; - crtc_offset_cntl |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; + if (tiling_flags & RADEON_TILING_MACRO) { if (ASIC_IS_R300(rdev)) crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | @@ -502,7 +502,6 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, gen_cntl_val = RREG32(gen_cntl_reg); gen_cntl_val &= ~(0xf << 8); gen_cntl_val |= (format << 8); - gen_cntl_val &= ~RADEON_CRTC_VSTAT_MODE_MASK; WREG32(gen_cntl_reg, gen_cntl_val); crtc_offset = (u32)base; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_ttm.c b/trunk/drivers/gpu/drm/radeon/radeon_ttm.c index 8389b4c63d12..e5b2cf10cbf4 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_ttm.c @@ -589,20 +589,6 @@ void radeon_ttm_fini(struct radeon_device *rdev) DRM_INFO("radeon: ttm finalized\n"); } -/* this should only be called at bootup or when userspace - * isn't running */ -void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size) -{ - struct ttm_mem_type_manager *man; - - if (!rdev->mman.initialized) - return; - - man = &rdev->mman.bdev.man[TTM_PL_VRAM]; - /* this just adjusts TTM size idea, which sets lpfn to the correct value */ - man->size = size >> PAGE_SHIFT; -} - static struct vm_operations_struct radeon_ttm_vm_ops; static const struct vm_operations_struct *ttm_vm_ops = NULL; diff --git a/trunk/drivers/gpu/drm/radeon/rs600.c b/trunk/drivers/gpu/drm/radeon/rs600.c index 8af4679db23e..5afe294ed51f 100644 --- a/trunk/drivers/gpu/drm/radeon/rs600.c +++ b/trunk/drivers/gpu/drm/radeon/rs600.c @@ -751,6 +751,7 @@ void rs600_mc_init(struct radeon_device *rdev) rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); rdev->mc.mc_vram_size = rdev->mc.real_vram_size; rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); base = RREG32_MC(R_000004_MC_FB_LOCATION); base = G_000004_MC_FB_START(base) << 16; diff --git a/trunk/drivers/gpu/drm/radeon/rs690.c b/trunk/drivers/gpu/drm/radeon/rs690.c index 66c949b7c18c..6638c8e4c81b 100644 --- a/trunk/drivers/gpu/drm/radeon/rs690.c +++ b/trunk/drivers/gpu/drm/radeon/rs690.c @@ -157,6 +157,7 @@ void rs690_mc_init(struct radeon_device *rdev) rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); base = G_000100_MC_FB_START(base) << 16; rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); diff --git a/trunk/drivers/gpu/drm/radeon/rv770.c b/trunk/drivers/gpu/drm/radeon/rv770.c index 714ad45757d0..d8ba67690656 100644 --- a/trunk/drivers/gpu/drm/radeon/rv770.c +++ b/trunk/drivers/gpu/drm/radeon/rv770.c @@ -307,7 +307,7 @@ static void rv770_mc_program(struct radeon_device *rdev) */ void r700_cp_stop(struct radeon_device *rdev) { - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); WREG32(SCRATCH_UMSK, 0); } @@ -1123,6 +1123,7 @@ int rv770_mc_init(struct radeon_device *rdev) rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; r700_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); diff --git a/trunk/drivers/hwmon/f71882fg.c b/trunk/drivers/hwmon/f71882fg.c index 6e06019015a5..3f49dd376f02 100644 --- a/trunk/drivers/hwmon/f71882fg.c +++ b/trunk/drivers/hwmon/f71882fg.c @@ -37,7 +37,7 @@ #define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */ #define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */ #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ -#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */ +#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ #define SIO_REG_LDSEL 0x07 /* Logical device select */ #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ @@ -2111,6 +2111,7 @@ static int f71882fg_remove(struct platform_device *pdev) int nr_fans = (data->type == f71882fg) ? 4 : 3; u8 start_reg = f71882fg_read8(data, F71882FG_REG_START); + platform_set_drvdata(pdev, NULL); if (data->hwmon_dev) hwmon_device_unregister(data->hwmon_dev); @@ -2177,7 +2178,6 @@ static int f71882fg_remove(struct platform_device *pdev) } } - platform_set_drvdata(pdev, NULL); kfree(data); return 0; diff --git a/trunk/drivers/i2c/busses/i2c-eg20t.c b/trunk/drivers/i2c/busses/i2c-eg20t.c index 50ea1f43bdc1..2e067dd2ee51 100644 --- a/trunk/drivers/i2c/busses/i2c-eg20t.c +++ b/trunk/drivers/i2c/busses/i2c-eg20t.c @@ -29,7 +29,6 @@ #include #include #include -#include #define PCH_EVENT_SET 0 /* I2C Interrupt Event Set Status */ #define PCH_EVENT_NONE 1 /* I2C Interrupt Event Clear Status */ diff --git a/trunk/drivers/i2c/busses/i2c-ocores.c b/trunk/drivers/i2c/busses/i2c-ocores.c index 61653f079671..ef3bcb1ce864 100644 --- a/trunk/drivers/i2c/busses/i2c-ocores.c +++ b/trunk/drivers/i2c/busses/i2c-ocores.c @@ -249,7 +249,7 @@ static struct i2c_adapter ocores_adapter = { static int ocores_i2c_of_probe(struct platform_device* pdev, struct ocores_i2c* i2c) { - const __be32* val; + __be32* val; val = of_get_property(pdev->dev.of_node, "regstep", NULL); if (!val) { diff --git a/trunk/drivers/i2c/busses/i2c-omap.c b/trunk/drivers/i2c/busses/i2c-omap.c index 58a58c7eaa17..829a2a1029f7 100644 --- a/trunk/drivers/i2c/busses/i2c-omap.c +++ b/trunk/drivers/i2c/busses/i2c-omap.c @@ -378,7 +378,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) * REVISIT: Some wkup sources might not be needed. */ dev->westate = OMAP_I2C_WE_ALL; - omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); + if (dev->rev < OMAP_I2C_REV_ON_4430) + omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, + dev->westate); } } omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); diff --git a/trunk/drivers/media/common/tuners/tda8290.c b/trunk/drivers/media/common/tuners/tda8290.c index 8c4852114eeb..bc6a67768af1 100644 --- a/trunk/drivers/media/common/tuners/tda8290.c +++ b/trunk/drivers/media/common/tuners/tda8290.c @@ -658,13 +658,13 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props) #define TDA8290_ID 0x89 u8 reg = 0x1f, id; struct i2c_msg msg_read[] = { - { .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = ® }, - { .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id }, + { .addr = 0x4b, .flags = 0, .len = 1, .buf = ® }, + { .addr = 0x4b, .flags = I2C_M_RD, .len = 1, .buf = &id }, }; /* detect tda8290 */ if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) { - printk(KERN_WARNING "%s: couldn't read register 0x%02x\n", + printk(KERN_WARNING "%s: tda8290 couldn't read register 0x%02x\n", __func__, reg); return -ENODEV; } @@ -685,13 +685,13 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props) #define TDA8295C2_ID 0x8b u8 reg = 0x2f, id; struct i2c_msg msg_read[] = { - { .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = ® }, - { .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id }, + { .addr = 0x4b, .flags = 0, .len = 1, .buf = ® }, + { .addr = 0x4b, .flags = I2C_M_RD, .len = 1, .buf = &id }, }; - /* detect tda8295 */ + /* detect tda8290 */ if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) { - printk(KERN_WARNING "%s: couldn't read register 0x%02x\n", + printk(KERN_WARNING "%s: tda8290 couldn't read register 0x%02x\n", __func__, reg); return -ENODEV; } diff --git a/trunk/drivers/media/dvb/dvb-usb/dib0700_devices.c b/trunk/drivers/media/dvb/dvb-usb/dib0700_devices.c index 193cdb77b76a..defd83964ce2 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/trunk/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -870,23 +870,6 @@ static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap) return 0; } -static int stk7700p_pid_filter(struct dvb_usb_adapter *adapter, int index, - u16 pid, int onoff) -{ - struct dib0700_state *st = adapter->dev->priv; - if (st->is_dib7000pc) - return dib7000p_pid_filter(adapter->fe, index, pid, onoff); - return dib7000m_pid_filter(adapter->fe, index, pid, onoff); -} - -static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) -{ - struct dib0700_state *st = adapter->dev->priv; - if (st->is_dib7000pc) - return dib7000p_pid_filter_ctrl(adapter->fe, onoff); - return dib7000m_pid_filter_ctrl(adapter->fe, onoff); -} - static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) { return dib7000p_pid_filter(adapter->fe, index, pid, onoff); @@ -1892,8 +1875,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .pid_filter = stk7700p_pid_filter, - .pid_filter_ctrl = stk7700p_pid_filter_ctrl, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, .frontend_attach = stk7700p_frontend_attach, .tuner_attach = stk7700p_tuner_attach, diff --git a/trunk/drivers/media/dvb/dvb-usb/lmedm04.c b/trunk/drivers/media/dvb/dvb-usb/lmedm04.c index 46ccd01a7696..9eea4188303b 100644 --- a/trunk/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/trunk/drivers/media/dvb/dvb-usb/lmedm04.c @@ -659,7 +659,7 @@ static int lme2510_download_firmware(struct usb_device *dev, } /* Default firmware for LME2510C */ -char lme_firmware[50] = "dvb-usb-lme2510c-s7395.fw"; +const char lme_firmware[50] = "dvb-usb-lme2510c-s7395.fw"; static void lme_coldreset(struct usb_device *dev) { @@ -1006,7 +1006,7 @@ static struct dvb_usb_device_properties lme2510c_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = DEVICE_SPECIFIC, .download_firmware = lme2510_download_firmware, - .firmware = (const char *)&lme_firmware, + .firmware = lme_firmware, .size_of_priv = sizeof(struct lme2510_state), .num_adapters = 1, .adapter = { @@ -1109,5 +1109,5 @@ module_exit(lme2510_module_exit); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); -MODULE_VERSION("1.75"); +MODULE_VERSION("1.74"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/media/dvb/frontends/dib7000m.c b/trunk/drivers/media/dvb/frontends/dib7000m.c index 289a79837f24..c7f5ccf54aa5 100644 --- a/trunk/drivers/media/dvb/frontends/dib7000m.c +++ b/trunk/drivers/media/dvb/frontends/dib7000m.c @@ -1285,25 +1285,6 @@ struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum di } EXPORT_SYMBOL(dib7000m_get_i2c_master); -int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) -{ - struct dib7000m_state *state = fe->demodulator_priv; - u16 val = dib7000m_read_word(state, 294 + state->reg_offs) & 0xffef; - val |= (onoff & 0x1) << 4; - dprintk("PID filter enabled %d", onoff); - return dib7000m_write_word(state, 294 + state->reg_offs, val); -} -EXPORT_SYMBOL(dib7000m_pid_filter_ctrl); - -int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) -{ - struct dib7000m_state *state = fe->demodulator_priv; - dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff); - return dib7000m_write_word(state, 300 + state->reg_offs + id, - onoff ? (1 << 13) | pid : 0); -} -EXPORT_SYMBOL(dib7000m_pid_filter); - #if 0 /* used with some prototype boards */ int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, diff --git a/trunk/drivers/media/dvb/frontends/dib7000m.h b/trunk/drivers/media/dvb/frontends/dib7000m.h index 81fcf2241c64..113819ce9f0d 100644 --- a/trunk/drivers/media/dvb/frontends/dib7000m.h +++ b/trunk/drivers/media/dvb/frontends/dib7000m.h @@ -46,8 +46,6 @@ extern struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap, extern struct i2c_adapter *dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); -extern int dib7000m_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff); -extern int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff); #else static inline struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap, @@ -65,19 +63,6 @@ struct i2c_adapter *dib7000m_get_i2c_master(struct dvb_frontend *demod, printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } -static inline int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, - u16 pid, u8 onoff) -{ - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return -ENODEV; -} - -static inline int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, - uint8_t onoff) -{ - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return -ENODEV; -} #endif /* TODO diff --git a/trunk/drivers/media/dvb/mantis/mantis_pci.c b/trunk/drivers/media/dvb/mantis/mantis_pci.c index 10a432a79d00..59feeb84aec7 100644 --- a/trunk/drivers/media/dvb/mantis/mantis_pci.c +++ b/trunk/drivers/media/dvb/mantis/mantis_pci.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/drivers/media/rc/ir-raw.c b/trunk/drivers/media/rc/ir-raw.c index 01f258a2a57a..73230ff93b8a 100644 --- a/trunk/drivers/media/rc/ir-raw.c +++ b/trunk/drivers/media/rc/ir-raw.c @@ -112,7 +112,7 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type) { ktime_t now; s64 delta; /* ns */ - DEFINE_IR_RAW_EVENT(ev); + struct ir_raw_event ev; int rc = 0; if (!dev->raw) @@ -125,6 +125,7 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type) * being called for the first time, note that delta can't * possibly be negative. */ + ev.duration = 0; if (delta > IR_MAX_DURATION || !dev->raw->last_type) type |= IR_START_EVENT; else diff --git a/trunk/drivers/media/rc/mceusb.c b/trunk/drivers/media/rc/mceusb.c index e4f8eac7f717..6df0a4980645 100644 --- a/trunk/drivers/media/rc/mceusb.c +++ b/trunk/drivers/media/rc/mceusb.c @@ -148,7 +148,6 @@ enum mceusb_model_type { MCE_GEN2_TX_INV, POLARIS_EVK, CX_HYBRID_TV, - MULTIFUNCTION, }; struct mceusb_model { @@ -156,10 +155,9 @@ struct mceusb_model { u32 mce_gen2:1; u32 mce_gen3:1; u32 tx_mask_normal:1; + u32 is_polaris:1; u32 no_tx:1; - int ir_intfnum; - const char *rc_map; /* Allow specify a per-board map */ const char *name; /* per-board name */ }; @@ -181,6 +179,7 @@ static const struct mceusb_model mceusb_model[] = { .tx_mask_normal = 1, }, [POLARIS_EVK] = { + .is_polaris = 1, /* * In fact, the EVK is shipped without * remotes, but we should have something handy, @@ -190,13 +189,10 @@ static const struct mceusb_model mceusb_model[] = { .name = "Conexant Hybrid TV (cx231xx) MCE IR", }, [CX_HYBRID_TV] = { + .is_polaris = 1, .no_tx = 1, /* tx isn't wired up at all */ .name = "Conexant Hybrid TV (cx231xx) MCE IR", }, - [MULTIFUNCTION] = { - .mce_gen2 = 1, - .ir_intfnum = 2, - }, }; static struct usb_device_id mceusb_dev_table[] = { @@ -220,9 +216,8 @@ static struct usb_device_id mceusb_dev_table[] = { { USB_DEVICE(VENDOR_PHILIPS, 0x206c) }, /* Philips/Spinel plus IR transceiver for ASUS */ { USB_DEVICE(VENDOR_PHILIPS, 0x2088) }, - /* Realtek MCE IR Receiver and card reader */ - { USB_DEVICE(VENDOR_REALTEK, 0x0161), - .driver_info = MULTIFUNCTION }, + /* Realtek MCE IR Receiver */ + { USB_DEVICE(VENDOR_REALTEK, 0x0161) }, /* SMK/Toshiba G83C0004D410 */ { USB_DEVICE(VENDOR_SMK, 0x031d), .driver_info = MCE_GEN2_TX_INV }, @@ -1106,7 +1101,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, bool is_gen3; bool is_microsoft_gen1; bool tx_mask_normal; - int ir_intfnum; + bool is_polaris; dev_dbg(&intf->dev, "%s called\n", __func__); @@ -1115,11 +1110,13 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, is_gen3 = mceusb_model[model].mce_gen3; is_microsoft_gen1 = mceusb_model[model].mce_gen1; tx_mask_normal = mceusb_model[model].tx_mask_normal; - ir_intfnum = mceusb_model[model].ir_intfnum; + is_polaris = mceusb_model[model].is_polaris; - /* There are multi-function devices with non-IR interfaces */ - if (idesc->desc.bInterfaceNumber != ir_intfnum) - return -ENODEV; + if (is_polaris) { + /* Interface 0 is IR */ + if (idesc->desc.bInterfaceNumber) + return -ENODEV; + } /* step through the endpoints to find first bulk in and out endpoint */ for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { diff --git a/trunk/drivers/media/rc/nuvoton-cir.c b/trunk/drivers/media/rc/nuvoton-cir.c index d4d64492a057..273d9d674792 100644 --- a/trunk/drivers/media/rc/nuvoton-cir.c +++ b/trunk/drivers/media/rc/nuvoton-cir.c @@ -385,9 +385,8 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt) static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) { - /* set number of bytes needed for wake from s3 (default 65) */ - nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_CMP_BYTES, - CIR_WAKE_FIFO_CMP_DEEP); + /* set number of bytes needed for wake key comparison (default 67) */ + nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_LEN, CIR_WAKE_FIFO_CMP_DEEP); /* set tolerance/variance allowed per byte during wake compare */ nvt_cir_wake_reg_write(nvt, CIR_WAKE_CMP_TOLERANCE, diff --git a/trunk/drivers/media/rc/nuvoton-cir.h b/trunk/drivers/media/rc/nuvoton-cir.h index 048135eea702..1df82351cb03 100644 --- a/trunk/drivers/media/rc/nuvoton-cir.h +++ b/trunk/drivers/media/rc/nuvoton-cir.h @@ -305,11 +305,8 @@ struct nvt_dev { #define CIR_WAKE_IRFIFOSTS_RX_EMPTY 0x20 #define CIR_WAKE_IRFIFOSTS_RX_FULL 0x10 -/* - * The CIR Wake FIFO buffer is 67 bytes long, but the stock remote wakes - * the system comparing only 65 bytes (fails with this set to 67) - */ -#define CIR_WAKE_FIFO_CMP_BYTES 65 +/* CIR Wake FIFO buffer is 67 bytes long */ +#define CIR_WAKE_FIFO_LEN 67 /* CIR Wake byte comparison tolerance */ #define CIR_WAKE_CMP_TOLERANCE 5 diff --git a/trunk/drivers/media/rc/rc-main.c b/trunk/drivers/media/rc/rc-main.c index 5b4422ef4e6d..512a2f4ada0e 100644 --- a/trunk/drivers/media/rc/rc-main.c +++ b/trunk/drivers/media/rc/rc-main.c @@ -850,7 +850,7 @@ static ssize_t store_protocols(struct device *device, count++; } else { for (i = 0; i < ARRAY_SIZE(proto_names); i++) { - if (!strcasecmp(tmp, proto_names[i].name)) { + if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) { tmp += strlen(proto_names[i].name); mask = proto_names[i].type; break; diff --git a/trunk/drivers/media/video/au0828/au0828-video.c b/trunk/drivers/media/video/au0828/au0828-video.c index 9c475c600fc9..e41e4ad5cc40 100644 --- a/trunk/drivers/media/video/au0828/au0828-video.c +++ b/trunk/drivers/media/video/au0828/au0828-video.c @@ -1758,12 +1758,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, if (rc < 0) return rc; - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_reqbufs(&fh->vb_vidq, rb); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_reqbufs(&fh->vb_vbiq, rb); - - return rc; + return videobuf_reqbufs(&fh->vb_vidq, rb); } static int vidioc_querybuf(struct file *file, void *priv, @@ -1777,12 +1772,7 @@ static int vidioc_querybuf(struct file *file, void *priv, if (rc < 0) return rc; - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_querybuf(&fh->vb_vidq, b); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_querybuf(&fh->vb_vbiq, b); - - return rc; + return videobuf_querybuf(&fh->vb_vidq, b); } static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1795,12 +1785,7 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) if (rc < 0) return rc; - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_qbuf(&fh->vb_vidq, b); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_qbuf(&fh->vb_vbiq, b); - - return rc; + return videobuf_qbuf(&fh->vb_vidq, b); } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1821,12 +1806,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) dev->greenscreen_detected = 0; } - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK); - - return rc; + return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); } static struct v4l2_file_operations au0828_v4l_fops = { diff --git a/trunk/drivers/media/video/cx18/cx18-cards.c b/trunk/drivers/media/video/cx18/cx18-cards.c index 68ad1963f421..87177733cf92 100644 --- a/trunk/drivers/media/video/cx18/cx18-cards.c +++ b/trunk/drivers/media/video/cx18/cx18-cards.c @@ -95,53 +95,6 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { .i2c = &cx18_i2c_std, }; -static const struct cx18_card cx18_card_hvr1600_s5h1411 = { - .type = CX18_CARD_HVR_1600_S5H1411, - .name = "Hauppauge HVR-1600", - .comment = "Simultaneous Digital and Analog TV capture supported\n", - .v4l2_capabilities = CX18_CAP_ENCODER, - .hw_audio_ctrl = CX18_HW_418_AV, - .hw_muxer = CX18_HW_CS5345, - .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | - CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL | - CX18_HW_Z8F0811_IR_HAUP, - .video_inputs = { - { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, - { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 }, - { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 }, - { CX18_CARD_INPUT_SVIDEO2, 2, CX18_AV_SVIDEO2 }, - { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 }, - }, - .audio_inputs = { - { CX18_CARD_INPUT_AUD_TUNER, - CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 }, - { CX18_CARD_INPUT_LINE_IN1, - CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 }, - { CX18_CARD_INPUT_LINE_IN2, - CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 }, - }, - .radio_input = { CX18_CARD_INPUT_AUD_TUNER, - CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 }, - .ddr = { - /* ESMT M13S128324A-5B memory */ - .chip_config = 0x003, - .refresh = 0x30c, - .timing1 = 0x44220e82, - .timing2 = 0x08, - .tune_lane = 0, - .initial_emrs = 0, - }, - .gpio_init.initial_value = 0x3001, - .gpio_init.direction = 0x3001, - .gpio_i2c_slave_reset = { - .active_lo_mask = 0x3001, - .msecs_asserted = 10, - .msecs_recovery = 40, - .ir_reset_mask = 0x0001, - }, - .i2c = &cx18_i2c_std, -}; - static const struct cx18_card cx18_card_hvr1600_samsung = { .type = CX18_CARD_HVR_1600_SAMSUNG, .name = "Hauppauge HVR-1600 (Preproduction)", @@ -570,8 +523,7 @@ static const struct cx18_card *cx18_card_list[] = { &cx18_card_toshiba_qosmio_dvbt, &cx18_card_leadtek_pvr2100, &cx18_card_leadtek_dvr3100h, - &cx18_card_gotview_dvd3, - &cx18_card_hvr1600_s5h1411 + &cx18_card_gotview_dvd3 }; const struct cx18_card *cx18_get_card(u16 index) diff --git a/trunk/drivers/media/video/cx18/cx18-driver.c b/trunk/drivers/media/video/cx18/cx18-driver.c index b1c3cbd92743..944af8adbe0c 100644 --- a/trunk/drivers/media/video/cx18/cx18-driver.c +++ b/trunk/drivers/media/video/cx18/cx18-driver.c @@ -157,7 +157,6 @@ MODULE_PARM_DESC(cardtype, "\t\t\t 7 = Leadtek WinFast PVR2100\n" "\t\t\t 8 = Leadtek WinFast DVR3100 H\n" "\t\t\t 9 = GoTView PCI DVD3 Hybrid\n" - "\t\t\t 10 = Hauppauge HVR 1600 (S5H1411)\n" "\t\t\t 0 = Autodetect (default)\n" "\t\t\t-1 = Ignore this card\n\t\t"); MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); @@ -338,7 +337,6 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) switch (cx->card->type) { case CX18_CARD_HVR_1600_ESMT: case CX18_CARD_HVR_1600_SAMSUNG: - case CX18_CARD_HVR_1600_S5H1411: tveeprom_hauppauge_analog(&c, tv, eedata); break; case CX18_CARD_YUAN_MPC718: @@ -367,25 +365,7 @@ static void cx18_process_eeprom(struct cx18 *cx) from the model number. Use the cardtype module option if you have one of these preproduction models. */ switch (tv.model) { - case 74301: /* Retail models */ - case 74321: - case 74351: /* OEM models */ - case 74361: - /* Digital side is s5h1411/tda18271 */ - cx->card = cx18_get_card(CX18_CARD_HVR_1600_S5H1411); - break; - case 74021: /* Retail models */ - case 74031: - case 74041: - case 74141: - case 74541: /* OEM models */ - case 74551: - case 74591: - case 74651: - case 74691: - case 74751: - case 74891: - /* Digital side is s5h1409/mxl5005s */ + case 74000 ... 74999: cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); break; case 0x718: @@ -397,8 +377,7 @@ static void cx18_process_eeprom(struct cx18 *cx) CX18_ERR("Invalid EEPROM\n"); return; default: - CX18_ERR("Unknown model %d, defaulting to original HVR-1600 " - "(cardtype=1)\n", tv.model); + CX18_ERR("Unknown model %d, defaulting to HVR-1600\n", tv.model); cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); break; } diff --git a/trunk/drivers/media/video/cx18/cx18-driver.h b/trunk/drivers/media/video/cx18/cx18-driver.h index f736679d2517..306caac6d3fc 100644 --- a/trunk/drivers/media/video/cx18/cx18-driver.h +++ b/trunk/drivers/media/video/cx18/cx18-driver.h @@ -85,8 +85,7 @@ #define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100 */ #define CX18_CARD_LEADTEK_DVR3100H 7 /* Leadtek WinFast DVR3100 H */ #define CX18_CARD_GOTVIEW_PCI_DVD3 8 /* GoTView PCI DVD3 Hybrid */ -#define CX18_CARD_HVR_1600_S5H1411 9 /* Hauppauge HVR 1600 s5h1411/tda18271*/ -#define CX18_CARD_LAST 9 +#define CX18_CARD_LAST 8 #define CX18_ENC_STREAM_TYPE_MPG 0 #define CX18_ENC_STREAM_TYPE_TS 1 diff --git a/trunk/drivers/media/video/cx18/cx18-dvb.c b/trunk/drivers/media/video/cx18/cx18-dvb.c index f41922bd4020..f0381d62518d 100644 --- a/trunk/drivers/media/video/cx18/cx18-dvb.c +++ b/trunk/drivers/media/video/cx18/cx18-dvb.c @@ -29,8 +29,6 @@ #include "cx18-gpio.h" #include "s5h1409.h" #include "mxl5005s.h" -#include "s5h1411.h" -#include "tda18271.h" #include "zl10353.h" #include @@ -78,32 +76,6 @@ static struct s5h1409_config hauppauge_hvr1600_config = { .hvr1600_opt = S5H1409_HVR1600_OPTIMIZE }; -/* - * CX18_CARD_HVR_1600_S5H1411 - */ -static struct s5h1411_config hcw_s5h1411_config = { - .output_mode = S5H1411_SERIAL_OUTPUT, - .gpio = S5H1411_GPIO_OFF, - .vsb_if = S5H1411_IF_44000, - .qam_if = S5H1411_IF_4000, - .inversion = S5H1411_INVERSION_ON, - .status_mode = S5H1411_DEMODLOCKING, - .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, -}; - -static struct tda18271_std_map hauppauge_tda18271_std_map = { - .atsc_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3, - .if_lvl = 6, .rfagc_top = 0x37 }, - .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0, - .if_lvl = 6, .rfagc_top = 0x37 }, -}; - -static struct tda18271_config hauppauge_tda18271_config = { - .std_map = &hauppauge_tda18271_std_map, - .gate = TDA18271_GATE_DIGITAL, - .output_opt = TDA18271_OUTPUT_LT_OFF, -}; - /* * CX18_CARD_LEADTEK_DVR3100H */ @@ -272,7 +244,6 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) switch (cx->card->type) { case CX18_CARD_HVR_1600_ESMT: case CX18_CARD_HVR_1600_SAMSUNG: - case CX18_CARD_HVR_1600_S5H1411: v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL); v |= 0x00400000; /* Serial Mode */ v |= 0x00002000; /* Data Length - Byte */ @@ -484,15 +455,6 @@ static int dvb_register(struct cx18_stream *stream) ret = 0; } break; - case CX18_CARD_HVR_1600_S5H1411: - dvb->fe = dvb_attach(s5h1411_attach, - &hcw_s5h1411_config, - &cx->i2c_adap[0]); - if (dvb->fe != NULL) - dvb_attach(tda18271_attach, dvb->fe, - 0x60, &cx->i2c_adap[0], - &hauppauge_tda18271_config); - break; case CX18_CARD_LEADTEK_DVR3100H: dvb->fe = dvb_attach(zl10353_attach, &leadtek_dvr3100h_demod, diff --git a/trunk/drivers/media/video/cx23885/cx23885-i2c.c b/trunk/drivers/media/video/cx23885/cx23885-i2c.c index 307ff543c254..ed3d8f55029b 100644 --- a/trunk/drivers/media/video/cx23885/cx23885-i2c.c +++ b/trunk/drivers/media/video/cx23885/cx23885-i2c.c @@ -122,6 +122,10 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, if (!i2c_wait_done(i2c_adap)) goto eio; + if (!i2c_slave_did_ack(i2c_adap)) { + retval = -ENXIO; + goto err; + } if (i2c_debug) { printk(" addr << 1, msg->buf[0]); if (!(ctrl & I2C_NOSTOP)) @@ -154,6 +158,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, eio: retval = -EIO; + err: if (i2c_debug) printk(KERN_ERR " ERR: %d\n", retval); return retval; @@ -204,6 +209,10 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, if (!i2c_wait_done(i2c_adap)) goto eio; + if (cnt == 0 && !i2c_slave_did_ack(i2c_adap)) { + retval = -ENXIO; + goto err; + } msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff; if (i2c_debug) { dprintk(1, " %02x", msg->buf[cnt]); @@ -215,6 +224,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, eio: retval = -EIO; + err: if (i2c_debug) printk(KERN_ERR " ERR: %d\n", retval); return retval; diff --git a/trunk/drivers/media/video/cx25840/cx25840-core.c b/trunk/drivers/media/video/cx25840/cx25840-core.c index 35796e035247..6fc09dd41b9d 100644 --- a/trunk/drivers/media/video/cx25840/cx25840-core.c +++ b/trunk/drivers/media/video/cx25840/cx25840-core.c @@ -2015,8 +2015,7 @@ static int cx25840_probe(struct i2c_client *client, kfree(state); return err; } - if (!is_cx2583x(state)) - v4l2_ctrl_cluster(2, &state->volume); + v4l2_ctrl_cluster(2, &state->volume); v4l2_ctrl_handler_setup(&state->hdl); if (client->dev.platform_data) { diff --git a/trunk/drivers/media/video/ivtv/ivtv-irq.c b/trunk/drivers/media/video/ivtv/ivtv-irq.c index 9c29e964d400..9b4faf009196 100644 --- a/trunk/drivers/media/video/ivtv/ivtv-irq.c +++ b/trunk/drivers/media/video/ivtv/ivtv-irq.c @@ -628,66 +628,22 @@ static void ivtv_irq_enc_pio_complete(struct ivtv *itv) static void ivtv_irq_dma_err(struct ivtv *itv) { u32 data[CX2341X_MBOX_MAX_DATA]; - u32 status; del_timer(&itv->dma_timer); - ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data); - status = read_reg(IVTV_REG_DMASTATUS); IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1], - status, itv->cur_dma_stream); - /* - * We do *not* write back to the IVTV_REG_DMASTATUS register to - * clear the error status, if either the encoder write (0x02) or - * decoder read (0x01) bus master DMA operation do not indicate - * completed. We can race with the DMA engine, which may have - * transitioned to completed status *after* we read the register. - * Setting a IVTV_REG_DMASTATUS flag back to "busy" status, after the - * DMA engine has completed, will cause the DMA engine to stop working. - */ - status &= 0x3; - if (status == 0x3) - write_reg(status, IVTV_REG_DMASTATUS); - + read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream); + write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream >= 0 && itv->cur_dma_stream < IVTV_MAX_STREAMS) { struct ivtv_stream *s = &itv->streams[itv->cur_dma_stream]; - if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { - /* retry */ - /* - * FIXME - handle cases of DMA error similar to - * encoder below, except conditioned on status & 0x1 - */ + /* retry */ + if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) ivtv_dma_dec_start(s); - return; - } else { - if ((status & 0x2) == 0) { - /* - * CX2341x Bus Master DMA write is ongoing. - * Reset the timer and let it complete. - */ - itv->dma_timer.expires = - jiffies + msecs_to_jiffies(600); - add_timer(&itv->dma_timer); - return; - } - - if (itv->dma_retries < 3) { - /* - * CX2341x Bus Master DMA write has ended. - * Retry the write, starting with the first - * xfer segment. Just retrying the current - * segment is not sufficient. - */ - s->sg_processed = 0; - itv->dma_retries++; - ivtv_dma_enc_start_xfer(s); - return; - } - /* Too many retries, give up on this one */ - } - + else + ivtv_dma_enc_start(s); + return; } if (test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { ivtv_udma_start(itv); diff --git a/trunk/drivers/media/video/mem2mem_testdev.c b/trunk/drivers/media/video/mem2mem_testdev.c index e7e717800ee2..c179041d91f8 100644 --- a/trunk/drivers/media/video/mem2mem_testdev.c +++ b/trunk/drivers/media/video/mem2mem_testdev.c @@ -1011,6 +1011,7 @@ static int m2mtest_remove(struct platform_device *pdev) v4l2_m2m_release(dev->m2m_dev); del_timer_sync(&dev->timer); video_unregister_device(dev->vfd); + video_device_release(dev->vfd); v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); diff --git a/trunk/drivers/media/video/s2255drv.c b/trunk/drivers/media/video/s2255drv.c index 561909b65ce6..b63f8cafa671 100644 --- a/trunk/drivers/media/video/s2255drv.c +++ b/trunk/drivers/media/video/s2255drv.c @@ -57,7 +57,7 @@ #include #define S2255_MAJOR_VERSION 1 -#define S2255_MINOR_VERSION 21 +#define S2255_MINOR_VERSION 20 #define S2255_RELEASE 0 #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ S2255_MINOR_VERSION, \ @@ -312,9 +312,9 @@ struct s2255_fh { }; /* current cypress EEPROM firmware version */ -#define S2255_CUR_USB_FWVER ((3 << 8) | 11) +#define S2255_CUR_USB_FWVER ((3 << 8) | 6) /* current DSP FW version */ -#define S2255_CUR_DSP_FWVER 10102 +#define S2255_CUR_DSP_FWVER 8 /* Need DSP version 5+ for video status feature */ #define S2255_MIN_DSP_STATUS 5 #define S2255_MIN_DSP_COLORFILTER 8 @@ -492,11 +492,9 @@ static void planar422p_to_yuv_packed(const unsigned char *in, static void s2255_reset_dsppower(struct s2255_dev *dev) { - s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b01, NULL, 0, 1); + s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b0b, NULL, 0, 1); msleep(10); s2255_vendor_req(dev, 0x50, 0x0000, 0x0000, NULL, 0, 1); - msleep(600); - s2255_vendor_req(dev, 0x10, 0x0000, 0x0000, NULL, 0, 1); return; } diff --git a/trunk/drivers/mmc/core/core.c b/trunk/drivers/mmc/core/core.c index 150b5f3cd401..6625c057be05 100644 --- a/trunk/drivers/mmc/core/core.c +++ b/trunk/drivers/mmc/core/core.c @@ -1529,7 +1529,7 @@ void mmc_rescan(struct work_struct *work) * still present */ if (host->bus_ops && host->bus_ops->detect && !host->bus_dead - && !(host->caps & MMC_CAP_NONREMOVABLE)) + && mmc_card_is_removable(host)) host->bus_ops->detect(host); /* diff --git a/trunk/drivers/mtd/chips/cfi_cmdset_0001.c b/trunk/drivers/mtd/chips/cfi_cmdset_0001.c index 4aaa88f8ab5f..a8c3e1c9b02a 100644 --- a/trunk/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/trunk/drivers/mtd/chips/cfi_cmdset_0001.c @@ -1230,32 +1230,10 @@ static int inval_cache_and_wait_for_operation( sleep_time = chip_op_time / 2; for (;;) { - if (chip->state != chip_state) { - /* Someone's suspended the operation: sleep */ - DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - mutex_unlock(&chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); - mutex_lock(&chip->mutex); - continue; - } - status = map_read(map, cmd_adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - if (chip->erase_suspended && chip_state == FL_ERASING) { - /* Erase suspend occured while sleep: reset timeout */ - timeo = reset_timeo; - chip->erase_suspended = 0; - } - if (chip->write_suspended && chip_state == FL_WRITING) { - /* Write suspend occured while sleep: reset timeout */ - timeo = reset_timeo; - chip->write_suspended = 0; - } if (!timeo) { map_write(map, CMD(0x70), cmd_adr); chip->state = FL_STATUS; @@ -1279,6 +1257,27 @@ static int inval_cache_and_wait_for_operation( timeo--; } mutex_lock(&chip->mutex); + + while (chip->state != chip_state) { + /* Someone's suspended the operation: sleep */ + DECLARE_WAITQUEUE(wait, current); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + mutex_unlock(&chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + mutex_lock(&chip->mutex); + } + if (chip->erase_suspended && chip_state == FL_ERASING) { + /* Erase suspend occured while sleep: reset timeout */ + timeo = reset_timeo; + chip->erase_suspended = 0; + } + if (chip->write_suspended && chip_state == FL_WRITING) { + /* Write suspend occured while sleep: reset timeout */ + timeo = reset_timeo; + chip->write_suspended = 0; + } } /* Done and happy. */ diff --git a/trunk/drivers/mtd/chips/jedec_probe.c b/trunk/drivers/mtd/chips/jedec_probe.c index 4e1be51cc122..d72a5fb2d041 100644 --- a/trunk/drivers/mtd/chips/jedec_probe.c +++ b/trunk/drivers/mtd/chips/jedec_probe.c @@ -1935,14 +1935,14 @@ static void jedec_reset(u32 base, struct map_info *map, struct cfi_private *cfi) } -static int cfi_jedec_setup(struct map_info *map, struct cfi_private *cfi, int index) +static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) { int i,num_erase_regions; uint8_t uaddr; - if (!(jedec_table[index].devtypes & cfi->device_type)) { + if (! (jedec_table[index].devtypes & p_cfi->device_type)) { DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n", - jedec_table[index].name, 4 * (1<device_type)); + jedec_table[index].name, 4 * (1<device_type)); return 0; } @@ -1950,28 +1950,27 @@ static int cfi_jedec_setup(struct map_info *map, struct cfi_private *cfi, int in num_erase_regions = jedec_table[index].nr_regions; - cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); - if (!cfi->cfiq) { + p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); + if (!p_cfi->cfiq) { //xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name); return 0; } - memset(cfi->cfiq, 0, sizeof(struct cfi_ident)); + memset(p_cfi->cfiq,0,sizeof(struct cfi_ident)); - cfi->cfiq->P_ID = jedec_table[index].cmd_set; - cfi->cfiq->NumEraseRegions = jedec_table[index].nr_regions; - cfi->cfiq->DevSize = jedec_table[index].dev_size; - cfi->cfi_mode = CFI_MODE_JEDEC; - cfi->sector_erase_cmd = CMD(0x30); + p_cfi->cfiq->P_ID = jedec_table[index].cmd_set; + p_cfi->cfiq->NumEraseRegions = jedec_table[index].nr_regions; + p_cfi->cfiq->DevSize = jedec_table[index].dev_size; + p_cfi->cfi_mode = CFI_MODE_JEDEC; for (i=0; icfiq->EraseRegionInfo[i] = jedec_table[index].regions[i]; + p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i]; } - cfi->cmdset_priv = NULL; + p_cfi->cmdset_priv = NULL; /* This may be redundant for some cases, but it doesn't hurt */ - cfi->mfr = jedec_table[index].mfr_id; - cfi->id = jedec_table[index].dev_id; + p_cfi->mfr = jedec_table[index].mfr_id; + p_cfi->id = jedec_table[index].dev_id; uaddr = jedec_table[index].uaddr; @@ -1979,8 +1978,8 @@ static int cfi_jedec_setup(struct map_info *map, struct cfi_private *cfi, int in our brains explode when we see the datasheets talking about address lines numbered from A-1 to A18. The CFI table has unlock addresses in device-words according to the mode the device is connected in */ - cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 / cfi->device_type; - cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 / cfi->device_type; + p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 / p_cfi->device_type; + p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 / p_cfi->device_type; return 1; /* ok */ } @@ -2176,7 +2175,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", __func__, cfi->mfr, cfi->id, cfi->addr_unlock1, cfi->addr_unlock2 ); - if (!cfi_jedec_setup(map, cfi, i)) + if (!cfi_jedec_setup(cfi, i)) return 0; goto ok_out; } diff --git a/trunk/drivers/mtd/maps/amd76xrom.c b/trunk/drivers/mtd/maps/amd76xrom.c index 92de7e3a49a5..77d64ce19e9f 100644 --- a/trunk/drivers/mtd/maps/amd76xrom.c +++ b/trunk/drivers/mtd/maps/amd76xrom.c @@ -151,7 +151,6 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev, printk(KERN_ERR MOD_NAME " %s(): Unable to register resource %pR - kernel bug?\n", __func__, &window->rsrc); - return -EBUSY; } diff --git a/trunk/drivers/mtd/mtd_blkdevs.c b/trunk/drivers/mtd/mtd_blkdevs.c index e0a2373bf0e2..cb20c67995d8 100644 --- a/trunk/drivers/mtd/mtd_blkdevs.c +++ b/trunk/drivers/mtd/mtd_blkdevs.c @@ -413,6 +413,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) error2: list_del(&new->list); error1: + kfree(new); return ret; } diff --git a/trunk/drivers/mtd/nand/omap2.c b/trunk/drivers/mtd/nand/omap2.c index 28af71c61834..15682ec8530e 100644 --- a/trunk/drivers/mtd/nand/omap2.c +++ b/trunk/drivers/mtd/nand/omap2.c @@ -968,6 +968,6 @@ static void __exit omap_nand_exit(void) module_init(omap_nand_init); module_exit(omap_nand_exit); -MODULE_ALIAS("platform:" DRIVER_NAME); +MODULE_ALIAS(DRIVER_NAME); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards"); diff --git a/trunk/drivers/mtd/onenand/generic.c b/trunk/drivers/mtd/onenand/generic.c index ac08750748a3..e78914938c5c 100644 --- a/trunk/drivers/mtd/onenand/generic.c +++ b/trunk/drivers/mtd/onenand/generic.c @@ -131,7 +131,7 @@ static struct platform_driver generic_onenand_driver = { .remove = __devexit_p(generic_onenand_remove), }; -MODULE_ALIAS("platform:" DRIVER_NAME); +MODULE_ALIAS(DRIVER_NAME); static int __init generic_onenand_init(void) { diff --git a/trunk/drivers/mtd/onenand/omap2.c b/trunk/drivers/mtd/onenand/omap2.c index c849cacf4b2f..ac31f461cc1c 100644 --- a/trunk/drivers/mtd/onenand/omap2.c +++ b/trunk/drivers/mtd/onenand/omap2.c @@ -860,7 +860,7 @@ static void __exit omap2_onenand_exit(void) module_init(omap2_onenand_init); module_exit(omap2_onenand_exit); -MODULE_ALIAS("platform:" DRIVER_NAME); +MODULE_ALIAS(DRIVER_NAME); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jarkko Lavinen "); MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3"); diff --git a/trunk/drivers/net/ariadne.c b/trunk/drivers/net/ariadne.c index 7ca0eded2561..39214e512452 100644 --- a/trunk/drivers/net/ariadne.c +++ b/trunk/drivers/net/ariadne.c @@ -425,6 +425,11 @@ static irqreturn_t ariadne_interrupt(int irq, void *data) int csr0, boguscnt; int handled = 0; + if (dev == NULL) { + printk(KERN_WARNING "ariadne_interrupt(): irq for unknown device.\n"); + return IRQ_NONE; + } + lance->RAP = CSR0; /* PCnet-ISA Controller Status */ if (!(lance->RDP & INTR)) /* Check if any interrupt has been */ diff --git a/trunk/drivers/net/bnx2x/bnx2x.h b/trunk/drivers/net/bnx2x/bnx2x.h index 8849699c66c4..7897d114b290 100644 --- a/trunk/drivers/net/bnx2x/bnx2x.h +++ b/trunk/drivers/net/bnx2x/bnx2x.h @@ -1211,7 +1211,6 @@ struct bnx2x { /* DCBX Negotation results */ struct dcbx_features dcbx_local_feat; u32 dcbx_error; - u32 pending_max; }; /** @@ -1617,8 +1616,8 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, /* CMNG constants, as derived from system spec calculations */ /* default MIN rate in case VNIC min rate is configured to zero - 100Mbps */ #define DEF_MIN_RATE 100 -/* resolution of the rate shaping timer - 400 usec */ -#define RS_PERIODIC_TIMEOUT_USEC 400 +/* resolution of the rate shaping timer - 100 usec */ +#define RS_PERIODIC_TIMEOUT_USEC 100 /* number of bytes in single QM arbitration cycle - * coefficient for calculating the fairness timer */ #define QM_ARB_BYTES 160000 diff --git a/trunk/drivers/net/bnx2x/bnx2x_cmn.c b/trunk/drivers/net/bnx2x/bnx2x_cmn.c index a71b32940533..93798129061b 100644 --- a/trunk/drivers/net/bnx2x/bnx2x_cmn.c +++ b/trunk/drivers/net/bnx2x/bnx2x_cmn.c @@ -996,23 +996,6 @@ void bnx2x_free_skbs(struct bnx2x *bp) bnx2x_free_rx_skbs(bp); } -void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value) -{ - /* load old values */ - u32 mf_cfg = bp->mf_config[BP_VN(bp)]; - - if (value != bnx2x_extract_max_cfg(bp, mf_cfg)) { - /* leave all but MAX value */ - mf_cfg &= ~FUNC_MF_CFG_MAX_BW_MASK; - - /* set new MAX value */ - mf_cfg |= (value << FUNC_MF_CFG_MAX_BW_SHIFT) - & FUNC_MF_CFG_MAX_BW_MASK; - - bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW, mf_cfg); - } -} - static void bnx2x_free_msix_irqs(struct bnx2x *bp) { int i, offset = 1; @@ -1481,11 +1464,6 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bnx2x_set_eth_mac(bp, 1); - if (bp->pending_max) { - bnx2x_update_max_mf_config(bp, bp->pending_max); - bp->pending_max = 0; - } - if (bp->port.pmf) bnx2x_initial_phy_init(bp, load_mode); diff --git a/trunk/drivers/net/bnx2x/bnx2x_cmn.h b/trunk/drivers/net/bnx2x/bnx2x_cmn.h index 85ea7f26b51f..326ba44b3ded 100644 --- a/trunk/drivers/net/bnx2x/bnx2x_cmn.h +++ b/trunk/drivers/net/bnx2x/bnx2x_cmn.h @@ -341,15 +341,6 @@ void bnx2x_dcbx_init(struct bnx2x *bp); */ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state); -/** - * Updates MAX part of MF configuration in HW - * (if required) - * - * @param bp - * @param value - */ -void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value); - /* dev_close main block */ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode); diff --git a/trunk/drivers/net/bnx2x/bnx2x_ethtool.c b/trunk/drivers/net/bnx2x/bnx2x_ethtool.c index 7e92f9d0dcfd..ef2919987a10 100644 --- a/trunk/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/trunk/drivers/net/bnx2x/bnx2x_ethtool.c @@ -238,7 +238,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) speed |= (cmd->speed_hi << 16); if (IS_MF_SI(bp)) { - u32 part; + u32 param = 0, part; u32 line_speed = bp->link_vars.line_speed; /* use 10G if no link detected */ @@ -251,22 +251,24 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) REQ_BC_VER_4_SET_MF_BW); return -EINVAL; } - part = (speed * 100) / line_speed; - if (line_speed < speed || !part) { BNX2X_DEV_INFO("Speed setting should be in a range " "from 1%% to 100%% " "of actual line speed\n"); return -EINVAL; } + /* load old values */ + param = bp->mf_config[BP_VN(bp)]; - if (bp->state != BNX2X_STATE_OPEN) - /* store value for following "load" */ - bp->pending_max = part; - else - bnx2x_update_max_mf_config(bp, part); + /* leave only MIN value */ + param &= FUNC_MF_CFG_MIN_BW_MASK; + + /* set new MAX value */ + param |= (part << FUNC_MF_CFG_MAX_BW_SHIFT) + & FUNC_MF_CFG_MAX_BW_MASK; + bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW, param); return 0; } diff --git a/trunk/drivers/net/bnx2x/bnx2x_main.c b/trunk/drivers/net/bnx2x/bnx2x_main.c index aa032339e321..032ae184b605 100644 --- a/trunk/drivers/net/bnx2x/bnx2x_main.c +++ b/trunk/drivers/net/bnx2x/bnx2x_main.c @@ -2092,9 +2092,8 @@ static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type) bnx2x_calc_vn_weight_sum(bp); /* calculate and set min-max rate for each vn */ - if (bp->port.pmf) - for (vn = VN_0; vn < E1HVN_MAX; vn++) - bnx2x_init_vn_minmax(bp, vn); + for (vn = VN_0; vn < E1HVN_MAX; vn++) + bnx2x_init_vn_minmax(bp, vn); /* always enable rate shaping and fairness */ bp->cmng.flags.cmng_enables |= @@ -2163,6 +2162,13 @@ static void bnx2x_link_attn(struct bnx2x *bp) bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); } + /* indicate link status only if link status actually changed */ + if (prev_link_status != bp->link_vars.link_status) + bnx2x_link_report(bp); + + if (IS_MF(bp)) + bnx2x_link_sync_notify(bp); + if (bp->link_vars.link_up && bp->link_vars.line_speed) { int cmng_fns = bnx2x_get_cmng_fns_mode(bp); @@ -2174,13 +2180,6 @@ static void bnx2x_link_attn(struct bnx2x *bp) DP(NETIF_MSG_IFUP, "single function mode without fairness\n"); } - - if (IS_MF(bp)) - bnx2x_link_sync_notify(bp); - - /* indicate link status only if link status actually changed */ - if (prev_link_status != bp->link_vars.link_status) - bnx2x_link_report(bp); } void bnx2x__link_status_update(struct bnx2x *bp) diff --git a/trunk/drivers/net/bonding/bond_3ad.c b/trunk/drivers/net/bonding/bond_3ad.c index a5d5d0b5b155..1024ae158227 100644 --- a/trunk/drivers/net/bonding/bond_3ad.c +++ b/trunk/drivers/net/bonding/bond_3ad.c @@ -281,23 +281,23 @@ static inline int __check_agg_selection_timer(struct port *port) } /** - * __get_state_machine_lock - lock the port's state machines + * __get_rx_machine_lock - lock the port's RX machine * @port: the port we're looking at * */ -static inline void __get_state_machine_lock(struct port *port) +static inline void __get_rx_machine_lock(struct port *port) { - spin_lock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); + spin_lock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); } /** - * __release_state_machine_lock - unlock the port's state machines + * __release_rx_machine_lock - unlock the port's RX machine * @port: the port we're looking at * */ -static inline void __release_state_machine_lock(struct port *port) +static inline void __release_rx_machine_lock(struct port *port) { - spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); + spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); } /** @@ -388,14 +388,14 @@ static u8 __get_duplex(struct port *port) } /** - * __initialize_port_locks - initialize a port's STATE machine spinlock + * __initialize_port_locks - initialize a port's RX machine spinlock * @port: the port we're looking at * */ static inline void __initialize_port_locks(struct port *port) { // make sure it isn't called twice - spin_lock_init(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); + spin_lock_init(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); } //conversions @@ -1025,6 +1025,9 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) { rx_states_t last_state; + // Lock to prevent 2 instances of this function to run simultaneously(rx interrupt and periodic machine callback) + __get_rx_machine_lock(port); + // keep current State Machine state to compare later if it was changed last_state = port->sm_rx_state; @@ -1130,6 +1133,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) pr_err("%s: An illegal loopback occurred on adapter (%s).\n" "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", port->slave->dev->master->name, port->slave->dev->name); + __release_rx_machine_lock(port); return; } __update_selected(lacpdu, port); @@ -1149,6 +1153,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) break; } } + __release_rx_machine_lock(port); } /** @@ -2150,12 +2155,6 @@ void bond_3ad_state_machine_handler(struct work_struct *work) goto re_arm; } - /* Lock around state machines to protect data accessed - * by all (e.g., port->sm_vars). ad_rx_machine may run - * concurrently due to incoming LACPDU. - */ - __get_state_machine_lock(port); - ad_rx_machine(NULL, port); ad_periodic_machine(port); ad_port_selection_logic(port); @@ -2165,8 +2164,6 @@ void bond_3ad_state_machine_handler(struct work_struct *work) // turn off the BEGIN bit, since we already handled it if (port->sm_vars & AD_PORT_BEGIN) port->sm_vars &= ~AD_PORT_BEGIN; - - __release_state_machine_lock(port); } re_arm: @@ -2203,10 +2200,7 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u case AD_TYPE_LACPDU: pr_debug("Received LACPDU on port %d\n", port->actor_port_number); - /* Protect against concurrent state machines */ - __get_state_machine_lock(port); ad_rx_machine(lacpdu, port); - __release_state_machine_lock(port); break; case AD_TYPE_MARKER: diff --git a/trunk/drivers/net/bonding/bond_3ad.h b/trunk/drivers/net/bonding/bond_3ad.h index b28baff70864..2c46a154f2c6 100644 --- a/trunk/drivers/net/bonding/bond_3ad.h +++ b/trunk/drivers/net/bonding/bond_3ad.h @@ -264,8 +264,7 @@ struct ad_bond_info { struct ad_slave_info { struct aggregator aggregator; // 802.3ad aggregator structure struct port port; // 802.3ad port structure - spinlock_t state_machine_lock; /* mutex state machines vs. - incoming LACPDU */ + spinlock_t rx_machine_lock; // To avoid race condition between callback and receive interrupt u16 id; }; diff --git a/trunk/drivers/net/macvtap.c b/trunk/drivers/net/macvtap.c index fc27a9926d9e..5933621ac3ff 100644 --- a/trunk/drivers/net/macvtap.c +++ b/trunk/drivers/net/macvtap.c @@ -528,9 +528,8 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, vnet_hdr_len = q->vnet_hdr_sz; err = -EINVAL; - if (len < vnet_hdr_len) + if ((len -= vnet_hdr_len) < 0) goto err; - len -= vnet_hdr_len; err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, sizeof(vnet_hdr)); diff --git a/trunk/drivers/net/r6040.c b/trunk/drivers/net/r6040.c index e3ebd90ae651..27e6f6d43cac 100644 --- a/trunk/drivers/net/r6040.c +++ b/trunk/drivers/net/r6040.c @@ -49,8 +49,8 @@ #include #define DRV_NAME "r6040" -#define DRV_VERSION "0.27" -#define DRV_RELDATE "23Feb2011" +#define DRV_VERSION "0.26" +#define DRV_RELDATE "30May2010" /* PHY CHIP Address */ #define PHY1_ADDR 1 /* For MAC1 */ @@ -69,8 +69,6 @@ /* MAC registers */ #define MCR0 0x00 /* Control register 0 */ -#define MCR0_PROMISC 0x0020 /* Promiscuous mode */ -#define MCR0_HASH_EN 0x0100 /* Enable multicast hash table function */ #define MCR1 0x04 /* Control register 1 */ #define MAC_RST 0x0001 /* Reset the MAC */ #define MBCR 0x08 /* Bus control */ @@ -853,92 +851,77 @@ static void r6040_multicast_list(struct net_device *dev) { struct r6040_private *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; + u16 *adrp; + u16 reg; unsigned long flags; struct netdev_hw_addr *ha; int i; - u16 *adrp; - u16 hash_table[4] = { 0 }; - - spin_lock_irqsave(&lp->lock, flags); - /* Keep our MAC Address */ + /* MAC Address */ adrp = (u16 *)dev->dev_addr; iowrite16(adrp[0], ioaddr + MID_0L); iowrite16(adrp[1], ioaddr + MID_0M); iowrite16(adrp[2], ioaddr + MID_0H); - /* Clear AMCP & PROM bits */ - lp->mcr0 = ioread16(ioaddr + MCR0) & ~(MCR0_PROMISC | MCR0_HASH_EN); - - /* Promiscuous mode */ - if (dev->flags & IFF_PROMISC) - lp->mcr0 |= MCR0_PROMISC; + /* Promiscous Mode */ + spin_lock_irqsave(&lp->lock, flags); - /* Enable multicast hash table function to - * receive all multicast packets. */ - else if (dev->flags & IFF_ALLMULTI) { - lp->mcr0 |= MCR0_HASH_EN; + /* Clear AMCP & PROM bits */ + reg = ioread16(ioaddr) & ~0x0120; + if (dev->flags & IFF_PROMISC) { + reg |= 0x0020; + lp->mcr0 |= 0x0020; + } + /* Too many multicast addresses + * accept all traffic */ + else if ((netdev_mc_count(dev) > MCAST_MAX) || + (dev->flags & IFF_ALLMULTI)) + reg |= 0x0020; - for (i = 0; i < MCAST_MAX ; i++) { - iowrite16(0, ioaddr + MID_1L + 8 * i); - iowrite16(0, ioaddr + MID_1M + 8 * i); - iowrite16(0, ioaddr + MID_1H + 8 * i); - } + iowrite16(reg, ioaddr); + spin_unlock_irqrestore(&lp->lock, flags); - for (i = 0; i < 4; i++) - hash_table[i] = 0xffff; - } - /* Use internal multicast address registers if the number of - * multicast addresses is not greater than MCAST_MAX. */ - else if (netdev_mc_count(dev) <= MCAST_MAX) { - i = 0; - netdev_for_each_mc_addr(ha, dev) { - u16 *adrp = (u16 *) ha->addr; - iowrite16(adrp[0], ioaddr + MID_1L + 8 * i); - iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); - iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); - i++; - } - while (i < MCAST_MAX) { - iowrite16(0, ioaddr + MID_1L + 8 * i); - iowrite16(0, ioaddr + MID_1M + 8 * i); - iowrite16(0, ioaddr + MID_1H + 8 * i); - i++; - } - } - /* Otherwise, Enable multicast hash table function. */ - else { + /* Build the hash table */ + if (netdev_mc_count(dev) > MCAST_MAX) { + u16 hash_table[4]; u32 crc; - lp->mcr0 |= MCR0_HASH_EN; - - for (i = 0; i < MCAST_MAX ; i++) { - iowrite16(0, ioaddr + MID_1L + 8 * i); - iowrite16(0, ioaddr + MID_1M + 8 * i); - iowrite16(0, ioaddr + MID_1H + 8 * i); - } + for (i = 0; i < 4; i++) + hash_table[i] = 0; - /* Build multicast hash table */ netdev_for_each_mc_addr(ha, dev) { - u8 *addrs = ha->addr; + char *addrs = ha->addr; + + if (!(*addrs & 1)) + continue; - crc = ether_crc(ETH_ALEN, addrs); + crc = ether_crc_le(6, addrs); crc >>= 26; - hash_table[crc >> 4] |= 1 << (crc & 0xf); + hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); } - } - - iowrite16(lp->mcr0, ioaddr + MCR0); - - /* Fill the MAC hash tables with their values */ - if (lp->mcr0 && MCR0_HASH_EN) { + /* Fill the MAC hash tables with their values */ iowrite16(hash_table[0], ioaddr + MAR0); iowrite16(hash_table[1], ioaddr + MAR1); iowrite16(hash_table[2], ioaddr + MAR2); iowrite16(hash_table[3], ioaddr + MAR3); } - - spin_unlock_irqrestore(&lp->lock, flags); + /* Multicast Address 1~4 case */ + i = 0; + netdev_for_each_mc_addr(ha, dev) { + if (i >= MCAST_MAX) + break; + adrp = (u16 *) ha->addr; + iowrite16(adrp[0], ioaddr + MID_1L + 8 * i); + iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); + iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); + i++; + } + while (i < MCAST_MAX) { + iowrite16(0xffff, ioaddr + MID_1L + 8 * i); + iowrite16(0xffff, ioaddr + MID_1M + 8 * i); + iowrite16(0xffff, ioaddr + MID_1H + 8 * i); + i++; + } } static void netdev_get_drvinfo(struct net_device *dev, diff --git a/trunk/drivers/net/smsc911x.c b/trunk/drivers/net/smsc911x.c index d70bde95460b..64bfdae5956f 100644 --- a/trunk/drivers/net/smsc911x.c +++ b/trunk/drivers/net/smsc911x.c @@ -1178,11 +1178,6 @@ static int smsc911x_open(struct net_device *dev) smsc911x_reg_write(pdata, HW_CFG, 0x00050000); smsc911x_reg_write(pdata, AFC_CFG, 0x006E3740); - /* Increase the legal frame size of VLAN tagged frames to 1522 bytes */ - spin_lock_irq(&pdata->mac_lock); - smsc911x_mac_write(pdata, VLAN1, ETH_P_8021Q); - spin_unlock_irq(&pdata->mac_lock); - /* Make sure EEPROM has finished loading before setting GPIO_CFG */ timeout = 50; while ((smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_) && diff --git a/trunk/drivers/pci/xen-pcifront.c b/trunk/drivers/pci/xen-pcifront.c index 492b7d807fe8..3a5a6fcc0ead 100644 --- a/trunk/drivers/pci/xen-pcifront.c +++ b/trunk/drivers/pci/xen-pcifront.c @@ -243,7 +243,7 @@ struct pci_ops pcifront_bus_ops = { #ifdef CONFIG_PCI_MSI static int pci_frontend_enable_msix(struct pci_dev *dev, - int vector[], int nvec) + int **vector, int nvec) { int err; int i; @@ -277,24 +277,18 @@ static int pci_frontend_enable_msix(struct pci_dev *dev, if (likely(!err)) { if (likely(!op.value)) { /* we get the result */ - for (i = 0; i < nvec; i++) { - if (op.msix_entries[i].vector <= 0) { - dev_warn(&dev->dev, "MSI-X entry %d is invalid: %d!\n", - i, op.msix_entries[i].vector); - err = -EINVAL; - vector[i] = -1; - continue; - } - vector[i] = op.msix_entries[i].vector; - } + for (i = 0; i < nvec; i++) + *(*vector+i) = op.msix_entries[i].vector; + return 0; } else { printk(KERN_DEBUG "enable msix get value %x\n", op.value); + return op.value; } } else { dev_err(&dev->dev, "enable msix get err %x\n", err); + return err; } - return err; } static void pci_frontend_disable_msix(struct pci_dev *dev) @@ -316,7 +310,7 @@ static void pci_frontend_disable_msix(struct pci_dev *dev) dev_err(&dev->dev, "pci_disable_msix get err %x\n", err); } -static int pci_frontend_enable_msi(struct pci_dev *dev, int vector[]) +static int pci_frontend_enable_msi(struct pci_dev *dev, int **vector) { int err; struct xen_pci_op op = { @@ -330,13 +324,7 @@ static int pci_frontend_enable_msi(struct pci_dev *dev, int vector[]) err = do_pci_op(pdev, &op); if (likely(!err)) { - vector[0] = op.value; - if (op.value <= 0) { - dev_warn(&dev->dev, "MSI entry is invalid: %d!\n", - op.value); - err = -EINVAL; - vector[0] = -1; - } + *(*vector) = op.value; } else { dev_err(&dev->dev, "pci frontend enable msi failed for dev " "%x:%x\n", op.bus, op.devfn); @@ -745,7 +733,8 @@ static void free_pdev(struct pcifront_device *pdev) pcifront_free_roots(pdev); - cancel_work_sync(&pdev->op_work); + /*For PCIE_AER error handling job*/ + flush_scheduled_work(); if (pdev->irq >= 0) unbind_from_irqhandler(pdev->irq, pdev); diff --git a/trunk/drivers/target/target_core_tmr.c b/trunk/drivers/target/target_core_tmr.c index 4a109835e420..158cecbec718 100644 --- a/trunk/drivers/target/target_core_tmr.c +++ b/trunk/drivers/target/target_core_tmr.c @@ -282,9 +282,6 @@ int core_tmr_lun_reset( atomic_set(&task->task_active, 0); atomic_set(&task->task_stop, 0); - } else { - if (atomic_read(&task->task_execute_queue) != 0) - transport_remove_task_from_execute_queue(task, dev); } __transport_stop_task_timer(task, &flags); @@ -304,7 +301,6 @@ int core_tmr_lun_reset( DEBUG_LR("LUN_RESET: got t_transport_active = 1 for" " task: %p, t_fe_count: %d dev: %p\n", task, fe_count, dev); - atomic_set(&T_TASK(cmd)->t_transport_aborted, 1); spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags); core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count); @@ -314,7 +310,6 @@ int core_tmr_lun_reset( } DEBUG_LR("LUN_RESET: Got t_transport_active = 0 for task: %p," " t_fe_count: %d dev: %p\n", task, fe_count, dev); - atomic_set(&T_TASK(cmd)->t_transport_aborted, 1); spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags); core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count); diff --git a/trunk/drivers/target/target_core_transport.c b/trunk/drivers/target/target_core_transport.c index 4bbf6c147f89..236e22d8cfae 100644 --- a/trunk/drivers/target/target_core_transport.c +++ b/trunk/drivers/target/target_core_transport.c @@ -1207,7 +1207,7 @@ transport_get_task_from_execute_queue(struct se_device *dev) * * */ -void transport_remove_task_from_execute_queue( +static void transport_remove_task_from_execute_queue( struct se_task *task, struct se_device *dev) { @@ -5549,8 +5549,7 @@ static void transport_generic_wait_for_tasks( atomic_set(&T_TASK(cmd)->transport_lun_stop, 0); } - if (!atomic_read(&T_TASK(cmd)->t_transport_active) || - atomic_read(&T_TASK(cmd)->t_transport_aborted)) + if (!atomic_read(&T_TASK(cmd)->t_transport_active)) goto remove; atomic_set(&T_TASK(cmd)->t_transport_stop, 1); @@ -5957,9 +5956,6 @@ static void transport_processing_shutdown(struct se_device *dev) atomic_set(&task->task_active, 0); atomic_set(&task->task_stop, 0); - } else { - if (atomic_read(&task->task_execute_queue) != 0) - transport_remove_task_from_execute_queue(task, dev); } __transport_stop_task_timer(task, &flags); diff --git a/trunk/drivers/watchdog/cpwd.c b/trunk/drivers/watchdog/cpwd.c index 3de4ba0260a5..eca855a55c0d 100644 --- a/trunk/drivers/watchdog/cpwd.c +++ b/trunk/drivers/watchdog/cpwd.c @@ -646,7 +646,7 @@ static int __devexit cpwd_remove(struct platform_device *op) struct cpwd *p = dev_get_drvdata(&op->dev); int i; - for (i = 0; i < WD_NUMDEVS; i++) { + for (i = 0; i < 4; i++) { misc_deregister(&p->devs[i].misc); if (!p->enabled) { diff --git a/trunk/drivers/watchdog/hpwdt.c b/trunk/drivers/watchdog/hpwdt.c index 204a5603c4ae..24b966d5061a 100644 --- a/trunk/drivers/watchdog/hpwdt.c +++ b/trunk/drivers/watchdog/hpwdt.c @@ -710,7 +710,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) return 0; } -static void hpwdt_exit_nmi_decoding(void) +static void __devexit hpwdt_exit_nmi_decoding(void) { unregister_die_notifier(&die_notifier); if (cru_rom_addr) @@ -726,7 +726,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) return 0; } -static void hpwdt_exit_nmi_decoding(void) +static void __devexit hpwdt_exit_nmi_decoding(void) { } #endif /* CONFIG_HPWDT_NMI_DECODING */ diff --git a/trunk/drivers/watchdog/sbc_fitpc2_wdt.c b/trunk/drivers/watchdog/sbc_fitpc2_wdt.c index 79906255eeb6..c7d67e9a7465 100644 --- a/trunk/drivers/watchdog/sbc_fitpc2_wdt.c +++ b/trunk/drivers/watchdog/sbc_fitpc2_wdt.c @@ -201,14 +201,11 @@ static struct miscdevice fitpc2_wdt_miscdev = { static int __init fitpc2_wdt_init(void) { int err; - const char *brd_name; - brd_name = dmi_get_system_info(DMI_BOARD_NAME); - - if (!brd_name || !strstr(brd_name, "SBC-FITPC2")) + if (!strstr(dmi_get_system_info(DMI_BOARD_NAME), "SBC-FITPC2")) return -ENODEV; - pr_info("%s found\n", brd_name); + pr_info("%s found\n", dmi_get_system_info(DMI_BOARD_NAME)); if (!request_region(COMMAND_PORT, 1, WATCHDOG_NAME)) { pr_err("I/O address 0x%04x already in use\n", COMMAND_PORT); diff --git a/trunk/drivers/watchdog/sch311x_wdt.c b/trunk/drivers/watchdog/sch311x_wdt.c index b61ab1c54293..0461858e07d0 100644 --- a/trunk/drivers/watchdog/sch311x_wdt.c +++ b/trunk/drivers/watchdog/sch311x_wdt.c @@ -508,7 +508,7 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr) sch311x_sio_outb(sio_config_port, 0x07, 0x0a); /* Check if Logical Device Register is currently active */ - if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0) + if (sch311x_sio_inb(sio_config_port, 0x30) && 0x01 == 0) printk(KERN_INFO PFX "Seems that LDN 0x0a is not active...\n"); /* Get the base address of the runtime registers */ diff --git a/trunk/drivers/watchdog/w83697ug_wdt.c b/trunk/drivers/watchdog/w83697ug_wdt.c index df2a64dc9672..a6c12dec91a1 100644 --- a/trunk/drivers/watchdog/w83697ug_wdt.c +++ b/trunk/drivers/watchdog/w83697ug_wdt.c @@ -109,7 +109,7 @@ static int w83697ug_select_wd_register(void) outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ outb_p(0x30, WDT_EFER); /* select CR30 */ c = inb_p(WDT_EFDR); - outb_p(c | 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ + outb_p(c || 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ return 0; } diff --git a/trunk/drivers/xen/balloon.c b/trunk/drivers/xen/balloon.c index 718050ace08f..43f9f02c7db0 100644 --- a/trunk/drivers/xen/balloon.c +++ b/trunk/drivers/xen/balloon.c @@ -232,7 +232,7 @@ static int increase_reservation(unsigned long nr_pages) set_phys_to_machine(pfn, frame_list[i]); /* Link back into the page tables if not highmem. */ - if (!xen_hvm_domain() && pfn < max_low_pfn) { + if (pfn < max_low_pfn) { int ret; ret = HYPERVISOR_update_va_mapping( (unsigned long)__va(pfn << PAGE_SHIFT), @@ -280,7 +280,7 @@ static int decrease_reservation(unsigned long nr_pages) scrub_page(page); - if (!xen_hvm_domain() && !PageHighMem(page)) { + if (!PageHighMem(page)) { ret = HYPERVISOR_update_va_mapping( (unsigned long)__va(pfn << PAGE_SHIFT), __pte_ma(0), 0); @@ -296,7 +296,7 @@ static int decrease_reservation(unsigned long nr_pages) /* No more mappings: invalidate P2M and add to balloon. */ for (i = 0; i < nr_pages; i++) { pfn = mfn_to_pfn(frame_list[i]); - __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); + set_phys_to_machine(pfn, INVALID_P2M_ENTRY); balloon_append(pfn_to_page(pfn)); } @@ -392,19 +392,15 @@ static struct notifier_block xenstore_notifier; static int __init balloon_init(void) { - unsigned long pfn, nr_pages, extra_pfn_end; + unsigned long pfn, extra_pfn_end; struct page *page; - if (!xen_domain()) + if (!xen_pv_domain()) return -ENODEV; pr_info("xen_balloon: Initialising balloon driver.\n"); - if (xen_pv_domain()) - nr_pages = xen_start_info->nr_pages; - else - nr_pages = max_pfn; - balloon_stats.current_pages = min(nr_pages, max_pfn); + balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn); balloon_stats.target_pages = balloon_stats.current_pages; balloon_stats.balloon_low = 0; balloon_stats.balloon_high = 0; diff --git a/trunk/drivers/xen/events.c b/trunk/drivers/xen/events.c index 149fa875e396..74681478100a 100644 --- a/trunk/drivers/xen/events.c +++ b/trunk/drivers/xen/events.c @@ -114,7 +114,7 @@ struct cpu_evtchn_s { static __initdata struct cpu_evtchn_s init_evtchn_mask = { .bits[0 ... (NR_EVENT_CHANNELS/BITS_PER_LONG)-1] = ~0ul, }; -static struct cpu_evtchn_s __refdata *cpu_evtchn_mask_p = &init_evtchn_mask; +static struct cpu_evtchn_s *cpu_evtchn_mask_p = &init_evtchn_mask; static inline unsigned long *cpu_evtchn_mask(int cpu) { @@ -277,7 +277,7 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) BUG_ON(irq == -1); #ifdef CONFIG_SMP - cpumask_copy(irq_to_desc(irq)->irq_data.affinity, cpumask_of(cpu)); + cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu)); #endif clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq))); @@ -294,7 +294,7 @@ static void init_evtchn_cpu_bindings(void) /* By default all event channels notify CPU#0. */ for_each_irq_desc(i, desc) { - cpumask_copy(desc->irq_data.affinity, cpumask_of(0)); + cpumask_copy(desc->affinity, cpumask_of(0)); } #endif @@ -376,69 +376,81 @@ static void unmask_evtchn(int port) put_cpu(); } -static int xen_allocate_irq_dynamic(void) +static int get_nr_hw_irqs(void) { - int first = 0; - int irq; + int ret = 1; #ifdef CONFIG_X86_IO_APIC - /* - * For an HVM guest or domain 0 which see "real" (emulated or - * actual repectively) GSIs we allocate dynamic IRQs - * e.g. those corresponding to event channels or MSIs - * etc. from the range above those "real" GSIs to avoid - * collisions. - */ - if (xen_initial_domain() || xen_hvm_domain()) - first = get_nr_irqs_gsi(); + ret = get_nr_irqs_gsi(); #endif -retry: - irq = irq_alloc_desc_from(first, -1); + return ret; +} - if (irq == -ENOMEM && first > NR_IRQS_LEGACY) { - printk(KERN_ERR "Out of dynamic IRQ space and eating into GSI space. You should increase nr_irqs\n"); - first = max(NR_IRQS_LEGACY, first - NR_IRQS_LEGACY); - goto retry; - } +static int find_unbound_pirq(int type) +{ + int rc, i; + struct physdev_get_free_pirq op_get_free_pirq; + op_get_free_pirq.type = type; - if (irq < 0) - panic("No available IRQ to bind to: increase nr_irqs!\n"); + rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); + if (!rc) + return op_get_free_pirq.pirq; - return irq; + for (i = 0; i < nr_irqs; i++) { + if (pirq_to_irq[i] < 0) + return i; + } + return -1; } -static int xen_allocate_irq_gsi(unsigned gsi) +static int find_unbound_irq(void) { - int irq; + struct irq_data *data; + int irq, res; + int bottom = get_nr_hw_irqs(); + int top = nr_irqs-1; - /* - * A PV guest has no concept of a GSI (since it has no ACPI - * nor access to/knowledge of the physical APICs). Therefore - * all IRQs are dynamically allocated from the entire IRQ - * space. + if (bottom == nr_irqs) + goto no_irqs; + + /* This loop starts from the top of IRQ space and goes down. + * We need this b/c if we have a PCI device in a Xen PV guest + * we do not have an IO-APIC (though the backend might have them) + * mapped in. To not have a collision of physical IRQs with the Xen + * event channels start at the top of the IRQ space for virtual IRQs. */ - if (xen_pv_domain() && !xen_initial_domain()) - return xen_allocate_irq_dynamic(); + for (irq = top; irq > bottom; irq--) { + data = irq_get_irq_data(irq); + /* only 15->0 have init'd desc; handle irq > 16 */ + if (!data) + break; + if (data->chip == &no_irq_chip) + break; + if (data->chip != &xen_dynamic_chip) + continue; + if (irq_info[irq].type == IRQT_UNBOUND) + return irq; + } - /* Legacy IRQ descriptors are already allocated by the arch. */ - if (gsi < NR_IRQS_LEGACY) - return gsi; + if (irq == bottom) + goto no_irqs; - irq = irq_alloc_desc_at(gsi, -1); - if (irq < 0) - panic("Unable to allocate to IRQ%d (%d)\n", gsi, irq); + res = irq_alloc_desc_at(irq, -1); + + if (WARN_ON(res != irq)) + return -1; return irq; + +no_irqs: + panic("No available IRQ to bind to: increase nr_irqs!\n"); } -static void xen_free_irq(unsigned irq) +static bool identity_mapped_irq(unsigned irq) { - /* Legacy IRQ descriptors are managed by the arch. */ - if (irq < NR_IRQS_LEGACY) - return; - - irq_free_desc(irq); + /* identity map all the hardware irqs */ + return irq < get_nr_hw_irqs(); } static void pirq_unmask_notify(int irq) @@ -474,7 +486,7 @@ static bool probing_irq(int irq) return desc && desc->action == NULL; } -static unsigned int __startup_pirq(unsigned int irq) +static unsigned int startup_pirq(unsigned int irq) { struct evtchn_bind_pirq bind_pirq; struct irq_info *info = info_for_irq(irq); @@ -512,15 +524,9 @@ static unsigned int __startup_pirq(unsigned int irq) return 0; } -static unsigned int startup_pirq(struct irq_data *data) -{ - return __startup_pirq(data->irq); -} - -static void shutdown_pirq(struct irq_data *data) +static void shutdown_pirq(unsigned int irq) { struct evtchn_close close; - unsigned int irq = data->irq; struct irq_info *info = info_for_irq(irq); int evtchn = evtchn_from_irq(irq); @@ -540,20 +546,20 @@ static void shutdown_pirq(struct irq_data *data) info->evtchn = 0; } -static void enable_pirq(struct irq_data *data) +static void enable_pirq(unsigned int irq) { - startup_pirq(data); + startup_pirq(irq); } -static void disable_pirq(struct irq_data *data) +static void disable_pirq(unsigned int irq) { } -static void ack_pirq(struct irq_data *data) +static void ack_pirq(unsigned int irq) { - int evtchn = evtchn_from_irq(data->irq); + int evtchn = evtchn_from_irq(irq); - move_native_irq(data->irq); + move_native_irq(irq); if (VALID_EVTCHN(evtchn)) { mask_evtchn(evtchn); @@ -561,6 +567,23 @@ static void ack_pirq(struct irq_data *data) } } +static void end_pirq(unsigned int irq) +{ + int evtchn = evtchn_from_irq(irq); + struct irq_desc *desc = irq_to_desc(irq); + + if (WARN_ON(!desc)) + return; + + if ((desc->status & (IRQ_DISABLED|IRQ_PENDING)) == + (IRQ_DISABLED|IRQ_PENDING)) { + shutdown_pirq(irq); + } else if (VALID_EVTCHN(evtchn)) { + unmask_evtchn(evtchn); + pirq_unmask_notify(irq); + } +} + static int find_irq_by_gsi(unsigned gsi) { int irq; @@ -615,7 +638,14 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name) goto out; /* XXX need refcount? */ } - irq = xen_allocate_irq_gsi(gsi); + /* If we are a PV guest, we don't have GSIs (no ACPI passed). Therefore + * we are using the !xen_initial_domain() to drop in the function.*/ + if (identity_mapped_irq(gsi) || (!xen_initial_domain() && + xen_pv_domain())) { + irq = gsi; + irq_alloc_desc_at(irq, -1); + } else + irq = find_unbound_irq(); set_irq_chip_and_handler_name(irq, &xen_pirq_chip, handle_level_irq, name); @@ -628,7 +658,7 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name) * this in the priv domain. */ if (xen_initial_domain() && HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) { - xen_free_irq(irq); + irq_free_desc(irq); irq = -ENOSPC; goto out; } @@ -644,46 +674,87 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name) } #ifdef CONFIG_PCI_MSI -int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) +#include +#include "../pci/msi.h" + +void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc) { - int rc; - struct physdev_get_free_pirq op_get_free_pirq; + spin_lock(&irq_mapping_update_lock); - op_get_free_pirq.type = MAP_PIRQ_TYPE_MSI; - rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); + if (alloc & XEN_ALLOC_IRQ) { + *irq = find_unbound_irq(); + if (*irq == -1) + goto out; + } + + if (alloc & XEN_ALLOC_PIRQ) { + *pirq = find_unbound_pirq(MAP_PIRQ_TYPE_MSI); + if (*pirq == -1) + goto out; + } + + set_irq_chip_and_handler_name(*irq, &xen_pirq_chip, + handle_level_irq, name); - WARN_ONCE(rc == -ENOSYS, - "hypervisor does not support the PHYSDEVOP_get_free_pirq interface\n"); + irq_info[*irq] = mk_pirq_info(0, *pirq, 0, 0); + pirq_to_irq[*pirq] = *irq; - return rc ? -1 : op_get_free_pirq.pirq; +out: + spin_unlock(&irq_mapping_update_lock); } -int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, - int pirq, int vector, const char *name) +int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type) { - int irq, ret; + int irq = -1; + struct physdev_map_pirq map_irq; + int rc; + int pos; + u32 table_offset, bir; + + memset(&map_irq, 0, sizeof(map_irq)); + map_irq.domid = DOMID_SELF; + map_irq.type = MAP_PIRQ_TYPE_MSI; + map_irq.index = -1; + map_irq.pirq = -1; + map_irq.bus = dev->bus->number; + map_irq.devfn = dev->devfn; + + if (type == PCI_CAP_ID_MSIX) { + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + + pci_read_config_dword(dev, msix_table_offset_reg(pos), + &table_offset); + bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); + + map_irq.table_base = pci_resource_start(dev, bir); + map_irq.entry_nr = msidesc->msi_attrib.entry_nr; + } spin_lock(&irq_mapping_update_lock); - irq = xen_allocate_irq_dynamic(); + irq = find_unbound_irq(); + if (irq == -1) goto out; + rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); + if (rc) { + printk(KERN_WARNING "xen map irq failed %d\n", rc); + + irq_free_desc(irq); + + irq = -1; + goto out; + } + irq_info[irq] = mk_pirq_info(0, map_irq.pirq, 0, map_irq.index); + set_irq_chip_and_handler_name(irq, &xen_pirq_chip, - handle_level_irq, name); + handle_level_irq, + (type == PCI_CAP_ID_MSIX) ? "msi-x":"msi"); - irq_info[irq] = mk_pirq_info(0, pirq, 0, vector); - pirq_to_irq[pirq] = irq; - ret = set_irq_msi(irq, msidesc); - if (ret < 0) - goto error_irq; out: spin_unlock(&irq_mapping_update_lock); return irq; -error_irq: - spin_unlock(&irq_mapping_update_lock); - xen_free_irq(irq); - return -1; } #endif @@ -708,12 +779,11 @@ int xen_destroy_irq(int irq) printk(KERN_WARNING "unmap irq failed %d\n", rc); goto out; } + pirq_to_irq[info->u.pirq.pirq] = -1; } - pirq_to_irq[info->u.pirq.pirq] = -1; - irq_info[irq] = mk_unbound_info(); - xen_free_irq(irq); + irq_free_desc(irq); out: spin_unlock(&irq_mapping_update_lock); @@ -744,7 +814,7 @@ int bind_evtchn_to_irq(unsigned int evtchn) irq = evtchn_to_irq[evtchn]; if (irq == -1) { - irq = xen_allocate_irq_dynamic(); + irq = find_unbound_irq(); set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, handle_fasteoi_irq, "event"); @@ -769,7 +839,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) irq = per_cpu(ipi_to_irq, cpu)[ipi]; if (irq == -1) { - irq = xen_allocate_irq_dynamic(); + irq = find_unbound_irq(); if (irq < 0) goto out; @@ -805,7 +875,7 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu) irq = per_cpu(virq_to_irq, cpu)[virq]; if (irq == -1) { - irq = xen_allocate_irq_dynamic(); + irq = find_unbound_irq(); set_irq_chip_and_handler_name(irq, &xen_percpu_chip, handle_percpu_irq, "virq"); @@ -864,7 +934,7 @@ static void unbind_from_irq(unsigned int irq) if (irq_info[irq].type != IRQT_UNBOUND) { irq_info[irq] = mk_unbound_info(); - xen_free_irq(irq); + irq_free_desc(irq); } spin_unlock(&irq_mapping_update_lock); @@ -920,7 +990,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi, if (irq < 0) return irq; - irqflags |= IRQF_NO_SUSPEND | IRQF_FORCE_RESUME; + irqflags |= IRQF_NO_SUSPEND; retval = request_irq(irq, handler, irqflags, devname, dev_id); if (retval != 0) { unbind_from_irq(irq); @@ -1164,12 +1234,11 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu) return 0; } -static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest, - bool force) +static int set_affinity_irq(unsigned irq, const struct cpumask *dest) { unsigned tcpu = cpumask_first(dest); - return rebind_irq_to_cpu(data->irq, tcpu); + return rebind_irq_to_cpu(irq, tcpu); } int resend_irq_on_evtchn(unsigned int irq) @@ -1188,35 +1257,35 @@ int resend_irq_on_evtchn(unsigned int irq) return 1; } -static void enable_dynirq(struct irq_data *data) +static void enable_dynirq(unsigned int irq) { - int evtchn = evtchn_from_irq(data->irq); + int evtchn = evtchn_from_irq(irq); if (VALID_EVTCHN(evtchn)) unmask_evtchn(evtchn); } -static void disable_dynirq(struct irq_data *data) +static void disable_dynirq(unsigned int irq) { - int evtchn = evtchn_from_irq(data->irq); + int evtchn = evtchn_from_irq(irq); if (VALID_EVTCHN(evtchn)) mask_evtchn(evtchn); } -static void ack_dynirq(struct irq_data *data) +static void ack_dynirq(unsigned int irq) { - int evtchn = evtchn_from_irq(data->irq); + int evtchn = evtchn_from_irq(irq); - move_masked_irq(data->irq); + move_masked_irq(irq); if (VALID_EVTCHN(evtchn)) unmask_evtchn(evtchn); } -static int retrigger_dynirq(struct irq_data *data) +static int retrigger_dynirq(unsigned int irq) { - int evtchn = evtchn_from_irq(data->irq); + int evtchn = evtchn_from_irq(irq); struct shared_info *sh = HYPERVISOR_shared_info; int ret = 0; @@ -1265,7 +1334,7 @@ static void restore_cpu_pirqs(void) printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq); - __startup_pirq(irq); + startup_pirq(irq); } } @@ -1376,6 +1445,7 @@ void xen_poll_irq(int irq) void xen_irq_resume(void) { unsigned int cpu, irq, evtchn; + struct irq_desc *desc; init_evtchn_cpu_bindings(); @@ -1395,48 +1465,66 @@ void xen_irq_resume(void) restore_cpu_ipis(cpu); } + /* + * Unmask any IRQF_NO_SUSPEND IRQs which are enabled. These + * are not handled by the IRQ core. + */ + for_each_irq_desc(irq, desc) { + if (!desc->action || !(desc->action->flags & IRQF_NO_SUSPEND)) + continue; + if (desc->status & IRQ_DISABLED) + continue; + + evtchn = evtchn_from_irq(irq); + if (evtchn == -1) + continue; + + unmask_evtchn(evtchn); + } + restore_cpu_pirqs(); } static struct irq_chip xen_dynamic_chip __read_mostly = { - .name = "xen-dyn", + .name = "xen-dyn", - .irq_disable = disable_dynirq, - .irq_mask = disable_dynirq, - .irq_unmask = enable_dynirq, + .disable = disable_dynirq, + .mask = disable_dynirq, + .unmask = enable_dynirq, - .irq_eoi = ack_dynirq, - .irq_set_affinity = set_affinity_irq, - .irq_retrigger = retrigger_dynirq, + .eoi = ack_dynirq, + .set_affinity = set_affinity_irq, + .retrigger = retrigger_dynirq, }; static struct irq_chip xen_pirq_chip __read_mostly = { - .name = "xen-pirq", + .name = "xen-pirq", - .irq_startup = startup_pirq, - .irq_shutdown = shutdown_pirq, + .startup = startup_pirq, + .shutdown = shutdown_pirq, - .irq_enable = enable_pirq, - .irq_unmask = enable_pirq, + .enable = enable_pirq, + .unmask = enable_pirq, - .irq_disable = disable_pirq, - .irq_mask = disable_pirq, + .disable = disable_pirq, + .mask = disable_pirq, - .irq_ack = ack_pirq, + .ack = ack_pirq, + .end = end_pirq, - .irq_set_affinity = set_affinity_irq, + .set_affinity = set_affinity_irq, - .irq_retrigger = retrigger_dynirq, + .retrigger = retrigger_dynirq, }; static struct irq_chip xen_percpu_chip __read_mostly = { - .name = "xen-percpu", + .name = "xen-percpu", - .irq_disable = disable_dynirq, - .irq_mask = disable_dynirq, - .irq_unmask = enable_dynirq, + .disable = disable_dynirq, + .mask = disable_dynirq, + .unmask = enable_dynirq, - .irq_ack = ack_dynirq, + .ack = ack_dynirq, }; int xen_set_callback_via(uint64_t via) diff --git a/trunk/drivers/xen/manage.c b/trunk/drivers/xen/manage.c index ebb292859b59..24177272bcb8 100644 --- a/trunk/drivers/xen/manage.c +++ b/trunk/drivers/xen/manage.c @@ -34,38 +34,42 @@ enum shutdown_state { /* Ignore multiple shutdown requests. */ static enum shutdown_state shutting_down = SHUTDOWN_INVALID; -struct suspend_info { - int cancelled; - unsigned long arg; /* extra hypercall argument */ - void (*pre)(void); - void (*post)(int cancelled); -}; - -static void xen_hvm_post_suspend(int cancelled) +#ifdef CONFIG_PM_SLEEP +static int xen_hvm_suspend(void *data) { - xen_arch_hvm_post_suspend(cancelled); - gnttab_resume(); -} + int err; + struct sched_shutdown r = { .reason = SHUTDOWN_suspend }; + int *cancelled = data; -static void xen_pre_suspend(void) -{ - xen_mm_pin_all(); - gnttab_suspend(); - xen_arch_pre_suspend(); -} + BUG_ON(!irqs_disabled()); -static void xen_post_suspend(int cancelled) -{ - xen_arch_post_suspend(cancelled); + err = sysdev_suspend(PMSG_SUSPEND); + if (err) { + printk(KERN_ERR "xen_hvm_suspend: sysdev_suspend failed: %d\n", + err); + return err; + } + + *cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r); + + xen_hvm_post_suspend(*cancelled); gnttab_resume(); - xen_mm_unpin_all(); + + if (!*cancelled) { + xen_irq_resume(); + xen_console_resume(); + xen_timer_resume(); + } + + sysdev_resume(); + + return 0; } -#ifdef CONFIG_PM_SLEEP static int xen_suspend(void *data) { - struct suspend_info *si = data; int err; + int *cancelled = data; BUG_ON(!irqs_disabled()); @@ -76,20 +80,22 @@ static int xen_suspend(void *data) return err; } - if (si->pre) - si->pre(); + xen_mm_pin_all(); + gnttab_suspend(); + xen_pre_suspend(); /* * This hypercall returns 1 if suspend was cancelled * or the domain was merely checkpointed, and 0 if it * is resuming in a new domain. */ - si->cancelled = HYPERVISOR_suspend(si->arg); + *cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); - if (si->post) - si->post(si->cancelled); + xen_post_suspend(*cancelled); + gnttab_resume(); + xen_mm_unpin_all(); - if (!si->cancelled) { + if (!*cancelled) { xen_irq_resume(); xen_console_resume(); xen_timer_resume(); @@ -103,7 +109,7 @@ static int xen_suspend(void *data) static void do_suspend(void) { int err; - struct suspend_info si; + int cancelled = 1; shutting_down = SHUTDOWN_SUSPEND; @@ -133,29 +139,20 @@ static void do_suspend(void) goto out_resume; } - si.cancelled = 1; - - if (xen_hvm_domain()) { - si.arg = 0UL; - si.pre = NULL; - si.post = &xen_hvm_post_suspend; - } else { - si.arg = virt_to_mfn(xen_start_info); - si.pre = &xen_pre_suspend; - si.post = &xen_post_suspend; - } - - err = stop_machine(xen_suspend, &si, cpumask_of(0)); + if (xen_hvm_domain()) + err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0)); + else + err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); dpm_resume_noirq(PMSG_RESUME); if (err) { printk(KERN_ERR "failed to start xen_suspend: %d\n", err); - si.cancelled = 1; + cancelled = 1; } out_resume: - if (!si.cancelled) { + if (!cancelled) { xen_arch_resume(); xs_resume(); } else @@ -175,39 +172,12 @@ static void do_suspend(void) } #endif /* CONFIG_PM_SLEEP */ -struct shutdown_handler { - const char *command; - void (*cb)(void); -}; - -static void do_poweroff(void) -{ - shutting_down = SHUTDOWN_POWEROFF; - orderly_poweroff(false); -} - -static void do_reboot(void) -{ - shutting_down = SHUTDOWN_POWEROFF; /* ? */ - ctrl_alt_del(); -} - static void shutdown_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { char *str; struct xenbus_transaction xbt; int err; - static struct shutdown_handler handlers[] = { - { "poweroff", do_poweroff }, - { "halt", do_poweroff }, - { "reboot", do_reboot }, -#ifdef CONFIG_PM_SLEEP - { "suspend", do_suspend }, -#endif - {NULL, NULL}, - }; - static struct shutdown_handler *handler; if (shutting_down != SHUTDOWN_INVALID) return; @@ -224,14 +194,7 @@ static void shutdown_handler(struct xenbus_watch *watch, return; } - for (handler = &handlers[0]; handler->command; handler++) { - if (strcmp(str, handler->command) == 0) - break; - } - - /* Only acknowledge commands which we are prepared to handle. */ - if (handler->cb) - xenbus_write(xbt, "control", "shutdown", ""); + xenbus_write(xbt, "control", "shutdown", ""); err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) { @@ -239,8 +202,17 @@ static void shutdown_handler(struct xenbus_watch *watch, goto again; } - if (handler->cb) { - handler->cb(); + if (strcmp(str, "poweroff") == 0 || + strcmp(str, "halt") == 0) { + shutting_down = SHUTDOWN_POWEROFF; + orderly_poweroff(false); + } else if (strcmp(str, "reboot") == 0) { + shutting_down = SHUTDOWN_POWEROFF; /* ? */ + ctrl_alt_del(); +#ifdef CONFIG_PM_SLEEP + } else if (strcmp(str, "suspend") == 0) { + do_suspend(); +#endif } else { printk(KERN_INFO "Ignoring shutdown request: %s\n", str); shutting_down = SHUTDOWN_INVALID; @@ -319,18 +291,27 @@ static int shutdown_event(struct notifier_block *notifier, return NOTIFY_DONE; } +static int __init __setup_shutdown_event(void) +{ + /* Delay initialization in the PV on HVM case */ + if (xen_hvm_domain()) + return 0; + + if (!xen_pv_domain()) + return -ENODEV; + + return xen_setup_shutdown_event(); +} + int xen_setup_shutdown_event(void) { static struct notifier_block xenstore_notifier = { .notifier_call = shutdown_event }; - - if (!xen_domain()) - return -ENODEV; register_xenstore_notifier(&xenstore_notifier); return 0; } EXPORT_SYMBOL_GPL(xen_setup_shutdown_event); -subsys_initcall(xen_setup_shutdown_event); +subsys_initcall(__setup_shutdown_event); diff --git a/trunk/drivers/xen/platform-pci.c b/trunk/drivers/xen/platform-pci.c index 319dd0a94d51..afbe041f42c5 100644 --- a/trunk/drivers/xen/platform-pci.c +++ b/trunk/drivers/xen/platform-pci.c @@ -156,6 +156,9 @@ static int __devinit platform_pci_init(struct pci_dev *pdev, if (ret) goto out; xenbus_probe(NULL); + ret = xen_setup_shutdown_event(); + if (ret) + goto out; return 0; out: diff --git a/trunk/fs/Kconfig b/trunk/fs/Kconfig index 7cb53aafac1e..3db9caa57edc 100644 --- a/trunk/fs/Kconfig +++ b/trunk/fs/Kconfig @@ -47,7 +47,7 @@ config FS_POSIX_ACL def_bool n config EXPORTFS - bool + tristate config FILE_LOCKING bool "Enable POSIX file locking API" if EXPERT diff --git a/trunk/fs/Makefile b/trunk/fs/Makefile index ba01202844c5..a7f7cef0c0c8 100644 --- a/trunk/fs/Makefile +++ b/trunk/fs/Makefile @@ -48,8 +48,6 @@ obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o obj-$(CONFIG_NFS_COMMON) += nfs_common/ obj-$(CONFIG_GENERIC_ACL) += generic_acl.o -obj-$(CONFIG_FHANDLE) += fhandle.o - obj-y += quota/ obj-$(CONFIG_PROC_FS) += proc/ diff --git a/trunk/fs/btrfs/ctree.h b/trunk/fs/btrfs/ctree.h index 7f78cc78fdd0..6f820fa23df4 100644 --- a/trunk/fs/btrfs/ctree.h +++ b/trunk/fs/btrfs/ctree.h @@ -729,15 +729,6 @@ struct btrfs_space_info { u64 disk_total; /* total bytes on disk, takes mirrors into account */ - /* - * we bump reservation progress every time we decrement - * bytes_reserved. This way people waiting for reservations - * know something good has happened and they can check - * for progress. The number here isn't to be trusted, it - * just shows reclaim activity - */ - unsigned long reservation_progress; - int full; /* indicates that we cannot allocate any more chunks for this space */ int force_alloc; /* set if we need to force a chunk alloc for diff --git a/trunk/fs/btrfs/export.c b/trunk/fs/btrfs/export.c index b4ffad859adb..ff27d7a477b2 100644 --- a/trunk/fs/btrfs/export.c +++ b/trunk/fs/btrfs/export.c @@ -21,13 +21,9 @@ static int btrfs_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, int len = *max_len; int type; - if (connectable && (len < BTRFS_FID_SIZE_CONNECTABLE)) { - *max_len = BTRFS_FID_SIZE_CONNECTABLE; + if ((len < BTRFS_FID_SIZE_NON_CONNECTABLE) || + (connectable && len < BTRFS_FID_SIZE_CONNECTABLE)) return 255; - } else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) { - *max_len = BTRFS_FID_SIZE_NON_CONNECTABLE; - return 255; - } len = BTRFS_FID_SIZE_NON_CONNECTABLE; type = FILEID_BTRFS_WITHOUT_PARENT; diff --git a/trunk/fs/btrfs/extent-tree.c b/trunk/fs/btrfs/extent-tree.c index 7b3089b5c2df..588ff9849873 100644 --- a/trunk/fs/btrfs/extent-tree.c +++ b/trunk/fs/btrfs/extent-tree.c @@ -3342,16 +3342,15 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, u64 max_reclaim; u64 reclaimed = 0; long time_left; + int pause = 1; int nr_pages = (2 * 1024 * 1024) >> PAGE_CACHE_SHIFT; int loops = 0; - unsigned long progress; block_rsv = &root->fs_info->delalloc_block_rsv; space_info = block_rsv->space_info; smp_mb(); reserved = space_info->bytes_reserved; - progress = space_info->reservation_progress; if (reserved == 0) return 0; @@ -3366,36 +3365,31 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages); spin_lock(&space_info->lock); - if (reserved > space_info->bytes_reserved) + if (reserved > space_info->bytes_reserved) { + loops = 0; reclaimed += reserved - space_info->bytes_reserved; + } else { + loops++; + } reserved = space_info->bytes_reserved; spin_unlock(&space_info->lock); - loops++; - if (reserved == 0 || reclaimed >= max_reclaim) break; if (trans && trans->transaction->blocked) return -EAGAIN; - time_left = schedule_timeout_interruptible(1); + __set_current_state(TASK_INTERRUPTIBLE); + time_left = schedule_timeout(pause); /* We were interrupted, exit */ if (time_left) break; - /* we've kicked the IO a few times, if anything has been freed, - * exit. There is no sense in looping here for a long time - * when we really need to commit the transaction, or there are - * just too many writers without enough free space - */ - - if (loops > 3) { - smp_mb(); - if (progress != space_info->reservation_progress) - break; - } + pause <<= 1; + if (pause > HZ / 10) + pause = HZ / 10; } return reclaimed >= to_reclaim; @@ -3618,7 +3612,6 @@ void block_rsv_release_bytes(struct btrfs_block_rsv *block_rsv, if (num_bytes) { spin_lock(&space_info->lock); space_info->bytes_reserved -= num_bytes; - space_info->reservation_progress++; spin_unlock(&space_info->lock); } } @@ -3851,7 +3844,6 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info) if (block_rsv->reserved >= block_rsv->size) { num_bytes = block_rsv->reserved - block_rsv->size; sinfo->bytes_reserved -= num_bytes; - sinfo->reservation_progress++; block_rsv->reserved = block_rsv->size; block_rsv->full = 1; } @@ -4013,6 +4005,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) to_reserve = 0; } spin_unlock(&BTRFS_I(inode)->accounting_lock); + to_reserve += calc_csum_metadata_size(inode, num_bytes); ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); if (ret) @@ -4140,7 +4133,6 @@ static int update_block_group(struct btrfs_trans_handle *trans, btrfs_set_block_group_used(&cache->item, old_val); cache->reserved -= num_bytes; cache->space_info->bytes_reserved -= num_bytes; - cache->space_info->reservation_progress++; cache->space_info->bytes_used += num_bytes; cache->space_info->disk_used += num_bytes * factor; spin_unlock(&cache->lock); @@ -4192,7 +4184,6 @@ static int pin_down_extent(struct btrfs_root *root, if (reserved) { cache->reserved -= num_bytes; cache->space_info->bytes_reserved -= num_bytes; - cache->space_info->reservation_progress++; } spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock); @@ -4243,7 +4234,6 @@ static int update_reserved_bytes(struct btrfs_block_group_cache *cache, space_info->bytes_readonly += num_bytes; cache->reserved -= num_bytes; space_info->bytes_reserved -= num_bytes; - space_info->reservation_progress++; } spin_unlock(&cache->lock); spin_unlock(&space_info->lock); @@ -4722,7 +4712,6 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, if (ret) { spin_lock(&cache->space_info->lock); cache->space_info->bytes_reserved -= buf->len; - cache->space_info->reservation_progress++; spin_unlock(&cache->space_info->lock); } goto out; diff --git a/trunk/fs/btrfs/extent_io.c b/trunk/fs/btrfs/extent_io.c index 714adc4ac4c2..fd3f172e94e6 100644 --- a/trunk/fs/btrfs/extent_io.c +++ b/trunk/fs/btrfs/extent_io.c @@ -3046,38 +3046,17 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, } while (!end) { - u64 offset_in_extent; - - /* break if the extent we found is outside the range */ - if (em->start >= max || extent_map_end(em) < off) - break; - - /* - * get_extent may return an extent that starts before our - * requested range. We have to make sure the ranges - * we return to fiemap always move forward and don't - * overlap, so adjust the offsets here - */ - em_start = max(em->start, off); + off = extent_map_end(em); + if (off >= max) + end = 1; - /* - * record the offset from the start of the extent - * for adjusting the disk offset below - */ - offset_in_extent = em_start - em->start; + em_start = em->start; + em_len = em->len; em_end = extent_map_end(em); - em_len = em_end - em_start; emflags = em->flags; disko = 0; flags = 0; - /* - * bump off for our next call to get_extent - */ - off = extent_map_end(em); - if (off >= max) - end = 1; - if (em->block_start == EXTENT_MAP_LAST_BYTE) { end = 1; flags |= FIEMAP_EXTENT_LAST; @@ -3088,7 +3067,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, flags |= (FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_UNKNOWN); } else { - disko = em->block_start + offset_in_extent; + disko = em->block_start; } if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) flags |= FIEMAP_EXTENT_ENCODED; diff --git a/trunk/fs/btrfs/file.c b/trunk/fs/btrfs/file.c index f447b783bb84..7084140d5940 100644 --- a/trunk/fs/btrfs/file.c +++ b/trunk/fs/btrfs/file.c @@ -70,19 +70,6 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, /* Flush processor's dcache for this page */ flush_dcache_page(page); - - /* - * if we get a partial write, we can end up with - * partially up to date pages. These add - * a lot of complexity, so make sure they don't - * happen by forcing this copy to be retried. - * - * The rest of the btrfs_file_write code will fall - * back to page at a time copies after we return 0. - */ - if (!PageUptodate(page) && copied < count) - copied = 0; - iov_iter_advance(i, copied); write_bytes -= copied; total_copied += copied; @@ -775,27 +762,6 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, return 0; } -/* - * on error we return an unlocked page and the error value - * on success we return a locked page and 0 - */ -static int prepare_uptodate_page(struct page *page, u64 pos) -{ - int ret = 0; - - if ((pos & (PAGE_CACHE_SIZE - 1)) && !PageUptodate(page)) { - ret = btrfs_readpage(NULL, page); - if (ret) - return ret; - lock_page(page); - if (!PageUptodate(page)) { - unlock_page(page); - return -EIO; - } - } - return 0; -} - /* * this gets pages into the page cache and locks them down, it also properly * waits for data=ordered extents to finish before allowing the pages to be @@ -811,7 +777,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, unsigned long index = pos >> PAGE_CACHE_SHIFT; struct inode *inode = fdentry(file)->d_inode; int err = 0; - int faili = 0; u64 start_pos; u64 last_pos; @@ -829,24 +794,15 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, for (i = 0; i < num_pages; i++) { pages[i] = grab_cache_page(inode->i_mapping, index + i); if (!pages[i]) { - faili = i - 1; - err = -ENOMEM; - goto fail; - } - - if (i == 0) - err = prepare_uptodate_page(pages[i], pos); - if (i == num_pages - 1) - err = prepare_uptodate_page(pages[i], - pos + write_bytes); - if (err) { - page_cache_release(pages[i]); - faili = i - 1; - goto fail; + int c; + for (c = i - 1; c >= 0; c--) { + unlock_page(pages[c]); + page_cache_release(pages[c]); + } + return -ENOMEM; } wait_on_page_writeback(pages[i]); } - err = 0; if (start_pos < inode->i_size) { struct btrfs_ordered_extent *ordered; lock_extent_bits(&BTRFS_I(inode)->io_tree, @@ -886,14 +842,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, WARN_ON(!PageLocked(pages[i])); } return 0; -fail: - while (faili >= 0) { - unlock_page(pages[faili]); - page_cache_release(pages[faili]); - faili--; - } - return err; - } static ssize_t btrfs_file_aio_write(struct kiocb *iocb, @@ -903,6 +851,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, struct file *file = iocb->ki_filp; struct inode *inode = fdentry(file)->d_inode; struct btrfs_root *root = BTRFS_I(inode)->root; + struct page *pinned[2]; struct page **pages = NULL; struct iov_iter i; loff_t *ppos = &iocb->ki_pos; @@ -923,6 +872,9 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || (file->f_flags & O_DIRECT)); + pinned[0] = NULL; + pinned[1] = NULL; + start_pos = pos; vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); @@ -1010,6 +962,32 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, first_index = pos >> PAGE_CACHE_SHIFT; last_index = (pos + iov_iter_count(&i)) >> PAGE_CACHE_SHIFT; + /* + * there are lots of better ways to do this, but this code + * makes sure the first and last page in the file range are + * up to date and ready for cow + */ + if ((pos & (PAGE_CACHE_SIZE - 1))) { + pinned[0] = grab_cache_page(inode->i_mapping, first_index); + if (!PageUptodate(pinned[0])) { + ret = btrfs_readpage(NULL, pinned[0]); + BUG_ON(ret); + wait_on_page_locked(pinned[0]); + } else { + unlock_page(pinned[0]); + } + } + if ((pos + iov_iter_count(&i)) & (PAGE_CACHE_SIZE - 1)) { + pinned[1] = grab_cache_page(inode->i_mapping, last_index); + if (!PageUptodate(pinned[1])) { + ret = btrfs_readpage(NULL, pinned[1]); + BUG_ON(ret); + wait_on_page_locked(pinned[1]); + } else { + unlock_page(pinned[1]); + } + } + while (iov_iter_count(&i) > 0) { size_t offset = pos & (PAGE_CACHE_SIZE - 1); size_t write_bytes = min(iov_iter_count(&i), @@ -1046,20 +1024,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, copied = btrfs_copy_from_user(pos, num_pages, write_bytes, pages, &i); - - /* - * if we have trouble faulting in the pages, fall - * back to one page at a time - */ - if (copied < write_bytes) - nrptrs = 1; - - if (copied == 0) - dirty_pages = 0; - else - dirty_pages = (copied + offset + - PAGE_CACHE_SIZE - 1) >> - PAGE_CACHE_SHIFT; + dirty_pages = (copied + offset + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT; if (num_pages > dirty_pages) { if (copied > 0) @@ -1103,6 +1069,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, err = ret; kfree(pages); + if (pinned[0]) + page_cache_release(pinned[0]); + if (pinned[1]) + page_cache_release(pinned[1]); *ppos = pos; /* diff --git a/trunk/fs/btrfs/inode.c b/trunk/fs/btrfs/inode.c index 4a0107e18747..0efdb65953c5 100644 --- a/trunk/fs/btrfs/inode.c +++ b/trunk/fs/btrfs/inode.c @@ -4806,6 +4806,9 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, int err; int drop_inode = 0; + if (inode->i_nlink == 0) + return -ENOENT; + /* do not allow sys_link's with other subvols of the same device */ if (root->objectid != BTRFS_I(inode)->root->objectid) return -EPERM; @@ -4818,11 +4821,10 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, goto fail; /* - * 2 items for inode and inode ref + * 1 item for inode ref * 2 items for dir items - * 1 item for parent inode */ - trans = btrfs_start_transaction(root, 5); + trans = btrfs_start_transaction(root, 3); if (IS_ERR(trans)) { err = PTR_ERR(trans); goto fail; @@ -6054,7 +6056,6 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, if (!skip_sum) { dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS); if (!dip->csums) { - kfree(dip); ret = -ENOMEM; goto free_ordered; } diff --git a/trunk/fs/ceph/dir.c b/trunk/fs/ceph/dir.c index ebafa65a29b6..099a58615b90 100644 --- a/trunk/fs/ceph/dir.c +++ b/trunk/fs/ceph/dir.c @@ -993,7 +993,7 @@ static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) { struct inode *dir; - if (nd && nd->flags & LOOKUP_RCU) + if (nd->flags & LOOKUP_RCU) return -ECHILD; dir = dentry->d_parent->d_inode; diff --git a/trunk/fs/compat.c b/trunk/fs/compat.c index c6d31a3bab88..f6fd0a00e6cc 100644 --- a/trunk/fs/compat.c +++ b/trunk/fs/compat.c @@ -262,19 +262,35 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs * */ asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf) { - struct kstatfs tmp; - int error = user_statfs(pathname, &tmp); - if (!error) - error = put_compat_statfs(buf, &tmp); + struct path path; + int error; + + error = user_path(pathname, &path); + if (!error) { + struct kstatfs tmp; + error = vfs_statfs(&path, &tmp); + if (!error) + error = put_compat_statfs(buf, &tmp); + path_put(&path); + } return error; } asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf) { + struct file * file; struct kstatfs tmp; - int error = fd_statfs(fd, &tmp); + int error; + + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = vfs_statfs(&file->f_path, &tmp); if (!error) error = put_compat_statfs(buf, &tmp); + fput(file); +out: return error; } @@ -313,29 +329,41 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf) { - struct kstatfs tmp; + struct path path; int error; if (sz != sizeof(*buf)) return -EINVAL; - error = user_statfs(pathname, &tmp); - if (!error) - error = put_compat_statfs64(buf, &tmp); + error = user_path(pathname, &path); + if (!error) { + struct kstatfs tmp; + error = vfs_statfs(&path, &tmp); + if (!error) + error = put_compat_statfs64(buf, &tmp); + path_put(&path); + } return error; } asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf) { + struct file * file; struct kstatfs tmp; int error; if (sz != sizeof(*buf)) return -EINVAL; - error = fd_statfs(fd, &tmp); + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = vfs_statfs(&file->f_path, &tmp); if (!error) error = put_compat_statfs64(buf, &tmp); + fput(file); +out: return error; } @@ -1200,9 +1228,7 @@ compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec, file = fget_light(fd, &fput_needed); if (!file) return -EBADF; - ret = -ESPIPE; - if (file->f_mode & FMODE_PREAD) - ret = compat_readv(file, vec, vlen, &pos); + ret = compat_readv(file, vec, vlen, &pos); fput_light(file, fput_needed); return ret; } @@ -1259,9 +1285,7 @@ compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec, file = fget_light(fd, &fput_needed); if (!file) return -EBADF; - ret = -ESPIPE; - if (file->f_mode & FMODE_PWRITE) - ret = compat_writev(file, vec, vlen, &pos); + ret = compat_writev(file, vec, vlen, &pos); fput_light(file, fput_needed); return ret; } @@ -2284,16 +2308,3 @@ asmlinkage long compat_sys_timerfd_gettime(int ufd, } #endif /* CONFIG_TIMERFD */ - -#ifdef CONFIG_FHANDLE -/* - * Exactly like fs/open.c:sys_open_by_handle_at(), except that it - * doesn't set the O_LARGEFILE flag. - */ -asmlinkage long -compat_sys_open_by_handle_at(int mountdirfd, - struct file_handle __user *handle, int flags) -{ - return do_handle_open(mountdirfd, handle, flags); -} -#endif diff --git a/trunk/fs/dcache.c b/trunk/fs/dcache.c index a39fe47c466f..2a6bd9a4ae97 100644 --- a/trunk/fs/dcache.c +++ b/trunk/fs/dcache.c @@ -296,12 +296,8 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) __releases(parent->d_lock) __releases(dentry->d_inode->i_lock) { + dentry->d_parent = NULL; list_del(&dentry->d_u.d_child); - /* - * Inform try_to_ascend() that we are no longer attached to the - * dentry tree - */ - dentry->d_flags |= DCACHE_DISCONNECTED; if (parent) spin_unlock(&parent->d_lock); dentry_iput(dentry); @@ -1015,35 +1011,6 @@ void shrink_dcache_for_umount(struct super_block *sb) } } -/* - * This tries to ascend one level of parenthood, but - * we can race with renaming, so we need to re-check - * the parenthood after dropping the lock and check - * that the sequence number still matches. - */ -static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq) -{ - struct dentry *new = old->d_parent; - - rcu_read_lock(); - spin_unlock(&old->d_lock); - spin_lock(&new->d_lock); - - /* - * might go back up the wrong parent if we have had a rename - * or deletion - */ - if (new != old->d_parent || - (old->d_flags & DCACHE_DISCONNECTED) || - (!locked && read_seqretry(&rename_lock, seq))) { - spin_unlock(&new->d_lock); - new = NULL; - } - rcu_read_unlock(); - return new; -} - - /* * Search for at least 1 mount point in the dentry's subdirs. * We descend to the next level whenever the d_subdirs @@ -1099,10 +1066,24 @@ int have_submounts(struct dentry *parent) * All done at this level ... ascend and resume the search. */ if (this_parent != parent) { - struct dentry *child = this_parent; - this_parent = try_to_ascend(this_parent, locked, seq); - if (!this_parent) + struct dentry *tmp; + struct dentry *child; + + tmp = this_parent->d_parent; + rcu_read_lock(); + spin_unlock(&this_parent->d_lock); + child = this_parent; + this_parent = tmp; + spin_lock(&this_parent->d_lock); + /* might go back up the wrong parent if we have had a rename + * or deletion */ + if (this_parent != child->d_parent || + (!locked && read_seqretry(&rename_lock, seq))) { + spin_unlock(&this_parent->d_lock); + rcu_read_unlock(); goto rename_retry; + } + rcu_read_unlock(); next = child->d_u.d_child.next; goto resume; } @@ -1200,10 +1181,24 @@ static int select_parent(struct dentry * parent) * All done at this level ... ascend and resume the search. */ if (this_parent != parent) { - struct dentry *child = this_parent; - this_parent = try_to_ascend(this_parent, locked, seq); - if (!this_parent) + struct dentry *tmp; + struct dentry *child; + + tmp = this_parent->d_parent; + rcu_read_lock(); + spin_unlock(&this_parent->d_lock); + child = this_parent; + this_parent = tmp; + spin_lock(&this_parent->d_lock); + /* might go back up the wrong parent if we have had a rename + * or deletion */ + if (this_parent != child->d_parent || + (!locked && read_seqretry(&rename_lock, seq))) { + spin_unlock(&this_parent->d_lock); + rcu_read_unlock(); goto rename_retry; + } + rcu_read_unlock(); next = child->d_u.d_child.next; goto resume; } @@ -1528,28 +1523,6 @@ struct dentry * d_alloc_root(struct inode * root_inode) } EXPORT_SYMBOL(d_alloc_root); -static struct dentry * __d_find_any_alias(struct inode *inode) -{ - struct dentry *alias; - - if (list_empty(&inode->i_dentry)) - return NULL; - alias = list_first_entry(&inode->i_dentry, struct dentry, d_alias); - __dget(alias); - return alias; -} - -static struct dentry * d_find_any_alias(struct inode *inode) -{ - struct dentry *de; - - spin_lock(&inode->i_lock); - de = __d_find_any_alias(inode); - spin_unlock(&inode->i_lock); - return de; -} - - /** * d_obtain_alias - find or allocate a dentry for a given inode * @inode: inode to allocate the dentry for @@ -1579,7 +1552,7 @@ struct dentry *d_obtain_alias(struct inode *inode) if (IS_ERR(inode)) return ERR_CAST(inode); - res = d_find_any_alias(inode); + res = d_find_alias(inode); if (res) goto out_iput; @@ -1592,7 +1565,7 @@ struct dentry *d_obtain_alias(struct inode *inode) spin_lock(&inode->i_lock); - res = __d_find_any_alias(inode); + res = __d_find_alias(inode, 0); if (res) { spin_unlock(&inode->i_lock); dput(tmp); @@ -2947,14 +2920,28 @@ void d_genocide(struct dentry *root) spin_unlock(&dentry->d_lock); } if (this_parent != root) { - struct dentry *child = this_parent; + struct dentry *tmp; + struct dentry *child; + + tmp = this_parent->d_parent; if (!(this_parent->d_flags & DCACHE_GENOCIDE)) { this_parent->d_flags |= DCACHE_GENOCIDE; this_parent->d_count--; } - this_parent = try_to_ascend(this_parent, locked, seq); - if (!this_parent) + rcu_read_lock(); + spin_unlock(&this_parent->d_lock); + child = this_parent; + this_parent = tmp; + spin_lock(&this_parent->d_lock); + /* might go back up the wrong parent if we have had a rename + * or deletion */ + if (this_parent != child->d_parent || + (!locked && read_seqretry(&rename_lock, seq))) { + spin_unlock(&this_parent->d_lock); + rcu_read_unlock(); goto rename_retry; + } + rcu_read_unlock(); next = child->d_u.d_child.next; goto resume; } diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index ba99e1abb1aa..52a447d9b6ab 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -115,16 +115,13 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) struct file *file; char *tmp = getname(library); int error = PTR_ERR(tmp); - static const struct open_flags uselib_flags = { - .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, - .acc_mode = MAY_READ | MAY_EXEC | MAY_OPEN, - .intent = LOOKUP_OPEN - }; if (IS_ERR(tmp)) goto out; - file = do_filp_open(AT_FDCWD, tmp, &uselib_flags, LOOKUP_FOLLOW); + file = do_filp_open(AT_FDCWD, tmp, + O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0, + MAY_READ | MAY_EXEC | MAY_OPEN); putname(tmp); error = PTR_ERR(file); if (IS_ERR(file)) @@ -724,13 +721,10 @@ struct file *open_exec(const char *name) { struct file *file; int err; - static const struct open_flags open_exec_flags = { - .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, - .acc_mode = MAY_EXEC | MAY_OPEN, - .intent = LOOKUP_OPEN - }; - file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW); + file = do_filp_open(AT_FDCWD, name, + O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0, + MAY_EXEC | MAY_OPEN); if (IS_ERR(file)) goto out; diff --git a/trunk/fs/exportfs/expfs.c b/trunk/fs/exportfs/expfs.c index b05acb796135..4b6825740dd5 100644 --- a/trunk/fs/exportfs/expfs.c +++ b/trunk/fs/exportfs/expfs.c @@ -320,14 +320,9 @@ static int export_encode_fh(struct dentry *dentry, struct fid *fid, struct inode * inode = dentry->d_inode; int len = *max_len; int type = FILEID_INO32_GEN; - - if (connectable && (len < 4)) { - *max_len = 4; - return 255; - } else if (len < 2) { - *max_len = 2; + + if (len < 2 || (connectable && len < 4)) return 255; - } len = 2; fid->i32.ino = inode->i_ino; @@ -374,8 +369,6 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, /* * Try to get any dentry for the given file handle from the filesystem. */ - if (!nop || !nop->fh_to_dentry) - return ERR_PTR(-ESTALE); result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type); if (!result) result = ERR_PTR(-ESTALE); diff --git a/trunk/fs/ext3/namei.c b/trunk/fs/ext3/namei.c index 561f69256266..b27ba71810ec 100644 --- a/trunk/fs/ext3/namei.c +++ b/trunk/fs/ext3/namei.c @@ -2253,6 +2253,13 @@ static int ext3_link (struct dentry * old_dentry, dquot_initialize(dir); + /* + * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing + * otherwise has the potential to corrupt the orphan inode list. + */ + if (inode->i_nlink == 0) + return -ENOENT; + retry: handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + EXT3_INDEX_EXTRA_TRANS_BLOCKS); diff --git a/trunk/fs/ext3/super.c b/trunk/fs/ext3/super.c index 9cc19a1dea8e..85c8cc8f2473 100644 --- a/trunk/fs/ext3/super.c +++ b/trunk/fs/ext3/super.c @@ -1936,7 +1936,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) sb->s_qcop = &ext3_qctl_operations; sb->dq_op = &ext3_quota_operations; #endif - memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid)); INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */ mutex_init(&sbi->s_orphan_lock); mutex_init(&sbi->s_resize_lock); diff --git a/trunk/fs/ext4/namei.c b/trunk/fs/ext4/namei.c index e781b7ea5630..5485390d32c5 100644 --- a/trunk/fs/ext4/namei.c +++ b/trunk/fs/ext4/namei.c @@ -2304,6 +2304,13 @@ static int ext4_link(struct dentry *old_dentry, dquot_initialize(dir); + /* + * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing + * otherwise has the potential to corrupt the orphan inode list. + */ + if (inode->i_nlink == 0) + return -ENOENT; + retry: handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS); diff --git a/trunk/fs/ext4/super.c b/trunk/fs/ext4/super.c index 5977b356a435..f6a318f836b2 100644 --- a/trunk/fs/ext4/super.c +++ b/trunk/fs/ext4/super.c @@ -3415,8 +3415,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) sb->s_qcop = &ext4_qctl_operations; sb->dq_op = &ext4_quota_operations; #endif - memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid)); - INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */ mutex_init(&sbi->s_orphan_lock); mutex_init(&sbi->s_resize_lock); diff --git a/trunk/fs/fat/inode.c b/trunk/fs/fat/inode.c index 0e277ec4b612..86753fe10bd1 100644 --- a/trunk/fs/fat/inode.c +++ b/trunk/fs/fat/inode.c @@ -757,10 +757,8 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable) struct inode *inode = de->d_inode; u32 ipos_h, ipos_m, ipos_l; - if (len < 5) { - *lenp = 5; + if (len < 5) return 255; /* no room */ - } ipos_h = MSDOS_I(inode)->i_pos >> 8; ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24; diff --git a/trunk/fs/fat/namei_vfat.c b/trunk/fs/fat/namei_vfat.c index adae3fb7451a..f88f752babd9 100644 --- a/trunk/fs/fat/namei_vfat.c +++ b/trunk/fs/fat/namei_vfat.c @@ -43,7 +43,7 @@ static int vfat_revalidate_shortname(struct dentry *dentry) static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd) { - if (nd && nd->flags & LOOKUP_RCU) + if (nd->flags & LOOKUP_RCU) return -ECHILD; /* This is not negative dentry. Always valid. */ @@ -54,7 +54,7 @@ static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd) static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd) { - if (nd && nd->flags & LOOKUP_RCU) + if (nd->flags & LOOKUP_RCU) return -ECHILD; /* diff --git a/trunk/fs/fcntl.c b/trunk/fs/fcntl.c index 6c82e5bac039..cb1026181bdc 100644 --- a/trunk/fs/fcntl.c +++ b/trunk/fs/fcntl.c @@ -131,7 +131,7 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd) SYSCALL_DEFINE1(dup, unsigned int, fildes) { int ret = -EBADF; - struct file *file = fget_raw(fildes); + struct file *file = fget(fildes); if (file) { ret = get_unused_fd(); @@ -426,35 +426,15 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, return err; } -static int check_fcntl_cmd(unsigned cmd) -{ - switch (cmd) { - case F_DUPFD: - case F_DUPFD_CLOEXEC: - case F_GETFD: - case F_SETFD: - case F_GETFL: - return 1; - } - return 0; -} - SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) { struct file *filp; long err = -EBADF; - filp = fget_raw(fd); + filp = fget(fd); if (!filp) goto out; - if (unlikely(filp->f_mode & FMODE_PATH)) { - if (!check_fcntl_cmd(cmd)) { - fput(filp); - goto out; - } - } - err = security_file_fcntl(filp, cmd, arg); if (err) { fput(filp); @@ -476,17 +456,10 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, long err; err = -EBADF; - filp = fget_raw(fd); + filp = fget(fd); if (!filp) goto out; - if (unlikely(filp->f_mode & FMODE_PATH)) { - if (!check_fcntl_cmd(cmd)) { - fput(filp); - goto out; - } - } - err = security_file_fcntl(filp, cmd, arg); if (err) { fput(filp); @@ -835,14 +808,14 @@ static int __init fcntl_init(void) * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY * is defined as O_NONBLOCK on some platforms and not on others. */ - BUILD_BUG_ON(19 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( + BUILD_BUG_ON(18 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | O_APPEND | /* O_NONBLOCK | */ __O_SYNC | O_DSYNC | FASYNC | O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | O_NOATIME | O_CLOEXEC | - __FMODE_EXEC | O_PATH + __FMODE_EXEC )); fasync_cache = kmem_cache_create("fasync_cache", diff --git a/trunk/fs/fhandle.c b/trunk/fs/fhandle.c deleted file mode 100644 index bf93ad2bee07..000000000000 --- a/trunk/fs/fhandle.c +++ /dev/null @@ -1,265 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "internal.h" - -static long do_sys_name_to_handle(struct path *path, - struct file_handle __user *ufh, - int __user *mnt_id) -{ - long retval; - struct file_handle f_handle; - int handle_dwords, handle_bytes; - struct file_handle *handle = NULL; - - /* - * We need t make sure wether the file system - * support decoding of the file handle - */ - if (!path->mnt->mnt_sb->s_export_op || - !path->mnt->mnt_sb->s_export_op->fh_to_dentry) - return -EOPNOTSUPP; - - if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle))) - return -EFAULT; - - if (f_handle.handle_bytes > MAX_HANDLE_SZ) - return -EINVAL; - - handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes, - GFP_KERNEL); - if (!handle) - return -ENOMEM; - - /* convert handle size to multiple of sizeof(u32) */ - handle_dwords = f_handle.handle_bytes >> 2; - - /* we ask for a non connected handle */ - retval = exportfs_encode_fh(path->dentry, - (struct fid *)handle->f_handle, - &handle_dwords, 0); - handle->handle_type = retval; - /* convert handle size to bytes */ - handle_bytes = handle_dwords * sizeof(u32); - handle->handle_bytes = handle_bytes; - if ((handle->handle_bytes > f_handle.handle_bytes) || - (retval == 255) || (retval == -ENOSPC)) { - /* As per old exportfs_encode_fh documentation - * we could return ENOSPC to indicate overflow - * But file system returned 255 always. So handle - * both the values - */ - /* - * set the handle size to zero so we copy only - * non variable part of the file_handle - */ - handle_bytes = 0; - retval = -EOVERFLOW; - } else - retval = 0; - /* copy the mount id */ - if (copy_to_user(mnt_id, &path->mnt->mnt_id, sizeof(*mnt_id)) || - copy_to_user(ufh, handle, - sizeof(struct file_handle) + handle_bytes)) - retval = -EFAULT; - kfree(handle); - return retval; -} - -/** - * sys_name_to_handle_at: convert name to handle - * @dfd: directory relative to which name is interpreted if not absolute - * @name: name that should be converted to handle. - * @handle: resulting file handle - * @mnt_id: mount id of the file system containing the file - * @flag: flag value to indicate whether to follow symlink or not - * - * @handle->handle_size indicate the space available to store the - * variable part of the file handle in bytes. If there is not - * enough space, the field is updated to return the minimum - * value required. - */ -SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name, - struct file_handle __user *, handle, int __user *, mnt_id, - int, flag) -{ - struct path path; - int lookup_flags; - int err; - - if ((flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) - return -EINVAL; - - lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0; - if (flag & AT_EMPTY_PATH) - lookup_flags |= LOOKUP_EMPTY; - err = user_path_at(dfd, name, lookup_flags, &path); - if (!err) { - err = do_sys_name_to_handle(&path, handle, mnt_id); - path_put(&path); - } - return err; -} - -static struct vfsmount *get_vfsmount_from_fd(int fd) -{ - struct path path; - - if (fd == AT_FDCWD) { - struct fs_struct *fs = current->fs; - spin_lock(&fs->lock); - path = fs->pwd; - mntget(path.mnt); - spin_unlock(&fs->lock); - } else { - int fput_needed; - struct file *file = fget_light(fd, &fput_needed); - if (!file) - return ERR_PTR(-EBADF); - path = file->f_path; - mntget(path.mnt); - fput_light(file, fput_needed); - } - return path.mnt; -} - -static int vfs_dentry_acceptable(void *context, struct dentry *dentry) -{ - return 1; -} - -static int do_handle_to_path(int mountdirfd, struct file_handle *handle, - struct path *path) -{ - int retval = 0; - int handle_dwords; - - path->mnt = get_vfsmount_from_fd(mountdirfd); - if (IS_ERR(path->mnt)) { - retval = PTR_ERR(path->mnt); - goto out_err; - } - /* change the handle size to multiple of sizeof(u32) */ - handle_dwords = handle->handle_bytes >> 2; - path->dentry = exportfs_decode_fh(path->mnt, - (struct fid *)handle->f_handle, - handle_dwords, handle->handle_type, - vfs_dentry_acceptable, NULL); - if (IS_ERR(path->dentry)) { - retval = PTR_ERR(path->dentry); - goto out_mnt; - } - return 0; -out_mnt: - mntput(path->mnt); -out_err: - return retval; -} - -static int handle_to_path(int mountdirfd, struct file_handle __user *ufh, - struct path *path) -{ - int retval = 0; - struct file_handle f_handle; - struct file_handle *handle = NULL; - - /* - * With handle we don't look at the execute bit on the - * the directory. Ideally we would like CAP_DAC_SEARCH. - * But we don't have that - */ - if (!capable(CAP_DAC_READ_SEARCH)) { - retval = -EPERM; - goto out_err; - } - if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle))) { - retval = -EFAULT; - goto out_err; - } - if ((f_handle.handle_bytes > MAX_HANDLE_SZ) || - (f_handle.handle_bytes == 0)) { - retval = -EINVAL; - goto out_err; - } - handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes, - GFP_KERNEL); - if (!handle) { - retval = -ENOMEM; - goto out_err; - } - /* copy the full handle */ - if (copy_from_user(handle, ufh, - sizeof(struct file_handle) + - f_handle.handle_bytes)) { - retval = -EFAULT; - goto out_handle; - } - - retval = do_handle_to_path(mountdirfd, handle, path); - -out_handle: - kfree(handle); -out_err: - return retval; -} - -long do_handle_open(int mountdirfd, - struct file_handle __user *ufh, int open_flag) -{ - long retval = 0; - struct path path; - struct file *file; - int fd; - - retval = handle_to_path(mountdirfd, ufh, &path); - if (retval) - return retval; - - fd = get_unused_fd_flags(open_flag); - if (fd < 0) { - path_put(&path); - return fd; - } - file = file_open_root(path.dentry, path.mnt, "", open_flag); - if (IS_ERR(file)) { - put_unused_fd(fd); - retval = PTR_ERR(file); - } else { - retval = fd; - fsnotify_open(file); - fd_install(fd, file); - } - path_put(&path); - return retval; -} - -/** - * sys_open_by_handle_at: Open the file handle - * @mountdirfd: directory file descriptor - * @handle: file handle to be opened - * @flag: open flags. - * - * @mountdirfd indicate the directory file descriptor - * of the mount point. file handle is decoded relative - * to the vfsmount pointed by the @mountdirfd. @flags - * value is same as the open(2) flags. - */ -SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd, - struct file_handle __user *, handle, - int, flags) -{ - long ret; - - if (force_o_largefile()) - flags |= O_LARGEFILE; - - ret = do_handle_open(mountdirfd, handle, flags); - return ret; -} diff --git a/trunk/fs/file_table.c b/trunk/fs/file_table.c index 74a9544ac770..eb36b6b17e26 100644 --- a/trunk/fs/file_table.c +++ b/trunk/fs/file_table.c @@ -276,10 +276,11 @@ struct file *fget(unsigned int fd) rcu_read_lock(); file = fcheck_files(files, fd); if (file) { - /* File object ref couldn't be taken */ - if (file->f_mode & FMODE_PATH || - !atomic_long_inc_not_zero(&file->f_count)) - file = NULL; + if (!atomic_long_inc_not_zero(&file->f_count)) { + /* File object ref couldn't be taken */ + rcu_read_unlock(); + return NULL; + } } rcu_read_unlock(); @@ -288,25 +289,6 @@ struct file *fget(unsigned int fd) EXPORT_SYMBOL(fget); -struct file *fget_raw(unsigned int fd) -{ - struct file *file; - struct files_struct *files = current->files; - - rcu_read_lock(); - file = fcheck_files(files, fd); - if (file) { - /* File object ref couldn't be taken */ - if (!atomic_long_inc_not_zero(&file->f_count)) - file = NULL; - } - rcu_read_unlock(); - - return file; -} - -EXPORT_SYMBOL(fget_raw); - /* * Lightweight file lookup - no refcnt increment if fd table isn't shared. * @@ -328,33 +310,6 @@ struct file *fget_light(unsigned int fd, int *fput_needed) struct file *file; struct files_struct *files = current->files; - *fput_needed = 0; - if (atomic_read(&files->count) == 1) { - file = fcheck_files(files, fd); - if (file && (file->f_mode & FMODE_PATH)) - file = NULL; - } else { - rcu_read_lock(); - file = fcheck_files(files, fd); - if (file) { - if (!(file->f_mode & FMODE_PATH) && - atomic_long_inc_not_zero(&file->f_count)) - *fput_needed = 1; - else - /* Didn't get the reference, someone's freed */ - file = NULL; - } - rcu_read_unlock(); - } - - return file; -} - -struct file *fget_raw_light(unsigned int fd, int *fput_needed) -{ - struct file *file; - struct files_struct *files = current->files; - *fput_needed = 0; if (atomic_read(&files->count) == 1) { file = fcheck_files(files, fd); diff --git a/trunk/fs/fuse/dir.c b/trunk/fs/fuse/dir.c index 8bd0ef9286c3..83543b5ff941 100644 --- a/trunk/fs/fuse/dir.c +++ b/trunk/fs/fuse/dir.c @@ -158,7 +158,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) { struct inode *inode; - if (nd && nd->flags & LOOKUP_RCU) + if (nd->flags & LOOKUP_RCU) return -ECHILD; inode = entry->d_inode; diff --git a/trunk/fs/fuse/inode.c b/trunk/fs/fuse/inode.c index 051b1a084528..9e3f68cc1bd1 100644 --- a/trunk/fs/fuse/inode.c +++ b/trunk/fs/fuse/inode.c @@ -637,10 +637,8 @@ static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, u64 nodeid; u32 generation; - if (*max_len < len) { - *max_len = len; + if (*max_len < len) return 255; - } nodeid = get_fuse_inode(inode)->nodeid; generation = inode->i_generation; diff --git a/trunk/fs/gfs2/dentry.c b/trunk/fs/gfs2/dentry.c index 0da8da2c991d..4a456338b873 100644 --- a/trunk/fs/gfs2/dentry.c +++ b/trunk/fs/gfs2/dentry.c @@ -44,7 +44,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) int error; int had_lock = 0; - if (nd && nd->flags & LOOKUP_RCU) + if (nd->flags & LOOKUP_RCU) return -ECHILD; parent = dget_parent(dentry); diff --git a/trunk/fs/gfs2/export.c b/trunk/fs/gfs2/export.c index b5a5e60df0d5..9023db8184f9 100644 --- a/trunk/fs/gfs2/export.c +++ b/trunk/fs/gfs2/export.c @@ -36,13 +36,9 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, struct super_block *sb = inode->i_sb; struct gfs2_inode *ip = GFS2_I(inode); - if (connectable && (*len < GFS2_LARGE_FH_SIZE)) { - *len = GFS2_LARGE_FH_SIZE; + if (*len < GFS2_SMALL_FH_SIZE || + (connectable && *len < GFS2_LARGE_FH_SIZE)) return 255; - } else if (*len < GFS2_SMALL_FH_SIZE) { - *len = GFS2_SMALL_FH_SIZE; - return 255; - } fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32); fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF); diff --git a/trunk/fs/internal.h b/trunk/fs/internal.h index f3d15de44b15..9b976b57d7fe 100644 --- a/trunk/fs/internal.h +++ b/trunk/fs/internal.h @@ -106,19 +106,6 @@ extern void put_super(struct super_block *sb); struct nameidata; extern struct file *nameidata_to_filp(struct nameidata *); extern void release_open_intent(struct nameidata *); -struct open_flags { - int open_flag; - int mode; - int acc_mode; - int intent; -}; -extern struct file *do_filp_open(int dfd, const char *pathname, - const struct open_flags *op, int lookup_flags); -extern struct file *do_file_open_root(struct dentry *, struct vfsmount *, - const char *, const struct open_flags *, int lookup_flags); - -extern long do_handle_open(int mountdirfd, - struct file_handle __user *ufh, int open_flag); /* * inode.c diff --git a/trunk/fs/isofs/export.c b/trunk/fs/isofs/export.c index dd4687ff30d0..ed752cb38474 100644 --- a/trunk/fs/isofs/export.c +++ b/trunk/fs/isofs/export.c @@ -124,13 +124,9 @@ isofs_export_encode_fh(struct dentry *dentry, * offset of the inode and the upper 16 bits of fh32[1] to * hold the offset of the parent. */ - if (connectable && (len < 5)) { - *max_len = 5; - return 255; - } else if (len < 3) { - *max_len = 3; + + if (len < 3 || (connectable && len < 5)) return 255; - } len = 3; fh32[0] = ei->i_iget5_block; diff --git a/trunk/fs/jfs/namei.c b/trunk/fs/jfs/namei.c index 3f04a1804931..81ead850ddb6 100644 --- a/trunk/fs/jfs/namei.c +++ b/trunk/fs/jfs/namei.c @@ -809,6 +809,9 @@ static int jfs_link(struct dentry *old_dentry, if (ip->i_nlink == JFS_LINK_MAX) return -EMLINK; + if (ip->i_nlink == 0) + return -ENOENT; + dquot_initialize(dir); tid = txBegin(ip->i_sb, 0); @@ -1597,7 +1600,7 @@ static int jfs_ci_compare(const struct dentry *parent, static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd) { - if (nd && nd->flags & LOOKUP_RCU) + if (nd->flags & LOOKUP_RCU) return -ECHILD; /* * This is not negative dentry. Always valid. diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index 0a601cae23de..0087cf9c2c6b 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -136,7 +136,7 @@ static int do_getname(const char __user *filename, char *page) return retval; } -static char *getname_flags(const char __user * filename, int flags) +char * getname(const char __user * filename) { char *tmp, *result; @@ -147,21 +147,14 @@ static char *getname_flags(const char __user * filename, int flags) result = tmp; if (retval < 0) { - if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) { - __putname(tmp); - result = ERR_PTR(retval); - } + __putname(tmp); + result = ERR_PTR(retval); } } audit_getname(result); return result; } -char *getname(const char __user * filename) -{ - return getname_flags(filename, 0); -} - #ifdef CONFIG_AUDITSYSCALL void putname(const char *name) { @@ -408,11 +401,9 @@ static int nameidata_drop_rcu(struct nameidata *nd) { struct fs_struct *fs = current->fs; struct dentry *dentry = nd->path.dentry; - int want_root = 0; BUG_ON(!(nd->flags & LOOKUP_RCU)); - if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) { - want_root = 1; + if (nd->root.mnt) { spin_lock(&fs->lock); if (nd->root.mnt != fs->root.mnt || nd->root.dentry != fs->root.dentry) @@ -423,7 +414,7 @@ static int nameidata_drop_rcu(struct nameidata *nd) goto err; BUG_ON(nd->inode != dentry->d_inode); spin_unlock(&dentry->d_lock); - if (want_root) { + if (nd->root.mnt) { path_get(&nd->root); spin_unlock(&fs->lock); } @@ -436,7 +427,7 @@ static int nameidata_drop_rcu(struct nameidata *nd) err: spin_unlock(&dentry->d_lock); err_root: - if (want_root) + if (nd->root.mnt) spin_unlock(&fs->lock); return -ECHILD; } @@ -463,11 +454,9 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry { struct fs_struct *fs = current->fs; struct dentry *parent = nd->path.dentry; - int want_root = 0; BUG_ON(!(nd->flags & LOOKUP_RCU)); - if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) { - want_root = 1; + if (nd->root.mnt) { spin_lock(&fs->lock); if (nd->root.mnt != fs->root.mnt || nd->root.dentry != fs->root.dentry) @@ -487,7 +476,7 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry parent->d_count++; spin_unlock(&dentry->d_lock); spin_unlock(&parent->d_lock); - if (want_root) { + if (nd->root.mnt) { path_get(&nd->root); spin_unlock(&fs->lock); } @@ -501,7 +490,7 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry spin_unlock(&dentry->d_lock); spin_unlock(&parent->d_lock); err_root: - if (want_root) + if (nd->root.mnt) spin_unlock(&fs->lock); return -ECHILD; } @@ -509,16 +498,8 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry /* Try to drop out of rcu-walk mode if we were in it, otherwise do nothing. */ static inline int nameidata_dentry_drop_rcu_maybe(struct nameidata *nd, struct dentry *dentry) { - if (nd->flags & LOOKUP_RCU) { - if (unlikely(nameidata_dentry_drop_rcu(nd, dentry))) { - nd->flags &= ~LOOKUP_RCU; - if (!(nd->flags & LOOKUP_ROOT)) - nd->root.mnt = NULL; - rcu_read_unlock(); - br_read_unlock(vfsmount_lock); - return -ECHILD; - } - } + if (nd->flags & LOOKUP_RCU) + return nameidata_dentry_drop_rcu(nd, dentry); return 0; } @@ -537,8 +518,7 @@ static int nameidata_drop_rcu_last(struct nameidata *nd) BUG_ON(!(nd->flags & LOOKUP_RCU)); nd->flags &= ~LOOKUP_RCU; - if (!(nd->flags & LOOKUP_ROOT)) - nd->root.mnt = NULL; + nd->root.mnt = NULL; spin_lock(&dentry->d_lock); if (!__d_rcu_to_refcount(dentry, nd->seq)) goto err_unlock; @@ -559,6 +539,14 @@ static int nameidata_drop_rcu_last(struct nameidata *nd) return -ECHILD; } +/* Try to drop out of rcu-walk mode if we were in it, otherwise do nothing. */ +static inline int nameidata_drop_rcu_last_maybe(struct nameidata *nd) +{ + if (likely(nd->flags & LOOKUP_RCU)) + return nameidata_drop_rcu_last(nd); + return 0; +} + /** * release_open_intent - free up open intent resources * @nd: pointer to nameidata @@ -602,8 +590,42 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd) return dentry; } +static inline struct dentry * +do_revalidate_rcu(struct dentry *dentry, struct nameidata *nd) +{ + int status = d_revalidate(dentry, nd); + if (likely(status > 0)) + return dentry; + if (status == -ECHILD) { + if (nameidata_dentry_drop_rcu(nd, dentry)) + return ERR_PTR(-ECHILD); + return do_revalidate(dentry, nd); + } + if (status < 0) + return ERR_PTR(status); + /* Don't d_invalidate in rcu-walk mode */ + if (nameidata_dentry_drop_rcu(nd, dentry)) + return ERR_PTR(-ECHILD); + if (!d_invalidate(dentry)) { + dput(dentry); + dentry = NULL; + } + return dentry; +} + +static inline int need_reval_dot(struct dentry *dentry) +{ + if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE))) + return 0; + + if (likely(!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT))) + return 0; + + return 1; +} + /* - * handle_reval_path - force revalidation of a dentry + * force_reval_path - force revalidation of a dentry * * In some situations the path walking code will trust dentries without * revalidating them. This causes problems for filesystems that depend on @@ -617,28 +639,27 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd) * invalidate the dentry. It's up to the caller to handle putting references * to the path if necessary. */ -static inline int handle_reval_path(struct nameidata *nd) +static int +force_reval_path(struct path *path, struct nameidata *nd) { - struct dentry *dentry = nd->path.dentry; int status; + struct dentry *dentry = path->dentry; - if (likely(!(nd->flags & LOOKUP_JUMPED))) - return 0; - - if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE))) - return 0; - - if (likely(!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT))) + /* + * only check on filesystems where it's possible for the dentry to + * become stale. + */ + if (!need_reval_dot(dentry)) return 0; - /* Note: we do not d_invalidate() */ status = d_revalidate(dentry, nd); if (status > 0) return 0; - if (!status) + if (!status) { + d_invalidate(dentry); status = -ESTALE; - + } return status; } @@ -707,7 +728,6 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l path_put(&nd->path); nd->path = nd->root; path_get(&nd->root); - nd->flags |= LOOKUP_JUMPED; } nd->inode = nd->path.dentry->d_inode; @@ -737,44 +757,20 @@ static inline void path_to_nameidata(const struct path *path, nd->path.dentry = path->dentry; } -static inline void put_link(struct nameidata *nd, struct path *link, void *cookie) -{ - struct inode *inode = link->dentry->d_inode; - if (!IS_ERR(cookie) && inode->i_op->put_link) - inode->i_op->put_link(link->dentry, nd, cookie); - path_put(link); -} - static __always_inline int -follow_link(struct path *link, struct nameidata *nd, void **p) +__do_follow_link(const struct path *link, struct nameidata *nd, void **p) { int error; struct dentry *dentry = link->dentry; BUG_ON(nd->flags & LOOKUP_RCU); - if (unlikely(current->total_link_count >= 40)) { - *p = ERR_PTR(-ELOOP); /* no ->put_link(), please */ - path_put_conditional(link, nd); - path_put(&nd->path); - return -ELOOP; - } - cond_resched(); - current->total_link_count++; - touch_atime(link->mnt, dentry); nd_set_link(nd, NULL); if (link->mnt == nd->path.mnt) mntget(link->mnt); - error = security_inode_follow_link(link->dentry, nd); - if (error) { - *p = ERR_PTR(error); /* no ->put_link(), please */ - path_put(&nd->path); - return error; - } - nd->last_type = LAST_BIND; *p = dentry->d_inode->i_op->follow_link(dentry, nd); error = PTR_ERR(*p); @@ -784,18 +780,56 @@ follow_link(struct path *link, struct nameidata *nd, void **p) if (s) error = __vfs_follow_link(nd, s); else if (nd->last_type == LAST_BIND) { - nd->flags |= LOOKUP_JUMPED; - nd->inode = nd->path.dentry->d_inode; - if (nd->inode->i_op->follow_link) { - /* stepped on a _really_ weird one */ + error = force_reval_path(&nd->path, nd); + if (error) path_put(&nd->path); - error = -ELOOP; - } } } return error; } +/* + * This limits recursive symlink follows to 8, while + * limiting consecutive symlinks to 40. + * + * Without that kind of total limit, nasty chains of consecutive + * symlinks can cause almost arbitrarily long lookups. + */ +static inline int do_follow_link(struct inode *inode, struct path *path, struct nameidata *nd) +{ + void *cookie; + int err = -ELOOP; + + /* We drop rcu-walk here */ + if (nameidata_dentry_drop_rcu_maybe(nd, path->dentry)) + return -ECHILD; + BUG_ON(inode != path->dentry->d_inode); + + if (current->link_count >= MAX_NESTED_LINKS) + goto loop; + if (current->total_link_count >= 40) + goto loop; + BUG_ON(nd->depth >= MAX_NESTED_LINKS); + cond_resched(); + err = security_inode_follow_link(path->dentry, nd); + if (err) + goto loop; + current->link_count++; + current->total_link_count++; + nd->depth++; + err = __do_follow_link(path, nd, &cookie); + if (!IS_ERR(cookie) && path->dentry->d_inode->i_op->put_link) + path->dentry->d_inode->i_op->put_link(path->dentry, nd, cookie); + path_put(path); + current->link_count--; + nd->depth--; + return err; +loop: + path_put_conditional(path, nd); + path_put(&nd->path); + return err; +} + static int follow_up_rcu(struct path *path) { struct vfsmount *parent; @@ -1034,7 +1068,7 @@ static int follow_dotdot_rcu(struct nameidata *nd) seq = read_seqcount_begin(&parent->d_seq); if (read_seqcount_retry(&old->d_seq, nd->seq)) - goto failed; + return -ECHILD; inode = parent->d_inode; nd->path.dentry = parent; nd->seq = seq; @@ -1047,15 +1081,8 @@ static int follow_dotdot_rcu(struct nameidata *nd) } __follow_mount_rcu(nd, &nd->path, &inode, true); nd->inode = inode; - return 0; -failed: - nd->flags &= ~LOOKUP_RCU; - if (!(nd->flags & LOOKUP_ROOT)) - nd->root.mnt = NULL; - rcu_read_unlock(); - br_read_unlock(vfsmount_lock); - return -ECHILD; + return 0; } /* @@ -1189,10 +1216,19 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, { struct vfsmount *mnt = nd->path.mnt; struct dentry *dentry, *parent = nd->path.dentry; - int need_reval = 1; - int status = 1; + struct inode *dir; int err; + /* + * See if the low-level filesystem might want + * to use its own hash.. + */ + if (unlikely(parent->d_flags & DCACHE_OP_HASH)) { + err = parent->d_op->d_hash(parent, nd->inode, name); + if (err < 0) + return err; + } + /* * Rename seqlock is not required here because in the off chance * of a false negative due to a concurrent rename, we're going to @@ -1200,74 +1236,48 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, */ if (nd->flags & LOOKUP_RCU) { unsigned seq; + *inode = nd->inode; dentry = __d_lookup_rcu(parent, name, &seq, inode); - if (!dentry) - goto unlazy; - + if (!dentry) { + if (nameidata_drop_rcu(nd)) + return -ECHILD; + goto need_lookup; + } /* Memory barrier in read_seqcount_begin of child is enough */ if (__read_seqcount_retry(&parent->d_seq, nd->seq)) return -ECHILD; - nd->seq = seq; + nd->seq = seq; if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) { - status = d_revalidate(dentry, nd); - if (unlikely(status <= 0)) { - if (status != -ECHILD) - need_reval = 0; - goto unlazy; - } + dentry = do_revalidate_rcu(dentry, nd); + if (!dentry) + goto need_lookup; + if (IS_ERR(dentry)) + goto fail; + if (!(nd->flags & LOOKUP_RCU)) + goto done; } path->mnt = mnt; path->dentry = dentry; if (likely(__follow_mount_rcu(nd, path, inode, false))) return 0; -unlazy: - if (dentry) { - if (nameidata_dentry_drop_rcu(nd, dentry)) - return -ECHILD; - } else { - if (nameidata_drop_rcu(nd)) - return -ECHILD; - } - } else { - dentry = __d_lookup(parent, name); - } - -retry: - if (unlikely(!dentry)) { - struct inode *dir = parent->d_inode; - BUG_ON(nd->inode != dir); - - mutex_lock(&dir->i_mutex); - dentry = d_lookup(parent, name); - if (likely(!dentry)) { - dentry = d_alloc_and_lookup(parent, name, nd); - if (IS_ERR(dentry)) { - mutex_unlock(&dir->i_mutex); - return PTR_ERR(dentry); - } - /* known good */ - need_reval = 0; - status = 1; - } - mutex_unlock(&dir->i_mutex); + if (nameidata_drop_rcu(nd)) + return -ECHILD; + /* fallthru */ } - if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE) && need_reval) - status = d_revalidate(dentry, nd); - if (unlikely(status <= 0)) { - if (status < 0) { - dput(dentry); - return status; - } - if (!d_invalidate(dentry)) { - dput(dentry); - dentry = NULL; - need_reval = 1; - goto retry; - } + dentry = __d_lookup(parent, name); + if (!dentry) + goto need_lookup; +found: + if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) { + dentry = do_revalidate(dentry, nd); + if (!dentry) + goto need_lookup; + if (IS_ERR(dentry)) + goto fail; } - +done: path->mnt = mnt; path->dentry = dentry; err = follow_managed(path, nd->flags); @@ -1277,113 +1287,39 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, } *inode = path->dentry->d_inode; return 0; -} - -static inline int may_lookup(struct nameidata *nd) -{ - if (nd->flags & LOOKUP_RCU) { - int err = exec_permission(nd->inode, IPERM_FLAG_RCU); - if (err != -ECHILD) - return err; - if (nameidata_drop_rcu(nd)) - return -ECHILD; - } - return exec_permission(nd->inode, 0); -} - -static inline int handle_dots(struct nameidata *nd, int type) -{ - if (type == LAST_DOTDOT) { - if (nd->flags & LOOKUP_RCU) { - if (follow_dotdot_rcu(nd)) - return -ECHILD; - } else - follow_dotdot(nd); - } - return 0; -} -static void terminate_walk(struct nameidata *nd) -{ - if (!(nd->flags & LOOKUP_RCU)) { - path_put(&nd->path); - } else { - nd->flags &= ~LOOKUP_RCU; - if (!(nd->flags & LOOKUP_ROOT)) - nd->root.mnt = NULL; - rcu_read_unlock(); - br_read_unlock(vfsmount_lock); - } -} +need_lookup: + dir = parent->d_inode; + BUG_ON(nd->inode != dir); -static inline int walk_component(struct nameidata *nd, struct path *path, - struct qstr *name, int type, int follow) -{ - struct inode *inode; - int err; + mutex_lock(&dir->i_mutex); /* - * "." and ".." are special - ".." especially so because it has - * to be able to know about the current root directory and - * parent relationships. + * First re-do the cached lookup just in case it was created + * while we waited for the directory semaphore, or the first + * lookup failed due to an unrelated rename. + * + * This could use version numbering or similar to avoid unnecessary + * cache lookups, but then we'd have to do the first lookup in the + * non-racy way. However in the common case here, everything should + * be hot in cache, so would it be a big win? */ - if (unlikely(type != LAST_NORM)) - return handle_dots(nd, type); - err = do_lookup(nd, name, path, &inode); - if (unlikely(err)) { - terminate_walk(nd); - return err; - } - if (!inode) { - path_to_nameidata(path, nd); - terminate_walk(nd); - return -ENOENT; - } - if (unlikely(inode->i_op->follow_link) && follow) { - if (nameidata_dentry_drop_rcu_maybe(nd, path->dentry)) - return -ECHILD; - BUG_ON(inode != path->dentry->d_inode); - return 1; - } - path_to_nameidata(path, nd); - nd->inode = inode; - return 0; -} - -/* - * This limits recursive symlink follows to 8, while - * limiting consecutive symlinks to 40. - * - * Without that kind of total limit, nasty chains of consecutive - * symlinks can cause almost arbitrarily long lookups. - */ -static inline int nested_symlink(struct path *path, struct nameidata *nd) -{ - int res; - - BUG_ON(nd->depth >= MAX_NESTED_LINKS); - if (unlikely(current->link_count >= MAX_NESTED_LINKS)) { - path_put_conditional(path, nd); - path_put(&nd->path); - return -ELOOP; + dentry = d_lookup(parent, name); + if (likely(!dentry)) { + dentry = d_alloc_and_lookup(parent, name, nd); + mutex_unlock(&dir->i_mutex); + if (IS_ERR(dentry)) + goto fail; + goto done; } + /* + * Uhhuh! Nasty case: the cache was re-populated while + * we waited on the semaphore. Need to revalidate. + */ + mutex_unlock(&dir->i_mutex); + goto found; - nd->depth++; - current->link_count++; - - do { - struct path link = *path; - void *cookie; - - res = follow_link(&link, nd, &cookie); - if (!res) - res = walk_component(nd, path, &nd->last, - nd->last_type, LOOKUP_FOLLOW); - put_link(nd, &link, cookie); - } while (res > 0); - - current->link_count--; - nd->depth--; - return res; +fail: + return PTR_ERR(dentry); } /* @@ -1403,18 +1339,30 @@ static int link_path_walk(const char *name, struct nameidata *nd) while (*name=='/') name++; if (!*name) - return 0; + goto return_reval; + + if (nd->depth) + lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); /* At this point we know we have a real path component. */ for(;;) { + struct inode *inode; unsigned long hash; struct qstr this; unsigned int c; - int type; nd->flags |= LOOKUP_CONTINUE; - - err = may_lookup(nd); + if (nd->flags & LOOKUP_RCU) { + err = exec_permission(nd->inode, IPERM_FLAG_RCU); + if (err == -ECHILD) { + if (nameidata_drop_rcu(nd)) + return -ECHILD; + goto exec_again; + } + } else { +exec_again: + err = exec_permission(nd->inode, 0); + } if (err) break; @@ -1430,43 +1378,52 @@ static int link_path_walk(const char *name, struct nameidata *nd) this.len = name - (const char *) this.name; this.hash = end_name_hash(hash); - type = LAST_NORM; - if (this.name[0] == '.') switch (this.len) { - case 2: - if (this.name[1] == '.') { - type = LAST_DOTDOT; - nd->flags |= LOOKUP_JUMPED; - } - break; - case 1: - type = LAST_DOT; - } - if (likely(type == LAST_NORM)) { - struct dentry *parent = nd->path.dentry; - nd->flags &= ~LOOKUP_JUMPED; - if (unlikely(parent->d_flags & DCACHE_OP_HASH)) { - err = parent->d_op->d_hash(parent, nd->inode, - &this); - if (err < 0) - break; - } - } - /* remove trailing slashes? */ if (!c) goto last_component; while (*++name == '/'); if (!*name) - goto last_component; + goto last_with_slashes; - err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW); - if (err < 0) - return err; + /* + * "." and ".." are special - ".." especially so because it has + * to be able to know about the current root directory and + * parent relationships. + */ + if (this.name[0] == '.') switch (this.len) { + default: + break; + case 2: + if (this.name[1] != '.') + break; + if (nd->flags & LOOKUP_RCU) { + if (follow_dotdot_rcu(nd)) + return -ECHILD; + } else + follow_dotdot(nd); + /* fallthrough */ + case 1: + continue; + } + /* This does the actual lookups.. */ + err = do_lookup(nd, &this, &next, &inode); + if (err) + break; + err = -ENOENT; + if (!inode) + goto out_dput; - if (err) { - err = nested_symlink(&next, nd); + if (inode->i_op->follow_link) { + err = do_follow_link(inode, &next, nd); if (err) - return err; + goto return_err; + nd->inode = nd->path.dentry->d_inode; + err = -ENOENT; + if (!nd->inode) + break; + } else { + path_to_nameidata(&next, nd); + nd->inode = inode; } err = -ENOTDIR; if (!nd->inode->i_op->lookup) @@ -1474,109 +1431,209 @@ static int link_path_walk(const char *name, struct nameidata *nd) continue; /* here ends the main loop */ +last_with_slashes: + lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; last_component: /* Clear LOOKUP_CONTINUE iff it was previously unset */ nd->flags &= lookup_flags | ~LOOKUP_CONTINUE; - nd->last = this; - nd->last_type = type; - return 0; - } - terminate_walk(nd); - return err; -} - -static int path_init(int dfd, const char *name, unsigned int flags, - struct nameidata *nd, struct file **fp) -{ - int retval = 0; - int fput_needed; - struct file *file; - - nd->last_type = LAST_ROOT; /* if there are only slashes... */ - nd->flags = flags | LOOKUP_JUMPED; - nd->depth = 0; - if (flags & LOOKUP_ROOT) { - struct inode *inode = nd->root.dentry->d_inode; - if (*name) { - if (!inode->i_op->lookup) - return -ENOTDIR; - retval = inode_permission(inode, MAY_EXEC); - if (retval) - return retval; + if (lookup_flags & LOOKUP_PARENT) + goto lookup_parent; + if (this.name[0] == '.') switch (this.len) { + default: + break; + case 2: + if (this.name[1] != '.') + break; + if (nd->flags & LOOKUP_RCU) { + if (follow_dotdot_rcu(nd)) + return -ECHILD; + } else + follow_dotdot(nd); + /* fallthrough */ + case 1: + goto return_reval; } - nd->path = nd->root; - nd->inode = inode; - if (flags & LOOKUP_RCU) { - br_read_lock(vfsmount_lock); - rcu_read_lock(); - nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); + err = do_lookup(nd, &this, &next, &inode); + if (err) + break; + if (inode && unlikely(inode->i_op->follow_link) && + (lookup_flags & LOOKUP_FOLLOW)) { + err = do_follow_link(inode, &next, nd); + if (err) + goto return_err; + nd->inode = nd->path.dentry->d_inode; } else { - path_get(&nd->path); + path_to_nameidata(&next, nd); + nd->inode = inode; + } + err = -ENOENT; + if (!nd->inode) + break; + if (lookup_flags & LOOKUP_DIRECTORY) { + err = -ENOTDIR; + if (!nd->inode->i_op->lookup) + break; } + goto return_base; +lookup_parent: + nd->last = this; + nd->last_type = LAST_NORM; + if (this.name[0] != '.') + goto return_base; + if (this.len == 1) + nd->last_type = LAST_DOT; + else if (this.len == 2 && this.name[1] == '.') + nd->last_type = LAST_DOTDOT; + else + goto return_base; +return_reval: + /* + * We bypassed the ordinary revalidation routines. + * We may need to check the cached dentry for staleness. + */ + if (need_reval_dot(nd->path.dentry)) { + if (nameidata_drop_rcu_last_maybe(nd)) + return -ECHILD; + /* Note: we do not d_invalidate() */ + err = d_revalidate(nd->path.dentry, nd); + if (!err) + err = -ESTALE; + if (err < 0) + break; + return 0; + } +return_base: + if (nameidata_drop_rcu_last_maybe(nd)) + return -ECHILD; return 0; +out_dput: + if (!(nd->flags & LOOKUP_RCU)) + path_put_conditional(&next, nd); + break; } + if (!(nd->flags & LOOKUP_RCU)) + path_put(&nd->path); +return_err: + return err; +} + +static inline int path_walk_rcu(const char *name, struct nameidata *nd) +{ + current->total_link_count = 0; + + return link_path_walk(name, nd); +} + +static inline int path_walk_simple(const char *name, struct nameidata *nd) +{ + current->total_link_count = 0; + + return link_path_walk(name, nd); +} + +static int path_walk(const char *name, struct nameidata *nd) +{ + struct path save = nd->path; + int result; + + current->total_link_count = 0; + + /* make sure the stuff we saved doesn't go away */ + path_get(&save); + + result = link_path_walk(name, nd); + if (result == -ESTALE) { + /* nd->path had been dropped */ + current->total_link_count = 0; + nd->path = save; + path_get(&nd->path); + nd->flags |= LOOKUP_REVAL; + result = link_path_walk(name, nd); + } + + path_put(&save); + + return result; +} + +static void path_finish_rcu(struct nameidata *nd) +{ + if (nd->flags & LOOKUP_RCU) { + /* RCU dangling. Cancel it. */ + nd->flags &= ~LOOKUP_RCU; + nd->root.mnt = NULL; + rcu_read_unlock(); + br_read_unlock(vfsmount_lock); + } + if (nd->file) + fput(nd->file); +} + +static int path_init_rcu(int dfd, const char *name, unsigned int flags, struct nameidata *nd) +{ + int retval = 0; + int fput_needed; + struct file *file; + nd->last_type = LAST_ROOT; /* if there are only slashes... */ + nd->flags = flags | LOOKUP_RCU; + nd->depth = 0; nd->root.mnt = NULL; + nd->file = NULL; if (*name=='/') { - if (flags & LOOKUP_RCU) { - br_read_lock(vfsmount_lock); - rcu_read_lock(); - set_root_rcu(nd); - } else { - set_root(nd); - path_get(&nd->root); - } - nd->path = nd->root; + struct fs_struct *fs = current->fs; + unsigned seq; + + br_read_lock(vfsmount_lock); + rcu_read_lock(); + + do { + seq = read_seqcount_begin(&fs->seq); + nd->root = fs->root; + nd->path = nd->root; + nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); + } while (read_seqcount_retry(&fs->seq, seq)); + } else if (dfd == AT_FDCWD) { - if (flags & LOOKUP_RCU) { - struct fs_struct *fs = current->fs; - unsigned seq; + struct fs_struct *fs = current->fs; + unsigned seq; - br_read_lock(vfsmount_lock); - rcu_read_lock(); + br_read_lock(vfsmount_lock); + rcu_read_lock(); + + do { + seq = read_seqcount_begin(&fs->seq); + nd->path = fs->pwd; + nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); + } while (read_seqcount_retry(&fs->seq, seq)); - do { - seq = read_seqcount_begin(&fs->seq); - nd->path = fs->pwd; - nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); - } while (read_seqcount_retry(&fs->seq, seq)); - } else { - get_fs_pwd(current->fs, &nd->path); - } } else { struct dentry *dentry; - file = fget_raw_light(dfd, &fput_needed); + file = fget_light(dfd, &fput_needed); retval = -EBADF; if (!file) goto out_fail; dentry = file->f_path.dentry; - if (*name) { - retval = -ENOTDIR; - if (!S_ISDIR(dentry->d_inode->i_mode)) - goto fput_fail; + retval = -ENOTDIR; + if (!S_ISDIR(dentry->d_inode->i_mode)) + goto fput_fail; - retval = file_permission(file, MAY_EXEC); - if (retval) - goto fput_fail; - } + retval = file_permission(file, MAY_EXEC); + if (retval) + goto fput_fail; nd->path = file->f_path; - if (flags & LOOKUP_RCU) { - if (fput_needed) - *fp = file; - nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); - br_read_lock(vfsmount_lock); - rcu_read_lock(); - } else { - path_get(&file->f_path); - fput_light(file, fput_needed); - } - } + if (fput_needed) + nd->file = file; + nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); + br_read_lock(vfsmount_lock); + rcu_read_lock(); + } nd->inode = nd->path.dentry->d_inode; return 0; @@ -1586,23 +1643,60 @@ static int path_init(int dfd, const char *name, unsigned int flags, return retval; } -static inline int lookup_last(struct nameidata *nd, struct path *path) +static int path_init(int dfd, const char *name, unsigned int flags, struct nameidata *nd) { - if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len]) - nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; + int retval = 0; + int fput_needed; + struct file *file; - nd->flags &= ~LOOKUP_PARENT; - return walk_component(nd, path, &nd->last, nd->last_type, - nd->flags & LOOKUP_FOLLOW); + nd->last_type = LAST_ROOT; /* if there are only slashes... */ + nd->flags = flags; + nd->depth = 0; + nd->root.mnt = NULL; + + if (*name=='/') { + set_root(nd); + nd->path = nd->root; + path_get(&nd->root); + } else if (dfd == AT_FDCWD) { + get_fs_pwd(current->fs, &nd->path); + } else { + struct dentry *dentry; + + file = fget_light(dfd, &fput_needed); + retval = -EBADF; + if (!file) + goto out_fail; + + dentry = file->f_path.dentry; + + retval = -ENOTDIR; + if (!S_ISDIR(dentry->d_inode->i_mode)) + goto fput_fail; + + retval = file_permission(file, MAY_EXEC); + if (retval) + goto fput_fail; + + nd->path = file->f_path; + path_get(&file->f_path); + + fput_light(file, fput_needed); + } + nd->inode = nd->path.dentry->d_inode; + return 0; + +fput_fail: + fput_light(file, fput_needed); +out_fail: + return retval; } /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ -static int path_lookupat(int dfd, const char *name, +static int do_path_lookup(int dfd, const char *name, unsigned int flags, struct nameidata *nd) { - struct file *base = NULL; - struct path path; - int err; + int retval; /* * Path walking is largely split up into 2 different synchronisation @@ -1618,62 +1712,29 @@ static int path_lookupat(int dfd, const char *name, * be handled by restarting a traditional ref-walk (which will always * be able to complete). */ - err = path_init(dfd, name, flags | LOOKUP_PARENT, nd, &base); - - if (unlikely(err)) - return err; - - current->total_link_count = 0; - err = link_path_walk(name, nd); - - if (!err && !(flags & LOOKUP_PARENT)) { - err = lookup_last(nd, &path); - while (err > 0) { - void *cookie; - struct path link = path; - nd->flags |= LOOKUP_PARENT; - err = follow_link(&link, nd, &cookie); - if (!err) - err = lookup_last(nd, &path); - put_link(nd, &link, cookie); - } - } - - if (nd->flags & LOOKUP_RCU) { - /* went all way through without dropping RCU */ - BUG_ON(err); - if (nameidata_drop_rcu_last(nd)) - err = -ECHILD; - } - - if (!err) - err = handle_reval_path(nd); - - if (!err && nd->flags & LOOKUP_DIRECTORY) { - if (!nd->inode->i_op->lookup) { - path_put(&nd->path); - return -ENOTDIR; - } - } - - if (base) - fput(base); - - if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) { + retval = path_init_rcu(dfd, name, flags, nd); + if (unlikely(retval)) + return retval; + retval = path_walk_rcu(name, nd); + path_finish_rcu(nd); + if (nd->root.mnt) { path_put(&nd->root); nd->root.mnt = NULL; } - return err; -} -static int do_path_lookup(int dfd, const char *name, - unsigned int flags, struct nameidata *nd) -{ - int retval = path_lookupat(dfd, name, flags | LOOKUP_RCU, nd); - if (unlikely(retval == -ECHILD)) - retval = path_lookupat(dfd, name, flags, nd); - if (unlikely(retval == -ESTALE)) - retval = path_lookupat(dfd, name, flags | LOOKUP_REVAL, nd); + if (unlikely(retval == -ECHILD || retval == -ESTALE)) { + /* slower, locked walk */ + if (retval == -ESTALE) + flags |= LOOKUP_REVAL; + retval = path_init(dfd, name, flags, nd); + if (unlikely(retval)) + return retval; + retval = path_walk(name, nd); + if (nd->root.mnt) { + path_put(&nd->root); + nd->root.mnt = NULL; + } + } if (likely(!retval)) { if (unlikely(!audit_dummy_context())) { @@ -1681,12 +1742,14 @@ static int do_path_lookup(int dfd, const char *name, audit_inode(name, nd->path.dentry); } } + return retval; } -int kern_path_parent(const char *name, struct nameidata *nd) +int path_lookup(const char *name, unsigned int flags, + struct nameidata *nd) { - return do_path_lookup(AT_FDCWD, name, LOOKUP_PARENT, nd); + return do_path_lookup(AT_FDCWD, name, flags, nd); } int kern_path(const char *name, unsigned int flags, struct path *path) @@ -1710,10 +1773,29 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, const char *name, unsigned int flags, struct nameidata *nd) { - nd->root.dentry = dentry; - nd->root.mnt = mnt; - /* the first argument of do_path_lookup() is ignored with LOOKUP_ROOT */ - return do_path_lookup(AT_FDCWD, name, flags | LOOKUP_ROOT, nd); + int retval; + + /* same as do_path_lookup */ + nd->last_type = LAST_ROOT; + nd->flags = flags; + nd->depth = 0; + + nd->path.dentry = dentry; + nd->path.mnt = mnt; + path_get(&nd->path); + nd->root = nd->path; + path_get(&nd->root); + nd->inode = nd->path.dentry->d_inode; + + retval = path_walk(name, nd); + if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry && + nd->inode)) + audit_inode(name, nd->path.dentry); + + path_put(&nd->root); + nd->root.mnt = NULL; + + return retval; } static struct dentry *__lookup_hash(struct qstr *name, @@ -1727,6 +1809,17 @@ static struct dentry *__lookup_hash(struct qstr *name, if (err) return ERR_PTR(err); + /* + * See if the low-level filesystem might want + * to use its own hash.. + */ + if (base->d_flags & DCACHE_OP_HASH) { + err = base->d_op->d_hash(base, inode, name); + dentry = ERR_PTR(err); + if (err < 0) + goto out; + } + /* * Don't bother with __d_lookup: callers are for creat as * well as unlink, so a lot of the time it would cost @@ -1739,7 +1832,7 @@ static struct dentry *__lookup_hash(struct qstr *name, if (!dentry) dentry = d_alloc_and_lookup(base, name, nd); - +out: return dentry; } @@ -1753,6 +1846,28 @@ static struct dentry *lookup_hash(struct nameidata *nd) return __lookup_hash(&nd->last, nd->path.dentry, nd); } +static int __lookup_one_len(const char *name, struct qstr *this, + struct dentry *base, int len) +{ + unsigned long hash; + unsigned int c; + + this->name = name; + this->len = len; + if (!len) + return -EACCES; + + hash = init_name_hash(); + while (len--) { + c = *(const unsigned char *)name++; + if (c == '/' || c == '\0') + return -EACCES; + hash = partial_name_hash(c, hash); + } + this->hash = end_name_hash(hash); + return 0; +} + /** * lookup_one_len - filesystem helper to lookup single pathname component * @name: pathname component to lookup @@ -1766,34 +1881,14 @@ static struct dentry *lookup_hash(struct nameidata *nd) */ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) { + int err; struct qstr this; - unsigned long hash; - unsigned int c; WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex)); - this.name = name; - this.len = len; - if (!len) - return ERR_PTR(-EACCES); - - hash = init_name_hash(); - while (len--) { - c = *(const unsigned char *)name++; - if (c == '/' || c == '\0') - return ERR_PTR(-EACCES); - hash = partial_name_hash(c, hash); - } - this.hash = end_name_hash(hash); - /* - * See if the low-level filesystem might want - * to use its own hash.. - */ - if (base->d_flags & DCACHE_OP_HASH) { - int err = base->d_op->d_hash(base, base->d_inode, &this); - if (err < 0) - return ERR_PTR(err); - } + err = __lookup_one_len(name, &this, base, len); + if (err) + return ERR_PTR(err); return __lookup_hash(&this, base, NULL); } @@ -1802,7 +1897,7 @@ int user_path_at(int dfd, const char __user *name, unsigned flags, struct path *path) { struct nameidata nd; - char *tmp = getname_flags(name, flags); + char *tmp = getname(name); int err = PTR_ERR(tmp); if (!IS_ERR(tmp)) { @@ -1982,16 +2077,12 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, return error; } -static int may_open(struct path *path, int acc_mode, int flag) +int may_open(struct path *path, int acc_mode, int flag) { struct dentry *dentry = path->dentry; struct inode *inode = dentry->d_inode; int error; - /* O_PATH? */ - if (!acc_mode) - return 0; - if (!inode) return -ENOENT; @@ -2059,6 +2150,34 @@ static int handle_truncate(struct file *filp) return error; } +/* + * Be careful about ever adding any more callers of this + * function. Its flags must be in the namei format, not + * what get passed to sys_open(). + */ +static int __open_namei_create(struct nameidata *nd, struct path *path, + int open_flag, int mode) +{ + int error; + struct dentry *dir = nd->path.dentry; + + if (!IS_POSIXACL(dir->d_inode)) + mode &= ~current_umask(); + error = security_path_mknod(&nd->path, path->dentry, mode, 0); + if (error) + goto out_unlock; + error = vfs_create(dir->d_inode, path->dentry, mode, nd); +out_unlock: + mutex_unlock(&dir->d_inode->i_mutex); + dput(nd->path.dentry); + nd->path.dentry = path->dentry; + + if (error) + return error; + /* Don't check for write permission, don't truncate */ + return may_open(&nd->path, 0, open_flag & ~O_TRUNC); +} + /* * Note that while the flag value (low two bits) for sys_open means: * 00 - read-only @@ -2083,115 +2202,126 @@ static inline int open_to_namei_flags(int flag) return flag; } +static int open_will_truncate(int flag, struct inode *inode) +{ + /* + * We'll never write to the fs underlying + * a device file. + */ + if (special_file(inode->i_mode)) + return 0; + return (flag & O_TRUNC); +} + +static struct file *finish_open(struct nameidata *nd, + int open_flag, int acc_mode) +{ + struct file *filp; + int will_truncate; + int error; + + will_truncate = open_will_truncate(open_flag, nd->path.dentry->d_inode); + if (will_truncate) { + error = mnt_want_write(nd->path.mnt); + if (error) + goto exit; + } + error = may_open(&nd->path, acc_mode, open_flag); + if (error) { + if (will_truncate) + mnt_drop_write(nd->path.mnt); + goto exit; + } + filp = nameidata_to_filp(nd); + if (!IS_ERR(filp)) { + error = ima_file_check(filp, acc_mode); + if (error) { + fput(filp); + filp = ERR_PTR(error); + } + } + if (!IS_ERR(filp)) { + if (will_truncate) { + error = handle_truncate(filp); + if (error) { + fput(filp); + filp = ERR_PTR(error); + } + } + } + /* + * It is now safe to drop the mnt write + * because the filp has had a write taken + * on its behalf. + */ + if (will_truncate) + mnt_drop_write(nd->path.mnt); + path_put(&nd->path); + return filp; + +exit: + path_put(&nd->path); + return ERR_PTR(error); +} + /* - * Handle the last step of open() + * Handle O_CREAT case for do_filp_open */ static struct file *do_last(struct nameidata *nd, struct path *path, - const struct open_flags *op, const char *pathname) + int open_flag, int acc_mode, + int mode, const char *pathname) { struct dentry *dir = nd->path.dentry; - struct dentry *dentry; - int open_flag = op->open_flag; - int will_truncate = open_flag & O_TRUNC; - int want_write = 0; - int acc_mode = op->acc_mode; struct file *filp; - int error; - - nd->flags &= ~LOOKUP_PARENT; - nd->flags |= op->intent; + int error = -EISDIR; switch (nd->last_type) { case LAST_DOTDOT: + follow_dotdot(nd); + dir = nd->path.dentry; case LAST_DOT: - error = handle_dots(nd, nd->last_type); - if (error) - return ERR_PTR(error); + if (need_reval_dot(dir)) { + int status = d_revalidate(nd->path.dentry, nd); + if (!status) + status = -ESTALE; + if (status < 0) { + error = status; + goto exit; + } + } /* fallthrough */ case LAST_ROOT: - if (nd->flags & LOOKUP_RCU) { - if (nameidata_drop_rcu_last(nd)) - return ERR_PTR(-ECHILD); - } - error = handle_reval_path(nd); - if (error) - goto exit; - audit_inode(pathname, nd->path.dentry); - if (open_flag & O_CREAT) { - error = -EISDIR; - goto exit; - } - goto ok; + goto exit; case LAST_BIND: - /* can't be RCU mode here */ - error = handle_reval_path(nd); - if (error) - goto exit; audit_inode(pathname, dir); goto ok; } - if (!(open_flag & O_CREAT)) { - int symlink_ok = 0; - if (nd->last.name[nd->last.len]) - nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; - if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW)) - symlink_ok = 1; - /* we _can_ be in RCU mode here */ - error = walk_component(nd, path, &nd->last, LAST_NORM, - !symlink_ok); - if (error < 0) - return ERR_PTR(error); - if (error) /* symlink */ - return NULL; - /* sayonara */ - if (nd->flags & LOOKUP_RCU) { - if (nameidata_drop_rcu_last(nd)) - return ERR_PTR(-ECHILD); - } - - error = -ENOTDIR; - if (nd->flags & LOOKUP_DIRECTORY) { - if (!nd->inode->i_op->lookup) - goto exit; - } - audit_inode(pathname, nd->path.dentry); - goto ok; - } - - /* create side of things */ - - if (nd->flags & LOOKUP_RCU) { - if (nameidata_drop_rcu_last(nd)) - return ERR_PTR(-ECHILD); - } - - audit_inode(pathname, dir); - error = -EISDIR; /* trailing slashes? */ if (nd->last.name[nd->last.len]) goto exit; mutex_lock(&dir->d_inode->i_mutex); - dentry = lookup_hash(nd); - error = PTR_ERR(dentry); - if (IS_ERR(dentry)) { + path->dentry = lookup_hash(nd); + path->mnt = nd->path.mnt; + + error = PTR_ERR(path->dentry); + if (IS_ERR(path->dentry)) { mutex_unlock(&dir->d_inode->i_mutex); goto exit; } - path->dentry = dentry; - path->mnt = nd->path.mnt; + if (IS_ERR(nd->intent.open.file)) { + error = PTR_ERR(nd->intent.open.file); + goto exit_mutex_unlock; + } /* Negative dentry, just create the file */ - if (!dentry->d_inode) { - int mode = op->mode; - if (!IS_POSIXACL(dir->d_inode)) - mode &= ~current_umask(); + if (!path->dentry->d_inode) { /* * This write is needed to ensure that a - * rw->ro transition does not occur between + * ro->rw transition does not occur between * the time when the file is created and when * a permanent write count is taken through * the 'struct file' in nameidata_to_filp(). @@ -2199,21 +2329,22 @@ static struct file *do_last(struct nameidata *nd, struct path *path, error = mnt_want_write(nd->path.mnt); if (error) goto exit_mutex_unlock; - want_write = 1; - /* Don't check for write permission, don't truncate */ - open_flag &= ~O_TRUNC; - will_truncate = 0; - acc_mode = MAY_OPEN; - error = security_path_mknod(&nd->path, dentry, mode, 0); - if (error) - goto exit_mutex_unlock; - error = vfs_create(dir->d_inode, dentry, mode, nd); - if (error) - goto exit_mutex_unlock; - mutex_unlock(&dir->d_inode->i_mutex); - dput(nd->path.dentry); - nd->path.dentry = dentry; - goto common; + error = __open_namei_create(nd, path, open_flag, mode); + if (error) { + mnt_drop_write(nd->path.mnt); + goto exit; + } + filp = nameidata_to_filp(nd); + mnt_drop_write(nd->path.mnt); + path_put(&nd->path); + if (!IS_ERR(filp)) { + error = ima_file_check(filp, acc_mode); + if (error) { + fput(filp); + filp = ERR_PTR(error); + } + } + return filp; } /* @@ -2243,40 +2374,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, if (S_ISDIR(nd->inode->i_mode)) goto exit; ok: - if (!S_ISREG(nd->inode->i_mode)) - will_truncate = 0; - - if (will_truncate) { - error = mnt_want_write(nd->path.mnt); - if (error) - goto exit; - want_write = 1; - } -common: - error = may_open(&nd->path, acc_mode, open_flag); - if (error) - goto exit; - filp = nameidata_to_filp(nd); - if (!IS_ERR(filp)) { - error = ima_file_check(filp, op->acc_mode); - if (error) { - fput(filp); - filp = ERR_PTR(error); - } - } - if (!IS_ERR(filp)) { - if (will_truncate) { - error = handle_truncate(filp); - if (error) { - fput(filp); - filp = ERR_PTR(error); - } - } - } -out: - if (want_write) - mnt_drop_write(nd->path.mnt); - path_put(&nd->path); + filp = finish_open(nd, open_flag, acc_mode); return filp; exit_mutex_unlock: @@ -2284,103 +2382,197 @@ static struct file *do_last(struct nameidata *nd, struct path *path, exit_dput: path_put_conditional(path, nd); exit: - filp = ERR_PTR(error); - goto out; + path_put(&nd->path); + return ERR_PTR(error); } -static struct file *path_openat(int dfd, const char *pathname, - struct nameidata *nd, const struct open_flags *op, int flags) +/* + * Note that the low bits of the passed in "open_flag" + * are not the same as in the local variable "flag". See + * open_to_namei_flags() for more details. + */ +struct file *do_filp_open(int dfd, const char *pathname, + int open_flag, int mode, int acc_mode) { - struct file *base = NULL; struct file *filp; - struct path path; + struct nameidata nd; int error; + struct path path; + int count = 0; + int flag = open_to_namei_flags(open_flag); + int flags; + + if (!(open_flag & O_CREAT)) + mode = 0; + + /* Must never be set by userspace */ + open_flag &= ~FMODE_NONOTIFY; + + /* + * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only + * check for O_DSYNC if the need any syncing at all we enforce it's + * always set instead of having to deal with possibly weird behaviour + * for malicious applications setting only __O_SYNC. + */ + if (open_flag & __O_SYNC) + open_flag |= O_DSYNC; + + if (!acc_mode) + acc_mode = MAY_OPEN | ACC_MODE(open_flag); + + /* O_TRUNC implies we need access checks for write permissions */ + if (open_flag & O_TRUNC) + acc_mode |= MAY_WRITE; + + /* Allow the LSM permission hook to distinguish append + access from general write access. */ + if (open_flag & O_APPEND) + acc_mode |= MAY_APPEND; + + flags = LOOKUP_OPEN; + if (open_flag & O_CREAT) { + flags |= LOOKUP_CREATE; + if (open_flag & O_EXCL) + flags |= LOOKUP_EXCL; + } + if (open_flag & O_DIRECTORY) + flags |= LOOKUP_DIRECTORY; + if (!(open_flag & O_NOFOLLOW)) + flags |= LOOKUP_FOLLOW; filp = get_empty_filp(); if (!filp) return ERR_PTR(-ENFILE); - filp->f_flags = op->open_flag; - nd->intent.open.file = filp; - nd->intent.open.flags = open_to_namei_flags(op->open_flag); - nd->intent.open.create_mode = op->mode; + filp->f_flags = open_flag; + nd.intent.open.file = filp; + nd.intent.open.flags = flag; + nd.intent.open.create_mode = mode; - error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base); + if (open_flag & O_CREAT) + goto creat; + + /* !O_CREAT, simple open */ + error = do_path_lookup(dfd, pathname, flags, &nd); if (unlikely(error)) goto out_filp; + error = -ELOOP; + if (!(nd.flags & LOOKUP_FOLLOW)) { + if (nd.inode->i_op->follow_link) + goto out_path; + } + error = -ENOTDIR; + if (nd.flags & LOOKUP_DIRECTORY) { + if (!nd.inode->i_op->lookup) + goto out_path; + } + audit_inode(pathname, nd.path.dentry); + filp = finish_open(&nd, open_flag, acc_mode); + release_open_intent(&nd); + return filp; - current->total_link_count = 0; - error = link_path_walk(pathname, nd); +creat: + /* OK, have to create the file. Find the parent. */ + error = path_init_rcu(dfd, pathname, + LOOKUP_PARENT | (flags & LOOKUP_REVAL), &nd); + if (error) + goto out_filp; + error = path_walk_rcu(pathname, &nd); + path_finish_rcu(&nd); + if (unlikely(error == -ECHILD || error == -ESTALE)) { + /* slower, locked walk */ + if (error == -ESTALE) { +reval: + flags |= LOOKUP_REVAL; + } + error = path_init(dfd, pathname, + LOOKUP_PARENT | (flags & LOOKUP_REVAL), &nd); + if (error) + goto out_filp; + + error = path_walk_simple(pathname, &nd); + } if (unlikely(error)) goto out_filp; + if (unlikely(!audit_dummy_context())) + audit_inode(pathname, nd.path.dentry); - filp = do_last(nd, &path, op, pathname); + /* + * We have the parent and last component. + */ + nd.flags = flags; + filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); while (unlikely(!filp)) { /* trailing symlink */ struct path link = path; + struct inode *linki = link.dentry->d_inode; void *cookie; - if (!(nd->flags & LOOKUP_FOLLOW)) { - path_put_conditional(&path, nd); - path_put(&nd->path); - filp = ERR_PTR(-ELOOP); - break; + error = -ELOOP; + if (!(nd.flags & LOOKUP_FOLLOW)) + goto exit_dput; + if (count++ == 32) + goto exit_dput; + /* + * This is subtle. Instead of calling do_follow_link() we do + * the thing by hands. The reason is that this way we have zero + * link_count and path_walk() (called from ->follow_link) + * honoring LOOKUP_PARENT. After that we have the parent and + * last component, i.e. we are in the same situation as after + * the first path_walk(). Well, almost - if the last component + * is normal we get its copy stored in nd->last.name and we will + * have to putname() it when we are done. Procfs-like symlinks + * just set LAST_BIND. + */ + nd.flags |= LOOKUP_PARENT; + error = security_inode_follow_link(link.dentry, &nd); + if (error) + goto exit_dput; + error = __do_follow_link(&link, &nd, &cookie); + if (unlikely(error)) { + if (!IS_ERR(cookie) && linki->i_op->put_link) + linki->i_op->put_link(link.dentry, &nd, cookie); + /* nd.path had been dropped */ + nd.path = link; + goto out_path; } - nd->flags |= LOOKUP_PARENT; - nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); - error = follow_link(&link, nd, &cookie); - if (unlikely(error)) - filp = ERR_PTR(error); - else - filp = do_last(nd, &path, op, pathname); - put_link(nd, &link, cookie); + nd.flags &= ~LOOKUP_PARENT; + filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); + if (linki->i_op->put_link) + linki->i_op->put_link(link.dentry, &nd, cookie); + path_put(&link); } out: - if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) - path_put(&nd->root); - if (base) - fput(base); - release_open_intent(nd); + if (nd.root.mnt) + path_put(&nd.root); + if (filp == ERR_PTR(-ESTALE) && !(flags & LOOKUP_REVAL)) + goto reval; + release_open_intent(&nd); return filp; +exit_dput: + path_put_conditional(&path, &nd); +out_path: + path_put(&nd.path); out_filp: filp = ERR_PTR(error); goto out; } -struct file *do_filp_open(int dfd, const char *pathname, - const struct open_flags *op, int flags) -{ - struct nameidata nd; - struct file *filp; - - filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU); - if (unlikely(filp == ERR_PTR(-ECHILD))) - filp = path_openat(dfd, pathname, &nd, op, flags); - if (unlikely(filp == ERR_PTR(-ESTALE))) - filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_REVAL); - return filp; -} - -struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, - const char *name, const struct open_flags *op, int flags) +/** + * filp_open - open file and return file pointer + * + * @filename: path to open + * @flags: open flags as per the open(2) second argument + * @mode: mode for the new file if O_CREAT is set, else ignored + * + * This is the helper to open a file from kernelspace if you really + * have to. But in generally you should not do this, so please move + * along, nothing to see here.. + */ +struct file *filp_open(const char *filename, int flags, int mode) { - struct nameidata nd; - struct file *file; - - nd.root.mnt = mnt; - nd.root.dentry = dentry; - - flags |= LOOKUP_ROOT; - - if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN) - return ERR_PTR(-ELOOP); - - file = path_openat(-1, name, &nd, op, flags | LOOKUP_RCU); - if (unlikely(file == ERR_PTR(-ECHILD))) - file = path_openat(-1, name, &nd, op, flags); - if (unlikely(file == ERR_PTR(-ESTALE))) - file = path_openat(-1, name, &nd, op, flags | LOOKUP_REVAL); - return file; + return do_filp_open(AT_FDCWD, filename, flags, mode, 0); } +EXPORT_SYMBOL(filp_open); /** * lookup_create - lookup a dentry, creating it if it doesn't exist @@ -2919,11 +3111,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de return error; mutex_lock(&inode->i_mutex); - /* Make sure we don't allow creating hardlink to an unlinked file */ - if (inode->i_nlink == 0) - error = -ENOENT; - else - error = dir->i_op->link(old_dentry, dir, new_dentry); + error = dir->i_op->link(old_dentry, dir, new_dentry); mutex_unlock(&inode->i_mutex); if (!error) fsnotify_link(dir, inode, new_dentry); @@ -2945,27 +3133,15 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, struct dentry *new_dentry; struct nameidata nd; struct path old_path; - int how = 0; int error; char *to; - if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) + if ((flags & ~AT_SYMLINK_FOLLOW) != 0) return -EINVAL; - /* - * To use null names we require CAP_DAC_READ_SEARCH - * This ensures that not everyone will be able to create - * handlink using the passed filedescriptor. - */ - if (flags & AT_EMPTY_PATH) { - if (!capable(CAP_DAC_READ_SEARCH)) - return -ENOENT; - how = LOOKUP_EMPTY; - } - - if (flags & AT_SYMLINK_FOLLOW) - how |= LOOKUP_FOLLOW; - error = user_path_at(olddfd, oldname, how, &old_path); + error = user_path_at(olddfd, oldname, + flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0, + &old_path); if (error) return error; @@ -3402,7 +3578,7 @@ EXPORT_SYMBOL(page_readlink); EXPORT_SYMBOL(__page_symlink); EXPORT_SYMBOL(page_symlink); EXPORT_SYMBOL(page_symlink_inode_operations); -EXPORT_SYMBOL(kern_path_parent); +EXPORT_SYMBOL(path_lookup); EXPORT_SYMBOL(kern_path); EXPORT_SYMBOL(vfs_path_lookup); EXPORT_SYMBOL(inode_permission); diff --git a/trunk/fs/namespace.c b/trunk/fs/namespace.c index dffe6f49ab93..d1edf26025dc 100644 --- a/trunk/fs/namespace.c +++ b/trunk/fs/namespace.c @@ -1002,18 +1002,6 @@ const struct seq_operations mounts_op = { .show = show_vfsmnt }; -static int uuid_is_nil(u8 *uuid) -{ - int i; - u8 *cp = (u8 *)uuid; - - for (i = 0; i < 16; i++) { - if (*cp++) - return 0; - } - return 1; -} - static int show_mountinfo(struct seq_file *m, void *v) { struct proc_mounts *p = m->private; @@ -1052,10 +1040,6 @@ static int show_mountinfo(struct seq_file *m, void *v) if (IS_MNT_UNBINDABLE(mnt)) seq_puts(m, " unbindable"); - if (!uuid_is_nil(mnt->mnt_sb->s_uuid)) - /* print the uuid */ - seq_printf(m, " uuid:%pU", mnt->mnt_sb->s_uuid); - /* Filesystem specific data */ seq_puts(m, " - "); show_type(m, sb); diff --git a/trunk/fs/nfs/inode.c b/trunk/fs/nfs/inode.c index 2f8e61816d75..1cc600e77bb4 100644 --- a/trunk/fs/nfs/inode.c +++ b/trunk/fs/nfs/inode.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include @@ -90,11 +89,7 @@ int nfs_wait_bit_killable(void *word) */ u64 nfs_compat_user_ino64(u64 fileid) { -#ifdef CONFIG_COMPAT - compat_ulong_t ino; -#else - unsigned long ino; -#endif + int ino; if (enable_ino64) return fileid; diff --git a/trunk/fs/nfs/nfs4_fs.h b/trunk/fs/nfs/nfs4_fs.h index 1be36cf65bfc..7a7474073148 100644 --- a/trunk/fs/nfs/nfs4_fs.h +++ b/trunk/fs/nfs/nfs4_fs.h @@ -298,11 +298,6 @@ struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp); #if defined(CONFIG_NFS_V4_1) struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp); struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp); -extern void nfs4_schedule_session_recovery(struct nfs4_session *); -#else -static inline void nfs4_schedule_session_recovery(struct nfs4_session *session) -{ -} #endif /* CONFIG_NFS_V4_1 */ extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *); @@ -312,9 +307,10 @@ extern void nfs4_put_open_state(struct nfs4_state *); extern void nfs4_close_state(struct path *, struct nfs4_state *, fmode_t); extern void nfs4_close_sync(struct path *, struct nfs4_state *, fmode_t); extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); -extern void nfs4_schedule_lease_recovery(struct nfs_client *); +extern void nfs4_schedule_state_recovery(struct nfs_client *); extern void nfs4_schedule_state_manager(struct nfs_client *); -extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); +extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); +extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state); extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); extern void nfs41_handle_recall_slot(struct nfs_client *clp); extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); diff --git a/trunk/fs/nfs/nfs4filelayoutdev.c b/trunk/fs/nfs/nfs4filelayoutdev.c index b73c34375f60..f5c9b125e8cc 100644 --- a/trunk/fs/nfs/nfs4filelayoutdev.c +++ b/trunk/fs/nfs/nfs4filelayoutdev.c @@ -219,10 +219,6 @@ decode_and_add_ds(__be32 **pp, struct inode *inode) goto out_err; } buf = kmalloc(rlen + 1, GFP_KERNEL); - if (!buf) { - dprintk("%s: Not enough memory\n", __func__); - goto out_err; - } buf[rlen] = '\0'; memcpy(buf, r_addr, rlen); diff --git a/trunk/fs/nfs/nfs4proc.c b/trunk/fs/nfs/nfs4proc.c index 0a07e353a961..1ff76acc7e98 100644 --- a/trunk/fs/nfs/nfs4proc.c +++ b/trunk/fs/nfs/nfs4proc.c @@ -51,6 +51,7 @@ #include #include #include +#include #include "nfs4_fs.h" #include "delegation.h" @@ -256,13 +257,12 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, case -NFS4ERR_OPENMODE: if (state == NULL) break; - nfs4_schedule_stateid_recovery(server, state); - goto wait_on_recovery; + nfs4_state_mark_reclaim_nograce(clp, state); + goto do_state_recovery; case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_EXPIRED: - nfs4_schedule_lease_recovery(clp); - goto wait_on_recovery; + goto do_state_recovery; #if defined(CONFIG_NFS_V4_1) case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: @@ -273,7 +273,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, case -NFS4ERR_SEQ_MISORDERED: dprintk("%s ERROR: %d Reset session\n", __func__, errorcode); - nfs4_schedule_session_recovery(clp->cl_session); + nfs4_schedule_state_recovery(clp); exception->retry = 1; break; #endif /* defined(CONFIG_NFS_V4_1) */ @@ -296,7 +296,8 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, } /* We failed to handle the error */ return nfs4_map_errors(ret); -wait_on_recovery: +do_state_recovery: + nfs4_schedule_state_recovery(clp); ret = nfs4_wait_clnt_recover(clp); if (ret == 0) exception->retry = 1; @@ -435,8 +436,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * clp = res->sr_session->clp; do_renew_lease(clp, timestamp); /* Check sequence flags */ - if (res->sr_status_flags != 0) - nfs4_schedule_lease_recovery(clp); + if (atomic_read(&clp->cl_count) > 1) + nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); break; case -NFS4ERR_DELAY: /* The server detected a resend of the RPC call and @@ -1255,13 +1256,14 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state case -NFS4ERR_BAD_HIGH_SLOT: case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: case -NFS4ERR_DEADSESSION: - nfs4_schedule_session_recovery(server->nfs_client->cl_session); + nfs4_schedule_state_recovery( + server->nfs_client); goto out; case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: /* Don't recall a delegation if it was lost */ - nfs4_schedule_lease_recovery(server->nfs_client); + nfs4_schedule_state_recovery(server->nfs_client); goto out; case -ERESTARTSYS: /* @@ -1270,7 +1272,7 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state */ case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_BAD_STATEID: - nfs4_schedule_stateid_recovery(server, state); + nfs4_state_mark_reclaim_nograce(server->nfs_client, state); case -EKEYEXPIRED: /* * User RPCSEC_GSS context has expired. @@ -1586,7 +1588,7 @@ static int nfs4_recover_expired_lease(struct nfs_server *server) if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state)) break; - nfs4_schedule_state_manager(clp); + nfs4_schedule_state_recovery(clp); ret = -EIO; } return ret; @@ -3177,7 +3179,7 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata) if (task->tk_status < 0) { /* Unless we're shutting down, schedule state recovery! */ if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) != 0) - nfs4_schedule_lease_recovery(clp); + nfs4_schedule_state_recovery(clp); return; } do_renew_lease(clp, timestamp); @@ -3260,7 +3262,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen, spages = pages; do { - len = min_t(size_t, PAGE_CACHE_SIZE, buflen); + len = min(PAGE_CACHE_SIZE, buflen); newpage = alloc_page(GFP_KERNEL); if (newpage == NULL) @@ -3502,13 +3504,12 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, case -NFS4ERR_OPENMODE: if (state == NULL) break; - nfs4_schedule_stateid_recovery(server, state); - goto wait_on_recovery; + nfs4_state_mark_reclaim_nograce(clp, state); + goto do_state_recovery; case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_EXPIRED: - nfs4_schedule_lease_recovery(clp); - goto wait_on_recovery; + goto do_state_recovery; #if defined(CONFIG_NFS_V4_1) case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: @@ -3519,7 +3520,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, case -NFS4ERR_SEQ_MISORDERED: dprintk("%s ERROR %d, Reset session\n", __func__, task->tk_status); - nfs4_schedule_session_recovery(clp->cl_session); + nfs4_schedule_state_recovery(clp); task->tk_status = 0; return -EAGAIN; #endif /* CONFIG_NFS_V4_1 */ @@ -3536,8 +3537,9 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, } task->tk_status = nfs4_map_errors(task->tk_status); return 0; -wait_on_recovery: +do_state_recovery: rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); + nfs4_schedule_state_recovery(clp); if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); task->tk_status = 0; @@ -4148,7 +4150,7 @@ static void nfs4_lock_release(void *calldata) task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, data->arg.lock_seqid); if (!IS_ERR(task)) - rpc_put_task_async(task); + rpc_put_task(task); dprintk("%s: cancelling lock!\n", __func__); } else nfs_free_seqid(data->arg.lock_seqid); @@ -4172,18 +4174,23 @@ static const struct rpc_call_ops nfs4_recover_lock_ops = { static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) { + struct nfs_client *clp = server->nfs_client; + struct nfs4_state *state = lsp->ls_state; + switch (error) { case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_BAD_STATEID: - lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; + case -NFS4ERR_EXPIRED: if (new_lock_owner != 0 || (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) - nfs4_schedule_stateid_recovery(server, lsp->ls_state); + nfs4_state_mark_reclaim_nograce(clp, state); + lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; break; case -NFS4ERR_STALE_STATEID: + if (new_lock_owner != 0 || + (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) + nfs4_state_mark_reclaim_reboot(clp, state); lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; - case -NFS4ERR_EXPIRED: - nfs4_schedule_lease_recovery(server->nfs_client); }; } @@ -4399,14 +4406,12 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) case -NFS4ERR_EXPIRED: case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_STATEID: - nfs4_schedule_lease_recovery(server->nfs_client); - goto out; case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: case -NFS4ERR_BAD_HIGH_SLOT: case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: case -NFS4ERR_DEADSESSION: - nfs4_schedule_session_recovery(server->nfs_client->cl_session); + nfs4_schedule_state_recovery(server->nfs_client); goto out; case -ERESTARTSYS: /* @@ -4416,7 +4421,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_BAD_STATEID: case -NFS4ERR_OPENMODE: - nfs4_schedule_stateid_recovery(server, state); + nfs4_state_mark_reclaim_nograce(server->nfs_client, state); err = 0; goto out; case -EKEYEXPIRED: @@ -5023,20 +5028,10 @@ int nfs4_proc_create_session(struct nfs_client *clp) int status; unsigned *ptr; struct nfs4_session *session = clp->cl_session; - long timeout = 0; - int err; dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); - do { - status = _nfs4_proc_create_session(clp); - if (status == -NFS4ERR_DELAY) { - err = nfs4_delay(clp->cl_rpcclient, &timeout); - if (err) - status = err; - } - } while (status == -NFS4ERR_DELAY); - + status = _nfs4_proc_create_session(clp); if (status) goto out; @@ -5145,7 +5140,7 @@ static int nfs41_sequence_handle_errors(struct rpc_task *task, struct nfs_client rpc_delay(task, NFS4_POLL_RETRY_MAX); return -EAGAIN; default: - nfs4_schedule_lease_recovery(clp); + nfs4_schedule_state_recovery(clp); } return 0; } @@ -5232,7 +5227,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr if (IS_ERR(task)) ret = PTR_ERR(task); else - rpc_put_task_async(task); + rpc_put_task(task); dprintk("<-- %s status=%d\n", __func__, ret); return ret; } @@ -5248,13 +5243,8 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) goto out; } ret = rpc_wait_for_completion_task(task); - if (!ret) { - struct nfs4_sequence_res *res = task->tk_msg.rpc_resp; - - if (task->tk_status == 0) - nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); + if (!ret) ret = task->tk_status; - } rpc_put_task(task); out: dprintk("<-- %s status=%d\n", __func__, ret); @@ -5291,7 +5281,7 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf rpc_delay(task, NFS4_POLL_RETRY_MAX); return -EAGAIN; default: - nfs4_schedule_lease_recovery(clp); + nfs4_schedule_state_recovery(clp); } return 0; } @@ -5359,9 +5349,6 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) status = PTR_ERR(task); goto out; } - status = nfs4_wait_for_completion_rpc_task(task); - if (status == 0) - status = task->tk_status; rpc_put_task(task); return 0; out: diff --git a/trunk/fs/nfs/nfs4state.c b/trunk/fs/nfs/nfs4state.c index 0592288f9f06..e6742b57a04c 100644 --- a/trunk/fs/nfs/nfs4state.c +++ b/trunk/fs/nfs/nfs4state.c @@ -1007,9 +1007,9 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) } /* - * Schedule a lease recovery attempt + * Schedule a state recovery attempt */ -void nfs4_schedule_lease_recovery(struct nfs_client *clp) +void nfs4_schedule_state_recovery(struct nfs_client *clp) { if (!clp) return; @@ -1018,7 +1018,7 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp) nfs4_schedule_state_manager(clp); } -static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) +int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) { set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); @@ -1032,7 +1032,7 @@ static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_st return 1; } -static int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state) +int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state) { set_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags); clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); @@ -1041,14 +1041,6 @@ static int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_s return 1; } -void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4_state *state) -{ - struct nfs_client *clp = server->nfs_client; - - nfs4_state_mark_reclaim_nograce(clp, state); - nfs4_schedule_state_manager(clp); -} - static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops) { struct inode *inode = state->inode; @@ -1444,15 +1436,10 @@ static int nfs4_reclaim_lease(struct nfs_client *clp) } #ifdef CONFIG_NFS_V4_1 -void nfs4_schedule_session_recovery(struct nfs4_session *session) -{ - nfs4_schedule_lease_recovery(session->clp); -} - void nfs41_handle_recall_slot(struct nfs_client *clp) { set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); - nfs4_schedule_state_manager(clp); + nfs4_schedule_state_recovery(clp); } static void nfs4_reset_all_state(struct nfs_client *clp) @@ -1460,7 +1447,7 @@ static void nfs4_reset_all_state(struct nfs_client *clp) if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { clp->cl_boot_time = CURRENT_TIME; nfs4_state_start_reclaim_nograce(clp); - nfs4_schedule_state_manager(clp); + nfs4_schedule_state_recovery(clp); } } @@ -1468,7 +1455,7 @@ static void nfs41_handle_server_reboot(struct nfs_client *clp) { if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { nfs4_state_start_reclaim_reboot(clp); - nfs4_schedule_state_manager(clp); + nfs4_schedule_state_recovery(clp); } } @@ -1488,7 +1475,7 @@ static void nfs41_handle_cb_path_down(struct nfs_client *clp) { nfs_expire_all_delegations(clp); if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0) - nfs4_schedule_state_manager(clp); + nfs4_schedule_state_recovery(clp); } void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) diff --git a/trunk/fs/nfs/nfs4xdr.c b/trunk/fs/nfs/nfs4xdr.c index 94d50e86a124..4e2c168b6ee9 100644 --- a/trunk/fs/nfs/nfs4xdr.c +++ b/trunk/fs/nfs/nfs4xdr.c @@ -1660,7 +1660,7 @@ static void encode_create_session(struct xdr_stream *xdr, p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12); *p++ = cpu_to_be32(OP_CREATE_SESSION); - p = xdr_encode_hyper(p, clp->cl_clientid); + p = xdr_encode_hyper(p, clp->cl_ex_clid); *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ *p++ = cpu_to_be32(args->flags); /*flags */ @@ -4694,7 +4694,7 @@ static int decode_exchange_id(struct xdr_stream *xdr, p = xdr_inline_decode(xdr, 8); if (unlikely(!p)) goto out_overflow; - xdr_decode_hyper(p, &clp->cl_clientid); + xdr_decode_hyper(p, &clp->cl_ex_clid); p = xdr_inline_decode(xdr, 12); if (unlikely(!p)) goto out_overflow; diff --git a/trunk/fs/nfs/nfsroot.c b/trunk/fs/nfs/nfsroot.c index c541093a5bf2..903908a20023 100644 --- a/trunk/fs/nfs/nfsroot.c +++ b/trunk/fs/nfs/nfsroot.c @@ -86,14 +86,11 @@ /* Default path we try to mount. "%s" gets replaced by our IP address */ #define NFS_ROOT "/tftpboot/%s" -/* Default NFSROOT mount options. */ -#define NFS_DEF_OPTIONS "udp" - /* Parameters passed from the kernel command line */ static char nfs_root_parms[256] __initdata = ""; /* Text-based mount options passed to super.c */ -static char nfs_root_options[256] __initdata = NFS_DEF_OPTIONS; +static char nfs_root_options[256] __initdata = ""; /* Address of NFS server */ static __be32 servaddr __initdata = htonl(INADDR_NONE); @@ -163,14 +160,8 @@ static int __init root_nfs_copy(char *dest, const char *src, } static int __init root_nfs_cat(char *dest, const char *src, - const size_t destlen) + const size_t destlen) { - size_t len = strlen(dest); - - if (len && dest[len - 1] != ',') - if (strlcat(dest, ",", destlen) > destlen) - return -1; - if (strlcat(dest, src, destlen) > destlen) return -1; return 0; @@ -203,6 +194,16 @@ static int __init root_nfs_parse_options(char *incoming, char *exppath, if (root_nfs_cat(nfs_root_options, incoming, sizeof(nfs_root_options))) return -1; + + /* + * Possibly prepare for more options to be appended + */ + if (nfs_root_options[0] != '\0' && + nfs_root_options[strlen(nfs_root_options)] != ',') + if (root_nfs_cat(nfs_root_options, ",", + sizeof(nfs_root_options))) + return -1; + return 0; } @@ -216,7 +217,7 @@ static int __init root_nfs_parse_options(char *incoming, char *exppath, */ static int __init root_nfs_data(char *cmdline) { - char mand_options[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1]; + char addr_option[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1]; int len, retval = -1; char *tmp = NULL; const size_t tmplen = sizeof(nfs_export_path); @@ -243,9 +244,9 @@ static int __init root_nfs_data(char *cmdline) * Append mandatory options for nfsroot so they override * what has come before */ - snprintf(mand_options, sizeof(mand_options), "nolock,addr=%pI4", + snprintf(addr_option, sizeof(addr_option), "nolock,addr=%pI4", &servaddr); - if (root_nfs_cat(nfs_root_options, mand_options, + if (root_nfs_cat(nfs_root_options, addr_option, sizeof(nfs_root_options))) goto out_optionstoolong; diff --git a/trunk/fs/nfs/unlink.c b/trunk/fs/nfs/unlink.c index 6481d537d69d..e313a51acdd1 100644 --- a/trunk/fs/nfs/unlink.c +++ b/trunk/fs/nfs/unlink.c @@ -180,7 +180,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n task_setup_data.rpc_client = NFS_CLIENT(dir); task = rpc_run_task(&task_setup_data); if (!IS_ERR(task)) - rpc_put_task_async(task); + rpc_put_task(task); return 1; } diff --git a/trunk/fs/nfs/write.c b/trunk/fs/nfs/write.c index 42b92d7a9cc4..c8278f4046cb 100644 --- a/trunk/fs/nfs/write.c +++ b/trunk/fs/nfs/write.c @@ -1292,8 +1292,6 @@ static int nfs_commit_rpcsetup(struct list_head *head, task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); - if (how & FLUSH_SYNC) - rpc_wait_for_completion_task(task); rpc_put_task(task); return 0; } diff --git a/trunk/fs/nfsctl.c b/trunk/fs/nfsctl.c index 124e8fcb0dd6..bf9cbd242ddd 100644 --- a/trunk/fs/nfsctl.c +++ b/trunk/fs/nfsctl.c @@ -22,17 +22,30 @@ static struct file *do_open(char *name, int flags) { + struct nameidata nd; struct vfsmount *mnt; - struct file *file; + int error; mnt = do_kern_mount("nfsd", 0, "nfsd", NULL); if (IS_ERR(mnt)) return (struct file *)mnt; - file = file_open_root(mnt->mnt_root, mnt, name, flags); - + error = vfs_path_lookup(mnt->mnt_root, mnt, name, 0, &nd); mntput(mnt); /* drop do_kern_mount reference */ - return file; + if (error) + return ERR_PTR(error); + + if (flags == O_RDWR) + error = may_open(&nd.path, MAY_READ|MAY_WRITE, flags); + else + error = may_open(&nd.path, MAY_WRITE, flags); + + if (!error) + return dentry_open(nd.path.dentry, nd.path.mnt, flags, + current_cred()); + + path_put(&nd.path); + return ERR_PTR(error); } static struct { diff --git a/trunk/fs/nfsd/nfs4callback.c b/trunk/fs/nfsd/nfs4callback.c index 02eb4edf0ece..cde36cb0f348 100644 --- a/trunk/fs/nfsd/nfs4callback.c +++ b/trunk/fs/nfsd/nfs4callback.c @@ -432,7 +432,7 @@ static int decode_cb_sequence4resok(struct xdr_stream *xdr, * If the server returns different values for sessionID, slotID or * sequence number, the server is looney tunes. */ - p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN + 4 + 4 + 4 + 4); + p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN + 4 + 4); if (unlikely(p == NULL)) goto out_overflow; memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN); diff --git a/trunk/fs/nfsd/nfs4state.c b/trunk/fs/nfsd/nfs4state.c index 7b566ec14e18..54b60bfceb8d 100644 --- a/trunk/fs/nfsd/nfs4state.c +++ b/trunk/fs/nfsd/nfs4state.c @@ -2445,16 +2445,15 @@ nfs4_check_delegmode(struct nfs4_delegation *dp, int flags) static struct nfs4_delegation * find_delegation_file(struct nfs4_file *fp, stateid_t *stid) { - struct nfs4_delegation *dp; + struct nfs4_delegation *dp = NULL; spin_lock(&recall_lock); - list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) - if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid) { - spin_unlock(&recall_lock); - return dp; - } + list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) { + if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid) + break; + } spin_unlock(&recall_lock); - return NULL; + return dp; } int share_access_to_flags(u32 share_access) diff --git a/trunk/fs/nfsd/nfs4xdr.c b/trunk/fs/nfsd/nfs4xdr.c index 615f0a9f0600..1275b8655070 100644 --- a/trunk/fs/nfsd/nfs4xdr.c +++ b/trunk/fs/nfsd/nfs4xdr.c @@ -1142,7 +1142,7 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp, u32 dummy; char *machine_name; - int i, j; + int i; int nr_secflavs; READ_BUF(16); @@ -1215,7 +1215,7 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp, READ_BUF(4); READ32(dummy); READ_BUF(dummy * 4); - for (j = 0; j < dummy; ++j) + for (i = 0; i < dummy; ++i) READ32(dummy); break; case RPC_AUTH_GSS: diff --git a/trunk/fs/ocfs2/dcache.c b/trunk/fs/ocfs2/dcache.c index 7eb90403fc8a..6d80ecc7834f 100644 --- a/trunk/fs/ocfs2/dcache.c +++ b/trunk/fs/ocfs2/dcache.c @@ -56,7 +56,7 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, int ret = 0; /* if all else fails, just return false */ struct ocfs2_super *osb; - if (nd && nd->flags & LOOKUP_RCU) + if (nd->flags & LOOKUP_RCU) return -ECHILD; inode = dentry->d_inode; diff --git a/trunk/fs/ocfs2/export.c b/trunk/fs/ocfs2/export.c index 254652a9b542..5dbc3062b4fd 100644 --- a/trunk/fs/ocfs2/export.c +++ b/trunk/fs/ocfs2/export.c @@ -197,12 +197,8 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, dentry->d_name.len, dentry->d_name.name, fh, len, connectable); - if (connectable && (len < 6)) { - *max_len = 6; - type = 255; - goto bail; - } else if (len < 3) { - *max_len = 3; + if (len < 3 || (connectable && len < 6)) { + mlog(ML_ERROR, "fh buffer is too small for encoding\n"); type = 255; goto bail; } diff --git a/trunk/fs/ocfs2/refcounttree.c b/trunk/fs/ocfs2/refcounttree.c index 29623da133cc..19ebc5aad391 100644 --- a/trunk/fs/ocfs2/refcounttree.c +++ b/trunk/fs/ocfs2/refcounttree.c @@ -4379,7 +4379,7 @@ static int ocfs2_user_path_parent(const char __user *path, if (IS_ERR(s)) return PTR_ERR(s); - error = kern_path_parent(s, nd); + error = path_lookup(s, LOOKUP_PARENT, nd); if (error) putname(s); else diff --git a/trunk/fs/open.c b/trunk/fs/open.c index 3cac0bda46df..5a2c6ebc22b5 100644 --- a/trunk/fs/open.c +++ b/trunk/fs/open.c @@ -233,14 +233,6 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (!(file->f_mode & FMODE_WRITE)) return -EBADF; - - /* It's not possible punch hole on append only file */ - if (mode & FALLOC_FL_PUNCH_HOLE && IS_APPEND(inode)) - return -EPERM; - - if (IS_IMMUTABLE(inode)) - return -EPERM; - /* * Revalidate the write permissions, in case security policy has * changed since the files were opened. @@ -573,15 +565,13 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, { struct path path; int error = -EINVAL; - int lookup_flags; + int follow; - if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) + if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) goto out; - lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; - if (flag & AT_EMPTY_PATH) - lookup_flags |= LOOKUP_EMPTY; - error = user_path_at(dfd, filename, lookup_flags, &path); + follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; + error = user_path_at(dfd, filename, follow, &path); if (error) goto out; error = mnt_want_write(path.mnt); @@ -671,16 +661,11 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, int (*open)(struct inode *, struct file *), const struct cred *cred) { - static const struct file_operations empty_fops = {}; struct inode *inode; int error; f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; - - if (unlikely(f->f_flags & O_PATH)) - f->f_mode = FMODE_PATH; - inode = dentry->d_inode; if (f->f_mode & FMODE_WRITE) { error = __get_file_write_access(inode, mnt); @@ -694,14 +679,8 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, f->f_path.dentry = dentry; f->f_path.mnt = mnt; f->f_pos = 0; - file_sb_list_add(f, inode->i_sb); - - if (unlikely(f->f_mode & FMODE_PATH)) { - f->f_op = &empty_fops; - return f; - } - f->f_op = fops_get(inode->i_fop); + file_sb_list_add(f, inode->i_sb); error = security_dentry_open(f, cred); if (error) @@ -903,110 +882,15 @@ void fd_install(unsigned int fd, struct file *file) EXPORT_SYMBOL(fd_install); -static inline int build_open_flags(int flags, int mode, struct open_flags *op) -{ - int lookup_flags = 0; - int acc_mode; - - if (!(flags & O_CREAT)) - mode = 0; - op->mode = mode; - - /* Must never be set by userspace */ - flags &= ~FMODE_NONOTIFY; - - /* - * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only - * check for O_DSYNC if the need any syncing at all we enforce it's - * always set instead of having to deal with possibly weird behaviour - * for malicious applications setting only __O_SYNC. - */ - if (flags & __O_SYNC) - flags |= O_DSYNC; - - /* - * If we have O_PATH in the open flag. Then we - * cannot have anything other than the below set of flags - */ - if (flags & O_PATH) { - flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH; - acc_mode = 0; - } else { - acc_mode = MAY_OPEN | ACC_MODE(flags); - } - - op->open_flag = flags; - - /* O_TRUNC implies we need access checks for write permissions */ - if (flags & O_TRUNC) - acc_mode |= MAY_WRITE; - - /* Allow the LSM permission hook to distinguish append - access from general write access. */ - if (flags & O_APPEND) - acc_mode |= MAY_APPEND; - - op->acc_mode = acc_mode; - - op->intent = flags & O_PATH ? 0 : LOOKUP_OPEN; - - if (flags & O_CREAT) { - op->intent |= LOOKUP_CREATE; - if (flags & O_EXCL) - op->intent |= LOOKUP_EXCL; - } - - if (flags & O_DIRECTORY) - lookup_flags |= LOOKUP_DIRECTORY; - if (!(flags & O_NOFOLLOW)) - lookup_flags |= LOOKUP_FOLLOW; - return lookup_flags; -} - -/** - * filp_open - open file and return file pointer - * - * @filename: path to open - * @flags: open flags as per the open(2) second argument - * @mode: mode for the new file if O_CREAT is set, else ignored - * - * This is the helper to open a file from kernelspace if you really - * have to. But in generally you should not do this, so please move - * along, nothing to see here.. - */ -struct file *filp_open(const char *filename, int flags, int mode) -{ - struct open_flags op; - int lookup = build_open_flags(flags, mode, &op); - return do_filp_open(AT_FDCWD, filename, &op, lookup); -} -EXPORT_SYMBOL(filp_open); - -struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt, - const char *filename, int flags) -{ - struct open_flags op; - int lookup = build_open_flags(flags, 0, &op); - if (flags & O_CREAT) - return ERR_PTR(-EINVAL); - if (!filename && (flags & O_DIRECTORY)) - if (!dentry->d_inode->i_op->lookup) - return ERR_PTR(-ENOTDIR); - return do_file_open_root(dentry, mnt, filename, &op, lookup); -} -EXPORT_SYMBOL(file_open_root); - long do_sys_open(int dfd, const char __user *filename, int flags, int mode) { - struct open_flags op; - int lookup = build_open_flags(flags, mode, &op); char *tmp = getname(filename); int fd = PTR_ERR(tmp); if (!IS_ERR(tmp)) { fd = get_unused_fd_flags(flags); if (fd >= 0) { - struct file *f = do_filp_open(dfd, tmp, &op, lookup); + struct file *f = do_filp_open(dfd, tmp, flags, mode, 0); if (IS_ERR(f)) { put_unused_fd(fd); fd = PTR_ERR(f); @@ -1076,10 +960,8 @@ int filp_close(struct file *filp, fl_owner_t id) if (filp->f_op && filp->f_op->flush) retval = filp->f_op->flush(filp, id); - if (likely(!(filp->f_mode & FMODE_PATH))) { - dnotify_flush(filp, id); - locks_remove_posix(filp, id); - } + dnotify_flush(filp, id); + locks_remove_posix(filp, id); fput(filp); return retval; } diff --git a/trunk/fs/partitions/osf.c b/trunk/fs/partitions/osf.c index be03a0b08b47..48cec7cbca17 100644 --- a/trunk/fs/partitions/osf.c +++ b/trunk/fs/partitions/osf.c @@ -10,13 +10,10 @@ #include "check.h" #include "osf.h" -#define MAX_OSF_PARTITIONS 8 - int osf_partition(struct parsed_partitions *state) { int i; int slot = 1; - unsigned int npartitions; Sector sect; unsigned char *data; struct disklabel { @@ -48,7 +45,7 @@ int osf_partition(struct parsed_partitions *state) u8 p_fstype; u8 p_frag; __le16 p_cpg; - } d_partitions[MAX_OSF_PARTITIONS]; + } d_partitions[8]; } * label; struct d_partition * partition; @@ -66,12 +63,7 @@ int osf_partition(struct parsed_partitions *state) put_dev_sector(sect); return 0; } - npartitions = le16_to_cpu(label->d_npartitions); - if (npartitions > MAX_OSF_PARTITIONS) { - put_dev_sector(sect); - return 0; - } - for (i = 0 ; i < npartitions; i++, partition++) { + for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) { if (slot == state->limit) break; if (le32_to_cpu(partition->p_size)) diff --git a/trunk/fs/proc/base.c b/trunk/fs/proc/base.c index d49c4b5d2c3e..9d096e82b201 100644 --- a/trunk/fs/proc/base.c +++ b/trunk/fs/proc/base.c @@ -2620,6 +2620,35 @@ static const struct pid_entry proc_base_stuff[] = { &proc_self_inode_operations, NULL, {}), }; +/* + * Exceptional case: normally we are not allowed to unhash a busy + * directory. In this case, however, we can do it - no aliasing problems + * due to the way we treat inodes. + */ +static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd) +{ + struct inode *inode; + struct task_struct *task; + + if (nd->flags & LOOKUP_RCU) + return -ECHILD; + + inode = dentry->d_inode; + task = get_proc_task(inode); + if (task) { + put_task_struct(task); + return 1; + } + d_drop(dentry); + return 0; +} + +static const struct dentry_operations proc_base_dentry_operations = +{ + .d_revalidate = proc_base_revalidate, + .d_delete = pid_delete_dentry, +}; + static struct dentry *proc_base_instantiate(struct inode *dir, struct dentry *dentry, struct task_struct *task, const void *ptr) { @@ -2656,6 +2685,7 @@ static struct dentry *proc_base_instantiate(struct inode *dir, if (p->fop) inode->i_fop = p->fop; ei->op = p->op; + d_set_d_op(dentry, &proc_base_dentry_operations); d_add(dentry, inode); error = NULL; out: diff --git a/trunk/fs/proc/inode.c b/trunk/fs/proc/inode.c index d6a7ca1fdac5..176ce4cda68a 100644 --- a/trunk/fs/proc/inode.c +++ b/trunk/fs/proc/inode.c @@ -27,7 +27,6 @@ static void proc_evict_inode(struct inode *inode) { struct proc_dir_entry *de; - struct ctl_table_header *head; truncate_inode_pages(&inode->i_data, 0); end_writeback(inode); @@ -39,11 +38,8 @@ static void proc_evict_inode(struct inode *inode) de = PROC_I(inode)->pde; if (de) pde_put(de); - head = PROC_I(inode)->sysctl; - if (head) { - rcu_assign_pointer(PROC_I(inode)->sysctl, NULL); - sysctl_head_put(head); - } + if (PROC_I(inode)->sysctl) + sysctl_head_put(PROC_I(inode)->sysctl); } struct vfsmount *proc_mnt; diff --git a/trunk/fs/proc/proc_sysctl.c b/trunk/fs/proc/proc_sysctl.c index 8eb2522111c5..09a1f92a34ef 100644 --- a/trunk/fs/proc/proc_sysctl.c +++ b/trunk/fs/proc/proc_sysctl.c @@ -408,18 +408,15 @@ static int proc_sys_compare(const struct dentry *parent, const struct dentry *dentry, const struct inode *inode, unsigned int len, const char *str, const struct qstr *name) { - struct ctl_table_header *head; /* Although proc doesn't have negative dentries, rcu-walk means * that inode here can be NULL */ - /* AV: can it, indeed? */ if (!inode) - return 1; + return 0; if (name->len != len) return 1; if (memcmp(name->name, str, len)) return 1; - head = rcu_dereference(PROC_I(inode)->sysctl); - return !head || !sysctl_is_seen(head); + return !sysctl_is_seen(PROC_I(inode)->sysctl); } static const struct dentry_operations proc_sys_dentry_operations = { diff --git a/trunk/fs/reiserfs/inode.c b/trunk/fs/reiserfs/inode.c index 1bba24bad820..0bae036831e2 100644 --- a/trunk/fs/reiserfs/inode.c +++ b/trunk/fs/reiserfs/inode.c @@ -1593,13 +1593,8 @@ int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, struct inode *inode = dentry->d_inode; int maxlen = *lenp; - if (need_parent && (maxlen < 5)) { - *lenp = 5; + if (maxlen < 3) return 255; - } else if (maxlen < 3) { - *lenp = 3; - return 255; - } data[0] = inode->i_ino; data[1] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id); diff --git a/trunk/fs/reiserfs/namei.c b/trunk/fs/reiserfs/namei.c index 4b2eb564fdad..68fdf45cc6c9 100644 --- a/trunk/fs/reiserfs/namei.c +++ b/trunk/fs/reiserfs/namei.c @@ -1122,6 +1122,10 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir, reiserfs_write_unlock(dir->i_sb); return -EMLINK; } + if (inode->i_nlink == 0) { + reiserfs_write_unlock(dir->i_sb); + return -ENOENT; + } /* inc before scheduling so reiserfs_unlink knows we are here */ inc_nlink(inode); diff --git a/trunk/fs/reiserfs/xattr.c b/trunk/fs/reiserfs/xattr.c index 5c11ca82b782..3cfb2e933644 100644 --- a/trunk/fs/reiserfs/xattr.c +++ b/trunk/fs/reiserfs/xattr.c @@ -978,6 +978,8 @@ int reiserfs_permission(struct inode *inode, int mask, unsigned int flags) static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd) { + if (nd->flags & LOOKUP_RCU) + return -ECHILD; return -EPERM; } diff --git a/trunk/fs/stat.c b/trunk/fs/stat.c index 961039121cb8..d5c61cf2b703 100644 --- a/trunk/fs/stat.c +++ b/trunk/fs/stat.c @@ -75,16 +75,13 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, int error = -EINVAL; int lookup_flags = 0; - if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | - AT_EMPTY_PATH)) != 0) + if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)) != 0) goto out; if (!(flag & AT_SYMLINK_NOFOLLOW)) lookup_flags |= LOOKUP_FOLLOW; if (flag & AT_NO_AUTOMOUNT) lookup_flags |= LOOKUP_NO_AUTOMOUNT; - if (flag & AT_EMPTY_PATH) - lookup_flags |= LOOKUP_EMPTY; error = user_path_at(dfd, filename, lookup_flags, &path); if (error) @@ -300,7 +297,7 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname, if (bufsiz <= 0) return -EINVAL; - error = user_path_at(dfd, pathname, LOOKUP_EMPTY, &path); + error = user_path_at(dfd, pathname, 0, &path); if (!error) { struct inode *inode = path.dentry->d_inode; diff --git a/trunk/fs/statfs.c b/trunk/fs/statfs.c index 8244924dec55..30ea8c8a996b 100644 --- a/trunk/fs/statfs.c +++ b/trunk/fs/statfs.c @@ -73,135 +73,149 @@ int vfs_statfs(struct path *path, struct kstatfs *buf) } EXPORT_SYMBOL(vfs_statfs); -int user_statfs(const char __user *pathname, struct kstatfs *st) +static int do_statfs_native(struct path *path, struct statfs *buf) { - struct path path; - int error = user_path(pathname, &path); - if (!error) { - error = vfs_statfs(&path, st); - path_put(&path); - } - return error; -} - -int fd_statfs(int fd, struct kstatfs *st) -{ - struct file *file = fget(fd); - int error = -EBADF; - if (file) { - error = vfs_statfs(&file->f_path, st); - fput(file); - } - return error; -} + struct kstatfs st; + int retval; -static int do_statfs_native(struct kstatfs *st, struct statfs __user *p) -{ - struct statfs buf; + retval = vfs_statfs(path, &st); + if (retval) + return retval; - if (sizeof(buf) == sizeof(*st)) - memcpy(&buf, st, sizeof(*st)); + if (sizeof(*buf) == sizeof(st)) + memcpy(buf, &st, sizeof(st)); else { - if (sizeof buf.f_blocks == 4) { - if ((st->f_blocks | st->f_bfree | st->f_bavail | - st->f_bsize | st->f_frsize) & + if (sizeof buf->f_blocks == 4) { + if ((st.f_blocks | st.f_bfree | st.f_bavail | + st.f_bsize | st.f_frsize) & 0xffffffff00000000ULL) return -EOVERFLOW; /* * f_files and f_ffree may be -1; it's okay to stuff * that into 32 bits */ - if (st->f_files != -1 && - (st->f_files & 0xffffffff00000000ULL)) + if (st.f_files != -1 && + (st.f_files & 0xffffffff00000000ULL)) return -EOVERFLOW; - if (st->f_ffree != -1 && - (st->f_ffree & 0xffffffff00000000ULL)) + if (st.f_ffree != -1 && + (st.f_ffree & 0xffffffff00000000ULL)) return -EOVERFLOW; } - buf.f_type = st->f_type; - buf.f_bsize = st->f_bsize; - buf.f_blocks = st->f_blocks; - buf.f_bfree = st->f_bfree; - buf.f_bavail = st->f_bavail; - buf.f_files = st->f_files; - buf.f_ffree = st->f_ffree; - buf.f_fsid = st->f_fsid; - buf.f_namelen = st->f_namelen; - buf.f_frsize = st->f_frsize; - buf.f_flags = st->f_flags; - memset(buf.f_spare, 0, sizeof(buf.f_spare)); + buf->f_type = st.f_type; + buf->f_bsize = st.f_bsize; + buf->f_blocks = st.f_blocks; + buf->f_bfree = st.f_bfree; + buf->f_bavail = st.f_bavail; + buf->f_files = st.f_files; + buf->f_ffree = st.f_ffree; + buf->f_fsid = st.f_fsid; + buf->f_namelen = st.f_namelen; + buf->f_frsize = st.f_frsize; + buf->f_flags = st.f_flags; + memset(buf->f_spare, 0, sizeof(buf->f_spare)); } - if (copy_to_user(p, &buf, sizeof(buf))) - return -EFAULT; return 0; } -static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p) +static int do_statfs64(struct path *path, struct statfs64 *buf) { - struct statfs64 buf; - if (sizeof(buf) == sizeof(*st)) - memcpy(&buf, st, sizeof(*st)); + struct kstatfs st; + int retval; + + retval = vfs_statfs(path, &st); + if (retval) + return retval; + + if (sizeof(*buf) == sizeof(st)) + memcpy(buf, &st, sizeof(st)); else { - buf.f_type = st->f_type; - buf.f_bsize = st->f_bsize; - buf.f_blocks = st->f_blocks; - buf.f_bfree = st->f_bfree; - buf.f_bavail = st->f_bavail; - buf.f_files = st->f_files; - buf.f_ffree = st->f_ffree; - buf.f_fsid = st->f_fsid; - buf.f_namelen = st->f_namelen; - buf.f_frsize = st->f_frsize; - buf.f_flags = st->f_flags; - memset(buf.f_spare, 0, sizeof(buf.f_spare)); + buf->f_type = st.f_type; + buf->f_bsize = st.f_bsize; + buf->f_blocks = st.f_blocks; + buf->f_bfree = st.f_bfree; + buf->f_bavail = st.f_bavail; + buf->f_files = st.f_files; + buf->f_ffree = st.f_ffree; + buf->f_fsid = st.f_fsid; + buf->f_namelen = st.f_namelen; + buf->f_frsize = st.f_frsize; + buf->f_flags = st.f_flags; + memset(buf->f_spare, 0, sizeof(buf->f_spare)); } - if (copy_to_user(p, &buf, sizeof(buf))) - return -EFAULT; return 0; } SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf) { - struct kstatfs st; - int error = user_statfs(pathname, &st); - if (!error) - error = do_statfs_native(&st, buf); + struct path path; + int error; + + error = user_path(pathname, &path); + if (!error) { + struct statfs tmp; + error = do_statfs_native(&path, &tmp); + if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) + error = -EFAULT; + path_put(&path); + } return error; } SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf) { - struct kstatfs st; - int error; + struct path path; + long error; + if (sz != sizeof(*buf)) return -EINVAL; - error = user_statfs(pathname, &st); - if (!error) - error = do_statfs64(&st, buf); + error = user_path(pathname, &path); + if (!error) { + struct statfs64 tmp; + error = do_statfs64(&path, &tmp); + if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) + error = -EFAULT; + path_put(&path); + } return error; } SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf) { - struct kstatfs st; - int error = fd_statfs(fd, &st); - if (!error) - error = do_statfs_native(&st, buf); + struct file *file; + struct statfs tmp; + int error; + + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = do_statfs_native(&file->f_path, &tmp); + if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) + error = -EFAULT; + fput(file); +out: return error; } SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf) { - struct kstatfs st; + struct file *file; + struct statfs64 tmp; int error; if (sz != sizeof(*buf)) return -EINVAL; - error = fd_statfs(fd, &st); - if (!error) - error = do_statfs64(&st, buf); + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = do_statfs64(&file->f_path, &tmp); + if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) + error = -EFAULT; + fput(file); +out: return error; } diff --git a/trunk/fs/ubifs/dir.c b/trunk/fs/ubifs/dir.c index 7217d67a80a6..14f64b689d7f 100644 --- a/trunk/fs/ubifs/dir.c +++ b/trunk/fs/ubifs/dir.c @@ -522,6 +522,24 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir, ubifs_assert(mutex_is_locked(&dir->i_mutex)); ubifs_assert(mutex_is_locked(&inode->i_mutex)); + /* + * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing + * otherwise has the potential to corrupt the orphan inode list. + * + * Indeed, consider a scenario when 'vfs_link(dirA/fileA)' and + * 'vfs_unlink(dirA/fileA, dirB/fileB)' race. 'vfs_link()' does not + * lock 'dirA->i_mutex', so this is possible. Both of the functions + * lock 'fileA->i_mutex' though. Suppose 'vfs_unlink()' wins, and takes + * 'fileA->i_mutex' mutex first. Suppose 'fileA->i_nlink' is 1. In this + * case 'ubifs_unlink()' will drop the last reference, and put 'inodeA' + * to the list of orphans. After this, 'vfs_link()' will link + * 'dirB/fileB' to 'inodeA'. This is a problem because, for example, + * the subsequent 'vfs_unlink(dirB/fileB)' will add the same inode + * to the list of orphans. + */ + if (inode->i_nlink == 0) + return -ENOENT; + err = dbg_check_synced_i_size(inode); if (err) return err; diff --git a/trunk/fs/udf/namei.c b/trunk/fs/udf/namei.c index f1dce848ef96..b7c338d5e9df 100644 --- a/trunk/fs/udf/namei.c +++ b/trunk/fs/udf/namei.c @@ -1286,13 +1286,8 @@ static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp, struct fid *fid = (struct fid *)fh; int type = FILEID_UDF_WITHOUT_PARENT; - if (connectable && (len < 5)) { - *lenp = 5; - return 255; - } else if (len < 3) { - *lenp = 3; + if (len < 3 || (connectable && len < 5)) return 255; - } *lenp = 3; fid->udf.block = location.logicalBlockNum; diff --git a/trunk/fs/xfs/linux-2.6/xfs_export.c b/trunk/fs/xfs/linux-2.6/xfs_export.c index f4f878fc0083..fc0114da7fdd 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_export.c +++ b/trunk/fs/xfs/linux-2.6/xfs_export.c @@ -89,10 +89,8 @@ xfs_fs_encode_fh( * seven combinations work. The real answer is "don't use v2". */ len = xfs_fileid_length(fileid_type); - if (*max_len < len) { - *max_len = len; + if (*max_len < len) return 255; - } *max_len = len; switch (fileid_type) { diff --git a/trunk/include/asm-generic/fcntl.h b/trunk/include/asm-generic/fcntl.h index 84793c7025e2..0fc16e3f0bfc 100644 --- a/trunk/include/asm-generic/fcntl.h +++ b/trunk/include/asm-generic/fcntl.h @@ -80,10 +80,6 @@ #define O_SYNC (__O_SYNC|O_DSYNC) #endif -#ifndef O_PATH -#define O_PATH 010000000 -#endif - #ifndef O_NDELAY #define O_NDELAY O_NONBLOCK #endif diff --git a/trunk/include/asm-generic/unistd.h b/trunk/include/asm-generic/unistd.h index 57af0338d270..b969770196c2 100644 --- a/trunk/include/asm-generic/unistd.h +++ b/trunk/include/asm-generic/unistd.h @@ -646,13 +646,9 @@ __SYSCALL(__NR_prlimit64, sys_prlimit64) __SYSCALL(__NR_fanotify_init, sys_fanotify_init) #define __NR_fanotify_mark 263 __SYSCALL(__NR_fanotify_mark, sys_fanotify_mark) -#define __NR_name_to_handle_at 264 -__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at) -#define __NR_open_by_handle_at 265 -__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at) #undef __NR_syscalls -#define __NR_syscalls 266 +#define __NR_syscalls 264 /* * All syscalls below here should go away really, diff --git a/trunk/include/linux/debugobjects.h b/trunk/include/linux/debugobjects.h index 597692f1fc8d..65970b811e22 100644 --- a/trunk/include/linux/debugobjects.h +++ b/trunk/include/linux/debugobjects.h @@ -34,7 +34,10 @@ struct debug_obj { /** * struct debug_obj_descr - object type specific debug description structure + * * @name: name of the object typee + * @debug_hint: function returning address, which have associated + * kernel symbol, to allow identify the object * @fixup_init: fixup function, which is called when the init check * fails * @fixup_activate: fixup function, which is called when the activate check @@ -46,7 +49,7 @@ struct debug_obj { */ struct debug_obj_descr { const char *name; - + void *(*debug_hint) (void *addr); int (*fixup_init) (void *addr, enum debug_obj_state state); int (*fixup_activate) (void *addr, enum debug_obj_state state); int (*fixup_destroy) (void *addr, enum debug_obj_state state); diff --git a/trunk/include/linux/exportfs.h b/trunk/include/linux/exportfs.h index 33a42f24b275..28028988c862 100644 --- a/trunk/include/linux/exportfs.h +++ b/trunk/include/linux/exportfs.h @@ -8,9 +8,6 @@ struct inode; struct super_block; struct vfsmount; -/* limit the handle size to NFSv4 handle size now */ -#define MAX_HANDLE_SZ 128 - /* * The fileid_type identifies how the file within the filesystem is encoded. * In theory this is freely set and parsed by the filesystem, but we try to @@ -124,10 +121,8 @@ struct fid { * set, the encode_fh() should store sufficient information so that a good * attempt can be made to find not only the file but also it's place in the * filesystem. This typically means storing a reference to de->d_parent in - * the filehandle fragment. encode_fh() should return the fileid_type on - * success and on error returns 255 (if the space needed to encode fh is - * greater than @max_len*4 bytes). On error @max_len contains the minimum - * size(in 4 byte unit) needed to encode the file handle. + * the filehandle fragment. encode_fh() should return the number of bytes + * stored or a negative error code such as %-ENOSPC * * fh_to_dentry: * @fh_to_dentry is given a &struct super_block (@sb) and a file handle diff --git a/trunk/include/linux/fcntl.h b/trunk/include/linux/fcntl.h index f550f894ba15..a562fa5fb4e3 100644 --- a/trunk/include/linux/fcntl.h +++ b/trunk/include/linux/fcntl.h @@ -46,7 +46,6 @@ unlinking file. */ #define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */ #define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */ -#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */ #ifdef __KERNEL__ diff --git a/trunk/include/linux/file.h b/trunk/include/linux/file.h index 21a79958541c..e85baebf6279 100644 --- a/trunk/include/linux/file.h +++ b/trunk/include/linux/file.h @@ -29,8 +29,6 @@ static inline void fput_light(struct file *file, int fput_needed) extern struct file *fget(unsigned int fd); extern struct file *fget_light(unsigned int fd, int *fput_needed); -extern struct file *fget_raw(unsigned int fd); -extern struct file *fget_raw_light(unsigned int fd, int *fput_needed); extern void set_close_on_exec(unsigned int fd, int flag); extern void put_filp(struct file *); extern int alloc_fd(unsigned start, unsigned flags); diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 13df14e2c42e..e38b50a4b9d2 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -102,9 +102,6 @@ struct inodes_stat_t { /* File is huge (eg. /dev/kmem): treat loff_t as unsigned */ #define FMODE_UNSIGNED_OFFSET ((__force fmode_t)0x2000) -/* File is opened with O_PATH; almost nothing can be done with it */ -#define FMODE_PATH ((__force fmode_t)0x4000) - /* File was opened by fanotify and shouldn't generate fanotify events */ #define FMODE_NONOTIFY ((__force fmode_t)0x1000000) @@ -981,13 +978,6 @@ struct file { #endif }; -struct file_handle { - __u32 handle_bytes; - int handle_type; - /* file identifier */ - unsigned char f_handle[0]; -}; - #define get_file(x) atomic_long_inc(&(x)->f_count) #define fput_atomic(x) atomic_long_add_unless(&(x)->f_count, -1, 1) #define file_count(x) atomic_long_read(&(x)->f_count) @@ -1411,7 +1401,6 @@ struct super_block { wait_queue_head_t s_wait_unfrozen; char s_id[32]; /* Informational name */ - u8 s_uuid[16]; /* UUID */ void *s_fs_info; /* Filesystem private info */ fmode_t s_mode; @@ -1885,8 +1874,6 @@ extern void drop_collected_mounts(struct vfsmount *); extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *, struct vfsmount *); extern int vfs_statfs(struct path *, struct kstatfs *); -extern int user_statfs(const char __user *, struct kstatfs *); -extern int fd_statfs(int, struct kstatfs *); extern int statfs_by_dentry(struct dentry *, struct kstatfs *); extern int freeze_super(struct super_block *super); extern int thaw_super(struct super_block *super); @@ -2003,8 +1990,6 @@ extern int do_fallocate(struct file *file, int mode, loff_t offset, extern long do_sys_open(int dfd, const char __user *filename, int flags, int mode); extern struct file *filp_open(const char *, int, int); -extern struct file *file_open_root(struct dentry *, struct vfsmount *, - const char *, int); extern struct file * dentry_open(struct dentry *, struct vfsmount *, int, const struct cred *); extern int filp_close(struct file *, fl_owner_t id); @@ -2220,6 +2205,10 @@ extern struct file *create_read_pipe(struct file *f, int flags); extern struct file *create_write_pipe(int flags); extern void free_write_pipe(struct file *); +extern struct file *do_filp_open(int dfd, const char *pathname, + int open_flag, int mode, int acc_mode); +extern int may_open(struct path *, int, int); + extern int kernel_read(struct file *, loff_t, char *, unsigned long); extern struct file * open_exec(const char *); diff --git a/trunk/include/linux/interrupt.h b/trunk/include/linux/interrupt.h index d746da19c6a2..55e0d4253e49 100644 --- a/trunk/include/linux/interrupt.h +++ b/trunk/include/linux/interrupt.h @@ -55,7 +55,7 @@ * Used by threaded interrupts which need to keep the * irq line disabled until the threaded handler has been run. * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend - * IRQF_FORCE_RESUME - Force enable it on resume even if IRQF_NO_SUSPEND is set + * */ #define IRQF_DISABLED 0x00000020 #define IRQF_SAMPLE_RANDOM 0x00000040 @@ -67,7 +67,6 @@ #define IRQF_IRQPOLL 0x00001000 #define IRQF_ONESHOT 0x00002000 #define IRQF_NO_SUSPEND 0x00004000 -#define IRQF_FORCE_RESUME 0x00008000 #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND) diff --git a/trunk/include/linux/namei.h b/trunk/include/linux/namei.h index 9c8603872c36..f276d4fa01fc 100644 --- a/trunk/include/linux/namei.h +++ b/trunk/include/linux/namei.h @@ -19,6 +19,7 @@ struct nameidata { struct path path; struct qstr last; struct path root; + struct file *file; struct inode *inode; /* path.dentry.d_inode */ unsigned int flags; unsigned seq; @@ -62,10 +63,6 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; #define LOOKUP_EXCL 0x0400 #define LOOKUP_RENAME_TARGET 0x0800 -#define LOOKUP_JUMPED 0x1000 -#define LOOKUP_ROOT 0x2000 -#define LOOKUP_EMPTY 0x4000 - extern int user_path_at(int, const char __user *, unsigned, struct path *); #define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW, path) @@ -75,7 +72,7 @@ extern int user_path_at(int, const char __user *, unsigned, struct path *); extern int kern_path(const char *, unsigned, struct path *); -extern int kern_path_parent(const char *, struct nameidata *); +extern int path_lookup(const char *, unsigned, struct nameidata *); extern int vfs_path_lookup(struct dentry *, struct vfsmount *, const char *, unsigned int, struct nameidata *); diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 71caf7a5e6c6..d971346b0340 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -2392,9 +2392,6 @@ extern int netdev_notice(const struct net_device *dev, const char *format, ...) extern int netdev_info(const struct net_device *dev, const char *format, ...) __attribute__ ((format (printf, 2, 3))); -#define MODULE_ALIAS_NETDEV(device) \ - MODULE_ALIAS("netdev-" device) - #if defined(DEBUG) #define netdev_dbg(__dev, format, args...) \ netdev_printk(KERN_DEBUG, __dev, format, ##args) diff --git a/trunk/include/linux/nfs_fs_sb.h b/trunk/include/linux/nfs_fs_sb.h index 3e112de12d8d..b197563913bf 100644 --- a/trunk/include/linux/nfs_fs_sb.h +++ b/trunk/include/linux/nfs_fs_sb.h @@ -68,7 +68,11 @@ struct nfs_client { unsigned char cl_id_uniquifier; u32 cl_cb_ident; /* v4.0 callback identifier */ const struct nfs4_minor_version_ops *cl_mvops; +#endif /* CONFIG_NFS_V4 */ +#ifdef CONFIG_NFS_V4_1 + /* clientid returned from EXCHANGE_ID, used by session operations */ + u64 cl_ex_clid; /* The sequence id to use for the next CREATE_SESSION */ u32 cl_seqid; /* The flags used for obtaining the clientid during EXCHANGE_ID */ @@ -76,7 +80,7 @@ struct nfs_client { struct nfs4_session *cl_session; /* sharred session */ struct list_head cl_layouts; struct pnfs_deviceid_cache *cl_devid_cache; /* pNFS deviceid cache */ -#endif /* CONFIG_NFS_V4 */ +#endif /* CONFIG_NFS_V4_1 */ #ifdef CONFIG_NFS_FSCACHE struct fscache_cookie *fscache; /* client index cache cookie */ @@ -181,7 +185,7 @@ struct nfs_server { /* maximum number of slots to use */ #define NFS4_MAX_SLOT_TABLE RPC_MAX_SLOT_TABLE -#if defined(CONFIG_NFS_V4) +#if defined(CONFIG_NFS_V4_1) /* Sessions */ #define SLOT_TABLE_SZ (NFS4_MAX_SLOT_TABLE/(8*sizeof(long))) @@ -221,5 +225,5 @@ struct nfs4_session { struct nfs_client *clp; }; -#endif /* CONFIG_NFS_V4 */ +#endif /* CONFIG_NFS_V4_1 */ #endif diff --git a/trunk/include/linux/sunrpc/sched.h b/trunk/include/linux/sunrpc/sched.h index d81db8012c63..88513fd8e208 100644 --- a/trunk/include/linux/sunrpc/sched.h +++ b/trunk/include/linux/sunrpc/sched.h @@ -212,7 +212,6 @@ struct rpc_task *rpc_run_task(const struct rpc_task_setup *); struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req, const struct rpc_call_ops *ops); void rpc_put_task(struct rpc_task *); -void rpc_put_task_async(struct rpc_task *); void rpc_exit_task(struct rpc_task *); void rpc_exit(struct rpc_task *, int); void rpc_release_calldata(const struct rpc_call_ops *, void *); diff --git a/trunk/include/linux/syscalls.h b/trunk/include/linux/syscalls.h index 2d9b79c0f224..98664db1be47 100644 --- a/trunk/include/linux/syscalls.h +++ b/trunk/include/linux/syscalls.h @@ -62,7 +62,6 @@ struct robust_list_head; struct getcpu_cache; struct old_linux_dirent; struct perf_event_attr; -struct file_handle; #include #include @@ -833,10 +832,5 @@ asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff); asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg); -asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name, - struct file_handle __user *handle, - int __user *mnt_id, int flag); -asmlinkage long sys_open_by_handle_at(int mountdirfd, - struct file_handle __user *handle, - int flags); + #endif diff --git a/trunk/include/linux/sysctl.h b/trunk/include/linux/sysctl.h index 11684d9e6bd2..7bb5cb64f3b8 100644 --- a/trunk/include/linux/sysctl.h +++ b/trunk/include/linux/sysctl.h @@ -930,7 +930,6 @@ enum #ifdef __KERNEL__ #include -#include /* For the /proc/sys support */ struct ctl_table; @@ -1038,15 +1037,10 @@ struct ctl_table_root { struct ctl_table trees. */ struct ctl_table_header { - union { - struct { - struct ctl_table *ctl_table; - struct list_head ctl_entry; - int used; - int count; - }; - struct rcu_head rcu; - }; + struct ctl_table *ctl_table; + struct list_head ctl_entry; + int used; + int count; struct completion *unregistering; struct ctl_table *ctl_table_arg; struct ctl_table_root *root; diff --git a/trunk/include/target/target_core_transport.h b/trunk/include/target/target_core_transport.h index 2e8ec51f0615..246940511579 100644 --- a/trunk/include/target/target_core_transport.h +++ b/trunk/include/target/target_core_transport.h @@ -135,8 +135,6 @@ extern void transport_complete_task(struct se_task *, int); extern void transport_add_task_to_execute_queue(struct se_task *, struct se_task *, struct se_device *); -extern void transport_remove_task_from_execute_queue(struct se_task *, - struct se_device *); unsigned char *transport_dump_cmd_direction(struct se_cmd *); extern void transport_dump_dev_state(struct se_device *, char *, int *); extern void transport_dump_dev_info(struct se_device *, struct se_lun *, diff --git a/trunk/include/xen/events.h b/trunk/include/xen/events.h index 962da2ced5b4..00f53ddcc062 100644 --- a/trunk/include/xen/events.h +++ b/trunk/include/xen/events.h @@ -75,9 +75,11 @@ int xen_allocate_pirq(unsigned gsi, int shareable, char *name); int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name); #ifdef CONFIG_PCI_MSI -int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc); -int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, - int pirq, int vector, const char *name); +/* Allocate an irq and a pirq to be used with MSIs. */ +#define XEN_ALLOC_PIRQ (1 << 0) +#define XEN_ALLOC_IRQ (1 << 1) +void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc_mask); +int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type); #endif /* De-allocates the above mentioned physical interrupt. */ diff --git a/trunk/include/xen/interface/io/blkif.h b/trunk/include/xen/interface/io/blkif.h index 61e523af3c46..c2d1fa4dc1ee 100644 --- a/trunk/include/xen/interface/io/blkif.h +++ b/trunk/include/xen/interface/io/blkif.h @@ -51,7 +51,11 @@ typedef uint64_t blkif_sector_t; */ #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11 -struct blkif_request_rw { +struct blkif_request { + uint8_t operation; /* BLKIF_OP_??? */ + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t handle; /* only for read/write requests */ + uint64_t id; /* private guest value, echoed in resp */ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ struct blkif_request_segment { grant_ref_t gref; /* reference to I/O buffer frame */ @@ -61,16 +65,6 @@ struct blkif_request_rw { } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; }; -struct blkif_request { - uint8_t operation; /* BLKIF_OP_??? */ - uint8_t nr_segments; /* number of segments */ - blkif_vdev_t handle; /* only for read/write requests */ - uint64_t id; /* private guest value, echoed in resp */ - union { - struct blkif_request_rw rw; - } u; -}; - struct blkif_response { uint64_t id; /* copied from request */ uint8_t operation; /* copied from request */ @@ -97,25 +91,4 @@ DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response); #define VDISK_REMOVABLE 0x2 #define VDISK_READONLY 0x4 -/* Xen-defined major numbers for virtual disks, they look strangely - * familiar */ -#define XEN_IDE0_MAJOR 3 -#define XEN_IDE1_MAJOR 22 -#define XEN_SCSI_DISK0_MAJOR 8 -#define XEN_SCSI_DISK1_MAJOR 65 -#define XEN_SCSI_DISK2_MAJOR 66 -#define XEN_SCSI_DISK3_MAJOR 67 -#define XEN_SCSI_DISK4_MAJOR 68 -#define XEN_SCSI_DISK5_MAJOR 69 -#define XEN_SCSI_DISK6_MAJOR 70 -#define XEN_SCSI_DISK7_MAJOR 71 -#define XEN_SCSI_DISK8_MAJOR 128 -#define XEN_SCSI_DISK9_MAJOR 129 -#define XEN_SCSI_DISK10_MAJOR 130 -#define XEN_SCSI_DISK11_MAJOR 131 -#define XEN_SCSI_DISK12_MAJOR 132 -#define XEN_SCSI_DISK13_MAJOR 133 -#define XEN_SCSI_DISK14_MAJOR 134 -#define XEN_SCSI_DISK15_MAJOR 135 - #endif /* __XEN_PUBLIC_IO_BLKIF_H__ */ diff --git a/trunk/include/xen/interface/xen.h b/trunk/include/xen/interface/xen.h index b33257bc7e83..2befa3e2f1bc 100644 --- a/trunk/include/xen/interface/xen.h +++ b/trunk/include/xen/interface/xen.h @@ -30,7 +30,7 @@ #define __HYPERVISOR_stack_switch 3 #define __HYPERVISOR_set_callbacks 4 #define __HYPERVISOR_fpu_taskswitch 5 -#define __HYPERVISOR_sched_op_compat 6 +#define __HYPERVISOR_sched_op 6 #define __HYPERVISOR_dom0_op 7 #define __HYPERVISOR_set_debugreg 8 #define __HYPERVISOR_get_debugreg 9 @@ -52,7 +52,7 @@ #define __HYPERVISOR_mmuext_op 26 #define __HYPERVISOR_acm_op 27 #define __HYPERVISOR_nmi_op 28 -#define __HYPERVISOR_sched_op 29 +#define __HYPERVISOR_sched_op_new 29 #define __HYPERVISOR_callback_op 30 #define __HYPERVISOR_xenoprof_op 31 #define __HYPERVISOR_event_channel_op 32 diff --git a/trunk/include/xen/xen-ops.h b/trunk/include/xen/xen-ops.h index 03c85d7387fb..98b92154a264 100644 --- a/trunk/include/xen/xen-ops.h +++ b/trunk/include/xen/xen-ops.h @@ -5,9 +5,9 @@ DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); -void xen_arch_pre_suspend(void); -void xen_arch_post_suspend(int suspend_cancelled); -void xen_arch_hvm_post_suspend(int suspend_cancelled); +void xen_pre_suspend(void); +void xen_post_suspend(int suspend_cancelled); +void xen_hvm_post_suspend(int suspend_cancelled); void xen_mm_pin_all(void); void xen_mm_unpin_all(void); diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index e72fa17fe559..be788c0957d4 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -287,18 +287,6 @@ config BSD_PROCESS_ACCT_V3 for processing it. A preliminary version of these tools is available at . -config FHANDLE - bool "open by fhandle syscalls" - select EXPORTFS - help - If you say Y here, a user level program will be able to map - file names to handle and then later use the handle for - different file system operations. This is useful in implementing - userspace file servers, which now track files using handles instead - of names. The handle would remain the same even if file names - get renamed. Enables open_by_handle_at(2) and name_to_handle_at(2) - syscalls. - config TASKSTATS bool "Export task/process statistics through netlink (EXPERIMENTAL)" depends on NET diff --git a/trunk/kernel/audit_watch.c b/trunk/kernel/audit_watch.c index e683869365d9..d2e3c7866460 100644 --- a/trunk/kernel/audit_watch.c +++ b/trunk/kernel/audit_watch.c @@ -144,9 +144,9 @@ int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev) } /* Initialize a parent watch entry. */ -static struct audit_parent *audit_init_parent(struct path *path) +static struct audit_parent *audit_init_parent(struct nameidata *ndp) { - struct inode *inode = path->dentry->d_inode; + struct inode *inode = ndp->path.dentry->d_inode; struct audit_parent *parent; int ret; @@ -353,40 +353,53 @@ static void audit_remove_parent_watches(struct audit_parent *parent) } /* Get path information necessary for adding watches. */ -static int audit_get_nd(struct audit_watch *watch, struct path *parent) +static int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw) { - struct nameidata nd; - struct dentry *d; + struct nameidata *ndparent, *ndwatch; int err; - err = kern_path_parent(watch->path, &nd); - if (err) - return err; + ndparent = kmalloc(sizeof(*ndparent), GFP_KERNEL); + if (unlikely(!ndparent)) + return -ENOMEM; - if (nd.last_type != LAST_NORM) { - path_put(&nd.path); - return -EINVAL; + ndwatch = kmalloc(sizeof(*ndwatch), GFP_KERNEL); + if (unlikely(!ndwatch)) { + kfree(ndparent); + return -ENOMEM; } - mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); - d = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); - if (IS_ERR(d)) { - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); - path_put(&nd.path); - return PTR_ERR(d); + err = path_lookup(path, LOOKUP_PARENT, ndparent); + if (err) { + kfree(ndparent); + kfree(ndwatch); + return err; } - if (d->d_inode) { - /* update watch filter fields */ - watch->dev = d->d_inode->i_sb->s_dev; - watch->ino = d->d_inode->i_ino; + + err = path_lookup(path, 0, ndwatch); + if (err) { + kfree(ndwatch); + ndwatch = NULL; } - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); - *parent = nd.path; - dput(d); + *ndp = ndparent; + *ndw = ndwatch; + return 0; } +/* Release resources used for watch path information. */ +static void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw) +{ + if (ndp) { + path_put(&ndp->path); + kfree(ndp); + } + if (ndw) { + path_put(&ndw->path); + kfree(ndw); + } +} + /* Associate the given rule with an existing parent. * Caller must hold audit_filter_mutex. */ static void audit_add_to_parent(struct audit_krule *krule, @@ -427,24 +440,31 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list) { struct audit_watch *watch = krule->watch; struct audit_parent *parent; - struct path parent_path; + struct nameidata *ndp = NULL, *ndw = NULL; int h, ret = 0; mutex_unlock(&audit_filter_mutex); /* Avoid calling path_lookup under audit_filter_mutex. */ - ret = audit_get_nd(watch, &parent_path); + ret = audit_get_nd(watch->path, &ndp, &ndw); + if (ret) { + /* caller expects mutex locked */ + mutex_lock(&audit_filter_mutex); + goto error; + } - /* caller expects mutex locked */ mutex_lock(&audit_filter_mutex); - if (ret) - return ret; + /* update watch filter fields */ + if (ndw) { + watch->dev = ndw->path.dentry->d_inode->i_sb->s_dev; + watch->ino = ndw->path.dentry->d_inode->i_ino; + } /* either find an old parent or attach a new one */ - parent = audit_find_parent(parent_path.dentry->d_inode); + parent = audit_find_parent(ndp->path.dentry->d_inode); if (!parent) { - parent = audit_init_parent(&parent_path); + parent = audit_init_parent(ndp); if (IS_ERR(parent)) { ret = PTR_ERR(parent); goto error; @@ -459,8 +479,9 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list) h = audit_hash_ino((u32)watch->ino); *list = &audit_inode_hash[h]; error: - path_put(&parent_path); + audit_put_nd(ndp, ndw); /* NULL args OK */ return ret; + } void audit_remove_watch_rule(struct audit_krule *krule) diff --git a/trunk/kernel/hrtimer.c b/trunk/kernel/hrtimer.c index 0c8d7c048615..e38f5a073d01 100644 --- a/trunk/kernel/hrtimer.c +++ b/trunk/kernel/hrtimer.c @@ -334,6 +334,11 @@ EXPORT_SYMBOL_GPL(ktime_add_safe); static struct debug_obj_descr hrtimer_debug_descr; +static void *hrtimer_debug_hint(void *addr) +{ + return ((struct hrtimer *) addr)->function; +} + /* * fixup_init is called when: * - an active object is initialized @@ -393,6 +398,7 @@ static int hrtimer_fixup_free(void *addr, enum debug_obj_state state) static struct debug_obj_descr hrtimer_debug_descr = { .name = "hrtimer", + .debug_hint = hrtimer_debug_hint, .fixup_init = hrtimer_fixup_init, .fixup_activate = hrtimer_fixup_activate, .fixup_free = hrtimer_fixup_free, diff --git a/trunk/kernel/irq/manage.c b/trunk/kernel/irq/manage.c index 2782bacdf494..9033c1c70828 100644 --- a/trunk/kernel/irq/manage.c +++ b/trunk/kernel/irq/manage.c @@ -282,17 +282,8 @@ EXPORT_SYMBOL(disable_irq); void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume) { - if (resume) { - if (!(desc->status & IRQ_SUSPENDED)) { - if (!desc->action) - return; - if (!(desc->action->flags & IRQF_FORCE_RESUME)) - return; - /* Pretend that it got disabled ! */ - desc->depth++; - } + if (resume) desc->status &= ~IRQ_SUSPENDED; - } switch (desc->depth) { case 0: diff --git a/trunk/kernel/irq/pm.c b/trunk/kernel/irq/pm.c index d6bfb89cce91..0d4005d85b03 100644 --- a/trunk/kernel/irq/pm.c +++ b/trunk/kernel/irq/pm.c @@ -53,6 +53,9 @@ void resume_device_irqs(void) for_each_irq_desc(irq, desc) { unsigned long flags; + if (!(desc->status & IRQ_SUSPENDED)) + continue; + raw_spin_lock_irqsave(&desc->lock, flags); __enable_irq(desc, irq, true); raw_spin_unlock_irqrestore(&desc->lock, flags); diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index 42eab5a8437d..18d38e4ec7ba 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -4213,7 +4213,6 @@ void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key) { __wake_up_common(q, mode, 1, 0, key); } -EXPORT_SYMBOL_GPL(__wake_up_locked_key); /** * __wake_up_sync_key - wake up threads blocked on a waitqueue. diff --git a/trunk/kernel/sched_rt.c b/trunk/kernel/sched_rt.c index 01f75a5f17af..ad6267714c84 100644 --- a/trunk/kernel/sched_rt.c +++ b/trunk/kernel/sched_rt.c @@ -210,12 +210,11 @@ static void dequeue_rt_entity(struct sched_rt_entity *rt_se); static void sched_rt_rq_enqueue(struct rt_rq *rt_rq) { + int this_cpu = smp_processor_id(); struct task_struct *curr = rq_of_rt_rq(rt_rq)->curr; struct sched_rt_entity *rt_se; - int cpu = cpu_of(rq_of_rt_rq(rt_rq)); - - rt_se = rt_rq->tg->rt_se[cpu]; + rt_se = rt_rq->tg->rt_se[this_cpu]; if (rt_rq->rt_nr_running) { if (rt_se && !on_rt_rq(rt_se)) @@ -227,10 +226,10 @@ static void sched_rt_rq_enqueue(struct rt_rq *rt_rq) static void sched_rt_rq_dequeue(struct rt_rq *rt_rq) { + int this_cpu = smp_processor_id(); struct sched_rt_entity *rt_se; - int cpu = cpu_of(rq_of_rt_rq(rt_rq)); - rt_se = rt_rq->tg->rt_se[cpu]; + rt_se = rt_rq->tg->rt_se[this_cpu]; if (rt_se && on_rt_rq(rt_se)) dequeue_rt_entity(rt_se); @@ -566,11 +565,8 @@ static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun) if (rt_rq->rt_time || rt_rq->rt_nr_running) idle = 0; raw_spin_unlock(&rt_rq->rt_runtime_lock); - } else if (rt_rq->rt_nr_running) { + } else if (rt_rq->rt_nr_running) idle = 0; - if (!rt_rq_throttled(rt_rq)) - enqueue = 1; - } if (enqueue) sched_rt_rq_enqueue(rt_rq); diff --git a/trunk/kernel/sys_ni.c b/trunk/kernel/sys_ni.c index 25cc41cd8f33..c782fe9924c7 100644 --- a/trunk/kernel/sys_ni.c +++ b/trunk/kernel/sys_ni.c @@ -186,8 +186,3 @@ cond_syscall(sys_perf_event_open); /* fanotify! */ cond_syscall(sys_fanotify_init); cond_syscall(sys_fanotify_mark); - -/* open by handle */ -cond_syscall(sys_name_to_handle_at); -cond_syscall(sys_open_by_handle_at); -cond_syscall(compat_sys_open_by_handle_at); diff --git a/trunk/kernel/sysctl.c b/trunk/kernel/sysctl.c index 4eed0af5d144..0f1bd83db985 100644 --- a/trunk/kernel/sysctl.c +++ b/trunk/kernel/sysctl.c @@ -194,9 +194,9 @@ static int sysrq_sysctl_handler(ctl_table *table, int write, static struct ctl_table root_table[]; static struct ctl_table_root sysctl_table_root; static struct ctl_table_header root_table_header = { - {{.count = 1, + .count = 1, .ctl_table = root_table, - .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list),}}, + .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list), .root = &sysctl_table_root, .set = &sysctl_table_root.default_set, }; @@ -1567,16 +1567,11 @@ void sysctl_head_get(struct ctl_table_header *head) spin_unlock(&sysctl_lock); } -static void free_head(struct rcu_head *rcu) -{ - kfree(container_of(rcu, struct ctl_table_header, rcu)); -} - void sysctl_head_put(struct ctl_table_header *head) { spin_lock(&sysctl_lock); if (!--head->count) - call_rcu(&head->rcu, free_head); + kfree(head); spin_unlock(&sysctl_lock); } @@ -1953,10 +1948,10 @@ void unregister_sysctl_table(struct ctl_table_header * header) start_unregistering(header); if (!--header->parent->count) { WARN_ON(1); - call_rcu(&header->parent->rcu, free_head); + kfree(header->parent); } if (!--header->count) - call_rcu(&header->rcu, free_head); + kfree(header); spin_unlock(&sysctl_lock); } diff --git a/trunk/kernel/sysctl_binary.c b/trunk/kernel/sysctl_binary.c index 3b8e028b9601..b875bedf7c9a 100644 --- a/trunk/kernel/sysctl_binary.c +++ b/trunk/kernel/sysctl_binary.c @@ -1321,11 +1321,13 @@ static ssize_t binary_sysctl(const int *name, int nlen, void __user *oldval, size_t oldlen, void __user *newval, size_t newlen) { const struct bin_table *table = NULL; + struct nameidata nd; struct vfsmount *mnt; struct file *file; ssize_t result; char *pathname; int flags; + int acc_mode; pathname = sysctl_getname(name, nlen, &table); result = PTR_ERR(pathname); @@ -1335,17 +1337,28 @@ static ssize_t binary_sysctl(const int *name, int nlen, /* How should the sysctl be accessed? */ if (oldval && oldlen && newval && newlen) { flags = O_RDWR; + acc_mode = MAY_READ | MAY_WRITE; } else if (newval && newlen) { flags = O_WRONLY; + acc_mode = MAY_WRITE; } else if (oldval && oldlen) { flags = O_RDONLY; + acc_mode = MAY_READ; } else { result = 0; goto out_putname; } mnt = current->nsproxy->pid_ns->proc_mnt; - file = file_open_root(mnt->mnt_root, mnt, pathname, flags); + result = vfs_path_lookup(mnt->mnt_root, mnt, pathname, 0, &nd); + if (result) + goto out_putname; + + result = may_open(&nd.path, acc_mode, flags); + if (result) + goto out_putpath; + + file = dentry_open(nd.path.dentry, nd.path.mnt, flags, current_cred()); result = PTR_ERR(file); if (IS_ERR(file)) goto out_putname; @@ -1357,6 +1370,10 @@ static ssize_t binary_sysctl(const int *name, int nlen, putname(pathname); out: return result; + +out_putpath: + path_put(&nd.path); + goto out_putname; } diff --git a/trunk/kernel/timer.c b/trunk/kernel/timer.c index d6459923d245..33a67925d900 100644 --- a/trunk/kernel/timer.c +++ b/trunk/kernel/timer.c @@ -404,6 +404,11 @@ static void timer_stats_account_timer(struct timer_list *timer) {} static struct debug_obj_descr timer_debug_descr; +static void *timer_debug_hint(void *addr) +{ + return ((struct timer_list *) addr)->function; +} + /* * fixup_init is called when: * - an active object is initialized @@ -477,6 +482,7 @@ static int timer_fixup_free(void *addr, enum debug_obj_state state) static struct debug_obj_descr timer_debug_descr = { .name = "timer_list", + .debug_hint = timer_debug_hint, .fixup_init = timer_fixup_init, .fixup_activate = timer_fixup_activate, .fixup_free = timer_fixup_free, diff --git a/trunk/kernel/workqueue.c b/trunk/kernel/workqueue.c index ee6578b578ad..b5fe4c00eb3c 100644 --- a/trunk/kernel/workqueue.c +++ b/trunk/kernel/workqueue.c @@ -316,6 +316,11 @@ static inline int __next_wq_cpu(int cpu, const struct cpumask *mask, static struct debug_obj_descr work_debug_descr; +static void *work_debug_hint(void *addr) +{ + return ((struct work_struct *) addr)->func; +} + /* * fixup_init is called when: * - an active object is initialized @@ -387,6 +392,7 @@ static int work_fixup_free(void *addr, enum debug_obj_state state) static struct debug_obj_descr work_debug_descr = { .name = "work_struct", + .debug_hint = work_debug_hint, .fixup_init = work_fixup_init, .fixup_activate = work_fixup_activate, .fixup_free = work_fixup_free, diff --git a/trunk/lib/debugobjects.c b/trunk/lib/debugobjects.c index deebcc57d4e6..9d86e45086f5 100644 --- a/trunk/lib/debugobjects.c +++ b/trunk/lib/debugobjects.c @@ -249,14 +249,17 @@ static struct debug_bucket *get_bucket(unsigned long addr) static void debug_print_object(struct debug_obj *obj, char *msg) { + struct debug_obj_descr *descr = obj->descr; static int limit; - if (limit < 5 && obj->descr != descr_test) { + if (limit < 5 && descr != descr_test) { + void *hint = descr->debug_hint ? + descr->debug_hint(obj->object) : NULL; limit++; WARN(1, KERN_ERR "ODEBUG: %s %s (active state %u) " - "object type: %s\n", + "object type: %s hint: %pS\n", msg, obj_states[obj->state], obj->astate, - obj->descr->name); + descr->name, hint); } debug_objects_warnings++; } diff --git a/trunk/mm/huge_memory.c b/trunk/mm/huge_memory.c index 113e35c47502..dbe99a5f2073 100644 --- a/trunk/mm/huge_memory.c +++ b/trunk/mm/huge_memory.c @@ -1762,10 +1762,6 @@ static void collapse_huge_page(struct mm_struct *mm, #ifndef CONFIG_NUMA VM_BUG_ON(!*hpage); new_page = *hpage; - if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { - up_read(&mm->mmap_sem); - return; - } #else VM_BUG_ON(*hpage); /* @@ -1785,12 +1781,12 @@ static void collapse_huge_page(struct mm_struct *mm, *hpage = ERR_PTR(-ENOMEM); return; } +#endif if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { up_read(&mm->mmap_sem); put_page(new_page); return; } -#endif /* after allocating the hugepage upgrade to mmap_sem write mode */ up_read(&mm->mmap_sem); diff --git a/trunk/mm/rmap.c b/trunk/mm/rmap.c index 941bf82e8961..f21f4a1d6a1c 100644 --- a/trunk/mm/rmap.c +++ b/trunk/mm/rmap.c @@ -497,51 +497,41 @@ int page_referenced_one(struct page *page, struct vm_area_struct *vma, struct mm_struct *mm = vma->vm_mm; int referenced = 0; + /* + * Don't want to elevate referenced for mlocked page that gets this far, + * in order that it progresses to try_to_unmap and is moved to the + * unevictable list. + */ + if (vma->vm_flags & VM_LOCKED) { + *mapcount = 0; /* break early from loop */ + *vm_flags |= VM_LOCKED; + goto out; + } + + /* Pretend the page is referenced if the task has the + swap token and is in the middle of a page fault. */ + if (mm != current->mm && has_swap_token(mm) && + rwsem_is_locked(&mm->mmap_sem)) + referenced++; + if (unlikely(PageTransHuge(page))) { pmd_t *pmd; spin_lock(&mm->page_table_lock); - /* - * rmap might return false positives; we must filter - * these out using page_check_address_pmd(). - */ pmd = page_check_address_pmd(page, mm, address, PAGE_CHECK_ADDRESS_PMD_FLAG); - if (!pmd) { - spin_unlock(&mm->page_table_lock); - goto out; - } - - if (vma->vm_flags & VM_LOCKED) { - spin_unlock(&mm->page_table_lock); - *mapcount = 0; /* break early from loop */ - *vm_flags |= VM_LOCKED; - goto out; - } - - /* go ahead even if the pmd is pmd_trans_splitting() */ - if (pmdp_clear_flush_young_notify(vma, address, pmd)) + if (pmd && !pmd_trans_splitting(*pmd) && + pmdp_clear_flush_young_notify(vma, address, pmd)) referenced++; spin_unlock(&mm->page_table_lock); } else { pte_t *pte; spinlock_t *ptl; - /* - * rmap might return false positives; we must filter - * these out using page_check_address(). - */ pte = page_check_address(page, mm, address, &ptl, 0); if (!pte) goto out; - if (vma->vm_flags & VM_LOCKED) { - pte_unmap_unlock(pte, ptl); - *mapcount = 0; /* break early from loop */ - *vm_flags |= VM_LOCKED; - goto out; - } - if (ptep_clear_flush_young_notify(vma, address, pte)) { /* * Don't treat a reference through a sequentially read @@ -556,12 +546,6 @@ int page_referenced_one(struct page *page, struct vm_area_struct *vma, pte_unmap_unlock(pte, ptl); } - /* Pretend the page is referenced if the task has the - swap token and is in the middle of a page fault. */ - if (mm != current->mm && has_swap_token(mm) && - rwsem_is_locked(&mm->mmap_sem)) - referenced++; - (*mapcount)--; if (referenced) diff --git a/trunk/mm/shmem.c b/trunk/mm/shmem.c index 3437b65d6d6e..5ee67c990602 100644 --- a/trunk/mm/shmem.c +++ b/trunk/mm/shmem.c @@ -2144,10 +2144,8 @@ static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len, { struct inode *inode = dentry->d_inode; - if (*len < 3) { - *len = 3; + if (*len < 3) return 255; - } if (inode_unhashed(inode)) { /* Unfortunately insert_inode_hash is not idempotent, diff --git a/trunk/net/Makefile b/trunk/net/Makefile index a51d9465e628..a3330ebe2c53 100644 --- a/trunk/net/Makefile +++ b/trunk/net/Makefile @@ -19,7 +19,9 @@ obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_INET) += ipv4/ obj-$(CONFIG_XFRM) += xfrm/ obj-$(CONFIG_UNIX) += unix/ -obj-$(CONFIG_NET) += ipv6/ +ifneq ($(CONFIG_IPV6),) +obj-y += ipv6/ +endif obj-$(CONFIG_PACKET) += packet/ obj-$(CONFIG_NET_KEY) += key/ obj-$(CONFIG_BRIDGE) += bridge/ diff --git a/trunk/net/bridge/Kconfig b/trunk/net/bridge/Kconfig index 6dee7bf648a9..9190ae462cb4 100644 --- a/trunk/net/bridge/Kconfig +++ b/trunk/net/bridge/Kconfig @@ -6,7 +6,6 @@ config BRIDGE tristate "802.1d Ethernet Bridging" select LLC select STP - depends on IPV6 || IPV6=n ---help--- If you say Y here, then your Linux box will be able to act as an Ethernet bridge, which means that the different Ethernet segments it diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 6561021d22d1..8ae6631abcc2 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -1114,21 +1114,13 @@ EXPORT_SYMBOL(netdev_bonding_change); void dev_load(struct net *net, const char *name) { struct net_device *dev; - int no_module; rcu_read_lock(); dev = dev_get_by_name_rcu(net, name); rcu_read_unlock(); - no_module = !dev; - if (no_module && capable(CAP_NET_ADMIN)) - no_module = request_module("netdev-%s", name); - if (no_module && capable(CAP_SYS_MODULE)) { - if (!request_module("%s", name)) - pr_err("Loading kernel module for a network device " -"with CAP_SYS_MODULE (deprecated). Use CAP_NET_ADMIN and alias netdev-%s " -"instead\n", name); - } + if (!dev && capable(CAP_NET_ADMIN)) + request_module("%s", name); } EXPORT_SYMBOL(dev_load); diff --git a/trunk/net/core/pktgen.c b/trunk/net/core/pktgen.c index b5bada92f637..a9e7fc4c461f 100644 --- a/trunk/net/core/pktgen.c +++ b/trunk/net/core/pktgen.c @@ -3321,7 +3321,7 @@ static void show_results(struct pktgen_dev *pkt_dev, int nr_frags) pkt_dev->started_at); ktime_t idle = ns_to_ktime(pkt_dev->idle_acc); - p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags)\n", + p += sprintf(p, "OK: %llu(c%llu+d%llu) nsec, %llu (%dbyte,%dfrags)\n", (unsigned long long)ktime_to_us(elapsed), (unsigned long long)ktime_to_us(ktime_sub(elapsed, idle)), (unsigned long long)ktime_to_us(idle), diff --git a/trunk/net/core/scm.c b/trunk/net/core/scm.c index 4c1ef026d695..bbe454450801 100644 --- a/trunk/net/core/scm.c +++ b/trunk/net/core/scm.c @@ -95,7 +95,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) int fd = fdp[i]; struct file *file; - if (fd < 0 || !(file = fget_raw(fd))) + if (fd < 0 || !(file = fget(fd))) return -EBADF; *fpp++ = file; fpl->count++; diff --git a/trunk/net/ipv4/devinet.c b/trunk/net/ipv4/devinet.c index 036652c8166d..df4616fce929 100644 --- a/trunk/net/ipv4/devinet.c +++ b/trunk/net/ipv4/devinet.c @@ -670,7 +670,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) ifap = &ifa->ifa_next) { if (!strcmp(ifr.ifr_name, ifa->ifa_label) && sin_orig.sin_addr.s_addr == - ifa->ifa_local) { + ifa->ifa_address) { break; /* found */ } } @@ -1040,8 +1040,8 @@ static void inetdev_send_gratuitous_arp(struct net_device *dev, return; arp_send(ARPOP_REQUEST, ETH_P_ARP, - ifa->ifa_local, dev, - ifa->ifa_local, NULL, + ifa->ifa_address, dev, + ifa->ifa_address, NULL, dev->dev_addr, NULL); } diff --git a/trunk/net/ipv4/ip_gre.c b/trunk/net/ipv4/ip_gre.c index d1d0e2c256fc..6613edfac28c 100644 --- a/trunk/net/ipv4/ip_gre.c +++ b/trunk/net/ipv4/ip_gre.c @@ -1765,4 +1765,4 @@ module_exit(ipgre_fini); MODULE_LICENSE("GPL"); MODULE_ALIAS_RTNL_LINK("gre"); MODULE_ALIAS_RTNL_LINK("gretap"); -MODULE_ALIAS_NETDEV("gre0"); +MODULE_ALIAS("gre0"); diff --git a/trunk/net/ipv4/ipip.c b/trunk/net/ipv4/ipip.c index a5f58e7cbb26..988f52fba54a 100644 --- a/trunk/net/ipv4/ipip.c +++ b/trunk/net/ipv4/ipip.c @@ -913,4 +913,4 @@ static void __exit ipip_fini(void) module_init(ipip_init); module_exit(ipip_fini); MODULE_LICENSE("GPL"); -MODULE_ALIAS_NETDEV("tunl0"); +MODULE_ALIAS("tunl0"); diff --git a/trunk/net/ipv6/ip6_tunnel.c b/trunk/net/ipv6/ip6_tunnel.c index e528a42a52be..4f4483e697bd 100644 --- a/trunk/net/ipv6/ip6_tunnel.c +++ b/trunk/net/ipv6/ip6_tunnel.c @@ -57,7 +57,6 @@ MODULE_AUTHOR("Ville Nuorvala"); MODULE_DESCRIPTION("IPv6 tunneling device"); MODULE_LICENSE("GPL"); -MODULE_ALIAS_NETDEV("ip6tnl0"); #ifdef IP6_TNL_DEBUG #define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __func__) diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index e7db7014e89f..904312e25a3c 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -739,10 +739,8 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); - else if (!(rt->dst.flags & DST_HOST)) - nrt = rt6_alloc_clone(rt, &fl->fl6_dst); else - goto out2; + nrt = rt6_alloc_clone(rt, &fl->fl6_dst); dst_release(&rt->dst); rt = nrt ? : net->ipv6.ip6_null_entry; diff --git a/trunk/net/ipv6/sit.c b/trunk/net/ipv6/sit.c index d2c16e10f650..8ce38f10a547 100644 --- a/trunk/net/ipv6/sit.c +++ b/trunk/net/ipv6/sit.c @@ -1290,4 +1290,4 @@ static int __init sit_init(void) module_init(sit_init); module_exit(sit_cleanup); MODULE_LICENSE("GPL"); -MODULE_ALIAS_NETDEV("sit0"); +MODULE_ALIAS("sit0"); diff --git a/trunk/net/rds/ib_send.c b/trunk/net/rds/ib_send.c index c47a511f203d..71f373c421bc 100644 --- a/trunk/net/rds/ib_send.c +++ b/trunk/net/rds/ib_send.c @@ -551,10 +551,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, if (conn->c_loopback && rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) { rds_cong_map_updated(conn->c_fcong, ~(u64) 0); - scat = &rm->data.op_sg[sg]; - ret = sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; - ret = min_t(int, ret, scat->length - conn->c_xmit_data_off); - return ret; + return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; } /* FIXME we may overallocate here */ diff --git a/trunk/net/rds/loop.c b/trunk/net/rds/loop.c index bca6761a3ca2..aeec1d483b17 100644 --- a/trunk/net/rds/loop.c +++ b/trunk/net/rds/loop.c @@ -61,15 +61,10 @@ static int rds_loop_xmit(struct rds_connection *conn, struct rds_message *rm, unsigned int hdr_off, unsigned int sg, unsigned int off) { - struct scatterlist *sgp = &rm->data.op_sg[sg]; - int ret = sizeof(struct rds_header) + - be32_to_cpu(rm->m_inc.i_hdr.h_len); - /* Do not send cong updates to loopback */ if (rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) { rds_cong_map_updated(conn->c_fcong, ~(u64) 0); - ret = min_t(int, ret, sgp->length - conn->c_xmit_data_off); - goto out; + return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; } BUG_ON(hdr_off || sg || off); @@ -85,8 +80,8 @@ static int rds_loop_xmit(struct rds_connection *conn, struct rds_message *rm, NULL); rds_inc_put(&rm->m_inc); -out: - return ret; + + return sizeof(struct rds_header) + be32_to_cpu(rm->m_inc.i_hdr.h_len); } /* diff --git a/trunk/net/sunrpc/sched.c b/trunk/net/sunrpc/sched.c index 59e599498e37..243fc09b164e 100644 --- a/trunk/net/sunrpc/sched.c +++ b/trunk/net/sunrpc/sched.c @@ -252,37 +252,23 @@ static void rpc_set_active(struct rpc_task *task) /* * Mark an RPC call as having completed by clearing the 'active' bit - * and then waking up all tasks that were sleeping. */ -static int rpc_complete_task(struct rpc_task *task) +static void rpc_mark_complete_task(struct rpc_task *task) { - void *m = &task->tk_runstate; - wait_queue_head_t *wq = bit_waitqueue(m, RPC_TASK_ACTIVE); - struct wait_bit_key k = __WAIT_BIT_KEY_INITIALIZER(m, RPC_TASK_ACTIVE); - unsigned long flags; - int ret; - - spin_lock_irqsave(&wq->lock, flags); + smp_mb__before_clear_bit(); clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); - ret = atomic_dec_and_test(&task->tk_count); - if (waitqueue_active(wq)) - __wake_up_locked_key(wq, TASK_NORMAL, &k); - spin_unlock_irqrestore(&wq->lock, flags); - return ret; + smp_mb__after_clear_bit(); + wake_up_bit(&task->tk_runstate, RPC_TASK_ACTIVE); } /* * Allow callers to wait for completion of an RPC call - * - * Note the use of out_of_line_wait_on_bit() rather than wait_on_bit() - * to enforce taking of the wq->lock and hence avoid races with - * rpc_complete_task(). */ int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *)) { if (action == NULL) action = rpc_wait_bit_killable; - return out_of_line_wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, + return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, action, TASK_KILLABLE); } EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); @@ -871,67 +857,34 @@ static void rpc_async_release(struct work_struct *work) rpc_free_task(container_of(work, struct rpc_task, u.tk_work)); } -static void rpc_release_resources_task(struct rpc_task *task) +void rpc_put_task(struct rpc_task *task) { + if (!atomic_dec_and_test(&task->tk_count)) + return; + /* Release resources */ if (task->tk_rqstp) xprt_release(task); if (task->tk_msg.rpc_cred) put_rpccred(task->tk_msg.rpc_cred); rpc_task_release_client(task); -} - -static void rpc_final_put_task(struct rpc_task *task, - struct workqueue_struct *q) -{ - if (q != NULL) { + if (task->tk_workqueue != NULL) { INIT_WORK(&task->u.tk_work, rpc_async_release); - queue_work(q, &task->u.tk_work); + queue_work(task->tk_workqueue, &task->u.tk_work); } else rpc_free_task(task); } - -static void rpc_do_put_task(struct rpc_task *task, struct workqueue_struct *q) -{ - if (atomic_dec_and_test(&task->tk_count)) { - rpc_release_resources_task(task); - rpc_final_put_task(task, q); - } -} - -void rpc_put_task(struct rpc_task *task) -{ - rpc_do_put_task(task, NULL); -} EXPORT_SYMBOL_GPL(rpc_put_task); -void rpc_put_task_async(struct rpc_task *task) -{ - rpc_do_put_task(task, task->tk_workqueue); -} -EXPORT_SYMBOL_GPL(rpc_put_task_async); - static void rpc_release_task(struct rpc_task *task) { dprintk("RPC: %5u release task\n", task->tk_pid); BUG_ON (RPC_IS_QUEUED(task)); - rpc_release_resources_task(task); + /* Wake up anyone who is waiting for task completion */ + rpc_mark_complete_task(task); - /* - * Note: at this point we have been removed from rpc_clnt->cl_tasks, - * so it should be safe to use task->tk_count as a test for whether - * or not any other processes still hold references to our rpc_task. - */ - if (atomic_read(&task->tk_count) != 1 + !RPC_IS_ASYNC(task)) { - /* Wake up anyone who may be waiting for task completion */ - if (!rpc_complete_task(task)) - return; - } else { - if (!atomic_dec_and_test(&task->tk_count)) - return; - } - rpc_final_put_task(task, task->tk_workqueue); + rpc_put_task(task); } int rpciod_up(void) diff --git a/trunk/net/sunrpc/xprtrdma/svc_rdma_transport.c b/trunk/net/sunrpc/xprtrdma/svc_rdma_transport.c index 1a10dcd999ea..9df1eadc912a 100644 --- a/trunk/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/trunk/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -1335,7 +1335,6 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp, p, 0, length, DMA_FROM_DEVICE); if (ib_dma_mapping_error(xprt->sc_cm_id->device, ctxt->sge[0].addr)) { put_page(p); - svc_rdma_put_context(ctxt, 1); return; } atomic_inc(&xprt->sc_dma_used); diff --git a/trunk/net/sunrpc/xprtsock.c b/trunk/net/sunrpc/xprtsock.c index be96d429b475..c431f5a57960 100644 --- a/trunk/net/sunrpc/xprtsock.c +++ b/trunk/net/sunrpc/xprtsock.c @@ -1631,8 +1631,7 @@ static struct socket *xs_create_sock(struct rpc_xprt *xprt, } xs_reclassify_socket(family, sock); - err = xs_bind(transport, sock); - if (err) { + if (xs_bind(transport, sock)) { sock_release(sock); goto out; } diff --git a/trunk/net/unix/af_unix.c b/trunk/net/unix/af_unix.c index ba5b8c208498..dd419d286204 100644 --- a/trunk/net/unix/af_unix.c +++ b/trunk/net/unix/af_unix.c @@ -850,7 +850,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) * Get the parent directory, calculate the hash for last * component. */ - err = kern_path_parent(sunaddr->sun_path, &nd); + err = path_lookup(sunaddr->sun_path, LOOKUP_PARENT, &nd); if (err) goto out_mknod_parent; @@ -1724,11 +1724,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, msg->msg_namelen = 0; - err = mutex_lock_interruptible(&u->readlock); - if (err) { - err = sock_intr_errno(sock_rcvtimeo(sk, noblock)); - goto out; - } + mutex_lock(&u->readlock); skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) { @@ -1868,11 +1864,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, memset(&tmp_scm, 0, sizeof(tmp_scm)); } - err = mutex_lock_interruptible(&u->readlock); - if (err) { - err = sock_intr_errno(timeo); - goto out; - } + mutex_lock(&u->readlock); do { int chunk; @@ -1903,12 +1895,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, timeo = unix_stream_data_wait(sk, timeo); - if (signal_pending(current) - || mutex_lock_interruptible(&u->readlock)) { + if (signal_pending(current)) { err = sock_intr_errno(timeo); goto out; } - + mutex_lock(&u->readlock); continue; unlock: unix_state_unlock(sk); diff --git a/trunk/net/unix/garbage.c b/trunk/net/unix/garbage.c index b6f4b994eb35..f89f83bf828e 100644 --- a/trunk/net/unix/garbage.c +++ b/trunk/net/unix/garbage.c @@ -104,7 +104,7 @@ struct sock *unix_get_socket(struct file *filp) /* * Socket ? */ - if (S_ISSOCK(inode->i_mode) && !(filp->f_mode & FMODE_PATH)) { + if (S_ISSOCK(inode->i_mode)) { struct socket *sock = SOCKET_I(inode); struct sock *s = sock->sk; diff --git a/trunk/scripts/basic/fixdep.c b/trunk/scripts/basic/fixdep.c index 291228e25984..6c94c6ce2925 100644 --- a/trunk/scripts/basic/fixdep.c +++ b/trunk/scripts/basic/fixdep.c @@ -309,11 +309,6 @@ static void do_config_file(const char *filename) close(fd); } -/* - * Important: The below generated source_foo.o and deps_foo.o variable - * assignments are parsed not only by make, but also by the rather simple - * parser in scripts/mod/sumversion.c. - */ static void parse_dep_file(void *map, size_t len) { char *m = map; @@ -328,6 +323,7 @@ static void parse_dep_file(void *map, size_t len) exit(1); } memcpy(s, m, p-m); s[p-m] = 0; + printf("deps_%s := \\\n", target); m = p+1; clear_config(); @@ -347,15 +343,12 @@ static void parse_dep_file(void *map, size_t len) strrcmp(s, "arch/um/include/uml-config.h") && strrcmp(s, ".ver")) { /* - * Do not list the source file as dependency, so that - * kbuild is not confused if a .c file is rewritten - * into .S or vice versa. Storing it in source_* is - * needed for modpost to compute srcversions. + * Do not output the first dependency (the + * source file), so that kbuild is not confused + * if a .c file is rewritten into .S or vice + * versa. */ - if (first) { - printf("source_%s := %s\n\n", target, s); - printf("deps_%s := \\\n", target); - } else + if (!first) printf(" %s \\\n", s); do_config_file(s); } diff --git a/trunk/scripts/mod/sumversion.c b/trunk/scripts/mod/sumversion.c index 9dfcd6d988da..ecf9c7dc1825 100644 --- a/trunk/scripts/mod/sumversion.c +++ b/trunk/scripts/mod/sumversion.c @@ -300,8 +300,8 @@ static int is_static_library(const char *objfile) return 0; } -/* We have dir/file.o. Open dir/.file.o.cmd, look for source_ and deps_ line - * to figure out source files. */ +/* We have dir/file.o. Open dir/.file.o.cmd, look for deps_ line to + * figure out source file. */ static int parse_source_files(const char *objfile, struct md4_ctx *md) { char *cmd, *file, *line, *dir; @@ -340,21 +340,6 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md) */ while ((line = get_next_line(&pos, file, flen)) != NULL) { char* p = line; - - if (strncmp(line, "source_", sizeof("source_")-1) == 0) { - p = strrchr(line, ' '); - if (!p) { - warn("malformed line: %s\n", line); - goto out_file; - } - p++; - if (!parse_file(p, md)) { - warn("could not open %s: %s\n", - p, strerror(errno)); - goto out_file; - } - continue; - } if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) { check_files = 1; continue; diff --git a/trunk/sound/soc/codecs/wm8978.c b/trunk/sound/soc/codecs/wm8978.c index 8dfb0a0da673..4bbc3442703f 100644 --- a/trunk/sound/soc/codecs/wm8978.c +++ b/trunk/sound/soc/codecs/wm8978.c @@ -145,18 +145,18 @@ static const struct snd_kcontrol_new wm8978_snd_controls[] = { SOC_SINGLE("DAC Playback Limiter Threshold", WM8978_DAC_LIMITER_2, 4, 7, 0), SOC_SINGLE("DAC Playback Limiter Boost", - WM8978_DAC_LIMITER_2, 0, 12, 0), + WM8978_DAC_LIMITER_2, 0, 15, 0), SOC_ENUM("ALC Enable Switch", alc1), SOC_SINGLE("ALC Capture Min Gain", WM8978_ALC_CONTROL_1, 0, 7, 0), SOC_SINGLE("ALC Capture Max Gain", WM8978_ALC_CONTROL_1, 3, 7, 0), - SOC_SINGLE("ALC Capture Hold", WM8978_ALC_CONTROL_2, 4, 10, 0), + SOC_SINGLE("ALC Capture Hold", WM8978_ALC_CONTROL_2, 4, 7, 0), SOC_SINGLE("ALC Capture Target", WM8978_ALC_CONTROL_2, 0, 15, 0), SOC_ENUM("ALC Capture Mode", alc3), - SOC_SINGLE("ALC Capture Decay", WM8978_ALC_CONTROL_3, 4, 10, 0), - SOC_SINGLE("ALC Capture Attack", WM8978_ALC_CONTROL_3, 0, 10, 0), + SOC_SINGLE("ALC Capture Decay", WM8978_ALC_CONTROL_3, 4, 15, 0), + SOC_SINGLE("ALC Capture Attack", WM8978_ALC_CONTROL_3, 0, 15, 0), SOC_SINGLE("ALC Capture Noise Gate Switch", WM8978_NOISE_GATE, 3, 1, 0), SOC_SINGLE("ALC Capture Noise Gate Threshold", @@ -211,10 +211,8 @@ static const struct snd_kcontrol_new wm8978_snd_controls[] = { WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, 6, 1, 1), /* DAC / ADC oversampling */ - SOC_SINGLE("DAC 128x Oversampling Switch", WM8978_DAC_CONTROL, - 5, 1, 0), - SOC_SINGLE("ADC 128x Oversampling Switch", WM8978_ADC_CONTROL, - 5, 1, 0), + SOC_SINGLE("DAC 128x Oversampling Switch", WM8978_DAC_CONTROL, 8, 1, 0), + SOC_SINGLE("ADC 128x Oversampling Switch", WM8978_ADC_CONTROL, 8, 1, 0), }; /* Mixer #1: Output (OUT1, OUT2) Mixer: mix AUX, Input mixer output and DAC */ diff --git a/trunk/sound/soc/codecs/wm8994.c b/trunk/sound/soc/codecs/wm8994.c index c6c958ee5d59..4afbe3b2e443 100644 --- a/trunk/sound/soc/codecs/wm8994.c +++ b/trunk/sound/soc/codecs/wm8994.c @@ -1418,7 +1418,7 @@ SND_SOC_DAPM_DAC_E("DAC1R", NULL, SND_SOC_NOPM, 0, 0, static const struct snd_soc_dapm_widget wm8994_dac_widgets[] = { SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0), -SND_SOC_DAPM_DAC("DAC2R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), +SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0), SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), }; @@ -3325,12 +3325,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) case WM8958: snd_soc_add_controls(codec, wm8958_snd_controls, ARRAY_SIZE(wm8958_snd_controls)); - snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, - ARRAY_SIZE(wm8994_lateclk_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets, - ARRAY_SIZE(wm8994_adc_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets, - ARRAY_SIZE(wm8994_dac_widgets)); snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, ARRAY_SIZE(wm8958_dapm_widgets)); break; @@ -3356,8 +3350,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) } break; case WM8958: - snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon, - ARRAY_SIZE(wm8994_lateclk_intercon)); snd_soc_dapm_add_routes(dapm, wm8958_intercon, ARRAY_SIZE(wm8958_intercon)); break; diff --git a/trunk/sound/soc/omap/am3517evm.c b/trunk/sound/soc/omap/am3517evm.c index 73dde4a1adc3..161750443ebc 100644 --- a/trunk/sound/soc/omap/am3517evm.c +++ b/trunk/sound/soc/omap/am3517evm.c @@ -139,7 +139,7 @@ static struct snd_soc_dai_link am3517evm_dai = { .cpu_dai_name ="omap-mcbsp-dai.0", .codec_dai_name = "tlv320aic23-hifi", .platform_name = "omap-pcm-audio", - .codec_name = "tlv320aic23-codec.2-001a", + .codec_name = "tlv320aic23-codec", .init = am3517evm_aic23_init, .ops = &am3517evm_ops, }; diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index 1790f83ee665..25e54230cc6a 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -941,7 +941,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, } if (!list_empty(&pending)) - dapm_seq_run_coalesced(cur_dapm, &pending); + dapm_seq_run_coalesced(dapm, &pending); } static void dapm_widget_update(struct snd_soc_dapm_context *dapm) diff --git a/trunk/tools/perf/util/header.c b/trunk/tools/perf/util/header.c index 0866bcdb5e8e..f6a929e74981 100644 --- a/trunk/tools/perf/util/header.c +++ b/trunk/tools/perf/util/header.c @@ -270,15 +270,11 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, const char *name, bool is_kallsyms) { const size_t size = PATH_MAX; - char *realname, *filename = malloc(size), + char *realname = realpath(name, NULL), + *filename = malloc(size), *linkname = malloc(size), *targetname; int len, err = -1; - if (is_kallsyms) - realname = (char *)name; - else - realname = realpath(name, NULL); - if (realname == NULL || filename == NULL || linkname == NULL) goto out_free; @@ -310,8 +306,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, if (symlink(targetname, linkname) == 0) err = 0; out_free: - if (!is_kallsyms) - free(realname); + free(realname); free(filename); free(linkname); return err; diff --git a/trunk/tools/perf/util/symbol.c b/trunk/tools/perf/util/symbol.c index b1bf490aff88..7821d0e6866f 100644 --- a/trunk/tools/perf/util/symbol.c +++ b/trunk/tools/perf/util/symbol.c @@ -1836,7 +1836,7 @@ int dso__load_vmlinux(struct dso *self, struct map *map, int err = -1, fd; char symfs_vmlinux[PATH_MAX]; - snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", + snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s/%s", symbol_conf.symfs, vmlinux); fd = open(symfs_vmlinux, O_RDONLY); if (fd < 0)