# define printf(format, b...) CDEBUG(D_OTHER, format , ## b)
# define time(a) CURRENT_TIME
-#ifndef num_possible_cpus
-#define cfs_num_possible_cpus() NR_CPUS
-#else
-#define cfs_num_possible_cpus() num_possible_cpus()
-#endif
+# define cfs_num_possible_cpus() num_possible_cpus()
+# define cfs_num_present_cpus() num_present_cpus()
/******************************************************************************/
/* Light-weight trace
* Just present a single processor until will add thread support.
*/
#ifndef smp_processor_id
-#define cfs_smp_processor_id() 0
+# define cfs_smp_processor_id() 0
#else
-#define cfs_smp_processor_id() smp_processor_id()
+# define cfs_smp_processor_id() smp_processor_id()
#endif
#ifndef num_online_cpus
-#define cfs_num_online_cpus() 1
+# define cfs_num_online_cpus() 1
#else
-#define cfs_num_online_cpus() num_online_cpus()
+# define cfs_num_online_cpus() num_online_cpus()
#endif
#ifndef num_possible_cpus
-#define cfs_num_possible_cpus() 1
+# define cfs_num_possible_cpus() 1
#else
-#define cfs_num_possible_cpus() num_possible_cpus()
+# define cfs_num_possible_cpus() num_possible_cpus()
+#endif
+#ifndef num_present_cpus
+# define cfs_num_present_cpus() 1
+#else
+# define cfs_num_present_cpus() num_present_cpus()
#endif
-
/*
* Wait Queue.
*/
#define CFS_NR_CPUS (32)
#define smp_num_cpus ((CCHAR)KeNumberProcessors)
#define cfs_num_possible_cpus() smp_num_cpus
+#define cfs_num_present_cpus() smp_num_cpus
#define cfs_num_online_cpus() smp_num_cpus
#define cfs_smp_processor_id() ((USHORT)KeGetCurrentProcessorNumber())
#define smp_call_function(f, a, n, w) do {} while(0)
memset(cfs_trace_data, 0, sizeof(cfs_trace_data));
for (i = 0; i < CFS_TCD_TYPE_MAX; i++) {
cfs_trace_data[i] =
- kmalloc(sizeof(union cfs_trace_data_union) * NR_CPUS,
- GFP_KERNEL);
+ kmalloc(sizeof(union cfs_trace_data_union) *
+ cfs_num_possible_cpus(), GFP_KERNEL);
if (cfs_trace_data[i] == NULL)
goto out;
tcd->tcd_cpu = j;
}
- for (i = 0; i < num_possible_cpus(); i++)
+ for (i = 0; i < cfs_num_possible_cpus(); i++)
for (j = 0; j < 3; j++) {
- cfs_trace_console_buffers[i][j] =
- kmalloc(CFS_TRACE_CONSOLE_BUFFER_SIZE,
- GFP_KERNEL);
+ cfs_trace_console_buffers[i][j] =
+ kmalloc(CFS_TRACE_CONSOLE_BUFFER_SIZE,
+ GFP_KERNEL);
if (cfs_trace_console_buffers[i][j] == NULL)
goto out;
cfs_tracefile_fini_arch();
printk(KERN_ERR "lnet: Not enough memory\n");
return -ENOMEM;
-
}
void cfs_tracefile_fini_arch()
int i;
int j;
- for (i = 0; i < num_possible_cpus(); i++)
+ for (i = 0; i < cfs_num_possible_cpus(); i++)
for (j = 0; j < 3; j++)
if (cfs_trace_console_buffers[i][j] != NULL) {
kfree(cfs_trace_console_buffers[i][j]);
};
struct lprocfs_percpu {
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
- __s64 pad;
+#ifndef __GNUC__
+ __s64 pad;
#endif
struct lprocfs_counter lp_cntr[0];
};
};
struct lprocfs_stats {
- unsigned int ls_num; /* # of counters */
- int ls_flags; /* See LPROCFS_STATS_FLAG_* */
- cfs_spinlock_t ls_lock; /* Lock used only when there are
- * no percpu stats areas */
- struct lprocfs_percpu *ls_percpu[0];
+ unsigned short ls_num; /* # of counters */
+ unsigned short ls_biggest_alloc_num;
+ /* 1 + the highest slot index which has
+ * been allocated, the 0th entry is
+ * a statically intialized template */
+ int ls_flags; /* See LPROCFS_STATS_FLAG_* */
+ cfs_spinlock_t ls_lock; /* Lock used only when there are
+ * no percpu stats areas */
+ struct lprocfs_percpu *ls_percpu[0];
};
#define OPC_RANGE(seg) (seg ## _LAST_OPC - seg ## _FIRST_OPC)
#ifdef LPROCFS
-static inline int lprocfs_stats_lock(struct lprocfs_stats *stats, int opc)
+extern int lprocfs_stats_alloc_one(struct lprocfs_stats *stats,
+ unsigned int cpuid);
+/*
+ * \return value
+ * < 0 : on error (only possible for opc as LPROCFS_GET_SMP_ID)
+ */
+static inline int lprocfs_stats_lock(struct lprocfs_stats *stats, int opc,
+ unsigned long *flags)
{
- switch (opc) {
- default:
- LBUG();
-
- case LPROCFS_GET_SMP_ID:
- if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) {
- cfs_spin_lock(&stats->ls_lock);
- return 0;
- } else {
- return cfs_get_cpu();
- }
-
- case LPROCFS_GET_NUM_CPU:
- if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) {
- cfs_spin_lock(&stats->ls_lock);
- return 1;
- } else {
- return cfs_num_possible_cpus();
- }
- }
+ int rc = 0;
+
+ switch (opc) {
+ default:
+ LBUG();
+
+ case LPROCFS_GET_SMP_ID:
+ if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) {
+ cfs_spin_lock_irqsave(&stats->ls_lock, *flags);
+ return 0;
+ } else {
+ unsigned int cpuid = cfs_get_cpu();
+
+ if (unlikely(stats->ls_percpu[cpuid + 1] == NULL))
+ rc = lprocfs_stats_alloc_one(stats, cpuid + 1);
+ return rc < 0 ? rc : cpuid + 1;
+ }
+
+ case LPROCFS_GET_NUM_CPU:
+ if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) {
+ cfs_spin_lock_irqsave(&stats->ls_lock, *flags);
+ return 1;
+ } else {
+ return stats->ls_biggest_alloc_num;
+ }
+ }
}
-static inline void lprocfs_stats_unlock(struct lprocfs_stats *stats, int opc)
+static inline void lprocfs_stats_unlock(struct lprocfs_stats *stats, int opc,
+ unsigned long *flags)
{
- switch (opc) {
- default:
- LBUG();
-
- case LPROCFS_GET_SMP_ID:
- if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
- cfs_spin_unlock(&stats->ls_lock);
- else
- cfs_put_cpu();
- return;
-
- case LPROCFS_GET_NUM_CPU:
- if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
- cfs_spin_unlock(&stats->ls_lock);
- return;
- }
+ switch (opc) {
+ default:
+ LBUG();
+
+ case LPROCFS_GET_SMP_ID:
+ if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
+ cfs_spin_unlock_irqrestore(&stats->ls_lock, *flags);
+ else
+ cfs_put_cpu();
+ return;
+
+ case LPROCFS_GET_NUM_CPU:
+ if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
+ cfs_spin_unlock_irqrestore(&stats->ls_lock, *flags);
+ return;
+ }
}
/* Two optimized LPROCFS counter increment functions are provided:
int idx,
enum lprocfs_fields_flags field)
{
- __u64 ret = 0;
- int i;
- unsigned int num_cpu;
-
- LASSERT(stats != NULL);
-
- num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
- for (i = 0; i < num_cpu; i++)
- ret += lprocfs_read_helper(&(stats->ls_percpu[i]->lp_cntr[idx]),
- field);
- lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
- return ret;
+ int i;
+ unsigned int num_cpu;
+ unsigned long flags = 0;
+ __u64 ret = 0;
+
+ LASSERT(stats != NULL);
+
+ num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
+ for (i = 0; i < num_cpu; i++) {
+ if (stats->ls_percpu[i] == NULL)
+ continue;
+ ret += lprocfs_read_helper(&(stats->ls_percpu[i]->lp_cntr[idx]),
+ field);
+ }
+ lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
+ return ret;
}
extern struct lprocfs_stats *
void lprocfs_counter_add(struct lprocfs_stats *stats, int idx,
long amount)
{
- struct lprocfs_counter *percpu_cntr;
- int smp_id;
+ struct lprocfs_counter *percpu_cntr;
+ int smp_id;
+ unsigned long flags = 0;
if (stats == NULL)
return;
- /* With per-client stats, statistics are allocated only for
- * single CPU area, so the smp_id should be 0 always. */
- smp_id = lprocfs_stats_lock(stats, LPROCFS_GET_SMP_ID);
+ /* With per-client stats, statistics are allocated only for
+ * single CPU area, so the smp_id should be 0 always. */
+ smp_id = lprocfs_stats_lock(stats, LPROCFS_GET_SMP_ID, &flags);
+ if (smp_id < 0)
+ return;
percpu_cntr = &(stats->ls_percpu[smp_id]->lp_cntr[idx]);
if (!(stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU))
}
if (!(stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU))
cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
- lprocfs_stats_unlock(stats, LPROCFS_GET_SMP_ID);
+ lprocfs_stats_unlock(stats, LPROCFS_GET_SMP_ID, &flags);
}
EXPORT_SYMBOL(lprocfs_counter_add);
-void lprocfs_counter_sub(struct lprocfs_stats *stats, int idx,
- long amount)
+void lprocfs_counter_sub(struct lprocfs_stats *stats, int idx, long amount)
{
- struct lprocfs_counter *percpu_cntr;
- int smp_id;
+ struct lprocfs_counter *percpu_cntr;
+ int smp_id;
+ unsigned long flags = 0;
if (stats == NULL)
return;
- /* With per-client stats, statistics are allocated only for
- * single CPU area, so the smp_id should be 0 always. */
- smp_id = lprocfs_stats_lock(stats, LPROCFS_GET_SMP_ID);
+ /* With per-client stats, statistics are allocated only for
+ * single CPU area, so the smp_id should be 0 always. */
+ smp_id = lprocfs_stats_lock(stats, LPROCFS_GET_SMP_ID, &flags);
+ if (smp_id < 0)
+ return;
percpu_cntr = &(stats->ls_percpu[smp_id]->lp_cntr[idx]);
if (!(stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU))
}
if (!(stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU))
cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
- lprocfs_stats_unlock(stats, LPROCFS_GET_SMP_ID);
+ lprocfs_stats_unlock(stats, LPROCFS_GET_SMP_ID, &flags);
}
EXPORT_SYMBOL(lprocfs_counter_sub);
+
+int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int idx)
+{
+ unsigned int percpusize;
+ int rc = -ENOMEM;
+
+ /* the 1st percpu entry was statically allocated in
+ * lprocfs_alloc_stats() */
+ LASSERT(idx != 0 && stats->ls_percpu[0] != NULL);
+ LASSERT(stats->ls_percpu[idx] == NULL);
+ LASSERT((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0);
+
+ percpusize = CFS_L1_CACHE_ALIGN(offsetof(struct lprocfs_percpu,
+ lp_cntr[stats->ls_num]));
+ OBD_ALLOC_GFP(stats->ls_percpu[idx], percpusize, CFS_ALLOC_ATOMIC);
+ if (stats->ls_percpu[idx] != NULL) {
+ rc = 0;
+ if (unlikely(stats->ls_biggest_alloc_num <= idx))
+ stats->ls_biggest_alloc_num = idx + 1;
+
+ /* initialize the ls_percpu[idx] by copying the 0th template
+ * entry */
+ memcpy(stats->ls_percpu[idx], stats->ls_percpu[0],
+ percpusize);
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL(lprocfs_stats_alloc_one);
#endif /* LPROCFS */
EXPORT_SYMBOL(obd_alloc_fail_rate);
void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
struct lprocfs_counter *cnt)
{
- unsigned int num_cpu;
- struct lprocfs_counter t;
- struct lprocfs_counter *percpu_cntr;
- int centry, i;
+ unsigned int num_entry;
+ struct lprocfs_counter t;
+ struct lprocfs_counter *percpu_cntr;
+ int centry;
+ int i;
+ unsigned long flags = 0;
memset(cnt, 0, sizeof(*cnt));
cnt->lc_min = LC_MIN_INIT;
- num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
+ num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
- for (i = 0; i < num_cpu; i++) {
- percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
+ for (i = 0; i < num_entry; i++) {
+ if (stats->ls_percpu[i] == NULL)
+ continue;
+ percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
do {
centry = cfs_atomic_read(&percpu_cntr-> \
cnt->lc_sumsquare += t.lc_sumsquare;
}
- cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
- lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
+ cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
+ lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
}
/**
struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
enum lprocfs_stats_flags flags)
{
- struct lprocfs_stats *stats;
- unsigned int percpusize;
- unsigned int i, j;
- unsigned int num_cpu;
+ struct lprocfs_stats *stats;
+ unsigned int percpusize;
+ unsigned int num_entry;
if (num == 0)
return NULL;
if (lprocfs_no_percpu_stats != 0)
flags |= LPROCFS_STATS_FLAG_NOPERCPU;
- if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
- num_cpu = 1;
- else
- num_cpu = cfs_num_possible_cpus();
+ if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
+ num_entry = 1;
+ else
+ num_entry = cfs_num_possible_cpus() + 1;
- OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
- if (stats == NULL)
- return NULL;
+ /* alloc percpu pointers for all possible cpu slots */
+ OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
+ if (stats == NULL)
+ return NULL;
+ stats->ls_num = num;
+ stats->ls_biggest_alloc_num = 1;
if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
stats->ls_flags = flags;
cfs_spin_lock_init(&stats->ls_lock);
stats->ls_flags = 0;
}
- percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
- if (num_cpu > 1)
- percpusize = CFS_L1_CACHE_ALIGN(percpusize);
+ percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
+ if (num_entry > 1)
+ percpusize = CFS_L1_CACHE_ALIGN(percpusize);
- for (i = 0; i < num_cpu; i++) {
- OBD_ALLOC(stats->ls_percpu[i], percpusize);
- if (stats->ls_percpu[i] == NULL) {
- for (j = 0; j < i; j++) {
- OBD_FREE(stats->ls_percpu[j], percpusize);
- stats->ls_percpu[j] = NULL;
- }
- break;
- }
- }
- if (stats->ls_percpu[0] == NULL) {
- OBD_FREE(stats, offsetof(typeof(*stats),
- ls_percpu[num_cpu]));
- return NULL;
- }
-
- stats->ls_num = num;
- return stats;
+ /* for no percpu area, the 0th entry is for real use,
+ * for percpu area, the 0th entry is for intialized entry template */
+ OBD_ALLOC(stats->ls_percpu[0], percpusize);
+ if (stats->ls_percpu[0] == NULL) {
+ OBD_FREE(stats,
+ offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
+ stats = NULL;
+ }
+ return stats;
}
void lprocfs_free_stats(struct lprocfs_stats **statsh)
{
- struct lprocfs_stats *stats = *statsh;
- unsigned int num_cpu;
- unsigned int percpusize;
- unsigned int i;
+ struct lprocfs_stats *stats = *statsh;
+ unsigned int num_entry;
+ unsigned int percpusize;
+ unsigned int i;
if (stats == NULL || stats->ls_num == 0)
return;
*statsh = NULL;
- if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
- num_cpu = 1;
- else
- num_cpu = cfs_num_possible_cpus();
+ if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
+ num_entry = 1;
+ else
+ num_entry = cfs_num_possible_cpus() + 1;
- percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
- if (num_cpu > 1)
- percpusize = CFS_L1_CACHE_ALIGN(percpusize);
- for (i = 0; i < num_cpu; i++)
- OBD_FREE(stats->ls_percpu[i], percpusize);
- OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
+ percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
+ if (num_entry > 1)
+ percpusize = CFS_L1_CACHE_ALIGN(percpusize);
+ for (i = 0; i < num_entry; i++)
+ if (stats->ls_percpu[i] != NULL)
+ OBD_FREE(stats->ls_percpu[i], percpusize);
+ OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
}
void lprocfs_clear_stats(struct lprocfs_stats *stats)
{
- struct lprocfs_counter *percpu_cntr;
- int i,j;
- unsigned int num_cpu;
+ struct lprocfs_counter *percpu_cntr;
+ int i;
+ int j;
+ unsigned int num_entry;
+ unsigned long flags = 0;
- num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
+ num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
- for (i = 0; i < num_cpu; i++) {
+ for (i = 0; i < num_entry; i++) {
+ if (stats->ls_percpu[i] == NULL)
+ continue;
for (j = 0; j < stats->ls_num; j++) {
percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
}
}
- lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
+ lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
}
static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
}
void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
- unsigned conf, const char *name, const char *units)
-{
- struct lprocfs_counter *c;
- int i;
- unsigned int num_cpu;
-
- LASSERT(stats != NULL);
-
- num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
-
- for (i = 0; i < num_cpu; i++) {
- c = &(stats->ls_percpu[i]->lp_cntr[index]);
- c->lc_config = conf;
- c->lc_count = 0;
- c->lc_sum = 0;
- c->lc_min = LC_MIN_INIT;
- c->lc_max = 0;
- c->lc_name = name;
- c->lc_units = units;
- }
-
- lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
+ unsigned conf, const char *name, const char *units)
+{
+ struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
+ unsigned long flags = 0;
+
+ LASSERT(stats != NULL);
+ LASSERT(stats->ls_percpu[0] != NULL);
+
+ lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
+ c->lc_config = conf;
+ c->lc_count = 0;
+ c->lc_sum = 0;
+ c->lc_min = LC_MIN_INIT;
+ c->lc_max = 0;
+ c->lc_name = name;
+ c->lc_units = units;
+ lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
}
EXPORT_SYMBOL(lprocfs_counter_init);
if (oss_num_threads < OSS_THREADS_MIN)
oss_num_threads = OSS_THREADS_MIN;
oss_max_threads = oss_min_threads = oss_num_threads;
- } else {
- /* Base min threads on memory and cpus */
- oss_min_threads =
- cfs_num_possible_cpus() * CFS_NUM_CACHEPAGES >>
- (27 - CFS_PAGE_SHIFT);
- if (oss_min_threads < OSS_THREADS_MIN)
- oss_min_threads = OSS_THREADS_MIN;
- /* Insure a 4x range for dynamic threads */
- if (oss_min_threads > OSS_THREADS_MAX / 4)
- oss_min_threads = OSS_THREADS_MAX / 4;
- oss_max_threads = min(OSS_THREADS_MAX, oss_min_threads * 4 + 1);
- }
+ } else {
+ /* Base min threads on memory and cpus */
+ oss_min_threads =
+ cfs_num_online_cpus() * CFS_NUM_CACHEPAGES >>
+ (27 - CFS_PAGE_SHIFT);
+ if (oss_min_threads < OSS_THREADS_MIN)
+ oss_min_threads = OSS_THREADS_MIN;
+ /* Insure a 4x range for dynamic threads */
+ if (oss_min_threads > OSS_THREADS_MAX / 4)
+ oss_min_threads = OSS_THREADS_MAX / 4;
+ oss_max_threads = min(OSS_THREADS_MAX, oss_min_threads * 4 + 1);
+ }
ost->ost_service =
ptlrpc_init_svc(OST_NBUFS, OST_BUFSIZE, OST_MAXREQSIZE,