/* * _evnt_trace_flush * * Write out tracing info to trace file * * Input: * fio - file descriptor * evnt_info - structure containing event information (timings, etc) * * Output: * */ void _evnt_trace_flush(struct fdinfo *fio, struct evnt_f *evnt_info) { #if !defined(__mips) && !defined(_LITTLE_ENDIAN) int status; int pos_save; int trc_file_number; struct ffsw log_stat; int log_ubc = 0; if (evnt_info->file_ptr == NULL) return; trc_file_number = evnt_info->trc_file_number; pos_save = EVNT_XR_TELL(); if (evnt_info->need_parent_child) { char PROGRAM[] = "program"; char *parent; char *child; if (evnt_info->parent_name == NULL) _evnt_get_parent_child(fio, &evnt_info->parent_name, &evnt_info->child_name); parent = evnt_info->parent_name; child = evnt_info->child_name; sprintf(evnt_info->open_info.parent_child, "%s <-> %s", parent, child); status = EVNT_XR_SEEK(evnt_info->open_pos, SEEK_SET); status = EVNT_XR_WRITE(&evnt_info->open_info, 1, sizeof(struct evnt_open_info)); evnt_info->need_parent_child = FALSE; } EVNT_FLUSH_TRACE_INFO(trc_file_number); status = EVNT_XR_SEEK(pos_save, SEEK_SET); #endif }
/* * _evnt_open * * Open routine for "event" layer. * * Input: * name - name of file to open * oflags * mode * fio - ffio file descriptor * spec * stat - pointer to status return word * cbits * cblks * oinf * * Output: * Returns: pointer to fdinfo block from next lower layer on success. * -1 if an error occurred. */ _ffopen_t _evnt_open(const char *name, int oflags, mode_t mode, struct fdinfo *fio, union spec_u *spec, struct ffsw *stat, long cbits, int cblks, struct gl_o_inf *oinf) { _ffopen_t nextfio; int ret; union spec_u *nspec; int status; struct evnt_f *evnt_info; struct stat fstat; int trc_file_number = 0; rtc_t start_rtc, finish_rtc; struct ffsw log_stat; int log_ubc = 0; #if !defined(__mips) && !defined(_LITTLE_ENDIAN) int end_open_link = _evnt_OPEN_LINK; #elif defined(__mips) struct dioattr dio; #endif int isvalid; static int evnt_atexit_called = FALSE; struct EVNT_FILE_TRACE *trace_file; /* * post atexit so we can call it to close our * diagnostic and trace files */ if (evnt_atexit_called == FALSE) { evnt_atexit_called = TRUE; atexit(_evnt_atexit); } fio->lyr_info = NULL; /* set to NULL for the benefit of _evnt_clfree */ evnt_info = (struct evnt_f *) calloc(1, sizeof(struct evnt_f)); if (evnt_info == NULL) goto nomem; fio->lyr_info = (char *) evnt_info; /* * set default layer options in envt_info */ evnt_info->optflags.diag = TRUE; /* default is full diagnostics*/ evnt_info->optflags.full_diag = TRUE; /* default is full diagnostics*/ evnt_info->optflags.summary = FALSE; evnt_info->optflags.brief = FALSE; evnt_info->optflags.trace = FALSE; evnt_info->optflags.rtc = RTC_MODE;/* use rtc by default */ evnt_info->optflags.k = FALSE; evnt_info->optflags.m = FALSE; evnt_info->optflags.g = FALSE; evnt_info->optflags.bytes = TRUE; /* default units */ evnt_info->optflags.words = FALSE; evnt_info->optflags.blocks = FALSE; evnt_info->do_zeros = TRUE; /* zero fill diag fields by default */ evnt_info->extend_trackers_failed = FALSE; /* * malloc space for async tracker structures */ if ((evnt_info->async_tracker = _evnt_add_trackers(NUM_TRACKERS)) == NULL) goto nomem; evnt_info->num_async_trackers = NUM_TRACKERS; /* * pick up user requested options - * get values from the FFIO spec */ _evnt_getopts(evnt_info, spec); /* * open diagnostics file */ if (evnt_info->optflags.diag == TRUE) { if(_evnt_open_log_file(evnt_info) == ERR) { goto badret; } else { if (_GL_ffio_logptr != NULL) _GL_evnt_logptr = _GL_ffio_logptr; else _GL_evnt_logptr = stderr; } } /* * open trace file if we're tracing */ #if !defined(__mips) && !defined(_LITTLE_ENDIAN) if (evnt_info->optflags.trace == TRUE) { trc_file_number = _ff_nparm_getv(spec, 1, &isvalid); /* * check for valid file number - issue message to stats file */ if (evnt_info->optflags.diag == TRUE && trc_file_number < 0 || trc_file_number > 9) { fprintf(_GL_evnt_logptr, "Invalid trace file number specified: %d. Valid numbers are 0-9.\n ffio.trace will be used\n", trc_file_number); trc_file_number = 0; } evnt_info->trc_file_number = trc_file_number; trace_file = &(_GL_evnt_trc_file[trc_file_number]); if (_evnt_open_trace_file(fio, name, evnt_info) == ERR) goto badret; } #endif #ifdef EVNT_DEBUG fprintf(stderr,"event layer options:\n"); fprintf(stderr, "diagnostics: diag = %d, full_diag = %d, summary = %d, brief = %d\n", evnt_info->optflags.diag, evnt_info->optflags.full_diag, evnt_info->optflags.summary, evnt_info->optflags.brief); fprintf(stderr,"tracing: trace = %d\n", evnt_info->optflags.trace); fprintf(stderr,"trc_file_number = %d\n", trc_file_number); fprintf(stderr,"clock: rtc = %d\n", evnt_info->optflags.rtc); fprintf(stderr,"units: bytes = %d, words = %d, blocks = %d\n", evnt_info->optflags.bytes, evnt_info->optflags.words, evnt_info->optflags.blocks); fprintf(stderr,"size: k = %d, m = %d, g = %d\n", evnt_info->optflags.k, evnt_info->optflags.m, evnt_info->optflags.g); #endif /* * initialize minimums to large values for diagnostics */ if (evnt_info->optflags.diag) { long bigmin; if (sizeof(size_t) == sizeof(long)){ bigmin = LONG_MAX; } else { bigmin = INT_MAX; } evnt_info->listio_write.min = bigmin; evnt_info->listio_writea.min = bigmin; evnt_info->listio_read.min = bigmin; evnt_info->listio_reada.min = bigmin; evnt_info->write.min = bigmin; evnt_info->writea.min = bigmin; evnt_info->read.min = bigmin; evnt_info->reada.min = bigmin; strncpy(evnt_info->name, name, NAMLEN); } /* * Get the FFIO spec for the next lower layer. */ nspec = spec; NEXT_SPEC(nspec); /* * Open the layers below this one. */ #if !defined(__mips) && !defined(_LITTLE_ENDIAN) if (evnt_info->optflags.trace == TRUE) trace_file->open_level_count++; #endif start_rtc = RTC(); nextfio = _ffopen(name, oflags, mode, nspec, stat, cbits, cblks, NULL, oinf); finish_rtc = RTC(); #if !defined(__mips) && !defined(_LITTLE_ENDIAN) if (evnt_info->optflags.trace == TRUE) trace_file->open_level_count--; #endif evnt_info->open_time = finish_rtc - start_rtc; if (nextfio == _FFOPEN_ERR) goto badret; if (1) { struct fdinfo *nfioptr; nfioptr = (struct fdinfo *) nextfio; ret = XRCALL(nfioptr, fcntlrtn) nfioptr, FC_STAT, &fstat, stat); if (oflags & O_TRUNC) evnt_info->cur_size = 0; else evnt_info->cur_size = fstat.st_size; if (oflags & O_APPEND) evnt_info->cur_pos = evnt_info->cur_size; else evnt_info->cur_pos = 0; #ifdef __mips ret = XRCALL(nfioptr, fcntlrtn) nfioptr, FC_DIOINFO, &dio, stat); if (ret == ERR)evnt_info->odirect = 0; else { evnt_info->odirect = 1; evnt_info->miniosize = dio.d_miniosz; evnt_info->chunksize = dio.d_miniosz; evnt_info->diskalign = dio.d_miniosz; evnt_info->maxiosize = dio.d_maxiosz; evnt_info->memalign = dio.d_mem; } #endif evnt_info->max_size = evnt_info->cur_size; evnt_info->oflags = oflags; evnt_info->cbits = cbits; evnt_info->cblks = cblks; #ifdef DO_WE_WANT_FAKE_SDS if (get out of * oinf) { evnt_info->fake_sds = TRUE; evnt_info->sector_mask = 4095; } else { evnt_info->fake_sds = FALSE; evnt_info->sector_mask = fstat.st_blksize - 1; } #endif /* we're not monitoring ssreads yet */ evnt_info->fake_sds = FALSE; evnt_info->sector_mask = fstat.st_blksize - 1; } /* * write some initial information to the trace file */ #if !defined(__mips) && !defined(_LITTLE_ENDIAN) if (evnt_info->optflags.trace) { if (trace_file->ptr) { struct evnt_open_info *open_info; int next_open_link; open_info = &(evnt_info->open_info); evnt_info->fd = (trace_file->file_info.open_count) << 48; open_info->fd = _evnt_OPEN | evnt_info->fd; open_info->oflags = oflags; open_info->mode = mode; strncpy(open_info->name, name, 80); open_info->name[79] = 0; open_info->open_size = evnt_info->cur_size; open_info->rtc_14 = RTC(); open_info->rtc_15 = RTC(); open_info->nextfio = nextfio; strcpy(open_info->parent_child, "??? <-> ???"); open_info->next_open_pos = 'UNUSED'; open_info->max_size = evnt_info->max_size; open_info->close_rtc = 0; open_info->event_count = 0; open_info->start_rtc = start_rtc; open_info->finish_rtc = finish_rtc; open_info->d_nextfio = nextfio; next_open_link = EVNT_XR_TELL(); evnt_info->open_pos = next_open_link + 8; if (trace_file->program_info.open_count == 0) trace_file->program_info.first_open_pos = next_open_link; if (trace_file->file_info.open_count == 0) { trace_file->file_info.first_open_pos = next_open_link; } else { long link_word; status = EVNT_XR_SEEK(trace_file->file_info.last_open_link, SEEK_SET); link_word = _evnt_OPEN_LINK | next_open_link; status = EVNT_XR_WRITE(&link_word, 8, 1); status = EVNT_XR_SEEK(0, SEEK_END); } trace_file->file_info.last_open_link = next_open_link; status = EVNT_XR_WRITE(&end_open_link, 1, sizeof(int)); status = EVNT_XR_WRITE(open_info, 1, sizeof(struct evnt_open_info)); } evnt_info->logged_count = &(_GL_evnt_trc_file[evnt_info->trc_file_number].program_info.event_count); trace_file->file_info.open_count++; trace_file->program_info.open_count++; EVNT_TRACE_SIZE; INC_GLOBAL_LOG_COUNT(open); _evnt_trace_flush(fio, evnt_info); evnt_info->need_parent_child = TRUE; } #endif evnt_info->counts.size_changes = 0; evnt_info->counts.open = 1; evnt_info->counts.total = 1; return (nextfio); nomem: badret: _evnt_clfree(fio); return (_FFOPEN_ERR); }
/* * _evnt_reada * * Log a reada request * * Input: * fio - ffio file descriptor * bufptr - bit pointer to where data is to go * nbytes - number of bytes to be read * stat - pointer to status return word * fulp - full or partial read mode flag * ubcp - pointer to unused bit count. On return, * *ubcp is updated to contain the unused bit * count in the data returned. * * Output: * ret - return value from readartn * */ ssize_t _evnt_reada(struct fdinfo *fio, bitptr bufptr, size_t nbytes, struct ffsw *stat, int fulp, int *ubcp) { struct fdinfo *llfio; struct evnt_f *evnt_info; int status; rtc_t start_rtc, finish_rtc; struct ffsw log_stat; int log_ubc = 0; ssize_t ret; ssize_t orig_ret; struct evnt_async_tracker *this_tracker; evnt_info = (struct evnt_f *) fio->lyr_info; llfio = fio->fioptr; EVNT_UPDATE(reada); if (evnt_info->optflags.diag || evnt_info->optflags.trace) this_tracker = _evnt_get_tracker(evnt_info, stat, TRACKER_READA, nbytes); start_rtc = RTC(); orig_ret = XRCALL(llfio, readartn) llfio, bufptr, nbytes, stat, fulp, ubcp); finish_rtc = RTC(); if (stat->sw_stat != 0 && stat->sw_flag != 0) ret = stat->sw_count; else ret = 0; evnt_info->cur_pos += nbytes; if (evnt_info->cur_pos > evnt_info->cur_size) evnt_info->cur_pos = evnt_info->cur_size; EVNT_CHECK_SIZE; if (evnt_info->optflags.diag) evnt_info->reada.time += (finish_rtc - start_rtc); #if !defined(__mips) && !defined(_LITTLE_ENDIAN) if (evnt_info->optflags.trace) { int record[8]; EVNT_LOCK_ON; record[0] = (_evnt_READA | evnt_info->fd) | nbytes; record[1] = (int) stat; record[2] = start_rtc; record[3] = finish_rtc; record[4] = ret; record[5] = record[6] = record[7] = 0; status = EVNT_XR_WRITE(record, sizeof(int), 8); if (this_tracker) this_tracker->logpos = EVNT_XR_TELL() - sizeof(int)*3; INC_GLOBAL_LOG_COUNT(reada); EVNT_LOCK_OFF; } #endif evnt_info->counts.total++; evnt_info->counts.reada++; if (this_tracker && (stat->sw_stat != 0 && stat->sw_flag != 0)) { evnt_info->reada.sync++; evnt_info->reada.delivered += stat->sw_count; evnt_info->reada.current--; this_tracker->mode = TRACKER_FREE; this_tracker->stat = NULL; this_tracker->logpos = 0; } return (orig_ret); }