From e9bd0a428a59f2f06be48d4cb42cb93ae43e946b Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 29 Apr 2011 22:35:33 -0400 Subject: [PATCH] --- yaml --- r: 245446 b: refs/heads/master c: 058e297d34a404caaa5ed277de15698d8dc43000 h: refs/heads/master v: v3 --- [refs] | 2 +- .../sound/alsa/SB-Live-mixer.txt | 6 +- trunk/MAINTAINERS | 2 +- trunk/arch/arm/mach-s3c2440/mach-gta02.c | 5 + trunk/arch/arm/mach-ux500/board-mop500.c | 19 +- trunk/arch/mips/include/asm/jump_label.h | 22 +- trunk/arch/s390/Kconfig | 1 - trunk/arch/s390/include/asm/jump_label.h | 37 -- trunk/arch/s390/kernel/Makefile | 2 +- trunk/arch/s390/kernel/jump_label.c | 59 -- trunk/arch/sparc/include/asm/jump_label.h | 25 +- trunk/arch/x86/include/asm/alternative.h | 3 +- trunk/arch/x86/include/asm/jump_label.h | 27 +- trunk/arch/x86/kernel/alternative.c | 2 +- trunk/arch/x86/kernel/apm_32.c | 5 + trunk/arch/x86/kernel/cpu/perf_event.c | 37 +- trunk/arch/x86/kernel/cpu/perf_event_intel.c | 38 +- trunk/arch/x86/kernel/cpu/perf_event_p4.c | 26 +- trunk/arch/x86/kernel/module.c | 1 - trunk/arch/xtensa/kernel/irq.c | 18 +- trunk/drivers/ata/ahci.c | 8 +- trunk/drivers/ata/ahci.h | 4 + trunk/drivers/ata/ata_piix.c | 8 + trunk/drivers/ata/libahci.c | 60 +- trunk/drivers/ata/libata-core.c | 3 +- trunk/drivers/ata/libata-eh.c | 6 +- trunk/drivers/ata/pata_at91.c | 22 +- trunk/drivers/base/syscore.c | 2 + trunk/drivers/parport/parport_pc.c | 8 +- trunk/drivers/rtc/rtc-coh901331.c | 4 +- trunk/drivers/tty/n_gsm.c | 8 +- trunk/drivers/tty/serial/imx.c | 3 +- trunk/drivers/xen/manage.c | 9 +- trunk/fs/dcache.c | 87 +-- trunk/fs/ecryptfs/crypto.c | 21 + trunk/fs/ecryptfs/ecryptfs_kernel.h | 7 +- trunk/fs/ecryptfs/file.c | 25 +- trunk/fs/ecryptfs/inode.c | 60 +- trunk/fs/ecryptfs/kthread.c | 6 +- trunk/fs/ecryptfs/main.c | 72 +- trunk/fs/ecryptfs/super.c | 16 +- trunk/fs/gfs2/glock.c | 6 +- trunk/fs/ubifs/recovery.c | 26 + trunk/fs/ubifs/super.c | 29 +- trunk/include/asm-generic/vmlinux.lds.h | 14 +- trunk/include/linux/bit_spinlock.h | 8 +- trunk/include/linux/dcache.h | 4 +- trunk/include/linux/dynamic_debug.h | 2 + trunk/include/linux/jump_label.h | 89 +-- trunk/include/linux/jump_label_ref.h | 44 ++ trunk/include/linux/libata.h | 3 +- trunk/include/linux/list_bl.h | 11 + trunk/include/linux/perf_event.h | 23 +- trunk/include/linux/security.h | 2 +- trunk/include/linux/tracepoint.h | 22 +- trunk/kernel/jump_label.c | 539 +++++++++------ trunk/kernel/kexec.c | 7 + trunk/kernel/perf_event.c | 4 +- trunk/kernel/power/hibernate.c | 10 +- trunk/kernel/power/suspend.c | 5 +- trunk/kernel/trace/Kconfig | 2 +- trunk/kernel/trace/ftrace.c | 12 +- trunk/kernel/trace/trace.c | 15 +- trunk/kernel/trace/trace_output.c | 3 - trunk/kernel/trace/trace_printk.c | 120 +--- trunk/kernel/tracepoint.c | 23 +- trunk/scripts/kconfig/conf.c | 2 +- trunk/security/capability.c | 2 +- trunk/security/security.c | 6 +- trunk/security/selinux/avc.c | 36 +- trunk/security/selinux/hooks.c | 24 +- trunk/security/selinux/include/avc.h | 18 +- trunk/security/smack/smack_lsm.c | 6 +- trunk/sound/pci/hda/hda_codec.c | 4 + trunk/sound/pci/hda/patch_realtek.c | 25 +- trunk/sound/soc/codecs/jz4740.c | 2 - trunk/sound/soc/codecs/sn95031.c | 2 +- trunk/sound/soc/codecs/wm8903.c | 38 +- trunk/sound/soc/codecs/wm8994.c | 16 + trunk/sound/soc/codecs/wm_hubs.c | 8 +- trunk/sound/soc/mid-x86/sst_platform.c | 10 +- trunk/sound/soc/samsung/pcm.c | 4 +- trunk/sound/soc/sh/fsi.c | 22 +- trunk/sound/soc/soc-core.c | 5 +- trunk/sound/soc/tegra/harmony.c | 1 + .../tools/perf/Documentation/perf-script.txt | 52 +- trunk/tools/perf/Makefile | 107 +-- trunk/tools/perf/builtin-script.c | 296 ++------- trunk/tools/perf/config/utilities.mak | 188 ------ .../tools/perf/{config => }/feature-tests.mak | 16 +- trunk/tools/perf/util/probe-finder.c | 72 -- trunk/tools/perf/util/probe-finder.h | 2 - trunk/tools/perf/util/session.c | 12 - trunk/tools/perf/util/session.h | 3 - trunk/tools/perf/util/symbol.c | 629 +++++++++--------- trunk/tools/perf/util/symbol.h | 78 ++- 96 files changed, 1599 insertions(+), 1886 deletions(-) delete mode 100644 trunk/arch/s390/include/asm/jump_label.h delete mode 100644 trunk/arch/s390/kernel/jump_label.c create mode 100644 trunk/include/linux/jump_label_ref.h delete mode 100644 trunk/tools/perf/config/utilities.mak rename trunk/tools/perf/{config => }/feature-tests.mak (86%) diff --git a/[refs] b/[refs] index 8be9bc2973e1..deba66c82c1a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 32673822e440eb92eb334631eb0a199d0c532d13 +refs/heads/master: 058e297d34a404caaa5ed277de15698d8dc43000 diff --git a/trunk/Documentation/sound/alsa/SB-Live-mixer.txt b/trunk/Documentation/sound/alsa/SB-Live-mixer.txt index f5639d40521d..f4b5988f450c 100644 --- a/trunk/Documentation/sound/alsa/SB-Live-mixer.txt +++ b/trunk/Documentation/sound/alsa/SB-Live-mixer.txt @@ -87,14 +87,14 @@ accumulator. ALSA uses accumulators 0 and 1 for left and right PCM. The result is forwarded to the ADC capture FIFO (thus to the standard capture PCM device). -name='Music Playback Volume',index=0 +name='Synth Playback Volume',index=0 This control is used to attenuate samples for left and right MIDI FX-bus accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples. The result samples are forwarded to the front DAC PCM slots of the AC97 codec. -name='Music Capture Volume',index=0 -name='Music Capture Switch',index=0 +name='Synth Capture Volume',index=0 +name='Synth Capture Switch',index=0 These controls are used to attenuate samples for left and right MIDI FX-bus accumulator. ALSA uses accumulators 4 and 5 for left and right PCM. diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 1e2724e55cf0..13803127b68f 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -5396,7 +5396,7 @@ F: drivers/media/video/*7146* F: include/media/*7146* SAMSUNG AUDIO (ASoC) DRIVERS -M: Jassi Brar +M: Jassi Brar L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Supported F: sound/soc/samsung diff --git a/trunk/arch/arm/mach-s3c2440/mach-gta02.c b/trunk/arch/arm/mach-s3c2440/mach-gta02.c index 0db2411ef4bb..716662008ce2 100644 --- a/trunk/arch/arm/mach-s3c2440/mach-gta02.c +++ b/trunk/arch/arm/mach-s3c2440/mach-gta02.c @@ -409,6 +409,10 @@ struct platform_device s3c24xx_pwm_device = { .num_resources = 0, }; +static struct platform_device gta02_dfbmcs320_device = { + .name = "dfbmcs320", +}; + static struct i2c_board_info gta02_i2c_devs[] __initdata = { { I2C_BOARD_INFO("pcf50633", 0x73), @@ -523,6 +527,7 @@ static struct platform_device *gta02_devices[] __initdata = { &s3c_device_iis, &samsung_asoc_dma, &s3c_device_i2c0, + >a02_dfbmcs320_device, >a02_buttons_device, &s3c_device_adc, &s3c_device_ts, diff --git a/trunk/arch/arm/mach-ux500/board-mop500.c b/trunk/arch/arm/mach-ux500/board-mop500.c index af913741e6ec..6e1907fa94f0 100644 --- a/trunk/arch/arm/mach-ux500/board-mop500.c +++ b/trunk/arch/arm/mach-ux500/board-mop500.c @@ -178,16 +178,15 @@ static struct i2c_board_info __initdata mop500_i2c0_devices[] = { .irq = NOMADIK_GPIO_TO_IRQ(217), .platform_data = &mop500_tc35892_data, }, -}; - -/* I2C0 devices only available prior to HREFv60 */ -static struct i2c_board_info __initdata mop500_i2c0_old_devices[] = { + /* I2C0 devices only available prior to HREFv60 */ { I2C_BOARD_INFO("tps61052", 0x33), .platform_data = &mop500_tps61052_data, }, }; +#define NUM_PRE_V60_I2C0_DEVICES 1 + static struct i2c_board_info __initdata mop500_i2c2_devices[] = { { /* lp5521 LED driver, 1st device */ @@ -425,6 +424,8 @@ static void __init mop500_uart_init(void) static void __init mop500_init_machine(void) { + int i2c0_devs; + /* * The HREFv60 board removed a GPIO expander and routed * all these GPIO pins to the internal GPIO controller @@ -448,11 +449,11 @@ static void __init mop500_init_machine(void) platform_device_register(&ab8500_device); - i2c_register_board_info(0, mop500_i2c0_devices, - ARRAY_SIZE(mop500_i2c0_devices)); - if (!machine_is_hrefv60()) - i2c_register_board_info(0, mop500_i2c0_old_devices, - ARRAY_SIZE(mop500_i2c0_old_devices)); + i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); + if (machine_is_hrefv60()) + i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES; + + i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); i2c_register_board_info(2, mop500_i2c2_devices, ARRAY_SIZE(mop500_i2c2_devices)); } diff --git a/trunk/arch/mips/include/asm/jump_label.h b/trunk/arch/mips/include/asm/jump_label.h index 1881b316ca45..7622ccf75076 100644 --- a/trunk/arch/mips/include/asm/jump_label.h +++ b/trunk/arch/mips/include/asm/jump_label.h @@ -20,18 +20,16 @@ #define WORD_INSN ".word" #endif -static __always_inline bool arch_static_branch(struct jump_label_key *key) -{ - asm goto("1:\tnop\n\t" - "nop\n\t" - ".pushsection __jump_table, \"aw\"\n\t" - WORD_INSN " 1b, %l[l_yes], %0\n\t" - ".popsection\n\t" - : : "i" (key) : : l_yes); - return false; -l_yes: - return true; -} +#define JUMP_LABEL(key, label) \ + do { \ + asm goto("1:\tnop\n\t" \ + "nop\n\t" \ + ".pushsection __jump_table, \"a\"\n\t" \ + WORD_INSN " 1b, %l[" #label "], %0\n\t" \ + ".popsection\n\t" \ + : : "i" (key) : : label); \ + } while (0) + #endif /* __KERNEL__ */ diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index 4a7f14079e03..2508a6f31588 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -88,7 +88,6 @@ config S390 select HAVE_KERNEL_XZ select HAVE_GET_USER_PAGES_FAST select HAVE_ARCH_MUTEX_CPU_RELAX - select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 select ARCH_INLINE_SPIN_TRYLOCK select ARCH_INLINE_SPIN_TRYLOCK_BH select ARCH_INLINE_SPIN_LOCK diff --git a/trunk/arch/s390/include/asm/jump_label.h b/trunk/arch/s390/include/asm/jump_label.h deleted file mode 100644 index 95a6cf2b5b67..000000000000 --- a/trunk/arch/s390/include/asm/jump_label.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _ASM_S390_JUMP_LABEL_H -#define _ASM_S390_JUMP_LABEL_H - -#include - -#define JUMP_LABEL_NOP_SIZE 6 - -#ifdef CONFIG_64BIT -#define ASM_PTR ".quad" -#define ASM_ALIGN ".balign 8" -#else -#define ASM_PTR ".long" -#define ASM_ALIGN ".balign 4" -#endif - -static __always_inline bool arch_static_branch(struct jump_label_key *key) -{ - asm goto("0: brcl 0,0\n" - ".pushsection __jump_table, \"aw\"\n" - ASM_ALIGN "\n" - ASM_PTR " 0b, %l[label], %0\n" - ".popsection\n" - : : "X" (key) : : label); - return false; -label: - return true; -} - -typedef unsigned long jump_label_t; - -struct jump_entry { - jump_label_t code; - jump_label_t target; - jump_label_t key; -}; - -#endif diff --git a/trunk/arch/s390/kernel/Makefile b/trunk/arch/s390/kernel/Makefile index 5ff15dacb571..64230bc392fa 100644 --- a/trunk/arch/s390/kernel/Makefile +++ b/trunk/arch/s390/kernel/Makefile @@ -23,7 +23,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \ processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \ - vdso.o vtime.o sysinfo.o nmi.o sclp.o jump_label.o + vdso.o vtime.o sysinfo.o nmi.o sclp.o obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) diff --git a/trunk/arch/s390/kernel/jump_label.c b/trunk/arch/s390/kernel/jump_label.c deleted file mode 100644 index 44cc06bedf77..000000000000 --- a/trunk/arch/s390/kernel/jump_label.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Jump label s390 support - * - * Copyright IBM Corp. 2011 - * Author(s): Jan Glauber - */ -#include -#include -#include -#include -#include - -#ifdef HAVE_JUMP_LABEL - -struct insn { - u16 opcode; - s32 offset; -} __packed; - -struct insn_args { - unsigned long *target; - struct insn *insn; - ssize_t size; -}; - -static int __arch_jump_label_transform(void *data) -{ - struct insn_args *args = data; - int rc; - - rc = probe_kernel_write(args->target, args->insn, args->size); - WARN_ON_ONCE(rc < 0); - return 0; -} - -void arch_jump_label_transform(struct jump_entry *entry, - enum jump_label_type type) -{ - struct insn_args args; - struct insn insn; - - if (type == JUMP_LABEL_ENABLE) { - /* brcl 15,offset */ - insn.opcode = 0xc0f4; - insn.offset = (entry->target - entry->code) >> 1; - } else { - /* brcl 0,0 */ - insn.opcode = 0xc004; - insn.offset = 0; - } - - args.target = (void *) entry->code; - args.insn = &insn; - args.size = JUMP_LABEL_NOP_SIZE; - - stop_machine(__arch_jump_label_transform, &args, NULL); -} - -#endif diff --git a/trunk/arch/sparc/include/asm/jump_label.h b/trunk/arch/sparc/include/asm/jump_label.h index fc73a82366f8..427d4684e0d2 100644 --- a/trunk/arch/sparc/include/asm/jump_label.h +++ b/trunk/arch/sparc/include/asm/jump_label.h @@ -7,20 +7,17 @@ #define JUMP_LABEL_NOP_SIZE 4 -static __always_inline bool arch_static_branch(struct jump_label_key *key) -{ - asm goto("1:\n\t" - "nop\n\t" - "nop\n\t" - ".pushsection __jump_table, \"aw\"\n\t" - ".align 4\n\t" - ".word 1b, %l[l_yes], %c0\n\t" - ".popsection \n\t" - : : "i" (key) : : l_yes); - return false; -l_yes: - return true; -} +#define JUMP_LABEL(key, label) \ + do { \ + asm goto("1:\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + ".pushsection __jump_table, \"a\"\n\t"\ + ".align 4\n\t" \ + ".word 1b, %l[" #label "], %c0\n\t" \ + ".popsection \n\t" \ + : : "i" (key) : : label);\ + } while (0) #endif /* __KERNEL__ */ diff --git a/trunk/arch/x86/include/asm/alternative.h b/trunk/arch/x86/include/asm/alternative.h index 8cdd1e247975..13009d1af99a 100644 --- a/trunk/arch/x86/include/asm/alternative.h +++ b/trunk/arch/x86/include/asm/alternative.h @@ -4,6 +4,7 @@ #include #include #include +#include #include /* @@ -190,7 +191,7 @@ extern void *text_poke(void *addr, const void *opcode, size_t len); extern void *text_poke_smp(void *addr, const void *opcode, size_t len); extern void text_poke_smp_batch(struct text_poke_param *params, int n); -#if defined(CONFIG_DYNAMIC_FTRACE) || defined(CONFIG_JUMP_LABEL) +#if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL) #define IDEAL_NOP_SIZE_5 5 extern unsigned char ideal_nop5[IDEAL_NOP_SIZE_5]; extern void arch_init_ideal_nop5(void); diff --git a/trunk/arch/x86/include/asm/jump_label.h b/trunk/arch/x86/include/asm/jump_label.h index a32b18ce6ead..574dbc22893a 100644 --- a/trunk/arch/x86/include/asm/jump_label.h +++ b/trunk/arch/x86/include/asm/jump_label.h @@ -5,25 +5,20 @@ #include #include -#include #define JUMP_LABEL_NOP_SIZE 5 -#define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t" - -static __always_inline bool arch_static_branch(struct jump_label_key *key) -{ - asm goto("1:" - JUMP_LABEL_INITIAL_NOP - ".pushsection __jump_table, \"aw\" \n\t" - _ASM_ALIGN "\n\t" - _ASM_PTR "1b, %l[l_yes], %c0 \n\t" - ".popsection \n\t" - : : "i" (key) : : l_yes); - return false; -l_yes: - return true; -} +# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t" + +# define JUMP_LABEL(key, label) \ + do { \ + asm goto("1:" \ + JUMP_LABEL_INITIAL_NOP \ + ".pushsection __jump_table, \"aw\" \n\t"\ + _ASM_PTR "1b, %l[" #label "], %c0 \n\t" \ + ".popsection \n\t" \ + : : "i" (key) : : label); \ + } while (0) #endif /* __KERNEL__ */ diff --git a/trunk/arch/x86/kernel/alternative.c b/trunk/arch/x86/kernel/alternative.c index 651454b0c811..4a234677e213 100644 --- a/trunk/arch/x86/kernel/alternative.c +++ b/trunk/arch/x86/kernel/alternative.c @@ -679,7 +679,7 @@ void __kprobes text_poke_smp_batch(struct text_poke_param *params, int n) __stop_machine(stop_machine_text_poke, (void *)&tpp, NULL); } -#if defined(CONFIG_DYNAMIC_FTRACE) || defined(CONFIG_JUMP_LABEL) +#if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL) #ifdef CONFIG_X86_64 unsigned char ideal_nop5[5] = { 0x66, 0x66, 0x66, 0x66, 0x90 }; diff --git a/trunk/arch/x86/kernel/apm_32.c b/trunk/arch/x86/kernel/apm_32.c index 0b4be431c620..adee12e0da1f 100644 --- a/trunk/arch/x86/kernel/apm_32.c +++ b/trunk/arch/x86/kernel/apm_32.c @@ -228,6 +228,7 @@ #include #include #include +#include #include #include @@ -1238,6 +1239,7 @@ static int suspend(int vetoable) local_irq_disable(); sysdev_suspend(PMSG_SUSPEND); + syscore_suspend(); local_irq_enable(); @@ -1255,6 +1257,7 @@ static int suspend(int vetoable) apm_error("suspend", err); err = (err == APM_SUCCESS) ? 0 : -EIO; + syscore_resume(); sysdev_resume(); local_irq_enable(); @@ -1280,6 +1283,7 @@ static void standby(void) local_irq_disable(); sysdev_suspend(PMSG_SUSPEND); + syscore_suspend(); local_irq_enable(); err = set_system_power_state(APM_STATE_STANDBY); @@ -1287,6 +1291,7 @@ static void standby(void) apm_error("standby", err); local_irq_disable(); + syscore_resume(); sysdev_resume(); local_irq_enable(); diff --git a/trunk/arch/x86/kernel/cpu/perf_event.c b/trunk/arch/x86/kernel/cpu/perf_event.c index 224a84f7080c..e638689279d3 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event.c +++ b/trunk/arch/x86/kernel/cpu/perf_event.c @@ -31,7 +31,6 @@ #include #include #include -#include #if 0 #undef wrmsrl @@ -364,18 +363,12 @@ x86_perf_event_update(struct perf_event *event) return new_raw_count; } +/* using X86_FEATURE_PERFCTR_CORE to later implement ALTERNATIVE() here */ static inline int x86_pmu_addr_offset(int index) { - int offset; - - /* offset = X86_FEATURE_PERFCTR_CORE ? index << 1 : index */ - alternative_io(ASM_NOP2, - "shll $1, %%eax", - X86_FEATURE_PERFCTR_CORE, - "=a" (offset), - "a" (index)); - - return offset; + if (boot_cpu_has(X86_FEATURE_PERFCTR_CORE)) + return index << 1; + return index; } static inline unsigned int x86_pmu_config_addr(int index) @@ -593,8 +586,12 @@ static int x86_setup_perfctr(struct perf_event *event) return -EOPNOTSUPP; } + /* + * Do not allow config1 (extended registers) to propagate, + * there's no sane user-space generalization yet: + */ if (attr->type == PERF_TYPE_RAW) - return x86_pmu_extra_regs(event->attr.config, event); + return 0; if (attr->type == PERF_TYPE_HW_CACHE) return set_ext_hw_attr(hwc, event); @@ -616,8 +613,8 @@ static int x86_setup_perfctr(struct perf_event *event) /* * Branch tracing: */ - if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) && - (hwc->sample_period == 1)) { + if (attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS && + !attr->freq && hwc->sample_period == 1) { /* BTS is not supported by this architecture. */ if (!x86_pmu.bts_active) return -EOPNOTSUPP; @@ -1291,6 +1288,16 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) cpuc = &__get_cpu_var(cpu_hw_events); + /* + * Some chipsets need to unmask the LVTPC in a particular spot + * inside the nmi handler. As a result, the unmasking was pushed + * into all the nmi handlers. + * + * This generic handler doesn't seem to have any issues where the + * unmasking occurs so it was left at the top. + */ + apic_write(APIC_LVTPC, APIC_DM_NMI); + for (idx = 0; idx < x86_pmu.num_counters; idx++) { if (!test_bit(idx, cpuc->active_mask)) { /* @@ -1377,8 +1384,6 @@ perf_event_nmi_handler(struct notifier_block *self, return NOTIFY_DONE; } - apic_write(APIC_LVTPC, APIC_DM_NMI); - handled = x86_pmu.handle_irq(args->regs); if (!handled) return NOTIFY_DONE; diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel.c b/trunk/arch/x86/kernel/cpu/perf_event_intel.c index 8fc2b2cee1da..e61539b07d2c 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel.c @@ -25,7 +25,7 @@ struct intel_percore { /* * Intel PerfMon, used on Core and later. */ -static const u64 intel_perfmon_event_map[] = +static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly = { [PERF_COUNT_HW_CPU_CYCLES] = 0x003c, [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, @@ -391,12 +391,12 @@ static __initconst const u64 nehalem_hw_cache_event_ids { [ C(L1D) ] = { [ C(OP_READ) ] = { - [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI */ - [ C(RESULT_MISS) ] = 0x0140, /* L1D_CACHE_LD.I_STATE */ + [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS */ + [ C(RESULT_MISS) ] = 0x0151, /* L1D.REPL */ }, [ C(OP_WRITE) ] = { - [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI */ - [ C(RESULT_MISS) ] = 0x0141, /* L1D_CACHE_ST.I_STATE */ + [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES */ + [ C(RESULT_MISS) ] = 0x0251, /* L1D.M_REPL */ }, [ C(OP_PREFETCH) ] = { [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS */ @@ -933,6 +933,16 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) cpuc = &__get_cpu_var(cpu_hw_events); + /* + * Some chipsets need to unmask the LVTPC in a particular spot + * inside the nmi handler. As a result, the unmasking was pushed + * into all the nmi handlers. + * + * This handler doesn't seem to have any issues with the unmasking + * so it was left at the top. + */ + apic_write(APIC_LVTPC, APIC_DM_NMI); + intel_pmu_disable_all(); handled = intel_pmu_drain_bts_buffer(); status = intel_pmu_get_status(); @@ -998,6 +1008,9 @@ intel_bts_constraints(struct perf_event *event) struct hw_perf_event *hwc = &event->hw; unsigned int hw_event, bts_event; + if (event->attr.freq) + return NULL; + hw_event = hwc->config & INTEL_ARCH_EVENT_MASK; bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS); @@ -1305,7 +1318,7 @@ static void intel_clovertown_quirks(void) * AJ106 could possibly be worked around by not allowing LBR * usage from PEBS, including the fixup. * AJ68 could possibly be worked around by always programming - * a pebs_event_reset[0] value and coping with the lost events. + * a pebs_event_reset[0] value and coping with the lost events. * * But taken together it might just make sense to not enable PEBS on * these chips. @@ -1409,6 +1422,18 @@ static __init int intel_pmu_init(void) x86_pmu.percore_constraints = intel_nehalem_percore_constraints; x86_pmu.enable_all = intel_pmu_nhm_enable_all; x86_pmu.extra_regs = intel_nehalem_extra_regs; + + if (ebx & 0x40) { + /* + * Erratum AAJ80 detected, we work it around by using + * the BR_MISP_EXEC.ANY event. This will over-count + * branch-misses, but it's still much better than the + * architectural event which is often completely bogus: + */ + intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89; + + pr_cont("erratum AAJ80 worked around, "); + } pr_cont("Nehalem events, "); break; @@ -1425,6 +1450,7 @@ static __init int intel_pmu_init(void) case 37: /* 32 nm nehalem, "Clarkdale" */ case 44: /* 32 nm nehalem, "Gulftown" */ + case 47: /* 32 nm Xeon E7 */ memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids, sizeof(hw_cache_event_ids)); memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs, diff --git a/trunk/arch/x86/kernel/cpu/perf_event_p4.c b/trunk/arch/x86/kernel/cpu/perf_event_p4.c index f4c1da2f9352..e93fcd55fae1 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_p4.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_p4.c @@ -468,7 +468,7 @@ static struct p4_event_bind p4_event_bind_map[] = { .opcode = P4_OPCODE(P4_EVENT_MISPRED_BRANCH_RETIRED), .escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 }, .escr_emask = - P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS), + P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS), .cntr = { {12, 13, 16}, {14, 15, 17} }, }, [P4_EVENT_X87_ASSIST] = { @@ -912,7 +912,8 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) int idx, handled = 0; u64 val; - perf_sample_data_init(&data, 0); + data.addr = 0; + data.raw = NULL; cpuc = &__get_cpu_var(cpu_hw_events); @@ -946,14 +947,23 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) if (!x86_perf_event_set_period(event)) continue; if (perf_event_overflow(event, 1, &data, regs)) - p4_pmu_disable_event(event); + x86_pmu_stop(event, 0); } - if (handled) { - /* p4 quirk: unmask it again */ - apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); + if (handled) inc_irq_stat(apic_perf_irqs); - } + + /* + * When dealing with the unmasking of the LVTPC on P4 perf hw, it has + * been observed that the OVF bit flag has to be cleared first _before_ + * the LVTPC can be unmasked. + * + * The reason is the NMI line will continue to be asserted while the OVF + * bit is set. This causes a second NMI to generate if the LVTPC is + * unmasked before the OVF bit is cleared, leading to unknown NMI + * messages. + */ + apic_write(APIC_LVTPC, APIC_DM_NMI); return handled; } @@ -1187,7 +1197,7 @@ static __init int p4_pmu_init(void) { unsigned int low, high; - /* If we get stripped -- indexing fails */ + /* If we get stripped -- indexig fails */ BUILD_BUG_ON(ARCH_P4_MAX_CCCR > X86_PMC_MAX_GENERIC); rdmsr(MSR_IA32_MISC_ENABLE, low, high); diff --git a/trunk/arch/x86/kernel/module.c b/trunk/arch/x86/kernel/module.c index 52f256f2cc81..ab23f1ad4bf1 100644 --- a/trunk/arch/x86/kernel/module.c +++ b/trunk/arch/x86/kernel/module.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/trunk/arch/xtensa/kernel/irq.c b/trunk/arch/xtensa/kernel/irq.c index d77089df412e..4340ee076bd5 100644 --- a/trunk/arch/xtensa/kernel/irq.c +++ b/trunk/arch/xtensa/kernel/irq.c @@ -64,47 +64,41 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs) int arch_show_interrupts(struct seq_file *p, int prec) { - int j; - - seq_printf(p, "%*s: ", prec, "NMI"); - for_each_online_cpu(j) - seq_printf(p, "%10u ", nmi_count(j)); - seq_putc(p, '\n'); seq_printf(p, "%*s: ", prec, "ERR"); seq_printf(p, "%10u\n", atomic_read(&irq_err_count)); return 0; } -static void xtensa_irq_mask(struct irq_chip *d) +static void xtensa_irq_mask(struct irq_data *d) { cached_irq_mask &= ~(1 << d->irq); set_sr (cached_irq_mask, INTENABLE); } -static void xtensa_irq_unmask(struct irq_chip *d) +static void xtensa_irq_unmask(struct irq_data *d) { cached_irq_mask |= 1 << d->irq; set_sr (cached_irq_mask, INTENABLE); } -static void xtensa_irq_enable(struct irq_chip *d) +static void xtensa_irq_enable(struct irq_data *d) { variant_irq_enable(d->irq); xtensa_irq_unmask(d->irq); } -static void xtensa_irq_disable(struct irq_chip *d) +static void xtensa_irq_disable(struct irq_data *d) { xtensa_irq_mask(d->irq); variant_irq_disable(d->irq); } -static void xtensa_irq_ack(struct irq_chip *d) +static void xtensa_irq_ack(struct irq_data *d) { set_sr(1 << d->irq, INTCLEAR); } -static int xtensa_irq_retrigger(struct irq_chip *d) +static int xtensa_irq_retrigger(struct irq_data *d) { set_sr (1 << d->irq, INTSET); return 1; diff --git a/trunk/drivers/ata/ahci.c b/trunk/drivers/ata/ahci.c index 39d829cd82dd..71afe0371311 100644 --- a/trunk/drivers/ata/ahci.c +++ b/trunk/drivers/ata/ahci.c @@ -150,7 +150,7 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ), - .flags = AHCI_FLAG_COMMON, + .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, @@ -261,6 +261,12 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ + { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ + { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */ + { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, diff --git a/trunk/drivers/ata/ahci.h b/trunk/drivers/ata/ahci.h index 39865009c251..12c5282e7fca 100644 --- a/trunk/drivers/ata/ahci.h +++ b/trunk/drivers/ata/ahci.h @@ -229,6 +229,10 @@ enum { EM_CTL_ALHD = (1 << 26), /* Activity LED */ EM_CTL_XMT = (1 << 25), /* Transmit Only */ EM_CTL_SMB = (1 << 24), /* Single Message Buffer */ + EM_CTL_SGPIO = (1 << 19), /* SGPIO messages supported */ + EM_CTL_SES = (1 << 18), /* SES-2 messages supported */ + EM_CTL_SAFTE = (1 << 17), /* SAF-TE messages supported */ + EM_CTL_LED = (1 << 16), /* LED messages supported */ /* em message type */ EM_MSG_TYPE_LED = (1 << 0), /* LED */ diff --git a/trunk/drivers/ata/ata_piix.c b/trunk/drivers/ata/ata_piix.c index 0bc3fd6c3fdb..6f6e7718b05c 100644 --- a/trunk/drivers/ata/ata_piix.c +++ b/trunk/drivers/ata/ata_piix.c @@ -309,6 +309,14 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, /* SATA Controller IDE (PBG) */ { 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Panther Point) */ + { 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, + /* SATA Controller IDE (Panther Point) */ + { 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, + /* SATA Controller IDE (Panther Point) */ + { 0x8086, 0x1e08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Panther Point) */ + { 0x8086, 0x1e09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, { } /* terminate list */ }; diff --git a/trunk/drivers/ata/libahci.c b/trunk/drivers/ata/libahci.c index 26d452339e98..ff9d832a163d 100644 --- a/trunk/drivers/ata/libahci.c +++ b/trunk/drivers/ata/libahci.c @@ -109,6 +109,8 @@ static ssize_t ahci_read_em_buffer(struct device *dev, static ssize_t ahci_store_em_buffer(struct device *dev, struct device_attribute *attr, const char *buf, size_t size); +static ssize_t ahci_show_em_supported(struct device *dev, + struct device_attribute *attr, char *buf); static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL); static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL); @@ -116,6 +118,7 @@ static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL); static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO, ahci_read_em_buffer, ahci_store_em_buffer); +static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL); struct device_attribute *ahci_shost_attrs[] = { &dev_attr_link_power_management_policy, @@ -126,6 +129,7 @@ struct device_attribute *ahci_shost_attrs[] = { &dev_attr_ahci_host_version, &dev_attr_ahci_port_cmd, &dev_attr_em_buffer, + &dev_attr_em_message_supported, NULL }; EXPORT_SYMBOL_GPL(ahci_shost_attrs); @@ -343,6 +347,24 @@ static ssize_t ahci_store_em_buffer(struct device *dev, return size; } +static ssize_t ahci_show_em_supported(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct ata_port *ap = ata_shost_to_port(shost); + struct ahci_host_priv *hpriv = ap->host->private_data; + void __iomem *mmio = hpriv->mmio; + u32 em_ctl; + + em_ctl = readl(mmio + HOST_EM_CTL); + + return sprintf(buf, "%s%s%s%s\n", + em_ctl & EM_CTL_LED ? "led " : "", + em_ctl & EM_CTL_SAFTE ? "saf-te " : "", + em_ctl & EM_CTL_SES ? "ses-2 " : "", + em_ctl & EM_CTL_SGPIO ? "sgpio " : ""); +} + /** * ahci_save_initial_config - Save and fixup initial config values * @dev: target AHCI device @@ -539,6 +561,27 @@ void ahci_start_engine(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); u32 tmp; + u8 status; + + status = readl(port_mmio + PORT_TFDATA) & 0xFF; + + /* + * At end of section 10.1 of AHCI spec (rev 1.3), it states + * Software shall not set PxCMD.ST to 1 until it is determined + * that a functoinal device is present on the port as determined by + * PxTFD.STS.BSY=0, PxTFD.STS.DRQ=0 and PxSSTS.DET=3h + * + * Even though most AHCI host controllers work without this check, + * specific controller will fail under this condition + */ + if (status & (ATA_BUSY | ATA_DRQ)) + return; + else { + ahci_scr_read(&ap->link, SCR_STATUS, &tmp); + + if ((tmp & 0xf) != 0x3) + return; + } /* start DMA */ tmp = readl(port_mmio + PORT_CMD); @@ -1897,7 +1940,17 @@ static void ahci_pmp_attach(struct ata_port *ap) ahci_enable_fbs(ap); pp->intr_mask |= PORT_IRQ_BAD_PMP; - writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); + + /* + * We must not change the port interrupt mask register if the + * port is marked frozen, the value in pp->intr_mask will be + * restored later when the port is thawed. + * + * Note that during initialization, the port is marked as + * frozen since the irq handler is not yet registered. + */ + if (!(ap->pflags & ATA_PFLAG_FROZEN)) + writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); } static void ahci_pmp_detach(struct ata_port *ap) @@ -1913,7 +1966,10 @@ static void ahci_pmp_detach(struct ata_port *ap) writel(cmd, port_mmio + PORT_CMD); pp->intr_mask &= ~PORT_IRQ_BAD_PMP; - writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); + + /* see comment above in ahci_pmp_attach() */ + if (!(ap->pflags & ATA_PFLAG_FROZEN)) + writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); } int ahci_port_resume(struct ata_port *ap) diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index 423c0a6952b2..76c3c15cb1e6 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -4139,6 +4139,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { */ { "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER }, { "PIONEER DVD-RW DVR-212D", "1.28", ATA_HORKAGE_NOSETXFER }, + { "PIONEER DVD-RW DVR-216D", "1.08", ATA_HORKAGE_NOSETXFER }, /* End Marker */ { } @@ -5480,7 +5481,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host) if (!ap) return NULL; - ap->pflags |= ATA_PFLAG_INITIALIZING; + ap->pflags |= ATA_PFLAG_INITIALIZING | ATA_PFLAG_FROZEN; ap->lock = &host->lock; ap->print_id = -1; ap->host = host; diff --git a/trunk/drivers/ata/libata-eh.c b/trunk/drivers/ata/libata-eh.c index 88cd22fa65cd..f26f2fe3480a 100644 --- a/trunk/drivers/ata/libata-eh.c +++ b/trunk/drivers/ata/libata-eh.c @@ -3316,6 +3316,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, struct ata_eh_context *ehc = &link->eh_context; struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL; enum ata_lpm_policy old_policy = link->lpm_policy; + bool no_dipm = ap->flags & ATA_FLAG_NO_DIPM; unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM; unsigned int err_mask; int rc; @@ -3332,7 +3333,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, */ ata_for_each_dev(dev, link, ENABLED) { bool hipm = ata_id_has_hipm(dev->id); - bool dipm = ata_id_has_dipm(dev->id); + bool dipm = ata_id_has_dipm(dev->id) && !no_dipm; /* find the first enabled and LPM enabled devices */ if (!link_dev) @@ -3389,7 +3390,8 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, /* host config updated, enable DIPM if transitioning to MIN_POWER */ ata_for_each_dev(dev, link, ENABLED) { - if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) { + if (policy == ATA_LPM_MIN_POWER && !no_dipm && + ata_id_has_dipm(dev->id)) { err_mask = ata_dev_set_feature(dev, SETFEATURES_SATA_ENABLE, SATA_DIPM); if (err_mask && err_mask != AC_ERR_DEV) { diff --git a/trunk/drivers/ata/pata_at91.c b/trunk/drivers/ata/pata_at91.c index 0da0dcc7dd08..a5fdbdcb0faf 100644 --- a/trunk/drivers/ata/pata_at91.c +++ b/trunk/drivers/ata/pata_at91.c @@ -33,11 +33,12 @@ #define DRV_NAME "pata_at91" -#define DRV_VERSION "0.1" +#define DRV_VERSION "0.2" #define CF_IDE_OFFSET 0x00c00000 #define CF_ALT_IDE_OFFSET 0x00e00000 #define CF_IDE_RES_SIZE 0x08 +#define NCS_RD_PULSE_LIMIT 0x3f /* maximal value for pulse bitfields */ struct at91_ide_info { unsigned long mode; @@ -49,8 +50,18 @@ struct at91_ide_info { void __iomem *alt_addr; }; -static const struct ata_timing initial_timing = - {XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0}; +static const struct ata_timing initial_timing = { + .mode = XFER_PIO_0, + .setup = 70, + .act8b = 290, + .rec8b = 240, + .cyc8b = 600, + .active = 165, + .recover = 150, + .dmack_hold = 0, + .cycle = 600, + .udma = 0 +}; static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz) { @@ -109,6 +120,11 @@ static void set_smc_timing(struct device *dev, /* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */ ncs_read_setup = 1; ncs_read_pulse = read_cycle - 2; + if (ncs_read_pulse > NCS_RD_PULSE_LIMIT) { + ncs_read_pulse = NCS_RD_PULSE_LIMIT; + dev_warn(dev, "ncs_read_pulse limited to maximal value %lu\n", + ncs_read_pulse); + } /* Write timings same as read timings */ write_cycle = read_cycle; diff --git a/trunk/drivers/base/syscore.c b/trunk/drivers/base/syscore.c index 90af2943f9e4..c126db3cb7d1 100644 --- a/trunk/drivers/base/syscore.c +++ b/trunk/drivers/base/syscore.c @@ -73,6 +73,7 @@ int syscore_suspend(void) return ret; } +EXPORT_SYMBOL_GPL(syscore_suspend); /** * syscore_resume - Execute all the registered system core resume callbacks. @@ -95,6 +96,7 @@ void syscore_resume(void) "Interrupts enabled after %pF\n", ops->resume); } } +EXPORT_SYMBOL_GPL(syscore_resume); #endif /* CONFIG_PM_SLEEP */ /** diff --git a/trunk/drivers/parport/parport_pc.c b/trunk/drivers/parport/parport_pc.c index a3755ffc03d4..bc8ce48f0778 100644 --- a/trunk/drivers/parport/parport_pc.c +++ b/trunk/drivers/parport/parport_pc.c @@ -2550,7 +2550,6 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, const struct parport_pc_via_data *via) { short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 }; - struct resource *base_res; u32 ite8872set; u32 ite8872_lpt, ite8872_lpthi; u8 ite8872_irq, type; @@ -2561,8 +2560,7 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, /* make sure which one chip */ for (i = 0; i < 5; i++) { - base_res = request_region(inta_addr[i], 32, "it887x"); - if (base_res) { + if (request_region(inta_addr[i], 32, "it887x")) { int test; pci_write_config_dword(pdev, 0x60, 0xe5000000 | inta_addr[i]); @@ -2571,7 +2569,7 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, test = inb(inta_addr[i]); if (test != 0xff) break; - release_region(inta_addr[i], 0x8); + release_region(inta_addr[i], 32); } } if (i >= 5) { @@ -2635,7 +2633,7 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, /* * Release the resource so that parport_pc_probe_port can get it. */ - release_resource(base_res); + release_region(inta_addr[i], 32); if (parport_pc_probe_port(ite8872_lpt, ite8872_lpthi, irq, PARPORT_DMA_NONE, &pdev->dev, 0)) { printk(KERN_INFO diff --git a/trunk/drivers/rtc/rtc-coh901331.c b/trunk/drivers/rtc/rtc-coh901331.c index 316f484999b5..80f9c88214c5 100644 --- a/trunk/drivers/rtc/rtc-coh901331.c +++ b/trunk/drivers/rtc/rtc-coh901331.c @@ -220,6 +220,7 @@ static int __init coh901331_probe(struct platform_device *pdev) } clk_disable(rtap->clk); + platform_set_drvdata(pdev, rtap); rtap->rtc = rtc_device_register("coh901331", &pdev->dev, &coh901331_ops, THIS_MODULE); if (IS_ERR(rtap->rtc)) { @@ -227,11 +228,10 @@ static int __init coh901331_probe(struct platform_device *pdev) goto out_no_rtc; } - platform_set_drvdata(pdev, rtap); - return 0; out_no_rtc: + platform_set_drvdata(pdev, NULL); out_no_clk_enable: clk_put(rtap->clk); out_no_clk: diff --git a/trunk/drivers/tty/n_gsm.c b/trunk/drivers/tty/n_gsm.c index 47f8cdb207f1..74273e638c0d 100644 --- a/trunk/drivers/tty/n_gsm.c +++ b/trunk/drivers/tty/n_gsm.c @@ -1658,8 +1658,12 @@ static void gsm_queue(struct gsm_mux *gsm) if ((gsm->control & ~PF) == UI) gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len); - /* generate final CRC with received FCS */ - gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs); + if (gsm->encoding == 0){ + /* WARNING: gsm->received_fcs is used for gsm->encoding = 0 only. + In this case it contain the last piece of data + required to generate final CRC */ + gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs); + } if (gsm->fcs != GOOD_FCS) { gsm->bad_fcs++; if (debug & 4) diff --git a/trunk/drivers/tty/serial/imx.c b/trunk/drivers/tty/serial/imx.c index cb36b0d4ef3c..62df72d9f0aa 100644 --- a/trunk/drivers/tty/serial/imx.c +++ b/trunk/drivers/tty/serial/imx.c @@ -382,12 +382,13 @@ static void imx_start_tx(struct uart_port *port) static irqreturn_t imx_rtsint(int irq, void *dev_id) { struct imx_port *sport = dev_id; - unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS; + unsigned int val; unsigned long flags; spin_lock_irqsave(&sport->port.lock, flags); writel(USR1_RTSD, sport->port.membase + USR1); + val = readl(sport->port.membase + USR1) & USR1_RTSS; uart_handle_cts_change(&sport->port, !!val); wake_up_interruptible(&sport->port.state->port.delta_msr_wait); diff --git a/trunk/drivers/xen/manage.c b/trunk/drivers/xen/manage.c index 1ac94125bf93..a2eee574784e 100644 --- a/trunk/drivers/xen/manage.c +++ b/trunk/drivers/xen/manage.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -70,8 +71,13 @@ static int xen_suspend(void *data) BUG_ON(!irqs_disabled()); err = sysdev_suspend(PMSG_FREEZE); + if (!err) { + err = syscore_suspend(); + if (err) + sysdev_resume(); + } if (err) { - printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", + printk(KERN_ERR "xen_suspend: system core suspend failed: %d\n", err); return err; } @@ -95,6 +101,7 @@ static int xen_suspend(void *data) xen_timer_resume(); } + syscore_resume(); sysdev_resume(); return 0; diff --git a/trunk/fs/dcache.c b/trunk/fs/dcache.c index 129a35730994..22a0ef41bad1 100644 --- a/trunk/fs/dcache.c +++ b/trunk/fs/dcache.c @@ -99,12 +99,9 @@ static struct kmem_cache *dentry_cache __read_mostly; static unsigned int d_hash_mask __read_mostly; static unsigned int d_hash_shift __read_mostly; -struct dcache_hash_bucket { - struct hlist_bl_head head; -}; -static struct dcache_hash_bucket *dentry_hashtable __read_mostly; +static struct hlist_bl_head *dentry_hashtable __read_mostly; -static inline struct dcache_hash_bucket *d_hash(struct dentry *parent, +static inline struct hlist_bl_head *d_hash(struct dentry *parent, unsigned long hash) { hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES; @@ -112,16 +109,6 @@ static inline struct dcache_hash_bucket *d_hash(struct dentry *parent, return dentry_hashtable + (hash & D_HASHMASK); } -static inline void spin_lock_bucket(struct dcache_hash_bucket *b) -{ - bit_spin_lock(0, (unsigned long *)&b->head.first); -} - -static inline void spin_unlock_bucket(struct dcache_hash_bucket *b) -{ - __bit_spin_unlock(0, (unsigned long *)&b->head.first); -} - /* Statistics gathering. */ struct dentry_stat_t dentry_stat = { .age_limit = 45, @@ -167,8 +154,8 @@ static void d_free(struct dentry *dentry) if (dentry->d_op && dentry->d_op->d_release) dentry->d_op->d_release(dentry); - /* if dentry was never inserted into hash, immediate free is OK */ - if (hlist_bl_unhashed(&dentry->d_hash)) + /* if dentry was never visible to RCU, immediate free is OK */ + if (!(dentry->d_flags & DCACHE_RCUACCESS)) __d_free(&dentry->d_u.d_rcu); else call_rcu(&dentry->d_u.d_rcu, __d_free); @@ -330,28 +317,19 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) */ void __d_drop(struct dentry *dentry) { - if (!(dentry->d_flags & DCACHE_UNHASHED)) { - if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) { - bit_spin_lock(0, - (unsigned long *)&dentry->d_sb->s_anon.first); - dentry->d_flags |= DCACHE_UNHASHED; - hlist_bl_del_init(&dentry->d_hash); - __bit_spin_unlock(0, - (unsigned long *)&dentry->d_sb->s_anon.first); - } else { - struct dcache_hash_bucket *b; + if (!d_unhashed(dentry)) { + struct hlist_bl_head *b; + if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) + b = &dentry->d_sb->s_anon; + else b = d_hash(dentry->d_parent, dentry->d_name.hash); - spin_lock_bucket(b); - /* - * We may not actually need to put DCACHE_UNHASHED - * manipulations under the hash lock, but follow - * the principle of least surprise. - */ - dentry->d_flags |= DCACHE_UNHASHED; - hlist_bl_del_rcu(&dentry->d_hash); - spin_unlock_bucket(b); - dentry_rcuwalk_barrier(dentry); - } + + hlist_bl_lock(b); + __hlist_bl_del(&dentry->d_hash); + dentry->d_hash.pprev = NULL; + hlist_bl_unlock(b); + + dentry_rcuwalk_barrier(dentry); } } EXPORT_SYMBOL(__d_drop); @@ -1304,7 +1282,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) dname[name->len] = 0; dentry->d_count = 1; - dentry->d_flags = DCACHE_UNHASHED; + dentry->d_flags = 0; spin_lock_init(&dentry->d_lock); seqcount_init(&dentry->d_seq); dentry->d_inode = NULL; @@ -1606,10 +1584,9 @@ struct dentry *d_obtain_alias(struct inode *inode) tmp->d_inode = inode; tmp->d_flags |= DCACHE_DISCONNECTED; list_add(&tmp->d_alias, &inode->i_dentry); - bit_spin_lock(0, (unsigned long *)&tmp->d_sb->s_anon.first); - tmp->d_flags &= ~DCACHE_UNHASHED; + hlist_bl_lock(&tmp->d_sb->s_anon); hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); - __bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first); + hlist_bl_unlock(&tmp->d_sb->s_anon); spin_unlock(&tmp->d_lock); spin_unlock(&inode->i_lock); security_d_instantiate(tmp, inode); @@ -1789,7 +1766,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, unsigned int len = name->len; unsigned int hash = name->hash; const unsigned char *str = name->name; - struct dcache_hash_bucket *b = d_hash(parent, hash); + struct hlist_bl_head *b = d_hash(parent, hash); struct hlist_bl_node *node; struct dentry *dentry; @@ -1813,7 +1790,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, * * See Documentation/filesystems/path-lookup.txt for more details. */ - hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) { + hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { struct inode *i; const char *tname; int tlen; @@ -1908,7 +1885,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name) unsigned int len = name->len; unsigned int hash = name->hash; const unsigned char *str = name->name; - struct dcache_hash_bucket *b = d_hash(parent, hash); + struct hlist_bl_head *b = d_hash(parent, hash); struct hlist_bl_node *node; struct dentry *found = NULL; struct dentry *dentry; @@ -1935,7 +1912,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name) */ rcu_read_lock(); - hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) { + hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { const char *tname; int tlen; @@ -2086,13 +2063,13 @@ void d_delete(struct dentry * dentry) } EXPORT_SYMBOL(d_delete); -static void __d_rehash(struct dentry * entry, struct dcache_hash_bucket *b) +static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b) { BUG_ON(!d_unhashed(entry)); - spin_lock_bucket(b); - entry->d_flags &= ~DCACHE_UNHASHED; - hlist_bl_add_head_rcu(&entry->d_hash, &b->head); - spin_unlock_bucket(b); + hlist_bl_lock(b); + entry->d_flags |= DCACHE_RCUACCESS; + hlist_bl_add_head_rcu(&entry->d_hash, b); + hlist_bl_unlock(b); } static void _d_rehash(struct dentry * entry) @@ -3025,7 +3002,7 @@ static void __init dcache_init_early(void) dentry_hashtable = alloc_large_system_hash("Dentry cache", - sizeof(struct dcache_hash_bucket), + sizeof(struct hlist_bl_head), dhash_entries, 13, HASH_EARLY, @@ -3034,7 +3011,7 @@ static void __init dcache_init_early(void) 0); for (loop = 0; loop < (1 << d_hash_shift); loop++) - INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head); + INIT_HLIST_BL_HEAD(dentry_hashtable + loop); } static void __init dcache_init(void) @@ -3057,7 +3034,7 @@ static void __init dcache_init(void) dentry_hashtable = alloc_large_system_hash("Dentry cache", - sizeof(struct dcache_hash_bucket), + sizeof(struct hlist_bl_head), dhash_entries, 13, 0, @@ -3066,7 +3043,7 @@ static void __init dcache_init(void) 0); for (loop = 0; loop < (1 << d_hash_shift); loop++) - INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head); + INIT_HLIST_BL_HEAD(dentry_hashtable + loop); } /* SLAB cache for __getname() consumers */ diff --git a/trunk/fs/ecryptfs/crypto.c b/trunk/fs/ecryptfs/crypto.c index d2a70a4561f9..b8d5c8091024 100644 --- a/trunk/fs/ecryptfs/crypto.c +++ b/trunk/fs/ecryptfs/crypto.c @@ -1452,6 +1452,25 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; } +void ecryptfs_i_size_init(const char *page_virt, struct inode *inode) +{ + struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct ecryptfs_crypt_stat *crypt_stat; + u64 file_size; + + crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; + mount_crypt_stat = + &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat; + if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { + file_size = i_size_read(ecryptfs_inode_to_lower(inode)); + if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) + file_size += crypt_stat->metadata_size; + } else + file_size = get_unaligned_be64(page_virt); + i_size_write(inode, (loff_t)file_size); + crypt_stat->flags |= ECRYPTFS_I_SIZE_INITIALIZED; +} + /** * ecryptfs_read_headers_virt * @page_virt: The virtual address into which to read the headers @@ -1482,6 +1501,8 @@ static int ecryptfs_read_headers_virt(char *page_virt, rc = -EINVAL; goto out; } + if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED)) + ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset), &bytes_read); diff --git a/trunk/fs/ecryptfs/ecryptfs_kernel.h b/trunk/fs/ecryptfs/ecryptfs_kernel.h index bd3cafd0949d..e70282775e2c 100644 --- a/trunk/fs/ecryptfs/ecryptfs_kernel.h +++ b/trunk/fs/ecryptfs/ecryptfs_kernel.h @@ -269,6 +269,7 @@ struct ecryptfs_crypt_stat { #define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800 #define ECRYPTFS_ENCFN_USE_FEK 0x00001000 #define ECRYPTFS_UNLINK_SIGS 0x00002000 +#define ECRYPTFS_I_SIZE_INITIALIZED 0x00004000 u32 flags; unsigned int file_version; size_t iv_bytes; @@ -295,6 +296,8 @@ struct ecryptfs_crypt_stat { struct ecryptfs_inode_info { struct inode vfs_inode; struct inode *wii_inode; + struct mutex lower_file_mutex; + atomic_t lower_file_count; struct file *lower_file; struct ecryptfs_crypt_stat crypt_stat; }; @@ -626,6 +629,7 @@ struct ecryptfs_open_req { int ecryptfs_interpose(struct dentry *hidden_dentry, struct dentry *this_dentry, struct super_block *sb, u32 flags); +void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, struct dentry *lower_dentry, struct inode *ecryptfs_dir_inode); @@ -757,7 +761,8 @@ int ecryptfs_privileged_open(struct file **lower_file, struct dentry *lower_dentry, struct vfsmount *lower_mnt, const struct cred *cred); -int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry); +int ecryptfs_get_lower_file(struct dentry *ecryptfs_dentry); +void ecryptfs_put_lower_file(struct inode *inode); int ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, size_t *packet_size, diff --git a/trunk/fs/ecryptfs/file.c b/trunk/fs/ecryptfs/file.c index cedc913d11ba..566e5472f78c 100644 --- a/trunk/fs/ecryptfs/file.c +++ b/trunk/fs/ecryptfs/file.c @@ -191,10 +191,10 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | ECRYPTFS_ENCRYPTED); } mutex_unlock(&crypt_stat->cs_mutex); - rc = ecryptfs_init_persistent_file(ecryptfs_dentry); + rc = ecryptfs_get_lower_file(ecryptfs_dentry); if (rc) { printk(KERN_ERR "%s: Error attempting to initialize " - "the persistent file for the dentry with name " + "the lower file for the dentry with name " "[%s]; rc = [%d]\n", __func__, ecryptfs_dentry->d_name.name, rc); goto out_free; @@ -202,9 +202,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file) if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE) == O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) { rc = -EPERM; - printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs " + printk(KERN_WARNING "%s: Lower file is RO; eCryptfs " "file must hence be opened RO\n", __func__); - goto out_free; + goto out_put; } ecryptfs_set_file_lower( file, ecryptfs_inode_to_private(inode)->lower_file); @@ -232,10 +232,11 @@ static int ecryptfs_open(struct inode *inode, struct file *file) "Plaintext passthrough mode is not " "enabled; returning -EIO\n"); mutex_unlock(&crypt_stat->cs_mutex); - goto out_free; + goto out_put; } rc = 0; - crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); + crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED + | ECRYPTFS_ENCRYPTED); mutex_unlock(&crypt_stat->cs_mutex); goto out; } @@ -245,6 +246,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file) "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, (unsigned long long)i_size_read(inode)); goto out; +out_put: + ecryptfs_put_lower_file(inode); out_free: kmem_cache_free(ecryptfs_file_info_cache, ecryptfs_file_to_private(file)); @@ -254,17 +257,13 @@ static int ecryptfs_open(struct inode *inode, struct file *file) static int ecryptfs_flush(struct file *file, fl_owner_t td) { - int rc = 0; - struct file *lower_file = NULL; - - lower_file = ecryptfs_file_to_lower(file); - if (lower_file->f_op && lower_file->f_op->flush) - rc = lower_file->f_op->flush(lower_file, td); - return rc; + return file->f_mode & FMODE_WRITE + ? filemap_write_and_wait(file->f_mapping) : 0; } static int ecryptfs_release(struct inode *inode, struct file *file) { + ecryptfs_put_lower_file(inode); kmem_cache_free(ecryptfs_file_info_cache, ecryptfs_file_to_private(file)); return 0; diff --git a/trunk/fs/ecryptfs/inode.c b/trunk/fs/ecryptfs/inode.c index f99051b7adab..4d4cc6a90cd5 100644 --- a/trunk/fs/ecryptfs/inode.c +++ b/trunk/fs/ecryptfs/inode.c @@ -168,19 +168,18 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) "context; rc = [%d]\n", rc); goto out; } - rc = ecryptfs_init_persistent_file(ecryptfs_dentry); + rc = ecryptfs_get_lower_file(ecryptfs_dentry); if (rc) { printk(KERN_ERR "%s: Error attempting to initialize " - "the persistent file for the dentry with name " + "the lower file for the dentry with name " "[%s]; rc = [%d]\n", __func__, ecryptfs_dentry->d_name.name, rc); goto out; } rc = ecryptfs_write_metadata(ecryptfs_dentry); - if (rc) { + if (rc) printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); - goto out; - } + ecryptfs_put_lower_file(ecryptfs_dentry->d_inode); out: return rc; } @@ -226,11 +225,9 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, struct dentry *lower_dir_dentry; struct vfsmount *lower_mnt; struct inode *lower_inode; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat; struct ecryptfs_crypt_stat *crypt_stat; char *page_virt = NULL; - u64 file_size; - int rc = 0; + int put_lower = 0, rc = 0; lower_dir_dentry = lower_dentry->d_parent; lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( @@ -277,14 +274,15 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, rc = -ENOMEM; goto out; } - rc = ecryptfs_init_persistent_file(ecryptfs_dentry); + rc = ecryptfs_get_lower_file(ecryptfs_dentry); if (rc) { printk(KERN_ERR "%s: Error attempting to initialize " - "the persistent file for the dentry with name " + "the lower file for the dentry with name " "[%s]; rc = [%d]\n", __func__, ecryptfs_dentry->d_name.name, rc); goto out_free_kmem; } + put_lower = 1; crypt_stat = &ecryptfs_inode_to_private( ecryptfs_dentry->d_inode)->crypt_stat; /* TODO: lock for crypt_stat comparison */ @@ -302,18 +300,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, } crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; } - mount_crypt_stat = &ecryptfs_superblock_to_private( - ecryptfs_dentry->d_sb)->mount_crypt_stat; - if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { - if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) - file_size = (crypt_stat->metadata_size - + i_size_read(lower_dentry->d_inode)); - else - file_size = i_size_read(lower_dentry->d_inode); - } else { - file_size = get_unaligned_be64(page_virt); - } - i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size); + ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); out_free_kmem: kmem_cache_free(ecryptfs_header_cache_2, page_virt); goto out; @@ -322,6 +309,8 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, mntput(lower_mnt); d_drop(ecryptfs_dentry); out: + if (put_lower) + ecryptfs_put_lower_file(ecryptfs_dentry->d_inode); return rc; } @@ -538,8 +527,6 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) dget(lower_dentry); rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); dput(lower_dentry); - if (!rc) - d_delete(lower_dentry); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; unlock_dir(lower_dir_dentry); @@ -610,8 +597,8 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); out_lock: unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); - dput(lower_new_dentry->d_parent); - dput(lower_old_dentry->d_parent); + dput(lower_new_dir_dentry); + dput(lower_old_dir_dentry); dput(lower_new_dentry); dput(lower_old_dentry); return rc; @@ -759,8 +746,11 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, if (unlikely((ia->ia_size == i_size))) { lower_ia->ia_valid &= ~ATTR_SIZE; - goto out; + return 0; } + rc = ecryptfs_get_lower_file(dentry); + if (rc) + return rc; crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; /* Switch on growing or shrinking file */ if (ia->ia_size > i_size) { @@ -838,6 +828,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, lower_ia->ia_valid &= ~ATTR_SIZE; } out: + ecryptfs_put_lower_file(inode); return rc; } @@ -913,7 +904,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) mount_crypt_stat = &ecryptfs_superblock_to_private( dentry->d_sb)->mount_crypt_stat; + rc = ecryptfs_get_lower_file(dentry); + if (rc) { + mutex_unlock(&crypt_stat->cs_mutex); + goto out; + } rc = ecryptfs_read_metadata(dentry); + ecryptfs_put_lower_file(inode); if (rc) { if (!(mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { @@ -927,10 +924,17 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) goto out; } rc = 0; - crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); + crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED + | ECRYPTFS_ENCRYPTED); } } mutex_unlock(&crypt_stat->cs_mutex); + if (S_ISREG(inode->i_mode)) { + rc = filemap_write_and_wait(inode->i_mapping); + if (rc) + goto out; + fsstack_copy_attr_all(inode, lower_inode); + } memcpy(&lower_ia, ia, sizeof(lower_ia)); if (ia->ia_valid & ATTR_FILE) lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); diff --git a/trunk/fs/ecryptfs/kthread.c b/trunk/fs/ecryptfs/kthread.c index 0851ab6980f5..69f994a7d524 100644 --- a/trunk/fs/ecryptfs/kthread.c +++ b/trunk/fs/ecryptfs/kthread.c @@ -44,7 +44,7 @@ static struct task_struct *ecryptfs_kthread; * @ignored: ignored * * The eCryptfs kernel thread that has the responsibility of getting - * the lower persistent file with RW permissions. + * the lower file with RW permissions. * * Returns zero on success; non-zero otherwise */ @@ -141,8 +141,8 @@ int ecryptfs_privileged_open(struct file **lower_file, int rc = 0; /* Corresponding dput() and mntput() are done when the - * persistent file is fput() when the eCryptfs inode is - * destroyed. */ + * lower file is fput() when all eCryptfs files for the inode are + * released. */ dget(lower_dentry); mntget(lower_mnt); flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; diff --git a/trunk/fs/ecryptfs/main.c b/trunk/fs/ecryptfs/main.c index fdb2eb0ad09e..89b93389af8e 100644 --- a/trunk/fs/ecryptfs/main.c +++ b/trunk/fs/ecryptfs/main.c @@ -96,7 +96,7 @@ void __ecryptfs_printk(const char *fmt, ...) } /** - * ecryptfs_init_persistent_file + * ecryptfs_init_lower_file * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with * the lower dentry and the lower mount set * @@ -104,42 +104,70 @@ void __ecryptfs_printk(const char *fmt, ...) * inode. All I/O operations to the lower inode occur through that * file. When the first eCryptfs dentry that interposes with the first * lower dentry for that inode is created, this function creates the - * persistent file struct and associates it with the eCryptfs - * inode. When the eCryptfs inode is destroyed, the file is closed. + * lower file struct and associates it with the eCryptfs + * inode. When all eCryptfs files associated with the inode are released, the + * file is closed. * - * The persistent file will be opened with read/write permissions, if + * The lower file will be opened with read/write permissions, if * possible. Otherwise, it is opened read-only. * - * This function does nothing if a lower persistent file is already + * This function does nothing if a lower file is already * associated with the eCryptfs inode. * * Returns zero on success; non-zero otherwise */ -int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) +static int ecryptfs_init_lower_file(struct dentry *dentry, + struct file **lower_file) { const struct cred *cred = current_cred(); - struct ecryptfs_inode_info *inode_info = - ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); - int rc = 0; + struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); + struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); + int rc; - if (!inode_info->lower_file) { - struct dentry *lower_dentry; - struct vfsmount *lower_mnt = - ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); + rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt, + cred); + if (rc) { + printk(KERN_ERR "Error opening lower file " + "for lower_dentry [0x%p] and lower_mnt [0x%p]; " + "rc = [%d]\n", lower_dentry, lower_mnt, rc); + (*lower_file) = NULL; + } + return rc; +} - lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); - rc = ecryptfs_privileged_open(&inode_info->lower_file, - lower_dentry, lower_mnt, cred); - if (rc) { - printk(KERN_ERR "Error opening lower persistent file " - "for lower_dentry [0x%p] and lower_mnt [0x%p]; " - "rc = [%d]\n", lower_dentry, lower_mnt, rc); - inode_info->lower_file = NULL; - } +int ecryptfs_get_lower_file(struct dentry *dentry) +{ + struct ecryptfs_inode_info *inode_info = + ecryptfs_inode_to_private(dentry->d_inode); + int count, rc = 0; + + mutex_lock(&inode_info->lower_file_mutex); + count = atomic_inc_return(&inode_info->lower_file_count); + if (WARN_ON_ONCE(count < 1)) + rc = -EINVAL; + else if (count == 1) { + rc = ecryptfs_init_lower_file(dentry, + &inode_info->lower_file); + if (rc) + atomic_set(&inode_info->lower_file_count, 0); } + mutex_unlock(&inode_info->lower_file_mutex); return rc; } +void ecryptfs_put_lower_file(struct inode *inode) +{ + struct ecryptfs_inode_info *inode_info; + + inode_info = ecryptfs_inode_to_private(inode); + if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count, + &inode_info->lower_file_mutex)) { + fput(inode_info->lower_file); + inode_info->lower_file = NULL; + mutex_unlock(&inode_info->lower_file_mutex); + } +} + static struct inode *ecryptfs_get_inode(struct inode *lower_inode, struct super_block *sb) { diff --git a/trunk/fs/ecryptfs/super.c b/trunk/fs/ecryptfs/super.c index bacc882e1ae4..245b517bf1b6 100644 --- a/trunk/fs/ecryptfs/super.c +++ b/trunk/fs/ecryptfs/super.c @@ -55,6 +55,8 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb) if (unlikely(!inode_info)) goto out; ecryptfs_init_crypt_stat(&inode_info->crypt_stat); + mutex_init(&inode_info->lower_file_mutex); + atomic_set(&inode_info->lower_file_count, 0); inode_info->lower_file = NULL; inode = &inode_info->vfs_inode; out: @@ -77,8 +79,7 @@ static void ecryptfs_i_callback(struct rcu_head *head) * * This is used during the final destruction of the inode. All * allocation of memory related to the inode, including allocated - * memory in the crypt_stat struct, will be released here. This - * function also fput()'s the persistent file for the lower inode. + * memory in the crypt_stat struct, will be released here. * There should be no chance that this deallocation will be missed. */ static void ecryptfs_destroy_inode(struct inode *inode) @@ -86,16 +87,7 @@ static void ecryptfs_destroy_inode(struct inode *inode) struct ecryptfs_inode_info *inode_info; inode_info = ecryptfs_inode_to_private(inode); - if (inode_info->lower_file) { - struct dentry *lower_dentry = - inode_info->lower_file->f_dentry; - - BUG_ON(!lower_dentry); - if (lower_dentry->d_inode) { - fput(inode_info->lower_file); - inode_info->lower_file = NULL; - } - } + BUG_ON(inode_info->lower_file); ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); call_rcu(&inode->i_rcu, ecryptfs_i_callback); } diff --git a/trunk/fs/gfs2/glock.c b/trunk/fs/gfs2/glock.c index f07643e21bfa..7a4fb630a320 100644 --- a/trunk/fs/gfs2/glock.c +++ b/trunk/fs/gfs2/glock.c @@ -93,14 +93,12 @@ static unsigned int gl_hash(const struct gfs2_sbd *sdp, static inline void spin_lock_bucket(unsigned int hash) { - struct hlist_bl_head *bl = &gl_hash_table[hash]; - bit_spin_lock(0, (unsigned long *)bl); + hlist_bl_lock(&gl_hash_table[hash]); } static inline void spin_unlock_bucket(unsigned int hash) { - struct hlist_bl_head *bl = &gl_hash_table[hash]; - __bit_spin_unlock(0, (unsigned long *)bl); + hlist_bl_unlock(&gl_hash_table[hash]); } static void gfs2_glock_dealloc(struct rcu_head *rcu) diff --git a/trunk/fs/ubifs/recovery.c b/trunk/fs/ubifs/recovery.c index 936f2cbfe6b6..3dbad6fbd1eb 100644 --- a/trunk/fs/ubifs/recovery.c +++ b/trunk/fs/ubifs/recovery.c @@ -317,6 +317,32 @@ int ubifs_recover_master_node(struct ubifs_info *c) goto out_free; } memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ); + + /* + * We had to recover the master node, which means there was an + * unclean reboot. However, it is possible that the master node + * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set. + * E.g., consider the following chain of events: + * + * 1. UBIFS was cleanly unmounted, so the master node is clean + * 2. UBIFS is being mounted R/W and starts changing the master + * node in the first (%UBIFS_MST_LNUM). A power cut happens, + * so this LEB ends up with some amount of garbage at the + * end. + * 3. UBIFS is being mounted R/O. We reach this place and + * recover the master node from the second LEB + * (%UBIFS_MST_LNUM + 1). But we cannot update the media + * because we are being mounted R/O. We have to defer the + * operation. + * 4. However, this master node (@c->mst_node) is marked as + * clean (since the step 1). And if we just return, the + * mount code will be confused and won't recover the master + * node when it is re-mounter R/W later. + * + * Thus, to force the recovery by marking the master node as + * dirty. + */ + c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); } else { /* Write the recovered master node */ c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1; diff --git a/trunk/fs/ubifs/super.c b/trunk/fs/ubifs/super.c index c75f6133206c..be6c7b008f38 100644 --- a/trunk/fs/ubifs/super.c +++ b/trunk/fs/ubifs/super.c @@ -1671,14 +1671,25 @@ static int ubifs_remount_rw(struct ubifs_info *c) if (err) goto out; + dbg_gen("re-mounted read-write"); + c->remounting_rw = 0; + if (c->need_recovery) { c->need_recovery = 0; ubifs_msg("deferred recovery completed"); + } else { + /* + * Do not run the debugging space check if the were doing + * recovery, because when we saved the information we had the + * file-system in a state where the TNC and lprops has been + * modified in memory, but all the I/O operations (including a + * commit) were deferred. So the file-system was in + * "non-committed" state. Now the file-system is in committed + * state, and of course the amount of free space will change + * because, for example, the old index size was imprecise. + */ + err = dbg_check_space_info(c); } - - dbg_gen("re-mounted read-write"); - c->remounting_rw = 0; - err = dbg_check_space_info(c); mutex_unlock(&c->umount_mutex); return err; @@ -1761,10 +1772,12 @@ static void ubifs_put_super(struct super_block *sb) * of the media. For example, there will be dirty inodes if we failed * to write them back because of I/O errors. */ - ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0); - ubifs_assert(c->budg_idx_growth == 0); - ubifs_assert(c->budg_dd_growth == 0); - ubifs_assert(c->budg_data_growth == 0); + if (!c->ro_error) { + ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0); + ubifs_assert(c->budg_idx_growth == 0); + ubifs_assert(c->budg_dd_growth == 0); + ubifs_assert(c->budg_data_growth == 0); + } /* * The 'c->umount_lock' prevents races between UBIFS memory shrinker diff --git a/trunk/include/asm-generic/vmlinux.lds.h b/trunk/include/asm-generic/vmlinux.lds.h index 75a8692d144f..bd297a20ab98 100644 --- a/trunk/include/asm-generic/vmlinux.lds.h +++ b/trunk/include/asm-generic/vmlinux.lds.h @@ -170,10 +170,6 @@ STRUCT_ALIGN(); \ *(__tracepoints) \ /* implement dynamic printk debug */ \ - . = ALIGN(8); \ - VMLINUX_SYMBOL(__start___jump_table) = .; \ - *(__jump_table) \ - VMLINUX_SYMBOL(__stop___jump_table) = .; \ . = ALIGN(8); \ VMLINUX_SYMBOL(__start___verbose) = .; \ *(__verbose) \ @@ -232,6 +228,8 @@ \ BUG_TABLE \ \ + JUMP_TABLE \ + \ /* PCI quirks */ \ .pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \ @@ -591,6 +589,14 @@ #define BUG_TABLE #endif +#define JUMP_TABLE \ + . = ALIGN(8); \ + __jump_table : AT(ADDR(__jump_table) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start___jump_table) = .; \ + *(__jump_table) \ + VMLINUX_SYMBOL(__stop___jump_table) = .; \ + } + #ifdef CONFIG_PM_TRACE #define TRACEDATA \ . = ALIGN(4); \ diff --git a/trunk/include/linux/bit_spinlock.h b/trunk/include/linux/bit_spinlock.h index e612575a2596..b4326bfa684f 100644 --- a/trunk/include/linux/bit_spinlock.h +++ b/trunk/include/linux/bit_spinlock.h @@ -23,11 +23,11 @@ static inline void bit_spin_lock(int bitnum, unsigned long *addr) preempt_disable(); #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) while (unlikely(test_and_set_bit_lock(bitnum, addr))) { - while (test_bit(bitnum, addr)) { - preempt_enable(); + preempt_enable(); + do { cpu_relax(); - preempt_disable(); - } + } while (test_bit(bitnum, addr)); + preempt_disable(); } #endif __acquire(bitlock); diff --git a/trunk/include/linux/dcache.h b/trunk/include/linux/dcache.h index f2afed4fa945..19d90a55541d 100644 --- a/trunk/include/linux/dcache.h +++ b/trunk/include/linux/dcache.h @@ -197,7 +197,7 @@ struct dentry_operations { * typically using d_splice_alias. */ #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ -#define DCACHE_UNHASHED 0x0010 +#define DCACHE_RCUACCESS 0x0010 /* Entry has ever been RCU-visible */ #define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched by inotify */ @@ -384,7 +384,7 @@ extern struct dentry *dget_parent(struct dentry *dentry); static inline int d_unhashed(struct dentry *dentry) { - return (dentry->d_flags & DCACHE_UNHASHED); + return hlist_bl_unhashed(&dentry->d_hash); } static inline int d_unlinked(struct dentry *dentry) diff --git a/trunk/include/linux/dynamic_debug.h b/trunk/include/linux/dynamic_debug.h index e747ecd48e1c..0c9653f11c18 100644 --- a/trunk/include/linux/dynamic_debug.h +++ b/trunk/include/linux/dynamic_debug.h @@ -1,6 +1,8 @@ #ifndef _DYNAMIC_DEBUG_H #define _DYNAMIC_DEBUG_H +#include + /* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They * use independent hash functions, to reduce the chance of false positives. diff --git a/trunk/include/linux/jump_label.h b/trunk/include/linux/jump_label.h index 83e745f3ead7..7880f18e4b86 100644 --- a/trunk/include/linux/jump_label.h +++ b/trunk/include/linux/jump_label.h @@ -1,43 +1,20 @@ #ifndef _LINUX_JUMP_LABEL_H #define _LINUX_JUMP_LABEL_H -#include -#include - #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL) - -struct jump_label_key { - atomic_t enabled; - struct jump_entry *entries; -#ifdef CONFIG_MODULES - struct jump_label_mod *next; -#endif -}; - # include # define HAVE_JUMP_LABEL #endif enum jump_label_type { - JUMP_LABEL_DISABLE = 0, JUMP_LABEL_ENABLE, + JUMP_LABEL_DISABLE }; struct module; #ifdef HAVE_JUMP_LABEL -#ifdef CONFIG_MODULES -#define JUMP_LABEL_INIT {{ 0 }, NULL, NULL} -#else -#define JUMP_LABEL_INIT {{ 0 }, NULL} -#endif - -static __always_inline bool static_branch(struct jump_label_key *key) -{ - return arch_static_branch(key); -} - extern struct jump_entry __start___jump_table[]; extern struct jump_entry __stop___jump_table[]; @@ -46,37 +23,37 @@ extern void jump_label_unlock(void); extern void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type type); extern void arch_jump_label_text_poke_early(jump_label_t addr); -extern int jump_label_text_reserved(void *start, void *end); -extern void jump_label_inc(struct jump_label_key *key); -extern void jump_label_dec(struct jump_label_key *key); -extern bool jump_label_enabled(struct jump_label_key *key); +extern void jump_label_update(unsigned long key, enum jump_label_type type); extern void jump_label_apply_nops(struct module *mod); +extern int jump_label_text_reserved(void *start, void *end); -#else +#define jump_label_enable(key) \ + jump_label_update((unsigned long)key, JUMP_LABEL_ENABLE); -#include +#define jump_label_disable(key) \ + jump_label_update((unsigned long)key, JUMP_LABEL_DISABLE); -#define JUMP_LABEL_INIT {ATOMIC_INIT(0)} +#else -struct jump_label_key { - atomic_t enabled; -}; +#define JUMP_LABEL(key, label) \ +do { \ + if (unlikely(*key)) \ + goto label; \ +} while (0) -static __always_inline bool static_branch(struct jump_label_key *key) -{ - if (unlikely(atomic_read(&key->enabled))) - return true; - return false; -} +#define jump_label_enable(cond_var) \ +do { \ + *(cond_var) = 1; \ +} while (0) -static inline void jump_label_inc(struct jump_label_key *key) -{ - atomic_inc(&key->enabled); -} +#define jump_label_disable(cond_var) \ +do { \ + *(cond_var) = 0; \ +} while (0) -static inline void jump_label_dec(struct jump_label_key *key) +static inline int jump_label_apply_nops(struct module *mod) { - atomic_dec(&key->enabled); + return 0; } static inline int jump_label_text_reserved(void *start, void *end) @@ -87,16 +64,16 @@ static inline int jump_label_text_reserved(void *start, void *end) static inline void jump_label_lock(void) {} static inline void jump_label_unlock(void) {} -static inline bool jump_label_enabled(struct jump_label_key *key) -{ - return !!atomic_read(&key->enabled); -} - -static inline int jump_label_apply_nops(struct module *mod) -{ - return 0; -} - #endif +#define COND_STMT(key, stmt) \ +do { \ + __label__ jl_enabled; \ + JUMP_LABEL(key, jl_enabled); \ + if (0) { \ +jl_enabled: \ + stmt; \ + } \ +} while (0) + #endif diff --git a/trunk/include/linux/jump_label_ref.h b/trunk/include/linux/jump_label_ref.h new file mode 100644 index 000000000000..e5d012ad92c6 --- /dev/null +++ b/trunk/include/linux/jump_label_ref.h @@ -0,0 +1,44 @@ +#ifndef _LINUX_JUMP_LABEL_REF_H +#define _LINUX_JUMP_LABEL_REF_H + +#include +#include + +#ifdef HAVE_JUMP_LABEL + +static inline void jump_label_inc(atomic_t *key) +{ + if (atomic_add_return(1, key) == 1) + jump_label_enable(key); +} + +static inline void jump_label_dec(atomic_t *key) +{ + if (atomic_dec_and_test(key)) + jump_label_disable(key); +} + +#else /* !HAVE_JUMP_LABEL */ + +static inline void jump_label_inc(atomic_t *key) +{ + atomic_inc(key); +} + +static inline void jump_label_dec(atomic_t *key) +{ + atomic_dec(key); +} + +#undef JUMP_LABEL +#define JUMP_LABEL(key, label) \ +do { \ + if (unlikely(__builtin_choose_expr( \ + __builtin_types_compatible_p(typeof(key), atomic_t *), \ + atomic_read((atomic_t *)(key)), *(key)))) \ + goto label; \ +} while (0) + +#endif /* HAVE_JUMP_LABEL */ + +#endif /* _LINUX_JUMP_LABEL_REF_H */ diff --git a/trunk/include/linux/libata.h b/trunk/include/linux/libata.h index 7f675aa81d87..04f32a3eb26b 100644 --- a/trunk/include/linux/libata.h +++ b/trunk/include/linux/libata.h @@ -137,8 +137,6 @@ enum { ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */ ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */ ATA_DFLAG_AN = (1 << 7), /* AN configured */ - ATA_DFLAG_HIPM = (1 << 8), /* device supports HIPM */ - ATA_DFLAG_DIPM = (1 << 9), /* device supports DIPM */ ATA_DFLAG_DMADIR = (1 << 10), /* device requires DMADIR */ ATA_DFLAG_CFG_MASK = (1 << 12) - 1, @@ -198,6 +196,7 @@ enum { * management */ ATA_FLAG_SW_ACTIVITY = (1 << 22), /* driver supports sw activity * led */ + ATA_FLAG_NO_DIPM = (1 << 23), /* host not happy with DIPM */ /* bits 24:31 of ap->flags are reserved for LLD specific flags */ diff --git a/trunk/include/linux/list_bl.h b/trunk/include/linux/list_bl.h index 5bad17d1acde..31f9d75adc5b 100644 --- a/trunk/include/linux/list_bl.h +++ b/trunk/include/linux/list_bl.h @@ -2,6 +2,7 @@ #define _LINUX_LIST_BL_H #include +#include /* * Special version of lists, where head of the list has a lock in the lowest @@ -114,6 +115,16 @@ static inline void hlist_bl_del_init(struct hlist_bl_node *n) } } +static inline void hlist_bl_lock(struct hlist_bl_head *b) +{ + bit_spin_lock(0, (unsigned long *)b); +} + +static inline void hlist_bl_unlock(struct hlist_bl_head *b) +{ + __bit_spin_unlock(0, (unsigned long *)b); +} + /** * hlist_bl_for_each_entry - iterate over list of given type * @tpos: the type * to use as a loop cursor. diff --git a/trunk/include/linux/perf_event.h b/trunk/include/linux/perf_event.h index 9eec53d97370..ee9f1e782800 100644 --- a/trunk/include/linux/perf_event.h +++ b/trunk/include/linux/perf_event.h @@ -505,7 +505,7 @@ struct perf_guest_info_callbacks { #include #include #include -#include +#include #include #include @@ -1034,7 +1034,7 @@ static inline int is_software_event(struct perf_event *event) return event->pmu->task_ctx_nr == perf_sw_context; } -extern struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX]; +extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX]; extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64); @@ -1063,21 +1063,22 @@ perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr) { struct pt_regs hot_regs; - if (static_branch(&perf_swevent_enabled[event_id])) { - if (!regs) { - perf_fetch_caller_regs(&hot_regs); - regs = &hot_regs; - } - __perf_sw_event(event_id, nr, nmi, regs, addr); + JUMP_LABEL(&perf_swevent_enabled[event_id], have_event); + return; + +have_event: + if (!regs) { + perf_fetch_caller_regs(&hot_regs); + regs = &hot_regs; } + __perf_sw_event(event_id, nr, nmi, regs, addr); } -extern struct jump_label_key perf_sched_events; +extern atomic_t perf_sched_events; static inline void perf_event_task_sched_in(struct task_struct *task) { - if (static_branch(&perf_sched_events)) - __perf_event_task_sched_in(task); + COND_STMT(&perf_sched_events, __perf_event_task_sched_in(task)); } static inline diff --git a/trunk/include/linux/security.h b/trunk/include/linux/security.h index ca02f1716736..8ce59ef3e5af 100644 --- a/trunk/include/linux/security.h +++ b/trunk/include/linux/security.h @@ -1456,7 +1456,7 @@ struct security_operations { struct inode *new_dir, struct dentry *new_dentry); int (*inode_readlink) (struct dentry *dentry); int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd); - int (*inode_permission) (struct inode *inode, int mask); + int (*inode_permission) (struct inode *inode, int mask, unsigned flags); int (*inode_setattr) (struct dentry *dentry, struct iattr *attr); int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry); int (*inode_setxattr) (struct dentry *dentry, const char *name, diff --git a/trunk/include/linux/tracepoint.h b/trunk/include/linux/tracepoint.h index d530a4460a0b..97c84a58efb8 100644 --- a/trunk/include/linux/tracepoint.h +++ b/trunk/include/linux/tracepoint.h @@ -29,7 +29,7 @@ struct tracepoint_func { struct tracepoint { const char *name; /* Tracepoint name */ - struct jump_label_key key; + int state; /* State. */ void (*regfunc)(void); void (*unregfunc)(void); struct tracepoint_func __rcu *funcs; @@ -146,7 +146,9 @@ void tracepoint_update_probe_range(struct tracepoint * const *begin, extern struct tracepoint __tracepoint_##name; \ static inline void trace_##name(proto) \ { \ - if (static_branch(&__tracepoint_##name.key)) \ + JUMP_LABEL(&__tracepoint_##name.state, do_trace); \ + return; \ +do_trace: \ __DO_TRACE(&__tracepoint_##name, \ TP_PROTO(data_proto), \ TP_ARGS(data_args), \ @@ -174,14 +176,14 @@ void tracepoint_update_probe_range(struct tracepoint * const *begin, * structures, so we create an array of pointers that will be used for iteration * on the tracepoints. */ -#define DEFINE_TRACE_FN(name, reg, unreg) \ - static const char __tpstrtab_##name[] \ - __attribute__((section("__tracepoints_strings"))) = #name; \ - struct tracepoint __tracepoint_##name \ - __attribute__((section("__tracepoints"))) = \ - { __tpstrtab_##name, JUMP_LABEL_INIT, reg, unreg, NULL };\ - static struct tracepoint * const __tracepoint_ptr_##name __used \ - __attribute__((section("__tracepoints_ptrs"))) = \ +#define DEFINE_TRACE_FN(name, reg, unreg) \ + static const char __tpstrtab_##name[] \ + __attribute__((section("__tracepoints_strings"))) = #name; \ + struct tracepoint __tracepoint_##name \ + __attribute__((section("__tracepoints"))) = \ + { __tpstrtab_##name, 0, reg, unreg, NULL }; \ + static struct tracepoint * const __tracepoint_ptr_##name __used \ + __attribute__((section("__tracepoints_ptrs"))) = \ &__tracepoint_##name; #define DEFINE_TRACE(name) \ diff --git a/trunk/kernel/jump_label.c b/trunk/kernel/jump_label.c index 74d1c099fbd1..3b79bd938330 100644 --- a/trunk/kernel/jump_label.c +++ b/trunk/kernel/jump_label.c @@ -2,23 +2,43 @@ * jump label support * * Copyright (C) 2009 Jason Baron - * Copyright (C) 2011 Peter Zijlstra * */ +#include #include #include #include #include +#include #include #include #include -#include #ifdef HAVE_JUMP_LABEL +#define JUMP_LABEL_HASH_BITS 6 +#define JUMP_LABEL_TABLE_SIZE (1 << JUMP_LABEL_HASH_BITS) +static struct hlist_head jump_label_table[JUMP_LABEL_TABLE_SIZE]; + /* mutex to protect coming/going of the the jump_label table */ static DEFINE_MUTEX(jump_label_mutex); +struct jump_label_entry { + struct hlist_node hlist; + struct jump_entry *table; + int nr_entries; + /* hang modules off here */ + struct hlist_head modules; + unsigned long key; +}; + +struct jump_label_module_entry { + struct hlist_node hlist; + struct jump_entry *table; + int nr_entries; + struct module *mod; +}; + void jump_label_lock(void) { mutex_lock(&jump_label_mutex); @@ -29,11 +49,6 @@ void jump_label_unlock(void) mutex_unlock(&jump_label_mutex); } -bool jump_label_enabled(struct jump_label_key *key) -{ - return !!atomic_read(&key->enabled); -} - static int jump_label_cmp(const void *a, const void *b) { const struct jump_entry *jea = a; @@ -49,7 +64,7 @@ static int jump_label_cmp(const void *a, const void *b) } static void -jump_label_sort_entries(struct jump_entry *start, struct jump_entry *stop) +sort_jump_label_entries(struct jump_entry *start, struct jump_entry *stop) { unsigned long size; @@ -58,25 +73,118 @@ jump_label_sort_entries(struct jump_entry *start, struct jump_entry *stop) sort(start, size, sizeof(struct jump_entry), jump_label_cmp, NULL); } -static void jump_label_update(struct jump_label_key *key, int enable); +static struct jump_label_entry *get_jump_label_entry(jump_label_t key) +{ + struct hlist_head *head; + struct hlist_node *node; + struct jump_label_entry *e; + u32 hash = jhash((void *)&key, sizeof(jump_label_t), 0); + + head = &jump_label_table[hash & (JUMP_LABEL_TABLE_SIZE - 1)]; + hlist_for_each_entry(e, node, head, hlist) { + if (key == e->key) + return e; + } + return NULL; +} -void jump_label_inc(struct jump_label_key *key) +static struct jump_label_entry * +add_jump_label_entry(jump_label_t key, int nr_entries, struct jump_entry *table) { - if (atomic_inc_not_zero(&key->enabled)) - return; + struct hlist_head *head; + struct jump_label_entry *e; + u32 hash; + + e = get_jump_label_entry(key); + if (e) + return ERR_PTR(-EEXIST); + + e = kmalloc(sizeof(struct jump_label_entry), GFP_KERNEL); + if (!e) + return ERR_PTR(-ENOMEM); + + hash = jhash((void *)&key, sizeof(jump_label_t), 0); + head = &jump_label_table[hash & (JUMP_LABEL_TABLE_SIZE - 1)]; + e->key = key; + e->table = table; + e->nr_entries = nr_entries; + INIT_HLIST_HEAD(&(e->modules)); + hlist_add_head(&e->hlist, head); + return e; +} - jump_label_lock(); - if (atomic_add_return(1, &key->enabled) == 1) - jump_label_update(key, JUMP_LABEL_ENABLE); - jump_label_unlock(); +static int +build_jump_label_hashtable(struct jump_entry *start, struct jump_entry *stop) +{ + struct jump_entry *iter, *iter_begin; + struct jump_label_entry *entry; + int count; + + sort_jump_label_entries(start, stop); + iter = start; + while (iter < stop) { + entry = get_jump_label_entry(iter->key); + if (!entry) { + iter_begin = iter; + count = 0; + while ((iter < stop) && + (iter->key == iter_begin->key)) { + iter++; + count++; + } + entry = add_jump_label_entry(iter_begin->key, + count, iter_begin); + if (IS_ERR(entry)) + return PTR_ERR(entry); + } else { + WARN_ONCE(1, KERN_ERR "build_jump_hashtable: unexpected entry!\n"); + return -1; + } + } + return 0; } -void jump_label_dec(struct jump_label_key *key) +/*** + * jump_label_update - update jump label text + * @key - key value associated with a a jump label + * @type - enum set to JUMP_LABEL_ENABLE or JUMP_LABEL_DISABLE + * + * Will enable/disable the jump for jump label @key, depending on the + * value of @type. + * + */ + +void jump_label_update(unsigned long key, enum jump_label_type type) { - if (!atomic_dec_and_mutex_lock(&key->enabled, &jump_label_mutex)) - return; + struct jump_entry *iter; + struct jump_label_entry *entry; + struct hlist_node *module_node; + struct jump_label_module_entry *e_module; + int count; - jump_label_update(key, JUMP_LABEL_DISABLE); + jump_label_lock(); + entry = get_jump_label_entry((jump_label_t)key); + if (entry) { + count = entry->nr_entries; + iter = entry->table; + while (count--) { + if (kernel_text_address(iter->code)) + arch_jump_label_transform(iter, type); + iter++; + } + /* eanble/disable jump labels in modules */ + hlist_for_each_entry(e_module, module_node, &(entry->modules), + hlist) { + count = e_module->nr_entries; + iter = e_module->table; + while (count--) { + if (iter->key && + kernel_text_address(iter->code)) + arch_jump_label_transform(iter, type); + iter++; + } + } + } jump_label_unlock(); } @@ -89,33 +197,77 @@ static int addr_conflict(struct jump_entry *entry, void *start, void *end) return 0; } -static int __jump_label_text_reserved(struct jump_entry *iter_start, - struct jump_entry *iter_stop, void *start, void *end) +#ifdef CONFIG_MODULES + +static int module_conflict(void *start, void *end) { + struct hlist_head *head; + struct hlist_node *node, *node_next, *module_node, *module_node_next; + struct jump_label_entry *e; + struct jump_label_module_entry *e_module; struct jump_entry *iter; + int i, count; + int conflict = 0; + + for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) { + head = &jump_label_table[i]; + hlist_for_each_entry_safe(e, node, node_next, head, hlist) { + hlist_for_each_entry_safe(e_module, module_node, + module_node_next, + &(e->modules), hlist) { + count = e_module->nr_entries; + iter = e_module->table; + while (count--) { + if (addr_conflict(iter, start, end)) { + conflict = 1; + goto out; + } + iter++; + } + } + } + } +out: + return conflict; +} + +#endif + +/*** + * jump_label_text_reserved - check if addr range is reserved + * @start: start text addr + * @end: end text addr + * + * checks if the text addr located between @start and @end + * overlaps with any of the jump label patch addresses. Code + * that wants to modify kernel text should first verify that + * it does not overlap with any of the jump label addresses. + * Caller must hold jump_label_mutex. + * + * returns 1 if there is an overlap, 0 otherwise + */ +int jump_label_text_reserved(void *start, void *end) +{ + struct jump_entry *iter; + struct jump_entry *iter_start = __start___jump_table; + struct jump_entry *iter_stop = __start___jump_table; + int conflict = 0; iter = iter_start; while (iter < iter_stop) { - if (addr_conflict(iter, start, end)) - return 1; + if (addr_conflict(iter, start, end)) { + conflict = 1; + goto out; + } iter++; } - return 0; -} - -static void __jump_label_update(struct jump_label_key *key, - struct jump_entry *entry, int enable) -{ - for (; entry->key == (jump_label_t)(unsigned long)key; entry++) { - /* - * entry->code set to 0 invalidates module init text sections - * kernel_text_address() verifies we are not in core kernel - * init code, see jump_label_invalidate_module_init(). - */ - if (entry->code && kernel_text_address(entry->code)) - arch_jump_label_transform(entry, enable); - } + /* now check modules */ +#ifdef CONFIG_MODULES + conflict = module_conflict(start, end); +#endif +out: + return conflict; } /* @@ -125,173 +277,142 @@ void __weak arch_jump_label_text_poke_early(jump_label_t addr) { } -static __init int jump_label_init(void) +static __init int init_jump_label(void) { + int ret; struct jump_entry *iter_start = __start___jump_table; struct jump_entry *iter_stop = __stop___jump_table; - struct jump_label_key *key = NULL; struct jump_entry *iter; jump_label_lock(); - jump_label_sort_entries(iter_start, iter_stop); - - for (iter = iter_start; iter < iter_stop; iter++) { + ret = build_jump_label_hashtable(__start___jump_table, + __stop___jump_table); + iter = iter_start; + while (iter < iter_stop) { arch_jump_label_text_poke_early(iter->code); - if (iter->key == (jump_label_t)(unsigned long)key) - continue; - - key = (struct jump_label_key *)(unsigned long)iter->key; - atomic_set(&key->enabled, 0); - key->entries = iter; -#ifdef CONFIG_MODULES - key->next = NULL; -#endif + iter++; } jump_label_unlock(); - - return 0; + return ret; } -early_initcall(jump_label_init); +early_initcall(init_jump_label); #ifdef CONFIG_MODULES -struct jump_label_mod { - struct jump_label_mod *next; - struct jump_entry *entries; - struct module *mod; -}; - -static int __jump_label_mod_text_reserved(void *start, void *end) -{ - struct module *mod; - - mod = __module_text_address((unsigned long)start); - if (!mod) - return 0; - - WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod); - - return __jump_label_text_reserved(mod->jump_entries, - mod->jump_entries + mod->num_jump_entries, - start, end); -} - -static void __jump_label_mod_update(struct jump_label_key *key, int enable) -{ - struct jump_label_mod *mod = key->next; - - while (mod) { - __jump_label_update(key, mod->entries, enable); - mod = mod->next; - } -} - -/*** - * apply_jump_label_nops - patch module jump labels with arch_get_jump_label_nop() - * @mod: module to patch - * - * Allow for run-time selection of the optimal nops. Before the module - * loads patch these with arch_get_jump_label_nop(), which is specified by - * the arch specific jump label code. - */ -void jump_label_apply_nops(struct module *mod) +static struct jump_label_module_entry * +add_jump_label_module_entry(struct jump_label_entry *entry, + struct jump_entry *iter_begin, + int count, struct module *mod) { - struct jump_entry *iter_start = mod->jump_entries; - struct jump_entry *iter_stop = iter_start + mod->num_jump_entries; - struct jump_entry *iter; - - /* if the module doesn't have jump label entries, just return */ - if (iter_start == iter_stop) - return; - - for (iter = iter_start; iter < iter_stop; iter++) - arch_jump_label_text_poke_early(iter->code); + struct jump_label_module_entry *e; + + e = kmalloc(sizeof(struct jump_label_module_entry), GFP_KERNEL); + if (!e) + return ERR_PTR(-ENOMEM); + e->mod = mod; + e->nr_entries = count; + e->table = iter_begin; + hlist_add_head(&e->hlist, &entry->modules); + return e; } -static int jump_label_add_module(struct module *mod) +static int add_jump_label_module(struct module *mod) { - struct jump_entry *iter_start = mod->jump_entries; - struct jump_entry *iter_stop = iter_start + mod->num_jump_entries; - struct jump_entry *iter; - struct jump_label_key *key = NULL; - struct jump_label_mod *jlm; + struct jump_entry *iter, *iter_begin; + struct jump_label_entry *entry; + struct jump_label_module_entry *module_entry; + int count; /* if the module doesn't have jump label entries, just return */ - if (iter_start == iter_stop) + if (!mod->num_jump_entries) return 0; - jump_label_sort_entries(iter_start, iter_stop); - - for (iter = iter_start; iter < iter_stop; iter++) { - if (iter->key == (jump_label_t)(unsigned long)key) - continue; - - key = (struct jump_label_key *)(unsigned long)iter->key; - - if (__module_address(iter->key) == mod) { - atomic_set(&key->enabled, 0); - key->entries = iter; - key->next = NULL; - continue; + sort_jump_label_entries(mod->jump_entries, + mod->jump_entries + mod->num_jump_entries); + iter = mod->jump_entries; + while (iter < mod->jump_entries + mod->num_jump_entries) { + entry = get_jump_label_entry(iter->key); + iter_begin = iter; + count = 0; + while ((iter < mod->jump_entries + mod->num_jump_entries) && + (iter->key == iter_begin->key)) { + iter++; + count++; } - - jlm = kzalloc(sizeof(struct jump_label_mod), GFP_KERNEL); - if (!jlm) - return -ENOMEM; - - jlm->mod = mod; - jlm->entries = iter; - jlm->next = key->next; - key->next = jlm; - - if (jump_label_enabled(key)) - __jump_label_update(key, iter, JUMP_LABEL_ENABLE); + if (!entry) { + entry = add_jump_label_entry(iter_begin->key, 0, NULL); + if (IS_ERR(entry)) + return PTR_ERR(entry); + } + module_entry = add_jump_label_module_entry(entry, iter_begin, + count, mod); + if (IS_ERR(module_entry)) + return PTR_ERR(module_entry); } - return 0; } -static void jump_label_del_module(struct module *mod) +static void remove_jump_label_module(struct module *mod) { - struct jump_entry *iter_start = mod->jump_entries; - struct jump_entry *iter_stop = iter_start + mod->num_jump_entries; - struct jump_entry *iter; - struct jump_label_key *key = NULL; - struct jump_label_mod *jlm, **prev; + struct hlist_head *head; + struct hlist_node *node, *node_next, *module_node, *module_node_next; + struct jump_label_entry *e; + struct jump_label_module_entry *e_module; + int i; - for (iter = iter_start; iter < iter_stop; iter++) { - if (iter->key == (jump_label_t)(unsigned long)key) - continue; - - key = (struct jump_label_key *)(unsigned long)iter->key; - - if (__module_address(iter->key) == mod) - continue; - - prev = &key->next; - jlm = key->next; - - while (jlm && jlm->mod != mod) { - prev = &jlm->next; - jlm = jlm->next; - } + /* if the module doesn't have jump label entries, just return */ + if (!mod->num_jump_entries) + return; - if (jlm) { - *prev = jlm->next; - kfree(jlm); + for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) { + head = &jump_label_table[i]; + hlist_for_each_entry_safe(e, node, node_next, head, hlist) { + hlist_for_each_entry_safe(e_module, module_node, + module_node_next, + &(e->modules), hlist) { + if (e_module->mod == mod) { + hlist_del(&e_module->hlist); + kfree(e_module); + } + } + if (hlist_empty(&e->modules) && (e->nr_entries == 0)) { + hlist_del(&e->hlist); + kfree(e); + } } } } -static void jump_label_invalidate_module_init(struct module *mod) +static void remove_jump_label_module_init(struct module *mod) { - struct jump_entry *iter_start = mod->jump_entries; - struct jump_entry *iter_stop = iter_start + mod->num_jump_entries; + struct hlist_head *head; + struct hlist_node *node, *node_next, *module_node, *module_node_next; + struct jump_label_entry *e; + struct jump_label_module_entry *e_module; struct jump_entry *iter; + int i, count; + + /* if the module doesn't have jump label entries, just return */ + if (!mod->num_jump_entries) + return; - for (iter = iter_start; iter < iter_stop; iter++) { - if (within_module_init(iter->code, mod)) - iter->code = 0; + for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) { + head = &jump_label_table[i]; + hlist_for_each_entry_safe(e, node, node_next, head, hlist) { + hlist_for_each_entry_safe(e_module, module_node, + module_node_next, + &(e->modules), hlist) { + if (e_module->mod != mod) + continue; + count = e_module->nr_entries; + iter = e_module->table; + while (count--) { + if (within_module_init(iter->code, mod)) + iter->key = 0; + iter++; + } + } + } } } @@ -305,77 +426,59 @@ jump_label_module_notify(struct notifier_block *self, unsigned long val, switch (val) { case MODULE_STATE_COMING: jump_label_lock(); - ret = jump_label_add_module(mod); + ret = add_jump_label_module(mod); if (ret) - jump_label_del_module(mod); + remove_jump_label_module(mod); jump_label_unlock(); break; case MODULE_STATE_GOING: jump_label_lock(); - jump_label_del_module(mod); + remove_jump_label_module(mod); jump_label_unlock(); break; case MODULE_STATE_LIVE: jump_label_lock(); - jump_label_invalidate_module_init(mod); + remove_jump_label_module_init(mod); jump_label_unlock(); break; } - - return notifier_from_errno(ret); -} - -struct notifier_block jump_label_module_nb = { - .notifier_call = jump_label_module_notify, - .priority = 1, /* higher than tracepoints */ -}; - -static __init int jump_label_init_module(void) -{ - return register_module_notifier(&jump_label_module_nb); + return ret; } -early_initcall(jump_label_init_module); - -#endif /* CONFIG_MODULES */ /*** - * jump_label_text_reserved - check if addr range is reserved - * @start: start text addr - * @end: end text addr - * - * checks if the text addr located between @start and @end - * overlaps with any of the jump label patch addresses. Code - * that wants to modify kernel text should first verify that - * it does not overlap with any of the jump label addresses. - * Caller must hold jump_label_mutex. + * apply_jump_label_nops - patch module jump labels with arch_get_jump_label_nop() + * @mod: module to patch * - * returns 1 if there is an overlap, 0 otherwise + * Allow for run-time selection of the optimal nops. Before the module + * loads patch these with arch_get_jump_label_nop(), which is specified by + * the arch specific jump label code. */ -int jump_label_text_reserved(void *start, void *end) +void jump_label_apply_nops(struct module *mod) { - int ret = __jump_label_text_reserved(__start___jump_table, - __stop___jump_table, start, end); + struct jump_entry *iter; - if (ret) - return ret; + /* if the module doesn't have jump label entries, just return */ + if (!mod->num_jump_entries) + return; -#ifdef CONFIG_MODULES - ret = __jump_label_mod_text_reserved(start, end); -#endif - return ret; + iter = mod->jump_entries; + while (iter < mod->jump_entries + mod->num_jump_entries) { + arch_jump_label_text_poke_early(iter->code); + iter++; + } } -static void jump_label_update(struct jump_label_key *key, int enable) -{ - struct jump_entry *entry = key->entries; - - /* if there are no users, entry can be NULL */ - if (entry) - __jump_label_update(key, entry, enable); +struct notifier_block jump_label_module_nb = { + .notifier_call = jump_label_module_notify, + .priority = 0, +}; -#ifdef CONFIG_MODULES - __jump_label_mod_update(key, enable); -#endif +static __init int init_jump_label_module(void) +{ + return register_module_notifier(&jump_label_module_nb); } +early_initcall(init_jump_label_module); + +#endif /* CONFIG_MODULES */ #endif diff --git a/trunk/kernel/kexec.c b/trunk/kernel/kexec.c index 55936f9cb251..87b77de03dd3 100644 --- a/trunk/kernel/kexec.c +++ b/trunk/kernel/kexec.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -1532,6 +1533,11 @@ int kernel_kexec(void) local_irq_disable(); /* Suspend system devices */ error = sysdev_suspend(PMSG_FREEZE); + if (!error) { + error = syscore_suspend(); + if (error) + sysdev_resume(); + } if (error) goto Enable_irqs; } else @@ -1546,6 +1552,7 @@ int kernel_kexec(void) #ifdef CONFIG_KEXEC_JUMP if (kexec_image->preserve_context) { + syscore_resume(); sysdev_resume(); Enable_irqs: local_irq_enable(); diff --git a/trunk/kernel/perf_event.c b/trunk/kernel/perf_event.c index 440bc485bbff..8e81a9860a0d 100644 --- a/trunk/kernel/perf_event.c +++ b/trunk/kernel/perf_event.c @@ -125,7 +125,7 @@ enum event_type_t { * perf_sched_events : >0 events exist * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu */ -struct jump_label_key perf_sched_events __read_mostly; +atomic_t perf_sched_events __read_mostly; static DEFINE_PER_CPU(atomic_t, perf_cgroup_events); static atomic_t nr_mmap_events __read_mostly; @@ -5429,7 +5429,7 @@ static int swevent_hlist_get(struct perf_event *event) return err; } -struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX]; +atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX]; static void sw_perf_event_destroy(struct perf_event *event) { diff --git a/trunk/kernel/power/hibernate.c b/trunk/kernel/power/hibernate.c index aeabd26e3342..50aae660174d 100644 --- a/trunk/kernel/power/hibernate.c +++ b/trunk/kernel/power/hibernate.c @@ -273,8 +273,11 @@ static int create_image(int platform_mode) local_irq_disable(); error = sysdev_suspend(PMSG_FREEZE); - if (!error) + if (!error) { error = syscore_suspend(); + if (error) + sysdev_resume(); + } if (error) { printk(KERN_ERR "PM: Some system devices failed to power down, " "aborting hibernation\n"); @@ -407,8 +410,11 @@ static int resume_target_kernel(bool platform_mode) local_irq_disable(); error = sysdev_suspend(PMSG_QUIESCE); - if (!error) + if (!error) { error = syscore_suspend(); + if (error) + sysdev_resume(); + } if (error) goto Enable_irqs; diff --git a/trunk/kernel/power/suspend.c b/trunk/kernel/power/suspend.c index 2814c32aed51..8935369d503a 100644 --- a/trunk/kernel/power/suspend.c +++ b/trunk/kernel/power/suspend.c @@ -164,8 +164,11 @@ static int suspend_enter(suspend_state_t state) BUG_ON(!irqs_disabled()); error = sysdev_suspend(PMSG_SUSPEND); - if (!error) + if (!error) { error = syscore_suspend(); + if (error) + sysdev_resume(); + } if (!error) { if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) { error = suspend_ops->enter(state); diff --git a/trunk/kernel/trace/Kconfig b/trunk/kernel/trace/Kconfig index 61d7d59f4a1a..2ad39e556cb4 100644 --- a/trunk/kernel/trace/Kconfig +++ b/trunk/kernel/trace/Kconfig @@ -141,7 +141,7 @@ if FTRACE config FUNCTION_TRACER bool "Kernel Function Tracer" depends on HAVE_FUNCTION_TRACER - select FRAME_POINTER if !ARM_UNWIND && !S390 + select FRAME_POINTER if !ARM_UNWIND && !S390 && !MICROBLAZE select KALLSYMS select GENERIC_TRACER select CONTEXT_SWITCH_TRACER diff --git a/trunk/kernel/trace/ftrace.c b/trunk/kernel/trace/ftrace.c index ee24fa1935ac..666880d051ef 100644 --- a/trunk/kernel/trace/ftrace.c +++ b/trunk/kernel/trace/ftrace.c @@ -2413,14 +2413,16 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable) ftrace_match_records(parser->buffer, parser->idx, enable); } - mutex_lock(&ftrace_lock); - if (ftrace_start_up && ftrace_enabled) - ftrace_run_update_code(FTRACE_ENABLE_CALLS); - mutex_unlock(&ftrace_lock); - trace_parser_put(parser); kfree(iter); + if (file->f_mode & FMODE_WRITE) { + mutex_lock(&ftrace_lock); + if (ftrace_start_up && ftrace_enabled) + ftrace_run_update_code(FTRACE_ENABLE_CALLS); + mutex_unlock(&ftrace_lock); + } + mutex_unlock(&ftrace_regex_lock); return 0; } diff --git a/trunk/kernel/trace/trace.c b/trunk/kernel/trace/trace.c index e0e14ce0caab..d38c16a06a6f 100644 --- a/trunk/kernel/trace/trace.c +++ b/trunk/kernel/trace/trace.c @@ -2013,10 +2013,9 @@ enum print_line_t print_trace_line(struct trace_iterator *iter) { enum print_line_t ret; - if (iter->lost_events && - !trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", - iter->cpu, iter->lost_events)) - return TRACE_TYPE_PARTIAL_LINE; + if (iter->lost_events) + trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", + iter->cpu, iter->lost_events); if (iter->trace && iter->trace->print_line) { ret = iter->trace->print_line(iter); @@ -3230,14 +3229,6 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, if (iter->seq.len >= cnt) break; - - /* - * Setting the full flag means we reached the trace_seq buffer - * size and we should leave by partial output condition above. - * One of the trace_seq_* functions is not used properly. - */ - WARN_ONCE(iter->seq.full, "full flag set for trace type %d", - iter->ent->type); } trace_access_unlock(iter->cpu_file); trace_event_read_unlock(); diff --git a/trunk/kernel/trace/trace_output.c b/trunk/kernel/trace/trace_output.c index cf535ccedc86..456be9063c2d 100644 --- a/trunk/kernel/trace/trace_output.c +++ b/trunk/kernel/trace/trace_output.c @@ -830,9 +830,6 @@ EXPORT_SYMBOL_GPL(unregister_ftrace_event); enum print_line_t trace_nop_print(struct trace_iterator *iter, int flags, struct trace_event *event) { - if (!trace_seq_printf(&iter->seq, "type: %d\n", iter->ent->type)) - return TRACE_TYPE_PARTIAL_LINE; - return TRACE_TYPE_HANDLED; } diff --git a/trunk/kernel/trace/trace_printk.c b/trunk/kernel/trace/trace_printk.c index dff763b7baf1..2547d8813cf0 100644 --- a/trunk/kernel/trace/trace_printk.c +++ b/trunk/kernel/trace/trace_printk.c @@ -32,7 +32,7 @@ static DEFINE_MUTEX(btrace_mutex); struct trace_bprintk_fmt { struct list_head list; - const char *fmt; + char fmt[0]; }; static inline struct trace_bprintk_fmt *lookup_format(const char *fmt) @@ -49,7 +49,6 @@ static void hold_module_trace_bprintk_format(const char **start, const char **end) { const char **iter; - char *fmt; mutex_lock(&btrace_mutex); for (iter = start; iter < end; iter++) { @@ -59,18 +58,14 @@ void hold_module_trace_bprintk_format(const char **start, const char **end) continue; } - tb_fmt = kmalloc(sizeof(*tb_fmt), GFP_KERNEL); - if (tb_fmt) - fmt = kmalloc(strlen(*iter) + 1, GFP_KERNEL); - if (tb_fmt && fmt) { + tb_fmt = kmalloc(offsetof(struct trace_bprintk_fmt, fmt) + + strlen(*iter) + 1, GFP_KERNEL); + if (tb_fmt) { list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list); - strcpy(fmt, *iter); - tb_fmt->fmt = fmt; + strcpy(tb_fmt->fmt, *iter); *iter = tb_fmt->fmt; - } else { - kfree(tb_fmt); + } else *iter = NULL; - } } mutex_unlock(&btrace_mutex); } @@ -89,76 +84,6 @@ static int module_trace_bprintk_format_notify(struct notifier_block *self, return 0; } -/* - * The debugfs/tracing/printk_formats file maps the addresses with - * the ASCII formats that are used in the bprintk events in the - * buffer. For userspace tools to be able to decode the events from - * the buffer, they need to be able to map the address with the format. - * - * The addresses of the bprintk formats are in their own section - * __trace_printk_fmt. But for modules we copy them into a link list. - * The code to print the formats and their addresses passes around the - * address of the fmt string. If the fmt address passed into the seq - * functions is within the kernel core __trace_printk_fmt section, then - * it simply uses the next pointer in the list. - * - * When the fmt pointer is outside the kernel core __trace_printk_fmt - * section, then we need to read the link list pointers. The trick is - * we pass the address of the string to the seq function just like - * we do for the kernel core formats. To get back the structure that - * holds the format, we simply use containerof() and then go to the - * next format in the list. - */ -static const char ** -find_next_mod_format(int start_index, void *v, const char **fmt, loff_t *pos) -{ - struct trace_bprintk_fmt *mod_fmt; - - if (list_empty(&trace_bprintk_fmt_list)) - return NULL; - - /* - * v will point to the address of the fmt record from t_next - * v will be NULL from t_start. - * If this is the first pointer or called from start - * then we need to walk the list. - */ - if (!v || start_index == *pos) { - struct trace_bprintk_fmt *p; - - /* search the module list */ - list_for_each_entry(p, &trace_bprintk_fmt_list, list) { - if (start_index == *pos) - return &p->fmt; - start_index++; - } - /* pos > index */ - return NULL; - } - - /* - * v points to the address of the fmt field in the mod list - * structure that holds the module print format. - */ - mod_fmt = container_of(v, typeof(*mod_fmt), fmt); - if (mod_fmt->list.next == &trace_bprintk_fmt_list) - return NULL; - - mod_fmt = container_of(mod_fmt->list.next, typeof(*mod_fmt), list); - - return &mod_fmt->fmt; -} - -static void format_mod_start(void) -{ - mutex_lock(&btrace_mutex); -} - -static void format_mod_stop(void) -{ - mutex_unlock(&btrace_mutex); -} - #else /* !CONFIG_MODULES */ __init static int module_trace_bprintk_format_notify(struct notifier_block *self, @@ -166,13 +91,6 @@ module_trace_bprintk_format_notify(struct notifier_block *self, { return 0; } -static inline const char ** -find_next_mod_format(int start_index, void *v, const char **fmt, loff_t *pos) -{ - return NULL; -} -static inline void format_mod_start(void) { } -static inline void format_mod_stop(void) { } #endif /* CONFIG_MODULES */ @@ -235,33 +153,20 @@ int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap) } EXPORT_SYMBOL_GPL(__ftrace_vprintk); -static const char **find_next(void *v, loff_t *pos) -{ - const char **fmt = v; - int start_index; - - if (!fmt) - fmt = __start___trace_bprintk_fmt + *pos; - - start_index = __stop___trace_bprintk_fmt - __start___trace_bprintk_fmt; - - if (*pos < start_index) - return fmt; - - return find_next_mod_format(start_index, v, fmt, pos); -} - static void * t_start(struct seq_file *m, loff_t *pos) { - format_mod_start(); - return find_next(NULL, pos); + const char **fmt = __start___trace_bprintk_fmt + *pos; + + if ((unsigned long)fmt >= (unsigned long)__stop___trace_bprintk_fmt) + return NULL; + return fmt; } static void *t_next(struct seq_file *m, void * v, loff_t *pos) { (*pos)++; - return find_next(v, pos); + return t_start(m, pos); } static int t_show(struct seq_file *m, void *v) @@ -300,7 +205,6 @@ static int t_show(struct seq_file *m, void *v) static void t_stop(struct seq_file *m, void *p) { - format_mod_stop(); } static const struct seq_operations show_format_seq_ops = { diff --git a/trunk/kernel/tracepoint.c b/trunk/kernel/tracepoint.c index b219f1449c54..68187af4889e 100644 --- a/trunk/kernel/tracepoint.c +++ b/trunk/kernel/tracepoint.c @@ -251,9 +251,9 @@ static void set_tracepoint(struct tracepoint_entry **entry, { WARN_ON(strcmp((*entry)->name, elem->name) != 0); - if (elem->regfunc && !jump_label_enabled(&elem->key) && active) + if (elem->regfunc && !elem->state && active) elem->regfunc(); - else if (elem->unregfunc && jump_label_enabled(&elem->key) && !active) + else if (elem->unregfunc && elem->state && !active) elem->unregfunc(); /* @@ -264,10 +264,13 @@ static void set_tracepoint(struct tracepoint_entry **entry, * is used. */ rcu_assign_pointer(elem->funcs, (*entry)->funcs); - if (active && !jump_label_enabled(&elem->key)) - jump_label_inc(&elem->key); - else if (!active && jump_label_enabled(&elem->key)) - jump_label_dec(&elem->key); + if (!elem->state && active) { + jump_label_enable(&elem->state); + elem->state = active; + } else if (elem->state && !active) { + jump_label_disable(&elem->state); + elem->state = active; + } } /* @@ -278,11 +281,13 @@ static void set_tracepoint(struct tracepoint_entry **entry, */ static void disable_tracepoint(struct tracepoint *elem) { - if (elem->unregfunc && jump_label_enabled(&elem->key)) + if (elem->unregfunc && elem->state) elem->unregfunc(); - if (jump_label_enabled(&elem->key)) - jump_label_dec(&elem->key); + if (elem->state) { + jump_label_disable(&elem->state); + elem->state = 0; + } rcu_assign_pointer(elem->funcs, NULL); } diff --git a/trunk/scripts/kconfig/conf.c b/trunk/scripts/kconfig/conf.c index 659326c3e895..006ad817cd5f 100644 --- a/trunk/scripts/kconfig/conf.c +++ b/trunk/scripts/kconfig/conf.c @@ -332,7 +332,7 @@ static int conf_choice(struct menu *menu) } if (!child) continue; - if (line[strlen(line) - 1] == '?') { + if (line[0] && line[strlen(line) - 1] == '?') { print_help(child); continue; } diff --git a/trunk/security/capability.c b/trunk/security/capability.c index 2984ea4f776f..bbb51156261b 100644 --- a/trunk/security/capability.c +++ b/trunk/security/capability.c @@ -181,7 +181,7 @@ static int cap_inode_follow_link(struct dentry *dentry, return 0; } -static int cap_inode_permission(struct inode *inode, int mask) +static int cap_inode_permission(struct inode *inode, int mask, unsigned flags) { return 0; } diff --git a/trunk/security/security.c b/trunk/security/security.c index 101142369db4..4ba6d4cc061f 100644 --- a/trunk/security/security.c +++ b/trunk/security/security.c @@ -518,16 +518,14 @@ int security_inode_permission(struct inode *inode, int mask) { if (unlikely(IS_PRIVATE(inode))) return 0; - return security_ops->inode_permission(inode, mask); + return security_ops->inode_permission(inode, mask, 0); } int security_inode_exec_permission(struct inode *inode, unsigned int flags) { if (unlikely(IS_PRIVATE(inode))) return 0; - if (flags) - return -ECHILD; - return security_ops->inode_permission(inode, MAY_EXEC); + return security_ops->inode_permission(inode, MAY_EXEC, flags); } int security_inode_setattr(struct dentry *dentry, struct iattr *attr) diff --git a/trunk/security/selinux/avc.c b/trunk/security/selinux/avc.c index 9da6420e2056..1d027e29ce8d 100644 --- a/trunk/security/selinux/avc.c +++ b/trunk/security/selinux/avc.c @@ -471,6 +471,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) * @avd: access vector decisions * @result: result from avc_has_perm_noaudit * @a: auxiliary audit data + * @flags: VFS walk flags * * Audit the granting or denial of permissions in accordance * with the policy. This function is typically called by @@ -481,9 +482,10 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) * be performed under a lock, to allow the lock to be released * before calling the auditing code. */ -void avc_audit(u32 ssid, u32 tsid, +int avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested, - struct av_decision *avd, int result, struct common_audit_data *a) + struct av_decision *avd, int result, struct common_audit_data *a, + unsigned flags) { struct common_audit_data stack_data; u32 denied, audited; @@ -515,11 +517,24 @@ void avc_audit(u32 ssid, u32 tsid, else audited = requested & avd->auditallow; if (!audited) - return; + return 0; + if (!a) { a = &stack_data; COMMON_AUDIT_DATA_INIT(a, NONE); } + + /* + * When in a RCU walk do the audit on the RCU retry. This is because + * the collection of the dname in an inode audit message is not RCU + * safe. Note this may drop some audits when the situation changes + * during retry. However this is logically just as if the operation + * happened a little later. + */ + if ((a->type == LSM_AUDIT_DATA_FS) && + (flags & IPERM_FLAG_RCU)) + return -ECHILD; + a->selinux_audit_data.tclass = tclass; a->selinux_audit_data.requested = requested; a->selinux_audit_data.ssid = ssid; @@ -529,6 +544,7 @@ void avc_audit(u32 ssid, u32 tsid, a->lsm_pre_audit = avc_audit_pre_callback; a->lsm_post_audit = avc_audit_post_callback; common_lsm_audit(a); + return 0; } /** @@ -793,6 +809,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, * @tclass: target security class * @requested: requested permissions, interpreted based on @tclass * @auditdata: auxiliary audit data + * @flags: VFS walk flags * * Check the AVC to determine whether the @requested permissions are granted * for the SID pair (@ssid, @tsid), interpreting the permissions @@ -802,14 +819,19 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, * permissions are granted, -%EACCES if any permissions are denied, or * another -errno upon other errors. */ -int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, - u32 requested, struct common_audit_data *auditdata) +int avc_has_perm_flags(u32 ssid, u32 tsid, u16 tclass, + u32 requested, struct common_audit_data *auditdata, + unsigned flags) { struct av_decision avd; - int rc; + int rc, rc2; rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd); - avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); + + rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata, + flags); + if (rc2) + return rc2; return rc; } diff --git a/trunk/security/selinux/hooks.c b/trunk/security/selinux/hooks.c index f9c3764e4859..f7cf0ea6faea 100644 --- a/trunk/security/selinux/hooks.c +++ b/trunk/security/selinux/hooks.c @@ -1446,8 +1446,11 @@ static int task_has_capability(struct task_struct *tsk, } rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); - if (audit == SECURITY_CAP_AUDIT) - avc_audit(sid, sid, sclass, av, &avd, rc, &ad); + if (audit == SECURITY_CAP_AUDIT) { + int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0); + if (rc2) + return rc2; + } return rc; } @@ -1467,7 +1470,8 @@ static int task_has_system(struct task_struct *tsk, static int inode_has_perm(const struct cred *cred, struct inode *inode, u32 perms, - struct common_audit_data *adp) + struct common_audit_data *adp, + unsigned flags) { struct inode_security_struct *isec; struct common_audit_data ad; @@ -1487,7 +1491,7 @@ static int inode_has_perm(const struct cred *cred, ad.u.fs.inode = inode; } - return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp); + return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); } /* Same as inode_has_perm, but pass explicit audit data containing @@ -1504,7 +1508,7 @@ static inline int dentry_has_perm(const struct cred *cred, COMMON_AUDIT_DATA_INIT(&ad, FS); ad.u.fs.path.mnt = mnt; ad.u.fs.path.dentry = dentry; - return inode_has_perm(cred, inode, av, &ad); + return inode_has_perm(cred, inode, av, &ad, 0); } /* Check whether a task can use an open file descriptor to @@ -1540,7 +1544,7 @@ static int file_has_perm(const struct cred *cred, /* av is zero if only checking access to the descriptor. */ rc = 0; if (av) - rc = inode_has_perm(cred, inode, av, &ad); + rc = inode_has_perm(cred, inode, av, &ad, 0); out: return rc; @@ -2103,7 +2107,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, file = file_priv->file; inode = file->f_path.dentry->d_inode; if (inode_has_perm(cred, inode, - FILE__READ | FILE__WRITE, NULL)) { + FILE__READ | FILE__WRITE, NULL, 0)) { drop_tty = 1; } } @@ -2635,7 +2639,7 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na return dentry_has_perm(cred, NULL, dentry, FILE__READ); } -static int selinux_inode_permission(struct inode *inode, int mask) +static int selinux_inode_permission(struct inode *inode, int mask, unsigned flags) { const struct cred *cred = current_cred(); struct common_audit_data ad; @@ -2657,7 +2661,7 @@ static int selinux_inode_permission(struct inode *inode, int mask) perms = file_mask_to_av(inode->i_mode, mask); - return inode_has_perm(cred, inode, perms, &ad); + return inode_has_perm(cred, inode, perms, &ad, flags); } static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) @@ -3205,7 +3209,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred) * new inode label or new policy. * This check is not redundant - do not remove. */ - return inode_has_perm(cred, inode, open_file_to_av(file), NULL); + return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0); } /* task security operations */ diff --git a/trunk/security/selinux/include/avc.h b/trunk/security/selinux/include/avc.h index 5615081b73ec..e77b2ac2908b 100644 --- a/trunk/security/selinux/include/avc.h +++ b/trunk/security/selinux/include/avc.h @@ -54,11 +54,11 @@ struct avc_cache_stats { void __init avc_init(void); -void avc_audit(u32 ssid, u32 tsid, +int avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested, struct av_decision *avd, int result, - struct common_audit_data *a); + struct common_audit_data *a, unsigned flags); #define AVC_STRICT 1 /* Ignore permissive mode. */ int avc_has_perm_noaudit(u32 ssid, u32 tsid, @@ -66,9 +66,17 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, unsigned flags, struct av_decision *avd); -int avc_has_perm(u32 ssid, u32 tsid, - u16 tclass, u32 requested, - struct common_audit_data *auditdata); +int avc_has_perm_flags(u32 ssid, u32 tsid, + u16 tclass, u32 requested, + struct common_audit_data *auditdata, + unsigned); + +static inline int avc_has_perm(u32 ssid, u32 tsid, + u16 tclass, u32 requested, + struct common_audit_data *auditdata) +{ + return avc_has_perm_flags(ssid, tsid, tclass, requested, auditdata, 0); +} u32 avc_policy_seqno(void); diff --git a/trunk/security/smack/smack_lsm.c b/trunk/security/smack/smack_lsm.c index c6f8fcadae07..400a5d5cde61 100644 --- a/trunk/security/smack/smack_lsm.c +++ b/trunk/security/smack/smack_lsm.c @@ -686,7 +686,7 @@ static int smack_inode_rename(struct inode *old_inode, * * Returns 0 if access is permitted, -EACCES otherwise */ -static int smack_inode_permission(struct inode *inode, int mask) +static int smack_inode_permission(struct inode *inode, int mask, unsigned flags) { struct smk_audit_info ad; @@ -696,6 +696,10 @@ static int smack_inode_permission(struct inode *inode, int mask) */ if (mask == 0) return 0; + + /* May be droppable after audit */ + if (flags & IPERM_FLAG_RCU) + return -ECHILD; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); smk_ad_setfield_u_fs_inode(&ad, inode); return smk_curacc(smk_of_inode(inode), mask, &ad); diff --git a/trunk/sound/pci/hda/hda_codec.c b/trunk/sound/pci/hda/hda_codec.c index 430f41db6044..759ade12e758 100644 --- a/trunk/sound/pci/hda/hda_codec.c +++ b/trunk/sound/pci/hda/hda_codec.c @@ -937,6 +937,7 @@ void snd_hda_shutup_pins(struct hda_codec *codec) } EXPORT_SYMBOL_HDA(snd_hda_shutup_pins); +#ifdef SND_HDA_NEEDS_RESUME /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */ static void restore_shutup_pins(struct hda_codec *codec) { @@ -953,6 +954,7 @@ static void restore_shutup_pins(struct hda_codec *codec) } codec->pins_shutup = 0; } +#endif static void init_hda_cache(struct hda_cache_rec *cache, unsigned int record_size); @@ -1329,6 +1331,7 @@ static void purify_inactive_streams(struct hda_codec *codec) } } +#ifdef SND_HDA_NEEDS_RESUME /* clean up all streams; called from suspend */ static void hda_cleanup_all_streams(struct hda_codec *codec) { @@ -1340,6 +1343,7 @@ static void hda_cleanup_all_streams(struct hda_codec *codec) really_cleanup_stream(codec, p); } } +#endif /* * amp access functions diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index 52928d9a72da..d3bd2c10180f 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -14868,6 +14868,23 @@ static void alc269_fixup_hweq(struct hda_codec *codec, alc_write_coef_idx(codec, 0x1e, coef | 0x80); } +static void alc271_fixup_dmic(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + static struct hda_verb verbs[] = { + {0x20, AC_VERB_SET_COEF_INDEX, 0x0d}, + {0x20, AC_VERB_SET_PROC_COEF, 0x4000}, + {} + }; + unsigned int cfg; + + if (strcmp(codec->chip_name, "ALC271X")) + return; + cfg = snd_hda_codec_get_pincfg(codec, 0x12); + if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED) + snd_hda_sequence_write(codec, verbs); +} + enum { ALC269_FIXUP_SONY_VAIO, ALC275_FIXUP_SONY_VAIO_GPIO2, @@ -14876,6 +14893,7 @@ enum { ALC269_FIXUP_ASUS_G73JW, ALC269_FIXUP_LENOVO_EAPD, ALC275_FIXUP_SONY_HWEQ, + ALC271_FIXUP_DMIC, }; static const struct alc_fixup alc269_fixups[] = { @@ -14929,7 +14947,11 @@ static const struct alc_fixup alc269_fixups[] = { .v.func = alc269_fixup_hweq, .chained = true, .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2 - } + }, + [ALC271_FIXUP_DMIC] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc271_fixup_dmic, + }, }; static struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -14938,6 +14960,7 @@ static struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), + SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), diff --git a/trunk/sound/soc/codecs/jz4740.c b/trunk/sound/soc/codecs/jz4740.c index f7cd346fd727..f5ccdbf7ebc6 100644 --- a/trunk/sound/soc/codecs/jz4740.c +++ b/trunk/sound/soc/codecs/jz4740.c @@ -308,8 +308,6 @@ static int jz4740_codec_dev_probe(struct snd_soc_codec *codec) snd_soc_dapm_add_routes(dapm, jz4740_codec_dapm_routes, ARRAY_SIZE(jz4740_codec_dapm_routes)); - snd_soc_dapm_new_widgets(codec); - jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; diff --git a/trunk/sound/soc/codecs/sn95031.c b/trunk/sound/soc/codecs/sn95031.c index a54d2a5b28f6..4d9fb279e146 100644 --- a/trunk/sound/soc/codecs/sn95031.c +++ b/trunk/sound/soc/codecs/sn95031.c @@ -927,7 +927,7 @@ static struct platform_driver sn95031_codec_driver = { .owner = THIS_MODULE, }, .probe = sn95031_device_probe, - .remove = sn95031_device_remove, + .remove = __devexit_p(sn95031_device_remove), }; static int __init sn95031_init(void) diff --git a/trunk/sound/soc/codecs/wm8903.c b/trunk/sound/soc/codecs/wm8903.c index ae1cadfae84c..f52b623bb692 100644 --- a/trunk/sound/soc/codecs/wm8903.c +++ b/trunk/sound/soc/codecs/wm8903.c @@ -247,8 +247,6 @@ static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int re case WM8903_REVISION_NUMBER: case WM8903_INTERRUPT_STATUS_1: case WM8903_WRITE_SEQUENCER_4: - case WM8903_POWER_MANAGEMENT_3: - case WM8903_POWER_MANAGEMENT_2: case WM8903_DC_SERVO_READBACK_1: case WM8903_DC_SERVO_READBACK_2: case WM8903_DC_SERVO_READBACK_3: @@ -875,34 +873,40 @@ SND_SOC_DAPM_MIXER("Left Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 1, 0, SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0, right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), -SND_SOC_DAPM_PGA_S("Left Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0, - 4, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("Right Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0, +SND_SOC_DAPM_PGA_S("Left Headphone Output PGA", 0, WM8903_POWER_MANAGEMENT_2, + 1, 0, NULL, 0), +SND_SOC_DAPM_PGA_S("Right Headphone Output PGA", 0, WM8903_POWER_MANAGEMENT_2, 0, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("Left Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 4, 0, +SND_SOC_DAPM_PGA_S("Left Line Output PGA", 0, WM8903_POWER_MANAGEMENT_3, 1, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("Right Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 0, 0, +SND_SOC_DAPM_PGA_S("Right Line Output PGA", 0, WM8903_POWER_MANAGEMENT_3, 0, 0, NULL, 0), SND_SOC_DAPM_PGA_S("HPL_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 7, 0, NULL, 0), SND_SOC_DAPM_PGA_S("HPL_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPL_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 5, 0, NULL, 0), +SND_SOC_DAPM_PGA_S("HPL_ENA_DLY", 2, WM8903_ANALOGUE_HP_0, 5, 0, NULL, 0), +SND_SOC_DAPM_PGA_S("HPL_ENA", 1, WM8903_ANALOGUE_HP_0, 4, 0, NULL, 0), SND_SOC_DAPM_PGA_S("HPR_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 3, 0, NULL, 0), SND_SOC_DAPM_PGA_S("HPR_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 2, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPR_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 1, 0, NULL, 0), +SND_SOC_DAPM_PGA_S("HPR_ENA_DLY", 2, WM8903_ANALOGUE_HP_0, 1, 0, NULL, 0), +SND_SOC_DAPM_PGA_S("HPR_ENA", 1, WM8903_ANALOGUE_HP_0, 0, 0, NULL, 0), SND_SOC_DAPM_PGA_S("LINEOUTL_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 7, 0, NULL, 0), SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 5, 0, +SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_DLY", 2, WM8903_ANALOGUE_LINEOUT_0, 5, 0, + NULL, 0), +SND_SOC_DAPM_PGA_S("LINEOUTL_ENA", 1, WM8903_ANALOGUE_LINEOUT_0, 4, 0, NULL, 0), SND_SOC_DAPM_PGA_S("LINEOUTR_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 3, 0, NULL, 0), SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 2, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 1, 0, +SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_DLY", 2, WM8903_ANALOGUE_LINEOUT_0, 1, 0, + NULL, 0), +SND_SOC_DAPM_PGA_S("LINEOUTR_ENA", 1, WM8903_ANALOGUE_LINEOUT_0, 0, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("DCS Master", WM8903_DC_SERVO_0, 4, 0, NULL, 0), @@ -1037,10 +1041,14 @@ static const struct snd_soc_dapm_route intercon[] = { { "Left Speaker PGA", NULL, "Left Speaker Mixer" }, { "Right Speaker PGA", NULL, "Right Speaker Mixer" }, - { "HPL_ENA_DLY", NULL, "Left Headphone Output PGA" }, - { "HPR_ENA_DLY", NULL, "Right Headphone Output PGA" }, - { "LINEOUTL_ENA_DLY", NULL, "Left Line Output PGA" }, - { "LINEOUTR_ENA_DLY", NULL, "Right Line Output PGA" }, + { "HPL_ENA", NULL, "Left Headphone Output PGA" }, + { "HPR_ENA", NULL, "Right Headphone Output PGA" }, + { "HPL_ENA_DLY", NULL, "HPL_ENA" }, + { "HPR_ENA_DLY", NULL, "HPR_ENA" }, + { "LINEOUTL_ENA", NULL, "Left Line Output PGA" }, + { "LINEOUTR_ENA", NULL, "Right Line Output PGA" }, + { "LINEOUTL_ENA_DLY", NULL, "LINEOUTL_ENA" }, + { "LINEOUTR_ENA_DLY", NULL, "LINEOUTR_ENA" }, { "HPL_DCS", NULL, "DCS Master" }, { "HPR_DCS", NULL, "DCS Master" }, diff --git a/trunk/sound/soc/codecs/wm8994.c b/trunk/sound/soc/codecs/wm8994.c index 3290333b2bb9..84e1bd1d2822 100644 --- a/trunk/sound/soc/codecs/wm8994.c +++ b/trunk/sound/soc/codecs/wm8994.c @@ -3261,20 +3261,36 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch volume updates (right only; we always do left then right). */ + snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME, + WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); + snd_soc_update_bits(codec, WM8994_AIF1_DAC2_LEFT_VOLUME, + WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); snd_soc_update_bits(codec, WM8994_AIF1_DAC2_RIGHT_VOLUME, WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); + snd_soc_update_bits(codec, WM8994_AIF2_DAC_LEFT_VOLUME, + WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); snd_soc_update_bits(codec, WM8994_AIF2_DAC_RIGHT_VOLUME, WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); + snd_soc_update_bits(codec, WM8994_AIF1_ADC1_LEFT_VOLUME, + WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); snd_soc_update_bits(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME, WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); + snd_soc_update_bits(codec, WM8994_AIF1_ADC2_LEFT_VOLUME, + WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); snd_soc_update_bits(codec, WM8994_AIF1_ADC2_RIGHT_VOLUME, WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); + snd_soc_update_bits(codec, WM8994_AIF2_ADC_LEFT_VOLUME, + WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); snd_soc_update_bits(codec, WM8994_AIF2_ADC_RIGHT_VOLUME, WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); + snd_soc_update_bits(codec, WM8994_DAC1_LEFT_VOLUME, + WM8994_DAC1_VU, WM8994_DAC1_VU); snd_soc_update_bits(codec, WM8994_DAC1_RIGHT_VOLUME, WM8994_DAC1_VU, WM8994_DAC1_VU); + snd_soc_update_bits(codec, WM8994_DAC2_LEFT_VOLUME, + WM8994_DAC2_VU, WM8994_DAC2_VU); snd_soc_update_bits(codec, WM8994_DAC2_RIGHT_VOLUME, WM8994_DAC2_VU, WM8994_DAC2_VU); diff --git a/trunk/sound/soc/codecs/wm_hubs.c b/trunk/sound/soc/codecs/wm_hubs.c index 7b6b3c18e299..4005e9af5d61 100644 --- a/trunk/sound/soc/codecs/wm_hubs.c +++ b/trunk/sound/soc/codecs/wm_hubs.c @@ -740,12 +740,12 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "SPKL", "Input Switch", "MIXINL" }, { "SPKL", "IN1LP Switch", "IN1LP" }, - { "SPKL", "Output Switch", "Left Output Mixer" }, + { "SPKL", "Output Switch", "Left Output PGA" }, { "SPKL", NULL, "TOCLK" }, { "SPKR", "Input Switch", "MIXINR" }, { "SPKR", "IN1RP Switch", "IN1RP" }, - { "SPKR", "Output Switch", "Right Output Mixer" }, + { "SPKR", "Output Switch", "Right Output PGA" }, { "SPKR", NULL, "TOCLK" }, { "SPKL Boost", "Direct Voice Switch", "Direct Voice" }, @@ -767,8 +767,8 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "SPKOUTRP", NULL, "SPKR Driver" }, { "SPKOUTRN", NULL, "SPKR Driver" }, - { "Left Headphone Mux", "Mixer", "Left Output Mixer" }, - { "Right Headphone Mux", "Mixer", "Right Output Mixer" }, + { "Left Headphone Mux", "Mixer", "Left Output PGA" }, + { "Right Headphone Mux", "Mixer", "Right Output PGA" }, { "Headphone PGA", NULL, "Left Headphone Mux" }, { "Headphone PGA", NULL, "Right Headphone Mux" }, diff --git a/trunk/sound/soc/mid-x86/sst_platform.c b/trunk/sound/soc/mid-x86/sst_platform.c index b2e9198a983a..d567c322a2fb 100644 --- a/trunk/sound/soc/mid-x86/sst_platform.c +++ b/trunk/sound/soc/mid-x86/sst_platform.c @@ -116,18 +116,20 @@ struct snd_soc_dai_driver sst_platform_dai[] = { static inline void sst_set_stream_status(struct sst_runtime_stream *stream, int state) { - spin_lock(&stream->status_lock); + unsigned long flags; + spin_lock_irqsave(&stream->status_lock, flags); stream->stream_status = state; - spin_unlock(&stream->status_lock); + spin_unlock_irqrestore(&stream->status_lock, flags); } static inline int sst_get_stream_status(struct sst_runtime_stream *stream) { int state; + unsigned long flags; - spin_lock(&stream->status_lock); + spin_lock_irqsave(&stream->status_lock, flags); state = stream->stream_status; - spin_unlock(&stream->status_lock); + spin_unlock_irqrestore(&stream->status_lock, flags); return state; } diff --git a/trunk/sound/soc/samsung/pcm.c b/trunk/sound/soc/samsung/pcm.c index 38aac7d57a59..9c7e8b48aed6 100644 --- a/trunk/sound/soc/samsung/pcm.c +++ b/trunk/sound/soc/samsung/pcm.c @@ -350,8 +350,8 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, ctl = readl(regs + S3C_PCM_CTL); switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - /* Nothing to do, NB_NF by default */ + case SND_SOC_DAIFMT_IB_NF: + /* Nothing to do, IB_NF by default */ break; default: dev_err(pcm->dev, "Unsupported clock inversion!\n"); diff --git a/trunk/sound/soc/sh/fsi.c b/trunk/sound/soc/sh/fsi.c index 0c9997e2d8c0..23c0e83d4c19 100644 --- a/trunk/sound/soc/sh/fsi.c +++ b/trunk/sound/soc/sh/fsi.c @@ -1200,10 +1200,11 @@ static int fsi_probe(struct platform_device *pdev) master->fsib.master = master; pm_runtime_enable(&pdev->dev); - pm_runtime_resume(&pdev->dev); dev_set_drvdata(&pdev->dev, master); + pm_runtime_get_sync(&pdev->dev); fsi_soft_all_reset(master); + pm_runtime_put_sync(&pdev->dev); ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, id_entry->name, master); @@ -1218,8 +1219,17 @@ static int fsi_probe(struct platform_device *pdev) goto exit_free_irq; } - return snd_soc_register_dais(&pdev->dev, fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); + ret = snd_soc_register_dais(&pdev->dev, fsi_soc_dai, + ARRAY_SIZE(fsi_soc_dai)); + if (ret < 0) { + dev_err(&pdev->dev, "cannot snd dai register\n"); + goto exit_snd_soc; + } + + return ret; +exit_snd_soc: + snd_soc_unregister_platform(&pdev->dev); exit_free_irq: free_irq(irq, master); exit_iounmap: @@ -1238,12 +1248,11 @@ static int fsi_remove(struct platform_device *pdev) master = dev_get_drvdata(&pdev->dev); - snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai)); - snd_soc_unregister_platform(&pdev->dev); - + free_irq(master->irq, master); pm_runtime_disable(&pdev->dev); - free_irq(master->irq, master); + snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai)); + snd_soc_unregister_platform(&pdev->dev); iounmap(master->base); kfree(master); @@ -1321,3 +1330,4 @@ module_exit(fsi_mobile_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SuperH onchip FSI audio driver"); MODULE_AUTHOR("Kuninori Morimoto "); +MODULE_ALIAS("platform:fsi-pcm-audio"); diff --git a/trunk/sound/soc/soc-core.c b/trunk/sound/soc/soc-core.c index b76b74db0968..d8562ce4de7a 100644 --- a/trunk/sound/soc/soc-core.c +++ b/trunk/sound/soc/soc-core.c @@ -629,6 +629,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) runtime->hw.rates |= codec_dai_drv->capture.rates; } + ret = -EINVAL; snd_pcm_limit_hw_rates(runtime); if (!runtime->hw.rates) { printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", @@ -640,7 +641,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) codec_dai->name, cpu_dai->name); goto config_err; } - if (!runtime->hw.channels_min || !runtime->hw.channels_max) { + if (!runtime->hw.channels_min || !runtime->hw.channels_max || + runtime->hw.channels_min > runtime->hw.channels_max) { printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", codec_dai->name, cpu_dai->name); goto config_err; @@ -2060,6 +2062,7 @@ const struct dev_pm_ops snd_soc_pm_ops = { .resume = snd_soc_resume, .poweroff = snd_soc_poweroff, }; +EXPORT_SYMBOL_GPL(snd_soc_pm_ops); /* ASoC platform driver */ static struct platform_driver soc_driver = { diff --git a/trunk/sound/soc/tegra/harmony.c b/trunk/sound/soc/tegra/harmony.c index 8585957477eb..556a57133925 100644 --- a/trunk/sound/soc/tegra/harmony.c +++ b/trunk/sound/soc/tegra/harmony.c @@ -370,6 +370,7 @@ static struct platform_driver tegra_snd_harmony_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, }, .probe = tegra_snd_harmony_probe, .remove = __devexit_p(tegra_snd_harmony_remove), diff --git a/trunk/tools/perf/Documentation/perf-script.txt b/trunk/tools/perf/Documentation/perf-script.txt index 86c87e214b11..66f040b30729 100644 --- a/trunk/tools/perf/Documentation/perf-script.txt +++ b/trunk/tools/perf/Documentation/perf-script.txt @@ -113,61 +113,13 @@ OPTIONS Do various checks like samples ordering and lost events. -f:: ---fields:: +--fields Comma separated list of fields to print. Options are: comm, tid, pid, time, cpu, event, trace, sym. Field - list can be prepended with the type, trace, sw or hw, + list must be prepended with the type, trace, sw or hw, to indicate to which event type the field list applies. e.g., -f sw:comm,tid,time,sym and -f trace:time,cpu,trace - perf script -f - - is equivalent to: - - perf script -f trace: -f sw: -f hw: - - i.e., the specified fields apply to all event types if the type string - is not given. - - The arguments are processed in the order received. A later usage can - reset a prior request. e.g.: - - -f trace: -f comm,tid,time,sym - - The first -f suppresses trace events (field list is ""), but then the - second invocation sets the fields to comm,tid,time,sym. In this case a - warning is given to the user: - - "Overriding previous field request for all events." - - Alternativey, consider the order: - - -f comm,tid,time,sym -f trace: - - The first -f sets the fields for all events and the second -f - suppresses trace events. The user is given a warning message about - the override, and the result of the above is that only S/W and H/W - events are displayed with the given fields. - - For the 'wildcard' option if a user selected field is invalid for an - event type, a message is displayed to the user that the option is - ignored for that type. For example: - - $ perf script -f comm,tid,trace - 'trace' not valid for hardware events. Ignoring. - 'trace' not valid for software events. Ignoring. - - Alternatively, if the type is given an invalid field is specified it - is an error. For example: - - perf script -v -f sw:comm,tid,trace - 'trace' not valid for software events. - - At this point usage is displayed, and perf-script exits. - - Finally, a user may not set fields to none for all event types. - i.e., -f "" is not allowed. - -k:: --vmlinux=:: vmlinux pathname diff --git a/trunk/tools/perf/Makefile b/trunk/tools/perf/Makefile index 91ad5cc95d85..207dee5c5b16 100644 --- a/trunk/tools/perf/Makefile +++ b/trunk/tools/perf/Makefile @@ -5,8 +5,6 @@ endif # The default target of this Makefile is... all: -include config/utilities.mak - ifneq ($(OUTPUT),) # check that the output directory actually exists OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd) @@ -15,12 +13,6 @@ endif # Define V to have a more verbose compile. # -# Define PYTHON to point to the python binary if the default -# `python' is not correct; for example: PYTHON=python2 -# -# Define PYTHON_CONFIG to point to the python-config binary if -# the default `$(PYTHON)-config' is not correct. -# # Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8 # # Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72. @@ -138,7 +130,7 @@ INSTALL = install # explicitly what architecture to check for. Fix this up for yours.. SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ --include config/feature-tests.mak +-include feature-tests.mak ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y) CFLAGS := $(CFLAGS) -fstack-protector-all @@ -173,10 +165,12 @@ grep-libs = $(filter -l%,$(1)) strip-libs = $(filter-out -l%,$(1)) $(OUTPUT)python/perf.so: $(PYRF_OBJS) - $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ - --quiet build_ext \ - --build-lib='$(OUTPUT)python' \ - --build-temp='$(OUTPUT)python/temp' + $(QUIET_GEN)( \ + export CFLAGS="$(BASIC_CFLAGS)"; \ + python util/setup.py --quiet build_ext --build-lib='$(OUTPUT)python' \ + --build-temp='$(OUTPUT)python/temp' \ + ) + # # No Perl scripts right now: # @@ -481,74 +475,24 @@ else endif endif -disable-python = $(eval $(disable-python_code)) -define disable-python_code - BASIC_CFLAGS += -DNO_LIBPYTHON - $(if $(1),$(warning No $(1) was found)) - $(warning Python support won't be built) -endef - -override PYTHON := \ - $(call get-executable-or-default,PYTHON,python) - -ifndef PYTHON - $(call disable-python,python interpreter) - python-clean := +ifdef NO_LIBPYTHON + BASIC_CFLAGS += -DNO_LIBPYTHON else - - PYTHON_WORD := $(call shell-wordify,$(PYTHON)) - - python-clean := $(PYTHON_WORD) util/setup.py clean \ - --build-lib='$(OUTPUT)python' \ - --build-temp='$(OUTPUT)python/temp' - - ifdef NO_LIBPYTHON - $(call disable-python) - else - - override PYTHON_CONFIG := \ - $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON)-config) - - ifndef PYTHON_CONFIG - $(call disable-python,python-config tool) - else - - PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG)) - - PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null) - PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) - PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) - PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) - FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) - - ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y) - $(call disable-python,Python.h (for Python 2.x)) - else - - ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED)),y) - $(warning Python 3 is not yet supported; please set) - $(warning PYTHON and/or PYTHON_CONFIG appropriately.) - $(warning If you also have Python 2 installed, then) - $(warning try something like:) - $(warning $(and ,)) - $(warning $(and ,) make PYTHON=python2) - $(warning $(and ,)) - $(warning Otherwise, disable Python support entirely:) - $(warning $(and ,)) - $(warning $(and ,) make NO_LIBPYTHON=1) - $(warning $(and ,)) - $(error $(and ,)) - else - ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS) - EXTLIBS += $(PYTHON_EMBED_LIBADD) - LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o - LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o - LANG_BINDINGS += $(OUTPUT)python/perf.so - endif - - endif - endif - endif + PYTHON_EMBED_LDOPTS = $(shell python-config --ldflags 2>/dev/null) + PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) + PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) + PYTHON_EMBED_CCOPTS = `python-config --cflags 2>/dev/null` + FLAGS_PYTHON_EMBED=$(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) + ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y) + msg := $(warning No Python.h found, install python-dev[el] to have python support in 'perf script' and to build the python bindings) + BASIC_CFLAGS += -DNO_LIBPYTHON + else + ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS) + EXTLIBS += $(PYTHON_EMBED_LIBADD) + LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o + LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o + LANG_BINDINGS += $(OUTPUT)python/perf.so + endif endif ifdef NO_DEMANGLE @@ -889,7 +833,8 @@ clean: $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(MAKE) -C Documentation/ clean $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS - $(python-clean) + @python util/setup.py clean --build-lib='$(OUTPUT)python' \ + --build-temp='$(OUTPUT)python/temp' .PHONY: all install clean strip .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell diff --git a/trunk/tools/perf/builtin-script.c b/trunk/tools/perf/builtin-script.c index 974f6d3f4e53..ac574ea23917 100644 --- a/trunk/tools/perf/builtin-script.c +++ b/trunk/tools/perf/builtin-script.c @@ -49,169 +49,57 @@ struct output_option { }; /* default set to maintain compatibility with current format */ -static struct { - bool user_set; - bool wildcard_set; - u64 fields; - u64 invalid_fields; -} output[PERF_TYPE_MAX] = { - - [PERF_TYPE_HARDWARE] = { - .user_set = false, - - .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | - PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | - PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, - - .invalid_fields = PERF_OUTPUT_TRACE, - }, - - [PERF_TYPE_SOFTWARE] = { - .user_set = false, - - .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | - PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | - PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, - - .invalid_fields = PERF_OUTPUT_TRACE, - }, - - [PERF_TYPE_TRACEPOINT] = { - .user_set = false, - - .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | - PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | - PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE, - }, - - [PERF_TYPE_RAW] = { - .user_set = false, - - .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | - PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | - PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, - - .invalid_fields = PERF_OUTPUT_TRACE, - }, +static u64 output_fields[PERF_TYPE_MAX] = { + [PERF_TYPE_HARDWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \ + PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \ + PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, + + [PERF_TYPE_SOFTWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \ + PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \ + PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, + + [PERF_TYPE_TRACEPOINT] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \ + PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \ + PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE, }; -static bool output_set_by_user(void) -{ - int j; - for (j = 0; j < PERF_TYPE_MAX; ++j) { - if (output[j].user_set) - return true; - } - return false; -} - -static const char *output_field2str(enum perf_output_field field) -{ - int i, imax = ARRAY_SIZE(all_output_options); - const char *str = ""; - - for (i = 0; i < imax; ++i) { - if (all_output_options[i].field == field) { - str = all_output_options[i].str; - break; - } - } - return str; -} +static bool output_set_by_user; -#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x) +#define PRINT_FIELD(x) (output_fields[attr->type] & PERF_OUTPUT_##x) -static int perf_event_attr__check_stype(struct perf_event_attr *attr, - u64 sample_type, const char *sample_msg, - enum perf_output_field field) +static int perf_session__check_attr(struct perf_session *session, + struct perf_event_attr *attr) { - int type = attr->type; - const char *evname; - - if (attr->sample_type & sample_type) - return 0; - - if (output[type].user_set) { - evname = __event_name(attr->type, attr->config); - pr_err("Samples for '%s' event do not have %s attribute set. " - "Cannot print '%s' field.\n", - evname, sample_msg, output_field2str(field)); - return -1; - } - - /* user did not ask for it explicitly so remove from the default list */ - output[type].fields &= ~field; - evname = __event_name(attr->type, attr->config); - pr_debug("Samples for '%s' event do not have %s attribute set. " - "Skipping '%s' field.\n", - evname, sample_msg, output_field2str(field)); - - return 0; -} - -static int perf_evsel__check_attr(struct perf_evsel *evsel, - struct perf_session *session) -{ - struct perf_event_attr *attr = &evsel->attr; - if (PRINT_FIELD(TRACE) && !perf_session__has_traces(session, "record -R")) return -EINVAL; if (PRINT_FIELD(SYM)) { - if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP", - PERF_OUTPUT_SYM)) + if (!(session->sample_type & PERF_SAMPLE_IP)) { + pr_err("Samples do not contain IP data.\n"); return -EINVAL; - + } if (!no_callchain && - !(attr->sample_type & PERF_SAMPLE_CALLCHAIN)) + !(session->sample_type & PERF_SAMPLE_CALLCHAIN)) symbol_conf.use_callchain = false; } if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && - perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID", - PERF_OUTPUT_TID|PERF_OUTPUT_PID)) + !(session->sample_type & PERF_SAMPLE_TID)) { + pr_err("Samples do not contain TID/PID data.\n"); return -EINVAL; + } if (PRINT_FIELD(TIME) && - perf_event_attr__check_stype(attr, PERF_SAMPLE_TIME, "TIME", - PERF_OUTPUT_TIME)) + !(session->sample_type & PERF_SAMPLE_TIME)) { + pr_err("Samples do not contain timestamps.\n"); return -EINVAL; + } if (PRINT_FIELD(CPU) && - perf_event_attr__check_stype(attr, PERF_SAMPLE_CPU, "CPU", - PERF_OUTPUT_CPU)) + !(session->sample_type & PERF_SAMPLE_CPU)) { + pr_err("Samples do not contain cpu.\n"); return -EINVAL; - - return 0; -} - -/* - * verify all user requested events exist and the samples - * have the expected data - */ -static int perf_session__check_output_opt(struct perf_session *session) -{ - int j; - struct perf_evsel *evsel; - - for (j = 0; j < PERF_TYPE_MAX; ++j) { - evsel = perf_session__find_first_evtype(session, j); - - /* - * even if fields is set to 0 (ie., show nothing) event must - * exist if user explicitly includes it on the command line - */ - if (!evsel && output[j].user_set && !output[j].wildcard_set) { - pr_err("%s events do not exist. " - "Remove corresponding -f option to proceed.\n", - event_type(j)); - return -1; - } - - if (evsel && output[j].fields && - perf_evsel__check_attr(evsel, session)) - return -1; } return 0; @@ -280,7 +168,10 @@ static void process_event(union perf_event *event __unused, { struct perf_event_attr *attr = &evsel->attr; - if (output[attr->type].fields == 0) + if (output_fields[attr->type] == 0) + return; + + if (perf_session__check_attr(session, attr) < 0) return; print_sample_start(sample, thread, attr); @@ -560,7 +451,6 @@ static int parse_output_fields(const struct option *opt __used, { char *tok; int i, imax = sizeof(all_output_options) / sizeof(struct output_option); - int j; int rc = 0; char *str = strdup(arg); int type = -1; @@ -568,99 +458,52 @@ static int parse_output_fields(const struct option *opt __used, if (!str) return -ENOMEM; - /* first word can state for which event type the user is specifying - * the fields. If no type exists, the specified fields apply to all - * event types found in the file minus the invalid fields for a type. - */ - tok = strchr(str, ':'); - if (tok) { - *tok = '\0'; - tok++; - if (!strcmp(str, "hw")) - type = PERF_TYPE_HARDWARE; - else if (!strcmp(str, "sw")) - type = PERF_TYPE_SOFTWARE; - else if (!strcmp(str, "trace")) - type = PERF_TYPE_TRACEPOINT; - else if (!strcmp(str, "raw")) - type = PERF_TYPE_RAW; - else { - fprintf(stderr, "Invalid event type in field string.\n"); - return -EINVAL; - } - - if (output[type].user_set) - pr_warning("Overriding previous field request for %s events.\n", - event_type(type)); - - output[type].fields = 0; - output[type].user_set = true; - output[type].wildcard_set = false; - - } else { - tok = str; - if (strlen(str) == 0) { - fprintf(stderr, - "Cannot set fields to 'none' for all event types.\n"); - rc = -EINVAL; - goto out; - } - - if (output_set_by_user()) - pr_warning("Overriding previous field request for all events.\n"); + tok = strtok(str, ":"); + if (!tok) { + fprintf(stderr, + "Invalid field string - not prepended with type."); + return -EINVAL; + } - for (j = 0; j < PERF_TYPE_MAX; ++j) { - output[j].fields = 0; - output[j].user_set = true; - output[j].wildcard_set = true; - } + /* first word should state which event type user + * is specifying the fields + */ + if (!strcmp(tok, "hw")) + type = PERF_TYPE_HARDWARE; + else if (!strcmp(tok, "sw")) + type = PERF_TYPE_SOFTWARE; + else if (!strcmp(tok, "trace")) + type = PERF_TYPE_TRACEPOINT; + else { + fprintf(stderr, "Invalid event type in field string."); + return -EINVAL; } - tok = strtok(tok, ","); - while (tok) { + output_fields[type] = 0; + while (1) { + tok = strtok(NULL, ","); + if (!tok) + break; for (i = 0; i < imax; ++i) { - if (strcmp(tok, all_output_options[i].str) == 0) + if (strcmp(tok, all_output_options[i].str) == 0) { + output_fields[type] |= all_output_options[i].field; break; + } } if (i == imax) { - fprintf(stderr, "Invalid field requested.\n"); + fprintf(stderr, "Invalid field requested."); rc = -EINVAL; - goto out; - } - - if (type == -1) { - /* add user option to all events types for - * which it is valid - */ - for (j = 0; j < PERF_TYPE_MAX; ++j) { - if (output[j].invalid_fields & all_output_options[i].field) { - pr_warning("\'%s\' not valid for %s events. Ignoring.\n", - all_output_options[i].str, event_type(j)); - } else - output[j].fields |= all_output_options[i].field; - } - } else { - if (output[type].invalid_fields & all_output_options[i].field) { - fprintf(stderr, "\'%s\' not valid for %s events.\n", - all_output_options[i].str, event_type(type)); - - rc = -EINVAL; - goto out; - } - output[type].fields |= all_output_options[i].field; + break; } - - tok = strtok(NULL, ","); } - if (type >= 0) { - if (output[type].fields == 0) { - pr_debug("No fields requested for %s type. " - "Events will not be displayed.\n", event_type(type)); - } + if (output_fields[type] == 0) { + pr_debug("No fields requested for %s type. " + "Events will not be displayed\n", event_type(type)); } -out: + output_set_by_user = true; + free(str); return rc; } @@ -986,7 +829,7 @@ static const struct option options[] = { OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", "Look for files with symbols relative to this directory"), OPT_CALLBACK('f', "fields", NULL, "str", - "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,sym", + "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace. Fields: comm,tid,pid,time,cpu,event,trace,sym", parse_output_fields), OPT_END() @@ -1177,7 +1020,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) struct stat perf_stat; int input; - if (output_set_by_user()) { + if (output_set_by_user) { fprintf(stderr, "custom fields not supported for generated scripts"); return -1; @@ -1217,11 +1060,6 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) pr_debug("perf script started with script %s\n\n", script_name); } - - err = perf_session__check_output_opt(session); - if (err < 0) - goto out; - err = __cmd_script(session); perf_session__delete(session); diff --git a/trunk/tools/perf/config/utilities.mak b/trunk/tools/perf/config/utilities.mak deleted file mode 100644 index 8046182a19eb..000000000000 --- a/trunk/tools/perf/config/utilities.mak +++ /dev/null @@ -1,188 +0,0 @@ -# This allows us to work with the newline character: -define newline - - -endef -newline := $(newline) - -# nl-escape -# -# Usage: escape = $(call nl-escape[,escape]) -# -# This is used as the common way to specify -# what should replace a newline when escaping -# newlines; the default is a bizarre string. -# -nl-escape = $(or $(1),m822df3020w6a44id34bt574ctac44eb9f4n) - -# escape-nl -# -# Usage: escaped-text = $(call escape-nl,text[,escape]) -# -# GNU make's $(shell ...) function converts to a -# single space each newline character in the output -# produced during the expansion; this may not be -# desirable. -# -# The only solution is to change each newline into -# something that won't be converted, so that the -# information can be recovered later with -# $(call unescape-nl...) -# -escape-nl = $(subst $(newline),$(call nl-escape,$(2)),$(1)) - -# unescape-nl -# -# Usage: text = $(call unescape-nl,escaped-text[,escape]) -# -# See escape-nl. -# -unescape-nl = $(subst $(call nl-escape,$(2)),$(newline),$(1)) - -# shell-escape-nl -# -# Usage: $(shell some-command | $(call shell-escape-nl[,escape])) -# -# Use this to escape newlines from within a shell call; -# the default escape is a bizarre string. -# -# NOTE: The escape is used directly as a string constant -# in an `awk' program that is delimited by shell -# single-quotes, so be wary of the characters -# that are chosen. -# -define shell-escape-nl -awk 'NR==1 {t=$$0} NR>1 {t=t "$(nl-escape)" $$0} END {printf t}' -endef - -# shell-unescape-nl -# -# Usage: $(shell some-command | $(call shell-unescape-nl[,escape])) -# -# Use this to unescape newlines from within a shell call; -# the default escape is a bizarre string. -# -# NOTE: The escape is used directly as an extended regular -# expression constant in an `awk' program that is -# delimited by shell single-quotes, so be wary -# of the characters that are chosen. -# -# (The bash shell has a bug where `{gsub(...),...}' is -# misinterpreted as a brace expansion; this can be -# overcome by putting a space between `{' and `gsub'). -# -define shell-unescape-nl -awk 'NR==1 {t=$$0} NR>1 {t=t "\n" $$0} END { gsub(/$(nl-escape)/,"\n",t); printf t }' -endef - -# escape-for-shell-sq -# -# Usage: embeddable-text = $(call escape-for-shell-sq,text) -# -# This function produces text that is suitable for -# embedding in a shell string that is delimited by -# single-quotes. -# -escape-for-shell-sq = $(subst ','\'',$(1)) - -# shell-sq -# -# Usage: single-quoted-and-escaped-text = $(call shell-sq,text) -# -shell-sq = '$(escape-for-shell-sq)' - -# shell-wordify -# -# Usage: wordified-text = $(call shell-wordify,text) -# -# For instance: -# -# |define text -# |hello -# |world -# |endef -# | -# |target: -# | echo $(call shell-wordify,$(text)) -# -# At least GNU make gets confused by expanding a newline -# within the context of a command line of a makefile rule -# (this is in constrast to a `$(shell ...)' function call, -# which can handle it just fine). -# -# This function avoids the problem by producing a string -# that works as a shell word, regardless of whether or -# not it contains a newline. -# -# If the text to be wordified contains a newline, then -# an intrictate shell command substitution is constructed -# to render the text as a single line; when the shell -# processes the resulting escaped text, it transforms -# it into the original unescaped text. -# -# If the text does not contain a newline, then this function -# produces the same results as the `$(shell-sq)' function. -# -shell-wordify = $(if $(findstring $(newline),$(1)),$(_sw-esc-nl),$(shell-sq)) -define _sw-esc-nl -"$$(echo $(call escape-nl,$(shell-sq),$(2)) | $(call shell-unescape-nl,$(2)))" -endef - -# is-absolute -# -# Usage: bool-value = $(call is-absolute,path) -# -is-absolute = $(shell echo $(shell-sq) | grep ^/ -q && echo y) - -# lookup -# -# Usage: absolute-executable-path-or-empty = $(call lookup,path) -# -# (It's necessary to use `sh -c' because GNU make messes up by -# trying too hard and getting things wrong). -# -lookup = $(call unescape-nl,$(shell sh -c $(_l-sh))) -_l-sh = $(call shell-sq,command -v $(shell-sq) | $(call shell-escape-nl,)) - -# is-executable -# -# Usage: bool-value = $(call is-executable,path) -# -# (It's necessary to use `sh -c' because GNU make messes up by -# trying too hard and getting things wrong). -# -is-executable = $(call _is-executable-helper,$(shell-sq)) -_is-executable-helper = $(shell sh -c $(_is-executable-sh)) -_is-executable-sh = $(call shell-sq,test -f $(1) -a -x $(1) && echo y) - -# get-executable -# -# Usage: absolute-executable-path-or-empty = $(call get-executable,path) -# -# The goal is to get an absolute path for an executable; -# the `command -v' is defined by POSIX, but it's not -# necessarily very portable, so it's only used if -# relative path resolution is requested, as determined -# by the presence of a leading `/'. -# -get-executable = $(if $(1),$(if $(is-absolute),$(_ge-abspath),$(lookup))) -_ge-abspath = $(if $(is-executable),$(1)) - -# get-supplied-or-default-executable -# -# Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default) -# -define get-executable-or-default -$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2))) -endef -_ge_attempt = $(or $(get-executable),$(_gea_warn),$(call _gea_err,$(2))) -_gea_warn = $(warning The path '$(1)' is not executable.) -_gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) - -# try-cc -# Usage: option = $(call try-cc, source-to-build, cc-options) -try-cc = $(shell sh -c \ - 'TMP="$(OUTPUT)$(TMPOUT).$$$$"; \ - echo "$(1)" | \ - $(CC) -x c - $(2) -o "$$TMP" > /dev/null 2>&1 && echo y; \ - rm -f "$$TMP"') diff --git a/trunk/tools/perf/config/feature-tests.mak b/trunk/tools/perf/feature-tests.mak similarity index 86% rename from trunk/tools/perf/config/feature-tests.mak rename to trunk/tools/perf/feature-tests.mak index 6170fd2531b5..b041ca67a2cb 100644 --- a/trunk/tools/perf/config/feature-tests.mak +++ b/trunk/tools/perf/feature-tests.mak @@ -79,15 +79,9 @@ endef endif ifndef NO_LIBPYTHON -define SOURCE_PYTHON_VERSION -#include -#if PY_VERSION_HEX >= 0x03000000 - #error -#endif -int main(void){} -endef define SOURCE_PYTHON_EMBED #include + int main(void) { Py_Initialize(); @@ -126,3 +120,11 @@ int main(void) return 0; } endef + +# try-cc +# Usage: option = $(call try-cc, source-to-build, cc-options) +try-cc = $(shell sh -c \ + 'TMP="$(OUTPUT)$(TMPOUT).$$$$"; \ + echo "$(1)" | \ + $(CC) -x c - $(2) -o "$$TMP" > /dev/null 2>&1 && echo y; \ + rm -f "$$TMP"') diff --git a/trunk/tools/perf/util/probe-finder.c b/trunk/tools/perf/util/probe-finder.c index a7c7145a8d4f..b7c85ce466a1 100644 --- a/trunk/tools/perf/util/probe-finder.c +++ b/trunk/tools/perf/util/probe-finder.c @@ -1471,38 +1471,6 @@ static int find_probe_point_by_func(struct probe_finder *pf) return _param.retval; } -struct pubname_callback_param { - char *function; - char *file; - Dwarf_Die *cu_die; - Dwarf_Die *sp_die; - int found; -}; - -static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data) -{ - struct pubname_callback_param *param = data; - - if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) { - if (dwarf_tag(param->sp_die) != DW_TAG_subprogram) - return DWARF_CB_OK; - - if (die_compare_name(param->sp_die, param->function)) { - if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die)) - return DWARF_CB_OK; - - if (param->file && - strtailcmp(param->file, dwarf_decl_file(param->sp_die))) - return DWARF_CB_OK; - - param->found = 1; - return DWARF_CB_ABORT; - } - } - - return DWARF_CB_OK; -} - /* Find probe points from debuginfo */ static int find_probes(int fd, struct probe_finder *pf) { @@ -1530,27 +1498,6 @@ static int find_probes(int fd, struct probe_finder *pf) off = 0; line_list__init(&pf->lcache); - - /* Fastpath: lookup by function name from .debug_pubnames section */ - if (pp->function) { - struct pubname_callback_param pubname_param = { - .function = pp->function, - .file = pp->file, - .cu_die = &pf->cu_die, - .sp_die = &pf->sp_die, - }; - struct dwarf_callback_param probe_param = { - .data = pf, - }; - - dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); - if (pubname_param.found) { - ret = probe_point_search_cb(&pf->sp_die, &probe_param); - if (ret) - goto found; - } - } - /* Loop on CUs (Compilation Unit) */ while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { /* Get the DIE(Debugging Information Entry) of this CU */ @@ -1578,8 +1525,6 @@ static int find_probes(int fd, struct probe_finder *pf) } off = noff; } - -found: line_list__free(&pf->lcache); if (dwfl) dwfl_end(dwfl); @@ -2001,22 +1946,6 @@ int find_line_range(int fd, struct line_range *lr) return -EBADF; } - /* Fastpath: lookup by function name from .debug_pubnames section */ - if (lr->function) { - struct pubname_callback_param pubname_param = { - .function = lr->function, .file = lr->file, - .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0}; - struct dwarf_callback_param line_range_param = { - .data = (void *)&lf, .retval = 0}; - - dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); - if (pubname_param.found) { - line_range_search_cb(&lf.sp_die, &line_range_param); - if (lf.found) - goto found; - } - } - /* Loop on CUs (Compilation Unit) */ while (!lf.found && ret >= 0) { if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) @@ -2045,7 +1974,6 @@ int find_line_range(int fd, struct line_range *lr) off = noff; } -found: /* Store comp_dir */ if (lf.found) { comp_dir = cu_get_comp_dir(&lf.cu_die); diff --git a/trunk/tools/perf/util/probe-finder.h b/trunk/tools/perf/util/probe-finder.h index 605730a366db..beaefc3c1223 100644 --- a/trunk/tools/perf/util/probe-finder.h +++ b/trunk/tools/perf/util/probe-finder.h @@ -49,7 +49,6 @@ struct probe_finder { Dwarf_Addr addr; /* Address */ const char *fname; /* Real file name */ Dwarf_Die cu_die; /* Current CU */ - Dwarf_Die sp_die; struct list_head lcache; /* Line cache for lazy match */ /* For variable searching */ @@ -84,7 +83,6 @@ struct line_finder { int lno_s; /* Start line number */ int lno_e; /* End line number */ Dwarf_Die cu_die; /* Current CU */ - Dwarf_Die sp_die; int found; }; diff --git a/trunk/tools/perf/util/session.c b/trunk/tools/perf/util/session.c index fff66741f18d..caa224522fea 100644 --- a/trunk/tools/perf/util/session.c +++ b/trunk/tools/perf/util/session.c @@ -1156,18 +1156,6 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) return ret; } -struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, - unsigned int type) -{ - struct perf_evsel *pos; - - list_for_each_entry(pos, &session->evlist->entries, node) { - if (pos->attr.type == type) - return pos; - } - return NULL; -} - void perf_session__print_symbols(union perf_event *event, struct perf_sample *sample, struct perf_session *session) diff --git a/trunk/tools/perf/util/session.h b/trunk/tools/perf/util/session.h index 8daaa2d15396..1ac481fc1100 100644 --- a/trunk/tools/perf/util/session.h +++ b/trunk/tools/perf/util/session.h @@ -162,9 +162,6 @@ static inline int perf_session__parse_sample(struct perf_session *session, session->sample_id_all, sample); } -struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, - unsigned int type); - void perf_session__print_symbols(union perf_event *event, struct perf_sample *sample, struct perf_session *session); diff --git a/trunk/tools/perf/util/symbol.c b/trunk/tools/perf/util/symbol.c index 516876dfbe52..f06c10f092ba 100644 --- a/trunk/tools/perf/util/symbol.c +++ b/trunk/tools/perf/util/symbol.c @@ -31,13 +31,13 @@ #define NT_GNU_BUILD_ID 3 #endif -static bool dso__build_id_equal(const struct dso *dso, u8 *build_id); +static bool dso__build_id_equal(const struct dso *self, u8 *build_id); static int elf_read_build_id(Elf *elf, void *bf, size_t size); static void dsos__add(struct list_head *head, struct dso *dso); static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); -static int dso__load_kernel_sym(struct dso *dso, struct map *map, +static int dso__load_kernel_sym(struct dso *self, struct map *map, symbol_filter_t filter); -static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, +static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, symbol_filter_t filter); static int vmlinux_path__nr_entries; static char **vmlinux_path; @@ -49,27 +49,27 @@ struct symbol_conf symbol_conf = { .symfs = "", }; -int dso__name_len(const struct dso *dso) +int dso__name_len(const struct dso *self) { if (verbose) - return dso->long_name_len; + return self->long_name_len; - return dso->short_name_len; + return self->short_name_len; } -bool dso__loaded(const struct dso *dso, enum map_type type) +bool dso__loaded(const struct dso *self, enum map_type type) { - return dso->loaded & (1 << type); + return self->loaded & (1 << type); } -bool dso__sorted_by_name(const struct dso *dso, enum map_type type) +bool dso__sorted_by_name(const struct dso *self, enum map_type type) { - return dso->sorted_by_name & (1 << type); + return self->sorted_by_name & (1 << type); } -static void dso__set_sorted_by_name(struct dso *dso, enum map_type type) +static void dso__set_sorted_by_name(struct dso *self, enum map_type type) { - dso->sorted_by_name |= (1 << type); + self->sorted_by_name |= (1 << type); } bool symbol_type__is_a(char symbol_type, enum map_type map_type) @@ -84,9 +84,9 @@ bool symbol_type__is_a(char symbol_type, enum map_type map_type) } } -static void symbols__fixup_end(struct rb_root *symbols) +static void symbols__fixup_end(struct rb_root *self) { - struct rb_node *nd, *prevnd = rb_first(symbols); + struct rb_node *nd, *prevnd = rb_first(self); struct symbol *curr, *prev; if (prevnd == NULL) @@ -107,10 +107,10 @@ static void symbols__fixup_end(struct rb_root *symbols) curr->end = roundup(curr->start, 4096); } -static void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) +static void __map_groups__fixup_end(struct map_groups *self, enum map_type type) { struct map *prev, *curr; - struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]); + struct rb_node *nd, *prevnd = rb_first(&self->maps[type]); if (prevnd == NULL) return; @@ -130,128 +130,128 @@ static void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) curr->end = ~0ULL; } -static void map_groups__fixup_end(struct map_groups *mg) +static void map_groups__fixup_end(struct map_groups *self) { int i; for (i = 0; i < MAP__NR_TYPES; ++i) - __map_groups__fixup_end(mg, i); + __map_groups__fixup_end(self, i); } static struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) { size_t namelen = strlen(name) + 1; - struct symbol *sym = calloc(1, (symbol_conf.priv_size + - sizeof(*sym) + namelen)); - if (sym == NULL) + struct symbol *self = calloc(1, (symbol_conf.priv_size + + sizeof(*self) + namelen)); + if (self == NULL) return NULL; if (symbol_conf.priv_size) - sym = ((void *)sym) + symbol_conf.priv_size; + self = ((void *)self) + symbol_conf.priv_size; + + self->start = start; + self->end = len ? start + len - 1 : start; + self->binding = binding; + self->namelen = namelen - 1; - sym->start = start; - sym->end = len ? start + len - 1 : start; - sym->binding = binding; - sym->namelen = namelen - 1; + pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n", __func__, name, start, self->end); - pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n", - __func__, name, start, sym->end); - memcpy(sym->name, name, namelen); + memcpy(self->name, name, namelen); - return sym; + return self; } -void symbol__delete(struct symbol *sym) +void symbol__delete(struct symbol *self) { - free(((void *)sym) - symbol_conf.priv_size); + free(((void *)self) - symbol_conf.priv_size); } -static size_t symbol__fprintf(struct symbol *sym, FILE *fp) +static size_t symbol__fprintf(struct symbol *self, FILE *fp) { return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n", - sym->start, sym->end, - sym->binding == STB_GLOBAL ? 'g' : - sym->binding == STB_LOCAL ? 'l' : 'w', - sym->name); + self->start, self->end, + self->binding == STB_GLOBAL ? 'g' : + self->binding == STB_LOCAL ? 'l' : 'w', + self->name); } -void dso__set_long_name(struct dso *dso, char *name) +void dso__set_long_name(struct dso *self, char *name) { if (name == NULL) return; - dso->long_name = name; - dso->long_name_len = strlen(name); + self->long_name = name; + self->long_name_len = strlen(name); } -static void dso__set_short_name(struct dso *dso, const char *name) +static void dso__set_short_name(struct dso *self, const char *name) { if (name == NULL) return; - dso->short_name = name; - dso->short_name_len = strlen(name); + self->short_name = name; + self->short_name_len = strlen(name); } -static void dso__set_basename(struct dso *dso) +static void dso__set_basename(struct dso *self) { - dso__set_short_name(dso, basename(dso->long_name)); + dso__set_short_name(self, basename(self->long_name)); } struct dso *dso__new(const char *name) { - struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1); + struct dso *self = calloc(1, sizeof(*self) + strlen(name) + 1); - if (dso != NULL) { + if (self != NULL) { int i; - strcpy(dso->name, name); - dso__set_long_name(dso, dso->name); - dso__set_short_name(dso, dso->name); + strcpy(self->name, name); + dso__set_long_name(self, self->name); + dso__set_short_name(self, self->name); for (i = 0; i < MAP__NR_TYPES; ++i) - dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; - dso->symtab_type = SYMTAB__NOT_FOUND; - dso->loaded = 0; - dso->sorted_by_name = 0; - dso->has_build_id = 0; - dso->kernel = DSO_TYPE_USER; - INIT_LIST_HEAD(&dso->node); + self->symbols[i] = self->symbol_names[i] = RB_ROOT; + self->symtab_type = SYMTAB__NOT_FOUND; + self->loaded = 0; + self->sorted_by_name = 0; + self->has_build_id = 0; + self->kernel = DSO_TYPE_USER; + INIT_LIST_HEAD(&self->node); } - return dso; + return self; } -static void symbols__delete(struct rb_root *symbols) +static void symbols__delete(struct rb_root *self) { struct symbol *pos; - struct rb_node *next = rb_first(symbols); + struct rb_node *next = rb_first(self); while (next) { pos = rb_entry(next, struct symbol, rb_node); next = rb_next(&pos->rb_node); - rb_erase(&pos->rb_node, symbols); + rb_erase(&pos->rb_node, self); symbol__delete(pos); } } -void dso__delete(struct dso *dso) +void dso__delete(struct dso *self) { int i; for (i = 0; i < MAP__NR_TYPES; ++i) - symbols__delete(&dso->symbols[i]); - if (dso->sname_alloc) - free((char *)dso->short_name); - if (dso->lname_alloc) - free(dso->long_name); - free(dso); + symbols__delete(&self->symbols[i]); + if (self->sname_alloc) + free((char *)self->short_name); + if (self->lname_alloc) + free(self->long_name); + free(self); } -void dso__set_build_id(struct dso *dso, void *build_id) +void dso__set_build_id(struct dso *self, void *build_id) { - memcpy(dso->build_id, build_id, sizeof(dso->build_id)); - dso->has_build_id = 1; + memcpy(self->build_id, build_id, sizeof(self->build_id)); + self->has_build_id = 1; } -static void symbols__insert(struct rb_root *symbols, struct symbol *sym) +static void symbols__insert(struct rb_root *self, struct symbol *sym) { - struct rb_node **p = &symbols->rb_node; + struct rb_node **p = &self->rb_node; struct rb_node *parent = NULL; const u64 ip = sym->start; struct symbol *s; @@ -265,17 +265,17 @@ static void symbols__insert(struct rb_root *symbols, struct symbol *sym) p = &(*p)->rb_right; } rb_link_node(&sym->rb_node, parent, p); - rb_insert_color(&sym->rb_node, symbols); + rb_insert_color(&sym->rb_node, self); } -static struct symbol *symbols__find(struct rb_root *symbols, u64 ip) +static struct symbol *symbols__find(struct rb_root *self, u64 ip) { struct rb_node *n; - if (symbols == NULL) + if (self == NULL) return NULL; - n = symbols->rb_node; + n = self->rb_node; while (n) { struct symbol *s = rb_entry(n, struct symbol, rb_node); @@ -296,9 +296,9 @@ struct symbol_name_rb_node { struct symbol sym; }; -static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym) +static void symbols__insert_by_name(struct rb_root *self, struct symbol *sym) { - struct rb_node **p = &symbols->rb_node; + struct rb_node **p = &self->rb_node; struct rb_node *parent = NULL; struct symbol_name_rb_node *symn, *s; @@ -313,29 +313,27 @@ static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym) p = &(*p)->rb_right; } rb_link_node(&symn->rb_node, parent, p); - rb_insert_color(&symn->rb_node, symbols); + rb_insert_color(&symn->rb_node, self); } -static void symbols__sort_by_name(struct rb_root *symbols, - struct rb_root *source) +static void symbols__sort_by_name(struct rb_root *self, struct rb_root *source) { struct rb_node *nd; for (nd = rb_first(source); nd; nd = rb_next(nd)) { struct symbol *pos = rb_entry(nd, struct symbol, rb_node); - symbols__insert_by_name(symbols, pos); + symbols__insert_by_name(self, pos); } } -static struct symbol *symbols__find_by_name(struct rb_root *symbols, - const char *name) +static struct symbol *symbols__find_by_name(struct rb_root *self, const char *name) { struct rb_node *n; - if (symbols == NULL) + if (self == NULL) return NULL; - n = symbols->rb_node; + n = self->rb_node; while (n) { struct symbol_name_rb_node *s; @@ -355,29 +353,29 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols, return NULL; } -struct symbol *dso__find_symbol(struct dso *dso, +struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr) { - return symbols__find(&dso->symbols[type], addr); + return symbols__find(&self->symbols[type], addr); } -struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, +struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, const char *name) { - return symbols__find_by_name(&dso->symbol_names[type], name); + return symbols__find_by_name(&self->symbol_names[type], name); } -void dso__sort_by_name(struct dso *dso, enum map_type type) +void dso__sort_by_name(struct dso *self, enum map_type type) { - dso__set_sorted_by_name(dso, type); - return symbols__sort_by_name(&dso->symbol_names[type], - &dso->symbols[type]); + dso__set_sorted_by_name(self, type); + return symbols__sort_by_name(&self->symbol_names[type], + &self->symbols[type]); } -int build_id__sprintf(const u8 *build_id, int len, char *bf) +int build_id__sprintf(const u8 *self, int len, char *bf) { char *bid = bf; - const u8 *raw = build_id; + const u8 *raw = self; int i; for (i = 0; i < len; ++i) { @@ -386,25 +384,24 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf) bid += 2; } - return raw - build_id; + return raw - self; } -size_t dso__fprintf_buildid(struct dso *dso, FILE *fp) +size_t dso__fprintf_buildid(struct dso *self, FILE *fp) { char sbuild_id[BUILD_ID_SIZE * 2 + 1]; - build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); + build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id); return fprintf(fp, "%s", sbuild_id); } -size_t dso__fprintf_symbols_by_name(struct dso *dso, - enum map_type type, FILE *fp) +size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp) { size_t ret = 0; struct rb_node *nd; struct symbol_name_rb_node *pos; - for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) { + for (nd = rb_first(&self->symbol_names[type]); nd; nd = rb_next(nd)) { pos = rb_entry(nd, struct symbol_name_rb_node, rb_node); fprintf(fp, "%s\n", pos->sym.name); } @@ -412,18 +409,18 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso, return ret; } -size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp) +size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp) { struct rb_node *nd; - size_t ret = fprintf(fp, "dso: %s (", dso->short_name); + size_t ret = fprintf(fp, "dso: %s (", self->short_name); - if (dso->short_name != dso->long_name) - ret += fprintf(fp, "%s, ", dso->long_name); + if (self->short_name != self->long_name) + ret += fprintf(fp, "%s, ", self->long_name); ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type], - dso->loaded ? "" : "NOT "); - ret += dso__fprintf_buildid(dso, fp); + self->loaded ? "" : "NOT "); + ret += dso__fprintf_buildid(self, fp); ret += fprintf(fp, ")\n"); - for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) { + for (nd = rb_first(&self->symbols[type]); nd; nd = rb_next(nd)) { struct symbol *pos = rb_entry(nd, struct symbol, rb_node); ret += symbol__fprintf(pos, fp); } @@ -546,10 +543,10 @@ static int map__process_kallsym_symbol(void *arg, const char *name, * so that we can in the next step set the symbol ->end address and then * call kernel_maps__split_kallsyms. */ -static int dso__load_all_kallsyms(struct dso *dso, const char *filename, +static int dso__load_all_kallsyms(struct dso *self, const char *filename, struct map *map) { - struct process_kallsyms_args args = { .map = map, .dso = dso, }; + struct process_kallsyms_args args = { .map = map, .dso = self, }; return kallsyms__parse(filename, &args, map__process_kallsym_symbol); } @@ -558,7 +555,7 @@ static int dso__load_all_kallsyms(struct dso *dso, const char *filename, * kernel range is broken in several maps, named [kernel].N, as we don't have * the original ELF section names vmlinux have. */ -static int dso__split_kallsyms(struct dso *dso, struct map *map, +static int dso__split_kallsyms(struct dso *self, struct map *map, symbol_filter_t filter) { struct map_groups *kmaps = map__kmap(map)->kmaps; @@ -566,7 +563,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, struct map *curr_map = map; struct symbol *pos; int count = 0, moved = 0; - struct rb_root *root = &dso->symbols[map->type]; + struct rb_root *root = &self->symbols[map->type]; struct rb_node *next = rb_first(root); int kernel_range = 0; @@ -585,7 +582,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, if (strcmp(curr_map->dso->short_name, module)) { if (curr_map != map && - dso->kernel == DSO_TYPE_GUEST_KERNEL && + self->kernel == DSO_TYPE_GUEST_KERNEL && machine__is_default_guest(machine)) { /* * We assume all symbols of a module are @@ -621,14 +618,14 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, pos->end = curr_map->map_ip(curr_map, pos->end); } else if (curr_map != map) { char dso_name[PATH_MAX]; - struct dso *ndso; + struct dso *dso; if (count == 0) { curr_map = map; goto filter_symbol; } - if (dso->kernel == DSO_TYPE_GUEST_KERNEL) + if (self->kernel == DSO_TYPE_GUEST_KERNEL) snprintf(dso_name, sizeof(dso_name), "[guest.kernel].%d", kernel_range++); @@ -637,15 +634,15 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, "[kernel].%d", kernel_range++); - ndso = dso__new(dso_name); - if (ndso == NULL) + dso = dso__new(dso_name); + if (dso == NULL) return -1; - ndso->kernel = dso->kernel; + dso->kernel = self->kernel; - curr_map = map__new2(pos->start, ndso, map->type); + curr_map = map__new2(pos->start, dso, map->type); if (curr_map == NULL) { - dso__delete(ndso); + dso__delete(dso); return -1; } @@ -668,7 +665,7 @@ discard_symbol: rb_erase(&pos->rb_node, root); } if (curr_map != map && - dso->kernel == DSO_TYPE_GUEST_KERNEL && + self->kernel == DSO_TYPE_GUEST_KERNEL && machine__is_default_guest(kmaps->machine)) { dso__set_loaded(curr_map->dso, curr_map->type); } @@ -676,21 +673,21 @@ discard_symbol: rb_erase(&pos->rb_node, root); return count + moved; } -int dso__load_kallsyms(struct dso *dso, const char *filename, +int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, symbol_filter_t filter) { - if (dso__load_all_kallsyms(dso, filename, map) < 0) + if (dso__load_all_kallsyms(self, filename, map) < 0) return -1; - if (dso->kernel == DSO_TYPE_GUEST_KERNEL) - dso->symtab_type = SYMTAB__GUEST_KALLSYMS; + if (self->kernel == DSO_TYPE_GUEST_KERNEL) + self->symtab_type = SYMTAB__GUEST_KALLSYMS; else - dso->symtab_type = SYMTAB__KALLSYMS; + self->symtab_type = SYMTAB__KALLSYMS; - return dso__split_kallsyms(dso, map, filter); + return dso__split_kallsyms(self, map, filter); } -static int dso__load_perf_map(struct dso *dso, struct map *map, +static int dso__load_perf_map(struct dso *self, struct map *map, symbol_filter_t filter) { char *line = NULL; @@ -698,7 +695,7 @@ static int dso__load_perf_map(struct dso *dso, struct map *map, FILE *file; int nr_syms = 0; - file = fopen(dso->long_name, "r"); + file = fopen(self->long_name, "r"); if (file == NULL) goto out_failure; @@ -736,7 +733,7 @@ static int dso__load_perf_map(struct dso *dso, struct map *map, if (filter && filter(map, sym)) symbol__delete(sym); else { - symbols__insert(&dso->symbols[map->type], sym); + symbols__insert(&self->symbols[map->type], sym); nr_syms++; } } @@ -755,7 +752,7 @@ static int dso__load_perf_map(struct dso *dso, struct map *map, /** * elf_symtab__for_each_symbol - iterate thru all the symbols * - * @syms: struct elf_symtab instance to iterate + * @self: struct elf_symtab instance to iterate * @idx: uint32_t idx * @sym: GElf_Sym iterator */ @@ -855,7 +852,7 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, * And always look at the original dso, not at debuginfo packages, that * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). */ -static int dso__synthesize_plt_symbols(struct dso *dso, struct map *map, +static int dso__synthesize_plt_symbols(struct dso *self, struct map *map, symbol_filter_t filter) { uint32_t nr_rel_entries, idx; @@ -874,7 +871,7 @@ static int dso__synthesize_plt_symbols(struct dso *dso, struct map *map, char name[PATH_MAX]; snprintf(name, sizeof(name), "%s%s", - symbol_conf.symfs, dso->long_name); + symbol_conf.symfs, self->long_name); fd = open(name, O_RDONLY); if (fd < 0) goto out; @@ -950,7 +947,7 @@ static int dso__synthesize_plt_symbols(struct dso *dso, struct map *map, if (filter && filter(map, f)) symbol__delete(f); else { - symbols__insert(&dso->symbols[map->type], f); + symbols__insert(&self->symbols[map->type], f); ++nr; } } @@ -972,7 +969,7 @@ static int dso__synthesize_plt_symbols(struct dso *dso, struct map *map, if (filter && filter(map, f)) symbol__delete(f); else { - symbols__insert(&dso->symbols[map->type], f); + symbols__insert(&self->symbols[map->type], f); ++nr; } } @@ -988,30 +985,29 @@ static int dso__synthesize_plt_symbols(struct dso *dso, struct map *map, return nr; out: pr_debug("%s: problems reading %s PLT info.\n", - __func__, dso->long_name); + __func__, self->long_name); return 0; } -static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type) +static bool elf_sym__is_a(GElf_Sym *self, enum map_type type) { switch (type) { case MAP__FUNCTION: - return elf_sym__is_function(sym); + return elf_sym__is_function(self); case MAP__VARIABLE: - return elf_sym__is_object(sym); + return elf_sym__is_object(self); default: return false; } } -static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs, - enum map_type type) +static bool elf_sec__is_a(GElf_Shdr *self, Elf_Data *secstrs, enum map_type type) { switch (type) { case MAP__FUNCTION: - return elf_sec__is_text(shdr, secstrs); + return elf_sec__is_text(self, secstrs); case MAP__VARIABLE: - return elf_sec__is_data(shdr, secstrs); + return elf_sec__is_data(self, secstrs); default: return false; } @@ -1036,13 +1032,13 @@ static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr) return -1; } -static int dso__load_sym(struct dso *dso, struct map *map, const char *name, +static int dso__load_sym(struct dso *self, struct map *map, const char *name, int fd, symbol_filter_t filter, int kmodule, int want_symtab) { - struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; + struct kmap *kmap = self->kernel ? map__kmap(map) : NULL; struct map *curr_map = map; - struct dso *curr_dso = dso; + struct dso *curr_dso = self; Elf_Data *symstrs, *secstrs; uint32_t nr_syms; int err = -1; @@ -1068,14 +1064,14 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, } /* Always reject images with a mismatched build-id: */ - if (dso->has_build_id) { + if (self->has_build_id) { u8 build_id[BUILD_ID_SIZE]; if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) != BUILD_ID_SIZE) goto out_elf_end; - if (!dso__build_id_equal(dso, build_id)) + if (!dso__build_id_equal(self, build_id)) goto out_elf_end; } @@ -1116,14 +1112,13 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, nr_syms = shdr.sh_size / shdr.sh_entsize; memset(&sym, 0, sizeof(sym)); - if (dso->kernel == DSO_TYPE_USER) { - dso->adjust_symbols = (ehdr.e_type == ET_EXEC || + if (self->kernel == DSO_TYPE_USER) { + self->adjust_symbols = (ehdr.e_type == ET_EXEC || elf_section_by_name(elf, &ehdr, &shdr, ".gnu.prelink_undo", NULL) != NULL); - } else { - dso->adjust_symbols = 0; - } + } else self->adjust_symbols = 0; + elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { struct symbol *f; const char *elf_name = elf_sym__name(&sym, symstrs); @@ -1173,22 +1168,22 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, (sym.st_value & 1)) --sym.st_value; - if (dso->kernel != DSO_TYPE_USER || kmodule) { + if (self->kernel != DSO_TYPE_USER || kmodule) { char dso_name[PATH_MAX]; if (strcmp(section_name, (curr_dso->short_name + - dso->short_name_len)) == 0) + self->short_name_len)) == 0) goto new_symbol; if (strcmp(section_name, ".text") == 0) { curr_map = map; - curr_dso = dso; + curr_dso = self; goto new_symbol; } snprintf(dso_name, sizeof(dso_name), - "%s%s", dso->short_name, section_name); + "%s%s", self->short_name, section_name); curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name); if (curr_map == NULL) { @@ -1200,9 +1195,9 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, curr_dso = dso__new(dso_name); if (curr_dso == NULL) goto out_elf_end; - curr_dso->kernel = dso->kernel; - curr_dso->long_name = dso->long_name; - curr_dso->long_name_len = dso->long_name_len; + curr_dso->kernel = self->kernel; + curr_dso->long_name = self->long_name; + curr_dso->long_name_len = self->long_name_len; curr_map = map__new2(start, curr_dso, map->type); if (curr_map == NULL) { @@ -1211,9 +1206,9 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, } curr_map->map_ip = identity__map_ip; curr_map->unmap_ip = identity__map_ip; - curr_dso->symtab_type = dso->symtab_type; + curr_dso->symtab_type = self->symtab_type; map_groups__insert(kmap->kmaps, curr_map); - dsos__add(&dso->node, curr_dso); + dsos__add(&self->node, curr_dso); dso__set_loaded(curr_dso, map->type); } else curr_dso = curr_map->dso; @@ -1255,7 +1250,7 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, * For misannotated, zeroed, ASM function sizes. */ if (nr > 0) { - symbols__fixup_end(&dso->symbols[map->type]); + symbols__fixup_end(&self->symbols[map->type]); if (kmap) { /* * We need to fixup this here too because we create new @@ -1271,9 +1266,9 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, return err; } -static bool dso__build_id_equal(const struct dso *dso, u8 *build_id) +static bool dso__build_id_equal(const struct dso *self, u8 *build_id) { - return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0; + return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0; } bool __dsos__read_build_ids(struct list_head *head, bool with_hits) @@ -1434,7 +1429,7 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size) return err; } -char dso__symtab_origin(const struct dso *dso) +char dso__symtab_origin(const struct dso *self) { static const char origin[] = { [SYMTAB__KALLSYMS] = 'k', @@ -1449,12 +1444,12 @@ char dso__symtab_origin(const struct dso *dso) [SYMTAB__GUEST_KMODULE] = 'G', }; - if (dso == NULL || dso->symtab_type == SYMTAB__NOT_FOUND) + if (self == NULL || self->symtab_type == SYMTAB__NOT_FOUND) return '!'; - return origin[dso->symtab_type]; + return origin[self->symtab_type]; } -int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) +int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) { int size = PATH_MAX; char *name; @@ -1464,12 +1459,12 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) const char *root_dir; int want_symtab; - dso__set_loaded(dso, map->type); + dso__set_loaded(self, map->type); - if (dso->kernel == DSO_TYPE_KERNEL) - return dso__load_kernel_sym(dso, map, filter); - else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) - return dso__load_guest_kernel_sym(dso, map, filter); + if (self->kernel == DSO_TYPE_KERNEL) + return dso__load_kernel_sym(self, map, filter); + else if (self->kernel == DSO_TYPE_GUEST_KERNEL) + return dso__load_guest_kernel_sym(self, map, filter); if (map->groups && map->groups->machine) machine = map->groups->machine; @@ -1480,11 +1475,11 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) if (!name) return -1; - dso->adjust_symbols = 0; + self->adjust_symbols = 0; - if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { - ret = dso__load_perf_map(dso, map, filter); - dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : + if (strncmp(self->name, "/tmp/perf-", 10) == 0) { + ret = dso__load_perf_map(self, map, filter); + self->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : SYMTAB__NOT_FOUND; return ret; } @@ -1495,33 +1490,33 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) */ want_symtab = 1; restart: - for (dso->symtab_type = SYMTAB__BUILD_ID_CACHE; - dso->symtab_type != SYMTAB__NOT_FOUND; - dso->symtab_type++) { - switch (dso->symtab_type) { + for (self->symtab_type = SYMTAB__BUILD_ID_CACHE; + self->symtab_type != SYMTAB__NOT_FOUND; + self->symtab_type++) { + switch (self->symtab_type) { case SYMTAB__BUILD_ID_CACHE: /* skip the locally configured cache if a symfs is given */ if (symbol_conf.symfs[0] || - (dso__build_id_filename(dso, name, size) == NULL)) { + (dso__build_id_filename(self, name, size) == NULL)) { continue; } break; case SYMTAB__FEDORA_DEBUGINFO: snprintf(name, size, "%s/usr/lib/debug%s.debug", - symbol_conf.symfs, dso->long_name); + symbol_conf.symfs, self->long_name); break; case SYMTAB__UBUNTU_DEBUGINFO: snprintf(name, size, "%s/usr/lib/debug%s", - symbol_conf.symfs, dso->long_name); + symbol_conf.symfs, self->long_name); break; case SYMTAB__BUILDID_DEBUGINFO: { char build_id_hex[BUILD_ID_SIZE * 2 + 1]; - if (!dso->has_build_id) + if (!self->has_build_id) continue; - build_id__sprintf(dso->build_id, - sizeof(dso->build_id), + build_id__sprintf(self->build_id, + sizeof(self->build_id), build_id_hex); snprintf(name, size, "%s/usr/lib/debug/.build-id/%.2s/%s.debug", @@ -1530,7 +1525,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) break; case SYMTAB__SYSTEM_PATH_DSO: snprintf(name, size, "%s%s", - symbol_conf.symfs, dso->long_name); + symbol_conf.symfs, self->long_name); break; case SYMTAB__GUEST_KMODULE: if (map->groups && machine) @@ -1538,12 +1533,12 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) else root_dir = ""; snprintf(name, size, "%s%s%s", symbol_conf.symfs, - root_dir, dso->long_name); + root_dir, self->long_name); break; case SYMTAB__SYSTEM_PATH_KMODULE: snprintf(name, size, "%s%s", symbol_conf.symfs, - dso->long_name); + self->long_name); break; default:; } @@ -1553,7 +1548,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) if (fd < 0) continue; - ret = dso__load_sym(dso, map, name, fd, filter, 0, + ret = dso__load_sym(self, map, name, fd, filter, 0, want_symtab); close(fd); @@ -1565,8 +1560,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) continue; if (ret > 0) { - int nr_plt = dso__synthesize_plt_symbols(dso, map, - filter); + int nr_plt = dso__synthesize_plt_symbols(self, map, filter); if (nr_plt > 0) ret += nr_plt; break; @@ -1583,17 +1577,17 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) } free(name); - if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) + if (ret < 0 && strstr(self->name, " (deleted)") != NULL) return 0; return ret; } -struct map *map_groups__find_by_name(struct map_groups *mg, +struct map *map_groups__find_by_name(struct map_groups *self, enum map_type type, const char *name) { struct rb_node *nd; - for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) { + for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) { struct map *map = rb_entry(nd, struct map, rb_node); if (map->dso && strcmp(map->dso->short_name, name) == 0) @@ -1603,28 +1597,28 @@ struct map *map_groups__find_by_name(struct map_groups *mg, return NULL; } -static int dso__kernel_module_get_build_id(struct dso *dso, - const char *root_dir) +static int dso__kernel_module_get_build_id(struct dso *self, + const char *root_dir) { char filename[PATH_MAX]; /* * kernel module short names are of the form "[module]" and * we need just "module" here. */ - const char *name = dso->short_name + 1; + const char *name = self->short_name + 1; snprintf(filename, sizeof(filename), "%s/sys/module/%.*s/notes/.note.gnu.build-id", root_dir, (int)strlen(name) - 1, name); - if (sysfs__read_build_id(filename, dso->build_id, - sizeof(dso->build_id)) == 0) - dso->has_build_id = true; + if (sysfs__read_build_id(filename, self->build_id, + sizeof(self->build_id)) == 0) + self->has_build_id = true; return 0; } -static int map_groups__set_modules_path_dir(struct map_groups *mg, +static int map_groups__set_modules_path_dir(struct map_groups *self, const char *dir_name) { struct dirent *dent; @@ -1652,7 +1646,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg, snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name); - ret = map_groups__set_modules_path_dir(mg, path); + ret = map_groups__set_modules_path_dir(self, path); if (ret < 0) goto out; } else { @@ -1667,8 +1661,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg, (int)(dot - dent->d_name), dent->d_name); strxfrchar(dso_name, '-', '_'); - map = map_groups__find_by_name(mg, MAP__FUNCTION, - dso_name); + map = map_groups__find_by_name(self, MAP__FUNCTION, dso_name); if (map == NULL) continue; @@ -1718,20 +1711,20 @@ static char *get_kernel_version(const char *root_dir) return strdup(name); } -static int machine__set_modules_path(struct machine *machine) +static int machine__set_modules_path(struct machine *self) { char *version; char modules_path[PATH_MAX]; - version = get_kernel_version(machine->root_dir); + version = get_kernel_version(self->root_dir); if (!version) return -1; snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", - machine->root_dir, version); + self->root_dir, version); free(version); - return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); + return map_groups__set_modules_path_dir(&self->kmaps, modules_path); } /* @@ -1741,23 +1734,23 @@ static int machine__set_modules_path(struct machine *machine) */ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) { - struct map *map = calloc(1, (sizeof(*map) + - (dso->kernel ? sizeof(struct kmap) : 0))); - if (map != NULL) { + struct map *self = calloc(1, (sizeof(*self) + + (dso->kernel ? sizeof(struct kmap) : 0))); + if (self != NULL) { /* * ->end will be filled after we load all the symbols */ - map__init(map, type, start, 0, 0, dso); + map__init(self, type, start, 0, 0, dso); } - return map; + return self; } -struct map *machine__new_module(struct machine *machine, u64 start, +struct map *machine__new_module(struct machine *self, u64 start, const char *filename) { struct map *map; - struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); + struct dso *dso = __dsos__findnew(&self->kernel_dsos, filename); if (dso == NULL) return NULL; @@ -1766,15 +1759,15 @@ struct map *machine__new_module(struct machine *machine, u64 start, if (map == NULL) return NULL; - if (machine__is_host(machine)) + if (machine__is_host(self)) dso->symtab_type = SYMTAB__SYSTEM_PATH_KMODULE; else dso->symtab_type = SYMTAB__GUEST_KMODULE; - map_groups__insert(&machine->kmaps, map); + map_groups__insert(&self->kmaps, map); return map; } -static int machine__create_modules(struct machine *machine) +static int machine__create_modules(struct machine *self) { char *line = NULL; size_t n; @@ -1783,10 +1776,10 @@ static int machine__create_modules(struct machine *machine) const char *modules; char path[PATH_MAX]; - if (machine__is_default_guest(machine)) + if (machine__is_default_guest(self)) modules = symbol_conf.default_guest_modules; else { - sprintf(path, "%s/proc/modules", machine->root_dir); + sprintf(path, "%s/proc/modules", self->root_dir); modules = path; } @@ -1822,16 +1815,16 @@ static int machine__create_modules(struct machine *machine) *sep = '\0'; snprintf(name, sizeof(name), "[%s]", line); - map = machine__new_module(machine, start, name); + map = machine__new_module(self, start, name); if (map == NULL) goto out_delete_line; - dso__kernel_module_get_build_id(map->dso, machine->root_dir); + dso__kernel_module_get_build_id(map->dso, self->root_dir); } free(line); fclose(file); - return machine__set_modules_path(machine); + return machine__set_modules_path(self); out_delete_line: free(line); @@ -1839,7 +1832,7 @@ static int machine__create_modules(struct machine *machine) return -1; } -int dso__load_vmlinux(struct dso *dso, struct map *map, +int dso__load_vmlinux(struct dso *self, struct map *map, const char *vmlinux, symbol_filter_t filter) { int err = -1, fd; @@ -1851,9 +1844,9 @@ int dso__load_vmlinux(struct dso *dso, struct map *map, if (fd < 0) return -1; - dso__set_long_name(dso, (char *)vmlinux); - dso__set_loaded(dso, map->type); - err = dso__load_sym(dso, map, symfs_vmlinux, fd, filter, 0, 0); + dso__set_long_name(self, (char *)vmlinux); + dso__set_loaded(self, map->type); + err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0); close(fd); if (err > 0) @@ -1862,7 +1855,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map, return err; } -int dso__load_vmlinux_path(struct dso *dso, struct map *map, +int dso__load_vmlinux_path(struct dso *self, struct map *map, symbol_filter_t filter) { int i, err = 0; @@ -1871,20 +1864,20 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, pr_debug("Looking at the vmlinux_path (%d entries long)\n", vmlinux_path__nr_entries + 1); - filename = dso__build_id_filename(dso, NULL, 0); + filename = dso__build_id_filename(self, NULL, 0); if (filename != NULL) { - err = dso__load_vmlinux(dso, map, filename, filter); + err = dso__load_vmlinux(self, map, filename, filter); if (err > 0) { - dso__set_long_name(dso, filename); + dso__set_long_name(self, filename); goto out; } free(filename); } for (i = 0; i < vmlinux_path__nr_entries; ++i) { - err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter); + err = dso__load_vmlinux(self, map, vmlinux_path[i], filter); if (err > 0) { - dso__set_long_name(dso, strdup(vmlinux_path[i])); + dso__set_long_name(self, strdup(vmlinux_path[i])); break; } } @@ -1892,7 +1885,7 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, return err; } -static int dso__load_kernel_sym(struct dso *dso, struct map *map, +static int dso__load_kernel_sym(struct dso *self, struct map *map, symbol_filter_t filter) { int err; @@ -1919,10 +1912,10 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, } if (symbol_conf.vmlinux_name != NULL) { - err = dso__load_vmlinux(dso, map, + err = dso__load_vmlinux(self, map, symbol_conf.vmlinux_name, filter); if (err > 0) { - dso__set_long_name(dso, + dso__set_long_name(self, strdup(symbol_conf.vmlinux_name)); goto out_fixup; } @@ -1930,7 +1923,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, } if (vmlinux_path != NULL) { - err = dso__load_vmlinux_path(dso, map, filter); + err = dso__load_vmlinux_path(self, map, filter); if (err > 0) goto out_fixup; } @@ -1944,13 +1937,13 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, * we have a build-id, so check if it is the same as the running kernel, * using it if it is. */ - if (dso->has_build_id) { + if (self->has_build_id) { u8 kallsyms_build_id[BUILD_ID_SIZE]; char sbuild_id[BUILD_ID_SIZE * 2 + 1]; if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id, sizeof(kallsyms_build_id)) == 0) { - if (dso__build_id_equal(dso, kallsyms_build_id)) { + if (dso__build_id_equal(self, kallsyms_build_id)) { kallsyms_filename = "/proc/kallsyms"; goto do_kallsyms; } @@ -1959,7 +1952,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, * Now look if we have it on the build-id cache in * $HOME/.debug/[kernel.kallsyms]. */ - build_id__sprintf(dso->build_id, sizeof(dso->build_id), + build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id); if (asprintf(&kallsyms_allocated_filename, @@ -1986,7 +1979,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, } do_kallsyms: - err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); + err = dso__load_kallsyms(self, kallsyms_filename, map, filter); if (err > 0) pr_debug("Using %s for symbols\n", kallsyms_filename); free(kallsyms_allocated_filename); @@ -1994,7 +1987,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, if (err > 0) { out_fixup: if (kallsyms_filename != NULL) - dso__set_long_name(dso, strdup("[kernel.kallsyms]")); + dso__set_long_name(self, strdup("[kernel.kallsyms]")); map__fixup_start(map); map__fixup_end(map); } @@ -2002,8 +1995,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, return err; } -static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, - symbol_filter_t filter) +static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, + symbol_filter_t filter) { int err; const char *kallsyms_filename = NULL; @@ -2023,7 +2016,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, * Or use file guest_kallsyms inputted by user on commandline */ if (symbol_conf.default_guest_vmlinux_name != NULL) { - err = dso__load_vmlinux(dso, map, + err = dso__load_vmlinux(self, map, symbol_conf.default_guest_vmlinux_name, filter); goto out_try_fixup; } @@ -2036,7 +2029,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, kallsyms_filename = path; } - err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); + err = dso__load_kallsyms(self, kallsyms_filename, map, filter); if (err > 0) pr_debug("Using %s for symbols\n", kallsyms_filename); @@ -2044,7 +2037,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, if (err > 0) { if (kallsyms_filename != NULL) { machine__mmap_name(machine, path, sizeof(path)); - dso__set_long_name(dso, strdup(path)); + dso__set_long_name(self, strdup(path)); } map__fixup_start(map); map__fixup_end(map); @@ -2097,12 +2090,12 @@ size_t __dsos__fprintf(struct list_head *head, FILE *fp) return ret; } -size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp) +size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp) { struct rb_node *nd; size_t ret = 0; - for (nd = rb_first(machines); nd; nd = rb_next(nd)) { + for (nd = rb_first(self); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); ret += __dsos__fprintf(&pos->kernel_dsos, fp); ret += __dsos__fprintf(&pos->user_dsos, fp); @@ -2126,20 +2119,18 @@ static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, return ret; } -size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, - bool with_hits) +size_t machine__fprintf_dsos_buildid(struct machine *self, FILE *fp, bool with_hits) { - return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, with_hits) + - __dsos__fprintf_buildid(&machine->user_dsos, fp, with_hits); + return __dsos__fprintf_buildid(&self->kernel_dsos, fp, with_hits) + + __dsos__fprintf_buildid(&self->user_dsos, fp, with_hits); } -size_t machines__fprintf_dsos_buildid(struct rb_root *machines, - FILE *fp, bool with_hits) +size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits) { struct rb_node *nd; size_t ret = 0; - for (nd = rb_first(machines); nd; nd = rb_next(nd)) { + for (nd = rb_first(self); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); ret += machine__fprintf_dsos_buildid(pos, fp, with_hits); } @@ -2148,59 +2139,59 @@ size_t machines__fprintf_dsos_buildid(struct rb_root *machines, struct dso *dso__new_kernel(const char *name) { - struct dso *dso = dso__new(name ?: "[kernel.kallsyms]"); + struct dso *self = dso__new(name ?: "[kernel.kallsyms]"); - if (dso != NULL) { - dso__set_short_name(dso, "[kernel]"); - dso->kernel = DSO_TYPE_KERNEL; + if (self != NULL) { + dso__set_short_name(self, "[kernel]"); + self->kernel = DSO_TYPE_KERNEL; } - return dso; + return self; } static struct dso *dso__new_guest_kernel(struct machine *machine, const char *name) { char bf[PATH_MAX]; - struct dso *dso = dso__new(name ?: machine__mmap_name(machine, bf, - sizeof(bf))); - if (dso != NULL) { - dso__set_short_name(dso, "[guest.kernel]"); - dso->kernel = DSO_TYPE_GUEST_KERNEL; + struct dso *self = dso__new(name ?: machine__mmap_name(machine, bf, sizeof(bf))); + + if (self != NULL) { + dso__set_short_name(self, "[guest.kernel]"); + self->kernel = DSO_TYPE_GUEST_KERNEL; } - return dso; + return self; } -void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine) +void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine) { char path[PATH_MAX]; if (machine__is_default_guest(machine)) return; sprintf(path, "%s/sys/kernel/notes", machine->root_dir); - if (sysfs__read_build_id(path, dso->build_id, - sizeof(dso->build_id)) == 0) - dso->has_build_id = true; + if (sysfs__read_build_id(path, self->build_id, + sizeof(self->build_id)) == 0) + self->has_build_id = true; } -static struct dso *machine__create_kernel(struct machine *machine) +static struct dso *machine__create_kernel(struct machine *self) { const char *vmlinux_name = NULL; struct dso *kernel; - if (machine__is_host(machine)) { + if (machine__is_host(self)) { vmlinux_name = symbol_conf.vmlinux_name; kernel = dso__new_kernel(vmlinux_name); } else { - if (machine__is_default_guest(machine)) + if (machine__is_default_guest(self)) vmlinux_name = symbol_conf.default_guest_vmlinux_name; - kernel = dso__new_guest_kernel(machine, vmlinux_name); + kernel = dso__new_guest_kernel(self, vmlinux_name); } if (kernel != NULL) { - dso__read_running_kernel_build_id(kernel, machine); - dsos__add(&machine->kernel_dsos, kernel); + dso__read_running_kernel_build_id(kernel, self); + dsos__add(&self->kernel_dsos, kernel); } return kernel; } @@ -2245,43 +2236,41 @@ static u64 machine__get_kernel_start_addr(struct machine *machine) return args.start; } -int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) +int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) { enum map_type type; - u64 start = machine__get_kernel_start_addr(machine); + u64 start = machine__get_kernel_start_addr(self); for (type = 0; type < MAP__NR_TYPES; ++type) { struct kmap *kmap; - machine->vmlinux_maps[type] = map__new2(start, kernel, type); - if (machine->vmlinux_maps[type] == NULL) + self->vmlinux_maps[type] = map__new2(start, kernel, type); + if (self->vmlinux_maps[type] == NULL) return -1; - machine->vmlinux_maps[type]->map_ip = - machine->vmlinux_maps[type]->unmap_ip = - identity__map_ip; - kmap = map__kmap(machine->vmlinux_maps[type]); - kmap->kmaps = &machine->kmaps; - map_groups__insert(&machine->kmaps, - machine->vmlinux_maps[type]); + self->vmlinux_maps[type]->map_ip = + self->vmlinux_maps[type]->unmap_ip = identity__map_ip; + + kmap = map__kmap(self->vmlinux_maps[type]); + kmap->kmaps = &self->kmaps; + map_groups__insert(&self->kmaps, self->vmlinux_maps[type]); } return 0; } -void machine__destroy_kernel_maps(struct machine *machine) +void machine__destroy_kernel_maps(struct machine *self) { enum map_type type; for (type = 0; type < MAP__NR_TYPES; ++type) { struct kmap *kmap; - if (machine->vmlinux_maps[type] == NULL) + if (self->vmlinux_maps[type] == NULL) continue; - kmap = map__kmap(machine->vmlinux_maps[type]); - map_groups__remove(&machine->kmaps, - machine->vmlinux_maps[type]); + kmap = map__kmap(self->vmlinux_maps[type]); + map_groups__remove(&self->kmaps, self->vmlinux_maps[type]); if (kmap->ref_reloc_sym) { /* * ref_reloc_sym is shared among all maps, so free just @@ -2295,25 +2284,25 @@ void machine__destroy_kernel_maps(struct machine *machine) kmap->ref_reloc_sym = NULL; } - map__delete(machine->vmlinux_maps[type]); - machine->vmlinux_maps[type] = NULL; + map__delete(self->vmlinux_maps[type]); + self->vmlinux_maps[type] = NULL; } } -int machine__create_kernel_maps(struct machine *machine) +int machine__create_kernel_maps(struct machine *self) { - struct dso *kernel = machine__create_kernel(machine); + struct dso *kernel = machine__create_kernel(self); if (kernel == NULL || - __machine__create_kernel_maps(machine, kernel) < 0) + __machine__create_kernel_maps(self, kernel) < 0) return -1; - if (symbol_conf.use_modules && machine__create_modules(machine) < 0) + if (symbol_conf.use_modules && machine__create_modules(self) < 0) pr_debug("Problems creating module maps, continuing anyway...\n"); /* * Now that we have all the maps created, just set the ->end of them: */ - map_groups__fixup_end(&machine->kmaps); + map_groups__fixup_end(&self->kmaps); return 0; } @@ -2377,11 +2366,11 @@ static int vmlinux_path__init(void) return -1; } -size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp) +size_t machine__fprintf_vmlinux_path(struct machine *self, FILE *fp) { int i; size_t printed = 0; - struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso; + struct dso *kdso = self->vmlinux_maps[MAP__FUNCTION]->dso; if (kdso->has_build_id) { char filename[PATH_MAX]; @@ -2478,9 +2467,9 @@ void symbol__exit(void) symbol_conf.initialized = false; } -int machines__create_kernel_maps(struct rb_root *machines, pid_t pid) +int machines__create_kernel_maps(struct rb_root *self, pid_t pid) { - struct machine *machine = machines__findnew(machines, pid); + struct machine *machine = machines__findnew(self, pid); if (machine == NULL) return -1; @@ -2531,7 +2520,7 @@ char *strxfrchar(char *s, char from, char to) return s; } -int machines__create_guest_kernel_maps(struct rb_root *machines) +int machines__create_guest_kernel_maps(struct rb_root *self) { int ret = 0; struct dirent **namelist = NULL; @@ -2542,7 +2531,7 @@ int machines__create_guest_kernel_maps(struct rb_root *machines) if (symbol_conf.default_guest_vmlinux_name || symbol_conf.default_guest_modules || symbol_conf.default_guest_kallsyms) { - machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID); + machines__create_kernel_maps(self, DEFAULT_GUEST_KERNEL_ID); } if (symbol_conf.guestmount) { @@ -2563,7 +2552,7 @@ int machines__create_guest_kernel_maps(struct rb_root *machines) pr_debug("Can't access file %s\n", path); goto failure; } - machines__create_kernel_maps(machines, pid); + machines__create_kernel_maps(self, pid); } failure: free(namelist); @@ -2572,23 +2561,23 @@ int machines__create_guest_kernel_maps(struct rb_root *machines) return ret; } -void machines__destroy_guest_kernel_maps(struct rb_root *machines) +void machines__destroy_guest_kernel_maps(struct rb_root *self) { - struct rb_node *next = rb_first(machines); + struct rb_node *next = rb_first(self); while (next) { struct machine *pos = rb_entry(next, struct machine, rb_node); next = rb_next(&pos->rb_node); - rb_erase(&pos->rb_node, machines); + rb_erase(&pos->rb_node, self); machine__delete(pos); } } -int machine__load_kallsyms(struct machine *machine, const char *filename, +int machine__load_kallsyms(struct machine *self, const char *filename, enum map_type type, symbol_filter_t filter) { - struct map *map = machine->vmlinux_maps[type]; + struct map *map = self->vmlinux_maps[type]; int ret = dso__load_kallsyms(map->dso, filename, map, filter); if (ret > 0) { @@ -2598,16 +2587,16 @@ int machine__load_kallsyms(struct machine *machine, const char *filename, * kernel, with modules between them, fixup the end of all * sections. */ - __map_groups__fixup_end(&machine->kmaps, type); + __map_groups__fixup_end(&self->kmaps, type); } return ret; } -int machine__load_vmlinux_path(struct machine *machine, enum map_type type, +int machine__load_vmlinux_path(struct machine *self, enum map_type type, symbol_filter_t filter) { - struct map *map = machine->vmlinux_maps[type]; + struct map *map = self->vmlinux_maps[type]; int ret = dso__load_vmlinux_path(map->dso, map, filter); if (ret > 0) { diff --git a/trunk/tools/perf/util/symbol.h b/trunk/tools/perf/util/symbol.h index 242de0101a86..713b0b40cc4a 100644 --- a/trunk/tools/perf/util/symbol.h +++ b/trunk/tools/perf/util/symbol.h @@ -62,7 +62,7 @@ struct symbol { char name[0]; }; -void symbol__delete(struct symbol *sym); +void symbol__delete(struct symbol *self); struct strlist; @@ -96,9 +96,9 @@ struct symbol_conf { extern struct symbol_conf symbol_conf; -static inline void *symbol__priv(struct symbol *sym) +static inline void *symbol__priv(struct symbol *self) { - return ((void *)sym) - symbol_conf.priv_size; + return ((void *)self) - symbol_conf.priv_size; } struct ref_reloc_sym { @@ -155,45 +155,43 @@ struct dso { struct dso *dso__new(const char *name); struct dso *dso__new_kernel(const char *name); -void dso__delete(struct dso *dso); +void dso__delete(struct dso *self); -int dso__name_len(const struct dso *dso); +int dso__name_len(const struct dso *self); -bool dso__loaded(const struct dso *dso, enum map_type type); -bool dso__sorted_by_name(const struct dso *dso, enum map_type type); +bool dso__loaded(const struct dso *self, enum map_type type); +bool dso__sorted_by_name(const struct dso *self, enum map_type type); -static inline void dso__set_loaded(struct dso *dso, enum map_type type) +static inline void dso__set_loaded(struct dso *self, enum map_type type) { - dso->loaded |= (1 << type); + self->loaded |= (1 << type); } -void dso__sort_by_name(struct dso *dso, enum map_type type); +void dso__sort_by_name(struct dso *self, enum map_type type); struct dso *__dsos__findnew(struct list_head *head, const char *name); -int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); -int dso__load_vmlinux(struct dso *dso, struct map *map, +int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); +int dso__load_vmlinux(struct dso *self, struct map *map, const char *vmlinux, symbol_filter_t filter); -int dso__load_vmlinux_path(struct dso *dso, struct map *map, +int dso__load_vmlinux_path(struct dso *self, struct map *map, symbol_filter_t filter); -int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, +int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, symbol_filter_t filter); -int machine__load_kallsyms(struct machine *machine, const char *filename, +int machine__load_kallsyms(struct machine *self, const char *filename, enum map_type type, symbol_filter_t filter); -int machine__load_vmlinux_path(struct machine *machine, enum map_type type, +int machine__load_vmlinux_path(struct machine *self, enum map_type type, symbol_filter_t filter); size_t __dsos__fprintf(struct list_head *head, FILE *fp); -size_t machine__fprintf_dsos_buildid(struct machine *machine, - FILE *fp, bool with_hits); -size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp); -size_t machines__fprintf_dsos_buildid(struct rb_root *machines, - FILE *fp, bool with_hits); -size_t dso__fprintf_buildid(struct dso *dso, FILE *fp); -size_t dso__fprintf_symbols_by_name(struct dso *dso, - enum map_type type, FILE *fp); -size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp); +size_t machine__fprintf_dsos_buildid(struct machine *self, FILE *fp, bool with_hits); +size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp); +size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits); + +size_t dso__fprintf_buildid(struct dso *self, FILE *fp); +size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp); +size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); enum symtab_type { SYMTAB__KALLSYMS = 0, @@ -209,36 +207,34 @@ enum symtab_type { SYMTAB__NOT_FOUND, }; -char dso__symtab_origin(const struct dso *dso); -void dso__set_long_name(struct dso *dso, char *name); -void dso__set_build_id(struct dso *dso, void *build_id); -void dso__read_running_kernel_build_id(struct dso *dso, - struct machine *machine); -struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, - u64 addr); -struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, +char dso__symtab_origin(const struct dso *self); +void dso__set_long_name(struct dso *self, char *name); +void dso__set_build_id(struct dso *self, void *build_id); +void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine); +struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); +struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, const char *name); int filename__read_build_id(const char *filename, void *bf, size_t size); int sysfs__read_build_id(const char *filename, void *bf, size_t size); bool __dsos__read_build_ids(struct list_head *head, bool with_hits); -int build_id__sprintf(const u8 *build_id, int len, char *bf); +int build_id__sprintf(const u8 *self, int len, char *bf); int kallsyms__parse(const char *filename, void *arg, int (*process_symbol)(void *arg, const char *name, char type, u64 start, u64 end)); -void machine__destroy_kernel_maps(struct machine *machine); -int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel); -int machine__create_kernel_maps(struct machine *machine); +void machine__destroy_kernel_maps(struct machine *self); +int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); +int machine__create_kernel_maps(struct machine *self); -int machines__create_kernel_maps(struct rb_root *machines, pid_t pid); -int machines__create_guest_kernel_maps(struct rb_root *machines); -void machines__destroy_guest_kernel_maps(struct rb_root *machines); +int machines__create_kernel_maps(struct rb_root *self, pid_t pid); +int machines__create_guest_kernel_maps(struct rb_root *self); +void machines__destroy_guest_kernel_maps(struct rb_root *self); int symbol__init(void); void symbol__exit(void); bool symbol_type__is_a(char symbol_type, enum map_type map_type); -size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); +size_t machine__fprintf_vmlinux_path(struct machine *self, FILE *fp); #endif /* __PERF_SYMBOL */