1ce0d9371SArne Jansen #include <stdio.h> 2ce0d9371SArne Jansen #include <stdlib.h> 3ce0d9371SArne Jansen #include <unistd.h> 4ce0d9371SArne Jansen #include <sys/types.h> 5ce0d9371SArne Jansen #include <sys/stat.h> 6ce0d9371SArne Jansen #include <sys/wait.h> 7ce0d9371SArne Jansen #include <fcntl.h> 8ce0d9371SArne Jansen #include <sys/fs/zfs.h> 9ce0d9371SArne Jansen #include <sys/zfs_ioctl.h> 10ce0d9371SArne Jansen #include <string.h> 11ce0d9371SArne Jansen #include <errno.h> 12ce0d9371SArne Jansen #include <dtrace.h> 13ce0d9371SArne Jansen #include <assert.h> 14ce0d9371SArne Jansen #include <sys/avl.h> 15ce0d9371SArne Jansen #include <sys/arc.h> 16ce0d9371SArne Jansen #include <stddef.h> 17ce0d9371SArne Jansen #include <pthread.h> 18ce0d9371SArne Jansen 19ce0d9371SArne Jansen #define ARCWATCH_READ_MAGIC "awrd" 20ce0d9371SArne Jansen #define ARCWATCH_READ_VERSION 1 21ce0d9371SArne Jansen 22ce0d9371SArne Jansen typedef struct arc_read_hdr { 23ce0d9371SArne Jansen char arh_magic[4]; 24ce0d9371SArne Jansen uint32_t arh_version; 25ce0d9371SArne Jansen } arc_read_hdr_t; 26ce0d9371SArne Jansen 27ce0d9371SArne Jansen typedef struct arc_read { 28ce0d9371SArne Jansen uint64_t ar_objset; 29ce0d9371SArne Jansen uint64_t ar_object; 30ce0d9371SArne Jansen uint64_t ar_level; 31ce0d9371SArne Jansen uint64_t ar_blkid; 32ce0d9371SArne Jansen uint64_t ar_size; 33ce0d9371SArne Jansen uint64_t ar_type; 34ce0d9371SArne Jansen uint64_t ar_dva0; 35ce0d9371SArne Jansen uint64_t ar_dva1; 36ce0d9371SArne Jansen uint64_t ar_birth; 37ce0d9371SArne Jansen uint64_t ar_spa; 38ce0d9371SArne Jansen } arc_read_t; 39ce0d9371SArne Jansen 40ce0d9371SArne Jansen #define ARNS_IN_L1_CACHE 1 41ce0d9371SArne Jansen #define ARNS_IN_L2_CACHE 2 42ce0d9371SArne Jansen typedef struct arc_read_node { 43ce0d9371SArne Jansen arc_read_t arn_ar; 44ce0d9371SArne Jansen avl_node_t arn_node; 45ce0d9371SArne Jansen uint64_t arn_color; 46ce0d9371SArne Jansen uint64_t arn_state; 47ce0d9371SArne Jansen uint64_t arn_flags; 48ce0d9371SArne Jansen } arc_read_node_t; 49ce0d9371SArne Jansen 50ce0d9371SArne Jansen #define ARCWATCH_CONTENT_MAGIC "awct" 51ce0d9371SArne Jansen #define ARCWATCH_CONTENT_VERSION 1 52ce0d9371SArne Jansen 53ce0d9371SArne Jansen typedef struct arc_content_hdr { 54ce0d9371SArne Jansen char ach_magic[4]; 55ce0d9371SArne Jansen uint32_t ach_version; 56ce0d9371SArne Jansen uint64_t ach_buckets; 57ce0d9371SArne Jansen uint64_t ach_buf_locks; 58ce0d9371SArne Jansen } arc_content_hdr_t; 59ce0d9371SArne Jansen 60ce0d9371SArne Jansen static const char * 61ce0d9371SArne Jansen state2str(arc_info_state_t state) 62ce0d9371SArne Jansen { 63ce0d9371SArne Jansen switch (state) { 64ce0d9371SArne Jansen case AIS_ANON: return "anon"; 65ce0d9371SArne Jansen case AIS_MRU: return "mru"; 66ce0d9371SArne Jansen case AIS_MRU_GHOST: return "mru_ghost"; 67ce0d9371SArne Jansen case AIS_MFU: return "mfu"; 68ce0d9371SArne Jansen case AIS_MFU_GHOST: return "mfu_ghost"; 69ce0d9371SArne Jansen case AIS_L2C_ONLY: return "l2c_only"; 70ce0d9371SArne Jansen case AIS_NO_L1HDR: return "no_l1hdr"; 71ce0d9371SArne Jansen default: 72ce0d9371SArne Jansen case AIS_UNKNOWN: return "unknown"; 73ce0d9371SArne Jansen } 74ce0d9371SArne Jansen } 75ce0d9371SArne Jansen 76ce0d9371SArne Jansen static int g_verbose = 0; 77ce0d9371SArne Jansen 78ce0d9371SArne Jansen static char *d_prog = 79ce0d9371SArne Jansen "dtrace:::BEGIN\n" 80ce0d9371SArne Jansen "{\n" 81ce0d9371SArne Jansen " trackedpid[pid] = 0;\n" 82ce0d9371SArne Jansen " self->child = 0;\n" 83ce0d9371SArne Jansen " OPT_follow = 1;\n" 84ce0d9371SArne Jansen "}\n" 85ce0d9371SArne Jansen "syscall::fork*:entry\n" 86ce0d9371SArne Jansen "/OPT_follow && (pid == $target || self->child)/\n" 87ce0d9371SArne Jansen "{\n" 88ce0d9371SArne Jansen " trackedpid[pid] = 1;\n" 89ce0d9371SArne Jansen "}\n" 90ce0d9371SArne Jansen "syscall::fork*:return\n" 91ce0d9371SArne Jansen "/OPT_follow && trackedpid[ppid]/\n" 92ce0d9371SArne Jansen "{\n" 93ce0d9371SArne Jansen " self->child = 1;\n" 94ce0d9371SArne Jansen "}\n" 95ce0d9371SArne Jansen "fbt::dbuf_hold_impl:entry\n" 96ce0d9371SArne Jansen "/pid == $target || self->child/\n" 97ce0d9371SArne Jansen "{\n" 98ce0d9371SArne Jansen " self->dbp = args[6];\n" 99ce0d9371SArne Jansen " self->type = args[0]->dn_type;\n" 100ce0d9371SArne Jansen "}\n" 101ce0d9371SArne Jansen "fbt::dbuf_hold_impl:return\n" 102ce0d9371SArne Jansen "/self->dbp && (*self->dbp)->db_state == 4/\n" 103ce0d9371SArne Jansen "{\n" 104ce0d9371SArne Jansen " this->db = *self->dbp;\n" 105ce0d9371SArne Jansen " this->os = this->db->db_objset;\n" 106ce0d9371SArne Jansen " this->hdr = this->db->db_buf ? this->db->db_buf->b_hdr : 0;\n" 107ce0d9371SArne Jansen " trace(this->os->os_dsl_dataset ?\n" 108ce0d9371SArne Jansen " this->os->os_dsl_dataset->ds_object : 0);\n" 109ce0d9371SArne Jansen " trace(this->db->db.db_object);\n" 110ce0d9371SArne Jansen " trace(this->db->db_level);\n" 111ce0d9371SArne Jansen " trace(this->db->db_blkid);\n" 112ce0d9371SArne Jansen " trace(this->db->db.db_size);\n" 113ce0d9371SArne Jansen " trace(self->type);\n" 114ce0d9371SArne Jansen " trace(this->hdr ? this->hdr->b_dva.dva_word[0] : 0);\n" 115ce0d9371SArne Jansen " trace(this->hdr ? this->hdr->b_dva.dva_word[1] : 0);\n" 116ce0d9371SArne Jansen " trace(this->hdr ? this->hdr->b_birth : 0);\n" 117ce0d9371SArne Jansen " trace(this->hdr ? this->hdr->b_spa : 0);\n" 118ce0d9371SArne Jansen " self->dbp = 0;\n" 119ce0d9371SArne Jansen " self->type = 0;\n" 120ce0d9371SArne Jansen "}\n"; 121ce0d9371SArne Jansen 122ce0d9371SArne Jansen static int 123ce0d9371SArne Jansen awr_cmp(const void *x, const void *y) 124ce0d9371SArne Jansen { 125ce0d9371SArne Jansen const arc_read_node_t *a = x; 126ce0d9371SArne Jansen const arc_read_node_t *b = y; 127ce0d9371SArne Jansen 128ce0d9371SArne Jansen if (a->arn_ar.ar_spa < b->arn_ar.ar_spa) 129ce0d9371SArne Jansen return -1; 130ce0d9371SArne Jansen if (a->arn_ar.ar_spa > b->arn_ar.ar_spa) 131ce0d9371SArne Jansen return 1; 132ce0d9371SArne Jansen if (a->arn_ar.ar_dva0 < b->arn_ar.ar_dva0) 133ce0d9371SArne Jansen return -1; 134ce0d9371SArne Jansen if (a->arn_ar.ar_dva0 > b->arn_ar.ar_dva0) 135ce0d9371SArne Jansen return 1; 136ce0d9371SArne Jansen if (a->arn_ar.ar_dva1 < b->arn_ar.ar_dva1) 137ce0d9371SArne Jansen return -1; 138ce0d9371SArne Jansen if (a->arn_ar.ar_dva1 > b->arn_ar.ar_dva1) 139ce0d9371SArne Jansen return 1; 140ce0d9371SArne Jansen if (a->arn_ar.ar_birth < b->arn_ar.ar_birth) 141ce0d9371SArne Jansen return -1; 142ce0d9371SArne Jansen if (a->arn_ar.ar_birth > b->arn_ar.ar_birth) 143ce0d9371SArne Jansen return 1; 144ce0d9371SArne Jansen return 0; 145ce0d9371SArne Jansen } 146ce0d9371SArne Jansen 147ce0d9371SArne Jansen static int 148ce0d9371SArne Jansen drophandler(const dtrace_dropdata_t *data, void *arg) 149ce0d9371SArne Jansen { 150ce0d9371SArne Jansen fprintf(stderr, "type %d drops %lld\n", data->dtdda_kind, data->dtdda_drops); 151ce0d9371SArne Jansen fprintf(stderr, "dtrace drops encountered. Try increasing buffers.\n"); 152ce0d9371SArne Jansen exit(1); 153ce0d9371SArne Jansen } 154ce0d9371SArne Jansen 155ce0d9371SArne Jansen static void 156ce0d9371SArne Jansen prochandler(struct ps_prochandle *P, const char *msg, void *arg) 157ce0d9371SArne Jansen { 158ce0d9371SArne Jansen int *proc_done = arg; 159ce0d9371SArne Jansen 160ce0d9371SArne Jansen *proc_done = 1; 161ce0d9371SArne Jansen } 162ce0d9371SArne Jansen 163ce0d9371SArne Jansen static uint64_t 164ce0d9371SArne Jansen get_val(caddr_t base, dtrace_recdesc_t *rec) 165ce0d9371SArne Jansen { 166ce0d9371SArne Jansen uint64_t val = 0; 167ce0d9371SArne Jansen 168ce0d9371SArne Jansen assert(rec->dtrd_action == DTRACEACT_DIFEXPR); 169ce0d9371SArne Jansen assert(rec->dtrd_size > 0); 170ce0d9371SArne Jansen assert(rec->dtrd_size <= 8); 171ce0d9371SArne Jansen 172ce0d9371SArne Jansen memcpy(&val, base + rec->dtrd_offset, rec->dtrd_size); 173ce0d9371SArne Jansen 174ce0d9371SArne Jansen return val; 175ce0d9371SArne Jansen } 176ce0d9371SArne Jansen 177ce0d9371SArne Jansen typedef struct trace_args { 178ce0d9371SArne Jansen int ofd; 179ce0d9371SArne Jansen avl_tree_t *awr; 180ce0d9371SArne Jansen pthread_mutex_t mtx; 181ce0d9371SArne Jansen int ptr; 182ce0d9371SArne Jansen char buf[16384]; 183ce0d9371SArne Jansen } trace_args_t; 184ce0d9371SArne Jansen 185ce0d9371SArne Jansen static int 186ce0d9371SArne Jansen process_trace(const dtrace_probedata_t *data, void *arg) 187ce0d9371SArne Jansen { 188ce0d9371SArne Jansen dtrace_eprobedesc_t *edesc = data->dtpda_edesc; 189ce0d9371SArne Jansen caddr_t base = data->dtpda_data; 190ce0d9371SArne Jansen dtrace_recdesc_t *rec = edesc->dtepd_rec; 191ce0d9371SArne Jansen trace_args_t *ta = arg; 192ce0d9371SArne Jansen arc_read_t ar; 193ce0d9371SArne Jansen int ret; 194ce0d9371SArne Jansen 195ce0d9371SArne Jansen assert(edesc->dtepd_nrecs == 15); 196ce0d9371SArne Jansen 197ce0d9371SArne Jansen ar.ar_objset = get_val(base, rec + 3); 198ce0d9371SArne Jansen ar.ar_object = get_val(base, rec + 4); 199ce0d9371SArne Jansen ar.ar_level = get_val(base, rec + 5); 200ce0d9371SArne Jansen ar.ar_blkid = get_val(base, rec + 6); 201ce0d9371SArne Jansen ar.ar_size = get_val(base, rec + 7); 202ce0d9371SArne Jansen ar.ar_type = get_val(base, rec + 8); 203ce0d9371SArne Jansen ar.ar_dva0 = get_val(base, rec + 9); 204ce0d9371SArne Jansen ar.ar_dva1 = get_val(base, rec + 10); 205ce0d9371SArne Jansen ar.ar_birth = get_val(base, rec + 11); 206ce0d9371SArne Jansen ar.ar_spa = get_val(base, rec + 12); 207ce0d9371SArne Jansen 208ce0d9371SArne Jansen if (ta->ofd != -1) { 209ce0d9371SArne Jansen pthread_mutex_lock(&ta->mtx); 210ce0d9371SArne Jansen if (ta->ptr + sizeof(ar) > sizeof(ta->buf)) { 211ce0d9371SArne Jansen ret = write(ta->ofd, ta->buf, ta->ptr); 212ce0d9371SArne Jansen if (ret == -1) { 213ce0d9371SArne Jansen fprintf(stderr, 214ce0d9371SArne Jansen "cannot write to output file: %s\n", 215ce0d9371SArne Jansen strerror(errno)); 216ce0d9371SArne Jansen exit(1); 217ce0d9371SArne Jansen } 218ce0d9371SArne Jansen ta->ptr = 0; 219ce0d9371SArne Jansen } 220ce0d9371SArne Jansen memcpy(ta->buf + ta->ptr, &ar, sizeof(ar)); 221ce0d9371SArne Jansen ta->ptr += sizeof(ar); 222ce0d9371SArne Jansen pthread_mutex_unlock(&ta->mtx); 223ce0d9371SArne Jansen } 224ce0d9371SArne Jansen 225ce0d9371SArne Jansen if (ta->awr) { 226ce0d9371SArne Jansen arc_read_node_t *arn; 227ce0d9371SArne Jansen 228ce0d9371SArne Jansen arn = calloc(sizeof(*arn), 1); 229ce0d9371SArne Jansen assert(arn); 230ce0d9371SArne Jansen arn->arn_ar = ar; 231ce0d9371SArne Jansen pthread_mutex_lock(&ta->mtx); 232ce0d9371SArne Jansen if (avl_find(ta->awr, arn, NULL) == NULL) 233ce0d9371SArne Jansen avl_add(ta->awr, arn); 234ce0d9371SArne Jansen pthread_mutex_unlock(&ta->mtx); 235ce0d9371SArne Jansen } 236ce0d9371SArne Jansen 237ce0d9371SArne Jansen if (g_verbose) { 238ce0d9371SArne Jansen printf("spa %llx objset %lld object %lld level %lld blkid " 239ce0d9371SArne Jansen "%lld size %lld type %lld dva %16x:%16x birth %lld\n", 240ce0d9371SArne Jansen ar.ar_spa, ar.ar_objset, ar.ar_object, ar.ar_level, 241ce0d9371SArne Jansen ar.ar_blkid, ar.ar_size, ar.ar_type, 242ce0d9371SArne Jansen ar.ar_dva0, ar.ar_dva1, ar.ar_birth); 243ce0d9371SArne Jansen } 244ce0d9371SArne Jansen 245ce0d9371SArne Jansen return (DTRACE_CONSUME_NEXT); 246ce0d9371SArne Jansen } 247ce0d9371SArne Jansen 248ce0d9371SArne Jansen static void 249ce0d9371SArne Jansen d_fatal(dtrace_hdl_t *dtp, char *msg) 250ce0d9371SArne Jansen { 251ce0d9371SArne Jansen fprintf(stderr, "%s: %s\n", msg, dtrace_errmsg(dtp, dtrace_errno(dtp))); 252ce0d9371SArne Jansen exit(1); 253ce0d9371SArne Jansen } 254ce0d9371SArne Jansen 255ce0d9371SArne Jansen static int 256ce0d9371SArne Jansen run_dtrace(char *bufsize, char *out_fn, avl_tree_t *awr, int argc, char **argv) 257ce0d9371SArne Jansen { 258ce0d9371SArne Jansen dtrace_prog_t *dp; 259ce0d9371SArne Jansen dtrace_hdl_t *dtp; 260ce0d9371SArne Jansen dtrace_proginfo_t info; 261ce0d9371SArne Jansen struct ps_prochandle *p; 262ce0d9371SArne Jansen int err; 263ce0d9371SArne Jansen int proc_done = 0; 264ce0d9371SArne Jansen int done = 0; 265ce0d9371SArne Jansen int ofd = -1; 266ce0d9371SArne Jansen arc_read_hdr_t arh = { 0 }; 267ce0d9371SArne Jansen trace_args_t ta = { 0 }; 268ce0d9371SArne Jansen 269ce0d9371SArne Jansen ta.ofd = -1; 270ce0d9371SArne Jansen ta.awr = awr; 271ce0d9371SArne Jansen pthread_mutex_init(&ta.mtx, NULL); 272ce0d9371SArne Jansen 273ce0d9371SArne Jansen if (out_fn) { 274ce0d9371SArne Jansen ofd = open(out_fn, O_CREAT | O_TRUNC | O_WRONLY, 0644); 275ce0d9371SArne Jansen if (ofd == -1) { 276ce0d9371SArne Jansen printf("cannot open output file %s: %s\n", 277ce0d9371SArne Jansen out_fn, strerror(errno)); 278ce0d9371SArne Jansen exit(1); 279ce0d9371SArne Jansen } 280ce0d9371SArne Jansen memcpy(arh.arh_magic, ARCWATCH_READ_MAGIC, 281ce0d9371SArne Jansen sizeof(arh.arh_magic)); 282ce0d9371SArne Jansen arh.arh_version = ARCWATCH_READ_VERSION; 283ce0d9371SArne Jansen err = write(ofd, &arh, sizeof(arh)); 284ce0d9371SArne Jansen if (err == -1) { 285ce0d9371SArne Jansen printf("cannot write to output file: %s\n", 286ce0d9371SArne Jansen strerror(errno)); 287ce0d9371SArne Jansen exit(1); 288ce0d9371SArne Jansen } 289ce0d9371SArne Jansen ta.ofd = ofd; 290ce0d9371SArne Jansen } 291ce0d9371SArne Jansen 292ce0d9371SArne Jansen dtp = dtrace_open(DTRACE_VERSION, 0, &err); 293ce0d9371SArne Jansen if (dtp == NULL) { 294ce0d9371SArne Jansen printf("cannot open dtrace library: %s\n", 295ce0d9371SArne Jansen dtrace_errmsg(NULL, err)); 296ce0d9371SArne Jansen exit(1); 297ce0d9371SArne Jansen } 298ce0d9371SArne Jansen 299ce0d9371SArne Jansen if (dtrace_handle_drop(dtp, &drophandler, NULL) == -1) 300ce0d9371SArne Jansen d_fatal(dtp, "couldn't establish drop handler"); 301ce0d9371SArne Jansen 302ce0d9371SArne Jansen if (dtrace_handle_proc(dtp, &prochandler, &proc_done) == -1) 303ce0d9371SArne Jansen d_fatal(dtp, "failed to establish proc handler"); 304ce0d9371SArne Jansen 305ce0d9371SArne Jansen if (dtrace_setopt(dtp, "bufsize", bufsize) == -1) 306ce0d9371SArne Jansen d_fatal(dtp, "failed to set bufsize"); 307ce0d9371SArne Jansen 308ce0d9371SArne Jansen /* XXX TODO understand dynvar drops */ 309ce0d9371SArne Jansen if (dtrace_setopt(dtp, "dynvarsize", "4m") == -1) 310ce0d9371SArne Jansen d_fatal(dtp, "failed to set dynvarsize"); 311ce0d9371SArne Jansen 312ce0d9371SArne Jansen if (dtrace_setopt(dtp, "temporal", "no") == -1) 313ce0d9371SArne Jansen d_fatal(dtp, "failed to set temporal"); 314ce0d9371SArne Jansen 315ce0d9371SArne Jansen if (dtrace_setopt(dtp, "switchrate", "100hz") == -1) 316ce0d9371SArne Jansen d_fatal(dtp, "failed to set switchrate"); 317ce0d9371SArne Jansen 318ce0d9371SArne Jansen if (dtrace_setopt(dtp, "cleanrate", "100hz") == -1) 319ce0d9371SArne Jansen d_fatal(dtp, "failed to set cleanrate"); 320ce0d9371SArne Jansen 321ce0d9371SArne Jansen p = dtrace_proc_create(dtp, argv[0], &argv[0]); 322ce0d9371SArne Jansen if (p == NULL) 323ce0d9371SArne Jansen d_fatal(dtp, "creating process failed"); 324ce0d9371SArne Jansen 325ce0d9371SArne Jansen dp = dtrace_program_strcompile(dtp, d_prog, DTRACE_PROBESPEC_NAME, 0, 326ce0d9371SArne Jansen 0, NULL); 327ce0d9371SArne Jansen if (dp == NULL) 328ce0d9371SArne Jansen d_fatal(dtp, "failed to compile program"); 329ce0d9371SArne Jansen 330ce0d9371SArne Jansen if (dtrace_program_exec(dtp, dp, &info) == -1) 331ce0d9371SArne Jansen d_fatal(dtp, "failed to enable probes"); 332ce0d9371SArne Jansen 333ce0d9371SArne Jansen if (dtrace_go(dtp)) 334ce0d9371SArne Jansen d_fatal(dtp, "couldn't start tracing"); 335ce0d9371SArne Jansen 336ce0d9371SArne Jansen (void) dtrace_proc_continue(dtp, p); 337ce0d9371SArne Jansen 338ce0d9371SArne Jansen do { 339ce0d9371SArne Jansen dtrace_sleep(dtp); 340ce0d9371SArne Jansen 341ce0d9371SArne Jansen if (proc_done) { 342ce0d9371SArne Jansen done = 1; 343ce0d9371SArne Jansen (void) dtrace_stop(dtp); 344ce0d9371SArne Jansen } 345ce0d9371SArne Jansen 346ce0d9371SArne Jansen err = dtrace_work(dtp, stdout, process_trace, NULL, &ta); 347ce0d9371SArne Jansen if (err == DTRACE_WORKSTATUS_DONE) 348ce0d9371SArne Jansen done = 1; 349ce0d9371SArne Jansen } while (!done); 350ce0d9371SArne Jansen 351ce0d9371SArne Jansen if (ta.ptr > 0) { 352ce0d9371SArne Jansen err = write(ta.ofd, ta.buf, ta.ptr); 353ce0d9371SArne Jansen if (err == -1) { 354ce0d9371SArne Jansen fprintf(stderr, 355ce0d9371SArne Jansen "cannot write to output file: %s\n", 356ce0d9371SArne Jansen strerror(errno)); 357ce0d9371SArne Jansen exit(1); 358ce0d9371SArne Jansen } 359ce0d9371SArne Jansen } 360ce0d9371SArne Jansen (void) dtrace_close(dtp); 361ce0d9371SArne Jansen if (ofd != -1) 362ce0d9371SArne Jansen close(ofd); 363ce0d9371SArne Jansen 364ce0d9371SArne Jansen return (0); 365ce0d9371SArne Jansen } 366ce0d9371SArne Jansen 367ce0d9371SArne Jansen static void 368ce0d9371SArne Jansen read_awr(avl_tree_t *awr, char *in_fn) 369ce0d9371SArne Jansen { 370ce0d9371SArne Jansen int fd; 371ce0d9371SArne Jansen int ret; 372ce0d9371SArne Jansen arc_read_hdr_t arh; 373ce0d9371SArne Jansen char buf[1000 * sizeof(arc_read_t)]; 374ce0d9371SArne Jansen int blen = 0; 375ce0d9371SArne Jansen int ptr = 0; 376ce0d9371SArne Jansen 377ce0d9371SArne Jansen fd = open(in_fn, O_RDONLY); 378ce0d9371SArne Jansen if (fd == -1) { 379ce0d9371SArne Jansen fprintf(stderr, "failed to open input: %s\n", 380ce0d9371SArne Jansen strerror(errno)); 381ce0d9371SArne Jansen exit(1); 382ce0d9371SArne Jansen } 383ce0d9371SArne Jansen ret = read(fd, &arh, sizeof(arh)); 384ce0d9371SArne Jansen if (ret == -1) { 385ce0d9371SArne Jansen fprintf(stderr, "failed to read input: %s\n", 386ce0d9371SArne Jansen strerror(errno)); 387ce0d9371SArne Jansen exit(1); 388ce0d9371SArne Jansen } 389ce0d9371SArne Jansen if (ret != sizeof(arh)) { 390ce0d9371SArne Jansen fprintf(stderr, "failed to read input: truncated file\n"); 391ce0d9371SArne Jansen exit(1); 392ce0d9371SArne Jansen } 393ce0d9371SArne Jansen if (memcmp(arh.arh_magic, ARCWATCH_READ_MAGIC, 4) != 0) { 394ce0d9371SArne Jansen fprintf(stderr, "failed to read input: bad file magic\n"); 395ce0d9371SArne Jansen exit(1); 396ce0d9371SArne Jansen } 397ce0d9371SArne Jansen if (arh.arh_version != ARCWATCH_READ_VERSION) { 398ce0d9371SArne Jansen fprintf(stderr, "failed to read input: bad file version\n"); 399ce0d9371SArne Jansen exit(1); 400ce0d9371SArne Jansen } 401ce0d9371SArne Jansen while (1) { 402ce0d9371SArne Jansen arc_read_node_t *arn = calloc(sizeof(*arn), 1); 403ce0d9371SArne Jansen 404ce0d9371SArne Jansen assert(arn); 405ce0d9371SArne Jansen if (blen == ptr) { 406ce0d9371SArne Jansen ret = read(fd, buf, sizeof(buf)); 407ce0d9371SArne Jansen if (ret == 0) 408ce0d9371SArne Jansen break; 409ce0d9371SArne Jansen if (ret == -1) { 410ce0d9371SArne Jansen fprintf(stderr, "failed to read input: %s\n", 411ce0d9371SArne Jansen strerror(errno)); 412ce0d9371SArne Jansen exit(1); 413ce0d9371SArne Jansen } 414ce0d9371SArne Jansen blen = ret; 415ce0d9371SArne Jansen ptr = 0; 416ce0d9371SArne Jansen } 417ce0d9371SArne Jansen if ((blen - ptr) < sizeof(arn->arn_ar)) { 418ce0d9371SArne Jansen fprintf(stderr, 419ce0d9371SArne Jansen "failed to read input: truncated file\n"); 420ce0d9371SArne Jansen exit(1); 421ce0d9371SArne Jansen } 422ce0d9371SArne Jansen memcpy(&arn->arn_ar, buf + ptr, sizeof(arn->arn_ar)); 423ce0d9371SArne Jansen ptr += sizeof(arn->arn_ar); 424ce0d9371SArne Jansen 425ce0d9371SArne Jansen if (g_verbose >= 2) { 426ce0d9371SArne Jansen arc_read_t *ar = &arn->arn_ar; 427ce0d9371SArne Jansen 428ce0d9371SArne Jansen printf("spa %llx objset % 8lld object % 8lld " 429ce0d9371SArne Jansen "level %lld blkid % 8lld size % 6lld type % 3lld " 430ce0d9371SArne Jansen "dva %016x:%016x birth % 8lld\n", 431ce0d9371SArne Jansen ar->ar_spa, ar->ar_objset, ar->ar_object, 432ce0d9371SArne Jansen ar->ar_level, ar->ar_blkid, ar->ar_size, 433ce0d9371SArne Jansen ar->ar_type, ar->ar_dva0, ar->ar_dva1, 434ce0d9371SArne Jansen ar->ar_birth); 435ce0d9371SArne Jansen } 436ce0d9371SArne Jansen 437ce0d9371SArne Jansen if (avl_find(awr, arn, NULL) == NULL) 438ce0d9371SArne Jansen avl_add(awr, arn); 439ce0d9371SArne Jansen } 440ce0d9371SArne Jansen close(fd); 441ce0d9371SArne Jansen } 442ce0d9371SArne Jansen 443ce0d9371SArne Jansen static void 444ce0d9371SArne Jansen read_arc(avl_tree_t *awr, char *in_fn, uint64_t color) 445ce0d9371SArne Jansen { 446ce0d9371SArne Jansen int fd; 447ce0d9371SArne Jansen int ret; 448ce0d9371SArne Jansen arc_content_hdr_t ach; 449ce0d9371SArne Jansen char buf[1000 * sizeof(arc_info_t)]; 450ce0d9371SArne Jansen int ptr = 0; 451ce0d9371SArne Jansen int blen = 0; 452ce0d9371SArne Jansen 453ce0d9371SArne Jansen fd = open(in_fn, O_RDONLY); 454ce0d9371SArne Jansen if (fd == -1) { 455ce0d9371SArne Jansen fprintf(stderr, "failed to open input: %s\n", 456ce0d9371SArne Jansen strerror(errno)); 457ce0d9371SArne Jansen exit(1); 458ce0d9371SArne Jansen } 459ce0d9371SArne Jansen ret = read(fd, &ach, sizeof(ach)); 460ce0d9371SArne Jansen if (ret == -1) { 461ce0d9371SArne Jansen fprintf(stderr, "failed to read input: %s\n", 462ce0d9371SArne Jansen strerror(errno)); 463ce0d9371SArne Jansen exit(1); 464ce0d9371SArne Jansen } 465ce0d9371SArne Jansen if (ret != sizeof(ach)) { 466ce0d9371SArne Jansen fprintf(stderr, "failed to read input: truncated file\n"); 467ce0d9371SArne Jansen exit(1); 468ce0d9371SArne Jansen } 469ce0d9371SArne Jansen if (memcmp(ach.ach_magic, ARCWATCH_CONTENT_MAGIC, 4) != 0) { 470ce0d9371SArne Jansen fprintf(stderr, "failed to read input: bad file magic\n"); 471ce0d9371SArne Jansen exit(1); 472ce0d9371SArne Jansen } 473ce0d9371SArne Jansen if (ach.ach_version != ARCWATCH_CONTENT_VERSION) { 474ce0d9371SArne Jansen fprintf(stderr, "failed to read input: bad file version\n"); 475ce0d9371SArne Jansen exit(1); 476ce0d9371SArne Jansen } 477ce0d9371SArne Jansen while (1) { 478ce0d9371SArne Jansen arc_info_t ai; 479ce0d9371SArne Jansen arc_read_node_t search; 480ce0d9371SArne Jansen arc_read_node_t *arn; 481ce0d9371SArne Jansen 482ce0d9371SArne Jansen if (blen == ptr) { 483ce0d9371SArne Jansen ret = read(fd, buf, sizeof(buf)); 484ce0d9371SArne Jansen if (ret == 0) 485ce0d9371SArne Jansen break; 486ce0d9371SArne Jansen if (ret == -1) { 487ce0d9371SArne Jansen fprintf(stderr, "failed to read input: %s\n", 488ce0d9371SArne Jansen strerror(errno)); 489ce0d9371SArne Jansen exit(1); 490ce0d9371SArne Jansen } 491ce0d9371SArne Jansen blen = ret; 492ce0d9371SArne Jansen ptr = 0; 493ce0d9371SArne Jansen } 494ce0d9371SArne Jansen if ((blen - ptr) < sizeof(ai)) { 495ce0d9371SArne Jansen fprintf(stderr, 496ce0d9371SArne Jansen "failed to read input: truncated file\n"); 497ce0d9371SArne Jansen exit(1); 498ce0d9371SArne Jansen } 499ce0d9371SArne Jansen memcpy(&ai, buf + ptr, sizeof(ai)); 500ce0d9371SArne Jansen ptr += sizeof(ai); 501ce0d9371SArne Jansen 502ce0d9371SArne Jansen search.arn_ar.ar_spa = ai.ai_spa; 503ce0d9371SArne Jansen search.arn_ar.ar_dva0 = ai.ai_dva.dva_word[0]; 504ce0d9371SArne Jansen search.arn_ar.ar_dva1 = ai.ai_dva.dva_word[1]; 505ce0d9371SArne Jansen search.arn_ar.ar_birth = ai.ai_birth; 506ce0d9371SArne Jansen 507ce0d9371SArne Jansen arn = avl_find(awr, &search, NULL); 508ce0d9371SArne Jansen if (arn) { 509ce0d9371SArne Jansen arn->arn_color = color; 510ce0d9371SArne Jansen arn->arn_flags = ai.ai_flags; 511ce0d9371SArne Jansen arn->arn_state = ai.ai_state; 512ce0d9371SArne Jansen } 513ce0d9371SArne Jansen } 514ce0d9371SArne Jansen close(fd); 515ce0d9371SArne Jansen } 516ce0d9371SArne Jansen 517ce0d9371SArne Jansen #define BUFSZ 1048576 /* 1MB */ 518ce0d9371SArne Jansen static void 519ce0d9371SArne Jansen get_arc(avl_tree_t *awr, uint64_t color, char *out_fn) 520ce0d9371SArne Jansen { 521ce0d9371SArne Jansen int ret; 522ce0d9371SArne Jansen int fd; 523ce0d9371SArne Jansen void *buf = malloc(BUFSZ); 524ce0d9371SArne Jansen zfs_cmd_t cmd = {0}; 525ce0d9371SArne Jansen arc_info_t *ai; 526ce0d9371SArne Jansen arc_info_hdr_t *aih; 527ce0d9371SArne Jansen int ofd = -1; 528ce0d9371SArne Jansen int hdr_written = 0; 529ce0d9371SArne Jansen char wbuf[16384]; 530ce0d9371SArne Jansen int wptr = 0; 531ce0d9371SArne Jansen 532ce0d9371SArne Jansen fd = open("/dev/zfs", O_RDWR); 533ce0d9371SArne Jansen if (fd == -1) { 534ce0d9371SArne Jansen fprintf(stderr, "failed to open /dev/zfs: %s\n", 535ce0d9371SArne Jansen strerror(errno)); 536ce0d9371SArne Jansen exit(1); 537ce0d9371SArne Jansen } 538ce0d9371SArne Jansen assert(buf); 539ce0d9371SArne Jansen cmd.zc_obj = 0; 540ce0d9371SArne Jansen cmd.zc_nvlist_dst = (uint64_t)buf; 541ce0d9371SArne Jansen cmd.zc_nvlist_dst_size = BUFSZ; 542ce0d9371SArne Jansen 543ce0d9371SArne Jansen if (out_fn != NULL) { 544ce0d9371SArne Jansen ofd = open(out_fn, O_CREAT | O_TRUNC | O_WRONLY, 0644); 545ce0d9371SArne Jansen if (ofd == -1) { 546ce0d9371SArne Jansen printf("cannot open output file %s: %s\n", 547ce0d9371SArne Jansen out_fn, strerror(errno)); 548ce0d9371SArne Jansen exit(1); 549ce0d9371SArne Jansen } 550ce0d9371SArne Jansen } 551ce0d9371SArne Jansen do { 552ce0d9371SArne Jansen int i; 553ce0d9371SArne Jansen 554ce0d9371SArne Jansen ret = ioctl(fd, ZFS_IOC_ARC_INFO, &cmd); 555ce0d9371SArne Jansen if (ret == -1) { 556ce0d9371SArne Jansen printf("ioctl failed with %d=%s\n", errno, 557ce0d9371SArne Jansen strerror(errno)); 558ce0d9371SArne Jansen exit(1); 559ce0d9371SArne Jansen } 560ce0d9371SArne Jansen aih = buf; 561ce0d9371SArne Jansen ai = buf + sizeof(aih); 562ce0d9371SArne Jansen if (ofd != -1 && !hdr_written) { 563ce0d9371SArne Jansen arc_content_hdr_t ach; 564ce0d9371SArne Jansen 565ce0d9371SArne Jansen memcpy(ach.ach_magic, ARCWATCH_CONTENT_MAGIC, 566ce0d9371SArne Jansen sizeof(ach.ach_magic)); 567ce0d9371SArne Jansen ach.ach_version = ARCWATCH_CONTENT_VERSION; 568ce0d9371SArne Jansen ach.ach_buckets = aih->aih_buckets; 569ce0d9371SArne Jansen ach.ach_buf_locks = aih->aih_buf_locks; 570ce0d9371SArne Jansen ret = write(ofd, &ach, sizeof(ach)); 571ce0d9371SArne Jansen if (ret == -1) { 572ce0d9371SArne Jansen printf("cannot write to output file: %s\n", 573ce0d9371SArne Jansen strerror(errno)); 574ce0d9371SArne Jansen exit(1); 575ce0d9371SArne Jansen } 576ce0d9371SArne Jansen hdr_written = 1; 577ce0d9371SArne Jansen } 578ce0d9371SArne Jansen for (i = 0; i < aih->aih_entries; ++i) { 579ce0d9371SArne Jansen ai = ((arc_info_t *)(aih + 1)) + i; 580ce0d9371SArne Jansen if (g_verbose) { 581*a1ff4d1fSSimon Klinkert printf("dva %016llx:%016llx birth %7d " 582ce0d9371SArne Jansen "spa %016llx " 583ce0d9371SArne Jansen "size % 8d flags %016x state %s\n", 584ce0d9371SArne Jansen ai->ai_dva.dva_word[0], 585ce0d9371SArne Jansen ai->ai_dva.dva_word[1], 586ce0d9371SArne Jansen ai->ai_birth, 587ce0d9371SArne Jansen ai->ai_spa, 588ce0d9371SArne Jansen ai->ai_size, 589ce0d9371SArne Jansen ai->ai_flags, 590ce0d9371SArne Jansen state2str(ai->ai_state)); 591ce0d9371SArne Jansen } 592ce0d9371SArne Jansen if (awr) { 593ce0d9371SArne Jansen arc_read_node_t search; 594ce0d9371SArne Jansen arc_read_node_t *arn; 595ce0d9371SArne Jansen 596ce0d9371SArne Jansen search.arn_ar.ar_spa = ai->ai_spa; 597ce0d9371SArne Jansen search.arn_ar.ar_dva0 = ai->ai_dva.dva_word[0]; 598ce0d9371SArne Jansen search.arn_ar.ar_dva1 = ai->ai_dva.dva_word[1]; 599ce0d9371SArne Jansen search.arn_ar.ar_birth = ai->ai_birth; 600ce0d9371SArne Jansen 601ce0d9371SArne Jansen arn = avl_find(awr, &search, NULL); 602ce0d9371SArne Jansen if (arn) { 603ce0d9371SArne Jansen arn->arn_color = color; 604ce0d9371SArne Jansen arn->arn_flags = ai->ai_flags; 605ce0d9371SArne Jansen arn->arn_state = ai->ai_state; 606ce0d9371SArne Jansen } 607ce0d9371SArne Jansen } 608ce0d9371SArne Jansen if (ofd != -1) { 609ce0d9371SArne Jansen if (wptr + sizeof(*ai) > sizeof(wbuf)) { 610ce0d9371SArne Jansen ret = write(ofd, wbuf, wptr); 611ce0d9371SArne Jansen if (ret == -1) { 612ce0d9371SArne Jansen printf("cannot write to output " 613ce0d9371SArne Jansen "file: %s\n", 614ce0d9371SArne Jansen strerror(errno)); 615ce0d9371SArne Jansen exit(1); 616ce0d9371SArne Jansen } 617ce0d9371SArne Jansen wptr = 0; 618ce0d9371SArne Jansen } 619ce0d9371SArne Jansen memcpy(wbuf + wptr, ai, sizeof(*ai)); 620ce0d9371SArne Jansen wptr += sizeof(*ai); 621ce0d9371SArne Jansen } 622ce0d9371SArne Jansen } 623ce0d9371SArne Jansen cmd.zc_obj = aih->aih_next; 624ce0d9371SArne Jansen } while (cmd.zc_obj != 0); 625ce0d9371SArne Jansen 626ce0d9371SArne Jansen if (wptr > 0) { 627ce0d9371SArne Jansen ret = write(ofd, wbuf, wptr); 628ce0d9371SArne Jansen if (ret == -1) { 629ce0d9371SArne Jansen printf("cannot write to output " 630ce0d9371SArne Jansen "file: %s\n", 631ce0d9371SArne Jansen strerror(errno)); 632ce0d9371SArne Jansen } 633ce0d9371SArne Jansen exit(1); 634ce0d9371SArne Jansen } 635ce0d9371SArne Jansen close(ofd); 636ce0d9371SArne Jansen free(buf); 637ce0d9371SArne Jansen } 638ce0d9371SArne Jansen 639ce0d9371SArne Jansen static void 640ce0d9371SArne Jansen awr_stat(avl_tree_t *awr, uint64_t color) 641ce0d9371SArne Jansen { 642ce0d9371SArne Jansen arc_read_node_t *arn = avl_first(awr); 643ce0d9371SArne Jansen uint64_t bufs_total = 0; 644ce0d9371SArne Jansen uint64_t bufs_in_l1 = 0; 645ce0d9371SArne Jansen uint64_t bufs_in_l1_ghost = 0; 646ce0d9371SArne Jansen uint64_t bufs_in_l2 = 0; 647ce0d9371SArne Jansen uint64_t bytes_total = 0; 648ce0d9371SArne Jansen uint64_t bytes_in_l1 = 0; 649ce0d9371SArne Jansen uint64_t bytes_in_l1_ghost = 0; 650ce0d9371SArne Jansen uint64_t bytes_in_l2 = 0; 651ce0d9371SArne Jansen 652ce0d9371SArne Jansen while (arn) { 653ce0d9371SArne Jansen arc_read_t *ar = &arn->arn_ar; 654ce0d9371SArne Jansen if (g_verbose) { 655ce0d9371SArne Jansen printf("dva %016llx:%016llx birth % 8d " 656ce0d9371SArne Jansen "spa %016llx size % 8d ", 657ce0d9371SArne Jansen ar->ar_dva0, 658ce0d9371SArne Jansen ar->ar_dva1, 659ce0d9371SArne Jansen ar->ar_birth, 660ce0d9371SArne Jansen ar->ar_spa, 661ce0d9371SArne Jansen ar->ar_size, 662ce0d9371SArne Jansen arn->arn_color); 663ce0d9371SArne Jansen if (arn->arn_color == color) 664ce0d9371SArne Jansen printf("flags %016x state %s\n", 665ce0d9371SArne Jansen arn->arn_flags, 666ce0d9371SArne Jansen state2str(arn->arn_state)); 667ce0d9371SArne Jansen else 668ce0d9371SArne Jansen printf("not in ARC\n"); 669ce0d9371SArne Jansen } 670ce0d9371SArne Jansen if (arn->arn_color == color) { 671ce0d9371SArne Jansen if (arn->arn_state == AIS_MRU || 672ce0d9371SArne Jansen arn->arn_state == AIS_MFU) { 673ce0d9371SArne Jansen ++bufs_in_l1; 674ce0d9371SArne Jansen bytes_in_l1 += ar->ar_size; 675ce0d9371SArne Jansen } else if (arn->arn_state == AIS_MRU_GHOST || 676ce0d9371SArne Jansen arn->arn_state == AIS_MFU_GHOST) { 677ce0d9371SArne Jansen ++bufs_in_l1_ghost; 678ce0d9371SArne Jansen bytes_in_l1_ghost =+ ar->ar_size; 679ce0d9371SArne Jansen } 680ce0d9371SArne Jansen if (arn->arn_flags & ARC_FLAG_HAS_L2HDR) { 681ce0d9371SArne Jansen ++bufs_in_l2; 682ce0d9371SArne Jansen bytes_in_l2 += ar->ar_size; 683ce0d9371SArne Jansen } 684ce0d9371SArne Jansen } 685ce0d9371SArne Jansen ++bufs_total; 686ce0d9371SArne Jansen bytes_total += ar->ar_size; 687ce0d9371SArne Jansen arn = AVL_NEXT(awr, arn); 688ce0d9371SArne Jansen } 689ce0d9371SArne Jansen if (g_verbose) { 690ce0d9371SArne Jansen printf("\n"); 691ce0d9371SArne Jansen } 692ce0d9371SArne Jansen printf(" | bufs | bytes\n"); 693ce0d9371SArne Jansen printf("---------+------------+-----------------\n"); 694ce0d9371SArne Jansen printf(" in l1 | % 10lld | %16lld\n", bufs_in_l1, bytes_in_l1); 695ce0d9371SArne Jansen printf("l1 ghost | % 10lld | %16lld\n", bufs_in_l1_ghost, 696ce0d9371SArne Jansen bytes_in_l1_ghost); 697ce0d9371SArne Jansen printf(" in l2 | % 10lld | %16lld\n", bufs_in_l2, bytes_in_l2); 698ce0d9371SArne Jansen printf(" total | % 10lld | %16lld\n", bufs_total, bytes_total); 699ce0d9371SArne Jansen printf("\n"); 700ce0d9371SArne Jansen } 701ce0d9371SArne Jansen 702ce0d9371SArne Jansen static void 703ce0d9371SArne Jansen usage(const char *basename) 704ce0d9371SArne Jansen { 705ce0d9371SArne Jansen (void) fprintf(stderr, 706ce0d9371SArne Jansen "Usage: %s -d [options]\n" 707ce0d9371SArne Jansen " %s {-c | -i} [options] [command [args]]\n\n" 708ce0d9371SArne Jansen "\tOptions:\n" 709ce0d9371SArne Jansen "\t -c run command and record read blocks\n" 710ce0d9371SArne Jansen "\t -i filename read previously recorded output from -o instead\n" 711ce0d9371SArne Jansen "\t of running a command\n" 712ce0d9371SArne Jansen "\t -b bufsize change tracing bufsize\n" 713ce0d9371SArne Jansen "\t -a dump arc\n" 714ce0d9371SArne Jansen "\t -v verbose\n" 715ce0d9371SArne Jansen "\t -w watch decay of buffers in arc\n" 716ce0d9371SArne Jansen "\t -d seconds watch interval\n" 717ce0d9371SArne Jansen "\t -o filename write output to file\n", 718ce0d9371SArne Jansen basename, basename); 719ce0d9371SArne Jansen exit(1); 720ce0d9371SArne Jansen } 721ce0d9371SArne Jansen 722ce0d9371SArne Jansen /* 723ce0d9371SArne Jansen * TODO: compare 2 traces 724ce0d9371SArne Jansen * TODO: compare 2 arc infos 725ce0d9371SArne Jansen * TODO: persistent spa numbering 726ce0d9371SArne Jansen */ 727ce0d9371SArne Jansen int 728ce0d9371SArne Jansen main(int argc, char **argv) 729ce0d9371SArne Jansen { 730ce0d9371SArne Jansen extern char *optarg; 731ce0d9371SArne Jansen extern int optind; 732ce0d9371SArne Jansen int c; 733ce0d9371SArne Jansen char *bufsize = "4m"; 734ce0d9371SArne Jansen int run_cmd = 0; 735ce0d9371SArne Jansen int watch = 0; 736ce0d9371SArne Jansen char *basename; 737ce0d9371SArne Jansen char *out_fn = NULL; 738ce0d9371SArne Jansen char *in_fn = NULL; 739ce0d9371SArne Jansen avl_tree_t awr; 740ce0d9371SArne Jansen uint64_t color = 0; 741ce0d9371SArne Jansen int interval = 10; 742ce0d9371SArne Jansen int dump_arc = 0; 743ce0d9371SArne Jansen char *arc_fn = NULL; 744ce0d9371SArne Jansen 745ce0d9371SArne Jansen avl_create(&awr, awr_cmp, sizeof(arc_read_node_t), 746ce0d9371SArne Jansen offsetof(arc_read_node_t, arn_node)); 747ce0d9371SArne Jansen basename = strrchr(argv[0], '/'); 748ce0d9371SArne Jansen if (basename == NULL) 749ce0d9371SArne Jansen basename = argv[0]; 750ce0d9371SArne Jansen 751ce0d9371SArne Jansen while ((c = getopt(argc, argv, "b:o:i:cvwhd:aI:")) != EOF) { 752ce0d9371SArne Jansen switch(c) { 753ce0d9371SArne Jansen case 'b': 754ce0d9371SArne Jansen bufsize = optarg; 755ce0d9371SArne Jansen break; 756ce0d9371SArne Jansen case 'c': 757ce0d9371SArne Jansen run_cmd = 1; 758ce0d9371SArne Jansen break; 759ce0d9371SArne Jansen case 'w': 760ce0d9371SArne Jansen watch = 1; 761ce0d9371SArne Jansen break; 762ce0d9371SArne Jansen case 'v': 763ce0d9371SArne Jansen ++g_verbose; 764ce0d9371SArne Jansen break; 765ce0d9371SArne Jansen case 'o': 766ce0d9371SArne Jansen out_fn = optarg; 767ce0d9371SArne Jansen break; 768ce0d9371SArne Jansen case 'i': 769ce0d9371SArne Jansen in_fn = optarg; 770ce0d9371SArne Jansen break; 771ce0d9371SArne Jansen case 'I': 772ce0d9371SArne Jansen arc_fn = optarg; 773ce0d9371SArne Jansen break; 774ce0d9371SArne Jansen case 'a': 775ce0d9371SArne Jansen dump_arc = 1; 776ce0d9371SArne Jansen break; 777ce0d9371SArne Jansen case 'd': 778ce0d9371SArne Jansen interval = atoi(optarg); 779ce0d9371SArne Jansen break; 780ce0d9371SArne Jansen case 'h': 781ce0d9371SArne Jansen default: 782ce0d9371SArne Jansen usage(basename); 783ce0d9371SArne Jansen } 784ce0d9371SArne Jansen } 785ce0d9371SArne Jansen 786ce0d9371SArne Jansen if (optind != argc && !run_cmd) { 787ce0d9371SArne Jansen fprintf(stderr, "command given without -c switch\n"); 788ce0d9371SArne Jansen exit(1); 789ce0d9371SArne Jansen } 790ce0d9371SArne Jansen if (dump_arc) { 791ce0d9371SArne Jansen get_arc(NULL, 0, out_fn); 792ce0d9371SArne Jansen exit(0); 793ce0d9371SArne Jansen } 794ce0d9371SArne Jansen if (arc_fn != NULL && !run_cmd && in_fn == NULL) { 795ce0d9371SArne Jansen fprintf(stderr, "-I given without -c and -i\n"); 796ce0d9371SArne Jansen exit(1); 797ce0d9371SArne Jansen } 798ce0d9371SArne Jansen if (arc_fn != NULL && watch) { 799ce0d9371SArne Jansen fprintf(stderr, "-I given with -w\n"); 800ce0d9371SArne Jansen exit(1); 801ce0d9371SArne Jansen } 802ce0d9371SArne Jansen if (run_cmd && (in_fn != NULL)) { 803ce0d9371SArne Jansen fprintf(stderr, "-i and -c are mutually exclusive\n"); 804ce0d9371SArne Jansen exit(1); 805ce0d9371SArne Jansen } 806ce0d9371SArne Jansen if (run_cmd) { 807ce0d9371SArne Jansen if (optind == argc) { 808ce0d9371SArne Jansen fprintf(stderr, "no command given\n"); 809ce0d9371SArne Jansen exit(1); 810ce0d9371SArne Jansen } 811ce0d9371SArne Jansen run_dtrace(bufsize, out_fn, &awr, argc - optind, argv + optind); 812ce0d9371SArne Jansen } 813ce0d9371SArne Jansen if (in_fn) 814ce0d9371SArne Jansen read_awr(&awr, in_fn); 815ce0d9371SArne Jansen if (watch) { 816ce0d9371SArne Jansen while (1) { 817ce0d9371SArne Jansen get_arc(&awr, ++color, NULL); 818ce0d9371SArne Jansen awr_stat(&awr, color); 819ce0d9371SArne Jansen sleep(10); 820ce0d9371SArne Jansen } 821ce0d9371SArne Jansen } 822ce0d9371SArne Jansen if (arc_fn) { 823ce0d9371SArne Jansen read_arc(&awr, arc_fn, 1); 824ce0d9371SArne Jansen awr_stat(&awr, 1); 825ce0d9371SArne Jansen } 826ce0d9371SArne Jansen 827ce0d9371SArne Jansen exit(0); 828ce0d9371SArne Jansen } 829