blktrace 1.1.0
[blktrace.git] / btt / inlines.h
index 4b7f10e30090309483889a87f8ad402e01d44262..64b5a2c2244f50dc293c15350c9677112cb0e7b4 100644 (file)
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
-static inline void dbg_ping(void) { }
 
-static inline void *zmalloc(size_t len)
+static inline int remapper_dev(__u32 dev)
 {
-       return memset(malloc(len), 0, len);
+       int mjr = MAJOR(dev);
+       return mjr == 9 || mjr == 253 || mjr == 254;
 }
 
-static inline int is_dev(struct io *iop, unsigned int mjr, unsigned int mnr)
+static inline void region_init(struct region_info *reg)
 {
-       return MAJOR(iop->t.device) == mjr && MINOR(iop->t.device) == mnr;
+       INIT_LIST_HEAD(&reg->qranges);
+       INIT_LIST_HEAD(&reg->cranges);
 }
 
-static inline int in_bit(struct io *in, struct io *out)
+static inline void __region_exit(struct list_head *range_head)
 {
-       return (BIT_START(out) <= BIT_START(in)) &&
-              (BIT_END(in) <= BIT_END(out));
+       struct list_head *p, *q;
+       struct range_info *rip;
+
+       list_for_each_safe(p, q, range_head) {
+               rip = list_entry(p, struct range_info, head);
+               free(rip);
+       }
 }
 
-static inline int is_bit(struct io *i1, struct io *i2)
+static inline void region_exit(struct region_info *reg)
 {
-       return (BIT_START(i1) == BIT_START(i2)) && (BIT_END(i1) == BIT_END(i2));
+       __region_exit(&reg->qranges);
+       __region_exit(&reg->cranges);
 }
 
-static inline struct range_info *new_cur(__u64 time)
+static inline void update_range(struct list_head *head_p, __u64 time)
 {
-       struct range_info *cur = zmalloc(sizeof(*cur));
+       struct range_info *rip;
 
-       INIT_LIST_HEAD(&cur->head);
-       cur->start = time;
-       return cur;
-}
+       if (!list_empty(head_p)) {
+               rip = list_entry(head_p->prev, struct range_info, head);
 
-static inline  void update_range(struct list_head *head_p,
-                                struct range_info **cur_p, __u64 time)
-{
-       if (*cur_p == NULL)
-               *cur_p = new_cur(time);
-       else {
-               __u64 my_delta = time - (*cur_p)->end;
-               if (BIT_TIME(my_delta) >= range_delta) {
-                       list_add_tail(&(*cur_p)->head, head_p);
-                       *cur_p = new_cur(time);
+               if (time < rip->end)
+                       return;
+
+               if (BIT_TIME(time - rip->end) < range_delta) {
+                       rip->end = time;
+                       return;
                }
        }
 
-       (*cur_p)->end = time;
-}
-
-static inline void init_region(struct region_info *reg)
-{
-       INIT_LIST_HEAD(&reg->qranges);
-       INIT_LIST_HEAD(&reg->cranges);
-       reg->qr_cur = reg->cr_cur = NULL;
+       rip = malloc(sizeof(*rip));
+       rip->start = rip->end = time;
+       list_add_tail(&rip->head, head_p);
 }
 
 static inline void update_qregion(struct region_info *reg, __u64 time)
 {
-       update_range(&reg->qranges, &reg->qr_cur, time);
+       update_range(&reg->qranges, time);
 }
 
 static inline void update_cregion(struct region_info *reg, __u64 time)
 {
-       update_range(&reg->cranges, &reg->cr_cur, time);
+       update_range(&reg->cranges, time);
 }
 
 static inline void avg_update(struct avg_info *ap, __u64 t)
@@ -96,135 +92,160 @@ static inline void avg_update(struct avg_info *ap, __u64 t)
         }
 }
 
-static inline void update_lq(__u64 *last_q, struct avg_info *avg, __u64 time)
+static inline void avg_update_n(struct avg_info *ap, __u64 t, int n)
 {
-       if (*last_q != ((__u64)-1))
-               avg_update(avg, time - *last_q);
-       *last_q = time;
+        if (ap->n == 0) {
+                ap->min = ap->max = t;
+               ap->total = (n * t);
+       } else {
+                if (t < ap->min)
+                        ap->min = t;
+                else if (t > ap->max)
+                        ap->max = t;
+                ap->total += (n * t);
+        }
+
+       ap->n += n;
 }
 
