Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
824df399
cloud-kernel
项目概览
openanolis
/
cloud-kernel
接近 2 年 前同步成功
通知
170
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
824df399
编写于
8月 15, 2009
作者:
R
Russell King
提交者:
Russell King
8月 15, 2009
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 's3c-fixes' of
git://aeryn.fluff.org.uk/bjdooks/linux
上级
8b612078
48ec45e7
变更
66
隐藏空白更改
内联
并排
Showing
66 changed file
with
1455 addition
and
341 deletion
+1455
-341
Documentation/ioctl/ioctl-number.txt
Documentation/ioctl/ioctl-number.txt
+1
-0
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+4
-0
arch/arm/plat-s3c24xx/clock-dclk.c
arch/arm/plat-s3c24xx/clock-dclk.c
+1
-1
arch/ia64/Makefile
arch/ia64/Makefile
+0
-5
arch/ia64/include/asm/bitops.h
arch/ia64/include/asm/bitops.h
+1
-1
arch/ia64/include/asm/pgtable.h
arch/ia64/include/asm/pgtable.h
+0
-1
arch/ia64/kernel/ia64_ksyms.c
arch/ia64/kernel/ia64_ksyms.c
+1
-3
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/iosapic.c
+4
-0
arch/ia64/kernel/pci-dma.c
arch/ia64/kernel/pci-dma.c
+0
-5
arch/ia64/kernel/topology.c
arch/ia64/kernel/topology.c
+5
-1
arch/mn10300/include/asm/pci.h
arch/mn10300/include/asm/pci.h
+0
-1
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/dma.c
+3
-3
arch/powerpc/kernel/perf_counter.c
arch/powerpc/kernel/perf_counter.c
+8
-0
arch/x86/kernel/tsc.c
arch/x86/kernel/tsc.c
+22
-7
drivers/ata/ahci.c
drivers/ata/ahci.c
+74
-5
drivers/ata/libata-core.c
drivers/ata/libata-core.c
+3
-0
drivers/ata/pata_at91.c
drivers/ata/pata_at91.c
+4
-13
drivers/ata/pata_atiixp.c
drivers/ata/pata_atiixp.c
+10
-9
drivers/ata/sata_nv.c
drivers/ata/sata_nv.c
+8
-0
drivers/base/platform.c
drivers/base/platform.c
+0
-3
drivers/char/pty.c
drivers/char/pty.c
+2
-0
drivers/mtd/maps/sbc8240.c
drivers/mtd/maps/sbc8240.c
+0
-0
drivers/pci/hotplug/sgi_hotplug.c
drivers/pci/hotplug/sgi_hotplug.c
+3
-4
drivers/serial/Kconfig
drivers/serial/Kconfig
+1
-1
fs/nfs/direct.c
fs/nfs/direct.c
+10
-10
fs/nfs/read.c
fs/nfs/read.c
+2
-4
fs/nfs/write.c
fs/nfs/write.c
+2
-4
fs/proc/base.c
fs/proc/base.c
+12
-15
fs/proc/task_mmu.c
fs/proc/task_mmu.c
+1
-0
fs/proc/task_nommu.c
fs/proc/task_nommu.c
+1
-0
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_buf.c
+1
-1
fs/xfs/xfs_attr.c
fs/xfs/xfs_attr.c
+5
-3
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap.c
+1
-1
fs/xfs/xfs_btree.c
fs/xfs/xfs_btree.c
+2
-2
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_da_btree.c
+3
-3
fs/xfs/xfs_dir2.c
fs/xfs/xfs_dir2.c
+1
-1
fs/xfs/xfs_fsops.c
fs/xfs/xfs_fsops.c
+14
-6
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.c
+10
-0
fs/xfs/xfs_log.c
fs/xfs/xfs_log.c
+1
-1
fs/xfs/xfs_vnodeops.c
fs/xfs/xfs_vnodeops.c
+3
-1
include/linux/nfs_fs.h
include/linux/nfs_fs.h
+2
-3
include/linux/perf_counter.h
include/linux/perf_counter.h
+7
-5
include/trace/ftrace.h
include/trace/ftrace.h
+13
-2
kernel/irq/numa_migrate.c
kernel/irq/numa_migrate.c
+2
-2
kernel/perf_counter.c
kernel/perf_counter.c
+145
-94
kernel/trace/blktrace.c
kernel/trace/blktrace.c
+1
-11
mm/mempool.c
mm/mempool.c
+2
-2
security/selinux/hooks.c
security/selinux/hooks.c
+2
-1
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_realtek.c
+14
-6
sound/soc/fsl/efika-audio-fabric.c
sound/soc/fsl/efika-audio-fabric.c
+2
-0
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/fsl/pcm030-audio-fabric.c
+2
-0
tools/perf/Documentation/perf-examples.txt
tools/perf/Documentation/perf-examples.txt
+225
-0
tools/perf/Documentation/perf-stat.txt
tools/perf/Documentation/perf-stat.txt
+1
-1
tools/perf/Documentation/perf-top.txt
tools/perf/Documentation/perf-top.txt
+99
-13
tools/perf/Makefile
tools/perf/Makefile
+4
-0
tools/perf/builtin-record.c
tools/perf/builtin-record.c
+8
-4
tools/perf/builtin-report.c
tools/perf/builtin-report.c
+89
-10
tools/perf/builtin-stat.c
tools/perf/builtin-stat.c
+1
-1
tools/perf/builtin-top.c
tools/perf/builtin-top.c
+508
-44
tools/perf/util/callchain.c
tools/perf/util/callchain.c
+20
-12
tools/perf/util/callchain.h
tools/perf/util/callchain.h
+7
-1
tools/perf/util/header.c
tools/perf/util/header.c
+4
-1
tools/perf/util/parse-events.c
tools/perf/util/parse-events.c
+24
-2
tools/perf/util/parse-events.h
tools/perf/util/parse-events.h
+1
-0
tools/perf/util/symbol.c
tools/perf/util/symbol.c
+46
-11
tools/perf/util/symbol.h
tools/perf/util/symbol.h
+2
-0
未找到文件。
Documentation/ioctl/ioctl-number.txt
浏览文件 @
824df399
...
@@ -139,6 +139,7 @@ Code Seq# Include File Comments
...
@@ -139,6 +139,7 @@ Code Seq# Include File Comments
'm' all linux/synclink.h conflict!
'm' all linux/synclink.h conflict!
'm' 00-1F net/irda/irmod.h conflict!
'm' 00-1F net/irda/irmod.h conflict!
'n' 00-7F linux/ncp_fs.h
'n' 00-7F linux/ncp_fs.h
'n' 80-8F linux/nilfs2_fs.h NILFS2
'n' E0-FF video/matrox.h matroxfb
'n' E0-FF video/matrox.h matroxfb
'o' 00-1F fs/ocfs2/ocfs2_fs.h OCFS2
'o' 00-1F fs/ocfs2/ocfs2_fs.h OCFS2
'o' 00-03 include/mtd/ubi-user.h conflict! (OCFS2 and UBI overlaps)
'o' 00-03 include/mtd/ubi-user.h conflict! (OCFS2 and UBI overlaps)
...
...
Documentation/kernel-parameters.txt
浏览文件 @
824df399
...
@@ -1115,6 +1115,10 @@ and is between 256 and 4096 characters. It is defined in the file
...
@@ -1115,6 +1115,10 @@ and is between 256 and 4096 characters. It is defined in the file
libata.dma=4 Compact Flash DMA only
libata.dma=4 Compact Flash DMA only
Combinations also work, so libata.dma=3 enables DMA
Combinations also work, so libata.dma=3 enables DMA
for disks and CDROMs, but not CFs.
for disks and CDROMs, but not CFs.
libata.ignore_hpa= [LIBATA] Ignore HPA limit
libata.ignore_hpa=0 keep BIOS limits (default)
libata.ignore_hpa=1 ignore limits, using full disk
libata.noacpi [LIBATA] Disables use of ACPI in libata suspend/resume
libata.noacpi [LIBATA] Disables use of ACPI in libata suspend/resume
when set.
when set.
...
...
arch/arm/plat-s3c24xx/clock-dclk.c
浏览文件 @
824df399
...
@@ -129,7 +129,7 @@ static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
...
@@ -129,7 +129,7 @@ static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
/* calculate the MISCCR setting for the clock */
/* calculate the MISCCR setting for the clock */
if
(
parent
==
&
clk_
xta
l
)
if
(
parent
==
&
clk_
mpl
l
)
source
=
S3C2410_MISCCR_CLK0_MPLL
;
source
=
S3C2410_MISCCR_CLK0_MPLL
;
else
if
(
parent
==
&
clk_upll
)
else
if
(
parent
==
&
clk_upll
)
source
=
S3C2410_MISCCR_CLK0_UPLL
;
source
=
S3C2410_MISCCR_CLK0_UPLL
;
...
...
arch/ia64/Makefile
浏览文件 @
824df399
...
@@ -41,11 +41,6 @@ $(error Sorry, you need a newer version of the assember, one that is built from
...
@@ -41,11 +41,6 @@ $(error Sorry, you need a newer version of the assember, one that is built from
ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
endif
endif
ifeq
($(call cc-version),0304)
cflags-$(CONFIG_ITANIUM)
+=
-mtune
=
merced
cflags-$(CONFIG_MCKINLEY)
+=
-mtune
=
mckinley
endif
KBUILD_CFLAGS
+=
$
(
cflags-y
)
KBUILD_CFLAGS
+=
$
(
cflags-y
)
head-y
:=
arch
/ia64/kernel/head.o
arch
/ia64/kernel/init_task.o
head-y
:=
arch
/ia64/kernel/head.o
arch
/ia64/kernel/init_task.o
...
...
arch/ia64/include/asm/bitops.h
浏览文件 @
824df399
...
@@ -286,7 +286,7 @@ __test_and_clear_bit(int nr, volatile void * addr)
...
@@ -286,7 +286,7 @@ __test_and_clear_bit(int nr, volatile void * addr)
{
{
__u32
*
p
=
(
__u32
*
)
addr
+
(
nr
>>
5
);
__u32
*
p
=
(
__u32
*
)
addr
+
(
nr
>>
5
);
__u32
m
=
1
<<
(
nr
&
31
);
__u32
m
=
1
<<
(
nr
&
31
);
int
oldbitset
=
*
p
&
m
;
int
oldbitset
=
(
*
p
&
m
)
!=
0
;
*
p
&=
~
m
;
*
p
&=
~
m
;
return
oldbitset
;
return
oldbitset
;
...
...
arch/ia64/include/asm/pgtable.h
浏览文件 @
824df399
...
@@ -155,7 +155,6 @@
...
@@ -155,7 +155,6 @@
#include <linux/bitops.h>
#include <linux/bitops.h>
#include <asm/cacheflush.h>
#include <asm/cacheflush.h>
#include <asm/mmu_context.h>
#include <asm/mmu_context.h>
#include <asm/processor.h>
/*
/*
* Next come the mappings that determine how mmap() protection bits
* Next come the mappings that determine how mmap() protection bits
...
...
arch/ia64/kernel/ia64_ksyms.c
浏览文件 @
824df399
...
@@ -21,6 +21,7 @@ EXPORT_SYMBOL(csum_ipv6_magic);
...
@@ -21,6 +21,7 @@ EXPORT_SYMBOL(csum_ipv6_magic);
#include <asm/page.h>
#include <asm/page.h>
EXPORT_SYMBOL
(
clear_page
);
EXPORT_SYMBOL
(
clear_page
);
EXPORT_SYMBOL
(
copy_page
);
#ifdef CONFIG_VIRTUAL_MEM_MAP
#ifdef CONFIG_VIRTUAL_MEM_MAP
#include <linux/bootmem.h>
#include <linux/bootmem.h>
...
@@ -60,9 +61,6 @@ EXPORT_SYMBOL(__udivdi3);
...
@@ -60,9 +61,6 @@ EXPORT_SYMBOL(__udivdi3);
EXPORT_SYMBOL
(
__moddi3
);
EXPORT_SYMBOL
(
__moddi3
);
EXPORT_SYMBOL
(
__umoddi3
);
EXPORT_SYMBOL
(
__umoddi3
);
#include <asm/page.h>
EXPORT_SYMBOL
(
copy_page
);
#if defined(CONFIG_MD_RAID456) || defined(CONFIG_MD_RAID456_MODULE)
#if defined(CONFIG_MD_RAID456) || defined(CONFIG_MD_RAID456_MODULE)
extern
void
xor_ia64_2
(
void
);
extern
void
xor_ia64_2
(
void
);
extern
void
xor_ia64_3
(
void
);
extern
void
xor_ia64_3
(
void
);
...
...
arch/ia64/kernel/iosapic.c
浏览文件 @
824df399
...
@@ -1072,6 +1072,10 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
...
@@ -1072,6 +1072,10 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
}
}
addr
=
ioremap
(
phys_addr
,
0
);
addr
=
ioremap
(
phys_addr
,
0
);
if
(
addr
==
NULL
)
{
spin_unlock_irqrestore
(
&
iosapic_lock
,
flags
);
return
-
ENOMEM
;
}
ver
=
iosapic_version
(
addr
);
ver
=
iosapic_version
(
addr
);
if
((
err
=
iosapic_check_gsi_range
(
gsi_base
,
ver
)))
{
if
((
err
=
iosapic_check_gsi_range
(
gsi_base
,
ver
)))
{
iounmap
(
addr
);
iounmap
(
addr
);
...
...
arch/ia64/kernel/pci-dma.c
浏览文件 @
824df399
...
@@ -69,11 +69,6 @@ iommu_dma_init(void)
...
@@ -69,11 +69,6 @@ iommu_dma_init(void)
int
iommu_dma_supported
(
struct
device
*
dev
,
u64
mask
)
int
iommu_dma_supported
(
struct
device
*
dev
,
u64
mask
)
{
{
struct
dma_map_ops
*
ops
=
platform_dma_get_ops
(
dev
);
if
(
ops
->
dma_supported
)
return
ops
->
dma_supported
(
dev
,
mask
);
/* Copied from i386. Doesn't make much sense, because it will
/* Copied from i386. Doesn't make much sense, because it will
only work for pci_alloc_coherent.
only work for pci_alloc_coherent.
The caller just has to use GFP_DMA in this case. */
The caller just has to use GFP_DMA in this case. */
...
...
arch/ia64/kernel/topology.c
浏览文件 @
824df399
...
@@ -372,6 +372,10 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
...
@@ -372,6 +372,10 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
retval
=
kobject_init_and_add
(
&
all_cpu_cache_info
[
cpu
].
kobj
,
retval
=
kobject_init_and_add
(
&
all_cpu_cache_info
[
cpu
].
kobj
,
&
cache_ktype_percpu_entry
,
&
sys_dev
->
kobj
,
&
cache_ktype_percpu_entry
,
&
sys_dev
->
kobj
,
"%s"
,
"cache"
);
"%s"
,
"cache"
);
if
(
unlikely
(
retval
<
0
))
{
cpu_cache_sysfs_exit
(
cpu
);
return
retval
;
}
for
(
i
=
0
;
i
<
all_cpu_cache_info
[
cpu
].
num_cache_leaves
;
i
++
)
{
for
(
i
=
0
;
i
<
all_cpu_cache_info
[
cpu
].
num_cache_leaves
;
i
++
)
{
this_object
=
LEAF_KOBJECT_PTR
(
cpu
,
i
);
this_object
=
LEAF_KOBJECT_PTR
(
cpu
,
i
);
...
@@ -385,7 +389,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
...
@@ -385,7 +389,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
}
}
kobject_put
(
&
all_cpu_cache_info
[
cpu
].
kobj
);
kobject_put
(
&
all_cpu_cache_info
[
cpu
].
kobj
);
cpu_cache_sysfs_exit
(
cpu
);
cpu_cache_sysfs_exit
(
cpu
);
break
;
return
retval
;
}
}
kobject_uevent
(
&
(
this_object
->
kobj
),
KOBJ_ADD
);
kobject_uevent
(
&
(
this_object
->
kobj
),
KOBJ_ADD
);
}
}
...
...
arch/mn10300/include/asm/pci.h
浏览文件 @
824df399
...
@@ -59,7 +59,6 @@ void pcibios_penalize_isa_irq(int irq);
...
@@ -59,7 +59,6 @@ void pcibios_penalize_isa_irq(int irq);
#include <linux/slab.h>
#include <linux/slab.h>
#include <asm/scatterlist.h>
#include <asm/scatterlist.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/io.h>
struct
pci_dev
;
struct
pci_dev
;
...
...
arch/powerpc/kernel/dma.c
浏览文件 @
824df399
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
#include <linux/device.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/dma-mapping.h>
#include <linux/lmb.h>
#include <asm/bug.h>
#include <asm/bug.h>
#include <asm/abs_addr.h>
#include <asm/abs_addr.h>
...
@@ -90,11 +91,10 @@ static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
...
@@ -90,11 +91,10 @@ static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
static
int
dma_direct_dma_supported
(
struct
device
*
dev
,
u64
mask
)
static
int
dma_direct_dma_supported
(
struct
device
*
dev
,
u64
mask
)
{
{
#ifdef CONFIG_PPC64
#ifdef CONFIG_PPC64
/* Could be improved to check for memory though it better be
/* Could be improved so platforms can set the limit in case
* done via some global so platforms can set the limit in case
* they have limited DMA windows
* they have limited DMA windows
*/
*/
return
mask
>=
DMA_BIT_MASK
(
32
);
return
mask
>=
(
lmb_end_of_DRAM
()
-
1
);
#else
#else
return
1
;
return
1
;
#endif
#endif
...
...
arch/powerpc/kernel/perf_counter.c
浏览文件 @
824df399
...
@@ -518,6 +518,8 @@ void hw_perf_disable(void)
...
@@ -518,6 +518,8 @@ void hw_perf_disable(void)
struct
cpu_hw_counters
*
cpuhw
;
struct
cpu_hw_counters
*
cpuhw
;
unsigned
long
flags
;
unsigned
long
flags
;
if
(
!
ppmu
)
return
;
local_irq_save
(
flags
);
local_irq_save
(
flags
);
cpuhw
=
&
__get_cpu_var
(
cpu_hw_counters
);
cpuhw
=
&
__get_cpu_var
(
cpu_hw_counters
);
...
@@ -572,6 +574,8 @@ void hw_perf_enable(void)
...
@@ -572,6 +574,8 @@ void hw_perf_enable(void)
int
n_lim
;
int
n_lim
;
int
idx
;
int
idx
;
if
(
!
ppmu
)
return
;
local_irq_save
(
flags
);
local_irq_save
(
flags
);
cpuhw
=
&
__get_cpu_var
(
cpu_hw_counters
);
cpuhw
=
&
__get_cpu_var
(
cpu_hw_counters
);
if
(
!
cpuhw
->
disabled
)
{
if
(
!
cpuhw
->
disabled
)
{
...
@@ -737,6 +741,8 @@ int hw_perf_group_sched_in(struct perf_counter *group_leader,
...
@@ -737,6 +741,8 @@ int hw_perf_group_sched_in(struct perf_counter *group_leader,
long
i
,
n
,
n0
;
long
i
,
n
,
n0
;
struct
perf_counter
*
sub
;
struct
perf_counter
*
sub
;
if
(
!
ppmu
)
return
0
;
cpuhw
=
&
__get_cpu_var
(
cpu_hw_counters
);
cpuhw
=
&
__get_cpu_var
(
cpu_hw_counters
);
n0
=
cpuhw
->
n_counters
;
n0
=
cpuhw
->
n_counters
;
n
=
collect_events
(
group_leader
,
ppmu
->
n_counter
-
n0
,
n
=
collect_events
(
group_leader
,
ppmu
->
n_counter
-
n0
,
...
@@ -1281,6 +1287,8 @@ void hw_perf_counter_setup(int cpu)
...
@@ -1281,6 +1287,8 @@ void hw_perf_counter_setup(int cpu)
{
{
struct
cpu_hw_counters
*
cpuhw
=
&
per_cpu
(
cpu_hw_counters
,
cpu
);
struct
cpu_hw_counters
*
cpuhw
=
&
per_cpu
(
cpu_hw_counters
,
cpu
);
if
(
!
ppmu
)
return
;
memset
(
cpuhw
,
0
,
sizeof
(
*
cpuhw
));
memset
(
cpuhw
,
0
,
sizeof
(
*
cpuhw
));
cpuhw
->
mmcr
[
0
]
=
MMCR0_FC
;
cpuhw
->
mmcr
[
0
]
=
MMCR0_FC
;
}
}
...
...
arch/x86/kernel/tsc.c
浏览文件 @
824df399
...
@@ -275,15 +275,20 @@ static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin)
...
@@ -275,15 +275,20 @@ static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin)
* use the TSC value at the transitions to calculate a pretty
* use the TSC value at the transitions to calculate a pretty
* good value for the TSC frequencty.
* good value for the TSC frequencty.
*/
*/
static
inline
int
pit_verify_msb
(
unsigned
char
val
)
{
/* Ignore LSB */
inb
(
0x42
);
return
inb
(
0x42
)
==
val
;
}
static
inline
int
pit_expect_msb
(
unsigned
char
val
,
u64
*
tscp
,
unsigned
long
*
deltap
)
static
inline
int
pit_expect_msb
(
unsigned
char
val
,
u64
*
tscp
,
unsigned
long
*
deltap
)
{
{
int
count
;
int
count
;
u64
tsc
=
0
;
u64
tsc
=
0
;
for
(
count
=
0
;
count
<
50000
;
count
++
)
{
for
(
count
=
0
;
count
<
50000
;
count
++
)
{
/* Ignore LSB */
if
(
!
pit_verify_msb
(
val
))
inb
(
0x42
);
if
(
inb
(
0x42
)
!=
val
)
break
;
break
;
tsc
=
get_cycles
();
tsc
=
get_cycles
();
}
}
...
@@ -336,8 +341,7 @@ static unsigned long quick_pit_calibrate(void)
...
@@ -336,8 +341,7 @@ static unsigned long quick_pit_calibrate(void)
* to do that is to just read back the 16-bit counter
* to do that is to just read back the 16-bit counter
* once from the PIT.
* once from the PIT.
*/
*/
inb
(
0x42
);
pit_verify_msb
(
0
);
inb
(
0x42
);
if
(
pit_expect_msb
(
0xff
,
&
tsc
,
&
d1
))
{
if
(
pit_expect_msb
(
0xff
,
&
tsc
,
&
d1
))
{
for
(
i
=
1
;
i
<=
MAX_QUICK_PIT_ITERATIONS
;
i
++
)
{
for
(
i
=
1
;
i
<=
MAX_QUICK_PIT_ITERATIONS
;
i
++
)
{
...
@@ -348,8 +352,19 @@ static unsigned long quick_pit_calibrate(void)
...
@@ -348,8 +352,19 @@ static unsigned long quick_pit_calibrate(void)
* Iterate until the error is less than 500 ppm
* Iterate until the error is less than 500 ppm
*/
*/
delta
-=
tsc
;
delta
-=
tsc
;
if
(
d1
+
d2
<
delta
>>
11
)
if
(
d1
+
d2
>=
delta
>>
11
)
goto
success
;
continue
;
/*
* Check the PIT one more time to verify that
* all TSC reads were stable wrt the PIT.
*
* This also guarantees serialization of the
* last cycle read ('d2') in pit_expect_msb.
*/
if
(
!
pit_verify_msb
(
0xfe
-
i
))
break
;
goto
success
;
}
}
}
}
printk
(
"Fast TSC calibration failed
\n
"
);
printk
(
"Fast TSC calibration failed
\n
"
);
...
...
drivers/ata/ahci.c
浏览文件 @
824df399
...
@@ -219,6 +219,8 @@ enum {
...
@@ -219,6 +219,8 @@ enum {
AHCI_HFLAG_SECT255
=
(
1
<<
8
),
/* max 255 sectors */
AHCI_HFLAG_SECT255
=
(
1
<<
8
),
/* max 255 sectors */
AHCI_HFLAG_YES_NCQ
=
(
1
<<
9
),
/* force NCQ cap on */
AHCI_HFLAG_YES_NCQ
=
(
1
<<
9
),
/* force NCQ cap on */
AHCI_HFLAG_NO_SUSPEND
=
(
1
<<
10
),
/* don't suspend */
AHCI_HFLAG_NO_SUSPEND
=
(
1
<<
10
),
/* don't suspend */
AHCI_HFLAG_SRST_TOUT_IS_OFFLINE
=
(
1
<<
11
),
/* treat SRST timeout as
link offline */
/* ap->flags bits */
/* ap->flags bits */
...
@@ -1663,6 +1665,7 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
...
@@ -1663,6 +1665,7 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
int
(
*
check_ready
)(
struct
ata_link
*
link
))
int
(
*
check_ready
)(
struct
ata_link
*
link
))
{
{
struct
ata_port
*
ap
=
link
->
ap
;
struct
ata_port
*
ap
=
link
->
ap
;
struct
ahci_host_priv
*
hpriv
=
ap
->
host
->
private_data
;
const
char
*
reason
=
NULL
;
const
char
*
reason
=
NULL
;
unsigned
long
now
,
msecs
;
unsigned
long
now
,
msecs
;
struct
ata_taskfile
tf
;
struct
ata_taskfile
tf
;
...
@@ -1701,12 +1704,21 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
...
@@ -1701,12 +1704,21 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
/* wait for link to become ready */
/* wait for link to become ready */
rc
=
ata_wait_after_reset
(
link
,
deadline
,
check_ready
);
rc
=
ata_wait_after_reset
(
link
,
deadline
,
check_ready
);
/* link occupied, -ENODEV too is an error */
if
(
rc
==
-
EBUSY
&&
hpriv
->
flags
&
AHCI_HFLAG_SRST_TOUT_IS_OFFLINE
)
{
if
(
rc
)
{
/*
* Workaround for cases where link online status can't
* be trusted. Treat device readiness timeout as link
* offline.
*/
ata_link_printk
(
link
,
KERN_INFO
,
"device not ready, treating as offline
\n
"
);
*
class
=
ATA_DEV_NONE
;
}
else
if
(
rc
)
{
/* link occupied, -ENODEV too is an error */
reason
=
"device not ready"
;
reason
=
"device not ready"
;
goto
fail
;
goto
fail
;
}
}
else
*
class
=
ahci_dev_classify
(
ap
);
*
class
=
ahci_dev_classify
(
ap
);
DPRINTK
(
"EXIT, class=%u
\n
"
,
*
class
);
DPRINTK
(
"EXIT, class=%u
\n
"
,
*
class
);
return
0
;
return
0
;
...
@@ -1773,7 +1785,8 @@ static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
...
@@ -1773,7 +1785,8 @@ static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
irq_sts
=
readl
(
port_mmio
+
PORT_IRQ_STAT
);
irq_sts
=
readl
(
port_mmio
+
PORT_IRQ_STAT
);
if
(
irq_sts
&
PORT_IRQ_BAD_PMP
)
{
if
(
irq_sts
&
PORT_IRQ_BAD_PMP
)
{
ata_link_printk
(
link
,
KERN_WARNING
,
ata_link_printk
(
link
,
KERN_WARNING
,
"failed due to HW bug, retry pmp=0
\n
"
);
"applying SB600 PMP SRST workaround "
"and retrying
\n
"
);
rc
=
ahci_do_softreset
(
link
,
class
,
0
,
deadline
,
rc
=
ahci_do_softreset
(
link
,
class
,
0
,
deadline
,
ahci_check_ready
);
ahci_check_ready
);
}
}
...
@@ -2726,6 +2739,56 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
...
@@ -2726,6 +2739,56 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
return
!
ver
||
strcmp
(
ver
,
dmi
->
driver_data
)
<
0
;
return
!
ver
||
strcmp
(
ver
,
dmi
->
driver_data
)
<
0
;
}
}
static
bool
ahci_broken_online
(
struct
pci_dev
*
pdev
)
{
#define ENCODE_BUSDEVFN(bus, slot, func) \
(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
static
const
struct
dmi_system_id
sysids
[]
=
{
/*
* There are several gigabyte boards which use
* SIMG5723s configured as hardware RAID. Certain
* 5723 firmware revisions shipped there keep the link
* online but fail to answer properly to SRST or
* IDENTIFY when no device is attached downstream
* causing libata to retry quite a few times leading
* to excessive detection delay.
*
* As these firmwares respond to the second reset try
* with invalid device signature, considering unknown
* sig as offline works around the problem acceptably.
*/
{
.
ident
=
"EP45-DQ6"
,
.
matches
=
{
DMI_MATCH
(
DMI_BOARD_VENDOR
,
"Gigabyte Technology Co., Ltd."
),
DMI_MATCH
(
DMI_BOARD_NAME
,
"EP45-DQ6"
),
},
.
driver_data
=
ENCODE_BUSDEVFN
(
0x0a
,
0x00
,
0
),
},
{
.
ident
=
"EP45-DS5"
,
.
matches
=
{
DMI_MATCH
(
DMI_BOARD_VENDOR
,
"Gigabyte Technology Co., Ltd."
),
DMI_MATCH
(
DMI_BOARD_NAME
,
"EP45-DS5"
),
},
.
driver_data
=
ENCODE_BUSDEVFN
(
0x03
,
0x00
,
0
),
},
{
}
/* terminate list */
};
#undef ENCODE_BUSDEVFN
const
struct
dmi_system_id
*
dmi
=
dmi_first_match
(
sysids
);
unsigned
int
val
;
if
(
!
dmi
)
return
false
;
val
=
(
unsigned
long
)
dmi
->
driver_data
;
return
pdev
->
bus
->
number
==
(
val
>>
8
)
&&
pdev
->
devfn
==
(
val
&
0xff
);
}
static
int
ahci_init_one
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
static
int
ahci_init_one
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
{
static
int
printed_version
;
static
int
printed_version
;
...
@@ -2841,6 +2904,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
...
@@ -2841,6 +2904,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
"BIOS update required for suspend/resume
\n
"
);
"BIOS update required for suspend/resume
\n
"
);
}
}
if
(
ahci_broken_online
(
pdev
))
{
hpriv
->
flags
|=
AHCI_HFLAG_SRST_TOUT_IS_OFFLINE
;
dev_info
(
&
pdev
->
dev
,
"online status unreliable, applying workaround
\n
"
);
}
/* CAP.NP sometimes indicate the index of the last enabled
/* CAP.NP sometimes indicate the index of the last enabled
* port, at other times, that of the last possible port, so
* port, at other times, that of the last possible port, so
* determining the maximum port number requires looking at
* determining the maximum port number requires looking at
...
...
drivers/ata/libata-core.c
浏览文件 @
824df399
...
@@ -4302,6 +4302,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
...
@@ -4302,6 +4302,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{
"WDC WD2500JD-00HBB0"
,
"WD-WMAL71490727"
,
ATA_HORKAGE_BROKEN_HPA
},
{
"WDC WD2500JD-00HBB0"
,
"WD-WMAL71490727"
,
ATA_HORKAGE_BROKEN_HPA
},
{
"MAXTOR 6L080L4"
,
"A93.0500"
,
ATA_HORKAGE_BROKEN_HPA
},
{
"MAXTOR 6L080L4"
,
"A93.0500"
,
ATA_HORKAGE_BROKEN_HPA
},
/* this one allows HPA unlocking but fails IOs on the area */
{
"OCZ-VERTEX"
,
"1.30"
,
ATA_HORKAGE_BROKEN_HPA
},
/* Devices which report 1 sector over size HPA */
/* Devices which report 1 sector over size HPA */
{
"ST340823A"
,
NULL
,
ATA_HORKAGE_HPA_SIZE
,
},
{
"ST340823A"
,
NULL
,
ATA_HORKAGE_HPA_SIZE
,
},
{
"ST320413A"
,
NULL
,
ATA_HORKAGE_HPA_SIZE
,
},
{
"ST320413A"
,
NULL
,
ATA_HORKAGE_HPA_SIZE
,
},
...
...
drivers/ata/pata_at91.c
浏览文件 @
824df399
...
@@ -250,7 +250,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
...
@@ -250,7 +250,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
ata_port_desc
(
ap
,
"no IRQ, using PIO polling"
);
ata_port_desc
(
ap
,
"no IRQ, using PIO polling"
);
}
}
info
=
kzalloc
(
sizeof
(
*
info
),
GFP_KERNEL
);
info
=
devm_kzalloc
(
dev
,
sizeof
(
*
info
),
GFP_KERNEL
);
if
(
!
info
)
{
if
(
!
info
)
{
dev_err
(
dev
,
"failed to allocate memory for private data
\n
"
);
dev_err
(
dev
,
"failed to allocate memory for private data
\n
"
);
...
@@ -275,7 +275,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
...
@@ -275,7 +275,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
if
(
!
info
->
ide_addr
)
{
if
(
!
info
->
ide_addr
)
{
dev_err
(
dev
,
"failed to map IO base
\n
"
);
dev_err
(
dev
,
"failed to map IO base
\n
"
);
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
err_
ide_ioremap
;
goto
err_
put
;
}
}
info
->
alt_addr
=
devm_ioremap
(
dev
,
info
->
alt_addr
=
devm_ioremap
(
dev
,
...
@@ -284,7 +284,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
...
@@ -284,7 +284,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
if
(
!
info
->
alt_addr
)
{
if
(
!
info
->
alt_addr
)
{
dev_err
(
dev
,
"failed to map CTL base
\n
"
);
dev_err
(
dev
,
"failed to map CTL base
\n
"
);
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
err_
alt_ioremap
;
goto
err_
put
;
}
}
ap
->
ioaddr
.
cmd_addr
=
info
->
ide_addr
;
ap
->
ioaddr
.
cmd_addr
=
info
->
ide_addr
;
...
@@ -303,13 +303,8 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
...
@@ -303,13 +303,8 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
irq
?
ata_sff_interrupt
:
NULL
,
irq
?
ata_sff_interrupt
:
NULL
,
irq_flags
,
&
pata_at91_sht
);
irq_flags
,
&
pata_at91_sht
);
err_alt_ioremap:
err_put:
devm_iounmap
(
dev
,
info
->
ide_addr
);
err_ide_ioremap:
clk_put
(
info
->
mck
);
clk_put
(
info
->
mck
);
kfree
(
info
);
return
ret
;
return
ret
;
}
}
...
@@ -317,7 +312,6 @@ static int __devexit pata_at91_remove(struct platform_device *pdev)
...
@@ -317,7 +312,6 @@ static int __devexit pata_at91_remove(struct platform_device *pdev)
{
{
struct
ata_host
*
host
=
dev_get_drvdata
(
&
pdev
->
dev
);
struct
ata_host
*
host
=
dev_get_drvdata
(
&
pdev
->
dev
);
struct
at91_ide_info
*
info
;
struct
at91_ide_info
*
info
;
struct
device
*
dev
=
&
pdev
->
dev
;
if
(
!
host
)
if
(
!
host
)
return
0
;
return
0
;
...
@@ -328,11 +322,8 @@ static int __devexit pata_at91_remove(struct platform_device *pdev)
...
@@ -328,11 +322,8 @@ static int __devexit pata_at91_remove(struct platform_device *pdev)
if
(
!
info
)
if
(
!
info
)
return
0
;
return
0
;
devm_iounmap
(
dev
,
info
->
ide_addr
);
devm_iounmap
(
dev
,
info
->
alt_addr
);
clk_put
(
info
->
mck
);
clk_put
(
info
->
mck
);
kfree
(
info
);
return
0
;
return
0
;
}
}
...
...
drivers/ata/pata_atiixp.c
浏览文件 @
824df399
/*
/*
* pata_atiixp.c - ATI PATA for new ATA layer
* pata_atiixp.c - ATI PATA for new ATA layer
* (C) 2005 Red Hat Inc
* (C) 2005 Red Hat Inc
* (C) 2009 Bartlomiej Zolnierkiewicz
*
*
* Based on
* Based on
*
*
...
@@ -61,20 +62,19 @@ static void atiixp_set_pio_timing(struct ata_port *ap, struct ata_device *adev,
...
@@ -61,20 +62,19 @@ static void atiixp_set_pio_timing(struct ata_port *ap, struct ata_device *adev,
struct
pci_dev
*
pdev
=
to_pci_dev
(
ap
->
host
->
dev
);
struct
pci_dev
*
pdev
=
to_pci_dev
(
ap
->
host
->
dev
);
int
dn
=
2
*
ap
->
port_no
+
adev
->
devno
;
int
dn
=
2
*
ap
->
port_no
+
adev
->
devno
;
/* Check this is correct - the order is odd in both drivers */
int
timing_shift
=
(
16
*
ap
->
port_no
)
+
8
*
(
adev
->
devno
^
1
);
int
timing_shift
=
(
16
*
ap
->
port_no
)
+
8
*
(
adev
->
devno
^
1
);
u16
pio_mode_data
,
pio_timing_data
;
u32
pio_timing_data
;
u16
pio_mode_data
;
pci_read_config_word
(
pdev
,
ATIIXP_IDE_PIO_MODE
,
&
pio_mode_data
);
pci_read_config_word
(
pdev
,
ATIIXP_IDE_PIO_MODE
,
&
pio_mode_data
);
pio_mode_data
&=
~
(
0x7
<<
(
4
*
dn
));
pio_mode_data
&=
~
(
0x7
<<
(
4
*
dn
));
pio_mode_data
|=
pio
<<
(
4
*
dn
);
pio_mode_data
|=
pio
<<
(
4
*
dn
);
pci_write_config_word
(
pdev
,
ATIIXP_IDE_PIO_MODE
,
pio_mode_data
);
pci_write_config_word
(
pdev
,
ATIIXP_IDE_PIO_MODE
,
pio_mode_data
);
pci_read_config_word
(
pdev
,
ATIIXP_IDE_PIO_TIMING
,
&
pio_timing_data
);
pci_read_config_
d
word
(
pdev
,
ATIIXP_IDE_PIO_TIMING
,
&
pio_timing_data
);
pio_timing_data
&=
~
(
0xFF
<<
timing_shift
);
pio_timing_data
&=
~
(
0xFF
<<
timing_shift
);
pio_timing_data
|=
(
pio_timings
[
pio
]
<<
timing_shift
);
pio_timing_data
|=
(
pio_timings
[
pio
]
<<
timing_shift
);
pci_write_config_word
(
pdev
,
ATIIXP_IDE_PIO_TIMING
,
pio_timing_data
);
pci_write_config_
d
word
(
pdev
,
ATIIXP_IDE_PIO_TIMING
,
pio_timing_data
);
}
}
/**
/**
...
@@ -119,16 +119,17 @@ static void atiixp_set_dmamode(struct ata_port *ap, struct ata_device *adev)
...
@@ -119,16 +119,17 @@ static void atiixp_set_dmamode(struct ata_port *ap, struct ata_device *adev)
udma_mode_data
|=
dma
<<
(
4
*
dn
);
udma_mode_data
|=
dma
<<
(
4
*
dn
);
pci_write_config_word
(
pdev
,
ATIIXP_IDE_UDMA_MODE
,
udma_mode_data
);
pci_write_config_word
(
pdev
,
ATIIXP_IDE_UDMA_MODE
,
udma_mode_data
);
}
else
{
}
else
{
u16
mwdma_timing_data
;
/* Check this is correct - the order is odd in both drivers */
int
timing_shift
=
(
16
*
ap
->
port_no
)
+
8
*
(
adev
->
devno
^
1
);
int
timing_shift
=
(
16
*
ap
->
port_no
)
+
8
*
(
adev
->
devno
^
1
);
u32
mwdma_timing_data
;
dma
-=
XFER_MW_DMA_0
;
dma
-=
XFER_MW_DMA_0
;
pci_read_config_word
(
pdev
,
ATIIXP_IDE_MWDMA_TIMING
,
&
mwdma_timing_data
);
pci_read_config_dword
(
pdev
,
ATIIXP_IDE_MWDMA_TIMING
,
&
mwdma_timing_data
);
mwdma_timing_data
&=
~
(
0xFF
<<
timing_shift
);
mwdma_timing_data
&=
~
(
0xFF
<<
timing_shift
);
mwdma_timing_data
|=
(
mwdma_timings
[
dma
]
<<
timing_shift
);
mwdma_timing_data
|=
(
mwdma_timings
[
dma
]
<<
timing_shift
);
pci_write_config_word
(
pdev
,
ATIIXP_IDE_MWDMA_TIMING
,
mwdma_timing_data
);
pci_write_config_dword
(
pdev
,
ATIIXP_IDE_MWDMA_TIMING
,
mwdma_timing_data
);
}
}
/*
/*
* We must now look at the PIO mode situation. We may need to
* We must now look at the PIO mode situation. We may need to
...
...
drivers/ata/sata_nv.c
浏览文件 @
824df399
...
@@ -602,6 +602,7 @@ MODULE_VERSION(DRV_VERSION);
...
@@ -602,6 +602,7 @@ MODULE_VERSION(DRV_VERSION);
static
int
adma_enabled
;
static
int
adma_enabled
;
static
int
swncq_enabled
=
1
;
static
int
swncq_enabled
=
1
;
static
int
msi_enabled
;
static
void
nv_adma_register_mode
(
struct
ata_port
*
ap
)
static
void
nv_adma_register_mode
(
struct
ata_port
*
ap
)
{
{
...
@@ -2459,6 +2460,11 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
...
@@ -2459,6 +2460,11 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
else
if
(
type
==
SWNCQ
)
}
else
if
(
type
==
SWNCQ
)
nv_swncq_host_init
(
host
);
nv_swncq_host_init
(
host
);
if
(
msi_enabled
)
{
dev_printk
(
KERN_NOTICE
,
&
pdev
->
dev
,
"Using MSI
\n
"
);
pci_enable_msi
(
pdev
);
}
pci_set_master
(
pdev
);
pci_set_master
(
pdev
);
return
ata_host_activate
(
host
,
pdev
->
irq
,
ipriv
->
irq_handler
,
return
ata_host_activate
(
host
,
pdev
->
irq
,
ipriv
->
irq_handler
,
IRQF_SHARED
,
ipriv
->
sht
);
IRQF_SHARED
,
ipriv
->
sht
);
...
@@ -2558,4 +2564,6 @@ module_param_named(adma, adma_enabled, bool, 0444);
...
@@ -2558,4 +2564,6 @@ module_param_named(adma, adma_enabled, bool, 0444);
MODULE_PARM_DESC
(
adma
,
"Enable use of ADMA (Default: false)"
);
MODULE_PARM_DESC
(
adma
,
"Enable use of ADMA (Default: false)"
);
module_param_named
(
swncq
,
swncq_enabled
,
bool
,
0444
);
module_param_named
(
swncq
,
swncq_enabled
,
bool
,
0444
);
MODULE_PARM_DESC
(
swncq
,
"Enable use of SWNCQ (Default: true)"
);
MODULE_PARM_DESC
(
swncq
,
"Enable use of SWNCQ (Default: true)"
);
module_param_named
(
msi
,
msi_enabled
,
bool
,
0444
);
MODULE_PARM_DESC
(
msi
,
"Enable use of MSI (Default: false)"
);
drivers/base/platform.c
浏览文件 @
824df399
...
@@ -483,9 +483,6 @@ int platform_driver_register(struct platform_driver *drv)
...
@@ -483,9 +483,6 @@ int platform_driver_register(struct platform_driver *drv)
drv
->
driver
.
remove
=
platform_drv_remove
;
drv
->
driver
.
remove
=
platform_drv_remove
;
if
(
drv
->
shutdown
)
if
(
drv
->
shutdown
)
drv
->
driver
.
shutdown
=
platform_drv_shutdown
;
drv
->
driver
.
shutdown
=
platform_drv_shutdown
;
if
(
drv
->
suspend
||
drv
->
resume
)
pr_warning
(
"Platform driver '%s' needs updating - please use "
"dev_pm_ops
\n
"
,
drv
->
driver
.
name
);
return
driver_register
(
&
drv
->
driver
);
return
driver_register
(
&
drv
->
driver
);
}
}
...
...
drivers/char/pty.c
浏览文件 @
824df399
...
@@ -144,6 +144,8 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf,
...
@@ -144,6 +144,8 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf,
static
int
pty_write_room
(
struct
tty_struct
*
tty
)
static
int
pty_write_room
(
struct
tty_struct
*
tty
)
{
{
if
(
tty
->
stopped
)
return
0
;
return
pty_space
(
tty
->
link
);
return
pty_space
(
tty
->
link
);
}
}
...
...
drivers/mtd/maps/sbc8240.c
已删除
100644 → 0
浏览文件 @
8b612078
drivers/pci/hotplug/sgi_hotplug.c
浏览文件 @
824df399
...
@@ -90,11 +90,10 @@ static struct hotplug_slot_ops sn_hotplug_slot_ops = {
...
@@ -90,11 +90,10 @@ static struct hotplug_slot_ops sn_hotplug_slot_ops = {
static
DEFINE_MUTEX
(
sn_hotplug_mutex
);
static
DEFINE_MUTEX
(
sn_hotplug_mutex
);
static
ssize_t
path_show
(
struct
hotplug_slot
*
bss_hotplug_slot
,
static
ssize_t
path_show
(
struct
pci_slot
*
pci_slot
,
char
*
buf
)
char
*
buf
)
{
{
int
retval
=
-
ENOENT
;
int
retval
=
-
ENOENT
;
struct
slot
*
slot
=
bss_hotplug_slot
->
private
;
struct
slot
*
slot
=
pci_slot
->
hotplug
->
private
;
if
(
!
slot
)
if
(
!
slot
)
return
retval
;
return
retval
;
...
@@ -103,7 +102,7 @@ static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot,
...
@@ -103,7 +102,7 @@ static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot,
return
retval
;
return
retval
;
}
}
static
struct
hotplug
_slot_attribute
sn_slot_path_attr
=
__ATTR_RO
(
path
);
static
struct
pci
_slot_attribute
sn_slot_path_attr
=
__ATTR_RO
(
path
);
static
int
sn_pci_slot_valid
(
struct
pci_bus
*
pci_bus
,
int
device
)
static
int
sn_pci_slot_valid
(
struct
pci_bus
*
pci_bus
,
int
device
)
{
{
...
...
drivers/serial/Kconfig
浏览文件 @
824df399
...
@@ -527,7 +527,7 @@ config SERIAL_S3C24A0
...
@@ -527,7 +527,7 @@ config SERIAL_S3C24A0
config SERIAL_S3C6400
config SERIAL_S3C6400
tristate "Samsung S3C6400/S3C6410 Serial port support"
tristate "Samsung S3C6400/S3C6410 Serial port support"
depends on SERIAL_SAMSUNG && (CPU_S3C600 || CPU_S3C6410)
depends on SERIAL_SAMSUNG && (CPU_S3C6
4
00 || CPU_S3C6410)
default y
default y
help
help
Serial port support for the Samsung S3C6400 and S3C6410
Serial port support for the Samsung S3C6400 and S3C6410
...
...
fs/nfs/direct.c
浏览文件 @
824df399
...
@@ -255,7 +255,7 @@ static void nfs_direct_read_release(void *calldata)
...
@@ -255,7 +255,7 @@ static void nfs_direct_read_release(void *calldata)
if
(
put_dreq
(
dreq
))
if
(
put_dreq
(
dreq
))
nfs_direct_complete
(
dreq
);
nfs_direct_complete
(
dreq
);
nfs_readdata_
release
(
call
data
);
nfs_readdata_
free
(
data
);
}
}
static
const
struct
rpc_call_ops
nfs_read_direct_ops
=
{
static
const
struct
rpc_call_ops
nfs_read_direct_ops
=
{
...
@@ -314,14 +314,14 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
...
@@ -314,14 +314,14 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
data
->
npages
,
1
,
0
,
data
->
pagevec
,
NULL
);
data
->
npages
,
1
,
0
,
data
->
pagevec
,
NULL
);
up_read
(
&
current
->
mm
->
mmap_sem
);
up_read
(
&
current
->
mm
->
mmap_sem
);
if
(
result
<
0
)
{
if
(
result
<
0
)
{
nfs_readdata_
releas
e
(
data
);
nfs_readdata_
fre
e
(
data
);
break
;
break
;
}
}
if
((
unsigned
)
result
<
data
->
npages
)
{
if
((
unsigned
)
result
<
data
->
npages
)
{
bytes
=
result
*
PAGE_SIZE
;
bytes
=
result
*
PAGE_SIZE
;
if
(
bytes
<=
pgbase
)
{
if
(
bytes
<=
pgbase
)
{
nfs_direct_release_pages
(
data
->
pagevec
,
result
);
nfs_direct_release_pages
(
data
->
pagevec
,
result
);
nfs_readdata_
releas
e
(
data
);
nfs_readdata_
fre
e
(
data
);
break
;
break
;
}
}
bytes
-=
pgbase
;
bytes
-=
pgbase
;
...
@@ -334,7 +334,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
...
@@ -334,7 +334,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
data
->
inode
=
inode
;
data
->
inode
=
inode
;
data
->
cred
=
msg
.
rpc_cred
;
data
->
cred
=
msg
.
rpc_cred
;
data
->
args
.
fh
=
NFS_FH
(
inode
);
data
->
args
.
fh
=
NFS_FH
(
inode
);
data
->
args
.
context
=
get_nfs_open_context
(
ctx
)
;
data
->
args
.
context
=
ctx
;
data
->
args
.
offset
=
pos
;
data
->
args
.
offset
=
pos
;
data
->
args
.
pgbase
=
pgbase
;
data
->
args
.
pgbase
=
pgbase
;
data
->
args
.
pages
=
data
->
pagevec
;
data
->
args
.
pages
=
data
->
pagevec
;
...
@@ -441,7 +441,7 @@ static void nfs_direct_free_writedata(struct nfs_direct_req *dreq)
...
@@ -441,7 +441,7 @@ static void nfs_direct_free_writedata(struct nfs_direct_req *dreq)
struct
nfs_write_data
*
data
=
list_entry
(
dreq
->
rewrite_list
.
next
,
struct
nfs_write_data
,
pages
);
struct
nfs_write_data
*
data
=
list_entry
(
dreq
->
rewrite_list
.
next
,
struct
nfs_write_data
,
pages
);
list_del
(
&
data
->
pages
);
list_del
(
&
data
->
pages
);
nfs_direct_release_pages
(
data
->
pagevec
,
data
->
npages
);
nfs_direct_release_pages
(
data
->
pagevec
,
data
->
npages
);
nfs_writedata_
releas
e
(
data
);
nfs_writedata_
fre
e
(
data
);
}
}
}
}
...
@@ -534,7 +534,7 @@ static void nfs_direct_commit_release(void *calldata)
...
@@ -534,7 +534,7 @@ static void nfs_direct_commit_release(void *calldata)
dprintk
(
"NFS: %5u commit returned %d
\n
"
,
data
->
task
.
tk_pid
,
status
);
dprintk
(
"NFS: %5u commit returned %d
\n
"
,
data
->
task
.
tk_pid
,
status
);
nfs_direct_write_complete
(
dreq
,
data
->
inode
);
nfs_direct_write_complete
(
dreq
,
data
->
inode
);
nfs_commit
data_release
(
call
data
);
nfs_commit
_free
(
data
);
}
}
static
const
struct
rpc_call_ops
nfs_commit_direct_ops
=
{
static
const
struct
rpc_call_ops
nfs_commit_direct_ops
=
{
...
@@ -570,7 +570,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
...
@@ -570,7 +570,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
data
->
args
.
fh
=
NFS_FH
(
data
->
inode
);
data
->
args
.
fh
=
NFS_FH
(
data
->
inode
);
data
->
args
.
offset
=
0
;
data
->
args
.
offset
=
0
;
data
->
args
.
count
=
0
;
data
->
args
.
count
=
0
;
data
->
args
.
context
=
get_nfs_open_context
(
dreq
->
ctx
)
;
data
->
args
.
context
=
dreq
->
ctx
;
data
->
res
.
count
=
0
;
data
->
res
.
count
=
0
;
data
->
res
.
fattr
=
&
data
->
fattr
;
data
->
res
.
fattr
=
&
data
->
fattr
;
data
->
res
.
verf
=
&
data
->
verf
;
data
->
res
.
verf
=
&
data
->
verf
;
...
@@ -734,14 +734,14 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
...
@@ -734,14 +734,14 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
data
->
npages
,
0
,
0
,
data
->
pagevec
,
NULL
);
data
->
npages
,
0
,
0
,
data
->
pagevec
,
NULL
);
up_read
(
&
current
->
mm
->
mmap_sem
);
up_read
(
&
current
->
mm
->
mmap_sem
);
if
(
result
<
0
)
{
if
(
result
<
0
)
{
nfs_writedata_
releas
e
(
data
);
nfs_writedata_
fre
e
(
data
);
break
;
break
;
}
}
if
((
unsigned
)
result
<
data
->
npages
)
{
if
((
unsigned
)
result
<
data
->
npages
)
{
bytes
=
result
*
PAGE_SIZE
;
bytes
=
result
*
PAGE_SIZE
;
if
(
bytes
<=
pgbase
)
{
if
(
bytes
<=
pgbase
)
{
nfs_direct_release_pages
(
data
->
pagevec
,
result
);
nfs_direct_release_pages
(
data
->
pagevec
,
result
);
nfs_writedata_
releas
e
(
data
);
nfs_writedata_
fre
e
(
data
);
break
;
break
;
}
}
bytes
-=
pgbase
;
bytes
-=
pgbase
;
...
@@ -756,7 +756,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
...
@@ -756,7 +756,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
data
->
inode
=
inode
;
data
->
inode
=
inode
;
data
->
cred
=
msg
.
rpc_cred
;
data
->
cred
=
msg
.
rpc_cred
;
data
->
args
.
fh
=
NFS_FH
(
inode
);
data
->
args
.
fh
=
NFS_FH
(
inode
);
data
->
args
.
context
=
get_nfs_open_context
(
ctx
)
;
data
->
args
.
context
=
ctx
;
data
->
args
.
offset
=
pos
;
data
->
args
.
offset
=
pos
;
data
->
args
.
pgbase
=
pgbase
;
data
->
args
.
pgbase
=
pgbase
;
data
->
args
.
pages
=
data
->
pagevec
;
data
->
args
.
pages
=
data
->
pagevec
;
...
...
fs/nfs/read.c
浏览文件 @
824df399
...
@@ -60,17 +60,15 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
...
@@ -60,17 +60,15 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
return
p
;
return
p
;
}
}
static
void
nfs_readdata_free
(
struct
nfs_read_data
*
p
)
void
nfs_readdata_free
(
struct
nfs_read_data
*
p
)
{
{
if
(
p
&&
(
p
->
pagevec
!=
&
p
->
page_array
[
0
]))
if
(
p
&&
(
p
->
pagevec
!=
&
p
->
page_array
[
0
]))
kfree
(
p
->
pagevec
);
kfree
(
p
->
pagevec
);
mempool_free
(
p
,
nfs_rdata_mempool
);
mempool_free
(
p
,
nfs_rdata_mempool
);
}
}
void
nfs_readdata_release
(
void
*
data
)
static
void
nfs_readdata_release
(
struct
nfs_read_data
*
r
data
)
{
{
struct
nfs_read_data
*
rdata
=
data
;
put_nfs_open_context
(
rdata
->
args
.
context
);
put_nfs_open_context
(
rdata
->
args
.
context
);
nfs_readdata_free
(
rdata
);
nfs_readdata_free
(
rdata
);
}
}
...
...
fs/nfs/write.c
浏览文件 @
824df399
...
@@ -87,17 +87,15 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
...
@@ -87,17 +87,15 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
return
p
;
return
p
;
}
}
static
void
nfs_writedata_free
(
struct
nfs_write_data
*
p
)
void
nfs_writedata_free
(
struct
nfs_write_data
*
p
)
{
{
if
(
p
&&
(
p
->
pagevec
!=
&
p
->
page_array
[
0
]))
if
(
p
&&
(
p
->
pagevec
!=
&
p
->
page_array
[
0
]))
kfree
(
p
->
pagevec
);
kfree
(
p
->
pagevec
);
mempool_free
(
p
,
nfs_wdata_mempool
);
mempool_free
(
p
,
nfs_wdata_mempool
);
}
}
void
nfs_writedata_release
(
void
*
data
)
static
void
nfs_writedata_release
(
struct
nfs_write_data
*
w
data
)
{
{
struct
nfs_write_data
*
wdata
=
data
;
put_nfs_open_context
(
wdata
->
args
.
context
);
put_nfs_open_context
(
wdata
->
args
.
context
);
nfs_writedata_free
(
wdata
);
nfs_writedata_free
(
wdata
);
}
}
...
...
fs/proc/base.c
浏览文件 @
824df399
...
@@ -234,23 +234,20 @@ static int check_mem_permission(struct task_struct *task)
...
@@ -234,23 +234,20 @@ static int check_mem_permission(struct task_struct *task)
struct
mm_struct
*
mm_for_maps
(
struct
task_struct
*
task
)
struct
mm_struct
*
mm_for_maps
(
struct
task_struct
*
task
)
{
{
struct
mm_struct
*
mm
=
get_task_mm
(
task
);
struct
mm_struct
*
mm
;
if
(
!
mm
)
if
(
mutex_lock_killable
(
&
task
->
cred_guard_mutex
))
return
NULL
;
return
NULL
;
down_read
(
&
mm
->
mmap_sem
);
task_lock
(
task
);
mm
=
get_task_mm
(
task
);
if
(
task
->
mm
!=
mm
)
if
(
mm
&&
mm
!=
current
->
mm
&&
goto
out
;
!
ptrace_may_access
(
task
,
PTRACE_MODE_READ
))
{
if
(
task
->
mm
!=
current
->
mm
&&
mmput
(
mm
);
__ptrace_may_access
(
task
,
PTRACE_MODE_READ
)
<
0
)
mm
=
NULL
;
goto
out
;
}
task_unlock
(
task
);
mutex_unlock
(
&
task
->
cred_guard_mutex
);
return
mm
;
return
mm
;
out:
task_unlock
(
task
);
up_read
(
&
mm
->
mmap_sem
);
mmput
(
mm
);
return
NULL
;
}
}
static
int
proc_pid_cmdline
(
struct
task_struct
*
task
,
char
*
buffer
)
static
int
proc_pid_cmdline
(
struct
task_struct
*
task
,
char
*
buffer
)
...
...
fs/proc/task_mmu.c
浏览文件 @
824df399
...
@@ -119,6 +119,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
...
@@ -119,6 +119,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
mm
=
mm_for_maps
(
priv
->
task
);
mm
=
mm_for_maps
(
priv
->
task
);
if
(
!
mm
)
if
(
!
mm
)
return
NULL
;
return
NULL
;
down_read
(
&
mm
->
mmap_sem
);
tail_vma
=
get_gate_vma
(
priv
->
task
);
tail_vma
=
get_gate_vma
(
priv
->
task
);
priv
->
tail_vma
=
tail_vma
;
priv
->
tail_vma
=
tail_vma
;
...
...
fs/proc/task_nommu.c
浏览文件 @
824df399
...
@@ -189,6 +189,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
...
@@ -189,6 +189,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
priv
->
task
=
NULL
;
priv
->
task
=
NULL
;
return
NULL
;
return
NULL
;
}
}
down_read
(
&
mm
->
mmap_sem
);
/* start from the Nth VMA */
/* start from the Nth VMA */
for
(
p
=
rb_first
(
&
mm
->
mm_rb
);
p
;
p
=
rb_next
(
p
))
for
(
p
=
rb_first
(
&
mm
->
mm_rb
);
p
;
p
=
rb_next
(
p
))
...
...
fs/xfs/linux-2.6/xfs_buf.c
浏览文件 @
824df399
...
@@ -770,7 +770,7 @@ xfs_buf_associate_memory(
...
@@ -770,7 +770,7 @@ xfs_buf_associate_memory(
bp
->
b_pages
=
NULL
;
bp
->
b_pages
=
NULL
;
bp
->
b_addr
=
mem
;
bp
->
b_addr
=
mem
;
rval
=
_xfs_buf_get_pages
(
bp
,
page_count
,
0
);
rval
=
_xfs_buf_get_pages
(
bp
,
page_count
,
XBF_DONT_BLOCK
);
if
(
rval
)
if
(
rval
)
return
rval
;
return
rval
;
...
...
fs/xfs/xfs_attr.c
浏览文件 @
824df399
...
@@ -2010,7 +2010,9 @@ xfs_attr_rmtval_get(xfs_da_args_t *args)
...
@@ -2010,7 +2010,9 @@ xfs_attr_rmtval_get(xfs_da_args_t *args)
dblkno
=
XFS_FSB_TO_DADDR
(
mp
,
map
[
i
].
br_startblock
);
dblkno
=
XFS_FSB_TO_DADDR
(
mp
,
map
[
i
].
br_startblock
);
blkcnt
=
XFS_FSB_TO_BB
(
mp
,
map
[
i
].
br_blockcount
);
blkcnt
=
XFS_FSB_TO_BB
(
mp
,
map
[
i
].
br_blockcount
);
error
=
xfs_read_buf
(
mp
,
mp
->
m_ddev_targp
,
dblkno
,
error
=
xfs_read_buf
(
mp
,
mp
->
m_ddev_targp
,
dblkno
,
blkcnt
,
XFS_BUF_LOCK
,
&
bp
);
blkcnt
,
XFS_BUF_LOCK
|
XBF_DONT_BLOCK
,
&
bp
);
if
(
error
)
if
(
error
)
return
(
error
);
return
(
error
);
...
@@ -2141,8 +2143,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
...
@@ -2141,8 +2143,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
dblkno
=
XFS_FSB_TO_DADDR
(
mp
,
map
.
br_startblock
),
dblkno
=
XFS_FSB_TO_DADDR
(
mp
,
map
.
br_startblock
),
blkcnt
=
XFS_FSB_TO_BB
(
mp
,
map
.
br_blockcount
);
blkcnt
=
XFS_FSB_TO_BB
(
mp
,
map
.
br_blockcount
);
bp
=
xfs_buf_get_flags
(
mp
->
m_ddev_targp
,
dblkno
,
bp
=
xfs_buf_get_flags
(
mp
->
m_ddev_targp
,
dblkno
,
blkcnt
,
blkcnt
,
XFS_BUF_
LOCK
);
XFS_BUF_LOCK
|
XBF_DONT_B
LOCK
);
ASSERT
(
bp
);
ASSERT
(
bp
);
ASSERT
(
!
XFS_BUF_GETERROR
(
bp
));
ASSERT
(
!
XFS_BUF_GETERROR
(
bp
));
...
...
fs/xfs/xfs_bmap.c
浏览文件 @
824df399
...
@@ -6009,7 +6009,7 @@ xfs_getbmap(
...
@@ -6009,7 +6009,7 @@ xfs_getbmap(
*/
*/
error
=
ENOMEM
;
error
=
ENOMEM
;
subnex
=
16
;
subnex
=
16
;
map
=
kmem_alloc
(
subnex
*
sizeof
(
*
map
),
KM_MAYFAIL
);
map
=
kmem_alloc
(
subnex
*
sizeof
(
*
map
),
KM_MAYFAIL
|
KM_NOFS
);
if
(
!
map
)
if
(
!
map
)
goto
out_unlock_ilock
;
goto
out_unlock_ilock
;
...
...
fs/xfs/xfs_btree.c
浏览文件 @
824df399
...
@@ -120,8 +120,8 @@ xfs_btree_check_sblock(
...
@@ -120,8 +120,8 @@ xfs_btree_check_sblock(
XFS_RANDOM_BTREE_CHECK_SBLOCK
)))
{
XFS_RANDOM_BTREE_CHECK_SBLOCK
)))
{
if
(
bp
)
if
(
bp
)
xfs_buftrace
(
"SBTREE ERROR"
,
bp
);
xfs_buftrace
(
"SBTREE ERROR"
,
bp
);
XFS_
ERROR_REPORT
(
"xfs_btree_check_sblock"
,
XFS_ERRLEVEL_LOW
,
XFS_
CORRUPTION_ERROR
(
"xfs_btree_check_sblock"
,
cur
->
bc_mp
);
XFS_ERRLEVEL_LOW
,
cur
->
bc_mp
,
block
);
return
XFS_ERROR
(
EFSCORRUPTED
);
return
XFS_ERROR
(
EFSCORRUPTED
);
}
}
return
0
;
return
0
;
...
...
fs/xfs/xfs_da_btree.c
浏览文件 @
824df399
...
@@ -2201,7 +2201,7 @@ kmem_zone_t *xfs_dabuf_zone; /* dabuf zone */
...
@@ -2201,7 +2201,7 @@ kmem_zone_t *xfs_dabuf_zone; /* dabuf zone */
xfs_da_state_t
*
xfs_da_state_t
*
xfs_da_state_alloc
(
void
)
xfs_da_state_alloc
(
void
)
{
{
return
kmem_zone_zalloc
(
xfs_da_state_zone
,
KM_
SLEEP
);
return
kmem_zone_zalloc
(
xfs_da_state_zone
,
KM_
NOFS
);
}
}
/*
/*
...
@@ -2261,9 +2261,9 @@ xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra)
...
@@ -2261,9 +2261,9 @@ xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra)
int
off
;
int
off
;
if
(
nbuf
==
1
)
if
(
nbuf
==
1
)
dabuf
=
kmem_zone_alloc
(
xfs_dabuf_zone
,
KM_
SLEEP
);
dabuf
=
kmem_zone_alloc
(
xfs_dabuf_zone
,
KM_
NOFS
);
else
else
dabuf
=
kmem_alloc
(
XFS_DA_BUF_SIZE
(
nbuf
),
KM_
SLEEP
);
dabuf
=
kmem_alloc
(
XFS_DA_BUF_SIZE
(
nbuf
),
KM_
NOFS
);
dabuf
->
dirty
=
0
;
dabuf
->
dirty
=
0
;
#ifdef XFS_DABUF_DEBUG
#ifdef XFS_DABUF_DEBUG
dabuf
->
ra
=
ra
;
dabuf
->
ra
=
ra
;
...
...
fs/xfs/xfs_dir2.c
浏览文件 @
824df399
...
@@ -256,7 +256,7 @@ xfs_dir_cilookup_result(
...
@@ -256,7 +256,7 @@ xfs_dir_cilookup_result(
!
(
args
->
op_flags
&
XFS_DA_OP_CILOOKUP
))
!
(
args
->
op_flags
&
XFS_DA_OP_CILOOKUP
))
return
EEXIST
;
return
EEXIST
;
args
->
value
=
kmem_alloc
(
len
,
KM_MAYFAIL
);
args
->
value
=
kmem_alloc
(
len
,
KM_
NOFS
|
KM_
MAYFAIL
);
if
(
!
args
->
value
)
if
(
!
args
->
value
)
return
ENOMEM
;
return
ENOMEM
;
...
...
fs/xfs/xfs_fsops.c
浏览文件 @
824df399
...
@@ -167,17 +167,25 @@ xfs_growfs_data_private(
...
@@ -167,17 +167,25 @@ xfs_growfs_data_private(
new
=
nb
-
mp
->
m_sb
.
sb_dblocks
;
new
=
nb
-
mp
->
m_sb
.
sb_dblocks
;
oagcount
=
mp
->
m_sb
.
sb_agcount
;
oagcount
=
mp
->
m_sb
.
sb_agcount
;
if
(
nagcount
>
oagcount
)
{
if
(
nagcount
>
oagcount
)
{
void
*
new_perag
,
*
old_perag
;
xfs_filestream_flush
(
mp
);
xfs_filestream_flush
(
mp
);
new_perag
=
kmem_zalloc
(
sizeof
(
xfs_perag_t
)
*
nagcount
,
KM_MAYFAIL
);
if
(
!
new_perag
)
return
XFS_ERROR
(
ENOMEM
);
down_write
(
&
mp
->
m_peraglock
);
down_write
(
&
mp
->
m_peraglock
);
mp
->
m_perag
=
kmem_realloc
(
mp
->
m_perag
,
memcpy
(
new_perag
,
mp
->
m_perag
,
sizeof
(
xfs_perag_t
)
*
oagcount
);
sizeof
(
xfs_perag_t
)
*
nagcount
,
old_perag
=
mp
->
m_perag
;
sizeof
(
xfs_perag_t
)
*
oagcount
,
mp
->
m_perag
=
new_perag
;
KM_SLEEP
);
memset
(
&
mp
->
m_perag
[
oagcount
],
0
,
(
nagcount
-
oagcount
)
*
sizeof
(
xfs_perag_t
));
mp
->
m_flags
|=
XFS_MOUNT_32BITINODES
;
mp
->
m_flags
|=
XFS_MOUNT_32BITINODES
;
nagimax
=
xfs_initialize_perag
(
mp
,
nagcount
);
nagimax
=
xfs_initialize_perag
(
mp
,
nagcount
);
up_write
(
&
mp
->
m_peraglock
);
up_write
(
&
mp
->
m_peraglock
);
kmem_free
(
old_perag
);
}
}
tp
=
xfs_trans_alloc
(
mp
,
XFS_TRANS_GROWFS
);
tp
=
xfs_trans_alloc
(
mp
,
XFS_TRANS_GROWFS
);
tp
->
t_flags
|=
XFS_TRANS_RESERVE
;
tp
->
t_flags
|=
XFS_TRANS_RESERVE
;
...
...
fs/xfs/xfs_inode.c
浏览文件 @
824df399
...
@@ -343,6 +343,16 @@ xfs_iformat(
...
@@ -343,6 +343,16 @@ xfs_iformat(
return
XFS_ERROR
(
EFSCORRUPTED
);
return
XFS_ERROR
(
EFSCORRUPTED
);
}
}
if
(
unlikely
((
ip
->
i_d
.
di_flags
&
XFS_DIFLAG_REALTIME
)
&&
!
ip
->
i_mount
->
m_rtdev_targp
))
{
xfs_fs_repair_cmn_err
(
CE_WARN
,
ip
->
i_mount
,
"corrupt dinode %Lu, has realtime flag set."
,
ip
->
i_ino
);
XFS_CORRUPTION_ERROR
(
"xfs_iformat(realtime)"
,
XFS_ERRLEVEL_LOW
,
ip
->
i_mount
,
dip
);
return
XFS_ERROR
(
EFSCORRUPTED
);
}
switch
(
ip
->
i_d
.
di_mode
&
S_IFMT
)
{
switch
(
ip
->
i_d
.
di_mode
&
S_IFMT
)
{
case
S_IFIFO
:
case
S_IFIFO
:
case
S_IFCHR
:
case
S_IFCHR
:
...
...
fs/xfs/xfs_log.c
浏览文件 @
824df399
...
@@ -3180,7 +3180,7 @@ xlog_state_sync(xlog_t *log,
...
@@ -3180,7 +3180,7 @@ xlog_state_sync(xlog_t *log,
STATIC
void
STATIC
void
xlog_state_want_sync
(
xlog_t
*
log
,
xlog_in_core_t
*
iclog
)
xlog_state_want_sync
(
xlog_t
*
log
,
xlog_in_core_t
*
iclog
)
{
{
ASSERT
(
spin_is_locked
(
&
log
->
l_icloglock
)
);
assert_spin_locked
(
&
log
->
l_icloglock
);
if
(
iclog
->
ic_state
==
XLOG_STATE_ACTIVE
)
{
if
(
iclog
->
ic_state
==
XLOG_STATE_ACTIVE
)
{
xlog_state_switch_iclogs
(
log
,
iclog
,
0
);
xlog_state_switch_iclogs
(
log
,
iclog
,
0
);
...
...
fs/xfs/xfs_vnodeops.c
浏览文件 @
824df399
...
@@ -538,7 +538,9 @@ xfs_readlink_bmap(
...
@@ -538,7 +538,9 @@ xfs_readlink_bmap(
d
=
XFS_FSB_TO_DADDR
(
mp
,
mval
[
n
].
br_startblock
);
d
=
XFS_FSB_TO_DADDR
(
mp
,
mval
[
n
].
br_startblock
);
byte_cnt
=
XFS_FSB_TO_B
(
mp
,
mval
[
n
].
br_blockcount
);
byte_cnt
=
XFS_FSB_TO_B
(
mp
,
mval
[
n
].
br_blockcount
);
bp
=
xfs_buf_read
(
mp
->
m_ddev_targp
,
d
,
BTOBB
(
byte_cnt
),
0
);
bp
=
xfs_buf_read_flags
(
mp
->
m_ddev_targp
,
d
,
BTOBB
(
byte_cnt
),
XBF_LOCK
|
XBF_MAPPED
|
XBF_DONT_BLOCK
);
error
=
XFS_BUF_GETERROR
(
bp
);
error
=
XFS_BUF_GETERROR
(
bp
);
if
(
error
)
{
if
(
error
)
{
xfs_ioerror_alert
(
"xfs_readlink"
,
xfs_ioerror_alert
(
"xfs_readlink"
,
...
...
include/linux/nfs_fs.h
浏览文件 @
824df399
...
@@ -473,7 +473,6 @@ extern int nfs_writepages(struct address_space *, struct writeback_control *);
...
@@ -473,7 +473,6 @@ extern int nfs_writepages(struct address_space *, struct writeback_control *);
extern
int
nfs_flush_incompatible
(
struct
file
*
file
,
struct
page
*
page
);
extern
int
nfs_flush_incompatible
(
struct
file
*
file
,
struct
page
*
page
);
extern
int
nfs_updatepage
(
struct
file
*
,
struct
page
*
,
unsigned
int
,
unsigned
int
);
extern
int
nfs_updatepage
(
struct
file
*
,
struct
page
*
,
unsigned
int
,
unsigned
int
);
extern
int
nfs_writeback_done
(
struct
rpc_task
*
,
struct
nfs_write_data
*
);
extern
int
nfs_writeback_done
(
struct
rpc_task
*
,
struct
nfs_write_data
*
);
extern
void
nfs_writedata_release
(
void
*
);
/*
/*
* Try to write back everything synchronously (but check the
* Try to write back everything synchronously (but check the
...
@@ -488,7 +487,6 @@ extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
...
@@ -488,7 +487,6 @@ extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
extern
int
nfs_commit_inode
(
struct
inode
*
,
int
);
extern
int
nfs_commit_inode
(
struct
inode
*
,
int
);
extern
struct
nfs_write_data
*
nfs_commitdata_alloc
(
void
);
extern
struct
nfs_write_data
*
nfs_commitdata_alloc
(
void
);
extern
void
nfs_commit_free
(
struct
nfs_write_data
*
wdata
);
extern
void
nfs_commit_free
(
struct
nfs_write_data
*
wdata
);
extern
void
nfs_commitdata_release
(
void
*
wdata
);
#else
#else
static
inline
int
static
inline
int
nfs_commit_inode
(
struct
inode
*
inode
,
int
how
)
nfs_commit_inode
(
struct
inode
*
inode
,
int
how
)
...
@@ -507,6 +505,7 @@ nfs_have_writebacks(struct inode *inode)
...
@@ -507,6 +505,7 @@ nfs_have_writebacks(struct inode *inode)
* Allocate nfs_write_data structures
* Allocate nfs_write_data structures
*/
*/
extern
struct
nfs_write_data
*
nfs_writedata_alloc
(
unsigned
int
npages
);
extern
struct
nfs_write_data
*
nfs_writedata_alloc
(
unsigned
int
npages
);
extern
void
nfs_writedata_free
(
struct
nfs_write_data
*
);
/*
/*
* linux/fs/nfs/read.c
* linux/fs/nfs/read.c
...
@@ -515,7 +514,6 @@ extern int nfs_readpage(struct file *, struct page *);
...
@@ -515,7 +514,6 @@ extern int nfs_readpage(struct file *, struct page *);
extern
int
nfs_readpages
(
struct
file
*
,
struct
address_space
*
,
extern
int
nfs_readpages
(
struct
file
*
,
struct
address_space
*
,
struct
list_head
*
,
unsigned
);
struct
list_head
*
,
unsigned
);
extern
int
nfs_readpage_result
(
struct
rpc_task
*
,
struct
nfs_read_data
*
);
extern
int
nfs_readpage_result
(
struct
rpc_task
*
,
struct
nfs_read_data
*
);
extern
void
nfs_readdata_release
(
void
*
data
);
extern
int
nfs_readpage_async
(
struct
nfs_open_context
*
,
struct
inode
*
,
extern
int
nfs_readpage_async
(
struct
nfs_open_context
*
,
struct
inode
*
,
struct
page
*
);
struct
page
*
);
...
@@ -523,6 +521,7 @@ extern int nfs_readpage_async(struct nfs_open_context *, struct inode *,
...
@@ -523,6 +521,7 @@ extern int nfs_readpage_async(struct nfs_open_context *, struct inode *,
* Allocate nfs_read_data structures
* Allocate nfs_read_data structures
*/
*/
extern
struct
nfs_read_data
*
nfs_readdata_alloc
(
unsigned
int
npages
);
extern
struct
nfs_read_data
*
nfs_readdata_alloc
(
unsigned
int
npages
);
extern
void
nfs_readdata_free
(
struct
nfs_read_data
*
);
/*
/*
* linux/fs/nfs3proc.c
* linux/fs/nfs3proc.c
...
...
include/linux/perf_counter.h
浏览文件 @
824df399
...
@@ -121,7 +121,7 @@ enum perf_counter_sample_format {
...
@@ -121,7 +121,7 @@ enum perf_counter_sample_format {
PERF_SAMPLE_CPU
=
1U
<<
7
,
PERF_SAMPLE_CPU
=
1U
<<
7
,
PERF_SAMPLE_PERIOD
=
1U
<<
8
,
PERF_SAMPLE_PERIOD
=
1U
<<
8
,
PERF_SAMPLE_STREAM_ID
=
1U
<<
9
,
PERF_SAMPLE_STREAM_ID
=
1U
<<
9
,
PERF_SAMPLE_
TP_RECORD
=
1U
<<
10
,
PERF_SAMPLE_
RAW
=
1U
<<
10
,
PERF_SAMPLE_MAX
=
1U
<<
11
,
/* non-ABI */
PERF_SAMPLE_MAX
=
1U
<<
11
,
/* non-ABI */
};
};
...
@@ -369,6 +369,8 @@ enum perf_event_type {
...
@@ -369,6 +369,8 @@ enum perf_event_type {
*
*
* { u64 nr,
* { u64 nr,
* u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
* u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
* { u32 size;
* char data[size];}&& PERF_SAMPLE_RAW
* };
* };
*/
*/
PERF_EVENT_SAMPLE
=
9
,
PERF_EVENT_SAMPLE
=
9
,
...
@@ -414,9 +416,9 @@ struct perf_callchain_entry {
...
@@ -414,9 +416,9 @@ struct perf_callchain_entry {
__u64
ip
[
PERF_MAX_STACK_DEPTH
];
__u64
ip
[
PERF_MAX_STACK_DEPTH
];
};
};
struct
perf_
tracepoint
_record
{
struct
perf_
raw
_record
{
int
size
;
u32
size
;
char
*
record
;
void
*
data
;
};
};
struct
task_struct
;
struct
task_struct
;
...
@@ -687,7 +689,7 @@ struct perf_sample_data {
...
@@ -687,7 +689,7 @@ struct perf_sample_data {
struct
pt_regs
*
regs
;
struct
pt_regs
*
regs
;
u64
addr
;
u64
addr
;
u64
period
;
u64
period
;
void
*
private
;
struct
perf_raw_record
*
raw
;
};
};
extern
int
perf_counter_overflow
(
struct
perf_counter
*
counter
,
int
nmi
,
extern
int
perf_counter_overflow
(
struct
perf_counter
*
counter
,
int
nmi
,
...
...
include/trace/ftrace.h
浏览文件 @
824df399
...
@@ -637,12 +637,20 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
...
@@ -637,12 +637,20 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
* pc = preempt_count();
* pc = preempt_count();
*
*
* __data_size = ftrace_get_offsets_<call>(&__data_offsets, args);
* __data_size = ftrace_get_offsets_<call>(&__data_offsets, args);
* __entry_size = __data_size + sizeof(*entry);
*
* // Below we want to get the aligned size by taking into account
* // the u32 field that will later store the buffer size
* __entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),
* sizeof(u64));
* __entry_size -= sizeof(u32);
*
*
* do {
* do {
* char raw_data[__entry_size]; <- allocate our sample in the stack
* char raw_data[__entry_size]; <- allocate our sample in the stack
* struct trace_entry *ent;
* struct trace_entry *ent;
*
*
* zero dead bytes from alignment to avoid stack leak to userspace:
*
* *(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL;
* entry = (struct ftrace_raw_<call> *)raw_data;
* entry = (struct ftrace_raw_<call> *)raw_data;
* ent = &entry->ent;
* ent = &entry->ent;
* tracing_generic_entry_update(ent, irq_flags, pc);
* tracing_generic_entry_update(ent, irq_flags, pc);
...
@@ -685,12 +693,15 @@ static void ftrace_profile_##call(proto) \
...
@@ -685,12 +693,15 @@ static void ftrace_profile_##call(proto) \
pc = preempt_count(); \
pc = preempt_count(); \
\
\
__data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
__data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
__entry_size = ALIGN(__data_size + sizeof(*entry), sizeof(u64));\
__entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),\
sizeof(u64)); \
__entry_size -= sizeof(u32); \
\
\
do { \
do { \
char raw_data[__entry_size]; \
char raw_data[__entry_size]; \
struct trace_entry *ent; \
struct trace_entry *ent; \
\
\
*(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL; \
entry = (struct ftrace_raw_##call *)raw_data; \
entry = (struct ftrace_raw_##call *)raw_data; \
ent = &entry->ent; \
ent = &entry->ent; \
tracing_generic_entry_update(ent, irq_flags, pc); \
tracing_generic_entry_update(ent, irq_flags, pc); \
...
...
kernel/irq/numa_migrate.c
浏览文件 @
824df399
...
@@ -107,8 +107,8 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
...
@@ -107,8 +107,8 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
struct
irq_desc
*
move_irq_desc
(
struct
irq_desc
*
desc
,
int
node
)
struct
irq_desc
*
move_irq_desc
(
struct
irq_desc
*
desc
,
int
node
)
{
{
/* those
all static, do
move them */
/* those
static or target node is -1, do not
move them */
if
(
desc
->
irq
<
NR_IRQS_LEGACY
)
if
(
desc
->
irq
<
NR_IRQS_LEGACY
||
node
==
-
1
)
return
desc
;
return
desc
;
if
(
desc
->
node
!=
node
)
if
(
desc
->
node
!=
node
)
...
...
kernel/perf_counter.c
浏览文件 @
824df399
...
@@ -2646,7 +2646,6 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
...
@@ -2646,7 +2646,6 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
u64
counter
;
u64
counter
;
}
group_entry
;
}
group_entry
;
struct
perf_callchain_entry
*
callchain
=
NULL
;
struct
perf_callchain_entry
*
callchain
=
NULL
;
struct
perf_tracepoint_record
*
tp
;
int
callchain_size
=
0
;
int
callchain_size
=
0
;
u64
time
;
u64
time
;
struct
{
struct
{
...
@@ -2715,9 +2714,16 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
...
@@ -2715,9 +2714,16 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
header
.
size
+=
sizeof
(
u64
);
header
.
size
+=
sizeof
(
u64
);
}
}
if
(
sample_type
&
PERF_SAMPLE_TP_RECORD
)
{
if
(
sample_type
&
PERF_SAMPLE_RAW
)
{
tp
=
data
->
private
;
int
size
=
sizeof
(
u32
);
header
.
size
+=
tp
->
size
;
if
(
data
->
raw
)
size
+=
data
->
raw
->
size
;
else
size
+=
sizeof
(
u32
);
WARN_ON_ONCE
(
size
&
(
sizeof
(
u64
)
-
1
));
header
.
size
+=
size
;
}
}
ret
=
perf_output_begin
(
&
handle
,
counter
,
header
.
size
,
nmi
,
1
);
ret
=
perf_output_begin
(
&
handle
,
counter
,
header
.
size
,
nmi
,
1
);
...
@@ -2783,8 +2789,21 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
...
@@ -2783,8 +2789,21 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
}
}
}
}
if
(
sample_type
&
PERF_SAMPLE_TP_RECORD
)
if
(
sample_type
&
PERF_SAMPLE_RAW
)
{
perf_output_copy
(
&
handle
,
tp
->
record
,
tp
->
size
);
if
(
data
->
raw
)
{
perf_output_put
(
&
handle
,
data
->
raw
->
size
);
perf_output_copy
(
&
handle
,
data
->
raw
->
data
,
data
->
raw
->
size
);
}
else
{
struct
{
u32
size
;
u32
data
;
}
raw
=
{
.
size
=
sizeof
(
u32
),
.
data
=
0
,
};
perf_output_put
(
&
handle
,
raw
);
}
}
perf_output_end
(
&
handle
);
perf_output_end
(
&
handle
);
}
}
...
@@ -2849,7 +2868,8 @@ perf_counter_read_event(struct perf_counter *counter,
...
@@ -2849,7 +2868,8 @@ perf_counter_read_event(struct perf_counter *counter,
*/
*/
struct
perf_task_event
{
struct
perf_task_event
{
struct
task_struct
*
task
;
struct
task_struct
*
task
;
struct
perf_counter_context
*
task_ctx
;
struct
{
struct
{
struct
perf_event_header
header
;
struct
perf_event_header
header
;
...
@@ -2909,24 +2929,23 @@ static void perf_counter_task_ctx(struct perf_counter_context *ctx,
...
@@ -2909,24 +2929,23 @@ static void perf_counter_task_ctx(struct perf_counter_context *ctx,
static
void
perf_counter_task_event
(
struct
perf_task_event
*
task_event
)
static
void
perf_counter_task_event
(
struct
perf_task_event
*
task_event
)
{
{
struct
perf_cpu_context
*
cpuctx
;
struct
perf_cpu_context
*
cpuctx
;
struct
perf_counter_context
*
ctx
;
struct
perf_counter_context
*
ctx
=
task_event
->
task_ctx
;
cpuctx
=
&
get_cpu_var
(
perf_cpu_context
);
cpuctx
=
&
get_cpu_var
(
perf_cpu_context
);
perf_counter_task_ctx
(
&
cpuctx
->
ctx
,
task_event
);
perf_counter_task_ctx
(
&
cpuctx
->
ctx
,
task_event
);
put_cpu_var
(
perf_cpu_context
);
put_cpu_var
(
perf_cpu_context
);
rcu_read_lock
();
rcu_read_lock
();
/*
if
(
!
ctx
)
* doesn't really matter which of the child contexts the
ctx
=
rcu_dereference
(
task_event
->
task
->
perf_counter_ctxp
);
* events ends up in.
*/
ctx
=
rcu_dereference
(
current
->
perf_counter_ctxp
);
if
(
ctx
)
if
(
ctx
)
perf_counter_task_ctx
(
ctx
,
task_event
);
perf_counter_task_ctx
(
ctx
,
task_event
);
rcu_read_unlock
();
rcu_read_unlock
();
}
}
static
void
perf_counter_task
(
struct
task_struct
*
task
,
int
new
)
static
void
perf_counter_task
(
struct
task_struct
*
task
,
struct
perf_counter_context
*
task_ctx
,
int
new
)
{
{
struct
perf_task_event
task_event
;
struct
perf_task_event
task_event
;
...
@@ -2936,8 +2955,9 @@ static void perf_counter_task(struct task_struct *task, int new)
...
@@ -2936,8 +2955,9 @@ static void perf_counter_task(struct task_struct *task, int new)
return
;
return
;
task_event
=
(
struct
perf_task_event
){
task_event
=
(
struct
perf_task_event
){
.
task
=
task
,
.
task
=
task
,
.
event
=
{
.
task_ctx
=
task_ctx
,
.
event
=
{
.
header
=
{
.
header
=
{
.
type
=
new
?
PERF_EVENT_FORK
:
PERF_EVENT_EXIT
,
.
type
=
new
?
PERF_EVENT_FORK
:
PERF_EVENT_EXIT
,
.
misc
=
0
,
.
misc
=
0
,
...
@@ -2955,7 +2975,7 @@ static void perf_counter_task(struct task_struct *task, int new)
...
@@ -2955,7 +2975,7 @@ static void perf_counter_task(struct task_struct *task, int new)
void
perf_counter_fork
(
struct
task_struct
*
task
)
void
perf_counter_fork
(
struct
task_struct
*
task
)
{
{
perf_counter_task
(
task
,
1
);
perf_counter_task
(
task
,
NULL
,
1
);
}
}
/*
/*
...
@@ -3344,87 +3364,81 @@ int perf_counter_overflow(struct perf_counter *counter, int nmi,
...
@@ -3344,87 +3364,81 @@ int perf_counter_overflow(struct perf_counter *counter, int nmi,
* Generic software counter infrastructure
* Generic software counter infrastructure
*/
*/
static
void
perf_swcounter_update
(
struct
perf_counter
*
counter
)
/*
* We directly increment counter->count and keep a second value in
* counter->hw.period_left to count intervals. This period counter
* is kept in the range [-sample_period, 0] so that we can use the
* sign as trigger.
*/
static
u64
perf_swcounter_set_period
(
struct
perf_counter
*
counter
)
{
{
struct
hw_perf_counter
*
hwc
=
&
counter
->
hw
;
struct
hw_perf_counter
*
hwc
=
&
counter
->
hw
;
u64
prev
,
now
;
u64
period
=
hwc
->
last_period
;
s64
delta
;
u64
nr
,
offset
;
s64
old
,
val
;
hwc
->
last_period
=
hwc
->
sample_period
;
again:
again:
prev
=
atomic64_read
(
&
hwc
->
prev_count
);
old
=
val
=
atomic64_read
(
&
hwc
->
period_left
);
now
=
atomic64_read
(
&
hwc
->
count
);
if
(
val
<
0
)
if
(
atomic64_cmpxchg
(
&
hwc
->
prev_count
,
prev
,
now
)
!=
prev
)
return
0
;
goto
again
;
delta
=
now
-
prev
;
nr
=
div64_u64
(
period
+
val
,
period
);
offset
=
nr
*
period
;
val
-=
offset
;
if
(
atomic64_cmpxchg
(
&
hwc
->
period_left
,
old
,
val
)
!=
old
)
goto
again
;
atomic64_add
(
delta
,
&
counter
->
count
);
return
nr
;
atomic64_sub
(
delta
,
&
hwc
->
period_left
);
}
}
static
void
perf_swcounter_set_period
(
struct
perf_counter
*
counter
)
static
void
perf_swcounter_overflow
(
struct
perf_counter
*
counter
,
int
nmi
,
struct
perf_sample_data
*
data
)
{
{
struct
hw_perf_counter
*
hwc
=
&
counter
->
hw
;
struct
hw_perf_counter
*
hwc
=
&
counter
->
hw
;
s64
left
=
atomic64_read
(
&
hwc
->
period_left
);
u64
overflow
;
s64
period
=
hwc
->
sample_period
;
if
(
unlikely
(
left
<=
-
period
))
{
data
->
period
=
counter
->
hw
.
last_period
;
left
=
period
;
overflow
=
perf_swcounter_set_period
(
counter
);
atomic64_set
(
&
hwc
->
period_left
,
left
);
hwc
->
last_period
=
period
;
}
if
(
unlikely
(
left
<=
0
))
{
if
(
hwc
->
interrupts
==
MAX_INTERRUPTS
)
left
+=
period
;
return
;
atomic64_add
(
period
,
&
hwc
->
period_left
);
hwc
->
last_period
=
period
;
}
atomic64_set
(
&
hwc
->
prev_count
,
-
left
);
for
(;
overflow
;
overflow
--
)
{
atomic64_set
(
&
hwc
->
count
,
-
left
);
if
(
perf_counter_overflow
(
counter
,
nmi
,
data
))
{
/*
* We inhibit the overflow from happening when
* hwc->interrupts == MAX_INTERRUPTS.
*/
break
;
}
}
}
}
static
enum
hrtimer_restart
perf_swcounter_hrtimer
(
struct
hrtimer
*
hrtim
er
)
static
void
perf_swcounter_unthrottle
(
struct
perf_counter
*
count
er
)
{
{
enum
hrtimer_restart
ret
=
HRTIMER_RESTART
;
struct
perf_sample_data
data
;
struct
perf_counter
*
counter
;
u64
period
;
counter
=
container_of
(
hrtimer
,
struct
perf_counter
,
hw
.
hrtimer
);
counter
->
pmu
->
read
(
counter
);
data
.
addr
=
0
;
data
.
regs
=
get_irq_regs
();
/*
/*
* In case we exclude kernel IPs or are somehow not in interrupt
* Nothing to do, we already reset hwc->interrupts.
* context, provide the next best thing, the user IP.
*/
*/
if
((
counter
->
attr
.
exclude_kernel
||
!
data
.
regs
)
&&
}
!
counter
->
attr
.
exclude_user
)
data
.
regs
=
task_pt_regs
(
current
);
if
(
data
.
regs
)
{
static
void
perf_swcounter_add
(
struct
perf_counter
*
counter
,
u64
nr
,
if
(
perf_counter_overflow
(
counter
,
0
,
&
data
)
)
int
nmi
,
struct
perf_sample_data
*
data
)
ret
=
HRTIMER_NORESTART
;
{
}
struct
hw_perf_counter
*
hwc
=
&
counter
->
hw
;
period
=
max_t
(
u64
,
10000
,
counter
->
hw
.
sample_period
);
atomic64_add
(
nr
,
&
counter
->
count
);
hrtimer_forward_now
(
hrtimer
,
ns_to_ktime
(
period
));
return
ret
;
if
(
!
hwc
->
sample_period
)
}
return
;
static
void
perf_swcounter_overflow
(
struct
perf_counter
*
counter
,
if
(
!
data
->
regs
)
int
nmi
,
struct
perf_sample_data
*
data
)
return
;
{
data
->
period
=
counter
->
hw
.
last_period
;
perf_swcounter_update
(
counter
);
if
(
!
atomic64_add_negative
(
nr
,
&
hwc
->
period_left
))
perf_swcounter_set_period
(
counter
);
perf_swcounter_overflow
(
counter
,
nmi
,
data
);
if
(
perf_counter_overflow
(
counter
,
nmi
,
data
))
/* soft-disable the counter */
;
}
}
static
int
perf_swcounter_is_counting
(
struct
perf_counter
*
counter
)
static
int
perf_swcounter_is_counting
(
struct
perf_counter
*
counter
)
...
@@ -3488,15 +3502,6 @@ static int perf_swcounter_match(struct perf_counter *counter,
...
@@ -3488,15 +3502,6 @@ static int perf_swcounter_match(struct perf_counter *counter,
return
1
;
return
1
;
}
}
static
void
perf_swcounter_add
(
struct
perf_counter
*
counter
,
u64
nr
,
int
nmi
,
struct
perf_sample_data
*
data
)
{
int
neg
=
atomic64_add_negative
(
nr
,
&
counter
->
hw
.
count
);
if
(
counter
->
hw
.
sample_period
&&
!
neg
&&
data
->
regs
)
perf_swcounter_overflow
(
counter
,
nmi
,
data
);
}
static
void
perf_swcounter_ctx_event
(
struct
perf_counter_context
*
ctx
,
static
void
perf_swcounter_ctx_event
(
struct
perf_counter_context
*
ctx
,
enum
perf_type_id
type
,
enum
perf_type_id
type
,
u32
event
,
u64
nr
,
int
nmi
,
u32
event
,
u64
nr
,
int
nmi
,
...
@@ -3575,26 +3580,65 @@ void __perf_swcounter_event(u32 event, u64 nr, int nmi,
...
@@ -3575,26 +3580,65 @@ void __perf_swcounter_event(u32 event, u64 nr, int nmi,
static
void
perf_swcounter_read
(
struct
perf_counter
*
counter
)
static
void
perf_swcounter_read
(
struct
perf_counter
*
counter
)
{
{
perf_swcounter_update
(
counter
);
}
}
static
int
perf_swcounter_enable
(
struct
perf_counter
*
counter
)
static
int
perf_swcounter_enable
(
struct
perf_counter
*
counter
)
{
{
perf_swcounter_set_period
(
counter
);
struct
hw_perf_counter
*
hwc
=
&
counter
->
hw
;
if
(
hwc
->
sample_period
)
{
hwc
->
last_period
=
hwc
->
sample_period
;
perf_swcounter_set_period
(
counter
);
}
return
0
;
return
0
;
}
}
static
void
perf_swcounter_disable
(
struct
perf_counter
*
counter
)
static
void
perf_swcounter_disable
(
struct
perf_counter
*
counter
)
{
{
perf_swcounter_update
(
counter
);
}
}
static
const
struct
pmu
perf_ops_generic
=
{
static
const
struct
pmu
perf_ops_generic
=
{
.
enable
=
perf_swcounter_enable
,
.
enable
=
perf_swcounter_enable
,
.
disable
=
perf_swcounter_disable
,
.
disable
=
perf_swcounter_disable
,
.
read
=
perf_swcounter_read
,
.
read
=
perf_swcounter_read
,
.
unthrottle
=
perf_swcounter_unthrottle
,
};
};
/*
* hrtimer based swcounter callback
*/
static
enum
hrtimer_restart
perf_swcounter_hrtimer
(
struct
hrtimer
*
hrtimer
)
{
enum
hrtimer_restart
ret
=
HRTIMER_RESTART
;
struct
perf_sample_data
data
;
struct
perf_counter
*
counter
;
u64
period
;
counter
=
container_of
(
hrtimer
,
struct
perf_counter
,
hw
.
hrtimer
);
counter
->
pmu
->
read
(
counter
);
data
.
addr
=
0
;
data
.
regs
=
get_irq_regs
();
/*
* In case we exclude kernel IPs or are somehow not in interrupt
* context, provide the next best thing, the user IP.
*/
if
((
counter
->
attr
.
exclude_kernel
||
!
data
.
regs
)
&&
!
counter
->
attr
.
exclude_user
)
data
.
regs
=
task_pt_regs
(
current
);
if
(
data
.
regs
)
{
if
(
perf_counter_overflow
(
counter
,
0
,
&
data
))
ret
=
HRTIMER_NORESTART
;
}
period
=
max_t
(
u64
,
10000
,
counter
->
hw
.
sample_period
);
hrtimer_forward_now
(
hrtimer
,
ns_to_ktime
(
period
));
return
ret
;
}
/*
/*
* Software counter: cpu wall time clock
* Software counter: cpu wall time clock
*/
*/
...
@@ -3715,15 +3759,15 @@ static const struct pmu perf_ops_task_clock = {
...
@@ -3715,15 +3759,15 @@ static const struct pmu perf_ops_task_clock = {
void
perf_tpcounter_event
(
int
event_id
,
u64
addr
,
u64
count
,
void
*
record
,
void
perf_tpcounter_event
(
int
event_id
,
u64
addr
,
u64
count
,
void
*
record
,
int
entry_size
)
int
entry_size
)
{
{
struct
perf_
tracepoint_record
tp
=
{
struct
perf_
raw_record
raw
=
{
.
size
=
entry_size
,
.
size
=
entry_size
,
.
record
=
record
,
.
data
=
record
,
};
};
struct
perf_sample_data
data
=
{
struct
perf_sample_data
data
=
{
.
regs
=
get_irq_regs
(),
.
regs
=
get_irq_regs
(),
.
addr
=
addr
,
.
addr
=
addr
,
.
private
=
&
tp
,
.
raw
=
&
raw
,
};
};
if
(
!
data
.
regs
)
if
(
!
data
.
regs
)
...
@@ -3743,6 +3787,14 @@ static void tp_perf_counter_destroy(struct perf_counter *counter)
...
@@ -3743,6 +3787,14 @@ static void tp_perf_counter_destroy(struct perf_counter *counter)
static
const
struct
pmu
*
tp_perf_counter_init
(
struct
perf_counter
*
counter
)
static
const
struct
pmu
*
tp_perf_counter_init
(
struct
perf_counter
*
counter
)
{
{
/*
* Raw tracepoint data is a severe data leak, only allow root to
* have these.
*/
if
((
counter
->
attr
.
sample_type
&
PERF_SAMPLE_RAW
)
&&
!
capable
(
CAP_SYS_ADMIN
))
return
ERR_PTR
(
-
EPERM
);
if
(
ftrace_profile_enable
(
counter
->
attr
.
config
))
if
(
ftrace_profile_enable
(
counter
->
attr
.
config
))
return
NULL
;
return
NULL
;
...
@@ -4285,7 +4337,7 @@ void perf_counter_exit_task(struct task_struct *child)
...
@@ -4285,7 +4337,7 @@ void perf_counter_exit_task(struct task_struct *child)
unsigned
long
flags
;
unsigned
long
flags
;
if
(
likely
(
!
child
->
perf_counter_ctxp
))
{
if
(
likely
(
!
child
->
perf_counter_ctxp
))
{
perf_counter_task
(
child
,
0
);
perf_counter_task
(
child
,
NULL
,
0
);
return
;
return
;
}
}
...
@@ -4305,6 +4357,7 @@ void perf_counter_exit_task(struct task_struct *child)
...
@@ -4305,6 +4357,7 @@ void perf_counter_exit_task(struct task_struct *child)
* incremented the context's refcount before we do put_ctx below.
* incremented the context's refcount before we do put_ctx below.
*/
*/
spin_lock
(
&
child_ctx
->
lock
);
spin_lock
(
&
child_ctx
->
lock
);
child
->
perf_counter_ctxp
=
NULL
;
/*
/*
* If this context is a clone; unclone it so it can't get
* If this context is a clone; unclone it so it can't get
* swapped to another process while we're removing all
* swapped to another process while we're removing all
...
@@ -4318,9 +4371,7 @@ void perf_counter_exit_task(struct task_struct *child)
...
@@ -4318,9 +4371,7 @@ void perf_counter_exit_task(struct task_struct *child)
* won't get any samples after PERF_EVENT_EXIT. We can however still
* won't get any samples after PERF_EVENT_EXIT. We can however still
* get a few PERF_EVENT_READ events.
* get a few PERF_EVENT_READ events.
*/
*/
perf_counter_task
(
child
,
0
);
perf_counter_task
(
child
,
child_ctx
,
0
);
child
->
perf_counter_ctxp
=
NULL
;
/*
/*
* We can recurse on the same lock type through:
* We can recurse on the same lock type through:
...
...
kernel/trace/blktrace.c
浏览文件 @
824df399
...
@@ -267,8 +267,8 @@ static void blk_trace_free(struct blk_trace *bt)
...
@@ -267,8 +267,8 @@ static void blk_trace_free(struct blk_trace *bt)
{
{
debugfs_remove
(
bt
->
msg_file
);
debugfs_remove
(
bt
->
msg_file
);
debugfs_remove
(
bt
->
dropped_file
);
debugfs_remove
(
bt
->
dropped_file
);
debugfs_remove
(
bt
->
dir
);
relay_close
(
bt
->
rchan
);
relay_close
(
bt
->
rchan
);
debugfs_remove
(
bt
->
dir
);
free_percpu
(
bt
->
sequence
);
free_percpu
(
bt
->
sequence
);
free_percpu
(
bt
->
msg_data
);
free_percpu
(
bt
->
msg_data
);
kfree
(
bt
);
kfree
(
bt
);
...
@@ -378,18 +378,8 @@ static int blk_subbuf_start_callback(struct rchan_buf *buf, void *subbuf,
...
@@ -378,18 +378,8 @@ static int blk_subbuf_start_callback(struct rchan_buf *buf, void *subbuf,
static
int
blk_remove_buf_file_callback
(
struct
dentry
*
dentry
)
static
int
blk_remove_buf_file_callback
(
struct
dentry
*
dentry
)
{
{
struct
dentry
*
parent
=
dentry
->
d_parent
;
debugfs_remove
(
dentry
);
debugfs_remove
(
dentry
);
/*
* this will fail for all but the last file, but that is ok. what we
* care about is the top level buts->name directory going away, when
* the last trace file is gone. Then we don't have to rmdir() that
* manually on trace stop, so it nicely solves the issue with
* force killing of running traces.
*/
debugfs_remove
(
parent
);
return
0
;
return
0
;
}
}
...
...
mm/mempool.c
浏览文件 @
824df399
...
@@ -303,14 +303,14 @@ EXPORT_SYMBOL(mempool_free_slab);
...
@@ -303,14 +303,14 @@ EXPORT_SYMBOL(mempool_free_slab);
*/
*/
void
*
mempool_kmalloc
(
gfp_t
gfp_mask
,
void
*
pool_data
)
void
*
mempool_kmalloc
(
gfp_t
gfp_mask
,
void
*
pool_data
)
{
{
size_t
size
=
(
size_t
)
(
long
)
pool_data
;
size_t
size
=
(
size_t
)
pool_data
;
return
kmalloc
(
size
,
gfp_mask
);
return
kmalloc
(
size
,
gfp_mask
);
}
}
EXPORT_SYMBOL
(
mempool_kmalloc
);
EXPORT_SYMBOL
(
mempool_kmalloc
);
void
*
mempool_kzalloc
(
gfp_t
gfp_mask
,
void
*
pool_data
)
void
*
mempool_kzalloc
(
gfp_t
gfp_mask
,
void
*
pool_data
)
{
{
size_t
size
=
(
size_t
)
pool_data
;
size_t
size
=
(
size_t
)
pool_data
;
return
kzalloc
(
size
,
gfp_mask
);
return
kzalloc
(
size
,
gfp_mask
);
}
}
EXPORT_SYMBOL
(
mempool_kzalloc
);
EXPORT_SYMBOL
(
mempool_kzalloc
);
...
...
security/selinux/hooks.c
浏览文件 @
824df399
...
@@ -1285,6 +1285,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
...
@@ -1285,6 +1285,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
rc
=
inode
->
i_op
->
getxattr
(
dentry
,
XATTR_NAME_SELINUX
,
rc
=
inode
->
i_op
->
getxattr
(
dentry
,
XATTR_NAME_SELINUX
,
context
,
len
);
context
,
len
);
if
(
rc
==
-
ERANGE
)
{
if
(
rc
==
-
ERANGE
)
{
kfree
(
context
);
/* Need a larger buffer. Query for the right size. */
/* Need a larger buffer. Query for the right size. */
rc
=
inode
->
i_op
->
getxattr
(
dentry
,
XATTR_NAME_SELINUX
,
rc
=
inode
->
i_op
->
getxattr
(
dentry
,
XATTR_NAME_SELINUX
,
NULL
,
0
);
NULL
,
0
);
...
@@ -1292,7 +1294,6 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
...
@@ -1292,7 +1294,6 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
dput
(
dentry
);
dput
(
dentry
);
goto
out_unlock
;
goto
out_unlock
;
}
}
kfree
(
context
);
len
=
rc
;
len
=
rc
;
context
=
kmalloc
(
len
+
1
,
GFP_NOFS
);
context
=
kmalloc
(
len
+
1
,
GFP_NOFS
);
if
(
!
context
)
{
if
(
!
context
)
{
...
...
sound/pci/hda/patch_realtek.c
浏览文件 @
824df399
...
@@ -13563,6 +13563,8 @@ static int patch_alc269(struct hda_codec *codec)
...
@@ -13563,6 +13563,8 @@ static int patch_alc269(struct hda_codec *codec)
set_capture_mixer(spec);
set_capture_mixer(spec);
set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
spec->vmaster_nid = 0x02;
codec->patch_ops = alc_patch_ops;
codec->patch_ops = alc_patch_ops;
if (board_config == ALC269_AUTO)
if (board_config == ALC269_AUTO)
spec->init_hook = alc269_auto_init;
spec->init_hook = alc269_auto_init;
...
@@ -15577,9 +15579,12 @@ static int patch_alc861vd(struct hda_codec *codec)
...
@@ -15577,9 +15579,12 @@ static int patch_alc861vd(struct hda_codec *codec)
spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
spec->adc_nids = alc861vd_adc_nids;
if (!spec->adc_nids) {
spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
spec->adc_nids = alc861vd_adc_nids;
spec->capsrc_nids = alc861vd_capsrc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
}
if (!spec->capsrc_nids)
spec->capsrc_nids = alc861vd_capsrc_nids;
set_capture_mixer(spec);
set_capture_mixer(spec);
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
...
@@ -17496,9 +17501,12 @@ static int patch_alc662(struct hda_codec *codec)
...
@@ -17496,9 +17501,12 @@ static int patch_alc662(struct hda_codec *codec)
spec->stream_digital_playback = &alc662_pcm_digital_playback;
spec->stream_digital_playback = &alc662_pcm_digital_playback;
spec->stream_digital_capture = &alc662_pcm_digital_capture;
spec->stream_digital_capture = &alc662_pcm_digital_capture;
spec->adc_nids = alc662_adc_nids;
if (!spec->adc_nids) {
spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
spec->adc_nids = alc662_adc_nids;
spec->capsrc_nids = alc662_capsrc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
}
if (!spec->capsrc_nids)
spec->capsrc_nids = alc662_capsrc_nids;
if (!spec->cap_mixer)
if (!spec->cap_mixer)
set_capture_mixer(spec);
set_capture_mixer(spec);
...
...
sound/soc/fsl/efika-audio-fabric.c
浏览文件 @
824df399
...
@@ -30,6 +30,8 @@
...
@@ -30,6 +30,8 @@
#include "mpc5200_psc_ac97.h"
#include "mpc5200_psc_ac97.h"
#include "../codecs/stac9766.h"
#include "../codecs/stac9766.h"
#define DRV_NAME "efika-audio-fabric"
static
struct
snd_soc_device
device
;
static
struct
snd_soc_device
device
;
static
struct
snd_soc_card
card
;
static
struct
snd_soc_card
card
;
...
...
sound/soc/fsl/pcm030-audio-fabric.c
浏览文件 @
824df399
...
@@ -30,6 +30,8 @@
...
@@ -30,6 +30,8 @@
#include "mpc5200_psc_ac97.h"
#include "mpc5200_psc_ac97.h"
#include "../codecs/wm9712.h"
#include "../codecs/wm9712.h"
#define DRV_NAME "pcm030-audio-fabric"
static
struct
snd_soc_device
device
;
static
struct
snd_soc_device
device
;
static
struct
snd_soc_card
card
;
static
struct
snd_soc_card
card
;
...
...
tools/perf/Documentation/perf-examples.txt
0 → 100644
浏览文件 @
824df399
------------------------------
****** perf by examples ******
------------------------------
[ From an e-mail by Ingo Molnar, http://lkml.org/lkml/2009/8/4/346 ]
First, discovery/enumeration of available counters can be done via
'perf list':
titan:~> perf list
[...]
kmem:kmalloc [Tracepoint event]
kmem:kmem_cache_alloc [Tracepoint event]
kmem:kmalloc_node [Tracepoint event]
kmem:kmem_cache_alloc_node [Tracepoint event]
kmem:kfree [Tracepoint event]
kmem:kmem_cache_free [Tracepoint event]
kmem:mm_page_free_direct [Tracepoint event]
kmem:mm_pagevec_free [Tracepoint event]
kmem:mm_page_alloc [Tracepoint event]
kmem:mm_page_alloc_zone_locked [Tracepoint event]
kmem:mm_page_pcpu_drain [Tracepoint event]
kmem:mm_page_alloc_extfrag [Tracepoint event]
Then any (or all) of the above event sources can be activated and
measured. For example the page alloc/free properties of a 'hackbench
run' are:
titan:~> perf stat -e kmem:mm_page_pcpu_drain -e kmem:mm_page_alloc
-e kmem:mm_pagevec_free -e kmem:mm_page_free_direct ./hackbench 10
Time: 0.575
Performance counter stats for './hackbench 10':
13857 kmem:mm_page_pcpu_drain
27576 kmem:mm_page_alloc
6025 kmem:mm_pagevec_free
20934 kmem:mm_page_free_direct
0.613972165 seconds time elapsed
You can observe the statistical properties as well, by using the
'repeat the workload N times' feature of perf stat:
titan:~> perf stat --repeat 5 -e kmem:mm_page_pcpu_drain -e
kmem:mm_page_alloc -e kmem:mm_pagevec_free -e
kmem:mm_page_free_direct ./hackbench 10
Time: 0.627
Time: 0.644
Time: 0.564
Time: 0.559
Time: 0.626
Performance counter stats for './hackbench 10' (5 runs):
12920 kmem:mm_page_pcpu_drain ( +- 3.359% )
25035 kmem:mm_page_alloc ( +- 3.783% )
6104 kmem:mm_pagevec_free ( +- 0.934% )
18376 kmem:mm_page_free_direct ( +- 4.941% )
0.643954516 seconds time elapsed ( +- 2.363% )
Furthermore, these tracepoints can be used to sample the workload as
well. For example the page allocations done by a 'git gc' can be
captured the following way:
titan:~/git> perf record -f -e kmem:mm_page_alloc -c 1 ./git gc
Counting objects: 1148, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (450/450), done.
Writing objects: 100% (1148/1148), done.
Total 1148 (delta 690), reused 1148 (delta 690)
[ perf record: Captured and wrote 0.267 MB perf.data (~11679 samples) ]
To check which functions generated page allocations:
titan:~/git> perf report
# Samples: 10646
#
# Overhead Command Shared Object
# ........ ............... ..........................
#
23.57% git-repack /lib64/libc-2.5.so
21.81% git /lib64/libc-2.5.so
14.59% git ./git
11.79% git-repack ./git
7.12% git /lib64/ld-2.5.so
3.16% git-repack /lib64/libpthread-2.5.so
2.09% git-repack /bin/bash
1.97% rm /lib64/libc-2.5.so
1.39% mv /lib64/ld-2.5.so
1.37% mv /lib64/libc-2.5.so
1.12% git-repack /lib64/ld-2.5.so
0.95% rm /lib64/ld-2.5.so
0.90% git-update-serv /lib64/libc-2.5.so
0.73% git-update-serv /lib64/ld-2.5.so
0.68% perf /lib64/libpthread-2.5.so
0.64% git-repack /usr/lib64/libz.so.1.2.3
Or to see it on a more finegrained level:
titan:~/git> perf report --sort comm,dso,symbol
# Samples: 10646
#
# Overhead Command Shared Object Symbol
# ........ ............... .......................... ......
#
9.35% git-repack ./git [.] insert_obj_hash
9.12% git ./git [.] insert_obj_hash
7.31% git /lib64/libc-2.5.so [.] memcpy
6.34% git-repack /lib64/libc-2.5.so [.] _int_malloc
6.24% git-repack /lib64/libc-2.5.so [.] memcpy
5.82% git-repack /lib64/libc-2.5.so [.] __GI___fork
5.47% git /lib64/libc-2.5.so [.] _int_malloc
2.99% git /lib64/libc-2.5.so [.] memset
Furthermore, call-graph sampling can be done too, of page
allocations - to see precisely what kind of page allocations there
are:
titan:~/git> perf record -f -g -e kmem:mm_page_alloc -c 1 ./git gc
Counting objects: 1148, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (450/450), done.
Writing objects: 100% (1148/1148), done.
Total 1148 (delta 690), reused 1148 (delta 690)
[ perf record: Captured and wrote 0.963 MB perf.data (~42069 samples) ]
titan:~/git> perf report -g
# Samples: 10686
#
# Overhead Command Shared Object
# ........ ............... ..........................
#
23.25% git-repack /lib64/libc-2.5.so
|
|--50.00%-- _int_free
|
|--37.50%-- __GI___fork
| make_child
|
|--12.50%-- ptmalloc_unlock_all2
| make_child
|
--6.25%-- __GI_strcpy
21.61% git /lib64/libc-2.5.so
|
|--30.00%-- __GI_read
| |
| --83.33%-- git_config_from_file
| git_config
| |
[...]
Or you can observe the whole system's page allocations for 10
seconds:
titan:~/git> perf stat -a -e kmem:mm_page_pcpu_drain -e
kmem:mm_page_alloc -e kmem:mm_pagevec_free -e
kmem:mm_page_free_direct sleep 10
Performance counter stats for 'sleep 10':
171585 kmem:mm_page_pcpu_drain
322114 kmem:mm_page_alloc
73623 kmem:mm_pagevec_free
254115 kmem:mm_page_free_direct
10.000591410 seconds time elapsed
Or observe how fluctuating the page allocations are, via statistical
analysis done over ten 1-second intervals:
titan:~/git> perf stat --repeat 10 -a -e kmem:mm_page_pcpu_drain -e
kmem:mm_page_alloc -e kmem:mm_pagevec_free -e
kmem:mm_page_free_direct sleep 1
Performance counter stats for 'sleep 1' (10 runs):
17254 kmem:mm_page_pcpu_drain ( +- 3.709% )
34394 kmem:mm_page_alloc ( +- 4.617% )
7509 kmem:mm_pagevec_free ( +- 4.820% )
25653 kmem:mm_page_free_direct ( +- 3.672% )
1.058135029 seconds time elapsed ( +- 3.089% )
Or you can annotate the recorded 'git gc' run on a per symbol basis
and check which instructions/source-code generated page allocations:
titan:~/git> perf annotate __GI___fork
------------------------------------------------
Percent | Source code & Disassembly of libc-2.5.so
------------------------------------------------
:
:
: Disassembly of section .plt:
: Disassembly of section .text:
:
: 00000031a2e95560 <__fork>:
[...]
0.00 : 31a2e95602: b8 38 00 00 00 mov $0x38,%eax
0.00 : 31a2e95607: 0f 05 syscall
83.42 : 31a2e95609: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax
0.00 : 31a2e9560f: 0f 87 4d 01 00 00 ja 31a2e95762 <__fork+0x202>
0.00 : 31a2e95615: 85 c0 test %eax,%eax
( this shows that 83.42% of __GI___fork's page allocations come from
the 0x38 system call it performs. )
etc. etc. - a lot more is possible. I could list a dozen of
other different usecases straight away - neither of which is
possible via /proc/vmstat.
/proc/vmstat is not in the same league really, in terms of
expressive power of system analysis and performance
analysis.
All that the above results needed were those new tracepoints
in include/tracing/events/kmem.h.
Ingo
tools/perf/Documentation/perf-stat.txt
浏览文件 @
824df399
...
@@ -40,7 +40,7 @@ OPTIONS
...
@@ -40,7 +40,7 @@ OPTIONS
-a::
-a::
system-wide collection
system-wide collection
-
S
::
-
c
::
scale counter values
scale counter values
EXAMPLES
EXAMPLES
...
...
tools/perf/Documentation/perf-top.txt
浏览文件 @
824df399
...
@@ -3,36 +3,122 @@ perf-top(1)
...
@@ -3,36 +3,122 @@ perf-top(1)
NAME
NAME
----
----
perf-top -
Run a command and profile it
perf-top -
System profiling tool.
SYNOPSIS
SYNOPSIS
--------
--------
[verse]
[verse]
'perf top' [-e <EVENT> | --event=EVENT] [
-l] [-a] <command>
'perf top' [-e <EVENT> | --event=EVENT] [
<options>]
DESCRIPTION
DESCRIPTION
-----------
-----------
This command runs a command and gathers a performance counter profile
This command generates and displays a performance counter profile in realtime.
from it.
OPTIONS
OPTIONS
-------
-------
<command>...::
-a::
Any command you can specify in a shell.
--all-cpus::
System-wide collection. (default)
-c <count>::
--count=<count>::
Event period to sample.
-C <cpu>::
--CPU=<cpu>::
CPU to profile.
-d <seconds>::
--delay=<seconds>::
Number of seconds to delay between refreshes.
-e::
-e
<event>
::
--event=::
--event=
<event>
::
Select the PMU event. Selection can be a symbolic event name
Select the PMU event. Selection can be a symbolic event name
(use 'perf list' to list all events) or a raw PMU
(use 'perf list' to list all events) or a raw PMU
event (eventsel+umask) in the form of rNNN where NNN is a
event (eventsel+umask) in the form of rNNN where NNN is a
hexadecimal event descriptor.
hexadecimal event descriptor.
-a::
-E <entries>::
system-wide collection
--entries=<entries>::
Display this many functions.
-f <count>::
--count-filter=<count>::
Only display functions with more events than this.
-F <freq>::
--freq=<freq>::
Profile at this frequency.
-i::
--inherit::
Child tasks inherit counters, only makes sens with -p option.
-k <path>::
--vmlinux=<path>::
Path to vmlinux. Required for annotation functionality.
-m <pages>::
--mmap-pages=<pages>::
Number of mmapped data pages.
-p <pid>::
--pid=<pid>::
Profile events on existing pid.
-r <priority>::
--realtime=<priority>::
Collect data with this RT SCHED_FIFO priority.
-s <symbol>::
--sym-annotate=<symbol>::
Annotate this symbol. Requires -k option.
-v::
--verbose::
Be more verbose (show counter open errors, etc).
-z::
--zero::
Zero history across display updates.
INTERACTIVE PROMPTING KEYS
--------------------------
[d]::
Display refresh delay.
[e]::
Number of entries to display.
[E]::
Event to display when multiple counters are active.
[f]::
Profile display filter (>= hit count).
[F]::
Annotation display filter (>= % of total).
[s]::
Annotate symbol.
[S]::
Stop annotation, return to full profile display.
[w]::
Toggle between weighted sum and individual count[E]r profile.
[z]::
Toggle event count zeroing across display updates.
[qQ]::
Quit.
Pressing any unmapped key displays a menu, and prompts for input.
-l::
scale counter values
SEE ALSO
SEE ALSO
--------
--------
...
...
tools/perf/Makefile
浏览文件 @
824df399
...
@@ -387,10 +387,14 @@ else
...
@@ -387,10 +387,14 @@ else
has_bfd_iberty
:=
$(
shell
sh
-c
"(echo '
\#
include <bfd.h>'; echo 'int main(void
)
{ bfd_demangle(0, 0, 0
)
; return 0;
}
'
)
|
$(CC)
-x c -
$(ALL_CFLAGS)
-o /dev/null
$(ALL_LDFLAGS)
-lbfd -liberty > /dev/null 2>&1 && echo y"
)
has_bfd_iberty
:=
$(
shell
sh
-c
"(echo '
\#
include <bfd.h>'; echo 'int main(void
)
{ bfd_demangle(0, 0, 0
)
; return 0;
}
'
)
|
$(CC)
-x c -
$(ALL_CFLAGS)
-o /dev/null
$(ALL_LDFLAGS)
-lbfd -liberty > /dev/null 2>&1 && echo y"
)
has_bfd_iberty_z
:=
$(
shell
sh
-c
"(echo '
\#
include <bfd.h>'; echo 'int main(void
)
{ bfd_demangle(0, 0, 0
)
; return 0;
}
'
)
|
$(CC)
-x c -
$(ALL_CFLAGS)
-o /dev/null
$(ALL_LDFLAGS)
-lbfd -liberty -lz > /dev/null 2>&1 && echo y"
)
ifeq
($(has_bfd),y)
ifeq
($(has_bfd),y)
EXTLIBS
+=
-lbfd
EXTLIBS
+=
-lbfd
else
ifeq
($(has_bfd_iberty),y)
else
ifeq
($(has_bfd_iberty),y)
EXTLIBS
+=
-lbfd
-liberty
EXTLIBS
+=
-lbfd
-liberty
else
ifeq
($(has_bfd_iberty_z),y)
EXTLIBS
+=
-lbfd
-liberty
-lz
else
else
msg
:=
$(
warning
No bfd.h/libbfd found,
install
binutils-dev[el] to gain symbol demangling
)
msg
:=
$(
warning
No bfd.h/libbfd found,
install
binutils-dev[el] to gain symbol demangling
)
BASIC_CFLAGS
+=
-DNO_DEMANGLE
BASIC_CFLAGS
+=
-DNO_DEMANGLE
...
...
tools/perf/builtin-record.c
浏览文件 @
824df399
...
@@ -525,10 +525,14 @@ static int __cmd_record(int argc, const char **argv)
...
@@ -525,10 +525,14 @@ static int __cmd_record(int argc, const char **argv)
signal
(
SIGCHLD
,
sig_handler
);
signal
(
SIGCHLD
,
sig_handler
);
signal
(
SIGINT
,
sig_handler
);
signal
(
SIGINT
,
sig_handler
);
if
(
!
stat
(
output_name
,
&
st
)
&&
!
force
&&
!
append_file
)
{
if
(
!
stat
(
output_name
,
&
st
)
&&
st
.
st_size
)
{
fprintf
(
stderr
,
"Error, output file %s exists, use -A to append or -f to overwrite.
\n
"
,
if
(
!
force
&&
!
append_file
)
{
output_name
);
fprintf
(
stderr
,
"Error, output file %s exists, use -A to append or -f to overwrite.
\n
"
,
exit
(
-
1
);
output_name
);
exit
(
-
1
);
}
}
else
{
append_file
=
0
;
}
}
flags
=
O_CREAT
|
O_RDWR
;
flags
=
O_CREAT
|
O_RDWR
;
...
...
tools/perf/builtin-report.c
浏览文件 @
824df399
...
@@ -68,7 +68,7 @@ static int callchain;
...
@@ -68,7 +68,7 @@ static int callchain;
static
static
struct
callchain_param
callchain_param
=
{
struct
callchain_param
callchain_param
=
{
.
mode
=
CHAIN_GRAPH_
ABS
,
.
mode
=
CHAIN_GRAPH_
REL
,
.
min_percent
=
0
.
5
.
min_percent
=
0
.
5
};
};
...
@@ -112,7 +112,9 @@ struct read_event {
...
@@ -112,7 +112,9 @@ struct read_event {
struct
perf_event_header
header
;
struct
perf_event_header
header
;
u32
pid
,
tid
;
u32
pid
,
tid
;
u64
value
;
u64
value
;
u64
format
[
3
];
u64
time_enabled
;
u64
time_running
;
u64
id
;
};
};
typedef
union
event_union
{
typedef
union
event_union
{
...
@@ -698,7 +700,8 @@ sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
...
@@ -698,7 +700,8 @@ sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
size_t
ret
=
0
;
size_t
ret
=
0
;
if
(
verbose
)
if
(
verbose
)
ret
+=
repsep_fprintf
(
fp
,
"%#018llx "
,
(
u64
)
self
->
ip
);
ret
+=
repsep_fprintf
(
fp
,
"%#018llx %c "
,
(
u64
)
self
->
ip
,
dso__symtab_origin
(
self
->
dso
));
ret
+=
repsep_fprintf
(
fp
,
"[%c] "
,
self
->
level
);
ret
+=
repsep_fprintf
(
fp
,
"[%c] "
,
self
->
level
);
if
(
self
->
sym
)
{
if
(
self
->
sym
)
{
...
@@ -888,6 +891,21 @@ ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
...
@@ -888,6 +891,21 @@ ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
return
ret
;
return
ret
;
}
}
static
struct
symbol
*
rem_sq_bracket
;
static
struct
callchain_list
rem_hits
;
static
void
init_rem_hits
(
void
)
{
rem_sq_bracket
=
malloc
(
sizeof
(
*
rem_sq_bracket
)
+
6
);
if
(
!
rem_sq_bracket
)
{
fprintf
(
stderr
,
"Not enough memory to display remaining hits
\n
"
);
return
;
}
strcpy
(
rem_sq_bracket
->
name
,
"[...]"
);
rem_hits
.
sym
=
rem_sq_bracket
;
}
static
size_t
static
size_t
callchain__fprintf_graph
(
FILE
*
fp
,
struct
callchain_node
*
self
,
callchain__fprintf_graph
(
FILE
*
fp
,
struct
callchain_node
*
self
,
u64
total_samples
,
int
depth
,
int
depth_mask
)
u64
total_samples
,
int
depth
,
int
depth_mask
)
...
@@ -897,25 +915,34 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
...
@@ -897,25 +915,34 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
struct
callchain_list
*
chain
;
struct
callchain_list
*
chain
;
int
new_depth_mask
=
depth_mask
;
int
new_depth_mask
=
depth_mask
;
u64
new_total
;
u64
new_total
;
u64
remaining
;
size_t
ret
=
0
;
size_t
ret
=
0
;
int
i
;
int
i
;
if
(
callchain_param
.
mode
==
CHAIN_GRAPH_REL
)
if
(
callchain_param
.
mode
==
CHAIN_GRAPH_REL
)
new_total
=
self
->
c
umul
_hit
;
new_total
=
self
->
c
hildren
_hit
;
else
else
new_total
=
total_samples
;
new_total
=
total_samples
;
remaining
=
new_total
;
node
=
rb_first
(
&
self
->
rb_root
);
node
=
rb_first
(
&
self
->
rb_root
);
while
(
node
)
{
while
(
node
)
{
u64
cumul
;
child
=
rb_entry
(
node
,
struct
callchain_node
,
rb_node
);
child
=
rb_entry
(
node
,
struct
callchain_node
,
rb_node
);
cumul
=
cumul_hits
(
child
);
remaining
-=
cumul
;
/*
/*
* The depth mask manages the output of pipes that show
* The depth mask manages the output of pipes that show
* the depth. We don't want to keep the pipes of the current
* the depth. We don't want to keep the pipes of the current
* level for the last child of this depth
* level for the last child of this depth.
* Except if we have remaining filtered hits. They will
* supersede the last child
*/
*/
next
=
rb_next
(
node
);
next
=
rb_next
(
node
);
if
(
!
next
)
if
(
!
next
&&
(
callchain_param
.
mode
!=
CHAIN_GRAPH_REL
||
!
remaining
)
)
new_depth_mask
&=
~
(
1
<<
(
depth
-
1
));
new_depth_mask
&=
~
(
1
<<
(
depth
-
1
));
/*
/*
...
@@ -930,7 +957,7 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
...
@@ -930,7 +957,7 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
ret
+=
ipchain__fprintf_graph
(
fp
,
chain
,
depth
,
ret
+=
ipchain__fprintf_graph
(
fp
,
chain
,
depth
,
new_depth_mask
,
i
++
,
new_depth_mask
,
i
++
,
new_total
,
new_total
,
c
hild
->
cumul_hit
);
c
umul
);
}
}
ret
+=
callchain__fprintf_graph
(
fp
,
child
,
new_total
,
ret
+=
callchain__fprintf_graph
(
fp
,
child
,
new_total
,
depth
+
1
,
depth
+
1
,
...
@@ -938,6 +965,19 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
...
@@ -938,6 +965,19 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
node
=
next
;
node
=
next
;
}
}
if
(
callchain_param
.
mode
==
CHAIN_GRAPH_REL
&&
remaining
&&
remaining
!=
new_total
)
{
if
(
!
rem_sq_bracket
)
return
ret
;
new_depth_mask
&=
~
(
1
<<
(
depth
-
1
));
ret
+=
ipchain__fprintf_graph
(
fp
,
&
rem_hits
,
depth
,
new_depth_mask
,
0
,
new_total
,
remaining
);
}
return
ret
;
return
ret
;
}
}
...
@@ -1358,6 +1398,8 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
...
@@ -1358,6 +1398,8 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
unsigned
int
width
;
unsigned
int
width
;
char
*
col_width
=
col_width_list_str
;
char
*
col_width
=
col_width_list_str
;
init_rem_hits
();
fprintf
(
fp
,
"# Samples: %Ld
\n
"
,
(
u64
)
total_samples
);
fprintf
(
fp
,
"# Samples: %Ld
\n
"
,
(
u64
)
total_samples
);
fprintf
(
fp
,
"#
\n
"
);
fprintf
(
fp
,
"#
\n
"
);
...
@@ -1429,6 +1471,8 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
...
@@ -1429,6 +1471,8 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
}
}
fprintf
(
fp
,
"
\n
"
);
fprintf
(
fp
,
"
\n
"
);
free
(
rem_sq_bracket
);
return
ret
;
return
ret
;
}
}
...
@@ -1690,14 +1734,37 @@ static void trace_event(event_t *event)
...
@@ -1690,14 +1734,37 @@ static void trace_event(event_t *event)
dprintf
(
".
\n
"
);
dprintf
(
".
\n
"
);
}
}
static
struct
perf_header
*
header
;
static
struct
perf_counter_attr
*
perf_header__find_attr
(
u64
id
)
{
int
i
;
for
(
i
=
0
;
i
<
header
->
attrs
;
i
++
)
{
struct
perf_header_attr
*
attr
=
header
->
attr
[
i
];
int
j
;
for
(
j
=
0
;
j
<
attr
->
ids
;
j
++
)
{
if
(
attr
->
id
[
j
]
==
id
)
return
&
attr
->
attr
;
}
}
return
NULL
;
}
static
int
static
int
process_read_event
(
event_t
*
event
,
unsigned
long
offset
,
unsigned
long
head
)
process_read_event
(
event_t
*
event
,
unsigned
long
offset
,
unsigned
long
head
)
{
{
dprintf
(
"%p [%p]: PERF_EVENT_READ: %d %d %Lu
\n
"
,
struct
perf_counter_attr
*
attr
=
perf_header__find_attr
(
event
->
read
.
id
);
dprintf
(
"%p [%p]: PERF_EVENT_READ: %d %d %s %Lu
\n
"
,
(
void
*
)(
offset
+
head
),
(
void
*
)(
offset
+
head
),
(
void
*
)(
long
)(
event
->
header
.
size
),
(
void
*
)(
long
)(
event
->
header
.
size
),
event
->
read
.
pid
,
event
->
read
.
pid
,
event
->
read
.
tid
,
event
->
read
.
tid
,
attr
?
__event_name
(
attr
->
type
,
attr
->
config
)
:
"FAIL"
,
event
->
read
.
value
);
event
->
read
.
value
);
return
0
;
return
0
;
...
@@ -1743,8 +1810,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
...
@@ -1743,8 +1810,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
return
0
;
return
0
;
}
}
static
struct
perf_header
*
header
;
static
u64
perf_header__sample_type
(
void
)
static
u64
perf_header__sample_type
(
void
)
{
{
u64
sample_type
=
0
;
u64
sample_type
=
0
;
...
@@ -1812,6 +1877,13 @@ static int __cmd_report(void)
...
@@ -1812,6 +1877,13 @@ static int __cmd_report(void)
" -g?
\n
"
);
" -g?
\n
"
);
exit
(
-
1
);
exit
(
-
1
);
}
}
}
else
if
(
callchain_param
.
mode
!=
CHAIN_NONE
&&
!
callchain
)
{
callchain
=
1
;
if
(
register_callchain_param
(
&
callchain_param
)
<
0
)
{
fprintf
(
stderr
,
"Can't register callchain"
" params
\n
"
);
exit
(
-
1
);
}
}
}
if
(
load_kernel
()
<
0
)
{
if
(
load_kernel
()
<
0
)
{
...
@@ -1950,6 +2022,13 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
...
@@ -1950,6 +2022,13 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
else
if
(
!
strncmp
(
tok
,
"fractal"
,
strlen
(
arg
)))
else
if
(
!
strncmp
(
tok
,
"fractal"
,
strlen
(
arg
)))
callchain_param
.
mode
=
CHAIN_GRAPH_REL
;
callchain_param
.
mode
=
CHAIN_GRAPH_REL
;
else
if
(
!
strncmp
(
tok
,
"none"
,
strlen
(
arg
)))
{
callchain_param
.
mode
=
CHAIN_NONE
;
callchain
=
0
;
return
0
;
}
else
else
return
-
1
;
return
-
1
;
...
...
tools/perf/builtin-stat.c
浏览文件 @
824df399
...
@@ -496,7 +496,7 @@ static const struct option options[] = {
...
@@ -496,7 +496,7 @@ static const struct option options[] = {
"stat events on existing pid"
),
"stat events on existing pid"
),
OPT_BOOLEAN
(
'a'
,
"all-cpus"
,
&
system_wide
,
OPT_BOOLEAN
(
'a'
,
"all-cpus"
,
&
system_wide
,
"system-wide collection from all CPUs"
),
"system-wide collection from all CPUs"
),
OPT_BOOLEAN
(
'
S
'
,
"scale"
,
&
scale
,
OPT_BOOLEAN
(
'
c
'
,
"scale"
,
&
scale
,
"scale/normalize counters"
),
"scale/normalize counters"
),
OPT_BOOLEAN
(
'v'
,
"verbose"
,
&
verbose
,
OPT_BOOLEAN
(
'v'
,
"verbose"
,
&
verbose
,
"be more verbose (show counter open errors, etc)"
),
"be more verbose (show counter open errors, etc)"
),
...
...
tools/perf/builtin-top.c
浏览文件 @
824df399
...
@@ -31,6 +31,8 @@
...
@@ -31,6 +31,8 @@
#include <fcntl.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <errno.h>
#include <time.h>
#include <time.h>
...
@@ -54,7 +56,7 @@ static int system_wide = 0;
...
@@ -54,7 +56,7 @@ static int system_wide = 0;
static
int
default_interval
=
100000
;
static
int
default_interval
=
100000
;
static
u64
count_filter
=
5
;
static
int
count_filter
=
5
;
static
int
print_entries
=
15
;
static
int
print_entries
=
15
;
static
int
target_pid
=
-
1
;
static
int
target_pid
=
-
1
;
...
@@ -69,14 +71,27 @@ static int freq = 0;
...
@@ -69,14 +71,27 @@ static int freq = 0;
static
int
verbose
=
0
;
static
int
verbose
=
0
;
static
char
*
vmlinux
=
NULL
;
static
char
*
vmlinux
=
NULL
;
static
char
*
sym_filter
;
static
unsigned
long
filter_start
;
static
unsigned
long
filter_end
;
static
int
delay_secs
=
2
;
static
int
delay_secs
=
2
;
static
int
zero
;
static
int
zero
;
static
int
dump_symtab
;
static
int
dump_symtab
;
/*
* Source
*/
struct
source_line
{
u64
eip
;
unsigned
long
count
[
MAX_COUNTERS
];
char
*
line
;
struct
source_line
*
next
;
};
static
char
*
sym_filter
=
NULL
;
struct
sym_entry
*
sym_filter_entry
=
NULL
;
static
int
sym_pcnt_filter
=
5
;
static
int
sym_counter
=
0
;
static
int
display_weighted
=
-
1
;
/*
/*
* Symbols
* Symbols
*/
*/
...
@@ -91,9 +106,237 @@ struct sym_entry {
...
@@ -91,9 +106,237 @@ struct sym_entry {
unsigned
long
snap_count
;
unsigned
long
snap_count
;
double
weight
;
double
weight
;
int
skip
;
int
skip
;
struct
source_line
*
source
;
struct
source_line
*
lines
;
struct
source_line
**
lines_tail
;
pthread_mutex_t
source_lock
;
};
};
struct
sym_entry
*
sym_filter_entry
;
/*
* Source functions
*/
static
void
parse_source
(
struct
sym_entry
*
syme
)
{
struct
symbol
*
sym
;
struct
module
*
module
;
struct
section
*
section
=
NULL
;
FILE
*
file
;
char
command
[
PATH_MAX
*
2
],
*
path
=
vmlinux
;
u64
start
,
end
,
len
;
if
(
!
syme
)
return
;
if
(
syme
->
lines
)
{
pthread_mutex_lock
(
&
syme
->
source_lock
);
goto
out_assign
;
}
sym
=
(
struct
symbol
*
)(
syme
+
1
);
module
=
sym
->
module
;
if
(
module
)
path
=
module
->
path
;
if
(
!
path
)
return
;
start
=
sym
->
obj_start
;
if
(
!
start
)
start
=
sym
->
start
;
if
(
module
)
{
section
=
module
->
sections
->
find_section
(
module
->
sections
,
".text"
);
if
(
section
)
start
-=
section
->
vma
;
}
end
=
start
+
sym
->
end
-
sym
->
start
+
1
;
len
=
sym
->
end
-
sym
->
start
;
sprintf
(
command
,
"objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s"
,
start
,
end
,
path
);
file
=
popen
(
command
,
"r"
);
if
(
!
file
)
return
;
pthread_mutex_lock
(
&
syme
->
source_lock
);
syme
->
lines_tail
=
&
syme
->
lines
;
while
(
!
feof
(
file
))
{
struct
source_line
*
src
;
size_t
dummy
=
0
;
char
*
c
;
src
=
malloc
(
sizeof
(
struct
source_line
));
assert
(
src
!=
NULL
);
memset
(
src
,
0
,
sizeof
(
struct
source_line
));
if
(
getline
(
&
src
->
line
,
&
dummy
,
file
)
<
0
)
break
;
if
(
!
src
->
line
)
break
;
c
=
strchr
(
src
->
line
,
'\n'
);
if
(
c
)
*
c
=
0
;
src
->
next
=
NULL
;
*
syme
->
lines_tail
=
src
;
syme
->
lines_tail
=
&
src
->
next
;
if
(
strlen
(
src
->
line
)
>
8
&&
src
->
line
[
8
]
==
':'
)
{
src
->
eip
=
strtoull
(
src
->
line
,
NULL
,
16
);
if
(
section
)
src
->
eip
+=
section
->
vma
;
}
if
(
strlen
(
src
->
line
)
>
8
&&
src
->
line
[
16
]
==
':'
)
{
src
->
eip
=
strtoull
(
src
->
line
,
NULL
,
16
);
if
(
section
)
src
->
eip
+=
section
->
vma
;
}
}
pclose
(
file
);
out_assign:
sym_filter_entry
=
syme
;
pthread_mutex_unlock
(
&
syme
->
source_lock
);
}
static
void
__zero_source_counters
(
struct
sym_entry
*
syme
)
{
int
i
;
struct
source_line
*
line
;
line
=
syme
->
lines
;
while
(
line
)
{
for
(
i
=
0
;
i
<
nr_counters
;
i
++
)
line
->
count
[
i
]
=
0
;
line
=
line
->
next
;
}
}
static
void
record_precise_ip
(
struct
sym_entry
*
syme
,
int
counter
,
u64
ip
)
{
struct
source_line
*
line
;
if
(
syme
!=
sym_filter_entry
)
return
;
if
(
pthread_mutex_trylock
(
&
syme
->
source_lock
))
return
;
if
(
!
syme
->
source
)
goto
out_unlock
;
for
(
line
=
syme
->
lines
;
line
;
line
=
line
->
next
)
{
if
(
line
->
eip
==
ip
)
{
line
->
count
[
counter
]
++
;
break
;
}
if
(
line
->
eip
>
ip
)
break
;
}
out_unlock:
pthread_mutex_unlock
(
&
syme
->
source_lock
);
}
static
void
lookup_sym_source
(
struct
sym_entry
*
syme
)
{
struct
symbol
*
symbol
=
(
struct
symbol
*
)(
syme
+
1
);
struct
source_line
*
line
;
char
pattern
[
PATH_MAX
];
char
*
idx
;
sprintf
(
pattern
,
"<%s>:"
,
symbol
->
name
);
if
(
symbol
->
module
)
{
idx
=
strstr
(
pattern
,
"
\t
"
);
if
(
idx
)
*
idx
=
0
;
}
pthread_mutex_lock
(
&
syme
->
source_lock
);
for
(
line
=
syme
->
lines
;
line
;
line
=
line
->
next
)
{
if
(
strstr
(
line
->
line
,
pattern
))
{
syme
->
source
=
line
;
break
;
}
}
pthread_mutex_unlock
(
&
syme
->
source_lock
);
}
static
void
show_lines
(
struct
source_line
*
queue
,
int
count
,
int
total
)
{
int
i
;
struct
source_line
*
line
;
line
=
queue
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
float
pcnt
=
100
.
0
*
(
float
)
line
->
count
[
sym_counter
]
/
(
float
)
total
;
printf
(
"%8li %4.1f%%
\t
%s
\n
"
,
line
->
count
[
sym_counter
],
pcnt
,
line
->
line
);
line
=
line
->
next
;
}
}
#define TRACE_COUNT 3
static
void
show_details
(
struct
sym_entry
*
syme
)
{
struct
symbol
*
symbol
;
struct
source_line
*
line
;
struct
source_line
*
line_queue
=
NULL
;
int
displayed
=
0
;
int
line_queue_count
=
0
,
total
=
0
,
more
=
0
;
if
(
!
syme
)
return
;
if
(
!
syme
->
source
)
lookup_sym_source
(
syme
);
if
(
!
syme
->
source
)
return
;
symbol
=
(
struct
symbol
*
)(
syme
+
1
);
printf
(
"Showing %s for %s
\n
"
,
event_name
(
sym_counter
),
symbol
->
name
);
printf
(
" Events Pcnt (>=%d%%)
\n
"
,
sym_pcnt_filter
);
pthread_mutex_lock
(
&
syme
->
source_lock
);
line
=
syme
->
source
;
while
(
line
)
{
total
+=
line
->
count
[
sym_counter
];
line
=
line
->
next
;
}
line
=
syme
->
source
;
while
(
line
)
{
float
pcnt
=
0
.
0
;
if
(
!
line_queue_count
)
line_queue
=
line
;
line_queue_count
++
;
if
(
line
->
count
[
sym_counter
])
pcnt
=
100
.
0
*
line
->
count
[
sym_counter
]
/
(
float
)
total
;
if
(
pcnt
>=
(
float
)
sym_pcnt_filter
)
{
if
(
displayed
<=
print_entries
)
show_lines
(
line_queue
,
line_queue_count
,
total
);
else
more
++
;
displayed
+=
line_queue_count
;
line_queue_count
=
0
;
line_queue
=
NULL
;
}
else
if
(
line_queue_count
>
TRACE_COUNT
)
{
line_queue
=
line_queue
->
next
;
line_queue_count
--
;
}
line
->
count
[
sym_counter
]
=
zero
?
0
:
line
->
count
[
sym_counter
]
*
7
/
8
;
line
=
line
->
next
;
}
pthread_mutex_unlock
(
&
syme
->
source_lock
);
if
(
more
)
printf
(
"%d lines not displayed, maybe increase display entries [e]
\n
"
,
more
);
}
struct
dso
*
kernel_dso
;
struct
dso
*
kernel_dso
;
...
@@ -112,6 +355,9 @@ static double sym_weight(const struct sym_entry *sym)
...
@@ -112,6 +355,9 @@ static double sym_weight(const struct sym_entry *sym)
double
weight
=
sym
->
snap_count
;
double
weight
=
sym
->
snap_count
;
int
counter
;
int
counter
;
if
(
!
display_weighted
)
return
weight
;
for
(
counter
=
1
;
counter
<
nr_counters
-
1
;
counter
++
)
for
(
counter
=
1
;
counter
<
nr_counters
-
1
;
counter
++
)
weight
*=
sym
->
count
[
counter
];
weight
*=
sym
->
count
[
counter
];
...
@@ -159,7 +405,7 @@ static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
...
@@ -159,7 +405,7 @@ static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
static
void
print_sym_table
(
void
)
static
void
print_sym_table
(
void
)
{
{
int
printed
=
0
,
j
;
int
printed
=
0
,
j
;
int
counter
;
int
counter
,
snap
=
!
display_weighted
?
sym_counter
:
0
;
float
samples_per_sec
=
samples
/
delay_secs
;
float
samples_per_sec
=
samples
/
delay_secs
;
float
ksamples_per_sec
=
(
samples
-
userspace_samples
)
/
delay_secs
;
float
ksamples_per_sec
=
(
samples
-
userspace_samples
)
/
delay_secs
;
float
sum_ksamples
=
0
.
0
;
float
sum_ksamples
=
0
.
0
;
...
@@ -175,7 +421,7 @@ static void print_sym_table(void)
...
@@ -175,7 +421,7 @@ static void print_sym_table(void)
pthread_mutex_unlock
(
&
active_symbols_lock
);
pthread_mutex_unlock
(
&
active_symbols_lock
);
list_for_each_entry_safe_from
(
syme
,
n
,
&
active_symbols
,
node
)
{
list_for_each_entry_safe_from
(
syme
,
n
,
&
active_symbols
,
node
)
{
syme
->
snap_count
=
syme
->
count
[
0
];
syme
->
snap_count
=
syme
->
count
[
snap
];
if
(
syme
->
snap_count
!=
0
)
{
if
(
syme
->
snap_count
!=
0
)
{
syme
->
weight
=
sym_weight
(
syme
);
syme
->
weight
=
sym_weight
(
syme
);
rb_insert_active_sym
(
&
tmp
,
syme
);
rb_insert_active_sym
(
&
tmp
,
syme
);
...
@@ -195,7 +441,7 @@ static void print_sym_table(void)
...
@@ -195,7 +441,7 @@ static void print_sym_table(void)
samples_per_sec
,
samples_per_sec
,
100
.
0
-
(
100
.
0
*
((
samples_per_sec
-
ksamples_per_sec
)
/
samples_per_sec
)));
100
.
0
-
(
100
.
0
*
((
samples_per_sec
-
ksamples_per_sec
)
/
samples_per_sec
)));
if
(
nr_counters
==
1
)
{
if
(
nr_counters
==
1
||
!
display_weighted
)
{
printf
(
"%Ld"
,
(
u64
)
attrs
[
0
].
sample_period
);
printf
(
"%Ld"
,
(
u64
)
attrs
[
0
].
sample_period
);
if
(
freq
)
if
(
freq
)
printf
(
"Hz "
);
printf
(
"Hz "
);
...
@@ -203,7 +449,9 @@ static void print_sym_table(void)
...
@@ -203,7 +449,9 @@ static void print_sym_table(void)
printf
(
" "
);
printf
(
" "
);
}
}
for
(
counter
=
0
;
counter
<
nr_counters
;
counter
++
)
{
if
(
!
display_weighted
)
printf
(
"%s"
,
event_name
(
sym_counter
));
else
for
(
counter
=
0
;
counter
<
nr_counters
;
counter
++
)
{
if
(
counter
)
if
(
counter
)
printf
(
"/"
);
printf
(
"/"
);
...
@@ -228,6 +476,11 @@ static void print_sym_table(void)
...
@@ -228,6 +476,11 @@ static void print_sym_table(void)
printf
(
"------------------------------------------------------------------------------
\n\n
"
);
printf
(
"------------------------------------------------------------------------------
\n\n
"
);
if
(
sym_filter_entry
)
{
show_details
(
sym_filter_entry
);
return
;
}
if
(
nr_counters
==
1
)
if
(
nr_counters
==
1
)
printf
(
" samples pcnt"
);
printf
(
" samples pcnt"
);
else
else
...
@@ -242,13 +495,13 @@ static void print_sym_table(void)
...
@@ -242,13 +495,13 @@ static void print_sym_table(void)
struct
symbol
*
sym
=
(
struct
symbol
*
)(
syme
+
1
);
struct
symbol
*
sym
=
(
struct
symbol
*
)(
syme
+
1
);
double
pcnt
;
double
pcnt
;
if
(
++
printed
>
print_entries
||
syme
->
snap_count
<
count_filter
)
if
(
++
printed
>
print_entries
||
(
int
)
syme
->
snap_count
<
count_filter
)
continue
;
continue
;
pcnt
=
100
.
0
-
(
100
.
0
*
((
sum_ksamples
-
syme
->
snap_count
)
/
pcnt
=
100
.
0
-
(
100
.
0
*
((
sum_ksamples
-
syme
->
snap_count
)
/
sum_ksamples
));
sum_ksamples
));
if
(
nr_counters
==
1
)
if
(
nr_counters
==
1
||
!
display_weighted
)
printf
(
"%20.2f - "
,
syme
->
weight
);
printf
(
"%20.2f - "
,
syme
->
weight
);
else
else
printf
(
"%9.1f %10ld - "
,
syme
->
weight
,
syme
->
snap_count
);
printf
(
"%9.1f %10ld - "
,
syme
->
weight
,
syme
->
snap_count
);
...
@@ -261,19 +514,250 @@ static void print_sym_table(void)
...
@@ -261,19 +514,250 @@ static void print_sym_table(void)
}
}
}
}
static
void
prompt_integer
(
int
*
target
,
const
char
*
msg
)
{
char
*
buf
=
malloc
(
0
),
*
p
;
size_t
dummy
=
0
;
int
tmp
;
fprintf
(
stdout
,
"
\n
%s: "
,
msg
);
if
(
getline
(
&
buf
,
&
dummy
,
stdin
)
<
0
)
return
;
p
=
strchr
(
buf
,
'\n'
);
if
(
p
)
*
p
=
0
;
p
=
buf
;
while
(
*
p
)
{
if
(
!
isdigit
(
*
p
))
goto
out_free
;
p
++
;
}
tmp
=
strtoul
(
buf
,
NULL
,
10
);
*
target
=
tmp
;
out_free:
free
(
buf
);
}
static
void
prompt_percent
(
int
*
target
,
const
char
*
msg
)
{
int
tmp
=
0
;
prompt_integer
(
&
tmp
,
msg
);
if
(
tmp
>=
0
&&
tmp
<=
100
)
*
target
=
tmp
;
}
static
void
prompt_symbol
(
struct
sym_entry
**
target
,
const
char
*
msg
)
{
char
*
buf
=
malloc
(
0
),
*
p
;
struct
sym_entry
*
syme
=
*
target
,
*
n
,
*
found
=
NULL
;
size_t
dummy
=
0
;
/* zero counters of active symbol */
if
(
syme
)
{
pthread_mutex_lock
(
&
syme
->
source_lock
);
__zero_source_counters
(
syme
);
*
target
=
NULL
;
pthread_mutex_unlock
(
&
syme
->
source_lock
);
}
fprintf
(
stdout
,
"
\n
%s: "
,
msg
);
if
(
getline
(
&
buf
,
&
dummy
,
stdin
)
<
0
)
goto
out_free
;
p
=
strchr
(
buf
,
'\n'
);
if
(
p
)
*
p
=
0
;
pthread_mutex_lock
(
&
active_symbols_lock
);
syme
=
list_entry
(
active_symbols
.
next
,
struct
sym_entry
,
node
);
pthread_mutex_unlock
(
&
active_symbols_lock
);
list_for_each_entry_safe_from
(
syme
,
n
,
&
active_symbols
,
node
)
{
struct
symbol
*
sym
=
(
struct
symbol
*
)(
syme
+
1
);
if
(
!
strcmp
(
buf
,
sym
->
name
))
{
found
=
syme
;
break
;
}
}
if
(
!
found
)
{
fprintf
(
stderr
,
"Sorry, %s is not active.
\n
"
,
sym_filter
);
sleep
(
1
);
return
;
}
else
parse_source
(
found
);
out_free:
free
(
buf
);
}
static
void
print_mapped_keys
(
void
)
{
char
*
name
=
NULL
;
if
(
sym_filter_entry
)
{
struct
symbol
*
sym
=
(
struct
symbol
*
)(
sym_filter_entry
+
1
);
name
=
sym
->
name
;
}
fprintf
(
stdout
,
"
\n
Mapped keys:
\n
"
);
fprintf
(
stdout
,
"
\t
[d] display refresh delay.
\t
(%d)
\n
"
,
delay_secs
);
fprintf
(
stdout
,
"
\t
[e] display entries (lines).
\t
(%d)
\n
"
,
print_entries
);
if
(
nr_counters
>
1
)
fprintf
(
stdout
,
"
\t
[E] active event counter.
\t
(%s)
\n
"
,
event_name
(
sym_counter
));
fprintf
(
stdout
,
"
\t
[f] profile display filter (count).
\t
(%d)
\n
"
,
count_filter
);
if
(
vmlinux
)
{
fprintf
(
stdout
,
"
\t
[F] annotate display filter (percent).
\t
(%d%%)
\n
"
,
sym_pcnt_filter
);
fprintf
(
stdout
,
"
\t
[s] annotate symbol.
\t
(%s)
\n
"
,
name
?:
"NULL"
);
fprintf
(
stdout
,
"
\t
[S] stop annotation.
\n
"
);
}
if
(
nr_counters
>
1
)
fprintf
(
stdout
,
"
\t
[w] toggle display weighted/count[E]r.
\t
(%d)
\n
"
,
display_weighted
?
1
:
0
);
fprintf
(
stdout
,
"
\t
[z] toggle sample zeroing.
\t
(%d)
\n
"
,
zero
?
1
:
0
);
fprintf
(
stdout
,
"
\t
[qQ] quit.
\n
"
);
}
static
int
key_mapped
(
int
c
)
{
switch
(
c
)
{
case
'd'
:
case
'e'
:
case
'f'
:
case
'z'
:
case
'q'
:
case
'Q'
:
return
1
;
case
'E'
:
case
'w'
:
return
nr_counters
>
1
?
1
:
0
;
case
'F'
:
case
's'
:
case
'S'
:
return
vmlinux
?
1
:
0
;
}
return
0
;
}
static
void
handle_keypress
(
int
c
)
{
if
(
!
key_mapped
(
c
))
{
struct
pollfd
stdin_poll
=
{
.
fd
=
0
,
.
events
=
POLLIN
};
struct
termios
tc
,
save
;
print_mapped_keys
();
fprintf
(
stdout
,
"
\n
Enter selection, or unmapped key to continue: "
);
fflush
(
stdout
);
tcgetattr
(
0
,
&
save
);
tc
=
save
;
tc
.
c_lflag
&=
~
(
ICANON
|
ECHO
);
tc
.
c_cc
[
VMIN
]
=
0
;
tc
.
c_cc
[
VTIME
]
=
0
;
tcsetattr
(
0
,
TCSANOW
,
&
tc
);
poll
(
&
stdin_poll
,
1
,
-
1
);
c
=
getc
(
stdin
);
tcsetattr
(
0
,
TCSAFLUSH
,
&
save
);
if
(
!
key_mapped
(
c
))
return
;
}
switch
(
c
)
{
case
'd'
:
prompt_integer
(
&
delay_secs
,
"Enter display delay"
);
break
;
case
'e'
:
prompt_integer
(
&
print_entries
,
"Enter display entries (lines)"
);
break
;
case
'E'
:
if
(
nr_counters
>
1
)
{
int
i
;
fprintf
(
stderr
,
"
\n
Available events:"
);
for
(
i
=
0
;
i
<
nr_counters
;
i
++
)
fprintf
(
stderr
,
"
\n\t
%d %s"
,
i
,
event_name
(
i
));
prompt_integer
(
&
sym_counter
,
"Enter details event counter"
);
if
(
sym_counter
>=
nr_counters
)
{
fprintf
(
stderr
,
"Sorry, no such event, using %s.
\n
"
,
event_name
(
0
));
sym_counter
=
0
;
sleep
(
1
);
}
}
else
sym_counter
=
0
;
break
;
case
'f'
:
prompt_integer
(
&
count_filter
,
"Enter display event count filter"
);
break
;
case
'F'
:
prompt_percent
(
&
sym_pcnt_filter
,
"Enter details display event filter (percent)"
);
break
;
case
'q'
:
case
'Q'
:
printf
(
"exiting.
\n
"
);
exit
(
0
);
case
's'
:
prompt_symbol
(
&
sym_filter_entry
,
"Enter details symbol"
);
break
;
case
'S'
:
if
(
!
sym_filter_entry
)
break
;
else
{
struct
sym_entry
*
syme
=
sym_filter_entry
;
pthread_mutex_lock
(
&
syme
->
source_lock
);
sym_filter_entry
=
NULL
;
__zero_source_counters
(
syme
);
pthread_mutex_unlock
(
&
syme
->
source_lock
);
}
break
;
case
'w'
:
display_weighted
=
~
display_weighted
;
break
;
case
'z'
:
zero
=
~
zero
;
break
;
}
}
static
void
*
display_thread
(
void
*
arg
__used
)
static
void
*
display_thread
(
void
*
arg
__used
)
{
{
struct
pollfd
stdin_poll
=
{
.
fd
=
0
,
.
events
=
POLLIN
};
struct
pollfd
stdin_poll
=
{
.
fd
=
0
,
.
events
=
POLLIN
};
int
delay_msecs
=
delay_secs
*
1000
;
struct
termios
tc
,
save
;
int
delay_msecs
,
c
;
tcgetattr
(
0
,
&
save
);
tc
=
save
;
tc
.
c_lflag
&=
~
(
ICANON
|
ECHO
);
tc
.
c_cc
[
VMIN
]
=
0
;
tc
.
c_cc
[
VTIME
]
=
0
;
printf
(
"PerfTop refresh period: %d seconds
\n
"
,
delay_secs
);
repeat:
delay_msecs
=
delay_secs
*
1000
;
tcsetattr
(
0
,
TCSANOW
,
&
tc
);
/* trash return*/
getc
(
stdin
);
do
{
do
{
print_sym_table
();
print_sym_table
();
}
while
(
!
poll
(
&
stdin_poll
,
1
,
delay_msecs
)
==
1
);
}
while
(
!
poll
(
&
stdin_poll
,
1
,
delay_msecs
)
==
1
);
printf
(
"key pressed - exiting.
\n
"
);
c
=
getc
(
stdin
);
exit
(
0
);
tcsetattr
(
0
,
TCSAFLUSH
,
&
save
);
handle_keypress
(
c
);
goto
repeat
;
return
NULL
;
return
NULL
;
}
}
...
@@ -293,7 +777,6 @@ static const char *skip_symbols[] = {
...
@@ -293,7 +777,6 @@ static const char *skip_symbols[] = {
static
int
symbol_filter
(
struct
dso
*
self
,
struct
symbol
*
sym
)
static
int
symbol_filter
(
struct
dso
*
self
,
struct
symbol
*
sym
)
{
{
static
int
filter_match
;
struct
sym_entry
*
syme
;
struct
sym_entry
*
syme
;
const
char
*
name
=
sym
->
name
;
const
char
*
name
=
sym
->
name
;
int
i
;
int
i
;
...
@@ -315,6 +798,10 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
...
@@ -315,6 +798,10 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
return
1
;
return
1
;
syme
=
dso__sym_priv
(
self
,
sym
);
syme
=
dso__sym_priv
(
self
,
sym
);
pthread_mutex_init
(
&
syme
->
source_lock
,
NULL
);
if
(
!
sym_filter_entry
&&
sym_filter
&&
!
strcmp
(
name
,
sym_filter
))
sym_filter_entry
=
syme
;
for
(
i
=
0
;
skip_symbols
[
i
];
i
++
)
{
for
(
i
=
0
;
skip_symbols
[
i
];
i
++
)
{
if
(
!
strcmp
(
skip_symbols
[
i
],
name
))
{
if
(
!
strcmp
(
skip_symbols
[
i
],
name
))
{
syme
->
skip
=
1
;
syme
->
skip
=
1
;
...
@@ -322,29 +809,6 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
...
@@ -322,29 +809,6 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
}
}
}
}
if
(
filter_match
==
1
)
{
filter_end
=
sym
->
start
;
filter_match
=
-
1
;
if
(
filter_end
-
filter_start
>
10000
)
{
fprintf
(
stderr
,
"hm, too large filter symbol <%s> - skipping.
\n
"
,
sym_filter
);
fprintf
(
stderr
,
"symbol filter start: %016lx
\n
"
,
filter_start
);
fprintf
(
stderr
,
" end: %016lx
\n
"
,
filter_end
);
filter_end
=
filter_start
=
0
;
sym_filter
=
NULL
;
sleep
(
1
);
}
}
if
(
filter_match
==
0
&&
sym_filter
&&
!
strcmp
(
name
,
sym_filter
))
{
filter_match
=
1
;
filter_start
=
sym
->
start
;
}
return
0
;
return
0
;
}
}
...
@@ -380,8 +844,6 @@ static int parse_symbols(void)
...
@@ -380,8 +844,6 @@ static int parse_symbols(void)
return
-
1
;
return
-
1
;
}
}
#define TRACE_COUNT 3
/*
/*
* Binary search in the histogram table and record the hit:
* Binary search in the histogram table and record the hit:
*/
*/
...
@@ -394,6 +856,7 @@ static void record_ip(u64 ip, int counter)
...
@@ -394,6 +856,7 @@ static void record_ip(u64 ip, int counter)
if
(
!
syme
->
skip
)
{
if
(
!
syme
->
skip
)
{
syme
->
count
[
counter
]
++
;
syme
->
count
[
counter
]
++
;
record_precise_ip
(
syme
,
counter
,
ip
);
pthread_mutex_lock
(
&
active_symbols_lock
);
pthread_mutex_lock
(
&
active_symbols_lock
);
if
(
list_empty
(
&
syme
->
node
)
||
!
syme
->
node
.
next
)
if
(
list_empty
(
&
syme
->
node
)
||
!
syme
->
node
.
next
)
__list_insert_active_sym
(
syme
);
__list_insert_active_sym
(
syme
);
...
@@ -690,8 +1153,8 @@ static const struct option options[] = {
...
@@ -690,8 +1153,8 @@ static const struct option options[] = {
"put the counters into a counter group"
),
"put the counters into a counter group"
),
OPT_BOOLEAN
(
'i'
,
"inherit"
,
&
inherit
,
OPT_BOOLEAN
(
'i'
,
"inherit"
,
&
inherit
,
"child tasks inherit counters"
),
"child tasks inherit counters"
),
OPT_STRING
(
's'
,
"sym-
filter"
,
&
sym_filter
,
"pattern
"
,
OPT_STRING
(
's'
,
"sym-
annotate"
,
&
sym_filter
,
"symbol name
"
,
"
only display symbols matchig this patter
n"
),
"
symbol to annotate - requires -k optio
n"
),
OPT_BOOLEAN
(
'z'
,
"zero"
,
&
zero
,
OPT_BOOLEAN
(
'z'
,
"zero"
,
&
zero
,
"zero history across updates"
),
"zero history across updates"
),
OPT_INTEGER
(
'F'
,
"freq"
,
&
freq
,
OPT_INTEGER
(
'F'
,
"freq"
,
&
freq
,
...
@@ -734,6 +1197,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
...
@@ -734,6 +1197,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
delay_secs
=
1
;
delay_secs
=
1
;
parse_symbols
();
parse_symbols
();
parse_source
(
sym_filter_entry
);
/*
/*
* Fill in the ones not specifically initialized via -c:
* Fill in the ones not specifically initialized via -c:
...
...
tools/perf/util/callchain.c
浏览文件 @
824df399
...
@@ -13,6 +13,7 @@
...
@@ -13,6 +13,7 @@
#include <stdio.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdbool.h>
#include <errno.h>
#include <errno.h>
#include <math.h>
#include "callchain.h"
#include "callchain.h"
...
@@ -26,10 +27,14 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
...
@@ -26,10 +27,14 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
struct
rb_node
**
p
=
&
root
->
rb_node
;
struct
rb_node
**
p
=
&
root
->
rb_node
;
struct
rb_node
*
parent
=
NULL
;
struct
rb_node
*
parent
=
NULL
;
struct
callchain_node
*
rnode
;
struct
callchain_node
*
rnode
;
u64
chain_cumul
=
cumul_hits
(
chain
);
while
(
*
p
)
{
while
(
*
p
)
{
u64
rnode_cumul
;
parent
=
*
p
;
parent
=
*
p
;
rnode
=
rb_entry
(
parent
,
struct
callchain_node
,
rb_node
);
rnode
=
rb_entry
(
parent
,
struct
callchain_node
,
rb_node
);
rnode_cumul
=
cumul_hits
(
rnode
);
switch
(
mode
)
{
switch
(
mode
)
{
case
CHAIN_FLAT
:
case
CHAIN_FLAT
:
...
@@ -40,7 +45,7 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
...
@@ -40,7 +45,7 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
break
;
break
;
case
CHAIN_GRAPH_ABS
:
/* Falldown */
case
CHAIN_GRAPH_ABS
:
/* Falldown */
case
CHAIN_GRAPH_REL
:
case
CHAIN_GRAPH_REL
:
if
(
rnode
->
cumul_hit
<
chain
->
cumul_hit
)
if
(
rnode
_cumul
<
chain_cumul
)
p
=
&
(
*
p
)
->
rb_left
;
p
=
&
(
*
p
)
->
rb_left
;
else
else
p
=
&
(
*
p
)
->
rb_right
;
p
=
&
(
*
p
)
->
rb_right
;
...
@@ -87,7 +92,7 @@ static void __sort_chain_graph_abs(struct callchain_node *node,
...
@@ -87,7 +92,7 @@ static void __sort_chain_graph_abs(struct callchain_node *node,
chain_for_each_child
(
child
,
node
)
{
chain_for_each_child
(
child
,
node
)
{
__sort_chain_graph_abs
(
child
,
min_hit
);
__sort_chain_graph_abs
(
child
,
min_hit
);
if
(
c
hild
->
cumul_hit
>=
min_hit
)
if
(
c
umul_hits
(
child
)
>=
min_hit
)
rb_insert_callchain
(
&
node
->
rb_root
,
child
,
rb_insert_callchain
(
&
node
->
rb_root
,
child
,
CHAIN_GRAPH_ABS
);
CHAIN_GRAPH_ABS
);
}
}
...
@@ -108,11 +113,11 @@ static void __sort_chain_graph_rel(struct callchain_node *node,
...
@@ -108,11 +113,11 @@ static void __sort_chain_graph_rel(struct callchain_node *node,
u64
min_hit
;
u64
min_hit
;
node
->
rb_root
=
RB_ROOT
;
node
->
rb_root
=
RB_ROOT
;
min_hit
=
node
->
cumul_hit
*
min_percent
/
100
.
0
;
min_hit
=
ceil
(
node
->
children_hit
*
min_percent
)
;
chain_for_each_child
(
child
,
node
)
{
chain_for_each_child
(
child
,
node
)
{
__sort_chain_graph_rel
(
child
,
min_percent
);
__sort_chain_graph_rel
(
child
,
min_percent
);
if
(
c
hild
->
cumul_hit
>=
min_hit
)
if
(
c
umul_hits
(
child
)
>=
min_hit
)
rb_insert_callchain
(
&
node
->
rb_root
,
child
,
rb_insert_callchain
(
&
node
->
rb_root
,
child
,
CHAIN_GRAPH_REL
);
CHAIN_GRAPH_REL
);
}
}
...
@@ -122,7 +127,7 @@ static void
...
@@ -122,7 +127,7 @@ static void
sort_chain_graph_rel
(
struct
rb_root
*
rb_root
,
struct
callchain_node
*
chain_root
,
sort_chain_graph_rel
(
struct
rb_root
*
rb_root
,
struct
callchain_node
*
chain_root
,
u64
min_hit
__used
,
struct
callchain_param
*
param
)
u64
min_hit
__used
,
struct
callchain_param
*
param
)
{
{
__sort_chain_graph_rel
(
chain_root
,
param
->
min_percent
);
__sort_chain_graph_rel
(
chain_root
,
param
->
min_percent
/
100
.
0
);
rb_root
->
rb_node
=
chain_root
->
rb_root
.
rb_node
;
rb_root
->
rb_node
=
chain_root
->
rb_root
.
rb_node
;
}
}
...
@@ -211,7 +216,8 @@ add_child(struct callchain_node *parent, struct ip_callchain *chain,
...
@@ -211,7 +216,8 @@ add_child(struct callchain_node *parent, struct ip_callchain *chain,
new
=
create_child
(
parent
,
false
);
new
=
create_child
(
parent
,
false
);
fill_node
(
new
,
chain
,
start
,
syms
);
fill_node
(
new
,
chain
,
start
,
syms
);
new
->
cumul_hit
=
new
->
hit
=
1
;
new
->
children_hit
=
0
;
new
->
hit
=
1
;
}
}
/*
/*
...
@@ -241,7 +247,8 @@ split_add_child(struct callchain_node *parent, struct ip_callchain *chain,
...
@@ -241,7 +247,8 @@ split_add_child(struct callchain_node *parent, struct ip_callchain *chain,
/* split the hits */
/* split the hits */
new
->
hit
=
parent
->
hit
;
new
->
hit
=
parent
->
hit
;
new
->
cumul_hit
=
parent
->
cumul_hit
;
new
->
children_hit
=
parent
->
children_hit
;
parent
->
children_hit
=
cumul_hits
(
new
);
new
->
val_nr
=
parent
->
val_nr
-
idx_local
;
new
->
val_nr
=
parent
->
val_nr
-
idx_local
;
parent
->
val_nr
=
idx_local
;
parent
->
val_nr
=
idx_local
;
...
@@ -249,6 +256,7 @@ split_add_child(struct callchain_node *parent, struct ip_callchain *chain,
...
@@ -249,6 +256,7 @@ split_add_child(struct callchain_node *parent, struct ip_callchain *chain,
if
(
idx_total
<
chain
->
nr
)
{
if
(
idx_total
<
chain
->
nr
)
{
parent
->
hit
=
0
;
parent
->
hit
=
0
;
add_child
(
parent
,
chain
,
idx_total
,
syms
);
add_child
(
parent
,
chain
,
idx_total
,
syms
);
parent
->
children_hit
++
;
}
else
{
}
else
{
parent
->
hit
=
1
;
parent
->
hit
=
1
;
}
}
...
@@ -269,13 +277,13 @@ __append_chain_children(struct callchain_node *root, struct ip_callchain *chain,
...
@@ -269,13 +277,13 @@ __append_chain_children(struct callchain_node *root, struct ip_callchain *chain,
unsigned
int
ret
=
__append_chain
(
rnode
,
chain
,
start
,
syms
);
unsigned
int
ret
=
__append_chain
(
rnode
,
chain
,
start
,
syms
);
if
(
!
ret
)
if
(
!
ret
)
goto
cumul
;
goto
inc_children_hit
;
}
}
/* nothing in children, add to the current node */
/* nothing in children, add to the current node */
add_child
(
root
,
chain
,
start
,
syms
);
add_child
(
root
,
chain
,
start
,
syms
);
cumul
:
inc_children_hit
:
root
->
c
umul
_hit
++
;
root
->
c
hildren
_hit
++
;
}
}
static
int
static
int
...
@@ -317,8 +325,6 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain,
...
@@ -317,8 +325,6 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain,
/* we match 100% of the path, increment the hit */
/* we match 100% of the path, increment the hit */
if
(
i
-
start
==
root
->
val_nr
&&
i
==
chain
->
nr
)
{
if
(
i
-
start
==
root
->
val_nr
&&
i
==
chain
->
nr
)
{
root
->
hit
++
;
root
->
hit
++
;
root
->
cumul_hit
++
;
return
0
;
return
0
;
}
}
...
@@ -331,5 +337,7 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain,
...
@@ -331,5 +337,7 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain,
void
append_chain
(
struct
callchain_node
*
root
,
struct
ip_callchain
*
chain
,
void
append_chain
(
struct
callchain_node
*
root
,
struct
ip_callchain
*
chain
,
struct
symbol
**
syms
)
struct
symbol
**
syms
)
{
{
if
(
!
chain
->
nr
)
return
;
__append_chain_children
(
root
,
chain
,
syms
,
0
);
__append_chain_children
(
root
,
chain
,
syms
,
0
);
}
}
tools/perf/util/callchain.h
浏览文件 @
824df399
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
#include "symbol.h"
#include "symbol.h"
enum
chain_mode
{
enum
chain_mode
{
CHAIN_NONE
,
CHAIN_FLAT
,
CHAIN_FLAT
,
CHAIN_GRAPH_ABS
,
CHAIN_GRAPH_ABS
,
CHAIN_GRAPH_REL
CHAIN_GRAPH_REL
...
@@ -21,7 +22,7 @@ struct callchain_node {
...
@@ -21,7 +22,7 @@ struct callchain_node {
struct
rb_root
rb_root
;
/* sorted tree of children */
struct
rb_root
rb_root
;
/* sorted tree of children */
unsigned
int
val_nr
;
unsigned
int
val_nr
;
u64
hit
;
u64
hit
;
u64
c
umul_hit
;
/* hit + hits of children */
u64
c
hildren_hit
;
};
};
struct
callchain_param
;
struct
callchain_param
;
...
@@ -48,6 +49,11 @@ static inline void callchain_init(struct callchain_node *node)
...
@@ -48,6 +49,11 @@ static inline void callchain_init(struct callchain_node *node)
INIT_LIST_HEAD
(
&
node
->
val
);
INIT_LIST_HEAD
(
&
node
->
val
);
}
}
static
inline
u64
cumul_hits
(
struct
callchain_node
*
node
)
{
return
node
->
hit
+
node
->
children_hit
;
}
int
register_callchain_param
(
struct
callchain_param
*
param
);
int
register_callchain_param
(
struct
callchain_param
*
param
);
void
append_chain
(
struct
callchain_node
*
root
,
struct
ip_callchain
*
chain
,
void
append_chain
(
struct
callchain_node
*
root
,
struct
ip_callchain
*
chain
,
struct
symbol
**
syms
);
struct
symbol
**
syms
);
...
...
tools/perf/util/header.c
浏览文件 @
824df399
...
@@ -185,6 +185,8 @@ static void do_read(int fd, void *buf, size_t size)
...
@@ -185,6 +185,8 @@ static void do_read(int fd, void *buf, size_t size)
if
(
ret
<
0
)
if
(
ret
<
0
)
die
(
"failed to read"
);
die
(
"failed to read"
);
if
(
ret
==
0
)
die
(
"failed to read: missing data"
);
size
-=
ret
;
size
-=
ret
;
buf
+=
ret
;
buf
+=
ret
;
...
@@ -213,9 +215,10 @@ struct perf_header *perf_header__read(int fd)
...
@@ -213,9 +215,10 @@ struct perf_header *perf_header__read(int fd)
for
(
i
=
0
;
i
<
nr_attrs
;
i
++
)
{
for
(
i
=
0
;
i
<
nr_attrs
;
i
++
)
{
struct
perf_header_attr
*
attr
;
struct
perf_header_attr
*
attr
;
off_t
tmp
=
lseek
(
fd
,
0
,
SEEK_CUR
)
;
off_t
tmp
;
do_read
(
fd
,
&
f_attr
,
sizeof
(
f_attr
));
do_read
(
fd
,
&
f_attr
,
sizeof
(
f_attr
));
tmp
=
lseek
(
fd
,
0
,
SEEK_CUR
);
attr
=
perf_header_attr__new
(
&
f_attr
.
attr
);
attr
=
perf_header_attr__new
(
&
f_attr
.
attr
);
...
...
tools/perf/util/parse-events.c
浏览文件 @
824df399
...
@@ -121,13 +121,29 @@ static unsigned long hw_cache_stat[C(MAX)] = {
...
@@ -121,13 +121,29 @@ static unsigned long hw_cache_stat[C(MAX)] = {
(strcmp(sys_dirent.d_name, ".")) && \
(strcmp(sys_dirent.d_name, ".")) && \
(strcmp(sys_dirent.d_name, "..")))
(strcmp(sys_dirent.d_name, "..")))
static
int
tp_event_has_id
(
struct
dirent
*
sys_dir
,
struct
dirent
*
evt_dir
)
{
char
evt_path
[
MAXPATHLEN
];
int
fd
;
snprintf
(
evt_path
,
MAXPATHLEN
,
"%s/%s/%s/id"
,
debugfs_path
,
sys_dir
->
d_name
,
evt_dir
->
d_name
);
fd
=
open
(
evt_path
,
O_RDONLY
);
if
(
fd
<
0
)
return
-
EINVAL
;
close
(
fd
);
return
0
;
}
#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st) \
#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st) \
while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \
while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \
if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path, \
if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path, \
sys_dirent.d_name, evt_dirent.d_name) && \
sys_dirent.d_name, evt_dirent.d_name) && \
(!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \
(!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \
(strcmp(evt_dirent.d_name, ".")) && \
(strcmp(evt_dirent.d_name, ".")) && \
(strcmp(evt_dirent.d_name, "..")))
(strcmp(evt_dirent.d_name, "..")) && \
(!tp_event_has_id(&sys_dirent, &evt_dirent)))
#define MAX_EVENT_LENGTH 30
#define MAX_EVENT_LENGTH 30
...
@@ -223,9 +239,15 @@ char *event_name(int counter)
...
@@ -223,9 +239,15 @@ char *event_name(int counter)
{
{
u64
config
=
attrs
[
counter
].
config
;
u64
config
=
attrs
[
counter
].
config
;
int
type
=
attrs
[
counter
].
type
;
int
type
=
attrs
[
counter
].
type
;
return
__event_name
(
type
,
config
);
}
char
*
__event_name
(
int
type
,
u64
config
)
{
static
char
buf
[
32
];
static
char
buf
[
32
];
if
(
attrs
[
counter
].
type
==
PERF_TYPE_RAW
)
{
if
(
type
==
PERF_TYPE_RAW
)
{
sprintf
(
buf
,
"raw 0x%llx"
,
config
);
sprintf
(
buf
,
"raw 0x%llx"
,
config
);
return
buf
;
return
buf
;
}
}
...
...
tools/perf/util/parse-events.h
浏览文件 @
824df399
...
@@ -10,6 +10,7 @@ extern int nr_counters;
...
@@ -10,6 +10,7 @@ extern int nr_counters;
extern
struct
perf_counter_attr
attrs
[
MAX_COUNTERS
];
extern
struct
perf_counter_attr
attrs
[
MAX_COUNTERS
];
extern
char
*
event_name
(
int
ctr
);
extern
char
*
event_name
(
int
ctr
);
extern
char
*
__event_name
(
int
type
,
u64
config
);
extern
int
parse_events
(
const
struct
option
*
opt
,
const
char
*
str
,
int
unset
);
extern
int
parse_events
(
const
struct
option
*
opt
,
const
char
*
str
,
int
unset
);
...
...
tools/perf/util/symbol.c
浏览文件 @
824df399
...
@@ -24,6 +24,16 @@ const char *sym_hist_filter;
...
@@ -24,6 +24,16 @@ const char *sym_hist_filter;
#define DMGL_ANSI (1 << 1)
/* Include const, volatile, etc */
#define DMGL_ANSI (1 << 1)
/* Include const, volatile, etc */
#endif
#endif
enum
dso_origin
{
DSO__ORIG_KERNEL
=
0
,
DSO__ORIG_JAVA_JIT
,
DSO__ORIG_FEDORA
,
DSO__ORIG_UBUNTU
,
DSO__ORIG_BUILDID
,
DSO__ORIG_DSO
,
DSO__ORIG_NOT_FOUND
,
};
static
struct
symbol
*
symbol__new
(
u64
start
,
u64
len
,
static
struct
symbol
*
symbol__new
(
u64
start
,
u64
len
,
const
char
*
name
,
unsigned
int
priv_size
,
const
char
*
name
,
unsigned
int
priv_size
,
u64
obj_start
,
int
verbose
)
u64
obj_start
,
int
verbose
)
...
@@ -81,6 +91,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
...
@@ -81,6 +91,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
self
->
sym_priv_size
=
sym_priv_size
;
self
->
sym_priv_size
=
sym_priv_size
;
self
->
find_symbol
=
dso__find_symbol
;
self
->
find_symbol
=
dso__find_symbol
;
self
->
slen_calculated
=
0
;
self
->
slen_calculated
=
0
;
self
->
origin
=
DSO__ORIG_NOT_FOUND
;
}
}
return
self
;
return
self
;
...
@@ -710,7 +721,7 @@ static char *dso__read_build_id(struct dso *self, int verbose)
...
@@ -710,7 +721,7 @@ static char *dso__read_build_id(struct dso *self, int verbose)
++
raw
;
++
raw
;
bid
+=
2
;
bid
+=
2
;
}
}
if
(
verbose
)
if
(
verbose
>=
2
)
printf
(
"%s(%s): %s
\n
"
,
__func__
,
self
->
name
,
build_id
);
printf
(
"%s(%s): %s
\n
"
,
__func__
,
self
->
name
,
build_id
);
out_elf_end:
out_elf_end:
elf_end
(
elf
);
elf_end
(
elf
);
...
@@ -720,11 +731,26 @@ static char *dso__read_build_id(struct dso *self, int verbose)
...
@@ -720,11 +731,26 @@ static char *dso__read_build_id(struct dso *self, int verbose)
return
build_id
;
return
build_id
;
}
}
char
dso__symtab_origin
(
const
struct
dso
*
self
)
{
static
const
char
origin
[]
=
{
[
DSO__ORIG_KERNEL
]
=
'k'
,
[
DSO__ORIG_JAVA_JIT
]
=
'j'
,
[
DSO__ORIG_FEDORA
]
=
'f'
,
[
DSO__ORIG_UBUNTU
]
=
'u'
,
[
DSO__ORIG_BUILDID
]
=
'b'
,
[
DSO__ORIG_DSO
]
=
'd'
,
};
if
(
self
==
NULL
||
self
->
origin
==
DSO__ORIG_NOT_FOUND
)
return
'!'
;
return
origin
[
self
->
origin
];
}
int
dso__load
(
struct
dso
*
self
,
symbol_filter_t
filter
,
int
verbose
)
int
dso__load
(
struct
dso
*
self
,
symbol_filter_t
filter
,
int
verbose
)
{
{
int
size
=
PATH_MAX
;
int
size
=
PATH_MAX
;
char
*
name
=
malloc
(
size
),
*
build_id
=
NULL
;
char
*
name
=
malloc
(
size
),
*
build_id
=
NULL
;
int
variant
=
0
;
int
ret
=
-
1
;
int
ret
=
-
1
;
int
fd
;
int
fd
;
...
@@ -733,19 +759,26 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
...
@@ -733,19 +759,26 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
self
->
adjust_symbols
=
0
;
self
->
adjust_symbols
=
0
;
if
(
strncmp
(
self
->
name
,
"/tmp/perf-"
,
10
)
==
0
)
if
(
strncmp
(
self
->
name
,
"/tmp/perf-"
,
10
)
==
0
)
{
return
dso__load_perf_map
(
self
,
filter
,
verbose
);
ret
=
dso__load_perf_map
(
self
,
filter
,
verbose
);
self
->
origin
=
ret
>
0
?
DSO__ORIG_JAVA_JIT
:
DSO__ORIG_NOT_FOUND
;
return
ret
;
}
self
->
origin
=
DSO__ORIG_FEDORA
-
1
;
more:
more:
do
{
do
{
switch
(
variant
)
{
self
->
origin
++
;
case
0
:
/* Fedora */
switch
(
self
->
origin
)
{
case
DSO__ORIG_FEDORA
:
snprintf
(
name
,
size
,
"/usr/lib/debug%s.debug"
,
self
->
name
);
snprintf
(
name
,
size
,
"/usr/lib/debug%s.debug"
,
self
->
name
);
break
;
break
;
case
1
:
/* Ubuntu */
case
DSO__ORIG_UBUNTU
:
snprintf
(
name
,
size
,
"/usr/lib/debug%s"
,
self
->
name
);
snprintf
(
name
,
size
,
"/usr/lib/debug%s"
,
self
->
name
);
break
;
break
;
case
2
:
case
DSO__ORIG_BUILDID
:
build_id
=
dso__read_build_id
(
self
,
verbose
);
build_id
=
dso__read_build_id
(
self
,
verbose
);
if
(
build_id
!=
NULL
)
{
if
(
build_id
!=
NULL
)
{
snprintf
(
name
,
size
,
snprintf
(
name
,
size
,
...
@@ -754,16 +787,15 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
...
@@ -754,16 +787,15 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
free
(
build_id
);
free
(
build_id
);
break
;
break
;
}
}
variant
++
;
self
->
origin
++
;
/* Fall thru */
/* Fall thru */
case
3
:
/* Sane people */
case
DSO__ORIG_DSO
:
snprintf
(
name
,
size
,
"%s"
,
self
->
name
);
snprintf
(
name
,
size
,
"%s"
,
self
->
name
);
break
;
break
;
default:
default:
goto
out
;
goto
out
;
}
}
variant
++
;
fd
=
open
(
name
,
O_RDONLY
);
fd
=
open
(
name
,
O_RDONLY
);
}
while
(
fd
<
0
);
}
while
(
fd
<
0
);
...
@@ -899,6 +931,9 @@ int dso__load_kernel(struct dso *self, const char *vmlinux,
...
@@ -899,6 +931,9 @@ int dso__load_kernel(struct dso *self, const char *vmlinux,
if
(
err
<=
0
)
if
(
err
<=
0
)
err
=
dso__load_kallsyms
(
self
,
filter
,
verbose
);
err
=
dso__load_kallsyms
(
self
,
filter
,
verbose
);
if
(
err
>
0
)
self
->
origin
=
DSO__ORIG_KERNEL
;
return
err
;
return
err
;
}
}
...
...
tools/perf/util/symbol.h
浏览文件 @
824df399
...
@@ -26,6 +26,7 @@ struct dso {
...
@@ -26,6 +26,7 @@ struct dso {
unsigned
int
sym_priv_size
;
unsigned
int
sym_priv_size
;
unsigned
char
adjust_symbols
;
unsigned
char
adjust_symbols
;
unsigned
char
slen_calculated
;
unsigned
char
slen_calculated
;
unsigned
char
origin
;
char
name
[
0
];
char
name
[
0
];
};
};
...
@@ -49,6 +50,7 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose);
...
@@ -49,6 +50,7 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose);
int
dso__load
(
struct
dso
*
self
,
symbol_filter_t
filter
,
int
verbose
);
int
dso__load
(
struct
dso
*
self
,
symbol_filter_t
filter
,
int
verbose
);
size_t
dso__fprintf
(
struct
dso
*
self
,
FILE
*
fp
);
size_t
dso__fprintf
(
struct
dso
*
self
,
FILE
*
fp
);
char
dso__symtab_origin
(
const
struct
dso
*
self
);
void
symbol__init
(
void
);
void
symbol__init
(
void
);
#endif
/* _PERF_SYMBOL_ */
#endif
/* _PERF_SYMBOL_ */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录