Whamcloud - gitweb
LU-2071 lprocfs: Memory leak on lustre proc access
[fs/lustre-release.git] / lustre / include / lprocfs_status.h
index 97336f8..dc32c08 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];
 };
@@ -175,9 +175,10 @@ struct lprocfs_percpu {
 #define LPROCFS_GET_SMP_ID  0x0002
 
 enum lprocfs_stats_flags {
-        LPROCFS_STATS_FLAG_NONE     = 0x0000, /* per cpu counter */
-        LPROCFS_STATS_FLAG_NOPERCPU = 0x0001, /* stats have no percpu
-                                               * area and need locking */
+       LPROCFS_STATS_FLAG_NONE     = 0x0000, /* per cpu counter */
+       LPROCFS_STATS_FLAG_NOPERCPU = 0x0001, /* stats have no percpu
+                                              * area and need locking */
+       LPROCFS_STATS_FLAG_IRQ_SAFE = 0x0002, /* alloc need irq safe */
 };
 
 enum lprocfs_fields_flags {
@@ -191,11 +192,16 @@ 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_* */
+       /* Lock used when there are no percpu stats areas; For percpu stats,
+        * it is used to protect ls_biggest_alloc_num change */
+       cfs_spinlock_t         ls_lock;
+       struct lprocfs_percpu *ls_percpu[0];
 };
 
 #define OPC_RANGE(seg) (seg ## _LAST_OPC - seg ## _FIRST_OPC)
@@ -360,56 +366,92 @@ struct obd_job_stats {
        cfs_hash_t        *ojs_hash;
        cfs_list_t         ojs_list;
        cfs_rwlock_t       ojs_lock; /* protect the obj_list */
-       int                ojs_cntr_num;
        cntr_init_callback ojs_cntr_init_fn;
-       cfs_timer_t        ojs_cleanup_timer;
+       int                ojs_cntr_num;
        int                ojs_cleanup_interval;
+       time_t             ojs_last_cleanup;
 };
 
 #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;
+       unsigned int    cpuid;
+
+       switch (opc) {
+       default:
+               LBUG();
+
+       case LPROCFS_GET_SMP_ID:
+               /* percpu counter stats */
+               if ((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0) {
+                       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;
+               }
+
+               /* non-percpu counter stats */
+               if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
+                       cfs_spin_lock_irqsave(&stats->ls_lock, *flags);
+               else
+                       cfs_spin_lock(&stats->ls_lock);
+               return 0;
+
+       case LPROCFS_GET_NUM_CPU:
+               /* percpu counter stats */
+               if ((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0)
+                       return stats->ls_biggest_alloc_num;
+
+               /* non-percpu counter stats */
+               if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
+                       cfs_spin_lock_irqsave(&stats->ls_lock, *flags);
+               else
+                       cfs_spin_lock(&stats->ls_lock);
+               return 1;
+       }
 }
 
-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) {
+                       if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) {
+                               cfs_spin_unlock_irqrestore(&stats->ls_lock,
+                                                          *flags);
+                       } else {
+                               cfs_spin_unlock(&stats->ls_lock);
+                       }
+               } else {
+                       cfs_put_cpu();
+               }
+               return;
+
+       case LPROCFS_GET_NUM_CPU:
+               if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) {
+                       if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) {
+                               cfs_spin_unlock_irqrestore(&stats->ls_lock,
+                                                          *flags);
+                       } else {
+                               cfs_spin_unlock(&stats->ls_lock);
+                       }
+               }
+               return;
+       }
 }
 
 /* Two optimized LPROCFS counter increment functions are provided:
@@ -435,18 +477,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 *
@@ -506,6 +552,8 @@ extern cfs_proc_dir_entry_t *lprocfs_register(const char *name,
 extern void lprocfs_remove(cfs_proc_dir_entry_t **root);
 extern void lprocfs_remove_proc_entry(const char *name,
                                       struct proc_dir_entry *parent);
+extern void lprocfs_try_remove_proc_entry(const char *name,
+                                         struct proc_dir_entry *parent);
 
 extern cfs_proc_dir_entry_t *lprocfs_srch(cfs_proc_dir_entry_t *root,
                                           const char *name);
@@ -586,6 +634,19 @@ extern int lprocfs_rd_filesfree(char *page, char **start, off_t off,
                                 int count, int *eof, void *data);
 extern int lprocfs_rd_filegroups(char *page, char **start, off_t off,
                                  int count, int *eof, void *data);
+extern int lprocfs_osd_rd_blksize(char *page, char **start, off_t off,
+                               int count, int *eof, void *data);
+extern int lprocfs_osd_rd_kbytesfree(char *page, char **start, off_t off,
+                               int count, int *eof, void *data);
+extern int lprocfs_osd_rd_kbytesavail(char *page, char **start, off_t off,
+                               int count, int *eof, void *data);
+extern int lprocfs_osd_rd_filestotal(char *page, char **start, off_t off,
+                               int count, int *eof, void *data);
+extern int lprocfs_osd_rd_filesfree(char *page, char **start, off_t off,
+                               int count, int *eof, void *data);
+extern int lprocfs_osd_rd_kbytestotal(char *page, char **start, off_t off,
+                               int count, int *eof, void *data);
+
 
 extern int lprocfs_write_helper(const char *buffer, unsigned long count,
                                 int *val);
@@ -620,6 +681,7 @@ int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
                              unsigned long count, void *data);
 
+extern int lprocfs_single_release(cfs_inode_t *, struct file *);
 extern int lprocfs_seq_release(cfs_inode_t *, struct file *);
 
 /* You must use these macros when you want to refer to
@@ -641,7 +703,7 @@ extern int lprocfs_seq_release(cfs_inode_t *, struct file *);
   a read-write proc entry, and then call LPROC_SEQ_SEQ instead. Finally,
   call lprocfs_obd_seq_create(obd, filename, 0444, &name#_fops, data); */
 #define __LPROC_SEQ_FOPS(name, custom_seq_write)                           \