-static inline struct list_head *dip_get_head(struct d_info *dip,
-                                             enum iop_type type)
+static inline void avg_unupdate(struct avg_info *ap, __u64 t)
 {
-       return &dip->iop_heads[type];
+       ap->n--;
+       ap->total -= t;
 }
 
-static inline struct list_head *dip_get_head_dev(__u32 dev, enum iop_type type)
+static inline void update_lq(__u64 *last_q, struct avg_info *avg, __u64 time)
 {
-       return dip_get_head(__dip_find(dev), type);
+       if (*last_q != ((__u64)-1))
+               avg_update(avg, (time > *last_q) ? time - *last_q : 1);
+       *last_q = time;
 }
 
 static inline void dip_update_q(struct d_info *dip, struct io *iop)
 {
-       update_lq(&dip->last_q, &dip->avgs.q2q, iop->t.time);
+       if (remapper_dev(dip->device))
+               update_lq(&dip->last_q, &dip->avgs.q2q_dm, iop->t.time);
+       else
+               update_lq(&dip->last_q, &dip->avgs.q2q, iop->t.time);
        update_qregion(&dip->regions, iop->t.time);
 }
 
-static inline void dip_rem(struct io *iop)
+static inline struct io *io_alloc(void)
 {
-       LIST_DEL(&iop->dev_head);
-}
+       struct io *iop = malloc(sizeof(*iop));
 
-static inline void *my_malloc(struct my_mem **head_p, size_t len)
-{
-       struct my_mem *this = *head_p;
+       memset(iop, 0, sizeof(struct io));
+       list_add_tail(&iop->a_head, &all_ios);
 
-       if (this)
-               *head_p = this->next;
-       else
-               this = malloc(len);
-
-       return this;
+       return iop;
 }
 
-static inline void *my_zmalloc(struct my_mem **head_p, size_t len)
+static inline void io_free(struct io *iop)
 {
-       return memset(my_malloc(head_p, len), 0, len);
+       list_del(&iop->a_head);
+       free(iop);
 }
 
-static inline void my_free(struct my_mem **head_p, void *p)
+static inline void io_free_all(void)
 {
-       struct my_mem *this = p;
+       struct io *iop;
+       struct list_head *p, *q;
 
-       this->next = *head_p;
-       *head_p = this;
+       list_for_each_safe(p, q, &all_ios) {
+               iop = list_entry(p, struct io, a_head);
+               free(iop);
+       }
 }
 
-static inline void io_setup(struct io *iop, enum iop_type type)
+static inline int io_setup(struct io *iop, enum iop_type type)
 {
        iop->type = type;
-       iop->dip = dip_add(iop->t.device, iop);
-       iop->pip = find_process(iop->t.pid, NULL);
+       iop->dip = dip_alloc(iop->t.device, iop);
+       if (iop->linked) {
+               iop->pip = find_process(iop->t.pid, NULL);
+               iop->bytes_left = iop->t.bytes;
+       }
 
-       n_io_allocs++;
-       list_add_tail(&iop->all_head, &all_ios);
+       return iop->linked;
 }
 
-static inline void io_free(struct io *iop)
+static inline void io_release(struct io *iop)
 {
-       ASSERT(iop->users == 0);
+       if (iop->linked)
+               iop_rem_dip(iop);
+       if (iop->pdu)
+               free(iop->pdu);
 
-       LIST_DEL(&iop->all_head);
-       dip_rem(iop);
-       IO_FREE(iop);
-       n_io_frees++;
+       io_free(iop);
 }
 
-static inline void io_get(struct io *iop)
-{
-       iop->users++;
-}
+#define UPDATE_AVGS(_avg, _iop, _pip, _time) do {                      \
+               avg_update(&all_avgs. _avg , _time);                    \
+               avg_update(&_iop->dip->avgs. _avg , _time);             \
+               if (_pip) avg_update(&_pip->avgs. _avg , _time);        \
+       } while (0)
 
