*
*/
-static inline struct range_info *new_cur(__u64 time)
+static inline int remapper_dev(__u32 dev)
{
- struct range_info *cur = malloc(sizeof(struct range_info));
+ int mjr = MAJOR(dev);
+ return mjr == 9 || mjr == 253 || mjr == 254;
+}
- INIT_LIST_HEAD(&cur->head);
- cur->start = time;
- return cur;
+static inline void region_init(struct region_info *reg)
+{
+ INIT_LIST_HEAD(®->qranges);
+ INIT_LIST_HEAD(®->cranges);
}
-static inline void update_range(struct list_head *head_p,
- struct range_info **cur_p, __u64 time)
+static inline void __region_exit(struct list_head *range_head)
{
- if (*cur_p == NULL)
- *cur_p = new_cur(time);
- else {
- __u64 my_delta = (time > (*cur_p)->end) ? time - (*cur_p)->end : 1;
- if (BIT_TIME(my_delta) >= range_delta) {
- list_add_tail(&(*cur_p)->head, head_p);
- *cur_p = new_cur(time);
- }
+ 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);
}
+}
- (*cur_p)->end = time;
+static inline void region_exit(struct region_info *reg)
+{
+ __region_exit(®->qranges);
+ __region_exit(®->cranges);
}
-static inline void init_region(struct region_info *reg)
+static inline void update_range(struct list_head *head_p, __u64 time)
{
- INIT_LIST_HEAD(®->qranges);
- INIT_LIST_HEAD(®->cranges);
- reg->qr_cur = reg->cr_cur = NULL;
+ struct range_info *rip;
+
+ if (!list_empty(head_p)) {
+ rip = list_entry(head_p->prev, struct range_info, head);
+
+ if (time < rip->end)
+ return;
+
+ if (BIT_TIME(time - rip->end) < range_delta) {
+ rip->end = time;
+ return;
+ }
+ }
+
+ 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(®->qranges, ®->qr_cur, time);
+ update_range(®->qranges, time);
}
static inline void update_cregion(struct region_info *reg, __u64 time)
{
- update_range(®->cranges, ®->cr_cur, time);
+ update_range(®->cranges, time);
}
static inline void avg_update(struct avg_info *ap, __u64 t)
}
}
+static inline void avg_update_n(struct avg_info *ap, __u64 t, int n)
+{
+ 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 void avg_unupdate(struct avg_info *ap, __u64 t)
{
ap->n--;
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 struct io *io_alloc(void)
{
- struct io *iop;
-
- if (!list_empty(&free_ios)) {
- iop = list_entry(free_ios.next, struct io, f_head);
- LIST_DEL(&iop->f_head);
- }
- else
- iop = malloc(sizeof(struct io));
+ struct io *iop = malloc(sizeof(*iop));
memset(iop, 0, sizeof(struct io));
+ list_add_tail(&iop->a_head, &all_ios);
return iop;
}
static inline void io_free(struct io *iop)
{
-# if defined(DEBUG)
- memset(iop, 0, sizeof(*iop));
-# endif
- list_add_tail(&iop->f_head, &free_ios);
+ list_del(&iop->a_head);
+ free(iop);
+}
+
+static inline void io_free_all(void)
+{
+ struct io *iop;
+ struct list_head *p, *q;
+
+ list_for_each_safe(p, q, &all_ios) {
+ iop = list_entry(p, struct io, a_head);
+ free(iop);
+ }
}
static inline int io_setup(struct io *iop, enum iop_type type)
{
iop->type = type;
- iop->dip = dip_add(iop->t.device, iop);
+ iop->dip = dip_alloc(iop->t.device, iop);
if (iop->linked) {
iop->pip = find_process(iop->t.pid, NULL);
- INIT_LIST_HEAD(&iop->down_list);
- INIT_LIST_HEAD(&iop->up_list);
iop->bytes_left = iop->t.bytes;
}
static inline void io_release(struct io *iop)
{
if (iop->linked)
- dip_rem(iop);
- if (iop->pdu)
+ iop_rem_dip(iop);
+ if (iop->pdu)
free(iop->pdu);
+
io_free(iop);
}
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)
+
#define UNUPDATE_AVGS(_avg, _iop, _pip, _time) do { \
avg_unupdate(&all_avgs. _avg , _time); \
avg_unupdate(&_iop->dip->avgs. _avg , _time); \
static inline void update_q2c(struct io *iop, __u64 c_time)
{
- UPDATE_AVGS(q2c, iop, iop->pip, c_time);
+ 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 update_q2a(struct io *iop, __u64 a_time)
{
- UPDATE_AVGS(q2a, iop, iop->pip, a_time);
+ 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 update_q2g(struct io *iop, __u64 g_time)
+{
+ UPDATE_AVGS(q2g, iop, iop->pip, g_time);
+}
+
+static inline void update_s2g(struct io *iop, __u64 g_time)
+{
+ UPDATE_AVGS(s2g, iop, iop->pip, g_time);
+}
+
+static inline void unupdate_q2g(struct io *iop, __u64 g_time)
+{
+ UNUPDATE_AVGS(q2g, iop, iop->pip, g_time);
+}
+
+static inline void update_g2i(struct io *iop, __u64 i_time)
+{
+ UPDATE_AVGS(g2i, iop, iop->pip, i_time);
+}
+
+static inline void unupdate_g2i(struct io *iop, __u64 i_time)
+{
+ UNUPDATE_AVGS(g2i, iop, iop->pip, i_time);
}
-static inline void update_q2i(struct io *iop, __u64 i_time)
+static inline void update_q2m(struct io *iop, __u64 m_time)
{
- UPDATE_AVGS(q2i, iop, iop->pip, i_time);
+ UPDATE_AVGS(q2m, iop, iop->pip, m_time);
+}
+
+static inline void unupdate_q2m(struct io *iop, __u64 m_time)
+{
+ UNUPDATE_AVGS(q2m, iop, iop->pip, m_time);
}
static inline void update_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);
{
__u64 nblks = iop->t.bytes >> 9;
avg_update(&all_avgs.blks, nblks);
- ASSERT(iop->dip != NULL);
avg_update(&iop->dip->avgs.blks, nblks);
if (iop->pip)
avg_update(&iop->pip->avgs.blks, nblks);
return &roots[type];
}
-static inline void *dip_rb_mkhds(void)
-{
- size_t len = N_IOP_TYPES * sizeof(struct rb_root);
- return memset(malloc(len), 0, len);
-}
-
static inline int dip_rb_ins(struct d_info *dip, struct io *iop)
{
return rb_insert(__get_root(dip, iop->type), 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),
+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,
+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 struct io *list_first_down(struct io *iop)
+static inline __u64 tdelta(__u64 from, __u64 to)
{
- struct list_head *p = list_first(&iop->down_list);
- return p ? list_entry(p, struct io, up_head) : NULL;
+ return (from < to) ? (to - from) : 1;
}
-static inline struct io *list_first_up(struct io *iop)
+static inline int type2c(enum iop_type type)
{
- struct list_head *p = list_first(&iop->up_list);
- return p ? list_entry(p, struct io, down_head) : NULL;
+ 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 list_empty_up(struct io *iop)
+static inline int histo_idx(__u64 nbytes)
{
- return list_empty(&iop->up_list);
+ int idx = (nbytes >> 9) - 1;
+ return min(idx, N_HIST_BKTS-1);
}
-static inline void __link(struct io *down_iop, struct io *up_iop)
+static inline void update_q_histo(__u64 nbytes)
{
- list_add_tail(&down_iop->up_head, &up_iop->down_list);
- list_add_tail(&up_iop->down_head, &down_iop->up_list);
+ q_histo[histo_idx(nbytes)]++;
}
-static inline void __unlink(struct io *down_iop, struct io *up_iop)
+static inline void update_d_histo(__u64 nbytes)
{
- LIST_DEL(&down_iop->up_head);
- LIST_DEL(&up_iop->down_head);
+ d_histo[histo_idx(nbytes)]++;
}
-static inline void add_retry(struct io *iop)
+static inline struct io *io_first_list(struct list_head *head)
{
- if (!iop->on_retry_list) {
- list_add_tail(&iop->retry, &retries);
- iop->on_retry_list = 1;
- }
+ if (list_empty(head))
+ return NULL;
+
+ return list_entry(head->next, struct io, f_head);
}
-static inline void del_retry(struct io *iop)
+static inline void __dump_iop(FILE *ofp, struct io *iop, int extra_nl)
{
- if (iop->on_retry_list) {
- LIST_DEL(&iop->retry);
- iop->on_retry_list = 0;
- }
+ 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 __u64 tdelta(struct io *iop1, struct io *iop2)
+static inline void __dump_iop2(FILE *ofp, struct io *a_iop, struct io *l_iop)
{
- __u64 t1 = iop1->t.time;
- __u64 t2 = iop2->t.time;
- return (t1 < t2) ? (t2 - t1) : 1;
+ 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);
}