[Patch] statistics infrastructure - update 10

From: Martin Peschke
Date: Wed Jul 12 2006 - 08:25:58 EST


lib/statistics.c didn't compile if CONFIG_SMP wasn't defined,
because struct percpu_data was used without precautions.

lib/statistic.c: In function 'statistic_move_ptr':
lib/statistic.c:182: error: dereferencing pointer to incomplete type
lib/statistic.c: In function 'statistic_free':
lib/statistic.c:197: error: dereferencing pointer to incomplete type
lib/statistic.c:198: error: dereferencing pointer to incomplete type
lib/statistic.c: In function 'statistic_alloc':
lib/statistic.c:217: error: invalid application of 'sizeof' to
incomplete
type 'struct percpu_data'
lib/statistic.c:222: error: dereferencing pointer to incomplete type
lib/statistic.c:223: error: dereferencing pointer to incomplete type
lib/statistic.c: In function 'statistic_reset':
lib/statistic.c:297: error: dereferencing pointer to incomplete type
lib/statistic.c: In function 'statistic_merge':
lib/statistic.c:309: error: dereferencing pointer to incomplete type
lib/statistic.c: In function '_statistic_hotcpu':
lib/statistic.c:443: error: dereferencing pointer to incomplete type
lib/statistic.c:444: error: dereferencing pointer to incomplete type
lib/statistic.c:449: error: dereferencing pointer to incomplete type
lib/statistic.c:450: error: dereferencing pointer to incomplete type
lib/statistic.c:451: error: dereferencing pointer to incomplete type
lib/statistic.c: In function 'statistic_add_counter_inc':
lib/statistic.c:854: error: dereferencing pointer to incomplete type
lib/statistic.c: In function 'statistic_add_counter_prod':
lib/statistic.c:862: error: dereferencing pointer to incomplete type
lib/statistic.c: In function 'statistic_add_util':
lib/statistic.c:923: error: dereferencing pointer to incomplete type
lib/statistic.c: In function 'statistic_add_histogram_lin':
lib/statistic.c:1054: error: dereferencing pointer to incomplete type
lib/statistic.c: In function 'statistic_add_histogram_log2':
lib/statistic.c:1061: error: dereferencing pointer to incomplete type
lib/statistic.c: In function 'statistic_add_sparse':
lib/statistic.c:1270: error: dereferencing pointer to incomplete type
make[1]: *** [lib/statistic.o] Error 1
make: *** [lib] Error 2

Signed-off-by: Martin Peschke <mp3@xxxxxxxxxx>
---

include/linux/statistic.h | 2
lib/statistic.c | 146 ++++++++++++++++++++++++++++------------------
2 files changed, 92 insertions(+), 56 deletions(-)

--- a/include/linux/statistic.h 2006-07-12 13:04:47.000000000 +0200
+++ b/include/linux/statistic.h 2006-07-12 13:07:12.000000000 +0200
@@ -83,7 +83,7 @@
/* private: */
enum statistic_state state;
enum statistic_type type;
- struct percpu_data *pdata;
+ void *data;
void (*add)(struct statistic *, s64, u64);
u64 started;
u64 stopped;
--- a/lib/statistic.c 2006-07-12 13:04:48.000000000 +0200
+++ b/lib/statistic.c 2006-07-12 13:07:14.000000000 +0200
@@ -62,6 +62,13 @@
#include <asm/bug.h>
#include <asm/uaccess.h>

+#ifdef CONFIG_SMP
+#define statistic_ptr(stat, cpu) \
+ ((struct percpu_data*)((stat)->data))->ptrs[(cpu)]
+#else
+#define statistic_ptr(stat, cpu) (stat)->data
+#endif
+
struct statistic_file_private {
struct list_head read_seg_lh;
struct list_head write_seg_lh;
@@ -179,56 +186,87 @@
unsigned long flags;
if (src) {
local_irq_save(flags);
- disc->merge(stat, stat->pdata->ptrs[smp_processor_id()], src);
+ disc->merge(stat, statistic_ptr(stat, smp_processor_id()), src);
local_irq_restore(flags);
}
}

-static int statistic_free(struct statistic *stat, struct statistic_info *info)
+static void statistic_free_1(struct statistic *stat)
+{
+ statistic_free_ptr(stat, stat->data);
+ stat->data = NULL;
+}
+
+#ifdef CONFIG_SMP
+static void statistic_free_n(struct statistic *stat)
{
int cpu;
- stat->state = STATISTIC_STATE_RELEASED;
- if (unlikely(info->flags & STATISTIC_FLAGS_NOINCR)) {
- statistic_free_ptr(stat, stat->pdata);
- stat->pdata = NULL;
- return 0;
- }
for_each_possible_cpu(cpu) {
- statistic_free_ptr(stat, stat->pdata->ptrs[cpu]);
- stat->pdata->ptrs[cpu] = NULL;
+ statistic_free_ptr(stat, statistic_ptr(stat, cpu));
+ statistic_ptr(stat, cpu) = NULL;
}
- kfree(stat->pdata);
- stat->pdata = NULL;
+ kfree(stat->data);
+ stat->data = NULL;
+}
+#endif
+
+static int statistic_free(struct statistic *stat, struct statistic_info *info)
+{
+#ifdef CONFIG_SMP
+ if (unlikely(info->flags & STATISTIC_FLAGS_NOINCR))
+ statistic_free_1(stat);
+ else
+ statistic_free_n(stat);
+#else
+ statistic_free_1(stat);
+#endif
+ stat->state = STATISTIC_STATE_RELEASED;
return 0;
}