+#define UPDATE_AVGS_N(_avg, _iop, _pip, _time, _n) do {                        \
+               avg_update_n(&all_avgs. _avg , _time, _n);              \
+               avg_update_n(&_iop->dip->avgs. _avg , _time, _n);       \
+               if (_pip) avg_update_n(&_pip->avgs. _avg , _time,_n);   \
+       } while (0)
 
-static inline int __io_put(struct io *iop)
+#define UNUPDATE_AVGS(_avg, _iop, _pip, _time) do {                    \
+               avg_unupdate(&all_avgs. _avg , _time);                  \
+               avg_unupdate(&_iop->dip->avgs. _avg , _time);           \
+               if (_pip) avg_unupdate(&_pip->avgs. _avg , _time);      \
+       } while (0)
+
+static inline void update_q2c(struct io *iop, __u64 c_time)
 {
-       return --iop->users;
+       if (remapper_dev(iop->dip->device))
+               UPDATE_AVGS(q2c_dm, iop, iop->pip, c_time);
+       else
+               UPDATE_AVGS(q2c, iop, iop->pip, c_time);
 }
 
-static inline void io_put(struct io *iop)
+static inline void update_q2a(struct io *iop, __u64 a_time)
 {
-       if (__io_put(iop) == 0) {
-               io_free_resources(iop);
-               io_free(iop);
-       }
+       if (remapper_dev(iop->dip->device))
+               UPDATE_AVGS(q2a_dm, iop, iop->pip, a_time);
+       else
+               UPDATE_AVGS(q2a, iop, iop->pip, a_time);
 }
 
-static inline void io_link(struct io **p_dst, struct io *iop)
+static inline void update_q2g(struct io *iop, __u64 g_time)
 {
-       ASSERT(iop != NULL);
-       io_get(iop);
-       *p_dst = iop;
+       UPDATE_AVGS(q2g, iop, iop->pip, g_time);
 }
 
-static inline void io_unlink(struct io **p_dst)
+static inline void update_s2g(struct io *iop, __u64 g_time)
 {
-       ASSERT(*p_dst != NULL);
-       io_put(*p_dst);
+       UPDATE_AVGS(s2g, iop, iop->pip, g_time);
+}
 
-#if defined(DEBUG)
-       *p_dst = NULL;
-#endif
+static inline void unupdate_q2g(struct io *iop, __u64 g_time)
+{
+       UNUPDATE_AVGS(q2g, iop, iop->pip, g_time);
 }
 
-#define UPDATE_AVGS(_avg, _iop, _pip, _time) do {                      \
-               avg_update(&all_avgs. _avg , _time);                    \
-               avg_update(&_iop->dip->avgs. _avg , _time);             \
-               if (_pip) avg_update(&_pip->avgs. _avg , _time);        \
-       } while (0)
+static inline void update_g2i(struct io *iop, __u64 i_time)
+{
+       UPDATE_AVGS(g2i, iop, iop->pip, i_time);
+}
 
-static inline void update_q2c(struct io *iop, __u64 c_time)
+static inline void unupdate_g2i(struct io *iop, __u64 i_time)
 {
-       UPDATE_AVGS(q2c, iop, iop->pip, c_time);
+       UNUPDATE_AVGS(g2i, iop, iop->pip, i_time);
 }
 
-static inline void update_q2a(struct io *iop, __u64 a_time)
+static inline void update_q2m(struct io *iop, __u64 m_time)
 {
-       UPDATE_AVGS(q2a, iop, iop->pip, a_time);
+       UPDATE_AVGS(q2m, iop, iop->pip, m_time);
 }
 
-static inline void update_q2i(struct io *iop, __u64 i_time)
+static inline void unupdate_q2m(struct io *iop, __u64 m_time)
 {
-       UPDATE_AVGS(q2i, iop, iop->pip, i_time);
+       UNUPDATE_AVGS(q2m, iop, iop->pip, m_time);
 }
 
 static inline void update_i2d(struct io *iop, __u64 d_time)
@@ -232,6 +253,21 @@ static inline void update_i2d(struct io *iop, __u64 d_time)
        UPDATE_AVGS(i2d, iop, iop->pip, d_time);
 }
 
