Whamcloud - gitweb
LU-1187 lmv: Locate right MDT in lmv.
[fs/lustre-release.git] / lustre / obdclass / lprocfs_jobstats.c
index 0072feb..aa8ba78 100644 (file)
@@ -19,7 +19,7 @@
  * GPL HEADER END
  */
 /*
- * Copyright (c) 2011 Whamcloud, Inc.
+ * Copyright (c) 2011, 2012, Intel Corporation.
  * Use is subject to license terms.
  *
  * Author: Niu Yawei <niu@whamcloud.com>
@@ -116,9 +116,9 @@ static void job_free(struct job_stat *job)
        LASSERT(atomic_read(&job->js_refcount) == 0);
        LASSERT(job->js_jobstats);
 
-       cfs_write_lock(&job->js_jobstats->ojs_lock);
+       write_lock(&job->js_jobstats->ojs_lock);
        cfs_list_del_init(&job->js_list);
-       cfs_write_unlock(&job->js_jobstats->ojs_lock);
+       write_unlock(&job->js_jobstats->ojs_lock);
 
        lprocfs_free_stats(&job->js_stats);
        OBD_FREE_PTR(job);
@@ -153,6 +153,37 @@ static cfs_hash_ops_t job_stats_hash_ops = {
        .hs_exit       = job_stat_exit,
 };
 
+static int job_iter_callback(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+                            cfs_hlist_node_t *hnode, void *data)
+{
+       time_t oldest = *((time_t *)data);
+       struct job_stat *job;
+
+       job = cfs_hlist_entry(hnode, struct job_stat, js_hash);
+       if (!oldest || job->js_timestamp < oldest)
+               cfs_hash_bd_del_locked(hs, bd, hnode);
+
+       return 0;
+}
+
+static void lprocfs_job_cleanup(struct obd_job_stats *stats, bool force)
+{
+       time_t oldest, now;
+
+       if (stats->ojs_cleanup_interval == 0)
+               return;
+
+       now = cfs_time_current_sec();
+       if (!force && now < stats->ojs_last_cleanup +
+                           stats->ojs_cleanup_interval)
+               return;
+
+       oldest = now - stats->ojs_cleanup_interval;
+       cfs_hash_for_each_safe(stats->ojs_hash, job_iter_callback,
+                              &oldest);
+       stats->ojs_last_cleanup = cfs_time_current_sec();
+}
+
 static struct job_stat *job_alloc(char *jobid, struct obd_job_stats *jobs)
 {
        struct job_stat *job;
@@ -190,6 +221,8 @@ int lprocfs_job_stats_log(struct obd_device *obd, char *jobid,
 
        LASSERT(stats && stats->ojs_hash);
 
+       lprocfs_job_cleanup(stats, false);
+
        if (!jobid || !strlen(jobid))
                RETURN(-EINVAL);
 
@@ -212,12 +245,16 @@ int lprocfs_job_stats_log(struct obd_device *obd, char *jobid,
        if (job2 != job) {
                job_putref(job);
                job = job2;
-               LASSERT(!cfs_list_empty(&job->js_list));
+               /* We cannot LASSERT(!cfs_list_empty(&job->js_list)) here,
+                * since we just lost the race for inserting "job" into the
+                * ojs_list, and some other thread is doing it _right_now_.
+                * Instead, be content the other thread is doing this, since
+                * "job2" was initialized in job_alloc() already. LU-2163 */
        } else {
                LASSERT(cfs_list_empty(&job->js_list));
-               cfs_write_lock(&stats->ojs_lock);
+               write_lock(&stats->ojs_lock);
                cfs_list_add_tail(&job->js_list, &stats->ojs_list);
-               cfs_write_unlock(&stats->ojs_lock);
+               write_unlock(&stats->ojs_lock);
        }
 
 found:
@@ -231,19 +268,6 @@ found:
 }
 EXPORT_SYMBOL(lprocfs_job_stats_log);
 
