Whamcloud - gitweb
LU-1282 misc: Use present cpu numbers to save memory.
[fs/lustre-release.git] / lustre / include / lprocfs_status.h
index 97336f8..3844583 100644 (file)
@@ -165,8 +165,8 @@ struct lprocfs_counter {
 };
 
 struct lprocfs_percpu {
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
-        __s64                  pad;
+#ifndef __GNUC__
+       __s64                   pad;
 #endif
         struct lprocfs_counter lp_cntr[0];
 };
@@ -191,11 +191,15 @@ enum lprocfs_fields_flags {
 };
 
 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)
@@ -368,48 +372,62 @@ struct obd_job_stats {
 
 #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:
@@ -435,18 +453,22 @@ static inline __u64 lprocfs_stats_collector(struct lprocfs_stats *stats,
                                             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 *