#include #include enum { Nanoi = 1000000000, /* 1/nano */ Microi = 1000000, }; void ioloop(int fd, uvlong bytes, char *prog) { char *buf, *p, *loop; int l; uint ss, iops; uvlong byte0, maxlba, lba, t, x; /* silence compiler */ iops = 0; l = 0; t = 0; loop = nil; byte0 = 0; lba = 0; ss = 512; maxlba = (bytes - byte0) / ss; buf = malloc(ss); if(buf == nil) sysfatal("malloc"); srand(nsec()); for(p = prog;; ){ switch(*p){ default: sysfatal("bad char %c in prog %s\n", *p, prog); case 0: goto end; case ' ': break; case ':': /* loop */ l = strtol(p+1, &loop, 0); p = loop; continue; case ';': /* end */ if(loop == nil) sysfatal("malformd loop: extra ';'"); if(--l > 0){ p = loop; continue; } loop = nil; break; case '{': iops = 0; t = - nsec(); break; case '}': t += nsec(); print("%lld.%03lld\n", t/Nanoi, (t%Nanoi)/Microi); x = (uvlong)iops*(uvlong)Nanoi*100; x /= t; print("%lld.%02lld iops\n", x/100, (x%100)); break; case 'o': byte0 = strtoull(p, &p, 0); maxlba = (bytes - byte0) / ss; continue; case 'z': ss = strtoul(p, &p, 0); if(ss == 0) sysfatal("sector size zero"); maxlba = (bytes - byte0) / ss; buf = realloc(buf, ss); if(buf == nil) sysfatal("realloc: %r"); break; case 'r': /* read */ pread(fd, buf, ss, byte0 + lba*ss); iops++; break; case 'w': /* write */ pwrite(fd, buf, ss, byte0 + lba*ss); iops++; break; case 's': /* seek */ switch(p[1]){ default: sysfatal("seek requires argument\n"); case 'r': lba = frand()*maxlba; /* awful. no vlnrand() */ p++; break; case 's': p++; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': p++; lba += strtol(p, &p, 0); break; } continue; } p++; } end: free(buf); } void usage(void) { fprint(2, "usage: iop [-p prog] ... [file ...]\n"); exits("usage"); } void main(int argc, char **argv) { char *prog[25]; int i, j, nprog, fd; uvlong bytes; Dir *d; nprog = 0; ARGBEGIN{ case 'p': if(nprog == nelem(prog)) sysfatal("too many programs"); prog[nprog++] = EARGF(usage()); break; default: usage(); }ARGEND; for(i = 0; i < argc; i++){ d = dirstat(argv[i]); if(d == nil) sysfatal("dirstat: %r"); bytes = d->length; free(d); fd = open(argv[i], ORDWR); if(fd == -1) sysfatal("open: %r"); for(j = 0; j < nprog; j++) ioloop(fd, bytes, prog[i]); close(fd); } exits(""); }