-static int job_iter_callback(cfs_hash_t *hs, cfs_hash_bd_t *bd,
-                            cfs_hlist_node_t *hnode, void *data)
-{
-       time_t oldest = *((time_t *)data);
-       struct job_stat *job;
-
-       job = cfs_hlist_entry(hnode, struct job_stat, js_hash);
-       if (!oldest || job->js_timestamp < oldest)
-               cfs_hash_bd_del_locked(hs, bd, hnode);
-
-       return 0;
-}
-
 void lprocfs_job_stats_fini(struct obd_device *obd)
 {
        struct obd_job_stats *stats = &obd->u.obt.obt_jobstats;
@@ -251,7 +275,6 @@ void lprocfs_job_stats_fini(struct obd_device *obd)
 
        if (stats->ojs_hash == NULL)
                return;
-       cfs_timer_disarm(&stats->ojs_cleanup_timer);
        cfs_hash_for_each_safe(stats->ojs_hash, job_iter_callback, &oldest);
        cfs_hash_putref(stats->ojs_hash);
        stats->ojs_hash = NULL;
@@ -265,7 +288,7 @@ static void *lprocfs_jobstats_seq_start(struct seq_file *p, loff_t *pos)
        loff_t off = *pos;
        struct job_stat *job;
 
-       cfs_read_lock(&stats->ojs_lock);
+       read_lock(&stats->ojs_lock);
        if (off == 0)
                return SEQ_START_TOKEN;
        off--;
@@ -280,7 +303,7 @@ static void lprocfs_jobstats_seq_stop(struct seq_file *p, void *v)
 {
        struct obd_job_stats *stats = p->private;
 
-       cfs_read_unlock(&stats->ojs_lock);
+       read_unlock(&stats->ojs_lock);
 }
 
 static void *lprocfs_jobstats_seq_next(struct seq_file *p, void *v, loff_t *pos)
@@ -463,20 +486,6 @@ struct file_operations lprocfs_jobstats_seq_fops = {
        .release = lprocfs_seq_release,
 };
 
-static void job_cleanup_callback(unsigned long data)
-{
-       struct obd_job_stats *stats = (struct obd_job_stats *)data;
-       time_t oldest;
-
-       if (stats->ojs_cleanup_interval) {
-               oldest = cfs_time_current_sec() - stats->ojs_cleanup_interval;
-               cfs_hash_for_each_safe(stats->ojs_hash, job_iter_callback,
-                                      &oldest);
-               cfs_timer_arm(&stats->ojs_cleanup_timer,
-                             cfs_time_shift(stats->ojs_cleanup_interval));
-       }
-}
-
 int lprocfs_job_stats_init(struct obd_device *obd, int cntr_num,
                           cntr_init_callback init_fn)
 {
@@ -507,13 +516,11 @@ int lprocfs_job_stats_init(struct obd_device *obd, int cntr_num,
                RETURN(-ENOMEM);
 
        CFS_INIT_LIST_HEAD(&stats->ojs_list);
-       cfs_rwlock_init(&stats->ojs_lock);
+       rwlock_init(&stats->ojs_lock);
        stats->ojs_cntr_num = cntr_num;
        stats->ojs_cntr_init_fn = init_fn;
-       cfs_timer_init(&stats->ojs_cleanup_timer, job_cleanup_callback, stats);
        stats->ojs_cleanup_interval = 600; /* 10 mins by default */
-       cfs_timer_arm(&stats->ojs_cleanup_timer,
-                     cfs_time_shift(stats->ojs_cleanup_interval));
+       stats->ojs_last_cleanup = cfs_time_current_sec();
 
        LPROCFS_WRITE_ENTRY();
        entry = create_proc_entry("job_stats", 0644, obd->obd_proc_entry);
@@ -557,11 +564,7 @@ int lprocfs_wr_job_interval(struct file *file, const char *buffer,
                return rc;
 
        stats->ojs_cleanup_interval = val;
-       if (!stats->ojs_cleanup_interval)
-               cfs_timer_disarm(&stats->ojs_cleanup_timer);
-       else
-               cfs_timer_arm(&stats->ojs_cleanup_timer,
-                             cfs_time_shift(stats->ojs_cleanup_interval));
+       lprocfs_job_cleanup(stats, true);
 
        return count;