+static inline void unupdate_i2d(struct io *iop, __u64 d_time)
+{
+       UNUPDATE_AVGS(i2d, iop, iop->pip, d_time);
+}
+
+static inline void update_m2d(struct io *iop, __u64 d_time)
+{
+       UPDATE_AVGS(m2d, iop, iop->pip, d_time);
+}
+
+static inline void unupdate_m2d(struct io *iop, __u64 d_time)
+{
+       UNUPDATE_AVGS(m2d, iop, iop->pip, d_time);
+}
+
 static inline void update_d2c(struct io *iop, __u64 c_time)
 {
        UPDATE_AVGS(d2c, iop, iop->pip, c_time);
@@ -245,3 +281,103 @@ static inline void update_blks(struct io *iop)
        if (iop->pip)
                avg_update(&iop->pip->avgs.blks, nblks);
 }
+
+static inline struct rb_root *__get_root(struct d_info *dip, enum iop_type type)
+{
+       struct rb_root *roots = dip->heads;
+       return &roots[type];
+}
+
+static inline int dip_rb_ins(struct d_info *dip, struct io *iop)
+{
+       return rb_insert(__get_root(dip, iop->type), iop);
+}
+
+static inline void dip_rb_rem(struct io *iop)
+{
+       rb_erase(&iop->rb_node, __get_root(iop->dip, iop->type));
+}
+
+static inline void dip_rb_fe(struct d_info *dip, enum iop_type type,
+                            struct io *iop,
+                            void (*fnc)(struct io *iop, struct io *this),
+                            struct list_head *head)
+{
+       rb_foreach(__get_root(dip, type)->rb_node, iop, fnc, head);
+}
+
+static inline struct io *dip_rb_find_sec(struct d_info *dip,
+                                        enum iop_type type, __u64 sec)
+{
+       return rb_find_sec(__get_root(dip, type), sec);
+}
+
+static inline __u64 tdelta(__u64 from, __u64 to)
+{
+       return (from < to) ? (to - from) : 1;
+}
+
+static inline int type2c(enum iop_type type)
+{
+       int c;
+
+       switch (type) {
+       case IOP_Q: c = 'Q'; break;
+       case IOP_X: c = 'X'; break;
+       case IOP_A: c = 'A'; break;
+       case IOP_I: c = 'I'; break;
+       case IOP_M: c = 'M'; break;
+       case IOP_D: c = 'D'; break;
+       case IOP_C: c = 'C'; break;
+       case IOP_R: c = 'R'; break;
+       case IOP_G: c = 'G'; break;
+       default   : c = '?'; break;
+       }
+
+       return c;
+}
+
+static inline int histo_idx(__u64 nbytes)
+{
+       int idx = (nbytes >> 9) - 1;
+       return min(idx, N_HIST_BKTS-1);
+}
+
+static inline void update_q_histo(__u64 nbytes)
+{
+       q_histo[histo_idx(nbytes)]++;
+}
+
+static inline void update_d_histo(__u64 nbytes)
+{
+       d_histo[histo_idx(nbytes)]++;
+}
+
+static inline struct io *io_first_list(struct list_head *head)
+{
+       if (list_empty(head))
+               return NULL;
+
+       return list_entry(head->next, struct io, f_head);
+}
+
+static inline void __dump_iop(FILE *ofp, struct io *iop, int extra_nl)
+{
+       fprintf(ofp, "%5d.%09lu %3d,%-3d %c %10llu+%-4u\n",
+               (int)SECONDS(iop->t.time),
+               (unsigned long)NANO_SECONDS(iop->t.time),
+               MAJOR(iop->t.device), MINOR(iop->t.device), type2c(iop->type),
+               (unsigned long long)iop->t.sector, t_sec(&iop->t));
+       if (extra_nl) fprintf(ofp, "\n");
+}
+
+static inline void __dump_iop2(FILE *ofp, struct io *a_iop, struct io *l_iop)
+{
+       fprintf(ofp, "%5d.%09lu %3d,%-3d %c %10llu+%-4u <- (%3d,%-3d) %10llu\n",
+               (int)SECONDS(a_iop->t.time),
+               (unsigned long)NANO_SECONDS(a_iop->t.time),
+               MAJOR(a_iop->t.device), MINOR(a_iop->t.device),
+               type2c(a_iop->type), (unsigned long long)a_iop->t.sector,
+               t_sec(&a_iop->t), MAJOR(l_iop->t.device),
+               MINOR(l_iop->t.device), (unsigned long long)l_iop->t.sector);
+}