2010-01-25 15:19:15

by Tejun Heo

[permalink] [raw]
Subject: [PATCHSET] percpu: add __percpu sparse annotations

This patchset adds __percpu sparse annotations to all percpu users
covered by x86_64 allmodconfig. __percpu annotation teaches sparse
that percpu variables live in a separate address space and can't be
accessed directly without going through percpu accessors. This allows
detection of most percpu access mistakes involving both static and
dyanmic percpu variables.

This patchset contains the following eight patches.

0001-percpu-add-__percpu-sparse-annotations-to-core-kerne.patch
0002-percpu-add-__percpu-sparse-annotations-to-fs.patch
0003-percpu-add-__percpu-sparse-annotations-to-net.patch
0004-percpu-add-__percpu-sparse-annotations-to-net-driver.patch
0005-percpu-add-__percpu-sparse-annotations-to-x86.patch
0006-percpu-add-__percpu-sparse-annotations-to-trace.patch
0007-percpu-add-__percpu-sparse-annotations-to-hw_breakpo.patch
0008-percpu-add-__percpu-sparse-annotations-to-what-s-lef.patch

As these annotations are for sparse, none of the above patches affects
normal kernel build and most of the conversions are straight-forward
and trivial. There are a few places where the conversion isn't
completely straight-forward (but still fairly trivial). Those are
mentioned in each patch description.

I can route the patch through percpu and conflict resolution, if
necessary, wouldn't be difficult at all for these changes. If anyone
wants to route one of these patches through a different tree, please
let me know. All that's necessary would be adding dummy __percpu
definition to the patch.

If nobody objects, I'll push these into percpu tree in three or four
days.

Thanks.

arch/x86/include/asm/msr.h | 12 ++++---
arch/x86/kernel/acpi/cstate.c | 2 -
arch/x86/kernel/cpu/common.c | 2 -
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 2 -
arch/x86/lib/msr-smp.c | 8 +++--
arch/x86/lib/msr.c | 6 +--
crypto/cryptd.c | 2 -
drivers/acpi/processor_perflib.c | 2 -
drivers/dma/dmaengine.c | 2 -
drivers/edac/amd64_edac.c | 2 -
drivers/md/raid5.c | 2 -
drivers/md/raid5.h | 2 -
drivers/net/chelsio/sge.c | 2 -
drivers/net/loopback.c | 16 +++++-----
drivers/net/macvlan.c | 2 -
drivers/net/veth.c | 4 +-
fs/ext4/ext4.h | 2 -
fs/nfs/iostat.h | 4 +-
fs/xfs/xfs_mount.h | 2 -
include/acpi/processor.h | 2 -
include/linux/blktrace_api.h | 4 +-
include/linux/dmaengine.h | 2 -
include/linux/ftrace_event.h | 4 +-
include/linux/genhd.h | 2 -
include/linux/hw_breakpoint.h | 8 ++---
include/linux/kexec.h | 2 -
include/linux/mmzone.h | 2 -
include/linux/module.h | 2 -
include/linux/mount.h | 2 -
include/linux/nfs_fs_sb.h | 2 -
include/linux/percpu_counter.h | 2 -
include/linux/srcu.h | 2 -
include/net/ip.h | 6 +--
include/net/ipcomp.h | 2 -
include/net/neighbour.h | 2 -
include/net/netns/conntrack.h | 2 -
include/net/netns/core.h | 2 -
include/net/route.h | 2 -
include/net/snmp.h | 12 +++++--
include/net/tcp.h | 2 -
include/trace/ftrace.h | 4 +-
kernel/hw_breakpoint.c | 14 ++++----
kernel/kexec.c | 2 -
kernel/sched.c | 4 +-
kernel/stop_machine.c | 2 -
kernel/trace/trace_event_profile.c | 16 +++++-----
kernel/trace/trace_functions_graph.c | 2 -
kernel/trace/trace_kprobe.c | 4 +-
kernel/trace/trace_ksym.c | 10 +++---
kernel/trace/trace_syscalls.c | 4 +-
mm/percpu.c | 18 ++++++-----
net/8021q/vlan.h | 2 -
net/dccp/proto.c | 5 +--
net/ipv4/af_inet.c | 46 ++++++++++++++---------------
net/ipv4/proc.c | 28 ++++++++---------
net/ipv4/route.c | 2 -
net/ipv4/tcp.c | 21 +++++++------
net/ipv6/addrconf.c | 24 +++++++--------
net/ipv6/af_inet6.c | 28 ++++++++---------
net/ipv6/proc.c | 24 ++++++++-------
net/sctp/proc.c | 2 -
net/sctp/protocol.c | 5 +--
net/xfrm/xfrm_ipcomp.c | 16 +++++-----
net/xfrm/xfrm_policy.c | 6 +--
net/xfrm/xfrm_proc.c | 3 +
samples/hw_breakpoint/data_breakpoint.c | 6 +--
66 files changed, 231 insertions(+), 209 deletions(-)

--
tejun


2010-01-25 15:19:17

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 2/8] percpu: add __percpu sparse annotations to fs

Add __percpu sparse annotations to fs.

These annotations are to make sparse consider percpu variables to be
in a different address space and warn if accessed without going
through percpu accessors. This patch doesn't affect normal builds.

Signed-off-by: Tejun Heo <[email protected]>
Cc: "Theodore Ts'o" <[email protected]>
Cc: Trond Myklebust <[email protected]>
Cc: Alex Elder <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Cc: Alexander Viro <[email protected]>
---
fs/ext4/ext4.h | 2 +-
fs/nfs/iostat.h | 4 ++--
fs/xfs/xfs_mount.h | 2 +-
include/linux/mount.h | 2 +-
include/linux/nfs_fs_sb.h | 2 +-
5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index af7b626..eeb1e36 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1017,7 +1017,7 @@ struct ext4_sb_info {
atomic_t s_lock_busy;

/* locality groups */
- struct ext4_locality_group *s_locality_groups;
+ struct ext4_locality_group __percpu *s_locality_groups;

/* for write statistics */
unsigned long s_sectors_written_start;
diff --git a/fs/nfs/iostat.h b/fs/nfs/iostat.h
index 46d779a..1d8d5c8 100644
--- a/fs/nfs/iostat.h
+++ b/fs/nfs/iostat.h
@@ -57,12 +57,12 @@ static inline void nfs_add_fscache_stats(struct inode *inode,
}
#endif

-static inline struct nfs_iostats *nfs_alloc_iostats(void)
+static inline struct nfs_iostats __percpu *nfs_alloc_iostats(void)
{
return alloc_percpu(struct nfs_iostats);
}

-static inline void nfs_free_iostats(struct nfs_iostats *stats)
+static inline void nfs_free_iostats(struct nfs_iostats __percpu *stats)
{
if (stats != NULL)
free_percpu(stats);
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 1df7e45..24c8887 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -243,7 +243,7 @@ typedef struct xfs_mount {
struct xfs_qmops *m_qm_ops; /* vector of XQM ops */
atomic_t m_active_trans; /* number trans frozen */
#ifdef HAVE_PERCPU_SB
- xfs_icsb_cnts_t *m_sb_cnts; /* per-cpu superblock counters */
+ xfs_icsb_cnts_t __percpu *m_sb_cnts; /* per-cpu superblock counters */
unsigned long m_icsb_counters; /* disabled per-cpu counters */
struct notifier_block m_icsb_notifier; /* hotplug cpu notifier */
struct mutex m_icsb_mutex; /* balancer sync lock */
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 5d52753..b5f43a3 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -66,7 +66,7 @@ struct vfsmount {
int mnt_pinned;
int mnt_ghosts;
#ifdef CONFIG_SMP
- int *mnt_writers;
+ int __percpu *mnt_writers;
#else
int mnt_writers;
#endif
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 34fc6be..6a2e44f 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -105,7 +105,7 @@ struct nfs_server {
struct rpc_clnt * client; /* RPC client handle */
struct rpc_clnt * client_acl; /* ACL RPC client handle */
struct nlm_host *nlm_host; /* NLM client handle */
- struct nfs_iostats * io_stats; /* I/O statistics */
+ struct nfs_iostats __percpu *io_stats; /* I/O statistics */
struct backing_dev_info backing_dev_info;
atomic_long_t writeback; /* number of writeback pages */
int flags; /* various flags */
--
1.6.4.2

2010-01-25 15:18:59

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 5/8] percpu: add __percpu sparse annotations to x86

Add __percpu sparse annotations to x86.

These annotations are to make sparse consider percpu variables to be
in a different address space and warn if accessed without going
through percpu accessors. This patch doesn't affect normal builds.

In arch/x86/kernel/cpu/common.c, per_cpu(exception_stacks, cpu) is
replaced with &per_cpu(exception_stacks[0], cpu) which is equivalent
except that it allows per_cpu() macro to correctly drop percpu
designation during sparse pass.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: [email protected]
---
arch/x86/include/asm/msr.h | 12 +++++++-----
arch/x86/kernel/acpi/cstate.c | 2 +-
arch/x86/kernel/cpu/common.c | 2 +-
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 2 +-
arch/x86/lib/msr-smp.c | 8 +++++---
arch/x86/lib/msr.c | 6 +++---
6 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index c5bc4c2..74882a5 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -30,7 +30,7 @@ struct msr {
struct msr_info {
u32 msr_no;
struct msr reg;
- struct msr *msrs;
+ struct msr __percpu *msrs;
int err;
};

@@ -256,14 +256,16 @@ do { \

#define write_rdtscp_aux(val) wrmsr(MSR_TSC_AUX, (val), 0)

-struct msr *msrs_alloc(void);
-void msrs_free(struct msr *msrs);
+struct msr __percpu *msrs_alloc(void);
+void msrs_free(struct msr __percpu *msrs);

#ifdef CONFIG_SMP
int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
-void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
-void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
+void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
+ struct msr __percpu *msrs);
+void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
+ struct msr __percpu *msrs);
int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index 2e837f5..62b0693 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -61,7 +61,7 @@ struct cstate_entry {
unsigned int ecx;
} states[ACPI_PROCESSOR_MAX_POWER];
};
-static struct cstate_entry *cpu_cstate_entry; /* per CPU ptr */
+static struct cstate_entry __percpu *cpu_cstate_entry; /* per CPU ptr */

static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 4868e4a..486cb06 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1146,7 +1146,7 @@ void __cpuinit cpu_init(void)
* set up and load the per-CPU TSS
*/
if (!oist->ist[0]) {
- char *estacks = per_cpu(exception_stacks, cpu);
+ char *estacks = &per_cpu(exception_stacks[0], cpu);

for (v = 0; v < N_EXCEPTION_STACKS; v++) {
estacks += exception_stack_sizes[v];
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
index 1b1920f..61cfd75 100644
--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -73,7 +73,7 @@ static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data);
static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf);

/* acpi_perf_data is a pointer to percpu data. */
-static struct acpi_processor_performance *acpi_perf_data;
+static struct acpi_processor_performance __percpu *acpi_perf_data;

static struct cpufreq_driver acpi_cpufreq_driver;

diff --git a/arch/x86/lib/msr-smp.c b/arch/x86/lib/msr-smp.c
index a6b1b86..b6a355f 100644
--- a/arch/x86/lib/msr-smp.c
+++ b/arch/x86/lib/msr-smp.c
@@ -64,7 +64,7 @@ int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
EXPORT_SYMBOL(wrmsr_on_cpu);

static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
- struct msr *msrs,
+ struct msr __percpu *msrs,
void (*msr_func) (void *info))
{
struct msr_info rv;
@@ -91,7 +91,8 @@ static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
* @msrs: array of MSR values
*
*/
-void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
+void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
+ struct msr __percpu *msrs)
{
__rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu);
}
@@ -105,7 +106,8 @@ EXPORT_SYMBOL(rdmsr_on_cpus);
* @msrs: array of MSR values
*
*/
-void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
+void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
+ struct msr __percpu *msrs)
{
__rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu);
}
diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c
index 8f8eebd..42c994c 100644
--- a/arch/x86/lib/msr.c
+++ b/arch/x86/lib/msr.c
@@ -2,9 +2,9 @@
#include <linux/preempt.h>
#include <asm/msr.h>

-struct msr *msrs_alloc(void)
+struct msr __percpu *msrs_alloc(void)
{
- struct msr *msrs = NULL;
+ struct msr __percpu *msrs = NULL;

msrs = alloc_percpu(struct msr);
if (!msrs) {
@@ -16,7 +16,7 @@ struct msr *msrs_alloc(void)
}
EXPORT_SYMBOL(msrs_alloc);

-void msrs_free(struct msr *msrs)
+void msrs_free(struct msr __percpu *msrs)
{
free_percpu(msrs);
}
--
1.6.4.2

2010-01-25 15:19:31

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 3/8] percpu: add __percpu sparse annotations to net

Add __percpu sparse annotations to net.

These annotations are to make sparse consider percpu variables to be
in a different address space and warn if accessed without going
through percpu accessors. This patch doesn't affect normal builds.

The macro and type tricks around snmp stats make things a bit
interesting. DEFINE/DECLARE_SNMP_STAT() macros mark the target field
as __percpu and SNMP_UPD_PO_STATS() macro is updated accordingly. All
snmp_mib_*() users which used to cast the argument to (void **) are
updated to cast it to (void __percpu **).

