/* * _evnt_weod * * Log an EOD write operation * * Input: * fio - ffio file descriptor * stat - pointer to status return word * * Output: * ret - return value from weodrtn * */ int _evnt_weod(struct fdinfo *fio, struct ffsw *stat) { struct fdinfo *llfio; struct evnt_f *evnt_info; int status; rtc_t start_rtc, finish_rtc; struct ffsw log_stat; int log_ubc = 0; int ret; evnt_info = (struct evnt_f *) fio->lyr_info; llfio = fio->fioptr; start_rtc = RTC(); ret = XRCALL(llfio, weodrtn) llfio, stat); finish_rtc = RTC(); #ifdef __mips if (!(evnt_info->odirect) || (evnt_info->cur_pos % evnt_info->diskalign != 0)) #else if (evnt_info->cur_pos & evnt_info->sector_mask) #endif evnt_info->ill_formed_weod++; #if !defined(__mips) && !defined(_LITTLE_ENDIAN) if (evnt_info->optflags.trace) { int record[4]; EVNT_LOCK_ON; record[0] = _evnt_WEOD | evnt_info->fd; record[1] = start_rtc; record[2] = finish_rtc; record[3] = ret; status = EVNT_XR_WRITE(record, sizeof(int), 4); INC_GLOBAL_LOG_COUNT(weod); EVNT_LOCK_OFF; } #endif _GL_evnt_trc_file[evnt_info->trc_file_number].cur_usage -= (evnt_info->cur_size - evnt_info->cur_pos); evnt_info->cur_size = evnt_info->cur_pos; EVNT_TRACE_SIZE; evnt_info->counts.weod++; evnt_info->counts.total++; return (ret); }
/* * _evnt_write * * Log a write request * * Input: * fio - ffio file descriptor * bufptr - bit pointer to where data is to go * nbytes - number of bytes to be written * stat - pointer to status return word * fulp - full or partial write mode flag * ubcp - pointer to unused bit count. On return, * *ubcp is updated to contain the unused bit * count in the data returned. * * Output: * The number of bytes transferred is returned upon successful completion. * if an error occurs, -1 is returned. * * The stat->sw_stat field is set to FFCNT upon normal return. * */ ssize_t _evnt_write(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; ssize_t ret; struct ffsw log_stat; int log_ubc = 0; evnt_info = (struct evnt_f *) fio->lyr_info; llfio = fio->fioptr; EVNT_UPDATE(write); start_rtc = RTC(); ret = XRCALL(llfio, writertn) llfio, bufptr, nbytes, stat, fulp, ubcp); finish_rtc = RTC(); evnt_info->cur_pos += nbytes; EVNT_CHECK_SIZE; #if !defined(__mips) && !defined(_LITTLE_ENDIAN) if (evnt_info->optflags.trace) { int record[4]; EVNT_LOCK_ON; record[0] = (_evnt_WRITE | evnt_info->fd) | nbytes; record[1] = start_rtc; record[2] = finish_rtc; record[3] = ret; status = EVNT_XR_WRITE(record, sizeof(int), 4); INC_GLOBAL_LOG_COUNT(write); EVNT_LOCK_OFF; } #endif evnt_info->counts.total++; evnt_info->counts.write++; evnt_info->write.delivered += ret; evnt_info->write.time += (finish_rtc - start_rtc); return (ret); }
/* * _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_bksp * * Time backspace request * * Input: * fio - ffio file descriptor * stat - pointer to status return word * * Output: * ret - return value from backrtn * */ int _evnt_bksp(struct fdinfo *fio, struct ffsw *stat) { struct fdinfo *llfio; struct evnt_f *evnt_info; int status; rtc_t start_rtc, finish_rtc; struct ffsw log_stat; int log_ubc = 0; int ret; evnt_info = (struct evnt_f *) fio->lyr_info; llfio = fio->fioptr; start_rtc = RTC(); ret = XRCALL(llfio, backrtn) llfio, stat); finish_rtc = RTC(); #if !defined(__mips) && !defined(_LITTLE_ENDIAN) if (evnt_info->optflags.trace) { int record[4]; EVNT_LOCK_ON; record[0] = (_evnt_BKSP | evnt_info->fd); record[1] = start_rtc; record[2] = finish_rtc; record[3] = ret; status = EVNT_XR_WRITE(record, sizeof(int), 4); INC_GLOBAL_LOG_COUNT(bksp); EVNT_LOCK_OFF; } #endif evnt_info->counts.bksp++; evnt_info->counts.total++; return (ret); }
/* * _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_open_trace_file * * Open file that we'll put tracing info in * * Input: * fio - ffio file descriptor * name - name of file we're monitoring * evnt_info - structure containing event information (timings, etc) * * Output: * Returns: ERR if open unsuccessful * 0 if successful */ _evnt_open_trace_file( struct fdinfo *fio, const char *name, struct evnt_f *evnt_info) { char file_name[128]; char *name_ptr; int trc_file_number; struct ffsw open_ffsw; int status; int append; int oflags; long program_keyword; struct ffsw log_stat; int log_ubc = 0; struct EVNT_FILE_TRACE *trace_file; trc_file_number = evnt_info->trc_file_number; trace_file = &(_GL_evnt_trc_file[trc_file_number]); #if !defined(__mips) && !defined(_LITTLE_ENDIAN) if (evnt_info->optflags.trace) { if (trace_file->ptr == NULL) { long start_rtc; double rtc_factor; file_name[0] = 0; if (trace_file->being_opened) { if (_GL_evnt_logptr) { fprintf(_GL_evnt_logptr, "Attempting to use same event.fil_num=%d for events file %s\n", trc_file_number, name); } return (ERR); } if ((name_ptr = getenv("FF_IO_TRACE_FILE")) != NULL) { strcpy(file_name, name_ptr); } else { strcpy(file_name, "ffio.trace"); } if (trc_file_number > 0) { char digits[8]; sprintf(digits, ".%d", trc_file_number); strcat(file_name, digits); } name_ptr = file_name; append = FALSE; if (*name_ptr == '+') { append = TRUE; name_ptr++; } start_rtc = RTC(); rtc_factor = RTC_FACTOR; trace_file->cur_usage = 0; trace_file->max_usage = 0; strncpy(trace_file->file_info.magic, EVNT_MAGIC_STRING, 7); strncpy(trace_file->file_info.version, "7.1BF2", 7); trace_file->file_info.start_rtc = start_rtc; trace_file->file_info.rtc_factor = rtc_factor; trace_file->file_info.event_count = 0; trace_file->file_info.open_count = 0; trace_file->file_info.program_count = 0; trace_file->file_info.reserve_1 = 'f_rsv_1'; trace_file->file_info.reserve_2 = 'f_rsv_2'; trace_file->file_info.reserve_3 = 'f_rsv_3'; trace_file->file_info.reserve_4 = 'f_rsv_4'; /* * set program_keyword so we can tell if we have valid * trace file or not when running iox */ program_keyword = ((_evnt_PROGRAM_START) | (sizeof(struct EVNT_PROGRAM_INFO) - 8)); trace_file->program_info.keyword = program_keyword; trace_file->program_info.next_program_info_pos = 0; trace_file->program_info.start_rtc = start_rtc; trace_file->program_info.exit_rtc = start_rtc; trace_file->program_info.event_count = 0; trace_file->program_info.open_count = 0; trace_file->program_info.reserve_1 = 'p_rsv_1'; trace_file->program_info.reserve_2 = 'p_rsv_2'; trace_file->program_info.reserve_3 = 'p_rsv_3'; trace_file->program_info.reserve_4 = 'p_rsv_4'; strcpy(trace_file->program_info.name, _argv[0]); try_again: if (append) { oflags = O_RDWR; trace_file->being_opened = TRUE; evnt_info->file_ptr = EVNT_XR_OPEN(name_ptr); trace_file->being_opened = FALSE; if (evnt_info->file_ptr <= NULL) { /* * file did not exist, lets just open * it non-append */ evnt_info->file_ptr = NULL; append = FALSE; goto try_again; } trace_file->ptr = evnt_info->file_ptr; /* * check for valid trace file to * append to (close if not valid) */ if (_evnt_restart_trace_file(evnt_info->file_ptr, trc_file_number, name_ptr) == FALSE) { status = EVNT_XR_CLOSE(); trace_file->ptr = NULL; evnt_info->file_ptr = NULL; } } else { oflags = O_RDWR | O_CREAT | O_TRUNC; trace_file->being_opened = TRUE; evnt_info->file_ptr = EVNT_XR_OPEN(name_ptr); trace_file->being_opened = FALSE; } trace_file->ptr = evnt_info->file_ptr; if ((int) evnt_info->file_ptr <= 0) { evnt_info->file_ptr = NULL; evnt_info->optflags.trace = FALSE; if (_GL_evnt_logptr) { fprintf(_GL_evnt_logptr, "Unable to open event trace file %s\n", name_ptr); } } trace_file->ptr = evnt_info->file_ptr; trace_file->file_info.program_count++; trace_file->file_info_pos = 0; EVNT_WRITE_FILE_INFO(trc_file_number); trace_file->program_info_pos = EVNT_XR_SEEK(0, SEEK_END); if (trace_file->file_info.program_count == 1) { /* update the first word in file_info */ trace_file->file_info.first_program_pos = trace_file->program_info_pos; } else { /* update the link word in the last program_info */ status = EVNT_XR_SEEK(trace_file->file_info.last_program_link, SEEK_SET); status = EVNT_XR_WRITE(&(trace_file->program_info_pos), sizeof(int), 1); } trace_file->file_info.last_program_link = trace_file->program_info_pos + 8; EVNT_WRITE_PROGRAM_INFO(trc_file_number); } else { evnt_info->file_ptr = trace_file->ptr; } } #endif return (0); }
/* * _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); }