Fixed plug/unplug logic in btt
[blktrace.git] / btt / devs.c
index b7943d3ec9c34539121b0ba77c5e891977c33708..3578633149c4a55c180c0e35c5d895a7e067b132 100644 (file)
@@ -73,26 +73,33 @@ struct d_info *__dip_find(__u32 device)
        return NULL;
 }
 
+void __dip_exit(struct d_info *dip)
+{
+       list_del(&dip->all_head);
+       __destroy_heads(dip->heads);
+       region_exit(&dip->regions);
+       seeki_free(dip->seek_handle);
+       seeki_free(dip->q2q_handle);
+       aqd_free(dip->aqd_handle);
+       plat_free(dip->q2d_plat_handle);
+       plat_free(dip->q2c_plat_handle);
+       plat_free(dip->d2c_plat_handle);
+       bno_dump_free(dip->bno_dump_handle);
+       unplug_hist_free(dip->up_hist_handle);
+       if (output_all_data)
+               q2d_free(dip->q2d_priv);
+       if (dip->pit_fp)
+               fclose(dip->pit_fp);
+       free(dip);
+}
+
 void dip_exit(void)
 {
-       struct d_info *dip;
        struct list_head *p, *q;
 
        list_for_each_safe(p, q, &all_devs) {
-               dip = list_entry(p, struct d_info, all_head);
-
-               __destroy_heads(dip->heads);
-               region_exit(&dip->regions);
-               seeki_exit(dip->seek_handle);
-               seeki_exit(dip->q2q_handle);
-               aqd_exit(dip->aqd_handle);
-               plat_exit(dip->q2c_plat_handle);
-               plat_exit(dip->d2c_plat_handle);
-               bno_dump_exit(dip->bno_dump_handle);
-               unplug_hist_exit(dip->unplug_hist_handle);
-               if (output_all_data)
-                       q2d_release(dip->q2d_priv);
-               free(dip);
+               struct d_info *dip = list_entry(p, struct d_info, all_head);
+               __dip_exit(dip);
        }
 }
 
@@ -105,7 +112,17 @@ static inline char *mkhandle(char *str, __u32 device, char *post)
        return str;
 }
 
-struct d_info *dip_add(__u32 device, struct io *iop)
+static inline FILE *open_pit(char *str)
+{
+       FILE *fp = my_fopen(str, "w");
+
+       if (fp == NULL)
+               perror(str);
+
+       return fp;
+}
+
+struct d_info *dip_alloc(__u32 device, struct io *iop)
 {
        struct d_info *dip = __dip_find(device);
 
@@ -118,24 +135,29 @@ struct d_info *dip_add(__u32 device, struct io *iop)
                region_init(&dip->regions);
                dip->device = device;
                dip->last_q = (__u64)-1;
-               dip->map = dev_map_find(device);
-               dip->bno_dump_handle = bno_dump_init(device);
-               dip->unplug_hist_handle = unplug_hist_init(device);
-               dip->seek_handle = seeki_init(mkhandle(str, device, "_d2d"));
-               dip->q2q_handle = seeki_init(mkhandle(str, device, "_q2q"));
-               dip->aqd_handle = aqd_init(mkhandle(str, device, "_aqd"));
+               dip->devmap = dev_map_find(device);
+               dip->bno_dump_handle = bno_dump_alloc(device);
+               dip->up_hist_handle = unplug_hist_alloc(device);
+               dip->seek_handle = seeki_alloc(mkhandle(str, device, "_d2d"));
+               dip->q2q_handle = seeki_alloc(mkhandle(str, device, "_q2q"));
+               dip->aqd_handle = aqd_alloc(mkhandle(str, device, "_aqd"));
+               dip->q2d_plat_handle =
+                               plat_alloc(mkhandle(str, device, "_q2d_plat"));
                dip->q2c_plat_handle =
-                               plat_init(mkhandle(str, device, "_q2c_plat"));
+                               plat_alloc(mkhandle(str, device, "_q2c_plat"));
                dip->d2c_plat_handle =
-                               plat_init(mkhandle(str, device, "_d2c_plat"));
-               latency_init(dip);
+                               plat_alloc(mkhandle(str, device, "_d2c_plat"));
+               latency_alloc(dip);
                list_add_tail(&dip->hash_head, &dev_heads[DEV_HASH(device)]);
                list_add_tail(&dip->all_head, &all_devs);
                dip->start_time = BIT_TIME(iop->t.time);
                dip->pre_culling = 1;
                if (output_all_data)
-                       dip->q2d_priv = q2d_init();
+                       dip->q2d_priv = q2d_alloc();
                n_devs++;
+               if (per_io_trees)
+                       dip->pit_fp = open_pit(mkhandle(per_io_trees,
+                                                         device, "_pit.dat"));
        }
 
        if (dip->pre_culling) {
@@ -151,7 +173,7 @@ struct d_info *dip_add(__u32 device, struct io *iop)
        return dip;
 }
 
-void dip_rem(struct io *iop)
+void iop_rem_dip(struct io *iop)
 {
        if (iop->linked) {
                dip_rb_rem(iop);
@@ -173,8 +195,7 @@ void dip_foreach(struct io *iop, enum iop_type type,
                        list_del(&this->f_head);
                        io_release(this);
                }
-       }
-       else
+       } else
                dip_rb_fe(iop->dip, type, iop, fnc, NULL);
 }
 
@@ -194,8 +215,7 @@ void dip_foreach_out(void (*func)(struct d_info *, void *), void *arg)
                struct list_head *p;
                __list_for_each(p, &all_devs)
                        func(list_entry(p, struct d_info, all_head), arg);
-       }
-       else {
+       } else {
                int i;
                struct d_info *dip;
                unsigned int mjr, mnr;
@@ -214,10 +234,16 @@ void dip_plug(__u32 dev, double cur_time)
 {
        struct d_info *dip = __dip_find(dev);
 
-       if (!dip || dip->is_plugged) return;
+       if (dip && !dip->is_plugged) {
+               dip->is_plugged = 1;
+               dip->last_plug = cur_time;
+       }
+}
 
-       dip->is_plugged = 1;
-       dip->last_plug = cur_time;
+static inline void unplug(struct d_info *dip, double cur_time)
+{
+       dip->is_plugged = 0;
+       dip->plugged_time += (cur_time - dip->last_plug);
 }
 
 void dip_unplug(__u32 dev, double cur_time, __u64 nios_up)
@@ -226,19 +252,30 @@ void dip_unplug(__u32 dev, double cur_time, __u64 nios_up)
 
        if (dip && dip->is_plugged) {
                dip->nplugs++;
-               dip->plugged_time += (cur_time - dip->last_plug);
-               dip->is_plugged = 0;
                dip->nios_up += nios_up;
+               unplug(dip, cur_time);
        }
 }
 
-void dip_unplug_tm(__u32 dev, __u64 nios_up)
+void dip_unplug_tm(__u32 dev, double cur_time, __u64 nios_up)
 {
        struct d_info *dip = __dip_find(dev);
 
        if (dip && dip->is_plugged) {
-               dip->n_timer_unplugs++;
                dip->nios_upt += nios_up;
                dip->nplugs_t++;
+               unplug(dip, cur_time);
+       }
+}
+
+void dip_cleanup(void)
+{
+       struct list_head *p, *q;
+
+       list_for_each_safe(p, q, &all_devs) {
+               struct d_info *dip = list_entry(p, struct d_info, all_head);
+
+               if (dip->n_qs == 0 && dip->n_ds == 0)
+                       __dip_exit(dip);
        }
 }