Signed-off-by: Tejun Heo <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: Patrick McHardy <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Vlad Yasevich <[email protected]>
Cc: [email protected]
---
include/net/ip.h | 6 ++--
include/net/ipcomp.h | 2 +-
include/net/neighbour.h | 2 +-
include/net/netns/conntrack.h | 2 +-
include/net/netns/core.h | 2 +-
include/net/route.h | 2 +-
include/net/snmp.h | 12 +++++++---
include/net/tcp.h | 2 +-
net/8021q/vlan.h | 2 +-
net/dccp/proto.c | 5 ++-
net/ipv4/af_inet.c | 46 ++++++++++++++++++++--------------------
net/ipv4/proc.c | 28 ++++++++++++------------
net/ipv4/route.c | 2 +-
net/ipv4/tcp.c | 21 ++++++++++--------
net/ipv6/addrconf.c | 24 ++++++++++----------
net/ipv6/af_inet6.c | 28 ++++++++++++------------
net/ipv6/proc.c | 24 ++++++++++++---------
net/sctp/proc.c | 2 +-
net/sctp/protocol.c | 5 ++-
net/xfrm/xfrm_ipcomp.c | 16 +++++++-------
net/xfrm/xfrm_policy.c | 6 ++--
net/xfrm/xfrm_proc.c | 3 +-
22 files changed, 128 insertions(+), 114 deletions(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index fb63371..667a55b 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -174,9 +174,9 @@ extern struct ipv4_config ipv4_config;
#define NET_ADD_STATS_BH(net, field, adnd) SNMP_ADD_STATS_BH((net)->mib.net_statistics, field, adnd)
#define NET_ADD_STATS_USER(net, field, adnd) SNMP_ADD_STATS_USER((net)->mib.net_statistics, field, adnd)

-extern unsigned long snmp_fold_field(void *mib[], int offt);
-extern int snmp_mib_init(void *ptr[2], size_t mibsize);
-extern void snmp_mib_free(void *ptr[2]);
+extern unsigned long snmp_fold_field(void __percpu *mib[], int offt);
+extern int snmp_mib_init(void __percpu *ptr[2], size_t mibsize);
+extern void snmp_mib_free(void __percpu *ptr[2]);

extern struct local_ports {
seqlock_t lock;
diff --git a/include/net/ipcomp.h b/include/net/ipcomp.h
index 2a1092a..cc4f30c 100644
--- a/include/net/ipcomp.h
+++ b/include/net/ipcomp.h
@@ -9,7 +9,7 @@ struct crypto_comp;

struct ipcomp_data {
u16 threshold;
- struct crypto_comp **tfms;
+ struct crypto_comp * __percpu *tfms;
};

struct ip_comp_hdr;
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index b017320..daf935b 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -164,7 +164,7 @@ struct neigh_table {
rwlock_t lock;
unsigned long last_rand;
struct kmem_cache *kmem_cachep;
- struct neigh_statistics *stats;
+ struct neigh_statistics __percpu *stats;
struct neighbour **hash_buckets;
unsigned int hash_mask;
__u32 hash_rnd;
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index ba1ba0c..1531c07 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -15,7 +15,7 @@ struct netns_ct {
struct hlist_head *expect_hash;
struct hlist_nulls_head unconfirmed;
struct hlist_nulls_head dying;
- struct ip_conntrack_stat *stat;
+ struct ip_conntrack_stat __percpu *stat;
int sysctl_events;
unsigned int sysctl_events_retry_timeout;
int sysctl_acct;
diff --git a/include/net/netns/core.h b/include/net/netns/core.h
index 24d4be7..78eb1ff 100644
--- a/include/net/netns/core.h
+++ b/include/net/netns/core.h
@@ -10,7 +10,7 @@ struct netns_core {

int sysctl_somaxconn;

- struct prot_inuse *inuse;
+ struct prot_inuse __percpu *inuse;
};

#endif
diff --git a/include/net/route.h b/include/net/route.h
index bce6dd6..2c9fba7 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -101,7 +101,7 @@ struct rt_cache_stat {
unsigned int out_hlist_search;
};

-extern struct ip_rt_acct *ip_rt_acct;
+extern struct ip_rt_acct __percpu *ip_rt_acct;

struct in_device;
extern int ip_rt_init(void);
diff --git a/include/net/snmp.h b/include/net/snmp.h
index f0d756f..d065976 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -129,9 +129,9 @@ struct linux_xfrm_mib {
* nonlocked_atomic_inc() primitives -AK
*/
#define DEFINE_SNMP_STAT(type, name) \
- __typeof__(type) *name[2]
+ __typeof__(type) __percpu *name[2]
#define DECLARE_SNMP_STAT(type, name) \
- extern __typeof__(type) *name[2]
+ extern __typeof__(type) __percpu *name[2]

#define SNMP_STAT_BHPTR(name) (name[0])
#define SNMP_STAT_USRPTR(name) (name[1])
@@ -148,9 +148,13 @@ struct linux_xfrm_mib {
__this_cpu_add(mib[0]->mibs[field], addend)
#define SNMP_ADD_STATS_USER(mib, field, addend) \
this_cpu_add(mib[1]->mibs[field], addend)
+/*
+ * Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr"
+ * to make @ptr a non-percpu pointer.
+ */
#define SNMP_UPD_PO_STATS(mib, basefield, addend) \
do { \
- __typeof__(mib[0]) ptr; \
+ __typeof__(*mib[0]) *ptr; \
preempt_disable(); \
ptr = this_cpu_ptr((mib)[!in_softirq()]); \
ptr->mibs[basefield##PKTS]++; \
@@ -159,7 +163,7 @@ struct linux_xfrm_mib {
} while (0)
#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \
do { \
- __typeof__(mib[0]) ptr = \
+ __typeof__(*mib[0]) *ptr = \
__this_cpu_ptr((mib)[!in_softirq()]); \
ptr->mibs[basefield##PKTS]++; \
ptr->mibs[basefield##OCTETS] += addend;\
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 34f5cc2..0511317 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1193,7 +1193,7 @@ extern int tcp_v4_md5_do_del(struct sock *sk,
#define tcp_twsk_md5_key(twsk) NULL
#endif

-extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(struct sock *);
+extern struct tcp_md5sig_pool * __percpu *tcp_alloc_md5sig_pool(struct sock *);
extern void tcp_free_md5sig_pool(void);

extern struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu);
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 5685296..6abdcac 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -61,7 +61,7 @@ struct vlan_dev_info {
struct proc_dir_entry *dent;
unsigned long cnt_inc_headroom_on_tx;
unsigned long cnt_encap_on_xmit;
- struct vlan_rx_stats *vlan_rx_stats;
+ struct vlan_rx_stats __percpu *vlan_rx_stats;
};

static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev)
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 671cd14..fb3b9f8 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -1003,12 +1003,13 @@ EXPORT_SYMBOL_GPL(dccp_shutdown);

static inline int dccp_mib_init(void)
{
- return snmp_mib_init((void**)dccp_statistics, sizeof(struct dccp_mib));
+ return snmp_mib_init((void __percpu **)dccp_statistics,
+ sizeof(struct dccp_mib));
}

static inline void dccp_mib_exit(void)
{
- snmp_mib_free((void**)dccp_statistics);
+ snmp_mib_free((void __percpu **)dccp_statistics);
}

static int thash_entries;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 7d12c6a..33b7dff 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1385,7 +1385,7 @@ int inet_ctl_sock_create(struct sock **sk, unsigned short family,
}
EXPORT_SYMBOL_GPL(inet_ctl_sock_create);

-unsigned long snmp_fold_field(void *mib[], int offt)
+unsigned long snmp_fold_field(void __percpu *mib[], int offt)
{
unsigned long res = 0;
int i;
@@ -1398,7 +1398,7 @@ unsigned long snmp_fold_field(void *mib[], int offt)
}
EXPORT_SYMBOL_GPL(snmp_fold_field);

-int snmp_mib_init(void *ptr[2], size_t mibsize)
+int snmp_mib_init(void __percpu *ptr[2], size_t mibsize)
{
BUG_ON(ptr == NULL);
ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long long));
@@ -1416,7 +1416,7 @@ err0:
}
EXPORT_SYMBOL_GPL(snmp_mib_init);

-void snmp_mib_free(void *ptr[2])
+void snmp_mib_free(void __percpu *ptr[2])
{
BUG_ON(ptr == NULL);
free_percpu(ptr[0]);
@@ -1460,25 +1460,25 @@ static const struct net_protocol icmp_protocol = {

static __net_init int ipv4_mib_init_net(struct net *net)
{
- if (snmp_mib_init((void **)net->mib.tcp_statistics,
+ if (snmp_mib_init((void __percpu **)net->mib.tcp_statistics,
sizeof(struct tcp_mib)) < 0)
goto err_tcp_mib;
- if (snmp_mib_init((void **)net->mib.ip_statistics,
+ if (snmp_mib_init((void __percpu **)net->mib.ip_statistics,
sizeof(struct ipstats_mib)) < 0)
goto err_ip_mib;
- if (snmp_mib_init((void **)net->mib.net_statistics,
+ if (snmp_mib_init((void __percpu **)net->mib.net_statistics,
sizeof(struct linux_mib)) < 0)
goto err_net_mib;
- if (snmp_mib_init((void **)net->mib.udp_statistics,
+ if (snmp_mib_init((void __percpu **)net->mib.udp_statistics,
sizeof(struct udp_mib)) < 0)
goto err_udp_mib;
- if (snmp_mib_init((void **)net->mib.udplite_statistics,
+ if (snmp_mib_init((void __percpu **)net->mib.udplite_statistics,
sizeof(struct udp_mib)) < 0)
goto err_udplite_mib;
- if (snmp_mib_init((void **)net->mib.icmp_statistics,
+ if (snmp_mib_init((void __percpu **)net->mib.icmp_statistics,
sizeof(struct icmp_mib)) < 0)
goto err_icmp_mib;
- if (snmp_mib_init((void **)net->mib.icmpmsg_statistics,
+ if (snmp_mib_init((void __percpu **)net->mib.icmpmsg_statistics,
sizeof(struct icmpmsg_mib)) < 0)
goto err_icmpmsg_mib;

@@ -1486,30 +1486,30 @@ static __net_init int ipv4_mib_init_net(struct net *net)
return 0;

err_icmpmsg_mib:
- snmp_mib_free((void **)net->mib.icmp_statistics);
+ snmp_mib_free((void __percpu **)net->mib.icmp_statistics);
err_icmp_mib:
- snmp_mib_free((void **)net->mib.udplite_statistics);
+ snmp_mib_free((void __percpu **)net->mib.udplite_statistics);
err_udplite_mib:
- snmp_mib_free((void **)net->mib.udp_statistics);
+ snmp_mib_free((void __percpu **)net->mib.udp_statistics);
err_udp_mib:
- snmp_mib_free((void **)net->mib.net_statistics);
+ snmp_mib_free((void __percpu **)net->mib.net_statistics);
err_net_mib:
- snmp_mib_free((void **)net->mib.ip_statistics);
+ snmp_mib_free((void __percpu **)net->mib.ip_statistics);
err_ip_mib:
- snmp_mib_free((void **)net->mib.tcp_statistics);
+ snmp_mib_free((void __percpu **)net->mib.tcp_statistics);
err_tcp_mib:
return -ENOMEM;
}

static __net_exit void ipv4_mib_exit_net(struct net *net)
{
- snmp_mib_free((void **)net->mib.icmpmsg_statistics);
- snmp_mib_free((void **)net->mib.icmp_statistics);
- snmp_mib_free((void **)net->mib.udplite_statistics);
- snmp_mib_free((void **)net->mib.udp_statistics);
- snmp_mib_free((void **)net->mib.net_statistics);
- snmp_mib_free((void **)net->mib.ip_statistics);
- snmp_mib_free((void **)net->mib.tcp_statistics);
+ snmp_mib_free((void __percpu **)net->mib.icmpmsg_statistics);
+ snmp_mib_free((void __percpu **)net->mib.icmp_statistics);
+ snmp_mib_free((void __percpu **)net->mib.udplite_statistics);
+ snmp_mib_free((void __percpu **)net->mib.udp_statistics);
+ snmp_mib_free((void __percpu **)net->mib.net_statistics);
+ snmp_mib_free((void __percpu **)net->mib.ip_statistics);
+ snmp_mib_free((void __percpu **)net->mib.tcp_statistics);
}

static __net_initdata struct pernet_operations ipv4_mib_ops = {
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index f25542c..1561eb6 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -280,7 +280,7 @@ static void icmpmsg_put(struct seq_file *seq)

count = 0;
for (i = 0; i < ICMPMSG_MIB_MAX; i++) {
- val = snmp_fold_field((void **) net->mib.icmpmsg_statistics, i);
+ val = snmp_fold_field((void __percpu **) net->mib.icmpmsg_statistics, i);
if (val) {
type[count] = i;
vals[count++] = val;
@@ -307,18 +307,18 @@ static void icmp_put(struct seq_file *seq)
for (i=0; icmpmibmap[i].name != NULL; i++)
seq_printf(seq, " Out%s", icmpmibmap[i].name);
seq_printf(seq, "\nIcmp: %lu %lu",
- snmp_fold_field((void **) net->mib.icmp_statistics, ICMP_MIB_INMSGS),
- snmp_fold_field((void **) net->mib.icmp_statistics, ICMP_MIB_INERRORS));
+ snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INMSGS),
+ snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INERRORS));
for (i=0; icmpmibmap[i].name != NULL; i++)
seq_printf(seq, " %lu",
- snmp_fold_field((void **) net->mib.icmpmsg_statistics,
+ snmp_fold_field((void __percpu **) net->mib.icmpmsg_statistics,
icmpmibmap[i].index));
seq_printf(seq, " %lu %lu",
- snmp_fold_field((void **) net->mib.icmp_statistics, ICMP_MIB_OUTMSGS),
- snmp_fold_field((void **) net->mib.icmp_statistics, ICMP_MIB_OUTERRORS));
+ snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_OUTMSGS),
+ snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_OUTERRORS));
for (i=0; icmpmibmap[i].name != NULL; i++)
seq_printf(seq, " %lu",
- snmp_fold_field((void **) net->mib.icmpmsg_statistics,
+ snmp_fold_field((void __percpu **) net->mib.icmpmsg_statistics,
icmpmibmap[i].index | 0x100));
}

@@ -341,7 +341,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v)

for (i = 0; snmp4_ipstats_list[i].name != NULL; i++)
seq_printf(seq, " %lu",
- snmp_fold_field((void **)net->mib.ip_statistics,
+ snmp_fold_field((void __percpu **)net->mib.ip_statistics,
snmp4_ipstats_list[i].entry));

icmp_put(seq); /* RFC 2011 compatibility */
@@ -356,11 +356,11 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
/* MaxConn field is signed, RFC 2012 */
if (snmp4_tcp_list[i].entry == TCP_MIB_MAXCONN)
seq_printf(seq, " %ld",
- snmp_fold_field((void **)net->mib.tcp_statistics,
+ snmp_fold_field((void __percpu **)net->mib.tcp_statistics,
snmp4_tcp_list[i].entry));
else
seq_printf(seq, " %lu",
- snmp_fold_field((void **)net->mib.tcp_statistics,
+ snmp_fold_field((void __percpu **)net->mib.tcp_statistics,
snmp4_tcp_list[i].entry));
}

@@ -371,7 +371,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
seq_puts(seq, "\nUdp:");
for (i = 0; snmp4_udp_list[i].name != NULL; i++)
seq_printf(seq, " %lu",
- snmp_fold_field((void **)net->mib.udp_statistics,
+ snmp_fold_field((void __percpu **)net->mib.udp_statistics,
snmp4_udp_list[i].entry));

/* the UDP and UDP-Lite MIBs are the same */
@@ -382,7 +382,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
seq_puts(seq, "\nUdpLite:");
for (i = 0; snmp4_udp_list[i].name != NULL; i++)
seq_printf(seq, " %lu",
- snmp_fold_field((void **)net->mib.udplite_statistics,
+ snmp_fold_field((void __percpu **)net->mib.udplite_statistics,
snmp4_udp_list[i].entry));

seq_putc(seq, '\n');
@@ -419,7 +419,7 @@ static int netstat_seq_show(struct seq_file *seq, void *v)
seq_puts(seq, "\nTcpExt:");
for (i = 0; snmp4_net_list[i].name != NULL; i++)
seq_printf(seq, " %lu",
- snmp_fold_field((void **)net->mib.net_statistics,
+ snmp_fold_field((void __percpu **)net->mib.net_statistics,
snmp4_net_list[i].entry));

seq_puts(seq, "\nIpExt:");
@@ -429,7 +429,7 @@ static int netstat_seq_show(struct seq_file *seq, void *v)
seq_puts(seq, "\nIpExt:");
for (i = 0; snmp4_ipextstats_list[i].name != NULL; i++)
seq_printf(seq, " %lu",
- snmp_fold_field((void **)net->mib.ip_statistics,
+ snmp_fold_field((void __percpu **)net->mib.ip_statistics,
snmp4_ipextstats_list[i].entry));

seq_putc(seq, '\n');
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index e446496..515d906 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3327,7 +3327,7 @@ static __net_initdata struct pernet_operations rt_secret_timer_ops = {


#ifdef CONFIG_NET_CLS_ROUTE
-struct ip_rt_acct *ip_rt_acct __read_mostly;
+struct ip_rt_acct __percpu *ip_rt_acct __read_mostly;
#endif /* CONFIG_NET_CLS_ROUTE */

static __initdata unsigned long rhash_entries;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index b0a26bb..bc04e66 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2788,10 +2788,10 @@ EXPORT_SYMBOL(tcp_gro_complete);

#ifdef CONFIG_TCP_MD5SIG
static unsigned long tcp_md5sig_users;
-static struct tcp_md5sig_pool **tcp_md5sig_pool;
+static struct tcp_md5sig_pool * __percpu *tcp_md5sig_pool;
static DEFINE_SPINLOCK(tcp_md5sig_pool_lock);

-static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool)
+static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool * __percpu *pool)
{
int cpu;
for_each_possible_cpu(cpu) {
@@ -2808,7 +2808,7 @@ static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool)

void tcp_free_md5sig_pool(void)
{
- struct tcp_md5sig_pool **pool = NULL;
+ struct tcp_md5sig_pool * __percpu *pool = NULL;

spin_lock_bh(&tcp_md5sig_pool_lock);
if (--tcp_md5sig_users == 0) {
@@ -2822,10 +2822,11 @@ void tcp_free_md5sig_pool(void)

EXPORT_SYMBOL(tcp_free_md5sig_pool);

-static struct tcp_md5sig_pool **__tcp_alloc_md5sig_pool(struct sock *sk)
+static struct tcp_md5sig_pool * __percpu *
+__tcp_alloc_md5sig_pool(struct sock *sk)
{
int cpu;
- struct tcp_md5sig_pool **pool;
+ struct tcp_md5sig_pool * __percpu *pool;

pool = alloc_percpu(struct tcp_md5sig_pool *);
if (!pool)
@@ -2852,9 +2853,9 @@ out_free:
return NULL;
}

-struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(struct sock *sk)
+struct tcp_md5sig_pool * __percpu *tcp_alloc_md5sig_pool(struct sock *sk)
{
- struct tcp_md5sig_pool **pool;
+ struct tcp_md5sig_pool * __percpu *pool;
int alloc = 0;

retry:
@@ -2873,7 +2874,9 @@ retry:

if (alloc) {
/* we cannot hold spinlock here because this may sleep. */
- struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool(sk);
+ struct tcp_md5sig_pool * __percpu *p;
+
+ p = __tcp_alloc_md5sig_pool(sk);
spin_lock_bh(&tcp_md5sig_pool_lock);
if (!p) {
tcp_md5sig_users--;
@@ -2897,7 +2900,7 @@ EXPORT_SYMBOL(tcp_alloc_md5sig_pool);

struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu)
{
- struct tcp_md5sig_pool **p;
+ struct tcp_md5sig_pool * __percpu *p;
spin_lock_bh(&tcp_md5sig_pool_lock);
p = tcp_md5sig_pool;
if (p)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index de7a194..1b5f2ed 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -278,31 +278,31 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp,

static int snmp6_alloc_dev(struct inet6_dev *idev)
{
- if (snmp_mib_init((void **)idev->stats.ipv6,
+ if (snmp_mib_init((void __percpu **)idev->stats.ipv6,
sizeof(struct ipstats_mib)) < 0)
goto err_ip;
- if (snmp_mib_init((void **)idev->stats.icmpv6,
+ if (snmp_mib_init((void __percpu **)idev->stats.icmpv6,
sizeof(struct icmpv6_mib)) < 0)
goto err_icmp;
- if (snmp_mib_init((void **)idev->stats.icmpv6msg,
+ if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg,
sizeof(struct icmpv6msg_mib)) < 0)
goto err_icmpmsg;

return 0;

err_icmpmsg:
- snmp_mib_free((void **)idev->stats.icmpv6);
+ snmp_mib_free((void __percpu **)idev->stats.icmpv6);
err_icmp:
- snmp_mib_free((void **)idev->stats.ipv6);
+ snmp_mib_free((void __percpu **)idev->stats.ipv6);
err_ip:
return -ENOMEM;
}

static void snmp6_free_dev(struct inet6_dev *idev)
{
- snmp_mib_free((void **)idev->stats.icmpv6msg);
- snmp_mib_free((void **)idev->stats.icmpv6);
- snmp_mib_free((void **)idev->stats.ipv6);
+ snmp_mib_free((void __percpu **)idev->stats.icmpv6msg);
+ snmp_mib_free((void __percpu **)idev->stats.icmpv6);
+ snmp_mib_free((void __percpu **)idev->stats.ipv6);
}

/* Nobody refers to this device, we may destroy it. */
@@ -3752,8 +3752,8 @@ static inline size_t inet6_if_nlmsg_size(void)
);
}

-static inline void __snmp6_fill_stats(u64 *stats, void **mib, int items,
- int bytes)
+static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib,
+ int items, int bytes)
{
int i;
int pad = bytes - sizeof(u64) * items;
@@ -3772,10 +3772,10 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype,
{
switch(attrtype) {
case IFLA_INET6_STATS:
- __snmp6_fill_stats(stats, (void **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes);
+ __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes);
break;
case IFLA_INET6_ICMP6STATS:
- __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes);
+ __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes);
break;
}
}
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 12e69d3..36b42af 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -971,41 +971,41 @@ static void ipv6_packet_cleanup(void)

static int __net_init ipv6_init_mibs(struct net *net)
{
- if (snmp_mib_init((void **)net->mib.udp_stats_in6,
+ if (snmp_mib_init((void __percpu **)net->mib.udp_stats_in6,
sizeof (struct udp_mib)) < 0)
return -ENOMEM;
- if (snmp_mib_init((void **)net->mib.udplite_stats_in6,
+ if (snmp_mib_init((void __percpu **)net->mib.udplite_stats_in6,
sizeof (struct udp_mib)) < 0)
goto err_udplite_mib;
- if (snmp_mib_init((void **)net->mib.ipv6_statistics,
+ if (snmp_mib_init((void __percpu **)net->mib.ipv6_statistics,
sizeof(struct ipstats_mib)) < 0)
goto err_ip_mib;
- if (snmp_mib_init((void **)net->mib.icmpv6_statistics,
+ if (snmp_mib_init((void __percpu **)net->mib.icmpv6_statistics,
sizeof(struct icmpv6_mib)) < 0)
goto err_icmp_mib;
- if (snmp_mib_init((void **)net->mib.icmpv6msg_statistics,
+ if (snmp_mib_init((void __percpu **)net->mib.icmpv6msg_statistics,
sizeof(struct icmpv6msg_mib)) < 0)
goto err_icmpmsg_mib;
return 0;

err_icmpmsg_mib:
- snmp_mib_free((void **)net->mib.icmpv6_statistics);
+ snmp_mib_free((void __percpu **)net->mib.icmpv6_statistics);
err_icmp_mib:
- snmp_mib_free((void **)net->mib.ipv6_statistics);
+ snmp_mib_free((void __percpu **)net->mib.ipv6_statistics);
err_ip_mib:
- snmp_mib_free((void **)net->mib.udplite_stats_in6);
+ snmp_mib_free((void __percpu **)net->mib.udplite_stats_in6);
err_udplite_mib:
- snmp_mib_free((void **)net->mib.udp_stats_in6);
+ snmp_mib_free((void __percpu **)net->mib.udp_stats_in6);
return -ENOMEM;
}

static void __net_exit ipv6_cleanup_mibs(struct net *net)
{
- snmp_mib_free((void **)net->mib.udp_stats_in6);
- snmp_mib_free((void **)net->mib.udplite_stats_in6);
- snmp_mib_free((void **)net->mib.ipv6_statistics);
- snmp_mib_free((void **)net->mib.icmpv6_statistics);
- snmp_mib_free((void **)net->mib.icmpv6msg_statistics);
+ snmp_mib_free((void __percpu **)net->mib.udp_stats_in6);
+ snmp_mib_free((void __percpu **)net->mib.udplite_stats_in6);
+ snmp_mib_free((void __percpu **)net->mib.ipv6_statistics);
+ snmp_mib_free((void __percpu **)net->mib.icmpv6_statistics);
+ snmp_mib_free((void __percpu **)net->mib.icmpv6msg_statistics);
}

static int __net_init inet6_net_init(struct net *net)
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index c9605c3..e3744d1 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -136,7 +136,7 @@ static struct snmp_mib snmp6_udplite6_list[] = {
SNMP_MIB_SENTINEL
};

-static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib)
+static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void __percpu **mib)
{
char name[32];
int i;
@@ -171,7 +171,8 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib)
}

static inline void
-snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp_mib *itemlist)
+snmp6_seq_show_item(struct seq_file *seq, void __percpu **mib,
+ struct snmp_mib *itemlist)
{
int i;
for (i=0; itemlist[i].name; i++)
@@ -183,14 +184,15 @@ static int snmp6_seq_show(struct seq_file *seq, void *v)
{
struct net *net = (struct net *)seq->private;

- snmp6_seq_show_item(seq, (void **)net->mib.ipv6_statistics,
+ snmp6_seq_show_item(seq, (void __percpu **)net->mib.ipv6_statistics,
snmp6_ipstats_list);
- snmp6_seq_show_item(seq, (void **)net->mib.icmpv6_statistics,
+ snmp6_seq_show_item(seq, (void __percpu **)net->mib.icmpv6_statistics,
snmp6_icmp6_list);
- snmp6_seq_show_icmpv6msg(seq, (void **)net->mib.icmpv6msg_statistics);
- snmp6_seq_show_item(seq, (void **)net->mib.udp_stats_in6,
+ snmp6_seq_show_icmpv6msg(seq,
+ (void __percpu **)net->mib.icmpv6msg_statistics);
+ snmp6_seq_show_item(seq, (void __percpu **)net->mib.udp_stats_in6,
snmp6_udp6_list);
- snmp6_seq_show_item(seq, (void **)net->mib.udplite_stats_in6,
+ snmp6_seq_show_item(seq, (void __percpu **)net->mib.udplite_stats_in6,
snmp6_udplite6_list);
return 0;
}
@@ -213,9 +215,11 @@ static int snmp6_dev_seq_show(struct seq_file *seq, void *v)
struct inet6_dev *idev = (struct inet6_dev *)seq->private;

seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex);
- snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list);
- snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list);
- snmp6_seq_show_icmpv6msg(seq, (void **)idev->stats.icmpv6msg);
+ snmp6_seq_show_item(seq, (void __percpu **)idev->stats.ipv6,
+ snmp6_ipstats_list);
+ snmp6_seq_show_item(seq, (void __percpu **)idev->stats.icmpv6,
+ snmp6_icmp6_list);
+ snmp6_seq_show_icmpv6msg(seq, (void __percpu **)idev->stats.icmpv6msg);
return 0;
}

diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index d093cbf..e1e04c6 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -83,7 +83,7 @@ static int sctp_snmp_seq_show(struct seq_file *seq, void *v)

for (i = 0; sctp_snmp_list[i].name != NULL; i++)
seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name,
- snmp_fold_field((void **)sctp_statistics,
+ snmp_fold_field((void __percpu **)sctp_statistics,
sctp_snmp_list[i].entry));

return 0;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index a3c8988..9687177 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -996,12 +996,13 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family)

static inline int init_sctp_mibs(void)
{
- return snmp_mib_init((void**)sctp_statistics, sizeof(struct sctp_mib));
+ return snmp_mib_init((void __percpu **)sctp_statistics,
+ sizeof(struct sctp_mib));
}

static inline void cleanup_sctp_mibs(void)
{
- snmp_mib_free((void**)sctp_statistics);
+ snmp_mib_free((void __percpu **)sctp_statistics);
}

static void sctp_v4_pf_init(void)
diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c
index 42cd183..0fc5ff6 100644
--- a/net/xfrm/xfrm_ipcomp.c
+++ b/net/xfrm/xfrm_ipcomp.c
@@ -30,12 +30,12 @@

struct ipcomp_tfms {
struct list_head list;
- struct crypto_comp **tfms;
+ struct crypto_comp * __percpu *tfms;
int users;
};

static DEFINE_MUTEX(ipcomp_resource_mutex);
-static void **ipcomp_scratches;
+static void * __percpu *ipcomp_scratches;
static int ipcomp_scratch_users;
static LIST_HEAD(ipcomp_tfms_list);

@@ -200,7 +200,7 @@ EXPORT_SYMBOL_GPL(ipcomp_output);
static void ipcomp_free_scratches(void)
{
int i;
- void **scratches;
+ void * __percpu *scratches;

if (--ipcomp_scratch_users)
return;
@@ -215,10 +215,10 @@ static void ipcomp_free_scratches(void)
free_percpu(scratches);
}

-static void **ipcomp_alloc_scratches(void)
+static void * __percpu *ipcomp_alloc_scratches(void)
{
int i;
- void **scratches;
+ void * __percpu *scratches;

if (ipcomp_scratch_users++)
return ipcomp_scratches;
@@ -239,7 +239,7 @@ static void **ipcomp_alloc_scratches(void)
return scratches;
}

-static void ipcomp_free_tfms(struct crypto_comp **tfms)
+static void ipcomp_free_tfms(struct crypto_comp * __percpu *tfms)
{
struct ipcomp_tfms *pos;
int cpu;
@@ -267,10 +267,10 @@ static void ipcomp_free_tfms(struct crypto_comp **tfms)
free_percpu(tfms);
}

-static struct crypto_comp **ipcomp_alloc_tfms(const char *alg_name)
+static struct crypto_comp * __percpu *ipcomp_alloc_tfms(const char *alg_name)
{
struct ipcomp_tfms *pos;
- struct crypto_comp **tfms;
+ struct crypto_comp * __percpu *tfms;
int cpu;

/* This can be any valid CPU ID so we don't need locking. */
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 4725a54..a8c3ced 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2369,19 +2369,19 @@ static int __net_init xfrm_statistics_init(struct net *net)
{
int rv;

- if (snmp_mib_init((void **)net->mib.xfrm_statistics,
+ if (snmp_mib_init((void __percpu **)net->mib.xfrm_statistics,
sizeof(struct linux_xfrm_mib)) < 0)
return -ENOMEM;
rv = xfrm_proc_init(net);
if (rv < 0)
- snmp_mib_free((void **)net->mib.xfrm_statistics);
+ snmp_mib_free((void __percpu **)net->mib.xfrm_statistics);
return rv;
}

static void xfrm_statistics_fini(struct net *net)
{
xfrm_proc_fini(net);
- snmp_mib_free((void **)net->mib.xfrm_statistics);
+ snmp_mib_free((void __percpu **)net->mib.xfrm_statistics);
}
#else
static int __net_init xfrm_statistics_init(struct net *net)
diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c
index fef8db5..54ad2a8 100644
--- a/net/xfrm/xfrm_proc.c
+++ b/net/xfrm/xfrm_proc.c
@@ -50,7 +50,8 @@ static int xfrm_statistics_seq_show(struct seq_file *seq, void *v)
int i;
for (i=0; xfrm_mib_list[i].name; i++)
seq_printf(seq, "%-24s\t%lu\n", xfrm_mib_list[i].name,
- snmp_fold_field((void **)net->mib.xfrm_statistics,
+ snmp_fold_field((void __percpu **)
+ net->mib.xfrm_statistics,
xfrm_mib_list[i].entry));
return 0;
}
--
1.6.4.2

2010-01-25 15:20:18

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 6/8] percpu: add __percpu sparse annotations to trace

Add __percpu sparse annotations to trace.

These annotations are to make sparse consider percpu variables to be
in a different address space and warn if accessed without going
through percpu accessors. This patch doesn't affect normal builds.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
---
include/linux/ftrace_event.h | 4 ++--
include/trace/ftrace.h | 4 ++--
kernel/trace/trace_event_profile.c | 16 ++++++++--------
kernel/trace/trace_functions_graph.c | 2 +-
kernel/trace/trace_kprobe.c | 4 ++--
kernel/trace/trace_ksym.c | 10 +++++-----
kernel/trace/trace_syscalls.c | 4 ++--
7 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 2233c98..72fccdd 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -138,8 +138,8 @@ struct ftrace_event_call {

#define FTRACE_MAX_PROFILE_SIZE 2048

-extern char *perf_trace_buf;
-extern char *perf_trace_buf_nmi;
+extern char __percpu *perf_trace_buf;
+extern char __percpu *perf_trace_buf_nmi;

#define MAX_FILTER_PRED 32
#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index c6fe03e..210d421 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -773,7 +773,7 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
* struct ftrace_event_call *event_call = &event_<call>;
* extern void perf_tp_event(int, u64, u64, void *, int);
* struct ftrace_raw_##call *entry;
- * struct perf_trace_buf *trace_buf;
+ * struct perf_trace_buf __percpu *trace_buf;
* u64 __addr = 0, __count = 1;
* unsigned long irq_flags;
* struct trace_entry *ent;
@@ -859,7 +859,7 @@ ftrace_profile_templ_##call(struct ftrace_event_call *event_call, \
struct trace_entry *ent; \
int __entry_size; \
int __data_size; \
- char *trace_buf; \
+ char __percpu *trace_buf; \
char *raw_data; \
int __cpu; \
int rctx; \
diff --git a/kernel/trace/trace_event_profile.c b/kernel/trace/trace_event_profile.c
index 9e25573..4b16312 100644
--- a/kernel/trace/trace_event_profile.c
+++ b/kernel/trace/trace_event_profile.c
@@ -9,11 +9,11 @@
#include "trace.h"


-char *perf_trace_buf;
-EXPORT_SYMBOL_GPL(perf_trace_buf);
+char __percpu *perf_trace_buf;
+EXPORT_PER_CPU_SYMBOL_GPL(perf_trace_buf);

-char *perf_trace_buf_nmi;
-EXPORT_SYMBOL_GPL(perf_trace_buf_nmi);
+char __percpu *perf_trace_buf_nmi;
+EXPORT_PER_CPU_SYMBOL_GPL(perf_trace_buf_nmi);

typedef typeof(char [FTRACE_MAX_PROFILE_SIZE]) perf_trace_t ;

@@ -22,20 +22,20 @@ static int total_profile_count;

static int ftrace_profile_enable_event(struct ftrace_event_call *event)
{
- char *buf;
+ char __percpu *buf;
int ret = -ENOMEM;

if (event->profile_count++ > 0)
return 0;

if (!total_profile_count) {
- buf = (char *)alloc_percpu(perf_trace_t);
+ buf = (char __percpu *)alloc_percpu(perf_trace_t);
if (!buf)
goto fail_buf;

rcu_assign_pointer(perf_trace_buf, buf);

- buf = (char *)alloc_percpu(perf_trace_t);
+ buf = (char __percpu *)alloc_percpu(perf_trace_t);
if (!buf)
goto fail_buf_nmi;

@@ -81,7 +81,7 @@ int ftrace_profile_enable(int event_id)

static void ftrace_profile_disable_event(struct ftrace_event_call *event)
{
- char *buf, *nmi_buf;
+ char __percpu *buf, *nmi_buf;

if (--event->profile_count > 0)
return;
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 9d976f3..2144178 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -21,7 +21,7 @@ struct fgraph_cpu_data {
};

struct fgraph_data {
- struct fgraph_cpu_data *cpu_data;
+ struct fgraph_cpu_data __percpu *cpu_data;

/* Place to preserve last processed entry. */
struct ftrace_graph_ent_entry ent;
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 6ea90c0..4567950 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -1262,7 +1262,7 @@ static __kprobes int kprobe_profile_func(struct kprobe *kp,
struct trace_entry *ent;
int size, __size, i, pc, __cpu;
unsigned long irq_flags;
- char *trace_buf;
+ char __percpu *trace_buf;
char *raw_data;
int rctx;

@@ -1327,7 +1327,7 @@ static __kprobes int kretprobe_profile_func(struct kretprobe_instance *ri,
struct trace_entry *ent;
int size, __size, i, pc, __cpu;
unsigned long irq_flags;
- char *trace_buf;
+ char __percpu *trace_buf;
char *raw_data;
int rctx;

diff --git a/kernel/trace/trace_ksym.c b/kernel/trace/trace_ksym.c
index 94103cd..7e5c483 100644
--- a/kernel/trace/trace_ksym.c
+++ b/kernel/trace/trace_ksym.c
@@ -42,7 +42,7 @@
#define KSYM_TRACER_OP_LEN 3 /* rw- */

struct trace_ksym {
- struct perf_event **ksym_hbp;
+ struct perf_event * __percpu *ksym_hbp;
struct perf_event_attr attr;
#ifdef CONFIG_PROFILE_KSYM_TRACER
atomic64_t counter;
@@ -200,8 +200,8 @@ int process_new_ksym_entry(char *ksymname, int op, unsigned long addr)
entry->ksym_hbp = register_wide_hw_breakpoint(&entry->attr,
ksym_hbp_handler);

- if (IS_ERR(entry->ksym_hbp)) {
- ret = PTR_ERR(entry->ksym_hbp);
+ if (IS_ERR((void __force *)entry->ksym_hbp)) {
+ ret = PTR_ERR((void __force *)entry->ksym_hbp);
printk(KERN_INFO "ksym_tracer request failed. Try again"
" later!!\n");
goto err;
@@ -331,8 +331,8 @@ static ssize_t ksym_trace_filter_write(struct file *file,
entry->ksym_hbp =
register_wide_hw_breakpoint(&entry->attr,
ksym_hbp_handler);
- if (IS_ERR(entry->ksym_hbp))
- ret = PTR_ERR(entry->ksym_hbp);
+ if (IS_ERR((void __force *)entry->ksym_hbp))
+ ret = PTR_ERR((void __force *)entry->ksym_hbp);
else
goto out_unlock;
}
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 75289f3..9f7de51 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -433,7 +433,7 @@ static void prof_syscall_enter(struct pt_regs *regs, long id)
struct syscall_metadata *sys_data;
struct syscall_trace_enter *rec;
unsigned long flags;
- char *trace_buf;
+ char __percpu *trace_buf;
char *raw_data;
int syscall_nr;
int rctx;
@@ -531,7 +531,7 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret)
struct syscall_trace_exit *rec;
unsigned long flags;
int syscall_nr;
- char *trace_buf;
+ char __percpu *trace_buf;
char *raw_data;
int rctx;
int size;
--
1.6.4.2

2010-01-25 15:21:17

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 8/8] percpu: add __percpu sparse annotations to what's left

Add __percpu sparse annotations to places which didn't make it in one
of the previous patches. All converions are trivial.

These annotations are to make sparse consider percpu variables to be
in a different address space and warn if accessed without going
through percpu accessors. This patch doesn't affect normal builds.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Dan Williams <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Huang Ying <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Neil Brown <[email protected]>
---
crypto/cryptd.c | 2 +-
drivers/acpi/processor_perflib.c | 2 +-
drivers/dma/dmaengine.c | 2 +-
drivers/edac/amd64_edac.c | 2 +-
drivers/md/raid5.c | 2 +-
drivers/md/raid5.h | 2 +-
include/acpi/processor.h | 2 +-
include/linux/dmaengine.h | 2 +-
8 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 704c141..ef71318 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -31,7 +31,7 @@ struct cryptd_cpu_queue {
};

struct cryptd_queue {
- struct cryptd_cpu_queue *cpu_queue;
+ struct cryptd_cpu_queue __percpu *cpu_queue;
};

struct cryptd_instance_ctx {
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 2cabadc..8c6a649 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -557,7 +557,7 @@ end:
}

int acpi_processor_preregister_performance(
- struct acpi_processor_performance *performance)
+ struct acpi_processor_performance __percpu *performance)
{
int count, count_target;
int retval = 0;
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 6f51a0a..4eadd98 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -284,7 +284,7 @@ struct dma_chan_tbl_ent {
/**
* channel_table - percpu lookup table for memory-to-memory offload providers
*/
-static struct dma_chan_tbl_ent *channel_table[DMA_TX_TYPE_END];
+static struct dma_chan_tbl_ent __percpu *channel_table[DMA_TX_TYPE_END];

static int __init dma_channel_table_init(void)
{
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 000dc67..7b36c88 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -13,7 +13,7 @@ module_param(report_gart_errors, int, 0644);
static int ecc_enable_override;
module_param(ecc_enable_override, int, 0644);

-static struct msr *msrs;
+static struct msr __percpu *msrs;

/* Lookup table for all possible MC control instances */
struct amd64_pvt;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index e84204e..77cb3ab 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -4680,7 +4680,7 @@ static int raid5_alloc_percpu(raid5_conf_t *conf)
{
unsigned long cpu;
struct page *spare_page;
- struct raid5_percpu *allcpus;
+ struct raid5_percpu __percpu *allcpus;
void *scribble;
int err;

diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index dd70835..0f86f5e 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -405,7 +405,7 @@ struct raid5_private_data {
* lists and performing address
* conversions
*/
- } *percpu;
+ } __percpu *percpu;
size_t scribble_len; /* size of scribble region must be
* associated with conf to handle
* cpu hotplug while reshaping
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 0ea5ef4..477544f 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -238,7 +238,7 @@ struct acpi_processor_errata {

extern int acpi_processor_preregister_performance(struct
acpi_processor_performance
- *performance);
+ __percpu *performance);

extern int acpi_processor_register_performance(struct acpi_processor_performance
*performance, unsigned int cpu);
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 7878498..21fd9b7 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -162,7 +162,7 @@ struct dma_chan {
struct dma_chan_dev *dev;

struct list_head device_node;
- struct dma_chan_percpu *local;
+ struct dma_chan_percpu __percpu *local;
int client_count;
int table_count;
void *private;
--
1.6.4.2

2010-01-25 15:19:56

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

Add __percpu sparse annotations to hw_breakpoint.

These annotations are to make sparse consider percpu variables to be
in a different address space and warn if accessed without going
through percpu accessors. This patch doesn't affect normal builds.

per_cpu(nr_task_bp_pinned, cpu) is replaced with
&per_cpu(nr_task_bp_pinned[0], cpu). This is the same to the compiler
but allows per_cpu() macro to correctly drop __percpu designation for
the returned pointer.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
---
include/linux/hw_breakpoint.h | 8 ++++----
kernel/hw_breakpoint.c | 14 +++++++-------
samples/hw_breakpoint/data_breakpoint.c | 6 +++---
3 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h
index 41235c9..f462d3d 100644
--- a/include/linux/hw_breakpoint.h
+++ b/include/linux/hw_breakpoint.h
@@ -66,14 +66,14 @@ register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
perf_overflow_handler_t triggered,
int cpu);

-extern struct perf_event **
+extern struct perf_event * __percpu *
register_wide_hw_breakpoint(struct perf_event_attr *attr,
perf_overflow_handler_t triggered);

extern int register_perf_hw_breakpoint(struct perf_event *bp);
extern int __register_perf_hw_breakpoint(struct perf_event *bp);
extern void unregister_hw_breakpoint(struct perf_event *bp);
-extern void unregister_wide_hw_breakpoint(struct perf_event **cpu_events);
+extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events);

extern int reserve_bp_slot(struct perf_event *bp);
extern void release_bp_slot(struct perf_event *bp);
@@ -98,7 +98,7 @@ static inline struct perf_event *
register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
perf_overflow_handler_t triggered,
int cpu) { return NULL; }
-static inline struct perf_event **
+static inline struct perf_event * __percpu *
register_wide_hw_breakpoint(struct perf_event_attr *attr,
perf_overflow_handler_t triggered) { return NULL; }
static inline int
@@ -107,7 +107,7 @@ static inline int
__register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
static inline void unregister_hw_breakpoint(struct perf_event *bp) { }
static inline void
-unregister_wide_hw_breakpoint(struct perf_event **cpu_events) { }
+unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events) { }
static inline int
reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; }
static inline void release_bp_slot(struct perf_event *bp) { }
diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c
index 50dbd59..11dae6d 100644
--- a/kernel/hw_breakpoint.c
+++ b/kernel/hw_breakpoint.c
@@ -74,7 +74,7 @@ static DEFINE_MUTEX(nr_bp_mutex);
static unsigned int max_task_bp_pinned(int cpu)
{
int i;
- unsigned int *tsk_pinned = per_cpu(nr_task_bp_pinned, cpu);
+ unsigned int *tsk_pinned = &per_cpu(nr_task_bp_pinned[0], cpu);

for (i = HBP_NUM -1; i >= 0; i--) {
if (tsk_pinned[i] > 0)
@@ -163,7 +163,7 @@ static void toggle_bp_task_slot(struct task_struct *tsk, int cpu, bool enable)

count = task_bp_pinned(tsk);

- tsk_pinned = per_cpu(nr_task_bp_pinned, cpu);
+ tsk_pinned = &per_cpu(nr_task_bp_pinned[0], cpu);
if (enable) {
tsk_pinned[count]++;
if (count > 0)
@@ -377,17 +377,17 @@ EXPORT_SYMBOL_GPL(unregister_hw_breakpoint);
*
* @return a set of per_cpu pointers to perf events
*/
-struct perf_event **
+struct perf_event * __percpu *
register_wide_hw_breakpoint(struct perf_event_attr *attr,
perf_overflow_handler_t triggered)
{
- struct perf_event **cpu_events, **pevent, *bp;
+ struct perf_event * __percpu *cpu_events, **pevent, *bp;
long err;
int cpu;

cpu_events = alloc_percpu(typeof(*cpu_events));
if (!cpu_events)
- return ERR_PTR(-ENOMEM);
+ return (void __percpu __force *)ERR_PTR(-ENOMEM);

get_online_cpus();
for_each_online_cpu(cpu) {
@@ -415,7 +415,7 @@ fail:
put_online_cpus();

free_percpu(cpu_events);
- return ERR_PTR(err);
+ return (void __percpu __force *)ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint);

@@ -423,7 +423,7 @@ EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint);
* unregister_wide_hw_breakpoint - unregister a wide breakpoint in the kernel
* @cpu_events: the per cpu set of events to unregister
*/
-void unregister_wide_hw_breakpoint(struct perf_event **cpu_events)
+void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events)
{
int cpu;
struct perf_event **pevent;
diff --git a/samples/hw_breakpoint/data_breakpoint.c b/samples/hw_breakpoint/data_breakpoint.c
index c69cbe9..bd0f337 100644
--- a/samples/hw_breakpoint/data_breakpoint.c
+++ b/samples/hw_breakpoint/data_breakpoint.c
@@ -34,7 +34,7 @@
#include <linux/perf_event.h>
#include <linux/hw_breakpoint.h>

-struct perf_event **sample_hbp;
+struct perf_event * __percpu *sample_hbp;

static char ksym_name[KSYM_NAME_LEN] = "pid_max";
module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO);
@@ -61,8 +61,8 @@ static int __init hw_break_module_init(void)
attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;

sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler);
- if (IS_ERR(sample_hbp)) {
- ret = PTR_ERR(sample_hbp);
+ if (IS_ERR((void __force *)sample_hbp)) {
+ ret = PTR_ERR((void __force *)sample_hbp);
goto fail;
}

--
1.6.4.2

2010-01-25 15:20:43

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 1/8] percpu: add __percpu sparse annotations to core kernel subsystems

Add __percpu sparse annotations to core subsystems.

These annotations are to make sparse consider percpu variables to be
in a different address space and warn if accessed without going
through percpu accessors. This patch doesn't affect normal builds.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: [email protected]
Cc: Rusty Russell <[email protected]>
Cc: Dipankar Sarma <[email protected]>
Cc: "Paul E. McKenney" <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Eric Biederman <[email protected]>
---
include/linux/blktrace_api.h | 4 ++--
include/linux/genhd.h | 2 +-
include/linux/kexec.h | 2 +-
include/linux/mmzone.h | 2 +-
include/linux/module.h | 2 +-
include/linux/percpu_counter.h | 2 +-
include/linux/srcu.h | 2 +-
kernel/kexec.c | 2 +-
kernel/sched.c | 4 ++--
kernel/stop_machine.c | 2 +-
mm/percpu.c | 18 ++++++++++--------
11 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
index 3b73b99..416bf62 100644
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -150,8 +150,8 @@ struct blk_user_trace_setup {
struct blk_trace {
int trace_state;
struct rchan *rchan;
- unsigned long *sequence;
- unsigned char *msg_data;
+ unsigned long __percpu *sequence;
+ unsigned char __percpu *msg_data;
u16 act_mask;
u64 start_lba;
u64 end_lba;
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 9717081..56b5051 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -101,7 +101,7 @@ struct hd_struct {
unsigned long stamp;
int in_flight[2];
#ifdef CONFIG_SMP
- struct disk_stats *dkstats;
+ struct disk_stats __percpu *dkstats;
#else
struct disk_stats dkstats;
#endif
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index c356b69..03e8e8d 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -199,7 +199,7 @@ extern struct kimage *kexec_crash_image;
*/
extern struct resource crashk_res;
typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
-extern note_buf_t *crash_notes;
+extern note_buf_t __percpu *crash_notes;
extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
extern size_t vmcoreinfo_size;
extern size_t vmcoreinfo_max_size;
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 7874201..41acd4b 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -301,7 +301,7 @@ struct zone {
unsigned long min_unmapped_pages;
unsigned long min_slab_pages;
#endif
- struct per_cpu_pageset *pageset;
+ struct per_cpu_pageset __percpu *pageset;
/*
* free areas of different sizes
*/
diff --git a/include/linux/module.h b/include/linux/module.h
index 7e74ae0..dd618eb 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -365,7 +365,7 @@ struct module

struct module_ref {
int count;
- } *refptr;
+ } __percpu *refptr;
#endif

#ifdef CONFIG_CONSTRUCTORS
diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h
index a7684a5..9bd103c 100644
--- a/include/linux/percpu_counter.h
+++ b/include/linux/percpu_counter.h
@@ -21,7 +21,7 @@ struct percpu_counter {
#ifdef CONFIG_HOTPLUG_CPU
struct list_head list; /* All percpu_counters are on a list */
#endif
- s32 *counters;
+ s32 __percpu *counters;
};

extern int percpu_counter_batch;
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index 4765d97..41eedcc 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -33,7 +33,7 @@ struct srcu_struct_array {

struct srcu_struct {
int completed;
- struct srcu_struct_array *per_cpu_ref;
+ struct srcu_struct_array __percpu *per_cpu_ref;
struct mutex mutex;
};

diff --git a/kernel/kexec.c b/kernel/kexec.c
index a9a93d9..c769613 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -40,7 +40,7 @@
#include <asm/sections.h>

/* Per cpu memory for storing cpu states in case of system crash. */
-note_buf_t* crash_notes;
+note_buf_t __percpu *crash_notes;

/* vmcoreinfo stuff */
static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
diff --git a/kernel/sched.c b/kernel/sched.c
index 4508fe7..512b10f 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1566,7 +1566,7 @@ static unsigned long cpu_avg_load_per_task(int cpu)

#ifdef CONFIG_FAIR_GROUP_SCHED

-static __read_mostly unsigned long *update_shares_data;
+static __read_mostly unsigned long __percpu *update_shares_data;

static void __set_se_shares(struct sched_entity *se, unsigned long shares);

@@ -10668,7 +10668,7 @@ struct cgroup_subsys cpu_cgroup_subsys = {
struct cpuacct {
struct cgroup_subsys_state css;
/* cpuusage holds pointer to a u64-type object on every cpu */
- u64 *cpuusage;
+ u64 __percpu *cpuusage;
struct percpu_counter cpustat[CPUACCT_STAT_NSTATS];
struct cpuacct *parent;
};
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 912823e..9bb9fb1 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -45,7 +45,7 @@ static int refcount;
static struct workqueue_struct *stop_machine_wq;
static struct stop_machine_data active, idle;
static const struct cpumask *active_cpus;
-static void *stop_machine_work;
+static void __percpu *stop_machine_work;

static void set_state(enum stopmachine_state newstate)
{
diff --git a/mm/percpu.c b/mm/percpu.c
index b336638..768419d 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -80,13 +80,15 @@
/* default addr <-> pcpu_ptr mapping, override in asm/percpu.h if necessary */
#ifndef __addr_to_pcpu_ptr
#define __addr_to_pcpu_ptr(addr) \
- (void *)((unsigned long)(addr) - (unsigned long)pcpu_base_addr \
- + (unsigned long)__per_cpu_start)
+ (void __percpu *)((unsigned long)(addr) - \
+ (unsigned long)pcpu_base_addr + \
+ (unsigned long)__per_cpu_start)
#endif
#ifndef __pcpu_ptr_to_addr
#define __pcpu_ptr_to_addr(ptr) \
- (void *)((unsigned long)(ptr) + (unsigned long)pcpu_base_addr \
- - (unsigned long)__per_cpu_start)
+ (void __force *)((unsigned long)(ptr) + \
+ (unsigned long)pcpu_base_addr - \
+ (unsigned long)__per_cpu_start)
#endif

struct pcpu_chunk {
@@ -1065,7 +1067,7 @@ static struct pcpu_chunk *alloc_pcpu_chunk(void)
* RETURNS:
* Percpu pointer to the allocated area on success, NULL on failure.
*/
-static void *pcpu_alloc(size_t size, size_t align, bool reserved)
+static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
{
static int warn_limit = 10;
struct pcpu_chunk *chunk;
@@ -1194,7 +1196,7 @@ fail_unlock_mutex:
* RETURNS:
* Percpu pointer to the allocated area on success, NULL on failure.
*/
-void *__alloc_percpu(size_t size, size_t align)
+void __percpu *__alloc_percpu(size_t size, size_t align)
{
return pcpu_alloc(size, align, false);
}
@@ -1215,7 +1217,7 @@ EXPORT_SYMBOL_GPL(__alloc_percpu);
* RETURNS:
* Percpu pointer to the allocated area on success, NULL on failure.
*/
-void *__alloc_reserved_percpu(size_t size, size_t align)
+void __percpu *__alloc_reserved_percpu(size_t size, size_t align)
{
return pcpu_alloc(size, align, true);
}
@@ -1267,7 +1269,7 @@ static void pcpu_reclaim(struct work_struct *work)
* CONTEXT:
* Can be called from atomic context.
*/
-void free_percpu(void *ptr)
+void free_percpu(void __percpu *ptr)
{
void *addr;
struct pcpu_chunk *chunk;
--
1.6.4.2

2010-01-25 15:20:53

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 4/8] percpu: add __percpu sparse annotations to net drivers

Add __percpu sparse annotations to net drivers.

These annotations are to make sparse consider percpu variables to be
in a different address space and warn if accessed without going
through percpu accessors. This patch doesn't affect normal builds.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Eric Dumazet <[email protected]>
Cc: David S. Miller <[email protected]>
Cc: Arnd Bergmann <[email protected]>
---
drivers/net/chelsio/sge.c | 2 +-
drivers/net/loopback.c | 16 +++++++++-------
drivers/net/macvlan.c | 2 +-
drivers/net/veth.c | 4 ++--
4 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 109d278..8e12505 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -267,7 +267,7 @@ struct sge {
struct sk_buff *espibug_skb[MAX_NPORTS];
u32 sge_control; /* shadow value of sge control reg */
struct sge_intr_counts stats;
- struct sge_port_stats *port_stats[MAX_NPORTS];
+ struct sge_port_stats __percpu *port_stats[MAX_NPORTS];
struct sched *tx_sched;
struct cmdQ cmdQ[SGE_CMDQ_N] ____cacheline_aligned_in_smp;
};
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index b9fcc98..72b7949 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -72,7 +72,8 @@ struct pcpu_lstats {
static netdev_tx_t loopback_xmit(struct sk_buff *skb,
struct net_device *dev)
{
- struct pcpu_lstats *pcpu_lstats, *lb_stats;
+ struct pcpu_lstats __percpu *pcpu_lstats;
+ struct pcpu_lstats *lb_stats;
int len;

skb_orphan(skb);
@@ -80,7 +81,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
skb->protocol = eth_type_trans(skb, dev);

/* it's OK to use per_cpu_ptr() because BHs are off */
- pcpu_lstats = dev->ml_priv;
+ pcpu_lstats = (void __percpu __force *)dev->ml_priv;
lb_stats = this_cpu_ptr(pcpu_lstats);

len = skb->len;
@@ -95,14 +96,14 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,

static struct net_device_stats *loopback_get_stats(struct net_device *dev)
{
- const struct pcpu_lstats *pcpu_lstats;
+ const struct pcpu_lstats __percpu *pcpu_lstats;
struct net_device_stats *stats = &dev->stats;
unsigned long bytes = 0;
unsigned long packets = 0;
unsigned long drops = 0;
int i;

- pcpu_lstats = dev->ml_priv;
+ pcpu_lstats = (void __percpu __force *)dev->ml_priv;
for_each_possible_cpu(i) {
const struct pcpu_lstats *lb_stats;

@@ -135,19 +136,20 @@ static const struct ethtool_ops loopback_ethtool_ops = {

static int loopback_dev_init(struct net_device *dev)
{
- struct pcpu_lstats *lstats;
+ struct pcpu_lstats __percpu *lstats;

lstats = alloc_percpu(struct pcpu_lstats);
if (!lstats)
return -ENOMEM;

- dev->ml_priv = lstats;
+ dev->ml_priv = (void __force *)lstats;
return 0;
}

static void loopback_dev_free(struct net_device *dev)
{
- struct pcpu_lstats *lstats = dev->ml_priv;
+ struct pcpu_lstats __percpu *lstats =
+ (void __percpu __force *)dev->ml_priv;

free_percpu(lstats);
free_netdev(dev);
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 21a9c9a..4d2040c 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -59,7 +59,7 @@ struct macvlan_dev {
struct hlist_node hlist;
struct macvlan_port *port;
struct net_device *lowerdev;
- struct macvlan_rx_stats *rx_stats;
+ struct macvlan_rx_stats __percpu *rx_stats;
enum macvlan_mode mode;
};

diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 3a15de5..35609e6 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -34,7 +34,7 @@ struct veth_net_stats {

struct veth_priv {
struct net_device *peer;
- struct veth_net_stats *stats;
+ struct veth_net_stats __percpu *stats;
unsigned ip_summed;
};

@@ -263,7 +263,7 @@ static int veth_change_mtu(struct net_device *dev, int new_mtu)

static int veth_dev_init(struct net_device *dev)
{
- struct veth_net_stats *stats;
+ struct veth_net_stats __percpu *stats;
struct veth_priv *priv;

stats = alloc_percpu(struct veth_net_stats);
--
1.6.4.2

2010-01-25 15:35:43

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH 6/8] percpu: add __percpu sparse annotations to trace

On Tue, 2010-01-26 at 00:22 +0900, Tejun Heo wrote:
> Add __percpu sparse annotations to trace.
>
> These annotations are to make sparse consider percpu variables to be
> in a different address space and warn if accessed without going
> through percpu accessors. This patch doesn't affect normal builds.
>
> Signed-off-by: Tejun Heo <[email protected]>

Acked-by: Steven Rostedt <[email protected]>

-- Steve

> Cc: Frederic Weisbecker <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> ---
> include/linux/ftrace_event.h | 4 ++--
> include/trace/ftrace.h | 4 ++--
> kernel/trace/trace_event_profile.c | 16 ++++++++--------
> kernel/trace/trace_functions_graph.c | 2 +-
> kernel/trace/trace_kprobe.c | 4 ++--
> kernel/trace/trace_ksym.c | 10 +++++-----
> kernel/trace/trace_syscalls.c | 4 ++--
> 7 files changed, 22 insertions(+), 22 deletions(-)
>

Subject: Re: [PATCH 8/8] percpu: add __percpu sparse annotations to what's left

On Tue, Jan 26, 2010 at 12:22:15AM +0900, Tejun Heo wrote:
> Add __percpu sparse annotations to places which didn't make it in one
> of the previous patches. All converions are trivial.
>
> These annotations are to make sparse consider percpu variables to be
> in a different address space and warn if accessed without going
> through percpu accessors. This patch doesn't affect normal builds.
>
> Signed-off-by: Tejun Heo <[email protected]>
> Cc: Dan Williams <[email protected]>
> Cc: Borislav Petkov <[email protected]>
> Cc: Huang Ying <[email protected]>
> Cc: Len Brown <[email protected]>
> Cc: Neil Brown <[email protected]>
> ---
> crypto/cryptd.c | 2 +-
> drivers/acpi/processor_perflib.c | 2 +-
> drivers/dma/dmaengine.c | 2 +-
> drivers/edac/amd64_edac.c | 2 +-

For the edac bits:

Acked-by: Borislav Petkov <[email protected]>

--
Regards/Gruss,
Boris.

--
Advanced Micro Devices, Inc.
Operating Systems Research Center

2010-01-25 21:32:40

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 3/8] percpu: add __percpu sparse annotations to net

From: Tejun Heo <[email protected]>
Date: Tue, 26 Jan 2010 00:22:10 +0900

> Add __percpu sparse annotations to net.
>
> These annotations are to make sparse consider percpu variables to be
> in a different address space and warn if accessed without going
> through percpu accessors. This patch doesn't affect normal builds.
>
> The macro and type tricks around snmp stats make things a bit
> interesting. DEFINE/DECLARE_SNMP_STAT() macros mark the target field
> as __percpu and SNMP_UPD_PO_STATS() macro is updated accordingly. All
> snmp_mib_*() users which used to cast the argument to (void **) are
> updated to cast it to (void __percpu **).
>
> Signed-off-by: Tejun Heo <[email protected]>

Acked-by: David S. Miller <[email protected]>

2010-01-25 21:33:01

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 4/8] percpu: add __percpu sparse annotations to net drivers

From: Tejun Heo <[email protected]>
Date: Tue, 26 Jan 2010 00:22:11 +0900

> Add __percpu sparse annotations to net drivers.
>
> These annotations are to make sparse consider percpu variables to be
> in a different address space and warn if accessed without going
> through percpu accessors. This patch doesn't affect normal builds.
>
> Signed-off-by: Tejun Heo <[email protected]>

Acked-by: David S. Miller <[email protected]>

2010-01-25 23:14:20

by Al Viro

[permalink] [raw]
Subject: Re: [PATCHSET] percpu: add __percpu sparse annotations

On Tue, Jan 26, 2010 at 12:22:07AM +0900, Tejun Heo wrote:
> This patchset adds __percpu sparse annotations to all percpu users
> covered by x86_64 allmodconfig. __percpu annotation teaches sparse
> that percpu variables live in a separate address space and can't be
> accessed directly without going through percpu accessors. This allows
> detection of most percpu access mistakes involving both static and
> dyanmic percpu variables.
>
> This patchset contains the following eight patches.
>
> 0001-percpu-add-__percpu-sparse-annotations-to-core-kerne.patch
> 0002-percpu-add-__percpu-sparse-annotations-to-fs.patch
> 0003-percpu-add-__percpu-sparse-annotations-to-net.patch
> 0004-percpu-add-__percpu-sparse-annotations-to-net-driver.patch
> 0005-percpu-add-__percpu-sparse-annotations-to-x86.patch
> 0006-percpu-add-__percpu-sparse-annotations-to-trace.patch
> 0007-percpu-add-__percpu-sparse-annotations-to-hw_breakpo.patch
> 0008-percpu-add-__percpu-sparse-annotations-to-what-s-lef.patch
>
> As these annotations are for sparse, none of the above patches affects
> normal kernel build and most of the conversions are straight-forward
> and trivial. There are a few places where the conversion isn't
> completely straight-forward (but still fairly trivial). Those are
> mentioned in each patch description.
>
> I can route the patch through percpu and conflict resolution, if
> necessary, wouldn't be difficult at all for these changes. If anyone
> wants to route one of these patches through a different tree, please
> let me know. All that's necessary would be adding dummy __percpu
> definition to the patch.
>
> If nobody objects, I'll push these into percpu tree in three or four
> days.

Um. Where *is* the definition of __percpu? Presumably, that'd be
something like __attribute__((noderef,address_space(4)) under ifdef
__CHECKER__ and empty otherwise? If so, I'm fine with that patchset,
provided that it does grow that #define and becomes self-contained...

2010-01-26 00:19:14

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On Tue, Jan 26, 2010 at 12:22:14AM +0900, Tejun Heo wrote:
> Add __percpu sparse annotations to hw_breakpoint.
>
> These annotations are to make sparse consider percpu variables to be
> in a different address space and warn if accessed without going
> through percpu accessors. This patch doesn't affect normal builds.
>
> per_cpu(nr_task_bp_pinned, cpu) is replaced with
> &per_cpu(nr_task_bp_pinned[0], cpu). This is the same to the compiler
> but allows per_cpu() macro to correctly drop __percpu designation for
> the returned pointer.



Ouch... It's unpleasant to see such workaround that messes up the
code just to make sparse happy.

I guess __percpu is an address_space attribute? Is there no
way to force the address space change directly from the
per_cpu() macro?

Thanks.

2010-01-26 00:25:40

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCHSET] percpu: add __percpu sparse annotations

Hello,

On 01/26/2010 08:14 AM, Al Viro wrote:
> Um. Where *is* the definition of __percpu? Presumably, that'd be
> something like __attribute__((noderef,address_space(4)) under ifdef
> __CHECKER__ and empty otherwise? If so, I'm fine with that patchset,
> provided that it does grow that #define and becomes self-contained...

Ah... sorry, I forgot about the base tree. The definition has been in
the percpu tree for some time now. The patchset is on top of the
following branch.

git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git for-next

and the series is available as git tree in the following branch.

git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git percpu-sparse-review

The definition is in include/linux/compiler.h.

# define __percpu __attribute__((noderef, address_space(3)))

which gets replaced by dummy def if !__CHECKER__.

Thanks.

--
tejun

2010-01-26 00:43:48

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

Hello, Frederic.

On 01/26/2010 09:19 AM, Frederic Weisbecker wrote:
> On Tue, Jan 26, 2010 at 12:22:14AM +0900, Tejun Heo wrote:
>> Add __percpu sparse annotations to hw_breakpoint.
>>
>> These annotations are to make sparse consider percpu variables to be
>> in a different address space and warn if accessed without going
>> through percpu accessors. This patch doesn't affect normal builds.
>>
>> per_cpu(nr_task_bp_pinned, cpu) is replaced with
>> &per_cpu(nr_task_bp_pinned[0], cpu). This is the same to the compiler
>> but allows per_cpu() macro to correctly drop __percpu designation for
>> the returned pointer.
>
> Ouch... It's unpleasant to see such workaround that messes up the
> code just to make sparse happy.
>
> I guess __percpu is an address_space attribute? Is there no
> way to force the address space change directly from the
> per_cpu() macro?

Yeah, per_cpu() macro does that but when things get a bit complicated
with static percpu arrays. In the above case, the variable is defined
as

static DEFINE_PER_CPU(unsigned int, nr_task_bp_pinned[HBP_NUM]);

which gets translated to

static __attribute__((noderef, address_space(3))) \
__attribute__((section(.data.percpu))) \
__typeof__(unsigned int) nr_task_bp_pinned[HBP_NUM];

The above tells sparse that the members of nr_task_bp_pinned array are
in address space 3 which is correct. The problematic dereference was

unsigned int *task_pinned = per_cpu(nr_task_bp_pinned, cpu)

per_cpu() macro changes the address space of the resulting address but
it does so assuming that the parameter it got passed is the one which
got declared to be in the percpu address space. It casts
nr_task_bp_pinned itself, which to the sparse isn't in the percpu
address space, to the kernel address space. So, the workaround is
basically to give per_cpu() macro the same thing that was defined.

This type of usage (define as array, dereference the array as address)
was the only place where I needed to work around to make address space
change explicit. There are two places which needed this and hwbreak
was one. The options were...

* Leave it alone. We can live with a few additional sparse warnings.

* Make the proposed change. It is slightly ugly but not cryptic or
difficult.

* Somehow teach per_cpu() macro or sparse how to handle the above
right.

I tried to improve per_cpu() macro but couldn't do it in any sane way.
Leaving it alone isn't too bad either but given that the workaround is
not horribly unreadable, I think it's best to use the slightly less
elegant form in the few places where they are needed.

Thanks.

--
tejun

2010-01-26 01:02:47

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On Tue, Jan 26, 2010 at 09:48:45AM +0900, Tejun Heo wrote:
> Hello, Frederic.
>
> On 01/26/2010 09:19 AM, Frederic Weisbecker wrote:
> > On Tue, Jan 26, 2010 at 12:22:14AM +0900, Tejun Heo wrote:
> >> Add __percpu sparse annotations to hw_breakpoint.
> >>
> >> These annotations are to make sparse consider percpu variables to be
> >> in a different address space and warn if accessed without going
> >> through percpu accessors. This patch doesn't affect normal builds.
> >>
> >> per_cpu(nr_task_bp_pinned, cpu) is replaced with
> >> &per_cpu(nr_task_bp_pinned[0], cpu). This is the same to the compiler
> >> but allows per_cpu() macro to correctly drop __percpu designation for
> >> the returned pointer.
> >
> > Ouch... It's unpleasant to see such workaround that messes up the
> > code just to make sparse happy.
> >
> > I guess __percpu is an address_space attribute? Is there no
> > way to force the address space change directly from the
> > per_cpu() macro?
>
> Yeah, per_cpu() macro does that but when things get a bit complicated
> with static percpu arrays. In the above case, the variable is defined
> as
>
> static DEFINE_PER_CPU(unsigned int, nr_task_bp_pinned[HBP_NUM]);
>
> which gets translated to
>
> static __attribute__((noderef, address_space(3))) \
> __attribute__((section(.data.percpu))) \
> __typeof__(unsigned int) nr_task_bp_pinned[HBP_NUM];
>
> The above tells sparse that the members of nr_task_bp_pinned array are
> in address space 3 which is correct. The problematic dereference was
>
> unsigned int *task_pinned = per_cpu(nr_task_bp_pinned, cpu)
>
> per_cpu() macro changes the address space of the resulting address but
> it does so assuming that the parameter it got passed is the one which
> got declared to be in the percpu address space. It casts
> nr_task_bp_pinned itself, which to the sparse isn't in the percpu
> address space, to the kernel address space. So, the workaround is
> basically to give per_cpu() macro the same thing that was defined.
>
> This type of usage (define as array, dereference the array as address)
> was the only place where I needed to work around to make address space
> change explicit. There are two places which needed this and hwbreak
> was one. The options were...
>
> * Leave it alone. We can live with a few additional sparse warnings.
>
> * Make the proposed change. It is slightly ugly but not cryptic or
> difficult.
>
> * Somehow teach per_cpu() macro or sparse how to handle the above
> right.
>
> I tried to improve per_cpu() macro but couldn't do it in any sane way.
> Leaving it alone isn't too bad either but given that the workaround is
> not horribly unreadable, I think it's best to use the slightly less
> elegant form in the few places where they are needed.



Ok.

Well, sorry I must be missing something obvious, but is it impossible
to make per_cpu(var, cpu) returning something cast in:

(typeof(var) __force)

Or I guess you did that already and it is not working with static
arrays, or?

Is there a patch that shows per_cpu() macro changes in the batch?

Thanks.

2010-01-26 01:12:43

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On Mon, Jan 25, 2010 at 05:06:37PM -0800, H. Peter Anvin wrote:
> On 01/25/2010 04:19 PM, Frederic Weisbecker wrote:
> > On Tue, Jan 26, 2010 at 12:22:14AM +0900, Tejun Heo wrote:
> >> Add __percpu sparse annotations to hw_breakpoint.
> >>
> >> These annotations are to make sparse consider percpu variables to be
> >> in a different address space and warn if accessed without going
> >> through percpu accessors. This patch doesn't affect normal builds.
> >>
> >> per_cpu(nr_task_bp_pinned, cpu) is replaced with
> >> &per_cpu(nr_task_bp_pinned[0], cpu). This is the same to the compiler
> >> but allows per_cpu() macro to correctly drop __percpu designation for
> >> the returned pointer.
> >
> > Ouch... It's unpleasant to see such workaround that messes up the
> > code just to make sparse happy.
> >
> > I guess __percpu is an address_space attribute? Is there no
> > way to force the address space change directly from the
> > per_cpu() macro?
> >
>
> Hmm... thinking more about it, we should be able to just move the & and
> [0] into the per_cpu() macro, addressing the situation, or does that
> cause problems elsewhere?
>
> -hpa


That would work only with arrays. per_cpu() can access either pointers
or direct values. Well that can be worked around with fake casts, but
I would except the (typeof(x) __force) to work and then offer a more
elegant solution.

2010-01-26 01:14:57

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

Hello,

On 01/26/2010 10:02 AM, Frederic Weisbecker wrote:
> Well, sorry I must be missing something obvious, but is it impossible
> to make per_cpu(var, cpu) returning something cast in:
>
> (typeof(var) __force)
>
> Or I guess you did that already and it is not working with static
> arrays, or?

Yeap, the definition looks like

#define SHIFT_PERCPU_PTR(__p, __offset) ({ \
__verify_pcpu_ptr((__p)); \
RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)); \
})

#define per_cpu(var, cpu) \
(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))

but it just ends up putting the __force at the wrong layer. It seems
that (typeof(var) __kernel __force) tell sparse var is in the kernel
address space but not its members.

> Is there a patch that shows per_cpu() macro changes in the batch?

Sorry I forgot to write about this. It's in the percpu tree.

git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git for-next

The related commits are 545695fb41da117928ab946067a42d9e15fd009d and
e0fdb0e050eae331046385643618f12452aa7e73.

Thanks.

--
tejun

2010-01-26 01:16:25

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On 01/25/2010 04:19 PM, Frederic Weisbecker wrote:
> On Tue, Jan 26, 2010 at 12:22:14AM +0900, Tejun Heo wrote:
>> Add __percpu sparse annotations to hw_breakpoint.
>>
>> These annotations are to make sparse consider percpu variables to be
>> in a different address space and warn if accessed without going
>> through percpu accessors. This patch doesn't affect normal builds.
>>
>> per_cpu(nr_task_bp_pinned, cpu) is replaced with
>> &per_cpu(nr_task_bp_pinned[0], cpu). This is the same to the compiler
>> but allows per_cpu() macro to correctly drop __percpu designation for
>> the returned pointer.
>
> Ouch... It's unpleasant to see such workaround that messes up the
> code just to make sparse happy.
>
> I guess __percpu is an address_space attribute? Is there no
> way to force the address space change directly from the
> per_cpu() macro?
>

A cast (using __typeof__) combined with an address space override?

-hpa

2010-01-26 01:19:15

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 5/8] percpu: add __percpu sparse annotations to x86

On 01/25/2010 07:22 AM, Tejun Heo wrote:
>
> In arch/x86/kernel/cpu/common.c, per_cpu(exception_stacks, cpu) is
> replaced with &per_cpu(exception_stacks[0], cpu) which is equivalent
> except that it allows per_cpu() macro to correctly drop percpu
> designation during sparse pass.
>

Same comment as Frederic's about this... this kind of uglification
really is unacceptable and needs to be addressed.

Other than that, it looks good.

-hpa

2010-01-26 01:19:35

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On 01/25/2010 04:19 PM, Frederic Weisbecker wrote:
> On Tue, Jan 26, 2010 at 12:22:14AM +0900, Tejun Heo wrote:
>> Add __percpu sparse annotations to hw_breakpoint.
>>
>> These annotations are to make sparse consider percpu variables to be
>> in a different address space and warn if accessed without going
>> through percpu accessors. This patch doesn't affect normal builds.
>>
>> per_cpu(nr_task_bp_pinned, cpu) is replaced with
>> &per_cpu(nr_task_bp_pinned[0], cpu). This is the same to the compiler
>> but allows per_cpu() macro to correctly drop __percpu designation for
>> the returned pointer.
>
> Ouch... It's unpleasant to see such workaround that messes up the
> code just to make sparse happy.
>
> I guess __percpu is an address_space attribute? Is there no
> way to force the address space change directly from the
> per_cpu() macro?
>

Hmm... thinking more about it, we should be able to just move the & and
[0] into the per_cpu() macro, addressing the situation, or does that
cause problems elsewhere?

-hpa

2010-01-26 02:01:23

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On Tue, Jan 26, 2010 at 10:19:04AM +0900, Tejun Heo wrote:
> Hello,
>
> On 01/26/2010 10:02 AM, Frederic Weisbecker wrote:
> > Well, sorry I must be missing something obvious, but is it impossible
> > to make per_cpu(var, cpu) returning something cast in:
> >
> > (typeof(var) __force)
> >
> > Or I guess you did that already and it is not working with static
> > arrays, or?
>
> Yeap, the definition looks like
>
> #define SHIFT_PERCPU_PTR(__p, __offset) ({ \
> __verify_pcpu_ptr((__p)); \
> RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)); \
> })
>
> #define per_cpu(var, cpu) \
> (*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))
>
> but it just ends up putting the __force at the wrong layer. It seems
> that (typeof(var) __kernel __force) tell sparse var is in the kernel
> address space but not its members.


So, may be it considers you are applying the address space overriding
to the pointer to the type and not to the type itself.

Consider:

int __percpu i;

What you do above *might* be considered as if SHIFT_PERCPU_PTR
returns something of a type:

int * __percpu i;

So the pointer is in the normal address space, but its content is in
__percpu address space.

What if you do this:


#define SHIFT_PERCPU_PTR(__p, __offset) ({ \
__verify_pcpu_ptr((__p)); \
RELOC_HIDE((__p), (__offset)); \
})

#define per_cpu(var, cpu) \
(typeof(var) __kernel __force)(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))

This should work because &(var) should be dereferencable directly, since
it is not of type "__force t" but of type "*__force t"

And you're not doing anymore this:

*(int * __kernel __force) i;
but
*(int __kernel __force *) i;


That all might make no sense, I'm just trying to think like a backend
so it might sound like I should just take more sleep and just shut up...

2010-01-26 02:01:21

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

Hello,

On 01/26/2010 10:02 AM, H. Peter Anvin wrote:
> A cast (using __typeof__) combined with an address space override?

That still puts the address specification at the wrong level. The
problem is that the __typeof__ would be an array type which itself
doesn't have address space set but its members are in address space 3.
So, you need to get *inside* the array type def to change that. :-(

Thanks.

--
tejun

2010-01-26 02:05:26

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

Hello,

On 01/26/2010 10:06 AM, H. Peter Anvin wrote:
>> I guess __percpu is an address_space attribute? Is there no
>> way to force the address space change directly from the
>> per_cpu() macro?
>>
>
> Hmm... thinking more about it, we should be able to just move the & and
> [0] into the per_cpu() macro, addressing the situation, or does that
> cause problems elsewhere?

Hmmm.... the argument gotta be an lvalue. Let me try just in case.
Nope, it doesn't work.

Thanks.

--
tejun

2010-01-26 02:05:47

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On Tue, Jan 26, 2010 at 11:06:10AM +0900, Tejun Heo wrote:
> Hello,
>
> On 01/26/2010 10:02 AM, H. Peter Anvin wrote:
> > A cast (using __typeof__) combined with an address space override?
>
> That still puts the address specification at the wrong level. The
> problem is that the __typeof__ would be an array type which itself
> doesn't have address space set but its members are in address space 3.
> So, you need to get *inside* the array type def to change that. :-(

Could you post the actual definitions in one piece? Would be easier to
discuss what's going on...

2010-01-26 02:08:34

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

Hello,

On 01/26/2010 11:01 AM, Frederic Weisbecker wrote:
> So, may be it considers you are applying the address space overriding
> to the pointer to the type and not to the type itself.
>
> Consider:
>
> int __percpu i;
>
> What you do above *might* be considered as if SHIFT_PERCPU_PTR
> returns something of a type:
>
> int * __percpu i;
>
> So the pointer is in the normal address space, but its content is in
> __percpu address space.
>
> What if you do this:
>
>
> #define SHIFT_PERCPU_PTR(__p, __offset) ({ \
> __verify_pcpu_ptr((__p)); \
> RELOC_HIDE((__p), (__offset)); \
> })
>
> #define per_cpu(var, cpu) \
> (typeof(var) __kernel __force)(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))

arch/x86/kernel/cpu/common.c:1149:20: warning: cast to non-scalar
arch/x86/kernel/cpu/common.c:1149:20: error: strange non-value function or array
CC arch/x86/kernel/cpu/common.o
arch/x86/kernel/cpu/common.c: In function 'cpu_init':
arch/x86/kernel/cpu/common.c:1149: error: cast specifies array type

Can't cast that way. :-(

--
tejun

2010-01-26 02:10:49

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On Tue, Jan 26, 2010 at 03:01:14AM +0100, Frederic Weisbecker wrote:
> On Tue, Jan 26, 2010 at 10:19:04AM +0900, Tejun Heo wrote:
> > Hello,
> >
> > On 01/26/2010 10:02 AM, Frederic Weisbecker wrote:
> > > Well, sorry I must be missing something obvious, but is it impossible
> > > to make per_cpu(var, cpu) returning something cast in:
> > >
> > > (typeof(var) __force)
> > >
> > > Or I guess you did that already and it is not working with static
> > > arrays, or?
> >
> > Yeap, the definition looks like
> >
> > #define SHIFT_PERCPU_PTR(__p, __offset) ({ \
> > __verify_pcpu_ptr((__p)); \
> > RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)); \
> > })
> >
> > #define per_cpu(var, cpu) \
> > (*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))
> >
> > but it just ends up putting the __force at the wrong layer. It seems
> > that (typeof(var) __kernel __force) tell sparse var is in the kernel
> > address space but not its members.
>
>
> So, may be it considers you are applying the address space overriding
> to the pointer to the type and not to the type itself.
>
> Consider:
>
> int __percpu i;
>
> What you do above *might* be considered as if SHIFT_PERCPU_PTR
> returns something of a type:
>
> int * __percpu i;
>
> So the pointer is in the normal address space, but its content is in
> __percpu address space.
>
> What if you do this:
>
>
> #define SHIFT_PERCPU_PTR(__p, __offset) ({ \
> __verify_pcpu_ptr((__p)); \
> RELOC_HIDE((__p), (__offset)); \
> })
>
> #define per_cpu(var, cpu) \
> (typeof(var) __kernel __force)(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))
>
> This should work because &(var) should be dereferencable directly, since
> it is not of type "__force t" but of type "*__force t"
>
> And you're not doing anymore this:
>
> *(int * __kernel __force) i;
> but
> *(int __kernel __force *) i;



The above is perhaps a bit confusing.
To be more clear, in the first case you only cast the pointer
to the type, which gives you a pointer valid in kernel space
to data valid in percpu space.

The second case gives you something valid in kernel space for both.

2010-01-26 02:12:21

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 5/8] percpu: add __percpu sparse annotations to x86

On 01/26/2010 10:06 AM, H. Peter Anvin wrote:
> On 01/25/2010 07:22 AM, Tejun Heo wrote:
>>
>> In arch/x86/kernel/cpu/common.c, per_cpu(exception_stacks, cpu) is
>> replaced with &per_cpu(exception_stacks[0], cpu) which is equivalent
>> except that it allows per_cpu() macro to correctly drop percpu
>> designation during sparse pass.
>>
>
> Same comment as Frederic's about this... this kind of uglification
> really is unacceptable and needs to be addressed.

Hmm... I don't think it's too bad but if you don't like it that much,
probably the right thing to do is just leave it there and let sparse
whine about it. There are only three in-kernel instances at this
point, so it's not that big a deal.

Thanks.

--
tejun

2010-01-26 02:12:37

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On 01/26/2010 11:04 AM, Al Viro wrote:
> On Tue, Jan 26, 2010 at 11:06:10AM +0900, Tejun Heo wrote:
>> Hello,
>>
>> On 01/26/2010 10:02 AM, H. Peter Anvin wrote:
>>> A cast (using __typeof__) combined with an address space override?
>>
>> That still puts the address specification at the wrong level. The
>> problem is that the __typeof__ would be an array type which itself
>> doesn't have address space set but its members are in address space 3.
>> So, you need to get *inside* the array type def to change that. :-(
>
> Could you post the actual definitions in one piece? Would be easier to
> discuss what's going on...

Here it is.

# define RELOC_HIDE(ptr, off) \
({ unsigned long __ptr; \
__ptr = (unsigned long) (ptr); \
(typeof(ptr)) (__ptr + (off)); })

#define __verify_pcpu_ptr(ptr) do { \
const void __percpu *__vpp_verify = (typeof(ptr))NULL; \
(void)__vpp_verify; \
} while (0)

/* Weird cast keeps both GCC and sparse happy. */
#define SHIFT_PERCPU_PTR(__p, __offset) ({ \
__verify_pcpu_ptr((__p)); \
RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)); \
})

#define per_cpu(var, cpu) \
(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))

Thanks.

--
tejun

2010-01-26 02:18:54

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On Tue, Jan 26, 2010 at 11:13:59AM +0900, Tejun Heo wrote:
> Hello,
>
> On 01/26/2010 11:01 AM, Frederic Weisbecker wrote:
> > So, may be it considers you are applying the address space overriding
> > to the pointer to the type and not to the type itself.
> >
> > Consider:
> >
> > int __percpu i;
> >
> > What you do above *might* be considered as if SHIFT_PERCPU_PTR
> > returns something of a type:
> >
> > int * __percpu i;
> >
> > So the pointer is in the normal address space, but its content is in
> > __percpu address space.
> >
> > What if you do this:
> >
> >
> > #define SHIFT_PERCPU_PTR(__p, __offset) ({ \
> > __verify_pcpu_ptr((__p)); \
> > RELOC_HIDE((__p), (__offset)); \
> > })
> >
> > #define per_cpu(var, cpu) \
> > (typeof(var) __kernel __force)(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))
>
> arch/x86/kernel/cpu/common.c:1149:20: warning: cast to non-scalar
> arch/x86/kernel/cpu/common.c:1149:20: error: strange non-value function or array
> CC arch/x86/kernel/cpu/common.o
> arch/x86/kernel/cpu/common.c: In function 'cpu_init':
> arch/x86/kernel/cpu/common.c:1149: error: cast specifies array type
>
> Can't cast that way. :-(


What about this? It doesn't use direct cast to scalar but should
create a pointer type to kernel space datas:


#define kernel_space_t(var) \
(typeof(var) __kernel __force)

#define SHIFT_PERCPU_PTR(__p, __offset) ({ \
__verify_pcpu_ptr((__p)); \
RELOC_HIDE((typeof(*(kernel_space_t(var)) __kernel __force *)(__p), (__offset)); \
})

#define per_cpu(var, cpu) \
(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))

2010-01-26 02:22:18

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On Tue, Jan 26, 2010 at 03:18:48AM +0100, Frederic Weisbecker wrote:
> On Tue, Jan 26, 2010 at 11:13:59AM +0900, Tejun Heo wrote:
> > Hello,
> >
> > On 01/26/2010 11:01 AM, Frederic Weisbecker wrote:
> > > So, may be it considers you are applying the address space overriding
> > > to the pointer to the type and not to the type itself.
> > >
> > > Consider:
> > >
> > > int __percpu i;
> > >
> > > What you do above *might* be considered as if SHIFT_PERCPU_PTR
> > > returns something of a type:
> > >
> > > int * __percpu i;
> > >
> > > So the pointer is in the normal address space, but its content is in
> > > __percpu address space.
> > >
> > > What if you do this:
> > >
> > >
> > > #define SHIFT_PERCPU_PTR(__p, __offset) ({ \
> > > __verify_pcpu_ptr((__p)); \
> > > RELOC_HIDE((__p), (__offset)); \
> > > })
> > >
> > > #define per_cpu(var, cpu) \
> > > (typeof(var) __kernel __force)(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))
> >
> > arch/x86/kernel/cpu/common.c:1149:20: warning: cast to non-scalar
> > arch/x86/kernel/cpu/common.c:1149:20: error: strange non-value function or array
> > CC arch/x86/kernel/cpu/common.o
> > arch/x86/kernel/cpu/common.c: In function 'cpu_init':
> > arch/x86/kernel/cpu/common.c:1149: error: cast specifies array type
> >
> > Can't cast that way. :-(
>
>
> What about this? It doesn't use direct cast to scalar but should
> create a pointer type to kernel space datas:
>
>
> #define kernel_space_t(var) \
> (typeof(var) __kernel __force)


Should be typeof(*var)



>
> #define SHIFT_PERCPU_PTR(__p, __offset) ({ \
> __verify_pcpu_ptr((__p)); \
> RELOC_HIDE((typeof(*(kernel_space_t(var)) __kernel __force *)(__p), (__offset)); \
> })
>
> #define per_cpu(var, cpu) \
> (*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))
>

2010-01-26 02:29:27

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On 01/26/2010 11:22 AM, Frederic Weisbecker wrote:
>> What about this? It doesn't use direct cast to scalar but should
>> create a pointer type to kernel space datas:
>>
>>
>> #define kernel_space_t(var) \
>> (typeof(var) __kernel __force)
>
>
> Should be typeof(*var)
>
>>
>> #define SHIFT_PERCPU_PTR(__p, __offset) ({ \
>> __verify_pcpu_ptr((__p)); \
>> RELOC_HIDE((typeof(*(kernel_space_t(var)) __kernel __force *)(__p), (__offset)); \
>> })

Can you balance ()'s here too?

--
tejun

2010-01-26 02:33:33

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On Tue, Jan 26, 2010 at 11:16:42AM +0900, Tejun Heo wrote:

> # define RELOC_HIDE(ptr, off) \
> ({ unsigned long __ptr; \
> __ptr = (unsigned long) (ptr); \
> (typeof(ptr)) (__ptr + (off)); })
>
> #define __verify_pcpu_ptr(ptr) do { \
> const void __percpu *__vpp_verify = (typeof(ptr))NULL; \
> (void)__vpp_verify; \
> } while (0)
>
> /* Weird cast keeps both GCC and sparse happy. */
> #define SHIFT_PERCPU_PTR(__p, __offset) ({ \
> __verify_pcpu_ptr((__p)); \
> RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)); \
> })
>
> #define per_cpu(var, cpu) \
> (*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))

Eh... You are leaving that noderef in place in case of array. And _that_
is not an address space, so casts to AS 0 won't do you any good.

2010-01-26 02:35:50

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On Tue, Jan 26, 2010 at 11:34:40AM +0900, Tejun Heo wrote:
> On 01/26/2010 11:22 AM, Frederic Weisbecker wrote:
> >> What about this? It doesn't use direct cast to scalar but should
> >> create a pointer type to kernel space datas:
> >>
> >>
> >> #define kernel_space_t(var) \
> >> (typeof(var) __kernel __force)
> >
> >
> > Should be typeof(*var)
> >
> >>
> >> #define SHIFT_PERCPU_PTR(__p, __offset) ({ \
> >> __verify_pcpu_ptr((__p)); \
> >> RELOC_HIDE((typeof(*(kernel_space_t(var)) __kernel __force *)(__p), (__offset)); \
> >> })
>
> Can you balance ()'s here too?


#define kernel_space_t(var) \
(typeof(*(var)) __kernel __force)


/* Weird cast keeps both GCC and sparse happy. */
#define SHIFT_PERCPU_PTR(__p, __offset) ({ \
__verify_pcpu_ptr((__p)); \
RELOC_HIDE((typeof(*(kernel_space_t(__p))) __kernel __force *)(__p), (__offset)); \
})

#define per_cpu(var, cpu) \
(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)));


No guarantee that will build. I should pull your tree and install
sparse (yeah, shame on me, I've never installed it).

2010-01-26 02:38:45

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

Hello,

On 01/26/2010 11:32 AM, Al Viro wrote:
> On Tue, Jan 26, 2010 at 11:16:42AM +0900, Tejun Heo wrote:
>
>> # define RELOC_HIDE(ptr, off) \
>> ({ unsigned long __ptr; \
>> __ptr = (unsigned long) (ptr); \
>> (typeof(ptr)) (__ptr + (off)); })
>>
>> #define __verify_pcpu_ptr(ptr) do { \
>> const void __percpu *__vpp_verify = (typeof(ptr))NULL; \
>> (void)__vpp_verify; \
>> } while (0)
>>
>> /* Weird cast keeps both GCC and sparse happy. */
>> #define SHIFT_PERCPU_PTR(__p, __offset) ({ \
>> __verify_pcpu_ptr((__p)); \
>> RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)); \
>> })
>>
>> #define per_cpu(var, cpu) \
>> (*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))
>
> Eh... You are leaving that noderef in place in case of array. And _that_
> is not an address space, so casts to AS 0 won't do you any good.

Any ideas on how to fix it?

Thanks.

--
tejun

2010-01-26 02:43:11

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On 01/26/2010 11:35 AM, Frederic Weisbecker wrote:
> No guarantee that will build. I should pull your tree and install
> sparse (yeah, shame on me, I've never installed it).

Nope, it doesn't. Please pull from the following tree to receive the
whole thing. The definitions in question are in
include/asm-generic/percpu.h.

git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git percpu-sparse-review

After installing sparse,

make C=2 arch/x86/kernel/cpu/common.o

should be enough.

Thanks.

--
tejun

2010-01-26 02:49:49

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On Tue, Jan 26, 2010 at 11:43:56AM +0900, Tejun Heo wrote:

> > Eh... You are leaving that noderef in place in case of array. And _that_
> > is not an address space, so casts to AS 0 won't do you any good.
>
> Any ideas on how to fix it?

BTW, before we go any further, which warnings are you getting from sparse
and which version of sparse are you using?

noderef is one thing; address_space mess is a different story. The version
I have here steps into the former, but not the latter; what are you seeing?

2010-01-26 03:14:42

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

Hello,

On 01/26/2010 11:48 AM, Al Viro wrote:
> On Tue, Jan 26, 2010 at 11:43:56AM +0900, Tejun Heo wrote:
>
>>> Eh... You are leaving that noderef in place in case of array. And _that_
>>> is not an address space, so casts to AS 0 won't do you any good.
>>
>> Any ideas on how to fix it?
>
> BTW, before we go any further, which warnings are you getting from sparse
> and which version of sparse are you using?
>
> noderef is one thing; address_space mess is a different story. The version
> I have here steps into the former, but not the latter; what are you seeing?

Oops, I too am seeing the noderef thing not the address space warning.

char *estacks = per_cpu(exception_stacks, cpu);

I get

arch/x86/kernel/cpu/common.c:1149:19: warning: incorrect type in initializer (different modifiers)
arch/x86/kernel/cpu/common.c:1149:19: expected char *estacks
arch/x86/kernel/cpu/common.c:1149:19: got char [noderef] *<noident>
CC arch/x86/kernel/cpu/common.o

$ rpm -qi sparse
Name : sparse Relocations: (not relocatable)
Version : 0.4.1.git1 Vendor: openSUSE
Release : 3.2 Build Date: Sat 24 Oct 2009 11:58:16 AM KST

Thanks.

--
tejun

2010-01-26 03:57:52

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH 7/8] percpu: add __percpu sparse annotations to hw_breakpoint

On Tue, Jan 26, 2010 at 12:10:51PM +0900, Tejun Heo wrote:
> Hello,
>
> On 01/26/2010 11:48 AM, Al Viro wrote:
> > On Tue, Jan 26, 2010 at 11:43:56AM +0900, Tejun Heo wrote:
> >
> >>> Eh... You are leaving that noderef in place in case of array. And _that_
> >>> is not an address space, so casts to AS 0 won't do you any good.
> >>
> >> Any ideas on how to fix it?
> >
> > BTW, before we go any further, which warnings are you getting from sparse
> > and which version of sparse are you using?
> >
> > noderef is one thing; address_space mess is a different story. The version
> > I have here steps into the former, but not the latter; what are you seeing?
>
> Oops, I too am seeing the noderef thing not the address space warning.

OK... So all messing around __kernel __force is actually a red herring.

Frankly, for now I'd keep it as in your patch. Yes, including workarounds
in these few places. Longer term... We probably want to implement
__attribute__((qualify(...)))/__attribute__((unqualify(...))), revert
__typeof__ for AS/noderef to what gcc is doing for normal qualifiers
(i.e. "if p is int const *, typeof(*p) v gives const int") go for explicit
__unqualify((address_space,noderef)) in there. Playing interesting games
with arrays for unqualify (i.e. creating parallel chains of type nodes
all way down to the place where original qualifier had been applied).

2010-01-31 11:42:42

by Paul E. McKenney

[permalink] [raw]
Subject: Re: [PATCH 1/8] percpu: add __percpu sparse annotations to core kernel subsystems

On Tue, Jan 26, 2010 at 12:22:08AM +0900, Tejun Heo wrote:
> Add __percpu sparse annotations to core subsystems.
>
> These annotations are to make sparse consider percpu variables to be
> in a different address space and warn if accessed without going
> through percpu accessors. This patch doesn't affect normal builds.

The RCU pieces look fine to me.

Acked-by: Paul E. McKenney <[email protected]>

> Signed-off-by: Tejun Heo <[email protected]>
> Cc: Jens Axboe <[email protected]>
> Cc: [email protected]
> Cc: Rusty Russell <[email protected]>
> Cc: Dipankar Sarma <[email protected]>
> Cc: "Paul E. McKenney" <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Cc: Andrew Morton <[email protected]>
> Cc: Eric Biederman <[email protected]>
> ---
> include/linux/blktrace_api.h | 4 ++--
> include/linux/genhd.h | 2 +-
> include/linux/kexec.h | 2 +-
> include/linux/mmzone.h | 2 +-
> include/linux/module.h | 2 +-
> include/linux/percpu_counter.h | 2 +-
> include/linux/srcu.h | 2 +-
> kernel/kexec.c | 2 +-
> kernel/sched.c | 4 ++--
> kernel/stop_machine.c | 2 +-
> mm/percpu.c | 18 ++++++++++--------
> 11 files changed, 22 insertions(+), 20 deletions(-)
>
> diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
> index 3b73b99..416bf62 100644
> --- a/include/linux/blktrace_api.h
> +++ b/include/linux/blktrace_api.h
> @@ -150,8 +150,8 @@ struct blk_user_trace_setup {
> struct blk_trace {
> int trace_state;
> struct rchan *rchan;
> - unsigned long *sequence;
> - unsigned char *msg_data;
> + unsigned long __percpu *sequence;
> + unsigned char __percpu *msg_data;
> u16 act_mask;
> u64 start_lba;
> u64 end_lba;
> diff --git a/include/linux/genhd.h b/include/linux/genhd.h
> index 9717081..56b5051 100644
> --- a/include/linux/genhd.h
> +++ b/include/linux/genhd.h
> @@ -101,7 +101,7 @@ struct hd_struct {
> unsigned long stamp;
> int in_flight[2];
> #ifdef CONFIG_SMP
> - struct disk_stats *dkstats;
> + struct disk_stats __percpu *dkstats;
> #else
> struct disk_stats dkstats;
> #endif
> diff --git a/include/linux/kexec.h b/include/linux/kexec.h
> index c356b69..03e8e8d 100644
> --- a/include/linux/kexec.h
> +++ b/include/linux/kexec.h
> @@ -199,7 +199,7 @@ extern struct kimage *kexec_crash_image;
> */
> extern struct resource crashk_res;
> typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
> -extern note_buf_t *crash_notes;
> +extern note_buf_t __percpu *crash_notes;
> extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
> extern size_t vmcoreinfo_size;
> extern size_t vmcoreinfo_max_size;
> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
> index 7874201..41acd4b 100644
> --- a/include/linux/mmzone.h
> +++ b/include/linux/mmzone.h
> @@ -301,7 +301,7 @@ struct zone {
> unsigned long min_unmapped_pages;
> unsigned long min_slab_pages;
> #endif
> - struct per_cpu_pageset *pageset;
> + struct per_cpu_pageset __percpu *pageset;
> /*
> * free areas of different sizes
> */
> diff --git a/include/linux/module.h b/include/linux/module.h
> index 7e74ae0..dd618eb 100644
> --- a/include/linux/module.h
> +++ b/include/linux/module.h
> @@ -365,7 +365,7 @@ struct module
>
> struct module_ref {
> int count;
> - } *refptr;
> + } __percpu *refptr;
> #endif
>
> #ifdef CONFIG_CONSTRUCTORS
> diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h
> index a7684a5..9bd103c 100644
> --- a/include/linux/percpu_counter.h
> +++ b/include/linux/percpu_counter.h
> @@ -21,7 +21,7 @@ struct percpu_counter {
> #ifdef CONFIG_HOTPLUG_CPU
> struct list_head list; /* All percpu_counters are on a list */
> #endif
> - s32 *counters;
> + s32 __percpu *counters;
> };
>
> extern int percpu_counter_batch;
> diff --git a/include/linux/srcu.h b/include/linux/srcu.h
> index 4765d97..41eedcc 100644
> --- a/include/linux/srcu.h
> +++ b/include/linux/srcu.h
> @@ -33,7 +33,7 @@ struct srcu_struct_array {
>
> struct srcu_struct {
> int completed;
> - struct srcu_struct_array *per_cpu_ref;
> + struct srcu_struct_array __percpu *per_cpu_ref;
> struct mutex mutex;
> };
>
> diff --git a/kernel/kexec.c b/kernel/kexec.c
> index a9a93d9..c769613 100644
> --- a/kernel/kexec.c
> +++ b/kernel/kexec.c
> @@ -40,7 +40,7 @@
> #include <asm/sections.h>
>
> /* Per cpu memory for storing cpu states in case of system crash. */
> -note_buf_t* crash_notes;
> +note_buf_t __percpu *crash_notes;
>
> /* vmcoreinfo stuff */
> static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
> diff --git a/kernel/sched.c b/kernel/sched.c
> index 4508fe7..512b10f 100644
> --- a/kernel/sched.c
> +++ b/kernel/sched.c
> @@ -1566,7 +1566,7 @@ static unsigned long cpu_avg_load_per_task(int cpu)
>
> #ifdef CONFIG_FAIR_GROUP_SCHED
>
> -static __read_mostly unsigned long *update_shares_data;
> +static __read_mostly unsigned long __percpu *update_shares_data;
>
> static void __set_se_shares(struct sched_entity *se, unsigned long shares);
>
> @@ -10668,7 +10668,7 @@ struct cgroup_subsys cpu_cgroup_subsys = {
> struct cpuacct {
> struct cgroup_subsys_state css;
> /* cpuusage holds pointer to a u64-type object on every cpu */
> - u64 *cpuusage;
> + u64 __percpu *cpuusage;
> struct percpu_counter cpustat[CPUACCT_STAT_NSTATS];
> struct cpuacct *parent;
> };
> diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
> index 912823e..9bb9fb1 100644
> --- a/kernel/stop_machine.c
> +++ b/kernel/stop_machine.c
> @@ -45,7 +45,7 @@ static int refcount;
> static struct workqueue_struct *stop_machine_wq;
> static struct stop_machine_data active, idle;
> static const struct cpumask *active_cpus;
> -static void *stop_machine_work;
> +static void __percpu *stop_machine_work;
>
> static void set_state(enum stopmachine_state newstate)
> {
> diff --git a/mm/percpu.c b/mm/percpu.c
> index b336638..768419d 100644
> --- a/mm/percpu.c
> +++ b/mm/percpu.c
> @@ -80,13 +80,15 @@
> /* default addr <-> pcpu_ptr mapping, override in asm/percpu.h if necessary */
> #ifndef __addr_to_pcpu_ptr
> #define __addr_to_pcpu_ptr(addr) \
> - (void *)((unsigned long)(addr) - (unsigned long)pcpu_base_addr \
> - + (unsigned long)__per_cpu_start)
> + (void __percpu *)((unsigned long)(addr) - \
> + (unsigned long)pcpu_base_addr + \
> + (unsigned long)__per_cpu_start)
> #endif
> #ifndef __pcpu_ptr_to_addr
> #define __pcpu_ptr_to_addr(ptr) \
> - (void *)((unsigned long)(ptr) + (unsigned long)pcpu_base_addr \
> - - (unsigned long)__per_cpu_start)
> + (void __force *)((unsigned long)(ptr) + \
> + (unsigned long)pcpu_base_addr - \
> + (unsigned long)__per_cpu_start)
> #endif
>
> struct pcpu_chunk {
> @@ -1065,7 +1067,7 @@ static struct pcpu_chunk *alloc_pcpu_chunk(void)
> * RETURNS:
> * Percpu pointer to the allocated area on success, NULL on failure.
> */
> -static void *pcpu_alloc(size_t size, size_t align, bool reserved)
> +static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
> {
> static int warn_limit = 10;
> struct pcpu_chunk *chunk;
> @@ -1194,7 +1196,7 @@ fail_unlock_mutex:
> * RETURNS:
> * Percpu pointer to the allocated area on success, NULL on failure.
> */
> -void *__alloc_percpu(size_t size, size_t align)
> +void __percpu *__alloc_percpu(size_t size, size_t align)
> {
> return pcpu_alloc(size, align, false);
> }
> @@ -1215,7 +1217,7 @@ EXPORT_SYMBOL_GPL(__alloc_percpu);
> * RETURNS:
> * Percpu pointer to the allocated area on success, NULL on failure.
> */
> -void *__alloc_reserved_percpu(size_t size, size_t align)
> +void __percpu *__alloc_reserved_percpu(size_t size, size_t align)
> {
> return pcpu_alloc(size, align, true);
> }
> @@ -1267,7 +1269,7 @@ static void pcpu_reclaim(struct work_struct *work)
> * CONTEXT:
> * Can be called from atomic context.
> */
> -void free_percpu(void *ptr)
> +void free_percpu(void __percpu *ptr)
> {
> void *addr;
> struct pcpu_chunk *chunk;
> --
> 1.6.4.2
>

2010-02-01 03:37:14

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 5/8] percpu: add __percpu sparse annotations to x86

On 01/25/2010 06:17 PM, Tejun Heo wrote:
> On 01/26/2010 10:06 AM, H. Peter Anvin wrote:
>> On 01/25/2010 07:22 AM, Tejun Heo wrote:
>>>
>>> In arch/x86/kernel/cpu/common.c, per_cpu(exception_stacks, cpu) is
>>> replaced with &per_cpu(exception_stacks[0], cpu) which is equivalent
>>> except that it allows per_cpu() macro to correctly drop percpu
>>> designation during sparse pass.
>>>
>>
>> Same comment as Frederic's about this... this kind of uglification
>> really is unacceptable and needs to be addressed.
>
> Hmm... I don't think it's too bad but if you don't like it that much,
> probably the right thing to do is just leave it there and let sparse
> whine about it. There are only three in-kernel instances at this
> point, so it's not that big a deal.
>

That would probably be my preference until it can be fixed in a better
way. If we paper it over now, it will be forgotten -- and then someone
will come along and cargo cult it for no good reason.

-hpa

--
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel. I don't speak on their behalf.

2010-02-02 05:41:36

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCHSET] percpu: add __percpu sparse annotations

On 01/26/2010 12:22 AM, Tejun Heo wrote:
> If nobody objects, I'll push these into percpu tree in three or four
> days.

Patchset pushed out w/ the array workarounds dropped.

Thanks.

--
tejun