Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
60e0a4c7
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
60e0a4c7
编写于
8月 15, 2009
作者:
P
Paul Mundt
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'sh/stable-updates'
上级
180aa6e6
237674e0
变更
45
显示空白变更内容
内联
并排
Showing
45 changed file
with
1042 addition
and
411 deletion
+1042
-411
Makefile
Makefile
+1
-1
arch/sh/boards/mach-se/7724/setup.c
arch/sh/boards/mach-se/7724/setup.c
+5
-4
arch/sh/kernel/cpu/shmobile/sleep.S
arch/sh/kernel/cpu/shmobile/sleep.S
+68
-2
arch/x86/Kconfig
arch/x86/Kconfig
+1
-1
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/amd.c
+7
-0
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/common.c
+24
-24
arch/x86/kernel/cpu/mcheck/therm_throt.c
arch/x86/kernel/cpu/mcheck/therm_throt.c
+11
-7
arch/x86/kernel/cpu/perf_counter.c
arch/x86/kernel/cpu/perf_counter.c
+33
-7
arch/x86/kernel/reboot.c
arch/x86/kernel/reboot.c
+6
-6
drivers/clocksource/sh_cmt.c
drivers/clocksource/sh_cmt.c
+28
-0
drivers/md/md.c
drivers/md/md.c
+16
-16
drivers/md/md.h
drivers/md/md.h
+10
-0
drivers/md/raid5.c
drivers/md/raid5.c
+30
-4
drivers/video/sh_mobile_lcdcfb.c
drivers/video/sh_mobile_lcdcfb.c
+5
-0
fs/ocfs2/alloc.c
fs/ocfs2/alloc.c
+41
-6
fs/ocfs2/aops.c
fs/ocfs2/aops.c
+49
-20
fs/ocfs2/dcache.c
fs/ocfs2/dcache.c
+27
-8
fs/ocfs2/dcache.h
fs/ocfs2/dcache.h
+3
-0
fs/ocfs2/dlm/dlmast.c
fs/ocfs2/dlm/dlmast.c
+0
-1
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/dlm/dlmrecovery.c
+1
-1
fs/ocfs2/file.c
fs/ocfs2/file.c
+4
-1
fs/ocfs2/journal.c
fs/ocfs2/journal.c
+7
-1
fs/ocfs2/journal.h
fs/ocfs2/journal.h
+11
-8
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2.h
+18
-4
fs/ocfs2/quota.h
fs/ocfs2/quota.h
+0
-1
fs/ocfs2/quota_global.c
fs/ocfs2/quota_global.c
+72
-62
fs/ocfs2/quota_local.c
fs/ocfs2/quota_local.c
+94
-16
fs/ocfs2/stack_o2cb.c
fs/ocfs2/stack_o2cb.c
+2
-1
fs/ocfs2/super.c
fs/ocfs2/super.c
+26
-4
fs/ocfs2/xattr.c
fs/ocfs2/xattr.c
+2
-1
include/linux/perf_counter.h
include/linux/perf_counter.h
+38
-11
include/linux/wait.h
include/linux/wait.h
+8
-1
kernel/futex.c
kernel/futex.c
+22
-6
kernel/futex_compat.c
kernel/futex_compat.c
+4
-2
kernel/irq/manage.c
kernel/irq/manage.c
+7
-10
kernel/perf_counter.c
kernel/perf_counter.c
+236
-102
kernel/wait.c
kernel/wait.c
+3
-2
net/socket.c
net/socket.c
+1
-1
tools/perf/Makefile
tools/perf/Makefile
+18
-11
tools/perf/builtin-list.c
tools/perf/builtin-list.c
+2
-1
tools/perf/builtin-record.c
tools/perf/builtin-record.c
+58
-37
tools/perf/builtin-report.c
tools/perf/builtin-report.c
+7
-5
tools/perf/util/parse-events.c
tools/perf/util/parse-events.c
+10
-0
tools/perf/util/symbol.c
tools/perf/util/symbol.c
+2
-15
tools/perf/util/symbol.h
tools/perf/util/symbol.h
+24
-0
未找到文件。
Makefile
浏览文件 @
60e0a4c7
VERSION
=
2
VERSION
=
2
PATCHLEVEL
=
6
PATCHLEVEL
=
6
SUBLEVEL
=
31
SUBLEVEL
=
31
EXTRAVERSION
=
-rc
5
EXTRAVERSION
=
-rc
6
NAME
=
Man-Eating Seals of Antiquity
NAME
=
Man-Eating Seals of Antiquity
# *DOCUMENTATION*
# *DOCUMENTATION*
...
...
arch/sh/boards/mach-se/7724/setup.c
浏览文件 @
60e0a4c7
...
@@ -246,7 +246,7 @@ static struct platform_device ceu1_device = {
...
@@ -246,7 +246,7 @@ static struct platform_device ceu1_device = {
},
},
};
};
/* KEYSC */
/* KEYSC
in SoC (Needs SW33-2 set to ON)
*/
static
struct
sh_keysc_info
keysc_info
=
{
static
struct
sh_keysc_info
keysc_info
=
{
.
mode
=
SH_KEYSC_MODE_1
,
.
mode
=
SH_KEYSC_MODE_1
,
.
scan_timing
=
10
,
.
scan_timing
=
10
,
...
@@ -263,12 +263,13 @@ static struct sh_keysc_info keysc_info = {
...
@@ -263,12 +263,13 @@ static struct sh_keysc_info keysc_info = {
static
struct
resource
keysc_resources
[]
=
{
static
struct
resource
keysc_resources
[]
=
{
[
0
]
=
{
[
0
]
=
{
.
start
=
0x1a204000
,
.
name
=
"KEYSC"
,
.
end
=
0x1a20400f
,
.
start
=
0x044b0000
,
.
end
=
0x044b000f
,
.
flags
=
IORESOURCE_MEM
,
.
flags
=
IORESOURCE_MEM
,
},
},
[
1
]
=
{
[
1
]
=
{
.
start
=
IRQ0_KEY
,
.
start
=
79
,
.
flags
=
IORESOURCE_IRQ
,
.
flags
=
IORESOURCE_IRQ
,
},
},
};
};
...
...
arch/sh/kernel/cpu/shmobile/sleep.S
浏览文件 @
60e0a4c7
...
@@ -26,8 +26,30 @@ ENTRY(sh_mobile_standby)
...
@@ -26,8 +26,30 @@ ENTRY(sh_mobile_standby)
tst
#
SUSP_SH_SF
,
r0
tst
#
SUSP_SH_SF
,
r0
bt
skip_set_sf
bt
skip_set_sf
#ifdef CONFIG_CPU_SUBTYPE_SH7724
/
*
DBSC
:
put
memory
in
self
-
refresh
mode
*/
/
*
SDRAM
:
disable
power
down
and
put
in
self
-
refresh
mode
*/
mov.l
dben_reg
,
r4
mov.l
dben_data0
,
r1
mov.l
r1
,
@
r4
mov.l
dbrfpdn0_reg
,
r4
mov.l
dbrfpdn0_data0
,
r1
mov.l
r1
,
@
r4
mov.l
dbcmdcnt_reg
,
r4
mov.l
dbcmdcnt_data0
,
r1
mov.l
r1
,
@
r4
mov.l
dbcmdcnt_reg
,
r4
mov.l
dbcmdcnt_data1
,
r1
mov.l
r1
,
@
r4
mov.l
dbrfpdn0_reg
,
r4
mov.l
dbrfpdn0_data1
,
r1
mov.l
r1
,
@
r4
#else
/
*
SBSC
:
disable
power
down
and
put
in
self
-
refresh
mode
*/
mov.l
1
f
,
r4
mov.l
1
f
,
r4
mov.l
2
f
,
r1
mov.l
2
f
,
r1
mov.l
@
r4
,
r2
mov.l
@
r4
,
r2
...
@@ -35,6 +57,7 @@ ENTRY(sh_mobile_standby)
...
@@ -35,6 +57,7 @@ ENTRY(sh_mobile_standby)
mov.l
3
f
,
r3
mov.l
3
f
,
r3
and
r3
,
r2
and
r3
,
r2
mov.l
r2
,
@
r4
mov.l
r2
,
@
r4
#endif
skip_set_sf
:
skip_set_sf
:
tst
#
SUSP_SH_SLEEP
,
r0
tst
#
SUSP_SH_SLEEP
,
r0
...
@@ -84,7 +107,36 @@ done_sleep:
...
@@ -84,7 +107,36 @@ done_sleep:
tst
#
SUSP_SH_SF
,
r0
tst
#
SUSP_SH_SF
,
r0
bt
skip_restore_sf
bt
skip_restore_sf
/
*
SDRAM
:
set
auto
-
refresh
mode
*/
#ifdef CONFIG_CPU_SUBTYPE_SH7724
/
*
DBSC
:
put
memory
in
auto
-
refresh
mode
*/
mov.l
dbrfpdn0_reg
,
r4
mov.l
dbrfpdn0_data0
,
r1
mov.l
r1
,
@
r4
/
*
sleep
140
ns
*/
nop
nop
nop
nop
mov.l
dbcmdcnt_reg
,
r4
mov.l
dbcmdcnt_data0
,
r1
mov.l
r1
,
@
r4
mov.l
dbcmdcnt_reg
,
r4
mov.l
dbcmdcnt_data1
,
r1
mov.l
r1
,
@
r4
mov.l
dben_reg
,
r4
mov.l
dben_data1
,
r1
mov.l
r1
,
@
r4
mov.l
dbrfpdn0_reg
,
r4
mov.l
dbrfpdn0_data2
,
r1
mov.l
r1
,
@
r4
#else
/
*
SBSC
:
set
auto
-
refresh
mode
*/
mov.l
1
f
,
r4
mov.l
1
f
,
r4
mov.l
@
r4
,
r2
mov.l
@
r4
,
r2
mov.l
4
f
,
r3
mov.l
4
f
,
r3
...
@@ -98,15 +150,29 @@ done_sleep:
...
@@ -98,15 +150,29 @@ done_sleep:
add
r4
,
r3
add
r4
,
r3
or
r2
,
r3
or
r2
,
r3
mov.l
r3
,
@
r1
mov.l
r3
,
@
r1
#endif
skip_restore_sf
:
skip_restore_sf
:
rts
rts
nop
nop
.
balign
4
.
balign
4
#ifdef CONFIG_CPU_SUBTYPE_SH7724
dben_reg
:
.
long
0xfd000010
/*
DBEN
*/
dben_data0
:
.
long
0
dben_data1
:
.
long
1
dbrfpdn0_reg
:
.
long
0xfd000040
/*
DBRFPDN0
*/
dbrfpdn0_data0
:
.
long
0
dbrfpdn0_data1
:
.
long
1
dbrfpdn0_data2
:
.
long
0x00010000
dbcmdcnt_reg
:
.
long
0xfd000014
/*
DBCMDCNT
*/
dbcmdcnt_data0
:
.
long
2
dbcmdcnt_data1
:
.
long
4
#else
1
:
.
long
0xfe400008
/*
SDCR0
*/
1
:
.
long
0xfe400008
/*
SDCR0
*/
2
:
.
long
0x00000400
2
:
.
long
0x00000400
3
:
.
long
0xffff7fff
3
:
.
long
0xffff7fff
4
:
.
long
0xfffffbff
4
:
.
long
0xfffffbff
#endif
5
:
.
long
0xa4150020
/*
STBCR
*/
5
:
.
long
0xa4150020
/*
STBCR
*/
6
:
.
long
0xfe40001c
/*
RTCOR
*/
6
:
.
long
0xfe40001c
/*
RTCOR
*/
7
:
.
long
0xfe400018
/*
RTCNT
*/
7
:
.
long
0xfe400018
/*
RTCNT
*/
...
...
arch/x86/Kconfig
浏览文件 @
60e0a4c7
...
@@ -24,6 +24,7 @@ config X86
...
@@ -24,6 +24,7 @@ config X86
select HAVE_UNSTABLE_SCHED_CLOCK
select HAVE_UNSTABLE_SCHED_CLOCK
select HAVE_IDE
select HAVE_IDE
select HAVE_OPROFILE
select HAVE_OPROFILE
select HAVE_PERF_COUNTERS if (!M386 && !M486)
select HAVE_IOREMAP_PROT
select HAVE_IOREMAP_PROT
select HAVE_KPROBES
select HAVE_KPROBES
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARCH_WANT_OPTIONAL_GPIOLIB
...
@@ -742,7 +743,6 @@ config X86_UP_IOAPIC
...
@@ -742,7 +743,6 @@ config X86_UP_IOAPIC
config X86_LOCAL_APIC
config X86_LOCAL_APIC
def_bool y
def_bool y
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
select HAVE_PERF_COUNTERS if (!M386 && !M486)
config X86_IO_APIC
config X86_IO_APIC
def_bool y
def_bool y
...
...
arch/x86/kernel/cpu/amd.c
浏览文件 @
60e0a4c7
...
@@ -400,6 +400,13 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
...
@@ -400,6 +400,13 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
level
=
cpuid_eax
(
1
);
level
=
cpuid_eax
(
1
);
if
((
level
>=
0x0f48
&&
level
<
0x0f50
)
||
level
>=
0x0f58
)
if
((
level
>=
0x0f48
&&
level
<
0x0f50
)
||
level
>=
0x0f58
)
set_cpu_cap
(
c
,
X86_FEATURE_REP_GOOD
);
set_cpu_cap
(
c
,
X86_FEATURE_REP_GOOD
);
/*
* Some BIOSes incorrectly force this feature, but only K8
* revision D (model = 0x14) and later actually support it.
*/
if
(
c
->
x86_model
<
0x14
)
clear_cpu_cap
(
c
,
X86_FEATURE_LAHF_LM
);
}
}
if
(
c
->
x86
==
0x10
||
c
->
x86
==
0x11
)
if
(
c
->
x86
==
0x10
||
c
->
x86
==
0x11
)
set_cpu_cap
(
c
,
X86_FEATURE_REP_GOOD
);
set_cpu_cap
(
c
,
X86_FEATURE_REP_GOOD
);
...
...
arch/x86/kernel/cpu/common.c
浏览文件 @
60e0a4c7
...
@@ -59,7 +59,30 @@ void __init setup_cpu_local_masks(void)
...
@@ -59,7 +59,30 @@ void __init setup_cpu_local_masks(void)
alloc_bootmem_cpumask_var
(
&
cpu_sibling_setup_mask
);
alloc_bootmem_cpumask_var
(
&
cpu_sibling_setup_mask
);
}
}
static
const
struct
cpu_dev
*
this_cpu
__cpuinitdata
;
static
void
__cpuinit
default_init
(
struct
cpuinfo_x86
*
c
)
{
#ifdef CONFIG_X86_64
display_cacheinfo
(
c
);
#else
/* Not much we can do here... */
/* Check if at least it has cpuid */
if
(
c
->
cpuid_level
==
-
1
)
{
/* No cpuid. It must be an ancient CPU */
if
(
c
->
x86
==
4
)
strcpy
(
c
->
x86_model_id
,
"486"
);
else
if
(
c
->
x86
==
3
)
strcpy
(
c
->
x86_model_id
,
"386"
);
}
#endif
}
static
const
struct
cpu_dev
__cpuinitconst
default_cpu
=
{
.
c_init
=
default_init
,
.
c_vendor
=
"Unknown"
,
.
c_x86_vendor
=
X86_VENDOR_UNKNOWN
,
};
static
const
struct
cpu_dev
*
this_cpu
__cpuinitdata
=
&
default_cpu
;
DEFINE_PER_CPU_PAGE_ALIGNED
(
struct
gdt_page
,
gdt_page
)
=
{
.
gdt
=
{
DEFINE_PER_CPU_PAGE_ALIGNED
(
struct
gdt_page
,
gdt_page
)
=
{
.
gdt
=
{
#ifdef CONFIG_X86_64
#ifdef CONFIG_X86_64
...
@@ -332,29 +355,6 @@ void switch_to_new_gdt(int cpu)
...
@@ -332,29 +355,6 @@ void switch_to_new_gdt(int cpu)
static
const
struct
cpu_dev
*
__cpuinitdata
cpu_devs
[
X86_VENDOR_NUM
]
=
{};
static
const
struct
cpu_dev
*
__cpuinitdata
cpu_devs
[
X86_VENDOR_NUM
]
=
{};
static
void
__cpuinit
default_init
(
struct
cpuinfo_x86
*
c
)
{
#ifdef CONFIG_X86_64
display_cacheinfo
(
c
);
#else
/* Not much we can do here... */
/* Check if at least it has cpuid */
if
(
c
->
cpuid_level
==
-
1
)
{
/* No cpuid. It must be an ancient CPU */
if
(
c
->
x86
==
4
)
strcpy
(
c
->
x86_model_id
,
"486"
);
else
if
(
c
->
x86
==
3
)
strcpy
(
c
->
x86_model_id
,
"386"
);
}
#endif
}
static
const
struct
cpu_dev
__cpuinitconst
default_cpu
=
{
.
c_init
=
default_init
,
.
c_vendor
=
"Unknown"
,
.
c_x86_vendor
=
X86_VENDOR_UNKNOWN
,
};
static
void
__cpuinit
get_model_name
(
struct
cpuinfo_x86
*
c
)
static
void
__cpuinit
get_model_name
(
struct
cpuinfo_x86
*
c
)
{
{
unsigned
int
*
v
;
unsigned
int
*
v
;
...
...
arch/x86/kernel/cpu/mcheck/therm_throt.c
浏览文件 @
60e0a4c7
...
@@ -36,6 +36,7 @@
...
@@ -36,6 +36,7 @@
static
DEFINE_PER_CPU
(
__u64
,
next_check
)
=
INITIAL_JIFFIES
;
static
DEFINE_PER_CPU
(
__u64
,
next_check
)
=
INITIAL_JIFFIES
;
static
DEFINE_PER_CPU
(
unsigned
long
,
thermal_throttle_count
);
static
DEFINE_PER_CPU
(
unsigned
long
,
thermal_throttle_count
);
static
DEFINE_PER_CPU
(
bool
,
thermal_throttle_active
);
static
atomic_t
therm_throt_en
=
ATOMIC_INIT
(
0
);
static
atomic_t
therm_throt_en
=
ATOMIC_INIT
(
0
);
...
@@ -96,24 +97,27 @@ static int therm_throt_process(int curr)
...
@@ -96,24 +97,27 @@ static int therm_throt_process(int curr)
{
{
unsigned
int
cpu
=
smp_processor_id
();
unsigned
int
cpu
=
smp_processor_id
();
__u64
tmp_jiffs
=
get_jiffies_64
();
__u64
tmp_jiffs
=
get_jiffies_64
();
bool
was_throttled
=
__get_cpu_var
(
thermal_throttle_active
);
bool
is_throttled
=
__get_cpu_var
(
thermal_throttle_active
)
=
curr
;
if
(
curr
)
if
(
is_throttled
)
__get_cpu_var
(
thermal_throttle_count
)
++
;
__get_cpu_var
(
thermal_throttle_count
)
++
;
if
(
time_before64
(
tmp_jiffs
,
__get_cpu_var
(
next_check
)))
if
(
!
(
was_throttled
^
is_throttled
)
&&
time_before64
(
tmp_jiffs
,
__get_cpu_var
(
next_check
)))
return
0
;
return
0
;
__get_cpu_var
(
next_check
)
=
tmp_jiffs
+
CHECK_INTERVAL
;
__get_cpu_var
(
next_check
)
=
tmp_jiffs
+
CHECK_INTERVAL
;
/* if we just entered the thermal event */
/* if we just entered the thermal event */
if
(
curr
)
{
if
(
is_throttled
)
{
printk
(
KERN_CRIT
"CPU%d: Temperature above threshold, "
printk
(
KERN_CRIT
"CPU%d: Temperature above threshold, "
"cpu clock throttled (total events = %lu)
\n
"
,
cpu
,
"cpu clock throttled (total events = %lu)
\n
"
,
__get_cpu_var
(
thermal_throttle_count
));
cpu
,
__get_cpu_var
(
thermal_throttle_count
));
add_taint
(
TAINT_MACHINE_CHECK
);
add_taint
(
TAINT_MACHINE_CHECK
);
}
else
{
}
else
if
(
was_throttled
)
{
printk
(
KERN_
CRIT
"CPU%d: Temperature/speed normal
\n
"
,
cpu
);
printk
(
KERN_
INFO
"CPU%d: Temperature/speed normal
\n
"
,
cpu
);
}
}
return
1
;
return
1
;
...
...
arch/x86/kernel/cpu/perf_counter.c
浏览文件 @
60e0a4c7
...
@@ -55,6 +55,7 @@ struct x86_pmu {
...
@@ -55,6 +55,7 @@ struct x86_pmu {
int
num_counters_fixed
;
int
num_counters_fixed
;
int
counter_bits
;
int
counter_bits
;
u64
counter_mask
;
u64
counter_mask
;
int
apic
;
u64
max_period
;
u64
max_period
;
u64
intel_ctrl
;
u64
intel_ctrl
;
};
};
...
@@ -72,8 +73,8 @@ static const u64 p6_perfmon_event_map[] =
...
@@ -72,8 +73,8 @@ static const u64 p6_perfmon_event_map[] =
{
{
[
PERF_COUNT_HW_CPU_CYCLES
]
=
0x0079
,
[
PERF_COUNT_HW_CPU_CYCLES
]
=
0x0079
,
[
PERF_COUNT_HW_INSTRUCTIONS
]
=
0x00c0
,
[
PERF_COUNT_HW_INSTRUCTIONS
]
=
0x00c0
,
[
PERF_COUNT_HW_CACHE_REFERENCES
]
=
0x0
000
,
[
PERF_COUNT_HW_CACHE_REFERENCES
]
=
0x0
f2e
,
[
PERF_COUNT_HW_CACHE_MISSES
]
=
0x0
000
,
[
PERF_COUNT_HW_CACHE_MISSES
]
=
0x0
12e
,
[
PERF_COUNT_HW_BRANCH_INSTRUCTIONS
]
=
0x00c4
,
[
PERF_COUNT_HW_BRANCH_INSTRUCTIONS
]
=
0x00c4
,
[
PERF_COUNT_HW_BRANCH_MISSES
]
=
0x00c5
,
[
PERF_COUNT_HW_BRANCH_MISSES
]
=
0x00c5
,
[
PERF_COUNT_HW_BUS_CYCLES
]
=
0x0062
,
[
PERF_COUNT_HW_BUS_CYCLES
]
=
0x0062
,
...
@@ -613,6 +614,7 @@ static DEFINE_MUTEX(pmc_reserve_mutex);
...
@@ -613,6 +614,7 @@ static DEFINE_MUTEX(pmc_reserve_mutex);
static
bool
reserve_pmc_hardware
(
void
)
static
bool
reserve_pmc_hardware
(
void
)
{
{
#ifdef CONFIG_X86_LOCAL_APIC
int
i
;
int
i
;
if
(
nmi_watchdog
==
NMI_LOCAL_APIC
)
if
(
nmi_watchdog
==
NMI_LOCAL_APIC
)
...
@@ -627,9 +629,11 @@ static bool reserve_pmc_hardware(void)
...
@@ -627,9 +629,11 @@ static bool reserve_pmc_hardware(void)
if
(
!
reserve_evntsel_nmi
(
x86_pmu
.
eventsel
+
i
))
if
(
!
reserve_evntsel_nmi
(
x86_pmu
.
eventsel
+
i
))
goto
eventsel_fail
;
goto
eventsel_fail
;
}
}
#endif
return
true
;
return
true
;
#ifdef CONFIG_X86_LOCAL_APIC
eventsel_fail:
eventsel_fail:
for
(
i
--
;
i
>=
0
;
i
--
)
for
(
i
--
;
i
>=
0
;
i
--
)
release_evntsel_nmi
(
x86_pmu
.
eventsel
+
i
);
release_evntsel_nmi
(
x86_pmu
.
eventsel
+
i
);
...
@@ -644,10 +648,12 @@ static bool reserve_pmc_hardware(void)
...
@@ -644,10 +648,12 @@ static bool reserve_pmc_hardware(void)
enable_lapic_nmi_watchdog
();
enable_lapic_nmi_watchdog
();
return
false
;
return
false
;
#endif
}
}
static
void
release_pmc_hardware
(
void
)
static
void
release_pmc_hardware
(
void
)
{
{
#ifdef CONFIG_X86_LOCAL_APIC
int
i
;
int
i
;
for
(
i
=
0
;
i
<
x86_pmu
.
num_counters
;
i
++
)
{
for
(
i
=
0
;
i
<
x86_pmu
.
num_counters
;
i
++
)
{
...
@@ -657,6 +663,7 @@ static void release_pmc_hardware(void)
...
@@ -657,6 +663,7 @@ static void release_pmc_hardware(void)
if
(
nmi_watchdog
==
NMI_LOCAL_APIC
)
if
(
nmi_watchdog
==
NMI_LOCAL_APIC
)
enable_lapic_nmi_watchdog
();
enable_lapic_nmi_watchdog
();
#endif
}
}
static
void
hw_perf_counter_destroy
(
struct
perf_counter
*
counter
)
static
void
hw_perf_counter_destroy
(
struct
perf_counter
*
counter
)
...
@@ -748,6 +755,15 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
...
@@ -748,6 +755,15 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
hwc
->
sample_period
=
x86_pmu
.
max_period
;
hwc
->
sample_period
=
x86_pmu
.
max_period
;
hwc
->
last_period
=
hwc
->
sample_period
;
hwc
->
last_period
=
hwc
->
sample_period
;
atomic64_set
(
&
hwc
->
period_left
,
hwc
->
sample_period
);
atomic64_set
(
&
hwc
->
period_left
,
hwc
->
sample_period
);
}
else
{
/*
* If we have a PMU initialized but no APIC
* interrupts, we cannot sample hardware
* counters (user-space has to fall back and
* sample via a hrtimer based software counter):
*/
if
(
!
x86_pmu
.
apic
)
return
-
EOPNOTSUPP
;
}
}
counter
->
destroy
=
hw_perf_counter_destroy
;
counter
->
destroy
=
hw_perf_counter_destroy
;
...
@@ -1449,18 +1465,22 @@ void smp_perf_pending_interrupt(struct pt_regs *regs)
...
@@ -1449,18 +1465,22 @@ void smp_perf_pending_interrupt(struct pt_regs *regs)
void
set_perf_counter_pending
(
void
)
void
set_perf_counter_pending
(
void
)
{
{
#ifdef CONFIG_X86_LOCAL_APIC
apic
->
send_IPI_self
(
LOCAL_PENDING_VECTOR
);
apic
->
send_IPI_self
(
LOCAL_PENDING_VECTOR
);
#endif
}
}
void
perf_counters_lapic_init
(
void
)
void
perf_counters_lapic_init
(
void
)
{
{
if
(
!
x86_pmu_initialized
())
#ifdef CONFIG_X86_LOCAL_APIC
if
(
!
x86_pmu
.
apic
||
!
x86_pmu_initialized
())
return
;
return
;
/*
/*
* Always use NMI for PMU
* Always use NMI for PMU
*/
*/
apic_write
(
APIC_LVTPC
,
APIC_DM_NMI
);
apic_write
(
APIC_LVTPC
,
APIC_DM_NMI
);
#endif
}
}
static
int
__kprobes
static
int
__kprobes
...
@@ -1484,7 +1504,9 @@ perf_counter_nmi_handler(struct notifier_block *self,
...
@@ -1484,7 +1504,9 @@ perf_counter_nmi_handler(struct notifier_block *self,
regs
=
args
->
regs
;
regs
=
args
->
regs
;
#ifdef CONFIG_X86_LOCAL_APIC
apic_write
(
APIC_LVTPC
,
APIC_DM_NMI
);
apic_write
(
APIC_LVTPC
,
APIC_DM_NMI
);
#endif
/*
/*
* Can't rely on the handled return value to say it was our NMI, two
* Can't rely on the handled return value to say it was our NMI, two
* counters could trigger 'simultaneously' raising two back-to-back NMIs.
* counters could trigger 'simultaneously' raising two back-to-back NMIs.
...
@@ -1515,6 +1537,7 @@ static struct x86_pmu p6_pmu = {
...
@@ -1515,6 +1537,7 @@ static struct x86_pmu p6_pmu = {
.
event_map
=
p6_pmu_event_map
,
.
event_map
=
p6_pmu_event_map
,
.
raw_event
=
p6_pmu_raw_event
,
.
raw_event
=
p6_pmu_raw_event
,
.
max_events
=
ARRAY_SIZE
(
p6_perfmon_event_map
),
.
max_events
=
ARRAY_SIZE
(
p6_perfmon_event_map
),
.
apic
=
1
,
.
max_period
=
(
1ULL
<<
31
)
-
1
,
.
max_period
=
(
1ULL
<<
31
)
-
1
,
.
version
=
0
,
.
version
=
0
,
.
num_counters
=
2
,
.
num_counters
=
2
,
...
@@ -1541,6 +1564,7 @@ static struct x86_pmu intel_pmu = {
...
@@ -1541,6 +1564,7 @@ static struct x86_pmu intel_pmu = {
.
event_map
=
intel_pmu_event_map
,
.
event_map
=
intel_pmu_event_map
,
.
raw_event
=
intel_pmu_raw_event
,
.
raw_event
=
intel_pmu_raw_event
,
.
max_events
=
ARRAY_SIZE
(
intel_perfmon_event_map
),
.
max_events
=
ARRAY_SIZE
(
intel_perfmon_event_map
),
.
apic
=
1
,
/*
/*
* Intel PMCs cannot be accessed sanely above 32 bit width,
* Intel PMCs cannot be accessed sanely above 32 bit width,
* so we install an artificial 1<<31 period regardless of
* so we install an artificial 1<<31 period regardless of
...
@@ -1564,6 +1588,7 @@ static struct x86_pmu amd_pmu = {
...
@@ -1564,6 +1588,7 @@ static struct x86_pmu amd_pmu = {
.
num_counters
=
4
,
.
num_counters
=
4
,
.
counter_bits
=
48
,
.
counter_bits
=
48
,
.
counter_mask
=
(
1ULL
<<
48
)
-
1
,
.
counter_mask
=
(
1ULL
<<
48
)
-
1
,
.
apic
=
1
,
/* use highest bit to detect overflow */
/* use highest bit to detect overflow */
.
max_period
=
(
1ULL
<<
47
)
-
1
,
.
max_period
=
(
1ULL
<<
47
)
-
1
,
};
};
...
@@ -1589,13 +1614,14 @@ static int p6_pmu_init(void)
...
@@ -1589,13 +1614,14 @@ static int p6_pmu_init(void)
return
-
ENODEV
;
return
-
ENODEV
;
}
}
x86_pmu
=
p6_pmu
;
if
(
!
cpu_has_apic
)
{
if
(
!
cpu_has_apic
)
{
pr_info
(
"no Local APIC, try rebooting with lapic"
);
pr_info
(
"no APIC, boot with the
\"
lapic
\"
boot parameter to force-enable it.
\n
"
);
return
-
ENODEV
;
pr_info
(
"no hardware sampling interrupt available.
\n
"
);
x86_pmu
.
apic
=
0
;
}
}
x86_pmu
=
p6_pmu
;
return
0
;
return
0
;
}
}
...
...
arch/x86/kernel/reboot.c
浏览文件 @
60e0a4c7
...
@@ -418,20 +418,20 @@ static int __init set_pci_reboot(const struct dmi_system_id *d)
...
@@ -418,20 +418,20 @@ static int __init set_pci_reboot(const struct dmi_system_id *d)
}
}
static
struct
dmi_system_id
__initdata
pci_reboot_dmi_table
[]
=
{
static
struct
dmi_system_id
__initdata
pci_reboot_dmi_table
[]
=
{
{
/* Handle problems with rebooting on Apple MacBook5
,2
*/
{
/* Handle problems with rebooting on Apple MacBook5 */
.
callback
=
set_pci_reboot
,
.
callback
=
set_pci_reboot
,
.
ident
=
"Apple MacBook"
,
.
ident
=
"Apple MacBook
5
"
,
.
matches
=
{
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Apple Inc."
),
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Apple Inc."
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"MacBook5
,2
"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"MacBook5"
),
},
},
},
},
{
/* Handle problems with rebooting on Apple MacBookPro5
,1
*/
{
/* Handle problems with rebooting on Apple MacBookPro5 */
.
callback
=
set_pci_reboot
,
.
callback
=
set_pci_reboot
,
.
ident
=
"Apple MacBookPro5
,1
"
,
.
ident
=
"Apple MacBookPro5"
,
.
matches
=
{
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Apple Inc."
),
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Apple Inc."
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"MacBookPro5
,1
"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"MacBookPro5"
),
},
},
},
},
{
}
{
}
...
...
drivers/clocksource/sh_cmt.c
浏览文件 @
60e0a4c7
...
@@ -40,6 +40,7 @@ struct sh_cmt_priv {
...
@@ -40,6 +40,7 @@ struct sh_cmt_priv {
struct
platform_device
*
pdev
;
struct
platform_device
*
pdev
;
unsigned
long
flags
;
unsigned
long
flags
;
unsigned
long
flags_suspend
;
unsigned
long
match_value
;
unsigned
long
match_value
;
unsigned
long
next_match_value
;
unsigned
long
next_match_value
;
unsigned
long
max_match_value
;
unsigned
long
max_match_value
;
...
@@ -667,11 +668,38 @@ static int __devexit sh_cmt_remove(struct platform_device *pdev)
...
@@ -667,11 +668,38 @@ static int __devexit sh_cmt_remove(struct platform_device *pdev)
return
-
EBUSY
;
/* cannot unregister clockevent and clocksource */
return
-
EBUSY
;
/* cannot unregister clockevent and clocksource */
}
}
static
int
sh_cmt_suspend
(
struct
device
*
dev
)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
sh_cmt_priv
*
p
=
platform_get_drvdata
(
pdev
);
/* save flag state and stop CMT channel */
p
->
flags_suspend
=
p
->
flags
;
sh_cmt_stop
(
p
,
p
->
flags
);
return
0
;
}
static
int
sh_cmt_resume
(
struct
device
*
dev
)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
sh_cmt_priv
*
p
=
platform_get_drvdata
(
pdev
);
/* start CMT channel from saved state */
sh_cmt_start
(
p
,
p
->
flags_suspend
);
return
0
;
}
static
struct
dev_pm_ops
sh_cmt_dev_pm_ops
=
{
.
suspend
=
sh_cmt_suspend
,
.
resume
=
sh_cmt_resume
,
};
static
struct
platform_driver
sh_cmt_device_driver
=
{
static
struct
platform_driver
sh_cmt_device_driver
=
{
.
probe
=
sh_cmt_probe
,
.
probe
=
sh_cmt_probe
,
.
remove
=
__devexit_p
(
sh_cmt_remove
),
.
remove
=
__devexit_p
(
sh_cmt_remove
),
.
driver
=
{
.
driver
=
{
.
name
=
"sh_cmt"
,
.
name
=
"sh_cmt"
,
.
pm
=
&
sh_cmt_dev_pm_ops
,
}
}
};
};
...
...
drivers/md/md.c
浏览文件 @
60e0a4c7
...
@@ -359,6 +359,7 @@ static mddev_t * mddev_find(dev_t unit)
...
@@ -359,6 +359,7 @@ static mddev_t * mddev_find(dev_t unit)
else
else
new
->
md_minor
=
MINOR
(
unit
)
>>
MdpMinorShift
;
new
->
md_minor
=
MINOR
(
unit
)
>>
MdpMinorShift
;
mutex_init
(
&
new
->
open_mutex
);
mutex_init
(
&
new
->
reconfig_mutex
);
mutex_init
(
&
new
->
reconfig_mutex
);
INIT_LIST_HEAD
(
&
new
->
disks
);
INIT_LIST_HEAD
(
&
new
->
disks
);
INIT_LIST_HEAD
(
&
new
->
all_mddevs
);
INIT_LIST_HEAD
(
&
new
->
all_mddevs
);
...
@@ -1974,19 +1975,16 @@ static void md_update_sb(mddev_t * mddev, int force_change)
...
@@ -1974,19 +1975,16 @@ static void md_update_sb(mddev_t * mddev, int force_change)
/* otherwise we have to go forward and ... */
/* otherwise we have to go forward and ... */
mddev
->
events
++
;
mddev
->
events
++
;
if
(
!
mddev
->
in_sync
||
mddev
->
recovery_cp
!=
MaxSector
)
{
/* not clean */
if
(
!
mddev
->
in_sync
||
mddev
->
recovery_cp
!=
MaxSector
)
{
/* not clean */
/* .. if the array isn't clean,
insist on an odd 'events' */
/* .. if the array isn't clean,
an 'even' event must also go
if
((
mddev
->
events
&
1
)
==
0
)
{
* to spares. */
mddev
->
events
++
;
if
((
mddev
->
events
&
1
)
==
0
)
nospares
=
0
;
nospares
=
0
;
}
}
else
{
}
else
{
/* otherwise insist on an even 'events' (for clean states) */
/* otherwise an 'odd' event must go to spares */
if
((
mddev
->
events
&
1
))
{
if
((
mddev
->
events
&
1
))
mddev
->
events
++
;
nospares
=
0
;
nospares
=
0
;
}
}
}
}
}
if
(
!
mddev
->
events
)
{
if
(
!
mddev
->
events
)
{
/*
/*
...
@@ -3601,6 +3599,7 @@ max_sync_store(mddev_t *mddev, const char *buf, size_t len)
...
@@ -3601,6 +3599,7 @@ max_sync_store(mddev_t *mddev, const char *buf, size_t len)
if
(
max
<
mddev
->
resync_min
)
if
(
max
<
mddev
->
resync_min
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
max
<
mddev
->
resync_max
&&
if
(
max
<
mddev
->
resync_max
&&
mddev
->
ro
==
0
&&
test_bit
(
MD_RECOVERY_RUNNING
,
&
mddev
->
recovery
))
test_bit
(
MD_RECOVERY_RUNNING
,
&
mddev
->
recovery
))
return
-
EBUSY
;
return
-
EBUSY
;
...
@@ -4304,12 +4303,11 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
...
@@ -4304,12 +4303,11 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
struct
gendisk
*
disk
=
mddev
->
gendisk
;
struct
gendisk
*
disk
=
mddev
->
gendisk
;
mdk_rdev_t
*
rdev
;
mdk_rdev_t
*
rdev
;
mutex_lock
(
&
mddev
->
open_mutex
);
if
(
atomic_read
(
&
mddev
->
openers
)
>
is_open
)
{
if
(
atomic_read
(
&
mddev
->
openers
)
>
is_open
)
{
printk
(
"md: %s still in use.
\n
"
,
mdname
(
mddev
));
printk
(
"md: %s still in use.
\n
"
,
mdname
(
mddev
));
return
-
EBUSY
;
err
=
-
EBUSY
;
}
}
else
if
(
mddev
->
pers
)
{
if
(
mddev
->
pers
)
{
if
(
mddev
->
sync_thread
)
{
if
(
mddev
->
sync_thread
)
{
set_bit
(
MD_RECOVERY_FROZEN
,
&
mddev
->
recovery
);
set_bit
(
MD_RECOVERY_FROZEN
,
&
mddev
->
recovery
);
...
@@ -4367,7 +4365,10 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
...
@@ -4367,7 +4365,10 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
set_disk_ro
(
disk
,
1
);
set_disk_ro
(
disk
,
1
);
clear_bit
(
MD_RECOVERY_FROZEN
,
&
mddev
->
recovery
);
clear_bit
(
MD_RECOVERY_FROZEN
,
&
mddev
->
recovery
);
}
}
out:
mutex_unlock
(
&
mddev
->
open_mutex
);
if
(
err
)
return
err
;
/*
/*
* Free resources if final stop
* Free resources if final stop
*/
*/
...
@@ -4433,7 +4434,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
...
@@ -4433,7 +4434,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
blk_integrity_unregister
(
disk
);
blk_integrity_unregister
(
disk
);
md_new_event
(
mddev
);
md_new_event
(
mddev
);
sysfs_notify_dirent
(
mddev
->
sysfs_state
);
sysfs_notify_dirent
(
mddev
->
sysfs_state
);
out:
return
err
;
return
err
;
}
}
...
@@ -5518,12 +5518,12 @@ static int md_open(struct block_device *bdev, fmode_t mode)
...
@@ -5518,12 +5518,12 @@ static int md_open(struct block_device *bdev, fmode_t mode)
}
}
BUG_ON
(
mddev
!=
bdev
->
bd_disk
->
private_data
);
BUG_ON
(
mddev
!=
bdev
->
bd_disk
->
private_data
);
if
((
err
=
mutex_lock_interruptible
_nested
(
&
mddev
->
reconfig_mutex
,
1
)))
if
((
err
=
mutex_lock_interruptible
(
&
mddev
->
open_mutex
)))
goto
out
;
goto
out
;
err
=
0
;
err
=
0
;
atomic_inc
(
&
mddev
->
openers
);
atomic_inc
(
&
mddev
->
openers
);
m
ddev_unlock
(
mddev
);
m
utex_unlock
(
&
mddev
->
open_mutex
);
check_disk_change
(
bdev
);
check_disk_change
(
bdev
);
out:
out:
...
...
drivers/md/md.h
浏览文件 @
60e0a4c7
...
@@ -223,6 +223,16 @@ struct mddev_s
...
@@ -223,6 +223,16 @@ struct mddev_s
* so we don't loop trying */
* so we don't loop trying */
int
in_sync
;
/* know to not need resync */
int
in_sync
;
/* know to not need resync */
/* 'open_mutex' avoids races between 'md_open' and 'do_md_stop', so
* that we are never stopping an array while it is open.
* 'reconfig_mutex' protects all other reconfiguration.
* These locks are separate due to conflicting interactions
* with bdev->bd_mutex.
* Lock ordering is:
* reconfig_mutex -> bd_mutex : e.g. do_md_run -> revalidate_disk
* bd_mutex -> open_mutex: e.g. __blkdev_get -> md_open
*/
struct
mutex
open_mutex
;
struct
mutex
reconfig_mutex
;
struct
mutex
reconfig_mutex
;
atomic_t
active
;
/* general refcount */
atomic_t
active
;
/* general refcount */
atomic_t
openers
;
/* number of active opens */
atomic_t
openers
;
/* number of active opens */
...
...
drivers/md/raid5.c
浏览文件 @
60e0a4c7
...
@@ -3785,7 +3785,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
...
@@ -3785,7 +3785,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
conf
->
reshape_progress
<
raid5_size
(
mddev
,
0
,
0
))
{
conf
->
reshape_progress
<
raid5_size
(
mddev
,
0
,
0
))
{
sector_nr
=
raid5_size
(
mddev
,
0
,
0
)
sector_nr
=
raid5_size
(
mddev
,
0
,
0
)
-
conf
->
reshape_progress
;
-
conf
->
reshape_progress
;
}
else
if
(
mddev
->
delta_disks
>
0
&&
}
else
if
(
mddev
->
delta_disks
>
=
0
&&
conf
->
reshape_progress
>
0
)
conf
->
reshape_progress
>
0
)
sector_nr
=
conf
->
reshape_progress
;
sector_nr
=
conf
->
reshape_progress
;
sector_div
(
sector_nr
,
new_data_disks
);
sector_div
(
sector_nr
,
new_data_disks
);
...
@@ -4509,7 +4509,26 @@ static int run(mddev_t *mddev)
...
@@ -4509,7 +4509,26 @@ static int run(mddev_t *mddev)
(
old_disks
-
max_degraded
));
(
old_disks
-
max_degraded
));
/* here_old is the first stripe that we might need to read
/* here_old is the first stripe that we might need to read
* from */
* from */
if
(
here_new
>=
here_old
)
{
if
(
mddev
->
delta_disks
==
0
)
{
/* We cannot be sure it is safe to start an in-place
* reshape. It is only safe if user-space if monitoring
* and taking constant backups.
* mdadm always starts a situation like this in
* readonly mode so it can take control before
* allowing any writes. So just check for that.
*/
if
((
here_new
*
mddev
->
new_chunk_sectors
!=
here_old
*
mddev
->
chunk_sectors
)
||
mddev
->
ro
==
0
)
{
printk
(
KERN_ERR
"raid5: in-place reshape must be started"
" in read-only mode - aborting
\n
"
);
return
-
EINVAL
;
}
}
else
if
(
mddev
->
delta_disks
<
0
?
(
here_new
*
mddev
->
new_chunk_sectors
<=
here_old
*
mddev
->
chunk_sectors
)
:
(
here_new
*
mddev
->
new_chunk_sectors
>=
here_old
*
mddev
->
chunk_sectors
))
{
/* Reading from the same stripe as writing to - bad */
/* Reading from the same stripe as writing to - bad */
printk
(
KERN_ERR
"raid5: reshape_position too early for "
printk
(
KERN_ERR
"raid5: reshape_position too early for "
"auto-recovery - aborting.
\n
"
);
"auto-recovery - aborting.
\n
"
);
...
@@ -5078,8 +5097,15 @@ static void raid5_finish_reshape(mddev_t *mddev)
...
@@ -5078,8 +5097,15 @@ static void raid5_finish_reshape(mddev_t *mddev)
mddev
->
degraded
--
;
mddev
->
degraded
--
;
for
(
d
=
conf
->
raid_disks
;
for
(
d
=
conf
->
raid_disks
;
d
<
conf
->
raid_disks
-
mddev
->
delta_disks
;
d
<
conf
->
raid_disks
-
mddev
->
delta_disks
;
d
++
)
d
++
)
{
raid5_remove_disk
(
mddev
,
d
);
mdk_rdev_t
*
rdev
=
conf
->
disks
[
d
].
rdev
;
if
(
rdev
&&
raid5_remove_disk
(
mddev
,
d
)
==
0
)
{
char
nm
[
20
];
sprintf
(
nm
,
"rd%d"
,
rdev
->
raid_disk
);
sysfs_remove_link
(
&
mddev
->
kobj
,
nm
);
rdev
->
raid_disk
=
-
1
;
}
}
}
}
mddev
->
layout
=
conf
->
algorithm
;
mddev
->
layout
=
conf
->
algorithm
;
mddev
->
chunk_sectors
=
conf
->
chunk_sectors
;
mddev
->
chunk_sectors
=
conf
->
chunk_sectors
;
...
...
drivers/video/sh_mobile_lcdcfb.c
浏览文件 @
60e0a4c7
...
@@ -477,6 +477,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
...
@@ -477,6 +477,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
/* tell the board code to enable the panel */
/* tell the board code to enable the panel */
for
(
k
=
0
;
k
<
ARRAY_SIZE
(
priv
->
ch
);
k
++
)
{
for
(
k
=
0
;
k
<
ARRAY_SIZE
(
priv
->
ch
);
k
++
)
{
ch
=
&
priv
->
ch
[
k
];
ch
=
&
priv
->
ch
[
k
];
if
(
!
ch
->
enabled
)
continue
;
board_cfg
=
&
ch
->
cfg
.
board_cfg
;
board_cfg
=
&
ch
->
cfg
.
board_cfg
;
if
(
board_cfg
->
display_on
)
if
(
board_cfg
->
display_on
)
board_cfg
->
display_on
(
board_cfg
->
board_data
);
board_cfg
->
display_on
(
board_cfg
->
board_data
);
...
@@ -494,6 +497,8 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
...
@@ -494,6 +497,8 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
/* clean up deferred io and ask board code to disable panel */
/* clean up deferred io and ask board code to disable panel */
for
(
k
=
0
;
k
<
ARRAY_SIZE
(
priv
->
ch
);
k
++
)
{
for
(
k
=
0
;
k
<
ARRAY_SIZE
(
priv
->
ch
);
k
++
)
{
ch
=
&
priv
->
ch
[
k
];
ch
=
&
priv
->
ch
[
k
];
if
(
!
ch
->
enabled
)
continue
;
/* deferred io mode:
/* deferred io mode:
* flush frame, and wait for frame end interrupt
* flush frame, and wait for frame end interrupt
...
...
fs/ocfs2/alloc.c
浏览文件 @
60e0a4c7
...
@@ -1914,7 +1914,8 @@ static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec,
...
@@ -1914,7 +1914,8 @@ static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec,
* immediately to their right.
* immediately to their right.
*/
*/
left_clusters
=
le32_to_cpu
(
right_child_el
->
l_recs
[
0
].
e_cpos
);
left_clusters
=
le32_to_cpu
(
right_child_el
->
l_recs
[
0
].
e_cpos
);
if
(
ocfs2_is_empty_extent
(
&
right_child_el
->
l_recs
[
0
]))
{
if
(
!
ocfs2_rec_clusters
(
right_child_el
,
&
right_child_el
->
l_recs
[
0
]))
{
BUG_ON
(
right_child_el
->
l_tree_depth
);
BUG_ON
(
le16_to_cpu
(
right_child_el
->
l_next_free_rec
)
<=
1
);
BUG_ON
(
le16_to_cpu
(
right_child_el
->
l_next_free_rec
)
<=
1
);
left_clusters
=
le32_to_cpu
(
right_child_el
->
l_recs
[
1
].
e_cpos
);
left_clusters
=
le32_to_cpu
(
right_child_el
->
l_recs
[
1
].
e_cpos
);
}
}
...
@@ -2476,15 +2477,37 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
...
@@ -2476,15 +2477,37 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
return
ret
;
return
ret
;
}
}
static
void
ocfs2_update_edge_lengths
(
struct
inode
*
inode
,
handle_t
*
handle
,
static
int
ocfs2_update_edge_lengths
(
struct
inode
*
inode
,
handle_t
*
handle
,
struct
ocfs2_path
*
path
)
int
subtree_index
,
struct
ocfs2_path
*
path
)
{
{
int
i
,
idx
;
int
i
,
idx
,
ret
;
struct
ocfs2_extent_rec
*
rec
;
struct
ocfs2_extent_rec
*
rec
;
struct
ocfs2_extent_list
*
el
;
struct
ocfs2_extent_list
*
el
;
struct
ocfs2_extent_block
*
eb
;
struct
ocfs2_extent_block
*
eb
;
u32
range
;
u32
range
;
/*
* In normal tree rotation process, we will never touch the
* tree branch above subtree_index and ocfs2_extend_rotate_transaction
* doesn't reserve the credits for them either.
*
* But we do have a special case here which will update the rightmost
* records for all the bh in the path.
* So we have to allocate extra credits and access them.
*/
ret
=
ocfs2_extend_trans
(
handle
,
handle
->
h_buffer_credits
+
subtree_index
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out
;
}
ret
=
ocfs2_journal_access_path
(
inode
,
handle
,
path
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out
;
}
/* Path should always be rightmost. */
/* Path should always be rightmost. */
eb
=
(
struct
ocfs2_extent_block
*
)
path_leaf_bh
(
path
)
->
b_data
;
eb
=
(
struct
ocfs2_extent_block
*
)
path_leaf_bh
(
path
)
->
b_data
;
BUG_ON
(
eb
->
h_next_leaf_blk
!=
0ULL
);
BUG_ON
(
eb
->
h_next_leaf_blk
!=
0ULL
);
...
@@ -2505,6 +2528,8 @@ static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
...
@@ -2505,6 +2528,8 @@ static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
ocfs2_journal_dirty
(
handle
,
path
->
p_node
[
i
].
bh
);
ocfs2_journal_dirty
(
handle
,
path
->
p_node
[
i
].
bh
);
}
}
out:
return
ret
;
}
}
static
void
ocfs2_unlink_path
(
struct
inode
*
inode
,
handle_t
*
handle
,
static
void
ocfs2_unlink_path
(
struct
inode
*
inode
,
handle_t
*
handle
,
...
@@ -2717,7 +2742,12 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
...
@@ -2717,7 +2742,12 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
if
(
del_right_subtree
)
{
if
(
del_right_subtree
)
{
ocfs2_unlink_subtree
(
inode
,
handle
,
left_path
,
right_path
,
ocfs2_unlink_subtree
(
inode
,
handle
,
left_path
,
right_path
,
subtree_index
,
dealloc
);
subtree_index
,
dealloc
);
ocfs2_update_edge_lengths
(
inode
,
handle
,
left_path
);
ret
=
ocfs2_update_edge_lengths
(
inode
,
handle
,
subtree_index
,
left_path
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out
;
}
eb
=
(
struct
ocfs2_extent_block
*
)
path_leaf_bh
(
left_path
)
->
b_data
;
eb
=
(
struct
ocfs2_extent_block
*
)
path_leaf_bh
(
left_path
)
->
b_data
;
ocfs2_et_set_last_eb_blk
(
et
,
le64_to_cpu
(
eb
->
h_blkno
));
ocfs2_et_set_last_eb_blk
(
et
,
le64_to_cpu
(
eb
->
h_blkno
));
...
@@ -3034,7 +3064,12 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
...
@@ -3034,7 +3064,12 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
ocfs2_unlink_subtree
(
inode
,
handle
,
left_path
,
path
,
ocfs2_unlink_subtree
(
inode
,
handle
,
left_path
,
path
,
subtree_index
,
dealloc
);
subtree_index
,
dealloc
);
ocfs2_update_edge_lengths
(
inode
,
handle
,
left_path
);
ret
=
ocfs2_update_edge_lengths
(
inode
,
handle
,
subtree_index
,
left_path
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out
;
}
eb
=
(
struct
ocfs2_extent_block
*
)
path_leaf_bh
(
left_path
)
->
b_data
;
eb
=
(
struct
ocfs2_extent_block
*
)
path_leaf_bh
(
left_path
)
->
b_data
;
ocfs2_et_set_last_eb_blk
(
et
,
le64_to_cpu
(
eb
->
h_blkno
));
ocfs2_et_set_last_eb_blk
(
et
,
le64_to_cpu
(
eb
->
h_blkno
));
...
...
fs/ocfs2/aops.c
浏览文件 @
60e0a4c7
...
@@ -193,6 +193,7 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
...
@@ -193,6 +193,7 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
(
unsigned
long
long
)
OCFS2_I
(
inode
)
->
ip_blkno
);
(
unsigned
long
long
)
OCFS2_I
(
inode
)
->
ip_blkno
);
mlog
(
ML_ERROR
,
"Size %llu, clusters %u
\n
"
,
(
unsigned
long
long
)
i_size_read
(
inode
),
OCFS2_I
(
inode
)
->
ip_clusters
);
mlog
(
ML_ERROR
,
"Size %llu, clusters %u
\n
"
,
(
unsigned
long
long
)
i_size_read
(
inode
),
OCFS2_I
(
inode
)
->
ip_clusters
);
dump_stack
();
dump_stack
();
goto
bail
;
}
}
past_eof
=
ocfs2_blocks_for_bytes
(
inode
->
i_sb
,
i_size_read
(
inode
));
past_eof
=
ocfs2_blocks_for_bytes
(
inode
->
i_sb
,
i_size_read
(
inode
));
...
@@ -894,18 +895,17 @@ struct ocfs2_write_cluster_desc {
...
@@ -894,18 +895,17 @@ struct ocfs2_write_cluster_desc {
*/
*/
unsigned
c_new
;
unsigned
c_new
;
unsigned
c_unwritten
;
unsigned
c_unwritten
;
unsigned
c_needs_zero
;
};
};
static
inline
int
ocfs2_should_zero_cluster
(
struct
ocfs2_write_cluster_desc
*
d
)
{
return
d
->
c_new
||
d
->
c_unwritten
;
}
struct
ocfs2_write_ctxt
{
struct
ocfs2_write_ctxt
{
/* Logical cluster position / len of write */
/* Logical cluster position / len of write */
u32
w_cpos
;
u32
w_cpos
;
u32
w_clen
;
u32
w_clen
;
/* First cluster allocated in a nonsparse extend */
u32
w_first_new_cpos
;
struct
ocfs2_write_cluster_desc
w_desc
[
OCFS2_MAX_CLUSTERS_PER_PAGE
];
struct
ocfs2_write_cluster_desc
w_desc
[
OCFS2_MAX_CLUSTERS_PER_PAGE
];
/*
/*
...
@@ -983,6 +983,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
...
@@ -983,6 +983,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
return
-
ENOMEM
;
return
-
ENOMEM
;
wc
->
w_cpos
=
pos
>>
osb
->
s_clustersize_bits
;
wc
->
w_cpos
=
pos
>>
osb
->
s_clustersize_bits
;
wc
->
w_first_new_cpos
=
UINT_MAX
;
cend
=
(
pos
+
len
-
1
)
>>
osb
->
s_clustersize_bits
;
cend
=
(
pos
+
len
-
1
)
>>
osb
->
s_clustersize_bits
;
wc
->
w_clen
=
cend
-
wc
->
w_cpos
+
1
;
wc
->
w_clen
=
cend
-
wc
->
w_cpos
+
1
;
get_bh
(
di_bh
);
get_bh
(
di_bh
);
...
@@ -1217,20 +1218,18 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping,
...
@@ -1217,20 +1218,18 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping,
*/
*/
static
int
ocfs2_write_cluster
(
struct
address_space
*
mapping
,
static
int
ocfs2_write_cluster
(
struct
address_space
*
mapping
,
u32
phys
,
unsigned
int
unwritten
,
u32
phys
,
unsigned
int
unwritten
,
unsigned
int
should_zero
,
struct
ocfs2_alloc_context
*
data_ac
,
struct
ocfs2_alloc_context
*
data_ac
,
struct
ocfs2_alloc_context
*
meta_ac
,
struct
ocfs2_alloc_context
*
meta_ac
,
struct
ocfs2_write_ctxt
*
wc
,
u32
cpos
,
struct
ocfs2_write_ctxt
*
wc
,
u32
cpos
,
loff_t
user_pos
,
unsigned
user_len
)
loff_t
user_pos
,
unsigned
user_len
)
{
{
int
ret
,
i
,
new
,
should_zero
=
0
;
int
ret
,
i
,
new
;
u64
v_blkno
,
p_blkno
;
u64
v_blkno
,
p_blkno
;
struct
inode
*
inode
=
mapping
->
host
;
struct
inode
*
inode
=
mapping
->
host
;
struct
ocfs2_extent_tree
et
;
struct
ocfs2_extent_tree
et
;
new
=
phys
==
0
?
1
:
0
;
new
=
phys
==
0
?
1
:
0
;
if
(
new
||
unwritten
)
should_zero
=
1
;
if
(
new
)
{
if
(
new
)
{
u32
tmp_pos
;
u32
tmp_pos
;
...
@@ -1301,7 +1300,7 @@ static int ocfs2_write_cluster(struct address_space *mapping,
...
@@ -1301,7 +1300,7 @@ static int ocfs2_write_cluster(struct address_space *mapping,
if
(
tmpret
)
{
if
(
tmpret
)
{
mlog_errno
(
tmpret
);
mlog_errno
(
tmpret
);
if
(
ret
==
0
)
if
(
ret
==
0
)
tmpret
=
ret
;
ret
=
tmp
ret
;
}
}
}
}
...
@@ -1341,7 +1340,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
...
@@ -1341,7 +1340,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
local_len
=
osb
->
s_clustersize
-
cluster_off
;
local_len
=
osb
->
s_clustersize
-
cluster_off
;
ret
=
ocfs2_write_cluster
(
mapping
,
desc
->
c_phys
,
ret
=
ocfs2_write_cluster
(
mapping
,
desc
->
c_phys
,
desc
->
c_unwritten
,
data_ac
,
meta_ac
,
desc
->
c_unwritten
,
desc
->
c_needs_zero
,
data_ac
,
meta_ac
,
wc
,
desc
->
c_cpos
,
pos
,
local_len
);
wc
,
desc
->
c_cpos
,
pos
,
local_len
);
if
(
ret
)
{
if
(
ret
)
{
mlog_errno
(
ret
);
mlog_errno
(
ret
);
...
@@ -1391,14 +1392,14 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
...
@@ -1391,14 +1392,14 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
* newly allocated cluster.
* newly allocated cluster.
*/
*/
desc
=
&
wc
->
w_desc
[
0
];
desc
=
&
wc
->
w_desc
[
0
];
if
(
ocfs2_should_zero_cluster
(
desc
)
)
if
(
desc
->
c_needs_zero
)
ocfs2_figure_cluster_boundaries
(
osb
,
ocfs2_figure_cluster_boundaries
(
osb
,
desc
->
c_cpos
,
desc
->
c_cpos
,
&
wc
->
w_target_from
,
&
wc
->
w_target_from
,
NULL
);
NULL
);
desc
=
&
wc
->
w_desc
[
wc
->
w_clen
-
1
];
desc
=
&
wc
->
w_desc
[
wc
->
w_clen
-
1
];
if
(
ocfs2_should_zero_cluster
(
desc
)
)
if
(
desc
->
c_needs_zero
)
ocfs2_figure_cluster_boundaries
(
osb
,
ocfs2_figure_cluster_boundaries
(
osb
,
desc
->
c_cpos
,
desc
->
c_cpos
,
NULL
,
NULL
,
...
@@ -1466,13 +1467,28 @@ static int ocfs2_populate_write_desc(struct inode *inode,
...
@@ -1466,13 +1467,28 @@ static int ocfs2_populate_write_desc(struct inode *inode,
phys
++
;
phys
++
;
}
}
/*
* If w_first_new_cpos is < UINT_MAX, we have a non-sparse
* file that got extended. w_first_new_cpos tells us
* where the newly allocated clusters are so we can
* zero them.
*/
if
(
desc
->
c_cpos
>=
wc
->
w_first_new_cpos
)
{
BUG_ON
(
phys
==
0
);
desc
->
c_needs_zero
=
1
;
}
desc
->
c_phys
=
phys
;
desc
->
c_phys
=
phys
;
if
(
phys
==
0
)
{
if
(
phys
==
0
)
{
desc
->
c_new
=
1
;
desc
->
c_new
=
1
;
desc
->
c_needs_zero
=
1
;
*
clusters_to_alloc
=
*
clusters_to_alloc
+
1
;
*
clusters_to_alloc
=
*
clusters_to_alloc
+
1
;
}
}
if
(
ext_flags
&
OCFS2_EXT_UNWRITTEN
)
if
(
ext_flags
&
OCFS2_EXT_UNWRITTEN
)
{
desc
->
c_unwritten
=
1
;
desc
->
c_unwritten
=
1
;
desc
->
c_needs_zero
=
1
;
}
num_clusters
--
;
num_clusters
--
;
}
}
...
@@ -1632,10 +1648,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos,
...
@@ -1632,10 +1648,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos,
if
(
newsize
<=
i_size_read
(
inode
))
if
(
newsize
<=
i_size_read
(
inode
))
return
0
;
return
0
;
ret
=
ocfs2_extend_no_holes
(
inode
,
newsize
,
newsize
-
len
);
ret
=
ocfs2_extend_no_holes
(
inode
,
newsize
,
pos
);
if
(
ret
)
if
(
ret
)
mlog_errno
(
ret
);
mlog_errno
(
ret
);
wc
->
w_first_new_cpos
=
ocfs2_clusters_for_bytes
(
inode
->
i_sb
,
i_size_read
(
inode
));
return
ret
;
return
ret
;
}
}
...
@@ -1644,7 +1663,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
...
@@ -1644,7 +1663,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
struct
page
**
pagep
,
void
**
fsdata
,
struct
page
**
pagep
,
void
**
fsdata
,
struct
buffer_head
*
di_bh
,
struct
page
*
mmap_page
)
struct
buffer_head
*
di_bh
,
struct
page
*
mmap_page
)
{
{
int
ret
,
credits
=
OCFS2_INODE_UPDATE_CREDITS
;
int
ret
,
c
luster_of_pages
,
c
redits
=
OCFS2_INODE_UPDATE_CREDITS
;
unsigned
int
clusters_to_alloc
,
extents_to_split
;
unsigned
int
clusters_to_alloc
,
extents_to_split
;
struct
ocfs2_write_ctxt
*
wc
;
struct
ocfs2_write_ctxt
*
wc
;
struct
inode
*
inode
=
mapping
->
host
;
struct
inode
*
inode
=
mapping
->
host
;
...
@@ -1722,8 +1741,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
...
@@ -1722,8 +1741,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
}
}
ocfs2_set_target_boundaries
(
osb
,
wc
,
pos
,
len
,
/*
clusters_to_alloc
+
extents_to_split
);
* We have to zero sparse allocated clusters, unwritten extent clusters,
* and non-sparse clusters we just extended. For non-sparse writes,
* we know zeros will only be needed in the first and/or last cluster.
*/
if
(
clusters_to_alloc
||
extents_to_split
||
wc
->
w_desc
[
0
].
c_needs_zero
||
wc
->
w_desc
[
wc
->
w_clen
-
1
].
c_needs_zero
)
cluster_of_pages
=
1
;
else
cluster_of_pages
=
0
;
ocfs2_set_target_boundaries
(
osb
,
wc
,
pos
,
len
,
cluster_of_pages
);
handle
=
ocfs2_start_trans
(
osb
,
credits
);
handle
=
ocfs2_start_trans
(
osb
,
credits
);
if
(
IS_ERR
(
handle
))
{
if
(
IS_ERR
(
handle
))
{
...
@@ -1756,8 +1786,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
...
@@ -1756,8 +1786,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
* extent.
* extent.
*/
*/
ret
=
ocfs2_grab_pages_for_write
(
mapping
,
wc
,
wc
->
w_cpos
,
pos
,
ret
=
ocfs2_grab_pages_for_write
(
mapping
,
wc
,
wc
->
w_cpos
,
pos
,
clusters_to_alloc
+
extents_to_split
,
cluster_of_pages
,
mmap_page
);
mmap_page
);
if
(
ret
)
{
if
(
ret
)
{
mlog_errno
(
ret
);
mlog_errno
(
ret
);
goto
out_quota
;
goto
out_quota
;
...
...
fs/ocfs2/dcache.c
浏览文件 @
60e0a4c7
...
@@ -310,22 +310,19 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry,
...
@@ -310,22 +310,19 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry,
return
ret
;
return
ret
;
}
}
static
DEFINE_SPINLOCK
(
dentry_list_lock
);
DEFINE_SPINLOCK
(
dentry_list_lock
);
/* We limit the number of dentry locks to drop in one go. We have
/* We limit the number of dentry locks to drop in one go. We have
* this limit so that we don't starve other users of ocfs2_wq. */
* this limit so that we don't starve other users of ocfs2_wq. */
#define DL_INODE_DROP_COUNT 64
#define DL_INODE_DROP_COUNT 64
/* Drop inode references from dentry locks */
/* Drop inode references from dentry locks */
void
ocfs2_drop_dl_inodes
(
struct
work_struct
*
work
)
static
void
__ocfs2_drop_dl_inodes
(
struct
ocfs2_super
*
osb
,
int
drop_count
)
{
{
struct
ocfs2_super
*
osb
=
container_of
(
work
,
struct
ocfs2_super
,
dentry_lock_work
);
struct
ocfs2_dentry_lock
*
dl
;
struct
ocfs2_dentry_lock
*
dl
;
int
drop_count
=
DL_INODE_DROP_COUNT
;
spin_lock
(
&
dentry_list_lock
);
spin_lock
(
&
dentry_list_lock
);
while
(
osb
->
dentry_lock_list
&&
drop_count
--
)
{
while
(
osb
->
dentry_lock_list
&&
(
drop_count
<
0
||
drop_count
--
)
)
{
dl
=
osb
->
dentry_lock_list
;
dl
=
osb
->
dentry_lock_list
;
osb
->
dentry_lock_list
=
dl
->
dl_next
;
osb
->
dentry_lock_list
=
dl
->
dl_next
;
spin_unlock
(
&
dentry_list_lock
);
spin_unlock
(
&
dentry_list_lock
);
...
@@ -333,11 +330,32 @@ void ocfs2_drop_dl_inodes(struct work_struct *work)
...
@@ -333,11 +330,32 @@ void ocfs2_drop_dl_inodes(struct work_struct *work)
kfree
(
dl
);
kfree
(
dl
);
spin_lock
(
&
dentry_list_lock
);
spin_lock
(
&
dentry_list_lock
);
}
}
if
(
osb
->
dentry_lock_list
)
spin_unlock
(
&
dentry_list_lock
);
}
void
ocfs2_drop_dl_inodes
(
struct
work_struct
*
work
)
{
struct
ocfs2_super
*
osb
=
container_of
(
work
,
struct
ocfs2_super
,
dentry_lock_work
);
__ocfs2_drop_dl_inodes
(
osb
,
DL_INODE_DROP_COUNT
);
/*
* Don't queue dropping if umount is in progress. We flush the
* list in ocfs2_dismount_volume
*/
spin_lock
(
&
dentry_list_lock
);
if
(
osb
->
dentry_lock_list
&&
!
ocfs2_test_osb_flag
(
osb
,
OCFS2_OSB_DROP_DENTRY_LOCK_IMMED
))
queue_work
(
ocfs2_wq
,
&
osb
->
dentry_lock_work
);
queue_work
(
ocfs2_wq
,
&
osb
->
dentry_lock_work
);
spin_unlock
(
&
dentry_list_lock
);
spin_unlock
(
&
dentry_list_lock
);
}
}
/* Flush the whole work queue */
void
ocfs2_drop_all_dl_inodes
(
struct
ocfs2_super
*
osb
)
{
__ocfs2_drop_dl_inodes
(
osb
,
-
1
);
}
/*
/*
* ocfs2_dentry_iput() and friends.
* ocfs2_dentry_iput() and friends.
*
*
...
@@ -368,7 +386,8 @@ static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
...
@@ -368,7 +386,8 @@ static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
/* We leave dropping of inode reference to ocfs2_wq as that can
/* We leave dropping of inode reference to ocfs2_wq as that can
* possibly lead to inode deletion which gets tricky */
* possibly lead to inode deletion which gets tricky */
spin_lock
(
&
dentry_list_lock
);
spin_lock
(
&
dentry_list_lock
);
if
(
!
osb
->
dentry_lock_list
)
if
(
!
osb
->
dentry_lock_list
&&
!
ocfs2_test_osb_flag
(
osb
,
OCFS2_OSB_DROP_DENTRY_LOCK_IMMED
))
queue_work
(
ocfs2_wq
,
&
osb
->
dentry_lock_work
);
queue_work
(
ocfs2_wq
,
&
osb
->
dentry_lock_work
);
dl
->
dl_next
=
osb
->
dentry_lock_list
;
dl
->
dl_next
=
osb
->
dentry_lock_list
;
osb
->
dentry_lock_list
=
dl
;
osb
->
dentry_lock_list
=
dl
;
...
...
fs/ocfs2/dcache.h
浏览文件 @
60e0a4c7
...
@@ -49,10 +49,13 @@ struct ocfs2_dentry_lock {
...
@@ -49,10 +49,13 @@ struct ocfs2_dentry_lock {
int
ocfs2_dentry_attach_lock
(
struct
dentry
*
dentry
,
struct
inode
*
inode
,
int
ocfs2_dentry_attach_lock
(
struct
dentry
*
dentry
,
struct
inode
*
inode
,
u64
parent_blkno
);
u64
parent_blkno
);
extern
spinlock_t
dentry_list_lock
;
void
ocfs2_dentry_lock_put
(
struct
ocfs2_super
*
osb
,
void
ocfs2_dentry_lock_put
(
struct
ocfs2_super
*
osb
,
struct
ocfs2_dentry_lock
*
dl
);
struct
ocfs2_dentry_lock
*
dl
);
void
ocfs2_drop_dl_inodes
(
struct
work_struct
*
work
);
void
ocfs2_drop_dl_inodes
(
struct
work_struct
*
work
);
void
ocfs2_drop_all_dl_inodes
(
struct
ocfs2_super
*
osb
);
struct
dentry
*
ocfs2_find_local_alias
(
struct
inode
*
inode
,
u64
parent_blkno
,
struct
dentry
*
ocfs2_find_local_alias
(
struct
inode
*
inode
,
u64
parent_blkno
,
int
skip_unhashed
);
int
skip_unhashed
);
...
...
fs/ocfs2/dlm/dlmast.c
浏览文件 @
60e0a4c7
...
@@ -103,7 +103,6 @@ static void __dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
...
@@ -103,7 +103,6 @@ static void __dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
lock
->
ast_pending
,
lock
->
ml
.
type
);
lock
->
ast_pending
,
lock
->
ml
.
type
);
BUG
();
BUG
();
}
}
BUG_ON
(
!
list_empty
(
&
lock
->
ast_list
));
if
(
lock
->
ast_pending
)
if
(
lock
->
ast_pending
)
mlog
(
0
,
"lock has an ast getting flushed right now
\n
"
);
mlog
(
0
,
"lock has an ast getting flushed right now
\n
"
);
...
...
fs/ocfs2/dlm/dlmrecovery.c
浏览文件 @
60e0a4c7
...
@@ -1118,7 +1118,7 @@ static int dlm_send_mig_lockres_msg(struct dlm_ctxt *dlm,
...
@@ -1118,7 +1118,7 @@ static int dlm_send_mig_lockres_msg(struct dlm_ctxt *dlm,
mlog
(
0
,
"%s:%.*s: sending mig lockres (%s) to %u
\n
"
,
mlog
(
0
,
"%s:%.*s: sending mig lockres (%s) to %u
\n
"
,
dlm
->
name
,
res
->
lockname
.
len
,
res
->
lockname
.
name
,
dlm
->
name
,
res
->
lockname
.
len
,
res
->
lockname
.
name
,
orig_flags
&
DLM_MRES_MIGRATION
?
"migrat
e
"
:
"recovery"
,
orig_flags
&
DLM_MRES_MIGRATION
?
"migrat
ion
"
:
"recovery"
,
send_to
);
send_to
);
/* send it */
/* send it */
...
...
fs/ocfs2/file.c
浏览文件 @
60e0a4c7
...
@@ -1851,6 +1851,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
...
@@ -1851,6 +1851,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
if
(
ret
)
if
(
ret
)
goto
out_dio
;
goto
out_dio
;
count
=
ocount
;
ret
=
generic_write_checks
(
file
,
ppos
,
&
count
,
ret
=
generic_write_checks
(
file
,
ppos
,
&
count
,
S_ISBLK
(
inode
->
i_mode
));
S_ISBLK
(
inode
->
i_mode
));
if
(
ret
)
if
(
ret
)
...
@@ -1918,8 +1919,10 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
...
@@ -1918,8 +1919,10 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
mutex_unlock
(
&
inode
->
i_mutex
);
mutex_unlock
(
&
inode
->
i_mutex
);
if
(
written
)
ret
=
written
;
mlog_exit
(
ret
);
mlog_exit
(
ret
);
return
written
?
written
:
ret
;
return
ret
;
}
}
static
int
ocfs2_splice_to_file
(
struct
pipe_inode_info
*
pipe
,
static
int
ocfs2_splice_to_file
(
struct
pipe_inode_info
*
pipe
,
...
...
fs/ocfs2/journal.c
浏览文件 @
60e0a4c7
...
@@ -1954,10 +1954,16 @@ void ocfs2_orphan_scan_init(struct ocfs2_super *osb)
...
@@ -1954,10 +1954,16 @@ void ocfs2_orphan_scan_init(struct ocfs2_super *osb)
os
->
os_osb
=
osb
;
os
->
os_osb
=
osb
;
os
->
os_count
=
0
;
os
->
os_count
=
0
;
os
->
os_seqno
=
0
;
os
->
os_seqno
=
0
;
os
->
os_scantime
=
CURRENT_TIME
;
mutex_init
(
&
os
->
os_lock
);
mutex_init
(
&
os
->
os_lock
);
INIT_DELAYED_WORK
(
&
os
->
os_orphan_scan_work
,
ocfs2_orphan_scan_work
);
INIT_DELAYED_WORK
(
&
os
->
os_orphan_scan_work
,
ocfs2_orphan_scan_work
);
}
void
ocfs2_orphan_scan_start
(
struct
ocfs2_super
*
osb
)
{
struct
ocfs2_orphan_scan
*
os
;
os
=
&
osb
->
osb_orphan_scan
;
os
->
os_scantime
=
CURRENT_TIME
;
if
(
ocfs2_is_hard_readonly
(
osb
)
||
ocfs2_mount_local
(
osb
))
if
(
ocfs2_is_hard_readonly
(
osb
)
||
ocfs2_mount_local
(
osb
))
atomic_set
(
&
os
->
os_state
,
ORPHAN_SCAN_INACTIVE
);
atomic_set
(
&
os
->
os_state
,
ORPHAN_SCAN_INACTIVE
);
else
{
else
{
...
...
fs/ocfs2/journal.h
浏览文件 @
60e0a4c7
...
@@ -145,6 +145,7 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
...
@@ -145,6 +145,7 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
/* Exported only for the journal struct init code in super.c. Do not call. */
/* Exported only for the journal struct init code in super.c. Do not call. */
void
ocfs2_orphan_scan_init
(
struct
ocfs2_super
*
osb
);
void
ocfs2_orphan_scan_init
(
struct
ocfs2_super
*
osb
);
void
ocfs2_orphan_scan_start
(
struct
ocfs2_super
*
osb
);
void
ocfs2_orphan_scan_stop
(
struct
ocfs2_super
*
osb
);
void
ocfs2_orphan_scan_stop
(
struct
ocfs2_super
*
osb
);
void
ocfs2_orphan_scan_exit
(
struct
ocfs2_super
*
osb
);
void
ocfs2_orphan_scan_exit
(
struct
ocfs2_super
*
osb
);
...
@@ -329,20 +330,27 @@ int ocfs2_journal_dirty(handle_t *handle,
...
@@ -329,20 +330,27 @@ int ocfs2_journal_dirty(handle_t *handle,
/* extended attribute block update */
/* extended attribute block update */
#define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
#define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
/* Update of a single quota block */
#define OCFS2_QUOTA_BLOCK_UPDATE_CREDITS 1
/* global quotafile inode update, data block */
/* global quotafile inode update, data block */
#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + \
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS)
#define OCFS2_LOCAL_QINFO_WRITE_CREDITS OCFS2_QUOTA_BLOCK_UPDATE_CREDITS
/*
/*
* The two writes below can accidentally see global info dirty due
* The two writes below can accidentally see global info dirty due
* to set_info() quotactl so make them prepared for the writes.
* to set_info() quotactl so make them prepared for the writes.
*/
*/
/* quota data block, global info */
/* quota data block, global info */
/* Write to local quota file */
/* Write to local quota file */
#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + 1)
#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + \
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS)
/* global quota data block, local quota data block, global quota inode,
/* global quota data block, local quota data block, global quota inode,
* global quota info */
* global quota info */
#define OCFS2_QSYNC_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 3)
#define OCFS2_QSYNC_CREDITS (OCFS2_QINFO_WRITE_CREDITS + \
2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS)
static
inline
int
ocfs2_quota_trans_credits
(
struct
super_block
*
sb
)
static
inline
int
ocfs2_quota_trans_credits
(
struct
super_block
*
sb
)
{
{
...
@@ -355,11 +363,6 @@ static inline int ocfs2_quota_trans_credits(struct super_block *sb)
...
@@ -355,11 +363,6 @@ static inline int ocfs2_quota_trans_credits(struct super_block *sb)
return
credits
;
return
credits
;
}
}
/* Number of credits needed for removing quota structure from file */
int
ocfs2_calc_qdel_credits
(
struct
super_block
*
sb
,
int
type
);
/* Number of credits needed for initialization of new quota structure */
int
ocfs2_calc_qinit_credits
(
struct
super_block
*
sb
,
int
type
);
/* group extend. inode update and last group update. */
/* group extend. inode update and last group update. */
#define OCFS2_GROUP_EXTEND_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
#define OCFS2_GROUP_EXTEND_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
...
...
fs/ocfs2/ocfs2.h
浏览文件 @
60e0a4c7
...
@@ -227,6 +227,8 @@ enum ocfs2_mount_options
...
@@ -227,6 +227,8 @@ enum ocfs2_mount_options
#define OCFS2_OSB_SOFT_RO 0x0001
#define OCFS2_OSB_SOFT_RO 0x0001
#define OCFS2_OSB_HARD_RO 0x0002
#define OCFS2_OSB_HARD_RO 0x0002
#define OCFS2_OSB_ERROR_FS 0x0004
#define OCFS2_OSB_ERROR_FS 0x0004
#define OCFS2_OSB_DROP_DENTRY_LOCK_IMMED 0x0008
#define OCFS2_DEFAULT_ATIME_QUANTUM 60
#define OCFS2_DEFAULT_ATIME_QUANTUM 60
struct
ocfs2_journal
;
struct
ocfs2_journal
;
...
@@ -490,6 +492,18 @@ static inline void ocfs2_set_osb_flag(struct ocfs2_super *osb,
...
@@ -490,6 +492,18 @@ static inline void ocfs2_set_osb_flag(struct ocfs2_super *osb,
spin_unlock
(
&
osb
->
osb_lock
);
spin_unlock
(
&
osb
->
osb_lock
);
}
}
static
inline
unsigned
long
ocfs2_test_osb_flag
(
struct
ocfs2_super
*
osb
,
unsigned
long
flag
)
{
unsigned
long
ret
;
spin_lock
(
&
osb
->
osb_lock
);
ret
=
osb
->
osb_flags
&
flag
;
spin_unlock
(
&
osb
->
osb_lock
);
return
ret
;
}
static
inline
void
ocfs2_set_ro_flag
(
struct
ocfs2_super
*
osb
,
static
inline
void
ocfs2_set_ro_flag
(
struct
ocfs2_super
*
osb
,
int
hard
)
int
hard
)
{
{
...
...
fs/ocfs2/quota.h
浏览文件 @
60e0a4c7
...
@@ -50,7 +50,6 @@ struct ocfs2_mem_dqinfo {
...
@@ -50,7 +50,6 @@ struct ocfs2_mem_dqinfo {
unsigned
int
dqi_chunks
;
/* Number of chunks in local quota file */
unsigned
int
dqi_chunks
;
/* Number of chunks in local quota file */
unsigned
int
dqi_blocks
;
/* Number of blocks allocated for local quota file */
unsigned
int
dqi_blocks
;
/* Number of blocks allocated for local quota file */
unsigned
int
dqi_syncms
;
/* How often should we sync with other nodes */
unsigned
int
dqi_syncms
;
/* How often should we sync with other nodes */
unsigned
int
dqi_syncjiff
;
/* Precomputed dqi_syncms in jiffies */
struct
list_head
dqi_chunk
;
/* List of chunks */
struct
list_head
dqi_chunk
;
/* List of chunks */
struct
inode
*
dqi_gqinode
;
/* Global quota file inode */
struct
inode
*
dqi_gqinode
;
/* Global quota file inode */
struct
ocfs2_lock_res
dqi_gqlock
;
/* Lock protecting quota information structure */
struct
ocfs2_lock_res
dqi_gqlock
;
/* Lock protecting quota information structure */
...
...
fs/ocfs2/quota_global.c
浏览文件 @
60e0a4c7
...
@@ -69,6 +69,7 @@ static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot)
...
@@ -69,6 +69,7 @@ static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot)
d
->
dqb_curspace
=
cpu_to_le64
(
m
->
dqb_curspace
);
d
->
dqb_curspace
=
cpu_to_le64
(
m
->
dqb_curspace
);
d
->
dqb_btime
=
cpu_to_le64
(
m
->
dqb_btime
);
d
->
dqb_btime
=
cpu_to_le64
(
m
->
dqb_btime
);
d
->
dqb_itime
=
cpu_to_le64
(
m
->
dqb_itime
);
d
->
dqb_itime
=
cpu_to_le64
(
m
->
dqb_itime
);
d
->
dqb_pad1
=
d
->
dqb_pad2
=
0
;
}
}
static
int
ocfs2_global_is_id
(
void
*
dp
,
struct
dquot
*
dquot
)
static
int
ocfs2_global_is_id
(
void
*
dp
,
struct
dquot
*
dquot
)
...
@@ -211,14 +212,13 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type,
...
@@ -211,14 +212,13 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type,
mutex_lock_nested
(
&
gqinode
->
i_mutex
,
I_MUTEX_QUOTA
);
mutex_lock_nested
(
&
gqinode
->
i_mutex
,
I_MUTEX_QUOTA
);
if
(
gqinode
->
i_size
<
off
+
len
)
{
if
(
gqinode
->
i_size
<
off
+
len
)
{
down_write
(
&
OCFS2_I
(
gqinode
)
->
ip_alloc_sem
);
loff_t
rounded_end
=
err
=
ocfs2_extend_no_holes
(
gqinode
,
off
+
len
,
off
);
ocfs2_align_bytes_to_blocks
(
sb
,
off
+
len
);
up_write
(
&
OCFS2_I
(
gqinode
)
->
ip_alloc_sem
);
if
(
err
<
0
)
/* Space is already allocated in ocfs2_global_read_dquot() */
goto
out
;
err
=
ocfs2_simple_size_update
(
gqinode
,
err
=
ocfs2_simple_size_update
(
gqinode
,
oinfo
->
dqi_gqi_bh
,
oinfo
->
dqi_gqi_bh
,
off
+
len
);
rounded_end
);
if
(
err
<
0
)
if
(
err
<
0
)
goto
out
;
goto
out
;
new
=
1
;
new
=
1
;
...
@@ -234,7 +234,7 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type,
...
@@ -234,7 +234,7 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type,
}
}
if
(
err
)
{
if
(
err
)
{
mlog_errno
(
err
);
mlog_errno
(
err
);
return
err
;
goto
out
;
}
}
lock_buffer
(
bh
);
lock_buffer
(
bh
);
if
(
new
)
if
(
new
)
...
@@ -342,7 +342,6 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
...
@@ -342,7 +342,6 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
info
->
dqi_bgrace
=
le32_to_cpu
(
dinfo
.
dqi_bgrace
);
info
->
dqi_bgrace
=
le32_to_cpu
(
dinfo
.
dqi_bgrace
);
info
->
dqi_igrace
=
le32_to_cpu
(
dinfo
.
dqi_igrace
);
info
->
dqi_igrace
=
le32_to_cpu
(
dinfo
.
dqi_igrace
);
oinfo
->
dqi_syncms
=
le32_to_cpu
(
dinfo
.
dqi_syncms
);
oinfo
->
dqi_syncms
=
le32_to_cpu
(
dinfo
.
dqi_syncms
);
oinfo
->
dqi_syncjiff
=
msecs_to_jiffies
(
oinfo
->
dqi_syncms
);
oinfo
->
dqi_gi
.
dqi_blocks
=
le32_to_cpu
(
dinfo
.
dqi_blocks
);
oinfo
->
dqi_gi
.
dqi_blocks
=
le32_to_cpu
(
dinfo
.
dqi_blocks
);
oinfo
->
dqi_gi
.
dqi_free_blk
=
le32_to_cpu
(
dinfo
.
dqi_free_blk
);
oinfo
->
dqi_gi
.
dqi_free_blk
=
le32_to_cpu
(
dinfo
.
dqi_free_blk
);
oinfo
->
dqi_gi
.
dqi_free_entry
=
le32_to_cpu
(
dinfo
.
dqi_free_entry
);
oinfo
->
dqi_gi
.
dqi_free_entry
=
le32_to_cpu
(
dinfo
.
dqi_free_entry
);
...
@@ -352,7 +351,7 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
...
@@ -352,7 +351,7 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
oinfo
->
dqi_gi
.
dqi_qtree_depth
=
qtree_depth
(
&
oinfo
->
dqi_gi
);
oinfo
->
dqi_gi
.
dqi_qtree_depth
=
qtree_depth
(
&
oinfo
->
dqi_gi
);
INIT_DELAYED_WORK
(
&
oinfo
->
dqi_sync_work
,
qsync_work_fn
);
INIT_DELAYED_WORK
(
&
oinfo
->
dqi_sync_work
,
qsync_work_fn
);
queue_delayed_work
(
ocfs2_quota_wq
,
&
oinfo
->
dqi_sync_work
,
queue_delayed_work
(
ocfs2_quota_wq
,
&
oinfo
->
dqi_sync_work
,
oinfo
->
dqi_syncjiff
);
msecs_to_jiffies
(
oinfo
->
dqi_syncms
)
);
out_err:
out_err:
mlog_exit
(
status
);
mlog_exit
(
status
);
...
@@ -402,13 +401,36 @@ int ocfs2_global_write_info(struct super_block *sb, int type)
...
@@ -402,13 +401,36 @@ int ocfs2_global_write_info(struct super_block *sb, int type)
return
err
;
return
err
;
}
}
static
int
ocfs2_global_qinit_alloc
(
struct
super_block
*
sb
,
int
type
)
{
struct
ocfs2_mem_dqinfo
*
oinfo
=
sb_dqinfo
(
sb
,
type
)
->
dqi_priv
;
/*
* We may need to allocate tree blocks and a leaf block but not the
* root block
*/
return
oinfo
->
dqi_gi
.
dqi_qtree_depth
;
}
static
int
ocfs2_calc_global_qinit_credits
(
struct
super_block
*
sb
,
int
type
)
{
/* We modify all the allocated blocks, tree root, and info block */
return
(
ocfs2_global_qinit_alloc
(
sb
,
type
)
+
2
)
*
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS
;
}
/* Read in information from global quota file and acquire a reference to it.
/* Read in information from global quota file and acquire a reference to it.
* dquot_acquire() has already started the transaction and locked quota file */
* dquot_acquire() has already started the transaction and locked quota file */
int
ocfs2_global_read_dquot
(
struct
dquot
*
dquot
)
int
ocfs2_global_read_dquot
(
struct
dquot
*
dquot
)
{
{
int
err
,
err2
,
ex
=
0
;
int
err
,
err2
,
ex
=
0
;
struct
ocfs2_mem_dqinfo
*
info
=
struct
super_block
*
sb
=
dquot
->
dq_sb
;
sb_dqinfo
(
dquot
->
dq_sb
,
dquot
->
dq_type
)
->
dqi_priv
;
int
type
=
dquot
->
dq_type
;
struct
ocfs2_mem_dqinfo
*
info
=
sb_dqinfo
(
sb
,
type
)
->
dqi_priv
;
struct
ocfs2_super
*
osb
=
OCFS2_SB
(
sb
);
struct
inode
*
gqinode
=
info
->
dqi_gqinode
;
int
need_alloc
=
ocfs2_global_qinit_alloc
(
sb
,
type
);
handle_t
*
handle
=
NULL
;
err
=
ocfs2_qinfo_lock
(
info
,
0
);
err
=
ocfs2_qinfo_lock
(
info
,
0
);
if
(
err
<
0
)
if
(
err
<
0
)
...
@@ -419,14 +441,33 @@ int ocfs2_global_read_dquot(struct dquot *dquot)
...
@@ -419,14 +441,33 @@ int ocfs2_global_read_dquot(struct dquot *dquot)
OCFS2_DQUOT
(
dquot
)
->
dq_use_count
++
;
OCFS2_DQUOT
(
dquot
)
->
dq_use_count
++
;
OCFS2_DQUOT
(
dquot
)
->
dq_origspace
=
dquot
->
dq_dqb
.
dqb_curspace
;
OCFS2_DQUOT
(
dquot
)
->
dq_origspace
=
dquot
->
dq_dqb
.
dqb_curspace
;
OCFS2_DQUOT
(
dquot
)
->
dq_originodes
=
dquot
->
dq_dqb
.
dqb_curinodes
;
OCFS2_DQUOT
(
dquot
)
->
dq_originodes
=
dquot
->
dq_dqb
.
dqb_curinodes
;
if
(
!
dquot
->
dq_off
)
{
/* No real quota entry? */
/* Upgrade to exclusive lock for allocation */
ocfs2_qinfo_unlock
(
info
,
0
);
ocfs2_qinfo_unlock
(
info
,
0
);
err
=
ocfs2_qinfo_lock
(
info
,
1
);
if
(
err
<
0
)
if
(
!
dquot
->
dq_off
)
{
/* No real quota entry? */
goto
out_qlock
;
ex
=
1
;
ex
=
1
;
/*
* Add blocks to quota file before we start a transaction since
* locking allocators ranks above a transaction start
*/
WARN_ON
(
journal_current_handle
());
down_write
(
&
OCFS2_I
(
gqinode
)
->
ip_alloc_sem
);
err
=
ocfs2_extend_no_holes
(
gqinode
,
gqinode
->
i_size
+
(
need_alloc
<<
sb
->
s_blocksize_bits
),
gqinode
->
i_size
);
up_write
(
&
OCFS2_I
(
gqinode
)
->
ip_alloc_sem
);
if
(
err
<
0
)
goto
out
;
}
handle
=
ocfs2_start_trans
(
osb
,
ocfs2_calc_global_qinit_credits
(
sb
,
type
));
if
(
IS_ERR
(
handle
))
{
err
=
PTR_ERR
(
handle
);
goto
out
;
}
}
err
=
ocfs2_qinfo_lock
(
info
,
ex
);
if
(
err
<
0
)
goto
out_trans
;
err
=
qtree_write_dquot
(
&
info
->
dqi_gi
,
dquot
);
err
=
qtree_write_dquot
(
&
info
->
dqi_gi
,
dquot
);
if
(
ex
&&
info_dirty
(
sb_dqinfo
(
dquot
->
dq_sb
,
dquot
->
dq_type
)))
{
if
(
ex
&&
info_dirty
(
sb_dqinfo
(
dquot
->
dq_sb
,
dquot
->
dq_type
)))
{
err2
=
__ocfs2_global_write_info
(
dquot
->
dq_sb
,
dquot
->
dq_type
);
err2
=
__ocfs2_global_write_info
(
dquot
->
dq_sb
,
dquot
->
dq_type
);
...
@@ -438,6 +479,9 @@ int ocfs2_global_read_dquot(struct dquot *dquot)
...
@@ -438,6 +479,9 @@ int ocfs2_global_read_dquot(struct dquot *dquot)
ocfs2_qinfo_unlock
(
info
,
1
);
ocfs2_qinfo_unlock
(
info
,
1
);
else
else
ocfs2_qinfo_unlock
(
info
,
0
);
ocfs2_qinfo_unlock
(
info
,
0
);
out_trans:
if
(
handle
)
ocfs2_commit_trans
(
osb
,
handle
);
out:
out:
if
(
err
<
0
)
if
(
err
<
0
)
mlog_errno
(
err
);
mlog_errno
(
err
);
...
@@ -607,7 +651,7 @@ static void qsync_work_fn(struct work_struct *work)
...
@@ -607,7 +651,7 @@ static void qsync_work_fn(struct work_struct *work)
dquot_scan_active
(
sb
,
ocfs2_sync_dquot_helper
,
oinfo
->
dqi_type
);
dquot_scan_active
(
sb
,
ocfs2_sync_dquot_helper
,
oinfo
->
dqi_type
);
queue_delayed_work
(
ocfs2_quota_wq
,
&
oinfo
->
dqi_sync_work
,
queue_delayed_work
(
ocfs2_quota_wq
,
&
oinfo
->
dqi_sync_work
,
oinfo
->
dqi_syncjiff
);
msecs_to_jiffies
(
oinfo
->
dqi_syncms
)
);
}
}
/*
/*
...
@@ -635,20 +679,18 @@ static int ocfs2_write_dquot(struct dquot *dquot)
...
@@ -635,20 +679,18 @@ static int ocfs2_write_dquot(struct dquot *dquot)
return
status
;
return
status
;
}
}
int
ocfs2_calc_qdel_credits
(
struct
super_block
*
sb
,
int
type
)
static
int
ocfs2_calc_qdel_credits
(
struct
super_block
*
sb
,
int
type
)
{
{
struct
ocfs2_mem_dqinfo
*
oinfo
;
struct
ocfs2_mem_dqinfo
*
oinfo
=
sb_dqinfo
(
sb
,
type
)
->
dqi_priv
;
int
features
[
MAXQUOTAS
]
=
{
OCFS2_FEATURE_RO_COMPAT_USRQUOTA
,
/*
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA
};
* We modify tree, leaf block, global info, local chunk header,
* global and local inode; OCFS2_QINFO_WRITE_CREDITS already
if
(
!
OCFS2_HAS_RO_COMPAT_FEATURE
(
sb
,
features
[
type
]))
* accounts for inode update
return
0
;
*/
return
(
oinfo
->
dqi_gi
.
dqi_qtree_depth
+
2
)
*
oinfo
=
sb_dqinfo
(
sb
,
type
)
->
dqi_priv
;
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS
+
/* We modify tree, leaf block, global info, local chunk header,
OCFS2_QINFO_WRITE_CREDITS
+
* global and local inode */
OCFS2_INODE_UPDATE_CREDITS
;
return
oinfo
->
dqi_gi
.
dqi_qtree_depth
+
2
+
1
+
2
*
OCFS2_INODE_UPDATE_CREDITS
;
}
}
static
int
ocfs2_release_dquot
(
struct
dquot
*
dquot
)
static
int
ocfs2_release_dquot
(
struct
dquot
*
dquot
)
...
@@ -680,33 +722,10 @@ static int ocfs2_release_dquot(struct dquot *dquot)
...
@@ -680,33 +722,10 @@ static int ocfs2_release_dquot(struct dquot *dquot)
return
status
;
return
status
;
}
}
int
ocfs2_calc_qinit_credits
(
struct
super_block
*
sb
,
int
type
)
{
struct
ocfs2_mem_dqinfo
*
oinfo
;
int
features
[
MAXQUOTAS
]
=
{
OCFS2_FEATURE_RO_COMPAT_USRQUOTA
,
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA
};
struct
ocfs2_dinode
*
lfe
,
*
gfe
;
if
(
!
OCFS2_HAS_RO_COMPAT_FEATURE
(
sb
,
features
[
type
]))
return
0
;
oinfo
=
sb_dqinfo
(
sb
,
type
)
->
dqi_priv
;
gfe
=
(
struct
ocfs2_dinode
*
)
oinfo
->
dqi_gqi_bh
->
b_data
;
lfe
=
(
struct
ocfs2_dinode
*
)
oinfo
->
dqi_lqi_bh
->
b_data
;
/* We can extend local file + global file. In local file we
* can modify info, chunk header block and dquot block. In
* global file we can modify info, tree and leaf block */
return
ocfs2_calc_extend_credits
(
sb
,
&
lfe
->
id2
.
i_list
,
0
)
+
ocfs2_calc_extend_credits
(
sb
,
&
gfe
->
id2
.
i_list
,
0
)
+
3
+
oinfo
->
dqi_gi
.
dqi_qtree_depth
+
2
;
}
static
int
ocfs2_acquire_dquot
(
struct
dquot
*
dquot
)
static
int
ocfs2_acquire_dquot
(
struct
dquot
*
dquot
)
{
{
handle_t
*
handle
;
struct
ocfs2_mem_dqinfo
*
oinfo
=
struct
ocfs2_mem_dqinfo
*
oinfo
=
sb_dqinfo
(
dquot
->
dq_sb
,
dquot
->
dq_type
)
->
dqi_priv
;
sb_dqinfo
(
dquot
->
dq_sb
,
dquot
->
dq_type
)
->
dqi_priv
;
struct
ocfs2_super
*
osb
=
OCFS2_SB
(
dquot
->
dq_sb
);
int
status
=
0
;
int
status
=
0
;
mlog_entry
(
"id=%u, type=%d"
,
dquot
->
dq_id
,
dquot
->
dq_type
);
mlog_entry
(
"id=%u, type=%d"
,
dquot
->
dq_id
,
dquot
->
dq_type
);
...
@@ -715,16 +734,7 @@ static int ocfs2_acquire_dquot(struct dquot *dquot)
...
@@ -715,16 +734,7 @@ static int ocfs2_acquire_dquot(struct dquot *dquot)
status
=
ocfs2_lock_global_qf
(
oinfo
,
1
);
status
=
ocfs2_lock_global_qf
(
oinfo
,
1
);
if
(
status
<
0
)
if
(
status
<
0
)
goto
out
;
goto
out
;
handle
=
ocfs2_start_trans
(
osb
,
ocfs2_calc_qinit_credits
(
dquot
->
dq_sb
,
dquot
->
dq_type
));
if
(
IS_ERR
(
handle
))
{
status
=
PTR_ERR
(
handle
);
mlog_errno
(
status
);
goto
out_ilock
;
}
status
=
dquot_acquire
(
dquot
);
status
=
dquot_acquire
(
dquot
);
ocfs2_commit_trans
(
osb
,
handle
);
out_ilock:
ocfs2_unlock_global_qf
(
oinfo
,
1
);
ocfs2_unlock_global_qf
(
oinfo
,
1
);
out:
out:
mlog_exit
(
status
);
mlog_exit
(
status
);
...
...
fs/ocfs2/quota_local.c
浏览文件 @
60e0a4c7
...
@@ -20,6 +20,7 @@
...
@@ -20,6 +20,7 @@
#include "sysfile.h"
#include "sysfile.h"
#include "dlmglue.h"
#include "dlmglue.h"
#include "quota.h"
#include "quota.h"
#include "uptodate.h"
/* Number of local quota structures per block */
/* Number of local quota structures per block */
static
inline
unsigned
int
ol_quota_entries_per_block
(
struct
super_block
*
sb
)
static
inline
unsigned
int
ol_quota_entries_per_block
(
struct
super_block
*
sb
)
...
@@ -100,7 +101,8 @@ static int ocfs2_modify_bh(struct inode *inode, struct buffer_head *bh,
...
@@ -100,7 +101,8 @@ static int ocfs2_modify_bh(struct inode *inode, struct buffer_head *bh,
handle_t
*
handle
;
handle_t
*
handle
;
int
status
;
int
status
;
handle
=
ocfs2_start_trans
(
OCFS2_SB
(
sb
),
1
);
handle
=
ocfs2_start_trans
(
OCFS2_SB
(
sb
),
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS
);
if
(
IS_ERR
(
handle
))
{
if
(
IS_ERR
(
handle
))
{
status
=
PTR_ERR
(
handle
);
status
=
PTR_ERR
(
handle
);
mlog_errno
(
status
);
mlog_errno
(
status
);
...
@@ -610,7 +612,8 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
...
@@ -610,7 +612,8 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
goto
out_bh
;
goto
out_bh
;
/* Mark quota file as clean if we are recovering quota file of
/* Mark quota file as clean if we are recovering quota file of
* some other node. */
* some other node. */
handle
=
ocfs2_start_trans
(
osb
,
1
);
handle
=
ocfs2_start_trans
(
osb
,
OCFS2_LOCAL_QINFO_WRITE_CREDITS
);
if
(
IS_ERR
(
handle
))
{
if
(
IS_ERR
(
handle
))
{
status
=
PTR_ERR
(
handle
);
status
=
PTR_ERR
(
handle
);
mlog_errno
(
status
);
mlog_errno
(
status
);
...
@@ -940,7 +943,7 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
...
@@ -940,7 +943,7 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
struct
ocfs2_local_disk_chunk
*
dchunk
;
struct
ocfs2_local_disk_chunk
*
dchunk
;
int
status
;
int
status
;
handle_t
*
handle
;
handle_t
*
handle
;
struct
buffer_head
*
bh
=
NULL
;
struct
buffer_head
*
bh
=
NULL
,
*
dbh
=
NULL
;
u64
p_blkno
;
u64
p_blkno
;
/* We are protected by dqio_sem so no locking needed */
/* We are protected by dqio_sem so no locking needed */
...
@@ -964,32 +967,35 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
...
@@ -964,32 +967,35 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
mlog_errno
(
status
);
mlog_errno
(
status
);
goto
out
;
goto
out
;
}
}
/* Local quota info and two new blocks we initialize */
handle
=
ocfs2_start_trans
(
OCFS2_SB
(
sb
),
OCFS2_LOCAL_QINFO_WRITE_CREDITS
+
2
*
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS
);
if
(
IS_ERR
(
handle
))
{
status
=
PTR_ERR
(
handle
);
mlog_errno
(
status
);
goto
out
;
}
/* Initialize chunk header */
down_read
(
&
OCFS2_I
(
lqinode
)
->
ip_alloc_sem
);
down_read
(
&
OCFS2_I
(
lqinode
)
->
ip_alloc_sem
);
status
=
ocfs2_extent_map_get_blocks
(
lqinode
,
oinfo
->
dqi_blocks
,
status
=
ocfs2_extent_map_get_blocks
(
lqinode
,
oinfo
->
dqi_blocks
,
&
p_blkno
,
NULL
,
NULL
);
&
p_blkno
,
NULL
,
NULL
);
up_read
(
&
OCFS2_I
(
lqinode
)
->
ip_alloc_sem
);
up_read
(
&
OCFS2_I
(
lqinode
)
->
ip_alloc_sem
);
if
(
status
<
0
)
{
if
(
status
<
0
)
{
mlog_errno
(
status
);
mlog_errno
(
status
);
goto
out
;
goto
out
_trans
;
}
}
bh
=
sb_getblk
(
sb
,
p_blkno
);
bh
=
sb_getblk
(
sb
,
p_blkno
);
if
(
!
bh
)
{
if
(
!
bh
)
{
status
=
-
ENOMEM
;
status
=
-
ENOMEM
;
mlog_errno
(
status
);
mlog_errno
(
status
);
goto
out
;
goto
out
_trans
;
}
}
dchunk
=
(
struct
ocfs2_local_disk_chunk
*
)
bh
->
b_data
;
dchunk
=
(
struct
ocfs2_local_disk_chunk
*
)
bh
->
b_data
;
ocfs2_set_new_buffer_uptodate
(
lqinode
,
bh
);
handle
=
ocfs2_start_trans
(
OCFS2_SB
(
sb
),
2
);
if
(
IS_ERR
(
handle
))
{
status
=
PTR_ERR
(
handle
);
mlog_errno
(
status
);
goto
out
;
}
status
=
ocfs2_journal_access_dq
(
handle
,
lqinode
,
bh
,
status
=
ocfs2_journal_access_dq
(
handle
,
lqinode
,
bh
,
OCFS2_JOURNAL_ACCESS_
WRI
TE
);
OCFS2_JOURNAL_ACCESS_
CREA
TE
);
if
(
status
<
0
)
{
if
(
status
<
0
)
{
mlog_errno
(
status
);
mlog_errno
(
status
);
goto
out_trans
;
goto
out_trans
;
...
@@ -999,7 +1005,6 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
...
@@ -999,7 +1005,6 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
memset
(
dchunk
->
dqc_bitmap
,
0
,
memset
(
dchunk
->
dqc_bitmap
,
0
,
sb
->
s_blocksize
-
sizeof
(
struct
ocfs2_local_disk_chunk
)
-
sb
->
s_blocksize
-
sizeof
(
struct
ocfs2_local_disk_chunk
)
-
OCFS2_QBLK_RESERVED_SPACE
);
OCFS2_QBLK_RESERVED_SPACE
);
set_buffer_uptodate
(
bh
);
unlock_buffer
(
bh
);
unlock_buffer
(
bh
);
status
=
ocfs2_journal_dirty
(
handle
,
bh
);
status
=
ocfs2_journal_dirty
(
handle
,
bh
);
if
(
status
<
0
)
{
if
(
status
<
0
)
{
...
@@ -1007,6 +1012,38 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
...
@@ -1007,6 +1012,38 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
goto
out_trans
;
goto
out_trans
;
}
}
/* Initialize new block with structures */
down_read
(
&
OCFS2_I
(
lqinode
)
->
ip_alloc_sem
);
status
=
ocfs2_extent_map_get_blocks
(
lqinode
,
oinfo
->
dqi_blocks
+
1
,
&
p_blkno
,
NULL
,
NULL
);
up_read
(
&
OCFS2_I
(
lqinode
)
->
ip_alloc_sem
);
if
(
status
<
0
)
{
mlog_errno
(
status
);
goto
out_trans
;
}
dbh
=
sb_getblk
(
sb
,
p_blkno
);
if
(
!
dbh
)
{
status
=
-
ENOMEM
;
mlog_errno
(
status
);
goto
out_trans
;
}
ocfs2_set_new_buffer_uptodate
(
lqinode
,
dbh
);
status
=
ocfs2_journal_access_dq
(
handle
,
lqinode
,
dbh
,
OCFS2_JOURNAL_ACCESS_CREATE
);
if
(
status
<
0
)
{
mlog_errno
(
status
);
goto
out_trans
;
}
lock_buffer
(
dbh
);
memset
(
dbh
->
b_data
,
0
,
sb
->
s_blocksize
-
OCFS2_QBLK_RESERVED_SPACE
);
unlock_buffer
(
dbh
);
status
=
ocfs2_journal_dirty
(
handle
,
dbh
);
if
(
status
<
0
)
{
mlog_errno
(
status
);
goto
out_trans
;
}
/* Update local quotafile info */
oinfo
->
dqi_blocks
+=
2
;
oinfo
->
dqi_blocks
+=
2
;
oinfo
->
dqi_chunks
++
;
oinfo
->
dqi_chunks
++
;
status
=
ocfs2_local_write_info
(
sb
,
type
);
status
=
ocfs2_local_write_info
(
sb
,
type
);
...
@@ -1031,6 +1068,7 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
...
@@ -1031,6 +1068,7 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
ocfs2_commit_trans
(
OCFS2_SB
(
sb
),
handle
);
ocfs2_commit_trans
(
OCFS2_SB
(
sb
),
handle
);
out:
out:
brelse
(
bh
);
brelse
(
bh
);
brelse
(
dbh
);
kmem_cache_free
(
ocfs2_qf_chunk_cachep
,
chunk
);
kmem_cache_free
(
ocfs2_qf_chunk_cachep
,
chunk
);
return
ERR_PTR
(
status
);
return
ERR_PTR
(
status
);
}
}
...
@@ -1048,6 +1086,8 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
...
@@ -1048,6 +1086,8 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
struct
ocfs2_local_disk_chunk
*
dchunk
;
struct
ocfs2_local_disk_chunk
*
dchunk
;
int
epb
=
ol_quota_entries_per_block
(
sb
);
int
epb
=
ol_quota_entries_per_block
(
sb
);
unsigned
int
chunk_blocks
;
unsigned
int
chunk_blocks
;
struct
buffer_head
*
bh
;
u64
p_blkno
;
int
status
;
int
status
;
handle_t
*
handle
;
handle_t
*
handle
;
...
@@ -1075,12 +1115,49 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
...
@@ -1075,12 +1115,49 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
mlog_errno
(
status
);
mlog_errno
(
status
);
goto
out
;
goto
out
;
}
}
handle
=
ocfs2_start_trans
(
OCFS2_SB
(
sb
),
2
);
/* Get buffer from the just added block */
down_read
(
&
OCFS2_I
(
lqinode
)
->
ip_alloc_sem
);
status
=
ocfs2_extent_map_get_blocks
(
lqinode
,
oinfo
->
dqi_blocks
,
&
p_blkno
,
NULL
,
NULL
);
up_read
(
&
OCFS2_I
(
lqinode
)
->
ip_alloc_sem
);
if
(
status
<
0
)
{
mlog_errno
(
status
);
goto
out
;
}
bh
=
sb_getblk
(
sb
,
p_blkno
);
if
(
!
bh
)
{
status
=
-
ENOMEM
;
mlog_errno
(
status
);
goto
out
;
}
ocfs2_set_new_buffer_uptodate
(
lqinode
,
bh
);
/* Local quota info, chunk header and the new block we initialize */
handle
=
ocfs2_start_trans
(
OCFS2_SB
(
sb
),
OCFS2_LOCAL_QINFO_WRITE_CREDITS
+
2
*
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS
);
if
(
IS_ERR
(
handle
))
{
if
(
IS_ERR
(
handle
))
{
status
=
PTR_ERR
(
handle
);
status
=
PTR_ERR
(
handle
);
mlog_errno
(
status
);
mlog_errno
(
status
);
goto
out
;
goto
out
;
}
}
/* Zero created block */
status
=
ocfs2_journal_access_dq
(
handle
,
lqinode
,
bh
,
OCFS2_JOURNAL_ACCESS_CREATE
);
if
(
status
<
0
)
{
mlog_errno
(
status
);
goto
out_trans
;
}
lock_buffer
(
bh
);
memset
(
bh
->
b_data
,
0
,
sb
->
s_blocksize
);
unlock_buffer
(
bh
);
status
=
ocfs2_journal_dirty
(
handle
,
bh
);
if
(
status
<
0
)
{
mlog_errno
(
status
);
goto
out_trans
;
}
/* Update chunk header */
status
=
ocfs2_journal_access_dq
(
handle
,
lqinode
,
chunk
->
qc_headerbh
,
status
=
ocfs2_journal_access_dq
(
handle
,
lqinode
,
chunk
->
qc_headerbh
,
OCFS2_JOURNAL_ACCESS_WRITE
);
OCFS2_JOURNAL_ACCESS_WRITE
);
if
(
status
<
0
)
{
if
(
status
<
0
)
{
...
@@ -1097,6 +1174,7 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
...
@@ -1097,6 +1174,7 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
mlog_errno
(
status
);
mlog_errno
(
status
);
goto
out_trans
;
goto
out_trans
;
}
}
/* Update file header */
oinfo
->
dqi_blocks
++
;
oinfo
->
dqi_blocks
++
;
status
=
ocfs2_local_write_info
(
sb
,
type
);
status
=
ocfs2_local_write_info
(
sb
,
type
);
if
(
status
<
0
)
{
if
(
status
<
0
)
{
...
...
fs/ocfs2/stack_o2cb.c
浏览文件 @
60e0a4c7
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
* General Public License for more details.
* General Public License for more details.
*/
*/
#include <linux/kernel.h>
#include <linux/crc32.h>
#include <linux/crc32.h>
#include <linux/module.h>
#include <linux/module.h>
...
@@ -153,7 +154,7 @@ static int status_map[] = {
...
@@ -153,7 +154,7 @@ static int status_map[] = {
static
int
dlm_status_to_errno
(
enum
dlm_status
status
)
static
int
dlm_status_to_errno
(
enum
dlm_status
status
)
{
{
BUG_ON
(
status
>
(
sizeof
(
status_map
)
/
sizeof
(
status_map
[
0
])
));
BUG_ON
(
status
<
0
||
status
>=
ARRAY_SIZE
(
status_map
));
return
status_map
[
status
];
return
status_map
[
status
];
}
}
...
...
fs/ocfs2/super.c
浏览文件 @
60e0a4c7
...
@@ -777,6 +777,7 @@ static int ocfs2_sb_probe(struct super_block *sb,
...
@@ -777,6 +777,7 @@ static int ocfs2_sb_probe(struct super_block *sb,
}
}
di
=
(
struct
ocfs2_dinode
*
)
(
*
bh
)
->
b_data
;
di
=
(
struct
ocfs2_dinode
*
)
(
*
bh
)
->
b_data
;
memset
(
stats
,
0
,
sizeof
(
struct
ocfs2_blockcheck_stats
));
memset
(
stats
,
0
,
sizeof
(
struct
ocfs2_blockcheck_stats
));
spin_lock_init
(
&
stats
->
b_lock
);
status
=
ocfs2_verify_volume
(
di
,
*
bh
,
blksize
,
stats
);
status
=
ocfs2_verify_volume
(
di
,
*
bh
,
blksize
,
stats
);
if
(
status
>=
0
)
if
(
status
>=
0
)
goto
bail
;
goto
bail
;
...
@@ -1182,7 +1183,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
...
@@ -1182,7 +1183,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
wake_up
(
&
osb
->
osb_mount_event
);
wake_up
(
&
osb
->
osb_mount_event
);
/* Start this when the mount is almost sure of being successful */
/* Start this when the mount is almost sure of being successful */
ocfs2_orphan_scan_
ini
t
(
osb
);
ocfs2_orphan_scan_
star
t
(
osb
);
mlog_exit
(
status
);
mlog_exit
(
status
);
return
status
;
return
status
;
...
@@ -1213,14 +1214,27 @@ static int ocfs2_get_sb(struct file_system_type *fs_type,
...
@@ -1213,14 +1214,27 @@ static int ocfs2_get_sb(struct file_system_type *fs_type,
mnt
);
mnt
);
}
}
static
void
ocfs2_kill_sb
(
struct
super_block
*
sb
)
{
struct
ocfs2_super
*
osb
=
OCFS2_SB
(
sb
);
/* Prevent further queueing of inode drop events */
spin_lock
(
&
dentry_list_lock
);
ocfs2_set_osb_flag
(
osb
,
OCFS2_OSB_DROP_DENTRY_LOCK_IMMED
);
spin_unlock
(
&
dentry_list_lock
);
/* Wait for work to finish and/or remove it */
cancel_work_sync
(
&
osb
->
dentry_lock_work
);
kill_block_super
(
sb
);
}
static
struct
file_system_type
ocfs2_fs_type
=
{
static
struct
file_system_type
ocfs2_fs_type
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
name
=
"ocfs2"
,
.
name
=
"ocfs2"
,
.
get_sb
=
ocfs2_get_sb
,
/* is this called when we mount
.
get_sb
=
ocfs2_get_sb
,
/* is this called when we mount
* the fs? */
* the fs? */
.
kill_sb
=
kill_block_super
,
/* set to the generic one
.
kill_sb
=
ocfs2_kill_sb
,
* right now, but do we
* need to change that? */
.
fs_flags
=
FS_REQUIRES_DEV
|
FS_RENAME_DOES_D_MOVE
,
.
fs_flags
=
FS_REQUIRES_DEV
|
FS_RENAME_DOES_D_MOVE
,
.
next
=
NULL
.
next
=
NULL
};
};
...
@@ -1819,6 +1833,12 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
...
@@ -1819,6 +1833,12 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
debugfs_remove
(
osb
->
osb_ctxt
);
debugfs_remove
(
osb
->
osb_ctxt
);
/*
* Flush inode dropping work queue so that deletes are
* performed while the filesystem is still working
*/
ocfs2_drop_all_dl_inodes
(
osb
);
/* Orphan scan should be stopped as early as possible */
/* Orphan scan should be stopped as early as possible */
ocfs2_orphan_scan_stop
(
osb
);
ocfs2_orphan_scan_stop
(
osb
);
...
@@ -1981,6 +2001,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
...
@@ -1981,6 +2001,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
snprintf
(
osb
->
dev_str
,
sizeof
(
osb
->
dev_str
),
"%u,%u"
,
snprintf
(
osb
->
dev_str
,
sizeof
(
osb
->
dev_str
),
"%u,%u"
,
MAJOR
(
osb
->
sb
->
s_dev
),
MINOR
(
osb
->
sb
->
s_dev
));
MAJOR
(
osb
->
sb
->
s_dev
),
MINOR
(
osb
->
sb
->
s_dev
));
ocfs2_orphan_scan_init
(
osb
);
status
=
ocfs2_recovery_init
(
osb
);
status
=
ocfs2_recovery_init
(
osb
);
if
(
status
)
{
if
(
status
)
{
mlog
(
ML_ERROR
,
"Unable to initialize recovery state
\n
"
);
mlog
(
ML_ERROR
,
"Unable to initialize recovery state
\n
"
);
...
...
fs/ocfs2/xattr.c
浏览文件 @
60e0a4c7
...
@@ -1052,7 +1052,8 @@ static int ocfs2_xattr_block_get(struct inode *inode,
...
@@ -1052,7 +1052,8 @@ static int ocfs2_xattr_block_get(struct inode *inode,
struct
ocfs2_xattr_block
*
xb
;
struct
ocfs2_xattr_block
*
xb
;
struct
ocfs2_xattr_value_root
*
xv
;
struct
ocfs2_xattr_value_root
*
xv
;
size_t
size
;
size_t
size
;
int
ret
=
-
ENODATA
,
name_offset
,
name_len
,
block_off
,
i
;
int
ret
=
-
ENODATA
,
name_offset
,
name_len
,
i
;
int
uninitialized_var
(
block_off
);
xs
->
bucket
=
ocfs2_xattr_bucket_new
(
inode
);
xs
->
bucket
=
ocfs2_xattr_bucket_new
(
inode
);
if
(
!
xs
->
bucket
)
{
if
(
!
xs
->
bucket
)
{
...
...
include/linux/perf_counter.h
浏览文件 @
60e0a4c7
...
@@ -115,7 +115,7 @@ enum perf_counter_sample_format {
...
@@ -115,7 +115,7 @@ enum perf_counter_sample_format {
PERF_SAMPLE_TID
=
1U
<<
1
,
PERF_SAMPLE_TID
=
1U
<<
1
,
PERF_SAMPLE_TIME
=
1U
<<
2
,
PERF_SAMPLE_TIME
=
1U
<<
2
,
PERF_SAMPLE_ADDR
=
1U
<<
3
,
PERF_SAMPLE_ADDR
=
1U
<<
3
,
PERF_SAMPLE_
GROUP
=
1U
<<
4
,
PERF_SAMPLE_
READ
=
1U
<<
4
,
PERF_SAMPLE_CALLCHAIN
=
1U
<<
5
,
PERF_SAMPLE_CALLCHAIN
=
1U
<<
5
,
PERF_SAMPLE_ID
=
1U
<<
6
,
PERF_SAMPLE_ID
=
1U
<<
6
,
PERF_SAMPLE_CPU
=
1U
<<
7
,
PERF_SAMPLE_CPU
=
1U
<<
7
,
...
@@ -127,16 +127,32 @@ enum perf_counter_sample_format {
...
@@ -127,16 +127,32 @@ enum perf_counter_sample_format {
};
};
/*
/*
* Bits that can be set in attr.read_format to request that
* The format of the data returned by read() on a perf counter fd,
* reads on the counter should return the indicated quantities,
* as specified by attr.read_format:
* in increasing order of bit value, after the counter value.
*
* struct read_format {
* { u64 value;
* { u64 time_enabled; } && PERF_FORMAT_ENABLED
* { u64 time_running; } && PERF_FORMAT_RUNNING
* { u64 id; } && PERF_FORMAT_ID
* } && !PERF_FORMAT_GROUP
*
* { u64 nr;
* { u64 time_enabled; } && PERF_FORMAT_ENABLED
* { u64 time_running; } && PERF_FORMAT_RUNNING
* { u64 value;
* { u64 id; } && PERF_FORMAT_ID
* } cntr[nr];
* } && PERF_FORMAT_GROUP
* };
*/
*/
enum
perf_counter_read_format
{
enum
perf_counter_read_format
{
PERF_FORMAT_TOTAL_TIME_ENABLED
=
1U
<<
0
,
PERF_FORMAT_TOTAL_TIME_ENABLED
=
1U
<<
0
,
PERF_FORMAT_TOTAL_TIME_RUNNING
=
1U
<<
1
,
PERF_FORMAT_TOTAL_TIME_RUNNING
=
1U
<<
1
,
PERF_FORMAT_ID
=
1U
<<
2
,
PERF_FORMAT_ID
=
1U
<<
2
,
PERF_FORMAT_GROUP
=
1U
<<
3
,
PERF_FORMAT_MAX
=
1U
<<
3
,
/* non-ABI */
PERF_FORMAT_MAX
=
1U
<<
4
,
/* non-ABI */
};
};
#define PERF_ATTR_SIZE_VER0 64
/* sizeof first published struct */
#define PERF_ATTR_SIZE_VER0 64
/* sizeof first published struct */
...
@@ -343,10 +359,8 @@ enum perf_event_type {
...
@@ -343,10 +359,8 @@ enum perf_event_type {
* struct {
* struct {
* struct perf_event_header header;
* struct perf_event_header header;
* u32 pid, tid;
* u32 pid, tid;
* u64 value;
*
* { u64 time_enabled; } && PERF_FORMAT_ENABLED
* struct read_format values;
* { u64 time_running; } && PERF_FORMAT_RUNNING
* { u64 parent_id; } && PERF_FORMAT_ID
* };
* };
*/
*/
PERF_EVENT_READ
=
8
,
PERF_EVENT_READ
=
8
,
...
@@ -364,11 +378,22 @@ enum perf_event_type {
...
@@ -364,11 +378,22 @@ enum perf_event_type {
* { u32 cpu, res; } && PERF_SAMPLE_CPU
* { u32 cpu, res; } && PERF_SAMPLE_CPU
* { u64 period; } && PERF_SAMPLE_PERIOD
* { u64 period; } && PERF_SAMPLE_PERIOD
*
*
* { u64 nr;
* { struct read_format values; } && PERF_SAMPLE_READ
* { u64 id, val; } cnt[nr]; } && PERF_SAMPLE_GROUP
*
*
* { u64 nr,
* { u64 nr,
* u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
* u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
*
* #
* # The RAW record below is opaque data wrt the ABI
* #
* # That is, the ABI doesn't make any promises wrt to
* # the stability of its content, it may vary depending
* # on event, hardware, kernel version and phase of
* # the moon.
* #
* # In other words, PERF_SAMPLE_RAW contents are not an ABI.
* #
*
* { u32 size;
* { u32 size;
* char data[size];}&& PERF_SAMPLE_RAW
* char data[size];}&& PERF_SAMPLE_RAW
* };
* };
...
@@ -694,6 +719,8 @@ struct perf_sample_data {
...
@@ -694,6 +719,8 @@ struct perf_sample_data {
extern
int
perf_counter_overflow
(
struct
perf_counter
*
counter
,
int
nmi
,
extern
int
perf_counter_overflow
(
struct
perf_counter
*
counter
,
int
nmi
,
struct
perf_sample_data
*
data
);
struct
perf_sample_data
*
data
);
extern
void
perf_counter_output
(
struct
perf_counter
*
counter
,
int
nmi
,
struct
perf_sample_data
*
data
);
/*
/*
* Return 1 for a software counter, 0 for a hardware counter
* Return 1 for a software counter, 0 for a hardware counter
...
...
include/linux/wait.h
浏览文件 @
60e0a4c7
...
@@ -77,7 +77,14 @@ struct task_struct;
...
@@ -77,7 +77,14 @@ struct task_struct;
#define __WAIT_BIT_KEY_INITIALIZER(word, bit) \
#define __WAIT_BIT_KEY_INITIALIZER(word, bit) \
{ .flags = word, .bit_nr = bit, }
{ .flags = word, .bit_nr = bit, }
extern
void
init_waitqueue_head
(
wait_queue_head_t
*
q
);
extern
void
__init_waitqueue_head
(
wait_queue_head_t
*
q
,
struct
lock_class_key
*
);
#define init_waitqueue_head(q) \
do { \
static struct lock_class_key __key; \
\
__init_waitqueue_head((q), &__key); \
} while (0)
#ifdef CONFIG_LOCKDEP
#ifdef CONFIG_LOCKDEP
# define __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) \
# define __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) \
...
...
kernel/futex.c
浏览文件 @
60e0a4c7
...
@@ -1010,15 +1010,19 @@ void requeue_futex(struct futex_q *q, struct futex_hash_bucket *hb1,
...
@@ -1010,15 +1010,19 @@ void requeue_futex(struct futex_q *q, struct futex_hash_bucket *hb1,
* requeue_pi_wake_futex() - Wake a task that acquired the lock during requeue
* requeue_pi_wake_futex() - Wake a task that acquired the lock during requeue
* q: the futex_q
* q: the futex_q
* key: the key of the requeue target futex
* key: the key of the requeue target futex
* hb: the hash_bucket of the requeue target futex
*
*
* During futex_requeue, with requeue_pi=1, it is possible to acquire the
* During futex_requeue, with requeue_pi=1, it is possible to acquire the
* target futex if it is uncontended or via a lock steal. Set the futex_q key
* target futex if it is uncontended or via a lock steal. Set the futex_q key
* to the requeue target futex so the waiter can detect the wakeup on the right
* to the requeue target futex so the waiter can detect the wakeup on the right
* futex, but remove it from the hb and NULL the rt_waiter so it can detect
* futex, but remove it from the hb and NULL the rt_waiter so it can detect
* atomic lock acquisition. Must be called with the q->lock_ptr held.
* atomic lock acquisition. Set the q->lock_ptr to the requeue target hb->lock
* to protect access to the pi_state to fixup the owner later. Must be called
* with both q->lock_ptr and hb->lock held.
*/
*/
static
inline
static
inline
void
requeue_pi_wake_futex
(
struct
futex_q
*
q
,
union
futex_key
*
key
)
void
requeue_pi_wake_futex
(
struct
futex_q
*
q
,
union
futex_key
*
key
,
struct
futex_hash_bucket
*
hb
)
{
{
drop_futex_key_refs
(
&
q
->
key
);
drop_futex_key_refs
(
&
q
->
key
);
get_futex_key_refs
(
key
);
get_futex_key_refs
(
key
);
...
@@ -1030,6 +1034,11 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key)
...
@@ -1030,6 +1034,11 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key)
WARN_ON
(
!
q
->
rt_waiter
);
WARN_ON
(
!
q
->
rt_waiter
);
q
->
rt_waiter
=
NULL
;
q
->
rt_waiter
=
NULL
;
q
->
lock_ptr
=
&
hb
->
lock
;
#ifdef CONFIG_DEBUG_PI_LIST
q
->
list
.
plist
.
lock
=
&
hb
->
lock
;
#endif
wake_up_state
(
q
->
task
,
TASK_NORMAL
);
wake_up_state
(
q
->
task
,
TASK_NORMAL
);
}
}
...
@@ -1088,7 +1097,7 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
...
@@ -1088,7 +1097,7 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
ret
=
futex_lock_pi_atomic
(
pifutex
,
hb2
,
key2
,
ps
,
top_waiter
->
task
,
ret
=
futex_lock_pi_atomic
(
pifutex
,
hb2
,
key2
,
ps
,
top_waiter
->
task
,
set_waiters
);
set_waiters
);
if
(
ret
==
1
)
if
(
ret
==
1
)
requeue_pi_wake_futex
(
top_waiter
,
key2
);
requeue_pi_wake_futex
(
top_waiter
,
key2
,
hb2
);
return
ret
;
return
ret
;
}
}
...
@@ -1247,8 +1256,15 @@ static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,
...
@@ -1247,8 +1256,15 @@ static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,
if
(
!
match_futex
(
&
this
->
key
,
&
key1
))
if
(
!
match_futex
(
&
this
->
key
,
&
key1
))
continue
;
continue
;
WARN_ON
(
!
requeue_pi
&&
this
->
rt_waiter
);
/*
WARN_ON
(
requeue_pi
&&
!
this
->
rt_waiter
);
* FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always
* be paired with each other and no other futex ops.
*/
if
((
requeue_pi
&&
!
this
->
rt_waiter
)
||
(
!
requeue_pi
&&
this
->
rt_waiter
))
{
ret
=
-
EINVAL
;
break
;
}
/*
/*
* Wake nr_wake waiters. For requeue_pi, if we acquired the
* Wake nr_wake waiters. For requeue_pi, if we acquired the
...
@@ -1273,7 +1289,7 @@ static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,
...
@@ -1273,7 +1289,7 @@ static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,
this
->
task
,
1
);
this
->
task
,
1
);
if
(
ret
==
1
)
{
if
(
ret
==
1
)
{
/* We got the lock. */
/* We got the lock. */
requeue_pi_wake_futex
(
this
,
&
key2
);
requeue_pi_wake_futex
(
this
,
&
key2
,
hb2
);
continue
;
continue
;
}
else
if
(
ret
)
{
}
else
if
(
ret
)
{
/* -EDEADLK */
/* -EDEADLK */
...
...
kernel/futex_compat.c
浏览文件 @
60e0a4c7
...
@@ -180,7 +180,8 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
...
@@ -180,7 +180,8 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
int
cmd
=
op
&
FUTEX_CMD_MASK
;
int
cmd
=
op
&
FUTEX_CMD_MASK
;
if
(
utime
&&
(
cmd
==
FUTEX_WAIT
||
cmd
==
FUTEX_LOCK_PI
||
if
(
utime
&&
(
cmd
==
FUTEX_WAIT
||
cmd
==
FUTEX_LOCK_PI
||
cmd
==
FUTEX_WAIT_BITSET
))
{
cmd
==
FUTEX_WAIT_BITSET
||
cmd
==
FUTEX_WAIT_REQUEUE_PI
))
{
if
(
get_compat_timespec
(
&
ts
,
utime
))
if
(
get_compat_timespec
(
&
ts
,
utime
))
return
-
EFAULT
;
return
-
EFAULT
;
if
(
!
timespec_valid
(
&
ts
))
if
(
!
timespec_valid
(
&
ts
))
...
@@ -191,7 +192,8 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
...
@@ -191,7 +192,8 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
t
=
ktime_add_safe
(
ktime_get
(),
t
);
t
=
ktime_add_safe
(
ktime_get
(),
t
);
tp
=
&
t
;
tp
=
&
t
;
}
}
if
(
cmd
==
FUTEX_REQUEUE
||
cmd
==
FUTEX_CMP_REQUEUE
)
if
(
cmd
==
FUTEX_REQUEUE
||
cmd
==
FUTEX_CMP_REQUEUE
||
cmd
==
FUTEX_CMP_REQUEUE_PI
||
cmd
==
FUTEX_WAKE_OP
)
val2
=
(
int
)
(
unsigned
long
)
utime
;
val2
=
(
int
)
(
unsigned
long
)
utime
;
return
do_futex
(
uaddr
,
op
,
val
,
tp
,
uaddr2
,
val2
,
val3
);
return
do_futex
(
uaddr
,
op
,
val
,
tp
,
uaddr2
,
val2
,
val3
);
...
...
kernel/irq/manage.c
浏览文件 @
60e0a4c7
...
@@ -761,7 +761,6 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
...
@@ -761,7 +761,6 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
{
{
struct
irq_desc
*
desc
=
irq_to_desc
(
irq
);
struct
irq_desc
*
desc
=
irq_to_desc
(
irq
);
struct
irqaction
*
action
,
**
action_ptr
;
struct
irqaction
*
action
,
**
action_ptr
;
struct
task_struct
*
irqthread
;
unsigned
long
flags
;
unsigned
long
flags
;
WARN
(
in_interrupt
(),
"Trying to free IRQ %d from IRQ context!
\n
"
,
irq
);
WARN
(
in_interrupt
(),
"Trying to free IRQ %d from IRQ context!
\n
"
,
irq
);
...
@@ -809,9 +808,6 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
...
@@ -809,9 +808,6 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
desc
->
chip
->
disable
(
irq
);
desc
->
chip
->
disable
(
irq
);
}
}
irqthread
=
action
->
thread
;
action
->
thread
=
NULL
;
spin_unlock_irqrestore
(
&
desc
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
desc
->
lock
,
flags
);
unregister_handler_proc
(
irq
,
action
);
unregister_handler_proc
(
irq
,
action
);
...
@@ -819,12 +815,6 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
...
@@ -819,12 +815,6 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
/* Make sure it's not being used on another CPU: */
/* Make sure it's not being used on another CPU: */
synchronize_irq
(
irq
);
synchronize_irq
(
irq
);
if
(
irqthread
)
{
if
(
!
test_bit
(
IRQTF_DIED
,
&
action
->
thread_flags
))
kthread_stop
(
irqthread
);
put_task_struct
(
irqthread
);
}
#ifdef CONFIG_DEBUG_SHIRQ
#ifdef CONFIG_DEBUG_SHIRQ
/*
/*
* It's a shared IRQ -- the driver ought to be prepared for an IRQ
* It's a shared IRQ -- the driver ought to be prepared for an IRQ
...
@@ -840,6 +830,13 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
...
@@ -840,6 +830,13 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
local_irq_restore
(
flags
);
local_irq_restore
(
flags
);
}
}
#endif
#endif
if
(
action
->
thread
)
{
if
(
!
test_bit
(
IRQTF_DIED
,
&
action
->
thread_flags
))
kthread_stop
(
action
->
thread
);
put_task_struct
(
action
->
thread
);
}
return
action
;
return
action
;
}
}
...
...
kernel/perf_counter.c
浏览文件 @
60e0a4c7
...
@@ -88,6 +88,7 @@ void __weak hw_perf_disable(void) { barrier(); }
...
@@ -88,6 +88,7 @@ void __weak hw_perf_disable(void) { barrier(); }
void
__weak
hw_perf_enable
(
void
)
{
barrier
();
}
void
__weak
hw_perf_enable
(
void
)
{
barrier
();
}
void
__weak
hw_perf_counter_setup
(
int
cpu
)
{
barrier
();
}
void
__weak
hw_perf_counter_setup
(
int
cpu
)
{
barrier
();
}
void
__weak
hw_perf_counter_setup_online
(
int
cpu
)
{
barrier
();
}
int
__weak
int
__weak
hw_perf_group_sched_in
(
struct
perf_counter
*
group_leader
,
hw_perf_group_sched_in
(
struct
perf_counter
*
group_leader
,
...
@@ -306,6 +307,10 @@ counter_sched_out(struct perf_counter *counter,
...
@@ -306,6 +307,10 @@ counter_sched_out(struct perf_counter *counter,
return
;
return
;
counter
->
state
=
PERF_COUNTER_STATE_INACTIVE
;
counter
->
state
=
PERF_COUNTER_STATE_INACTIVE
;
if
(
counter
->
pending_disable
)
{
counter
->
pending_disable
=
0
;
counter
->
state
=
PERF_COUNTER_STATE_OFF
;
}
counter
->
tstamp_stopped
=
ctx
->
time
;
counter
->
tstamp_stopped
=
ctx
->
time
;
counter
->
pmu
->
disable
(
counter
);
counter
->
pmu
->
disable
(
counter
);
counter
->
oncpu
=
-
1
;
counter
->
oncpu
=
-
1
;
...
@@ -1691,7 +1696,32 @@ static int perf_release(struct inode *inode, struct file *file)
...
@@ -1691,7 +1696,32 @@ static int perf_release(struct inode *inode, struct file *file)
return
0
;
return
0
;
}
}
static
u64
perf_counter_read_tree
(
struct
perf_counter
*
counter
)
static
int
perf_counter_read_size
(
struct
perf_counter
*
counter
)
{
int
entry
=
sizeof
(
u64
);
/* value */
int
size
=
0
;
int
nr
=
1
;
if
(
counter
->
attr
.
read_format
&
PERF_FORMAT_TOTAL_TIME_ENABLED
)
size
+=
sizeof
(
u64
);
if
(
counter
->
attr
.
read_format
&
PERF_FORMAT_TOTAL_TIME_RUNNING
)
size
+=
sizeof
(
u64
);
if
(
counter
->
attr
.
read_format
&
PERF_FORMAT_ID
)
entry
+=
sizeof
(
u64
);
if
(
counter
->
attr
.
read_format
&
PERF_FORMAT_GROUP
)
{
nr
+=
counter
->
group_leader
->
nr_siblings
;
size
+=
sizeof
(
u64
);
}
size
+=
entry
*
nr
;
return
size
;
}
static
u64
perf_counter_read_value
(
struct
perf_counter
*
counter
)
{
{
struct
perf_counter
*
child
;
struct
perf_counter
*
child
;
u64
total
=
0
;
u64
total
=
0
;
...
@@ -1703,14 +1733,96 @@ static u64 perf_counter_read_tree(struct perf_counter *counter)
...
@@ -1703,14 +1733,96 @@ static u64 perf_counter_read_tree(struct perf_counter *counter)
return
total
;
return
total
;
}
}
static
int
perf_counter_read_entry
(
struct
perf_counter
*
counter
,
u64
read_format
,
char
__user
*
buf
)
{
int
n
=
0
,
count
=
0
;
u64
values
[
2
];
values
[
n
++
]
=
perf_counter_read_value
(
counter
);
if
(
read_format
&
PERF_FORMAT_ID
)
values
[
n
++
]
=
primary_counter_id
(
counter
);
count
=
n
*
sizeof
(
u64
);
if
(
copy_to_user
(
buf
,
values
,
count
))
return
-
EFAULT
;
return
count
;
}
static
int
perf_counter_read_group
(
struct
perf_counter
*
counter
,
u64
read_format
,
char
__user
*
buf
)
{
struct
perf_counter
*
leader
=
counter
->
group_leader
,
*
sub
;
int
n
=
0
,
size
=
0
,
err
=
-
EFAULT
;
u64
values
[
3
];
values
[
n
++
]
=
1
+
leader
->
nr_siblings
;
if
(
read_format
&
PERF_FORMAT_TOTAL_TIME_ENABLED
)
{
values
[
n
++
]
=
leader
->
total_time_enabled
+
atomic64_read
(
&
leader
->
child_total_time_enabled
);
}
if
(
read_format
&
PERF_FORMAT_TOTAL_TIME_RUNNING
)
{
values
[
n
++
]
=
leader
->
total_time_running
+
atomic64_read
(
&
leader
->
child_total_time_running
);
}
size
=
n
*
sizeof
(
u64
);
if
(
copy_to_user
(
buf
,
values
,
size
))
return
-
EFAULT
;
err
=
perf_counter_read_entry
(
leader
,
read_format
,
buf
+
size
);
if
(
err
<
0
)
return
err
;
size
+=
err
;
list_for_each_entry
(
sub
,
&
leader
->
sibling_list
,
list_entry
)
{
err
=
perf_counter_read_entry
(
counter
,
read_format
,
buf
+
size
);
if
(
err
<
0
)
return
err
;
size
+=
err
;
}
return
size
;
}
static
int
perf_counter_read_one
(
struct
perf_counter
*
counter
,
u64
read_format
,
char
__user
*
buf
)
{
u64
values
[
4
];
int
n
=
0
;
values
[
n
++
]
=
perf_counter_read_value
(
counter
);
if
(
read_format
&
PERF_FORMAT_TOTAL_TIME_ENABLED
)
{
values
[
n
++
]
=
counter
->
total_time_enabled
+
atomic64_read
(
&
counter
->
child_total_time_enabled
);
}
if
(
read_format
&
PERF_FORMAT_TOTAL_TIME_RUNNING
)
{
values
[
n
++
]
=
counter
->
total_time_running
+
atomic64_read
(
&
counter
->
child_total_time_running
);
}
if
(
read_format
&
PERF_FORMAT_ID
)
values
[
n
++
]
=
primary_counter_id
(
counter
);
if
(
copy_to_user
(
buf
,
values
,
n
*
sizeof
(
u64
)))
return
-
EFAULT
;
return
n
*
sizeof
(
u64
);
}
/*
/*
* Read the performance counter - simple non blocking version for now
* Read the performance counter - simple non blocking version for now
*/
*/
static
ssize_t
static
ssize_t
perf_read_hw
(
struct
perf_counter
*
counter
,
char
__user
*
buf
,
size_t
count
)
perf_read_hw
(
struct
perf_counter
*
counter
,
char
__user
*
buf
,
size_t
count
)
{
{
u64
values
[
4
]
;
u64
read_format
=
counter
->
attr
.
read_format
;
int
n
;
int
ret
;
/*
/*
* Return end-of-file for a read on a counter that is in
* Return end-of-file for a read on a counter that is in
...
@@ -1720,28 +1832,18 @@ perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count)
...
@@ -1720,28 +1832,18 @@ perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count)
if
(
counter
->
state
==
PERF_COUNTER_STATE_ERROR
)
if
(
counter
->
state
==
PERF_COUNTER_STATE_ERROR
)
return
0
;
return
0
;
if
(
count
<
perf_counter_read_size
(
counter
))
return
-
ENOSPC
;
WARN_ON_ONCE
(
counter
->
ctx
->
parent_ctx
);
WARN_ON_ONCE
(
counter
->
ctx
->
parent_ctx
);
mutex_lock
(
&
counter
->
child_mutex
);
mutex_lock
(
&
counter
->
child_mutex
);
values
[
0
]
=
perf_counter_read_tree
(
counter
);
if
(
read_format
&
PERF_FORMAT_GROUP
)
n
=
1
;
ret
=
perf_counter_read_group
(
counter
,
read_format
,
buf
);
if
(
counter
->
attr
.
read_format
&
PERF_FORMAT_TOTAL_TIME_ENABLED
)
else
values
[
n
++
]
=
counter
->
total_time_enabled
+
ret
=
perf_counter_read_one
(
counter
,
read_format
,
buf
);
atomic64_read
(
&
counter
->
child_total_time_enabled
);
if
(
counter
->
attr
.
read_format
&
PERF_FORMAT_TOTAL_TIME_RUNNING
)
values
[
n
++
]
=
counter
->
total_time_running
+
atomic64_read
(
&
counter
->
child_total_time_running
);
if
(
counter
->
attr
.
read_format
&
PERF_FORMAT_ID
)
values
[
n
++
]
=
primary_counter_id
(
counter
);
mutex_unlock
(
&
counter
->
child_mutex
);
mutex_unlock
(
&
counter
->
child_mutex
);
if
(
count
<
n
*
sizeof
(
u64
))
return
ret
;
return
-
EINVAL
;
count
=
n
*
sizeof
(
u64
);
if
(
copy_to_user
(
buf
,
values
,
count
))
return
-
EFAULT
;
return
count
;
}
}
static
ssize_t
static
ssize_t
...
@@ -2245,7 +2347,7 @@ static void perf_pending_counter(struct perf_pending_entry *entry)
...
@@ -2245,7 +2347,7 @@ static void perf_pending_counter(struct perf_pending_entry *entry)
if
(
counter
->
pending_disable
)
{
if
(
counter
->
pending_disable
)
{
counter
->
pending_disable
=
0
;
counter
->
pending_disable
=
0
;
perf_counter_disable
(
counter
);
__
perf_counter_disable
(
counter
);
}
}
if
(
counter
->
pending_wakeup
)
{
if
(
counter
->
pending_wakeup
)
{
...
@@ -2630,7 +2732,80 @@ static u32 perf_counter_tid(struct perf_counter *counter, struct task_struct *p)
...
@@ -2630,7 +2732,80 @@ static u32 perf_counter_tid(struct perf_counter *counter, struct task_struct *p)
return
task_pid_nr_ns
(
p
,
counter
->
ns
);
return
task_pid_nr_ns
(
p
,
counter
->
ns
);
}
}
static
void
perf_counter_output
(
struct
perf_counter
*
counter
,
int
nmi
,
static
void
perf_output_read_one
(
struct
perf_output_handle
*
handle
,
struct
perf_counter
*
counter
)
{
u64
read_format
=
counter
->
attr
.
read_format
;
u64
values
[
4
];
int
n
=
0
;
values
[
n
++
]
=
atomic64_read
(
&
counter
->
count
);
if
(
read_format
&
PERF_FORMAT_TOTAL_TIME_ENABLED
)
{
values
[
n
++
]
=
counter
->
total_time_enabled
+
atomic64_read
(
&
counter
->
child_total_time_enabled
);
}
if
(
read_format
&
PERF_FORMAT_TOTAL_TIME_RUNNING
)
{
values
[
n
++
]
=
counter
->
total_time_running
+
atomic64_read
(
&
counter
->
child_total_time_running
);
}
if
(
read_format
&
PERF_FORMAT_ID
)
values
[
n
++
]
=
primary_counter_id
(
counter
);
perf_output_copy
(
handle
,
values
,
n
*
sizeof
(
u64
));
}
/*
* XXX PERF_FORMAT_GROUP vs inherited counters seems difficult.
*/
static
void
perf_output_read_group
(
struct
perf_output_handle
*
handle
,
struct
perf_counter
*
counter
)
{
struct
perf_counter
*
leader
=
counter
->
group_leader
,
*
sub
;
u64
read_format
=
counter
->
attr
.
read_format
;
u64
values
[
5
];
int
n
=
0
;
values
[
n
++
]
=
1
+
leader
->
nr_siblings
;
if
(
read_format
&
PERF_FORMAT_TOTAL_TIME_ENABLED
)
values
[
n
++
]
=
leader
->
total_time_enabled
;
if
(
read_format
&
PERF_FORMAT_TOTAL_TIME_RUNNING
)
values
[
n
++
]
=
leader
->
total_time_running
;
if
(
leader
!=
counter
)
leader
->
pmu
->
read
(
leader
);
values
[
n
++
]
=
atomic64_read
(
&
leader
->
count
);
if
(
read_format
&
PERF_FORMAT_ID
)
values
[
n
++
]
=
primary_counter_id
(
leader
);
perf_output_copy
(
handle
,
values
,
n
*
sizeof
(
u64
));
list_for_each_entry
(
sub
,
&
leader
->
sibling_list
,
list_entry
)
{
n
=
0
;
if
(
sub
!=
counter
)
sub
->
pmu
->
read
(
sub
);
values
[
n
++
]
=
atomic64_read
(
&
sub
->
count
);
if
(
read_format
&
PERF_FORMAT_ID
)
values
[
n
++
]
=
primary_counter_id
(
sub
);
perf_output_copy
(
handle
,
values
,
n
*
sizeof
(
u64
));
}
}
static
void
perf_output_read
(
struct
perf_output_handle
*
handle
,
struct
perf_counter
*
counter
)
{
if
(
counter
->
attr
.
read_format
&
PERF_FORMAT_GROUP
)
perf_output_read_group
(
handle
,
counter
);
else
perf_output_read_one
(
handle
,
counter
);
}
void
perf_counter_output
(
struct
perf_counter
*
counter
,
int
nmi
,
struct
perf_sample_data
*
data
)
struct
perf_sample_data
*
data
)
{
{
int
ret
;
int
ret
;
...
@@ -2641,10 +2816,6 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
...
@@ -2641,10 +2816,6 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
struct
{
struct
{
u32
pid
,
tid
;
u32
pid
,
tid
;
}
tid_entry
;
}
tid_entry
;
struct
{
u64
id
;
u64
counter
;
}
group_entry
;
struct
perf_callchain_entry
*
callchain
=
NULL
;
struct
perf_callchain_entry
*
callchain
=
NULL
;
int
callchain_size
=
0
;
int
callchain_size
=
0
;
u64
time
;
u64
time
;
...
@@ -2699,10 +2870,8 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
...
@@ -2699,10 +2870,8 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
if
(
sample_type
&
PERF_SAMPLE_PERIOD
)
if
(
sample_type
&
PERF_SAMPLE_PERIOD
)
header
.
size
+=
sizeof
(
u64
);
header
.
size
+=
sizeof
(
u64
);
if
(
sample_type
&
PERF_SAMPLE_GROUP
)
{
if
(
sample_type
&
PERF_SAMPLE_READ
)
header
.
size
+=
sizeof
(
u64
)
+
header
.
size
+=
perf_counter_read_size
(
counter
);
counter
->
nr_siblings
*
sizeof
(
group_entry
);
}
if
(
sample_type
&
PERF_SAMPLE_CALLCHAIN
)
{
if
(
sample_type
&
PERF_SAMPLE_CALLCHAIN
)
{
callchain
=
perf_callchain
(
data
->
regs
);
callchain
=
perf_callchain
(
data
->
regs
);
...
@@ -2759,26 +2928,8 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
...
@@ -2759,26 +2928,8 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
if
(
sample_type
&
PERF_SAMPLE_PERIOD
)
if
(
sample_type
&
PERF_SAMPLE_PERIOD
)
perf_output_put
(
&
handle
,
data
->
period
);
perf_output_put
(
&
handle
,
data
->
period
);
/*
if
(
sample_type
&
PERF_SAMPLE_READ
)
* XXX PERF_SAMPLE_GROUP vs inherited counters seems difficult.
perf_output_read
(
&
handle
,
counter
);
*/
if
(
sample_type
&
PERF_SAMPLE_GROUP
)
{
struct
perf_counter
*
leader
,
*
sub
;
u64
nr
=
counter
->
nr_siblings
;
perf_output_put
(
&
handle
,
nr
);
leader
=
counter
->
group_leader
;
list_for_each_entry
(
sub
,
&
leader
->
sibling_list
,
list_entry
)
{
if
(
sub
!=
counter
)
sub
->
pmu
->
read
(
sub
);
group_entry
.
id
=
primary_counter_id
(
sub
);
group_entry
.
counter
=
atomic64_read
(
&
sub
->
count
);
perf_output_put
(
&
handle
,
group_entry
);
}
}
if
(
sample_type
&
PERF_SAMPLE_CALLCHAIN
)
{
if
(
sample_type
&
PERF_SAMPLE_CALLCHAIN
)
{
if
(
callchain
)
if
(
callchain
)
...
@@ -2817,8 +2968,6 @@ struct perf_read_event {
...
@@ -2817,8 +2968,6 @@ struct perf_read_event {
u32
pid
;
u32
pid
;
u32
tid
;
u32
tid
;
u64
value
;
u64
format
[
3
];
};
};
static
void
static
void
...
@@ -2830,34 +2979,20 @@ perf_counter_read_event(struct perf_counter *counter,
...
@@ -2830,34 +2979,20 @@ perf_counter_read_event(struct perf_counter *counter,
.
header
=
{
.
header
=
{
.
type
=
PERF_EVENT_READ
,
.
type
=
PERF_EVENT_READ
,
.
misc
=
0
,
.
misc
=
0
,
.
size
=
sizeof
(
event
)
-
sizeof
(
event
.
format
),
.
size
=
sizeof
(
event
)
+
perf_counter_read_size
(
counter
),
},
},
.
pid
=
perf_counter_pid
(
counter
,
task
),
.
pid
=
perf_counter_pid
(
counter
,
task
),
.
tid
=
perf_counter_tid
(
counter
,
task
),
.
tid
=
perf_counter_tid
(
counter
,
task
),
.
value
=
atomic64_read
(
&
counter
->
count
),
};
};
int
ret
,
i
=
0
;
int
ret
;
if
(
counter
->
attr
.
read_format
&
PERF_FORMAT_TOTAL_TIME_ENABLED
)
{
event
.
header
.
size
+=
sizeof
(
u64
);
event
.
format
[
i
++
]
=
counter
->
total_time_enabled
;
}
if
(
counter
->
attr
.
read_format
&
PERF_FORMAT_TOTAL_TIME_RUNNING
)
{
event
.
header
.
size
+=
sizeof
(
u64
);
event
.
format
[
i
++
]
=
counter
->
total_time_running
;
}
if
(
counter
->
attr
.
read_format
&
PERF_FORMAT_ID
)
{
event
.
header
.
size
+=
sizeof
(
u64
);
event
.
format
[
i
++
]
=
primary_counter_id
(
counter
);
}
ret
=
perf_output_begin
(
&
handle
,
counter
,
event
.
header
.
size
,
0
,
0
);
ret
=
perf_output_begin
(
&
handle
,
counter
,
event
.
header
.
size
,
0
,
0
);
if
(
ret
)
if
(
ret
)
return
;
return
;
perf_output_copy
(
&
handle
,
&
event
,
event
.
header
.
size
);
perf_output_put
(
&
handle
,
event
);
perf_output_read
(
&
handle
,
counter
);
perf_output_end
(
&
handle
);
perf_output_end
(
&
handle
);
}
}
...
@@ -2893,10 +3028,10 @@ static void perf_counter_task_output(struct perf_counter *counter,
...
@@ -2893,10 +3028,10 @@ static void perf_counter_task_output(struct perf_counter *counter,
return
;
return
;
task_event
->
event
.
pid
=
perf_counter_pid
(
counter
,
task
);
task_event
->
event
.
pid
=
perf_counter_pid
(
counter
,
task
);
task_event
->
event
.
ppid
=
perf_counter_pid
(
counter
,
task
->
real_pa
rent
);
task_event
->
event
.
ppid
=
perf_counter_pid
(
counter
,
cur
rent
);
task_event
->
event
.
tid
=
perf_counter_tid
(
counter
,
task
);
task_event
->
event
.
tid
=
perf_counter_tid
(
counter
,
task
);
task_event
->
event
.
ptid
=
perf_counter_tid
(
counter
,
task
->
real_pa
rent
);
task_event
->
event
.
ptid
=
perf_counter_tid
(
counter
,
cur
rent
);
perf_output_put
(
&
handle
,
task_event
->
event
);
perf_output_put
(
&
handle
,
task_event
->
event
);
perf_output_end
(
&
handle
);
perf_output_end
(
&
handle
);
...
@@ -3443,40 +3578,32 @@ static void perf_swcounter_add(struct perf_counter *counter, u64 nr,
...
@@ -3443,40 +3578,32 @@ static void perf_swcounter_add(struct perf_counter *counter, u64 nr,
static
int
perf_swcounter_is_counting
(
struct
perf_counter
*
counter
)
static
int
perf_swcounter_is_counting
(
struct
perf_counter
*
counter
)
{
{
struct
perf_counter_context
*
ctx
;
/*
unsigned
long
flags
;
* The counter is active, we're good!
int
count
;
*/
if
(
counter
->
state
==
PERF_COUNTER_STATE_ACTIVE
)
if
(
counter
->
state
==
PERF_COUNTER_STATE_ACTIVE
)
return
1
;
return
1
;
/*
* The counter is off/error, not counting.
*/
if
(
counter
->
state
!=
PERF_COUNTER_STATE_INACTIVE
)
if
(
counter
->
state
!=
PERF_COUNTER_STATE_INACTIVE
)
return
0
;
return
0
;
/*
/*
* If the counter is inactive, it could be just because
* The counter is inactive, if the context is active
* its task is scheduled out, or because it's in a group
* we're part of a group that didn't make it on the 'pmu',
* which could not go on the PMU. We want to count in
* not counting.
* the first case but not the second. If the context is
* currently active then an inactive software counter must
* be the second case. If it's not currently active then
* we need to know whether the counter was active when the
* context was last active, which we can determine by
* comparing counter->tstamp_stopped with ctx->time.
*
* We are within an RCU read-side critical section,
* which protects the existence of *ctx.
*/
*/
ctx
=
counter
->
ctx
;
if
(
counter
->
ctx
->
is_active
)
spin_lock_irqsave
(
&
ctx
->
lock
,
flags
);
return
0
;
count
=
1
;
/* Re-check state now we have the lock */
/*
if
(
counter
->
state
<
PERF_COUNTER_STATE_INACTIVE
||
* We're inactive and the context is too, this means the
counter
->
ctx
->
is_active
||
* task is scheduled out, we're counting events that happen
counter
->
tstamp_stopped
<
ctx
->
time
)
* to us, like migration events.
count
=
0
;
*/
spin_unlock_irqrestore
(
&
ctx
->
lock
,
flags
);
return
1
;
return
count
;
}
}
static
int
perf_swcounter_match
(
struct
perf_counter
*
counter
,
static
int
perf_swcounter_match
(
struct
perf_counter
*
counter
,
...
@@ -3928,9 +4055,9 @@ perf_counter_alloc(struct perf_counter_attr *attr,
...
@@ -3928,9 +4055,9 @@ perf_counter_alloc(struct perf_counter_attr *attr,
atomic64_set
(
&
hwc
->
period_left
,
hwc
->
sample_period
);
atomic64_set
(
&
hwc
->
period_left
,
hwc
->
sample_period
);
/*
/*
* we currently do not support PERF_
SAMPLE
_GROUP on inherited counters
* we currently do not support PERF_
FORMAT
_GROUP on inherited counters
*/
*/
if
(
attr
->
inherit
&&
(
attr
->
sample_type
&
PERF_SAMPLE
_GROUP
))
if
(
attr
->
inherit
&&
(
attr
->
read_format
&
PERF_FORMAT
_GROUP
))
goto
done
;
goto
done
;
switch
(
attr
->
type
)
{
switch
(
attr
->
type
)
{
...
@@ -4592,6 +4719,11 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
...
@@ -4592,6 +4719,11 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
perf_counter_init_cpu
(
cpu
);
perf_counter_init_cpu
(
cpu
);
break
;
break
;
case
CPU_ONLINE
:
case
CPU_ONLINE_FROZEN
:
hw_perf_counter_setup_online
(
cpu
);
break
;
case
CPU_DOWN_PREPARE
:
case
CPU_DOWN_PREPARE
:
case
CPU_DOWN_PREPARE_FROZEN
:
case
CPU_DOWN_PREPARE_FROZEN
:
perf_counter_exit_cpu
(
cpu
);
perf_counter_exit_cpu
(
cpu
);
...
@@ -4616,6 +4748,8 @@ void __init perf_counter_init(void)
...
@@ -4616,6 +4748,8 @@ void __init perf_counter_init(void)
{
{
perf_cpu_notify
(
&
perf_cpu_nb
,
(
unsigned
long
)
CPU_UP_PREPARE
,
perf_cpu_notify
(
&
perf_cpu_nb
,
(
unsigned
long
)
CPU_UP_PREPARE
,
(
void
*
)(
long
)
smp_processor_id
());
(
void
*
)(
long
)
smp_processor_id
());
perf_cpu_notify
(
&
perf_cpu_nb
,
(
unsigned
long
)
CPU_ONLINE
,
(
void
*
)(
long
)
smp_processor_id
());
register_cpu_notifier
(
&
perf_cpu_nb
);
register_cpu_notifier
(
&
perf_cpu_nb
);
}
}
...
...
kernel/wait.c
浏览文件 @
60e0a4c7
...
@@ -10,13 +10,14 @@
...
@@ -10,13 +10,14 @@
#include <linux/wait.h>
#include <linux/wait.h>
#include <linux/hash.h>
#include <linux/hash.h>
void
init_waitqueue_head
(
wait_queue_head_t
*
q
)
void
__init_waitqueue_head
(
wait_queue_head_t
*
q
,
struct
lock_class_key
*
key
)
{
{
spin_lock_init
(
&
q
->
lock
);
spin_lock_init
(
&
q
->
lock
);
lockdep_set_class
(
&
q
->
lock
,
key
);
INIT_LIST_HEAD
(
&
q
->
task_list
);
INIT_LIST_HEAD
(
&
q
->
task_list
);
}
}
EXPORT_SYMBOL
(
init_waitqueue_head
);
EXPORT_SYMBOL
(
__
init_waitqueue_head
);
void
add_wait_queue
(
wait_queue_head_t
*
q
,
wait_queue_t
*
wait
)
void
add_wait_queue
(
wait_queue_head_t
*
q
,
wait_queue_t
*
wait
)
{
{
...
...
net/socket.c
浏览文件 @
60e0a4c7
...
@@ -736,7 +736,7 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
...
@@ -736,7 +736,7 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
if
(
more
)
if
(
more
)
flags
|=
MSG_MORE
;
flags
|=
MSG_MORE
;
return
sock
->
ops
->
sendpage
(
sock
,
page
,
offset
,
size
,
flags
);
return
kernel_
sendpage
(
sock
,
page
,
offset
,
size
,
flags
);
}
}
static
ssize_t
sock_splice_read
(
struct
file
*
file
,
loff_t
*
ppos
,
static
ssize_t
sock_splice_read
(
struct
file
*
file
,
loff_t
*
ppos
,
...
...
tools/perf/Makefile
浏览文件 @
60e0a4c7
...
@@ -382,23 +382,30 @@ endif
...
@@ -382,23 +382,30 @@ endif
ifdef
NO_DEMANGLE
ifdef
NO_DEMANGLE
BASIC_CFLAGS
+=
-DNO_DEMANGLE
BASIC_CFLAGS
+=
-DNO_DEMANGLE
else
else
has_bfd
:=
$(
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 > /dev/null 2>&1 && echo y"
)
has_bfd
:=
$(
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 > /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
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"
)
ifeq
($(has_bfd_iberty),y)
EXTLIBS
+=
-lbfd
-liberty
EXTLIBS
+=
-lbfd
-liberty
else
ifeq
($(has_bfd_iberty_z),y)
else
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_iberty_z),y)
EXTLIBS
+=
-lbfd
-liberty
-lz
EXTLIBS
+=
-lbfd
-liberty
-lz
else
has_cplus_demangle
:=
$(
shell
sh
-c
"(echo 'extern char *cplus_demangle(const char *, int
)
;'; echo 'int main(void
)
{ cplus_demangle(0, 0
)
; return 0;
}
'
)
|
$(CC)
-x c -
$(ALL_CFLAGS)
-o /dev/null
$(ALL_LDFLAGS)
-liberty > /dev/null 2>&1 && echo y"
)
ifeq
($(has_cplus_demangle),y)
EXTLIBS
+=
-liberty
BASIC_CFLAGS
+=
-DHAVE_CPLUS_DEMANGLE
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
endif
endif
endif
endif
endif
endif
endif
ifndef
CC_LD_DYNPATH
ifndef
CC_LD_DYNPATH
...
...
tools/perf/builtin-list.c
浏览文件 @
60e0a4c7
...
@@ -10,11 +10,12 @@
...
@@ -10,11 +10,12 @@
#include "perf.h"
#include "perf.h"
#include "util/parse-options.h"
#include "util/parse-events.h"
#include "util/parse-events.h"
#include "util/cache.h"
int
cmd_list
(
int
argc
__used
,
const
char
**
argv
__used
,
const
char
*
prefix
__used
)
int
cmd_list
(
int
argc
__used
,
const
char
**
argv
__used
,
const
char
*
prefix
__used
)
{
{
setup_pager
();
print_events
();
print_events
();
return
0
;
return
0
;
}
}
tools/perf/builtin-record.c
浏览文件 @
60e0a4c7
...
@@ -34,7 +34,9 @@ static int output;
...
@@ -34,7 +34,9 @@ static int output;
static
const
char
*
output_name
=
"perf.data"
;
static
const
char
*
output_name
=
"perf.data"
;
static
int
group
=
0
;
static
int
group
=
0
;
static
unsigned
int
realtime_prio
=
0
;
static
unsigned
int
realtime_prio
=
0
;
static
int
raw_samples
=
0
;
static
int
system_wide
=
0
;
static
int
system_wide
=
0
;
static
int
profile_cpu
=
-
1
;
static
pid_t
target_pid
=
-
1
;
static
pid_t
target_pid
=
-
1
;
static
int
inherit
=
1
;
static
int
inherit
=
1
;
static
int
force
=
0
;
static
int
force
=
0
;
...
@@ -203,46 +205,48 @@ static void sig_atexit(void)
...
@@ -203,46 +205,48 @@ static void sig_atexit(void)
kill
(
getpid
(),
signr
);
kill
(
getpid
(),
signr
);
}
}
static
void
pid_synthesize_comm_event
(
pid_t
pid
,
int
full
)
static
pid_t
pid_synthesize_comm_event
(
pid_t
pid
,
int
full
)
{
{
struct
comm_event
comm_ev
;
struct
comm_event
comm_ev
;
char
filename
[
PATH_MAX
];
char
filename
[
PATH_MAX
];
char
bf
[
BUFSIZ
];
char
bf
[
BUFSIZ
];
int
fd
;
FILE
*
fp
;
size_t
size
;
size_t
size
=
0
;
char
*
field
,
*
sep
;
DIR
*
tasks
;
DIR
*
tasks
;
struct
dirent
dirent
,
*
next
;
struct
dirent
dirent
,
*
next
;
pid_t
tgid
=
0
;
snprintf
(
filename
,
sizeof
(
filename
),
"/proc/%d/stat"
,
pid
);
snprintf
(
filename
,
sizeof
(
filename
),
"/proc/%d/stat
us
"
,
pid
);
f
d
=
open
(
filename
,
O_RDONLY
);
f
p
=
fopen
(
filename
,
"r"
);
if
(
fd
<
0
)
{
if
(
fd
==
NULL
)
{
/*
/*
* We raced with a task exiting - just return:
* We raced with a task exiting - just return:
*/
*/
if
(
verbose
)
if
(
verbose
)
fprintf
(
stderr
,
"couldn't open %s
\n
"
,
filename
);
fprintf
(
stderr
,
"couldn't open %s
\n
"
,
filename
);
return
;
return
0
;
}
if
(
read
(
fd
,
bf
,
sizeof
(
bf
))
<
0
)
{
fprintf
(
stderr
,
"couldn't read %s
\n
"
,
filename
);
exit
(
EXIT_FAILURE
);
}
}
close
(
fd
);
/* 9027 (cat) R 6747 9027 6747 34816 9027 ... */
memset
(
&
comm_ev
,
0
,
sizeof
(
comm_ev
));
memset
(
&
comm_ev
,
0
,
sizeof
(
comm_ev
));
field
=
strchr
(
bf
,
'('
);
while
(
!
comm_ev
.
comm
[
0
]
||
!
comm_ev
.
pid
)
{
if
(
field
==
NULL
)
if
(
fgets
(
bf
,
sizeof
(
bf
),
fp
)
==
NULL
)
goto
out_failure
;
sep
=
strchr
(
++
field
,
')'
);
if
(
sep
==
NULL
)
goto
out_failure
;
goto
out_failure
;
size
=
sep
-
field
;
memcpy
(
comm_ev
.
comm
,
field
,
size
++
);
comm_ev
.
pid
=
pid
;
if
(
memcmp
(
bf
,
"Name:"
,
5
)
==
0
)
{
char
*
name
=
bf
+
5
;
while
(
*
name
&&
isspace
(
*
name
))
++
name
;
size
=
strlen
(
name
)
-
1
;
memcpy
(
comm_ev
.
comm
,
name
,
size
++
);
}
else
if
(
memcmp
(
bf
,
"Tgid:"
,
5
)
==
0
)
{
char
*
tgids
=
bf
+
5
;
while
(
*
tgids
&&
isspace
(
*
tgids
))
++
tgids
;
tgid
=
comm_ev
.
pid
=
atoi
(
tgids
);
}
}
comm_ev
.
header
.
type
=
PERF_EVENT_COMM
;
comm_ev
.
header
.
type
=
PERF_EVENT_COMM
;
size
=
ALIGN
(
size
,
sizeof
(
u64
));
size
=
ALIGN
(
size
,
sizeof
(
u64
));
comm_ev
.
header
.
size
=
sizeof
(
comm_ev
)
-
(
sizeof
(
comm_ev
.
comm
)
-
size
);
comm_ev
.
header
.
size
=
sizeof
(
comm_ev
)
-
(
sizeof
(
comm_ev
.
comm
)
-
size
);
...
@@ -251,7 +255,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
...
@@ -251,7 +255,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
comm_ev
.
tid
=
pid
;
comm_ev
.
tid
=
pid
;
write_output
(
&
comm_ev
,
comm_ev
.
header
.
size
);
write_output
(
&
comm_ev
,
comm_ev
.
header
.
size
);
return
;
goto
out_fclose
;
}
}
snprintf
(
filename
,
sizeof
(
filename
),
"/proc/%d/task"
,
pid
);
snprintf
(
filename
,
sizeof
(
filename
),
"/proc/%d/task"
,
pid
);
...
@@ -268,7 +272,10 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
...
@@ -268,7 +272,10 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
write_output
(
&
comm_ev
,
comm_ev
.
header
.
size
);
write_output
(
&
comm_ev
,
comm_ev
.
header
.
size
);
}
}
closedir
(
tasks
);
closedir
(
tasks
);
return
;
out_fclose:
fclose
(
fp
);
return
tgid
;
out_failure:
out_failure:
fprintf
(
stderr
,
"couldn't get COMM and pgid, malformed %s
\n
"
,
fprintf
(
stderr
,
"couldn't get COMM and pgid, malformed %s
\n
"
,
...
@@ -276,7 +283,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
...
@@ -276,7 +283,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
static
void
pid_synthesize_mmap_samples
(
pid_t
pid
)
static
void
pid_synthesize_mmap_samples
(
pid_t
pid
,
pid_t
tgid
)
{
{
char
filename
[
PATH_MAX
];
char
filename
[
PATH_MAX
];
FILE
*
fp
;
FILE
*
fp
;
...
@@ -328,7 +335,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
...
@@ -328,7 +335,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
mmap_ev
.
len
-=
mmap_ev
.
start
;
mmap_ev
.
len
-=
mmap_ev
.
start
;
mmap_ev
.
header
.
size
=
(
sizeof
(
mmap_ev
)
-
mmap_ev
.
header
.
size
=
(
sizeof
(
mmap_ev
)
-
(
sizeof
(
mmap_ev
.
filename
)
-
size
));
(
sizeof
(
mmap_ev
.
filename
)
-
size
));
mmap_ev
.
pid
=
p
id
;
mmap_ev
.
pid
=
tg
id
;
mmap_ev
.
tid
=
pid
;
mmap_ev
.
tid
=
pid
;
write_output
(
&
mmap_ev
,
mmap_ev
.
header
.
size
);
write_output
(
&
mmap_ev
,
mmap_ev
.
header
.
size
);
...
@@ -347,14 +354,14 @@ static void synthesize_all(void)
...
@@ -347,14 +354,14 @@ static void synthesize_all(void)
while
(
!
readdir_r
(
proc
,
&
dirent
,
&
next
)
&&
next
)
{
while
(
!
readdir_r
(
proc
,
&
dirent
,
&
next
)
&&
next
)
{
char
*
end
;
char
*
end
;
pid_t
pid
;
pid_t
pid
,
tgid
;
pid
=
strtol
(
dirent
.
d_name
,
&
end
,
10
);
pid
=
strtol
(
dirent
.
d_name
,
&
end
,
10
);
if
(
*
end
)
/* only interested in proper numerical dirents */
if
(
*
end
)
/* only interested in proper numerical dirents */
continue
;
continue
;
pid_synthesize_comm_event
(
pid
,
1
);
tgid
=
pid_synthesize_comm_event
(
pid
,
1
);
pid_synthesize_mmap_samples
(
pid
);
pid_synthesize_mmap_samples
(
pid
,
tgid
);
}
}
closedir
(
proc
);
closedir
(
proc
);
...
@@ -392,7 +399,7 @@ static void create_counter(int counter, int cpu, pid_t pid)
...
@@ -392,7 +399,7 @@ static void create_counter(int counter, int cpu, pid_t pid)
PERF_FORMAT_TOTAL_TIME_RUNNING
|
PERF_FORMAT_TOTAL_TIME_RUNNING
|
PERF_FORMAT_ID
;
PERF_FORMAT_ID
;
attr
->
sample_type
=
PERF_SAMPLE_IP
|
PERF_SAMPLE_TID
;
attr
->
sample_type
|
=
PERF_SAMPLE_IP
|
PERF_SAMPLE_TID
;
if
(
freq
)
{
if
(
freq
)
{
attr
->
sample_type
|=
PERF_SAMPLE_PERIOD
;
attr
->
sample_type
|=
PERF_SAMPLE_PERIOD
;
...
@@ -412,6 +419,8 @@ static void create_counter(int counter, int cpu, pid_t pid)
...
@@ -412,6 +419,8 @@ static void create_counter(int counter, int cpu, pid_t pid)
if
(
call_graph
)
if
(
call_graph
)
attr
->
sample_type
|=
PERF_SAMPLE_CALLCHAIN
;
attr
->
sample_type
|=
PERF_SAMPLE_CALLCHAIN
;
if
(
raw_samples
)
attr
->
sample_type
|=
PERF_SAMPLE_RAW
;
attr
->
mmap
=
track
;
attr
->
mmap
=
track
;
attr
->
comm
=
track
;
attr
->
comm
=
track
;
...
@@ -426,6 +435,8 @@ static void create_counter(int counter, int cpu, pid_t pid)
...
@@ -426,6 +435,8 @@ static void create_counter(int counter, int cpu, pid_t pid)
if
(
err
==
EPERM
)
if
(
err
==
EPERM
)
die
(
"Permission error - are you root?
\n
"
);
die
(
"Permission error - are you root?
\n
"
);
else
if
(
err
==
ENODEV
&&
profile_cpu
!=
-
1
)
die
(
"No such device - did you specify an out-of-range profile CPU?
\n
"
);
/*
/*
* If it's cycles then fall back to hrtimer
* If it's cycles then fall back to hrtimer
...
@@ -559,16 +570,22 @@ static int __cmd_record(int argc, const char **argv)
...
@@ -559,16 +570,22 @@ static int __cmd_record(int argc, const char **argv)
if
(
pid
==
-
1
)
if
(
pid
==
-
1
)
pid
=
getpid
();
pid
=
getpid
();
open_counters
(
-
1
,
pid
);
open_counters
(
profile_cpu
,
pid
);
}
else
for
(
i
=
0
;
i
<
nr_cpus
;
i
++
)
}
else
{
if
(
profile_cpu
!=
-
1
)
{
open_counters
(
profile_cpu
,
target_pid
);
}
else
{
for
(
i
=
0
;
i
<
nr_cpus
;
i
++
)
open_counters
(
i
,
target_pid
);
open_counters
(
i
,
target_pid
);
}
}
if
(
file_new
)
if
(
file_new
)
perf_header__write
(
header
,
output
);
perf_header__write
(
header
,
output
);
if
(
!
system_wide
)
{
if
(
!
system_wide
)
{
pid_synthesize_comm_event
(
pid
,
0
);
pid_
t
tgid
=
pid_
synthesize_comm_event
(
pid
,
0
);
pid_synthesize_mmap_samples
(
pid
);
pid_synthesize_mmap_samples
(
pid
,
tgid
);
}
else
}
else
synthesize_all
();
synthesize_all
();
...
@@ -636,10 +653,14 @@ static const struct option options[] = {
...
@@ -636,10 +653,14 @@ static const struct option options[] = {
"record events on existing pid"
),
"record events on existing pid"
),
OPT_INTEGER
(
'r'
,
"realtime"
,
&
realtime_prio
,
OPT_INTEGER
(
'r'
,
"realtime"
,
&
realtime_prio
,
"collect data with this RT SCHED_FIFO priority"
),
"collect data with this RT SCHED_FIFO priority"
),
OPT_BOOLEAN
(
'R'
,
"raw-samples"
,
&
raw_samples
,
"collect raw sample records from all opened counters"
),
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
(
'A'
,
"append"
,
&
append_file
,
OPT_BOOLEAN
(
'A'
,
"append"
,
&
append_file
,
"append to the output file to do incremental profiling"
),
"append to the output file to do incremental profiling"
),
OPT_INTEGER
(
'C'
,
"profile_cpu"
,
&
profile_cpu
,
"CPU to profile on"
),
OPT_BOOLEAN
(
'f'
,
"force"
,
&
force
,
OPT_BOOLEAN
(
'f'
,
"force"
,
&
force
,
"overwrite existing data file"
),
"overwrite existing data file"
),
OPT_LONG
(
'c'
,
"count"
,
&
default_interval
,
OPT_LONG
(
'c'
,
"count"
,
&
default_interval
,
...
...
tools/perf/builtin-report.c
浏览文件 @
60e0a4c7
...
@@ -1526,11 +1526,11 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
...
@@ -1526,11 +1526,11 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
more_data
+=
sizeof
(
u64
);
more_data
+=
sizeof
(
u64
);
}
}
dprintf
(
"%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d: %p period: %Ld
\n
"
,
dprintf
(
"%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d
/%d
: %p period: %Ld
\n
"
,
(
void
*
)(
offset
+
head
),
(
void
*
)(
offset
+
head
),
(
void
*
)(
long
)(
event
->
header
.
size
),
(
void
*
)(
long
)(
event
->
header
.
size
),
event
->
header
.
misc
,
event
->
header
.
misc
,
event
->
ip
.
pid
,
event
->
ip
.
pid
,
event
->
ip
.
tid
,
(
void
*
)(
long
)
ip
,
(
void
*
)(
long
)
ip
,
(
long
long
)
period
);
(
long
long
)
period
);
...
@@ -1590,10 +1590,11 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
...
@@ -1590,10 +1590,11 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
if
(
show
&
show_mask
)
{
if
(
show
&
show_mask
)
{
struct
symbol
*
sym
=
resolve_symbol
(
thread
,
&
map
,
&
dso
,
&
ip
);
struct
symbol
*
sym
=
resolve_symbol
(
thread
,
&
map
,
&
dso
,
&
ip
);
if
(
dso_list
&&
dso
&&
dso
->
name
&&
!
strlist__has_entry
(
dso_list
,
dso
->
name
))
if
(
dso_list
&&
(
!
dso
||
!
dso
->
name
||
!
strlist__has_entry
(
dso_list
,
dso
->
name
)))
return
0
;
return
0
;
if
(
sym_list
&&
sym
&&
!
strlist__has_entry
(
sym_list
,
sym
->
name
))
if
(
sym_list
&&
(
!
sym
||
!
strlist__has_entry
(
sym_list
,
sym
->
name
)
))
return
0
;
return
0
;
if
(
hist_entry__add
(
thread
,
map
,
dso
,
sym
,
ip
,
chain
,
level
,
period
))
{
if
(
hist_entry__add
(
thread
,
map
,
dso
,
sym
,
ip
,
chain
,
level
,
period
))
{
...
@@ -1612,10 +1613,11 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
...
@@ -1612,10 +1613,11 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
struct
thread
*
thread
=
threads__findnew
(
event
->
mmap
.
pid
);
struct
thread
*
thread
=
threads__findnew
(
event
->
mmap
.
pid
);
struct
map
*
map
=
map__new
(
&
event
->
mmap
);
struct
map
*
map
=
map__new
(
&
event
->
mmap
);
dprintf
(
"%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s
\n
"
,
dprintf
(
"%p [%p]: PERF_EVENT_MMAP %d
/%d
: [%p(%p) @ %p]: %s
\n
"
,
(
void
*
)(
offset
+
head
),
(
void
*
)(
offset
+
head
),
(
void
*
)(
long
)(
event
->
header
.
size
),
(
void
*
)(
long
)(
event
->
header
.
size
),
event
->
mmap
.
pid
,
event
->
mmap
.
pid
,
event
->
mmap
.
tid
,
(
void
*
)(
long
)
event
->
mmap
.
start
,
(
void
*
)(
long
)
event
->
mmap
.
start
,
(
void
*
)(
long
)
event
->
mmap
.
len
,
(
void
*
)(
long
)
event
->
mmap
.
len
,
(
void
*
)(
long
)
event
->
mmap
.
pgoff
,
(
void
*
)(
long
)
event
->
mmap
.
pgoff
,
...
...
tools/perf/util/parse-events.c
浏览文件 @
60e0a4c7
...
@@ -379,6 +379,7 @@ static int parse_tracepoint_event(const char **strp,
...
@@ -379,6 +379,7 @@ static int parse_tracepoint_event(const char **strp,
struct
perf_counter_attr
*
attr
)
struct
perf_counter_attr
*
attr
)
{
{
const
char
*
evt_name
;
const
char
*
evt_name
;
char
*
flags
;
char
sys_name
[
MAX_EVENT_LENGTH
];
char
sys_name
[
MAX_EVENT_LENGTH
];
char
id_buf
[
4
];
char
id_buf
[
4
];
int
fd
;
int
fd
;
...
@@ -400,6 +401,15 @@ static int parse_tracepoint_event(const char **strp,
...
@@ -400,6 +401,15 @@ static int parse_tracepoint_event(const char **strp,
strncpy
(
sys_name
,
*
strp
,
sys_length
);
strncpy
(
sys_name
,
*
strp
,
sys_length
);
sys_name
[
sys_length
]
=
'\0'
;
sys_name
[
sys_length
]
=
'\0'
;
evt_name
=
evt_name
+
1
;
evt_name
=
evt_name
+
1
;
flags
=
strchr
(
evt_name
,
':'
);
if
(
flags
)
{
*
flags
=
'\0'
;
flags
++
;
if
(
!
strncmp
(
flags
,
"record"
,
strlen
(
flags
)))
attr
->
sample_type
|=
PERF_SAMPLE_RAW
;
}
evt_length
=
strlen
(
evt_name
);
evt_length
=
strlen
(
evt_name
);
if
(
evt_length
>=
MAX_EVENT_LENGTH
)
if
(
evt_length
>=
MAX_EVENT_LENGTH
)
return
0
;
return
0
;
...
...
tools/perf/util/symbol.c
浏览文件 @
60e0a4c7
...
@@ -7,23 +7,8 @@
...
@@ -7,23 +7,8 @@
#include <gelf.h>
#include <gelf.h>
#include <elf.h>
#include <elf.h>
#ifndef NO_DEMANGLE
#include <bfd.h>
#else
static
inline
char
*
bfd_demangle
(
void
__used
*
v
,
const
char
__used
*
c
,
int
__used
i
)
{
return
NULL
;
}
#endif
const
char
*
sym_hist_filter
;
const
char
*
sym_hist_filter
;
#ifndef DMGL_PARAMS
#define DMGL_PARAMS (1 << 0)
/* Include function args */
#define DMGL_ANSI (1 << 1)
/* Include const, volatile, etc */
#endif
enum
dso_origin
{
enum
dso_origin
{
DSO__ORIG_KERNEL
=
0
,
DSO__ORIG_KERNEL
=
0
,
DSO__ORIG_JAVA_JIT
,
DSO__ORIG_JAVA_JIT
,
...
@@ -816,6 +801,8 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
...
@@ -816,6 +801,8 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
}
}
out:
out:
free
(
name
);
free
(
name
);
if
(
ret
<
0
&&
strstr
(
self
->
name
,
" (deleted)"
)
!=
NULL
)
return
0
;
return
ret
;
return
ret
;
}
}
...
...
tools/perf/util/symbol.h
浏览文件 @
60e0a4c7
...
@@ -7,6 +7,30 @@
...
@@ -7,6 +7,30 @@
#include <linux/rbtree.h>
#include <linux/rbtree.h>
#include "module.h"
#include "module.h"
#ifdef HAVE_CPLUS_DEMANGLE
extern
char
*
cplus_demangle
(
const
char
*
,
int
);
static
inline
char
*
bfd_demangle
(
void
__used
*
v
,
const
char
*
c
,
int
i
)
{
return
cplus_demangle
(
c
,
i
);
}
#else
#ifdef NO_DEMANGLE
static
inline
char
*
bfd_demangle
(
void
__used
*
v
,
const
char
__used
*
c
,
int
__used
i
)
{
return
NULL
;
}
#else
#include <bfd.h>
#endif
#endif
#ifndef DMGL_PARAMS
#define DMGL_PARAMS (1 << 0)
/* Include function args */
#define DMGL_ANSI (1 << 1)
/* Include const, volatile, etc */
#endif
struct
symbol
{
struct
symbol
{
struct
rb_node
rb_node
;
struct
rb_node
rb_node
;
u64
start
;
u64
start
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录