-static int name##_seq_open(cfs_inode_t *inode, struct file *file) {        \
+static int name##_single_open(cfs_inode_t *inode, struct file *file) {     \
         struct proc_dir_entry *dp = PDE(inode);                            \
         int rc;                                                            \
         LPROCFS_ENTRY_AND_CHECK(dp);                                       \
@@ -654,11 +716,11 @@ static int name##_seq_open(cfs_inode_t *inode, struct file *file) {        \
 }                                                                          \
 struct file_operations name##_fops = {                                     \
         .owner   = THIS_MODULE,                                            \
-        .open    = name##_seq_open,                                        \
+        .open    = name##_single_open,                                     \
         .read    = seq_read,                                               \
         .write   = custom_seq_write,                                       \
         .llseek  = seq_lseek,                                              \
-        .release = lprocfs_seq_release,                                    \
+        .release = lprocfs_single_release,                                 \
 }
 
 #define LPROC_SEQ_FOPS_RO(name)         __LPROC_SEQ_FOPS(name, NULL)
@@ -764,7 +826,7 @@ extern int lprocfs_quota_wr_qs_factor(struct file *file,
 #else
 /* LPROCFS is not defined */
 
-
+#define proc_lustre_root NULL
 
 static inline void lprocfs_counter_add(struct lprocfs_stats *stats,
                                        int index, long amount)
@@ -859,6 +921,9 @@ static inline void lprocfs_remove(cfs_proc_dir_entry_t **root)
 static inline void lprocfs_remove_proc_entry(const char *name,
                                              struct proc_dir_entry *parent)
 { return; }
+static inline void lprocfs_try_remove_proc_entry(const char *name,
+                                                struct proc_dir_entry *parent)
+{ return; }
 static inline cfs_proc_dir_entry_t *lprocfs_srch(cfs_proc_dir_entry_t *head,
                                                  const char *name)
 { return 0; }