*/
#include "globals.h"
-LIST_HEAD(pending_cs);
-
-static void gen_c_list(struct io *c_iop, struct list_head *c_head)
+static inline void __out(FILE *ofp, __u64 tm, enum iop_type type,
+ __u64 sec, __u32 nsec, int indent)
{
- struct io *iop;
- struct list_head *p;
-
- __list_for_each(p, &pending_cs) {
- iop = list_entry(p, struct io, c_pending);
- if (iop->t.device == c_iop->t.device)
- continue;
- if (dip_find_sec(iop->dip, IOP_D, BIT_START(iop)) == NULL)
- continue;
-
- __link(iop, c_iop);
- if (ready_complete(iop, c_iop))
- list_add_tail(&iop->f_head, c_head);
- __unlink(iop, c_iop);
+ if (tm != (__u64)-1) {
+ if (indent)
+ fprintf(ofp, " ");
+ fprintf(ofp, "%5d.%09lu %c %10llu+%-4u\n",
+ (int)SECONDS(tm), (unsigned long)NANO_SECONDS(tm),
+ type2c(type), (unsigned long long)sec, nsec);
}
}
-static void run_comp(struct io *c_iop, struct io *top, struct list_head *rmhd)
+static void display_io_track(FILE *ofp, struct io *iop)
{
- struct io *d_iop = dip_find_sec(c_iop->dip, IOP_D, BIT_START(c_iop));
-
- update_blks(c_iop);
- if (d_iop) {
- __u64 d2c = tdelta(d_iop, c_iop);
-
- update_d2c(d_iop, d2c);
- latency_d2c(d_iop->dip, c_iop->t.time, d2c);
- iostat_complete(d_iop, c_iop);
-
- __link(d_iop, c_iop);
- run_issue(d_iop, top, rmhd);
- __unlink(d_iop, c_iop);
- }
- else {
- LIST_HEAD(head);
- struct io *iop;
- struct list_head *p, *q;
-
- gen_c_list(c_iop, &head);
- list_for_each_safe(p, q, &head) {
- iop = list_entry(p, struct io, f_head);
- LIST_DEL(&iop->f_head);
-
- dump_level++;
- __link(iop, c_iop);
- run_comp(iop, top, rmhd);
- __unlink(iop, c_iop);
- dump_level--;
- }
- }
- dump_iop(per_io_ofp, c_iop, NULL, 0);
- LIST_DEL(&c_iop->c_pending);
- list_add_tail(&c_iop->f_head, rmhd);
+ fprintf(ofp, "%3d,%-3d: ", MAJOR(iop->t.device), MINOR(iop->t.device));
+ __out(ofp, iop->t.time, IOP_Q, iop->t.sector, t_sec(&iop->t), 0);
+
+ if (iop->g_time != (__u64)-1)
+ __out(ofp, iop->g_time, IOP_G, iop->t.sector, t_sec(&iop->t),1);
+ if (iop->i_time != (__u64)-1)
+ __out(ofp, iop->i_time, IOP_I, iop->t.sector, t_sec(&iop->t),1);
+ if (iop->m_time != (__u64)-1)
+ __out(ofp, iop->m_time, IOP_M, iop->t.sector, t_sec(&iop->t),1);
+
+ __out(ofp, iop->d_time, IOP_D, iop->d_sec, iop->d_nsec, 1);
+ __out(ofp, iop->c_time, IOP_C, iop->c_sec, iop->c_nsec, 1);
+ fprintf(ofp, "\n");
}
-static int ready_comp(struct io *c_iop,
- __attribute__((__unused__)) struct io *top)
+static void handle_complete(struct io *c_iop)
{
LIST_HEAD(head);
- struct io *iop;
struct list_head *p, *q;
- __u64 bl = c_iop->bytes_left;
+ __u64 d_time = (__u64)-1;
+ FILE *pit_fp = c_iop->dip->pit_fp;
+ double cur = BIT_TIME(c_iop->t.time);
- gen_c_list(c_iop, &head);
+ update_blks(c_iop);
+ update_cregion(&all_regions, c_iop->t.time);
+ update_cregion(&c_iop->dip->regions, c_iop->t.time);
+ if (c_iop->pip)
+ update_cregion(&c_iop->pip->regions, c_iop->t.time);
+ aqd_complete(c_iop->dip->aqd_handle, cur);
+ rstat_add(c_iop->dip->rstat_handle, cur, c_iop->t.bytes >> 9);
+
+ dip_foreach_list(c_iop, IOP_Q, &head);
list_for_each_safe(p, q, &head) {
- iop = list_entry(p, struct io, f_head);
- LIST_DEL(&iop->f_head);
+ struct io *q_iop = list_entry(p, struct io, f_head);
+ __u64 q2c = tdelta(q_iop->t.time, c_iop->t.time);
- __link(iop, c_iop);
- if (ready_complete(iop, c_iop))
- bl -= iop->bytes_left;
- __unlink(iop, c_iop);
- }
+ c_iop->bytes_left -= q_iop->t.bytes;
- return bl == 0;
-}
+ update_q2c(q_iop, q2c);
+ latency_q2c(q_iop->dip, q_iop->t.time, q2c);
-void trace_complete(struct io *c_iop)
-{
- if (!io_setup(c_iop, IOP_C)) {
- io_release(c_iop);
- return;
- }
+ if (q_iop->d_time != (__u64)-1) {
+ __u64 d2c = tdelta(q_iop->d_time, c_iop->t.time);
- list_add_tail(&c_iop->c_pending, &pending_cs);
- if (ready_complete(c_iop, c_iop)) {
- dump_level = 0;
- run_complete(c_iop);
- }
- else
- add_retry(c_iop);
-}
+ update_d2c(q_iop, d2c);
+ latency_d2c(q_iop->dip, c_iop->t.time, d2c);
+ iostat_complete(q_iop, c_iop);
-int retry_complete(struct io *c_iop)
-{
- if (!ready_complete(c_iop, c_iop))
- return 0;
+ d_time = q_iop->d_time;
+ }
- del_retry(c_iop);
- run_complete(c_iop);
- return 1;
-}
+ if (per_io_ofp) {
+ q_iop->c_time = c_iop->t.time;
+ q_iop->c_sec = c_iop->t.sector;
+ q_iop->c_nsec = t_sec(&c_iop->t);
+ display_io_track(per_io_ofp, q_iop);
+ }
-int ready_complete(struct io *c_iop, struct io *top)
-{
- struct io *d_iop = dip_find_sec(c_iop->dip, IOP_D, BIT_START(c_iop));
+ if (q_iop->dip->pit_fp) {
+ fprintf(pit_fp, "%d.%09lu ",
+ (int)SECONDS(q_iop->t.time),
+ (unsigned long)NANO_SECONDS(q_iop->t.time));
+ }
- if (d_iop) {
- ASSERT(d_iop->t.bytes == c_iop->bytes_left);
- return ready_issue(d_iop, top);
+ list_del(&q_iop->f_head);
+ io_release(q_iop);
+ }
+
+ if (per_io_ofp)
+ fprintf(per_io_ofp,
+ "-----------------------------------------\n");
+
+ if (c_iop->dip->pit_fp) {
+ fprintf(pit_fp, "| %d.%09lu | %d.%09lu\n",
+ (int)SECONDS(d_time),
+ (unsigned long)NANO_SECONDS(d_time),
+ (int)SECONDS(c_iop->t.time),
+ (unsigned long)NANO_SECONDS(c_iop->t.time));
}
- else
- return ready_comp(c_iop, top);
}
-void run_complete(struct io *c_iop)
+void trace_complete(struct io *c_iop)
{
- LIST_HEAD(rmhd);
+ if (c_iop->t.bytes == 0)
+ return;
- update_cregion(&all_regions, c_iop->t.time);
- update_cregion(&c_iop->dip->regions, c_iop->t.time);
- if (c_iop->pip)
- update_cregion(&c_iop->pip->regions, c_iop->t.time);
+ if (io_setup(c_iop, IOP_C))
+ handle_complete(c_iop);
- run_comp(c_iop, c_iop, &rmhd);
- if (per_io_ofp) fprintf(per_io_ofp, "\n");
- release_iops(&rmhd);
+ io_release(c_iop);
}