-static int statistic_alloc(struct statistic *stat,
- struct statistic_info *info)
+static int statistic_alloc_1(struct statistic *stat)
{
- int cpu, node;
+ stat->data = statistic_alloc_ptr(stat, -1);
+ return (likely(stat->data) ? 0 : -ENOMEM);
+}

- stat->age = timestamp_clock();
- if (unlikely(info->flags & STATISTIC_FLAGS_NOINCR)) {
- stat->pdata = statistic_alloc_ptr(stat, -1);
- if (unlikely(!stat->pdata))
- return -ENOMEM;
- stat->state = STATISTIC_STATE_OFF;
- return 0;
- }
- stat->pdata = kzalloc(sizeof(struct percpu_data), GFP_KERNEL);
- if (unlikely(!stat->pdata))
+#ifdef CONFIG_SMP
+static int statistic_alloc_n(struct statistic *stat)
+{
+ int cpu, node;
+ stat->data = kzalloc(sizeof(struct percpu_data), GFP_KERNEL);
+ if (unlikely(!stat->data))
return -ENOMEM;
for_each_online_cpu(cpu) {
node = cpu_to_node(cpu);
- stat->pdata->ptrs[cpu] = statistic_alloc_ptr(stat, node);
- if (unlikely(!stat->pdata->ptrs[cpu])) {
- statistic_free(stat, info);
+ statistic_ptr(stat, cpu) = statistic_alloc_ptr(stat, node);
+ if (unlikely(!statistic_ptr(stat, cpu)))
return -ENOMEM;
- }
}
- stat->state = STATISTIC_STATE_OFF;
return 0;
}
+#endif
+
+static int statistic_alloc(struct statistic *stat,
+ struct statistic_info *info)
+{
+ int retval;
+#ifdef CONFIG_SMP
+ if (unlikely(info->flags & STATISTIC_FLAGS_NOINCR))
+ retval = statistic_alloc_1(stat);
+ else
+ retval = statistic_alloc_n(stat);
+#else
+ retval = statistic_alloc_1(stat);
+#endif
+ if (likely(!retval)) {
+ stat->state = STATISTIC_STATE_OFF;
+ stat->age = timestamp_clock();
+ } else
+ statistic_free(stat, info);
+ return retval;
+
+}

static int statistic_start(struct statistic *stat)
{
@@ -292,10 +330,10 @@
return 0;
statistic_transition(stat, info, STATISTIC_STATE_OFF);
if (unlikely(info->flags & STATISTIC_FLAGS_NOINCR))
- statistic_reset_ptr(stat, stat->pdata);
+ statistic_reset_ptr(stat, stat->data);
else
for_each_possible_cpu(cpu)
- statistic_reset_ptr(stat, stat->pdata->ptrs[cpu]);
+ statistic_reset_ptr(stat, statistic_ptr(stat, cpu));
stat->age = timestamp_clock();
statistic_transition(stat, info, prev_state);
return 0;
@@ -307,7 +345,7 @@
struct statistic *stat = mpriv->stat;
struct statistic_discipline *disc = &statistic_discs[stat->type];
spin_lock(&mpriv->lock);
- disc->merge(stat, mpriv->dst, stat->pdata->ptrs[smp_processor_id()]);
+ disc->merge(stat, mpriv->dst, statistic_ptr(stat, smp_processor_id()));
spin_unlock(&mpriv->lock);
}

@@ -414,7 +452,7 @@
if (unlikely(stat->state < STATISTIC_STATE_OFF))
return 0;
if (unlikely(info->flags & STATISTIC_FLAGS_NOINCR))
- return disc->fdata(stat, info->name, fpriv, stat->pdata);
+ return disc->fdata(stat, info->name, fpriv, stat->data);
mpriv.dst = statistic_alloc_ptr(stat, -1);
if (unlikely(!mpriv.dst))
return -ENOMEM;
@@ -441,15 +479,15 @@
return NOTIFY_OK;
switch (action) {
case CPU_UP_PREPARE:
- stat->pdata->ptrs[cpu] = statistic_alloc_ptr(stat, node);
- if (!stat->pdata->ptrs[cpu])
+ statistic_ptr(stat, cpu) = statistic_alloc_ptr(stat, node);
+ if (!statistic_ptr(stat, cpu))
return NOTIFY_BAD;
break;
case CPU_UP_CANCELED:
case CPU_DEAD:
- statistic_move_ptr(stat, stat->pdata->ptrs[cpu]);
- statistic_free_ptr(stat, stat->pdata->ptrs[cpu]);
- stat->pdata->ptrs[cpu] = NULL;
+ statistic_move_ptr(stat, statistic_ptr(stat, cpu));
+ statistic_free_ptr(stat, statistic_ptr(stat, cpu));
+ statistic_ptr(stat, cpu) = NULL;
break;
}
return NOTIFY_OK;
@@ -852,7 +890,7 @@

void statistic_add_counter_inc(struct statistic *stat, s64 value, u64 incr)
{
- *(u64*)stat->pdata->ptrs[smp_processor_id()] += incr;
+ *(u64*)statistic_ptr(stat, smp_processor_id()) += incr;
}
EXPORT_SYMBOL_GPL(statistic_add_counter_inc);

@@ -860,14 +898,14 @@
{
if (unlikely(value < 0))
value = -value;
- *(u64*)stat->pdata->ptrs[smp_processor_id()] += value * incr;
+ *(u64*)statistic_ptr(stat, smp_processor_id()) += value * incr;
}
EXPORT_SYMBOL_GPL(statistic_add_counter_prod);

static void statistic_set_counter_inc(struct statistic *stat,
s64 value, u64 total)
{
- *(u64*)stat->pdata = total;
+ *(u64*)stat->data = total;
}

static void statistic_set_counter_prod(struct statistic *stat,
@@ -875,7 +913,7 @@
{
if (unlikely(value < 0))
value = -value;
- *(u64*)stat->pdata = value * total;
+ *(u64*)stat->data = value * total;
}

static void statistic_merge_counter(struct statistic *stat,
@@ -920,8 +958,8 @@

void statistic_add_util(struct statistic *stat, s64 value, u64 incr)
{
- int cpu = smp_processor_id();
- struct statistic_entry_util *util = stat->pdata->ptrs[cpu];
+ struct statistic_entry_util *util;
+ util = statistic_ptr(stat, smp_processor_id());
util->num += incr;
util->acc += value * incr;
util->sqr += value * value * incr;
@@ -934,8 +972,7 @@

static void statistic_set_util(struct statistic *stat, s64 value, u64 total)
{
- struct statistic_entry_util *util;
- util = (struct statistic_entry_util *) stat->pdata;
+ struct statistic_entry_util *util = stat->data;
util->num = total;
util->acc = value * total;
util->sqr = value * value * total;
@@ -1052,14 +1089,14 @@
void statistic_add_histogram_lin(struct statistic *stat, s64 value, u64 incr)
{
int i = statistic_histogram_calc_index_lin(stat, value);
- ((u64*)stat->pdata->ptrs[smp_processor_id()])[i] += incr;
+ ((u64*)statistic_ptr(stat, smp_processor_id()))[i] += incr;
}
EXPORT_SYMBOL_GPL(statistic_add_histogram_lin);

void statistic_add_histogram_log2(struct statistic *stat, s64 value, u64 incr)
{
int i = statistic_histogram_calc_index_log2(stat, value);
- ((u64*)stat->pdata->ptrs[smp_processor_id()])[i] += incr;
+ ((u64*)statistic_ptr(stat, smp_processor_id()))[i] += incr;
}
EXPORT_SYMBOL_GPL(statistic_add_histogram_log2);

@@ -1067,14 +1104,14 @@
s64 value, u64 total)
{
int i = statistic_histogram_calc_index_lin(stat, value);
- ((u64*)stat->pdata)[i] = total;
+ ((u64*)stat->data)[i] = total;
}

static void statistic_set_histogram_log2(struct statistic *stat,
s64 value, u64 total)
{
int i = statistic_histogram_calc_index_log2(stat, value);
- ((u64*)stat->pdata)[i] = total;
+ ((u64*)stat->data)[i] = total;
}

static void statistic_merge_histogram(struct statistic *stat,
@@ -1267,16 +1304,15 @@

void statistic_add_sparse(struct statistic *stat, s64 value, u64 incr)
{
- int cpu = smp_processor_id();
- struct statistic_sparse_list *slist = stat->pdata->ptrs[cpu];
+ struct statistic_sparse_list *slist;
+ slist = statistic_ptr(stat, smp_processor_id());
_statistic_add_sparse(slist, value, incr);
}
EXPORT_SYMBOL_GPL(statistic_add_sparse);

static void statistic_set_sparse(struct statistic *stat, s64 value, u64 total)
{
- struct statistic_sparse_list *slist = (struct statistic_sparse_list *)
- stat->pdata;
+ struct statistic_sparse_list *slist = stat->data;
struct list_head *head = &slist->entry_lh;
struct statistic_entry_sparse *entry;




-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/