rf_acctrace.c revision 1.1 1 /* $NetBSD: rf_acctrace.c,v 1.1 1998/11/13 04:20:26 oster Exp $ */
2 /*
3 * Copyright (c) 1995 Carnegie-Mellon University.
4 * All rights reserved.
5 *
6 * Author: Mark Holland
7 *
8 * Permission to use, copy, modify and distribute this software and
9 * its documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
13 *
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
16 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
27 */
28
29 /*****************************************************************************
30 *
31 * acctrace.c -- code to support collecting information about each access
32 *
33 *****************************************************************************/
34
35 /* :
36 * Log: rf_acctrace.c,v
37 * Revision 1.29 1996/07/27 23:36:08 jimz
38 * Solaris port of simulator
39 *
40 * Revision 1.28 1996/07/17 21:00:58 jimz
41 * clean up timer interface, tracing
42 *
43 * Revision 1.27 1996/06/14 14:35:24 jimz
44 * clean up dfstrace protection
45 *
46 * Revision 1.26 1996/06/13 19:09:04 jimz
47 * remove trace.dat file before beginning
48 *
49 * Revision 1.25 1996/06/12 04:41:26 jimz
50 * tweaks to make genplot work with user-level driver
51 * (mainly change stat collection)
52 *
53 * Revision 1.24 1996/06/10 11:55:47 jimz
54 * Straightened out some per-array/not-per-array distinctions, fixed
55 * a couple bugs related to confusion. Added shutdown lists. Removed
56 * layout shutdown function (now subsumed by shutdown lists).
57 *
58 * Revision 1.23 1996/06/09 02:36:46 jimz
59 * lots of little crufty cleanup- fixup whitespace
60 * issues, comment #ifdefs, improve typing in some
61 * places (esp size-related)
62 *
63 * Revision 1.22 1996/06/05 18:06:02 jimz
64 * Major code cleanup. The Great Renaming is now done.
65 * Better modularity. Better typing. Fixed a bunch of
66 * synchronization bugs. Made a lot of global stuff
67 * per-desc or per-array. Removed dead code.
68 *
69 * Revision 1.21 1996/05/31 22:26:54 jimz
70 * fix a lot of mapping problems, memory allocation problems
71 * found some weird lock issues, fixed 'em
72 * more code cleanup
73 *
74 * Revision 1.20 1996/05/30 23:22:16 jimz
75 * bugfixes of serialization, timing problems
76 * more cleanup
77 *
78 * Revision 1.19 1996/05/30 12:59:18 jimz
79 * make etimer happier, more portable
80 *
81 * Revision 1.18 1996/05/27 18:56:37 jimz
82 * more code cleanup
83 * better typing
84 * compiles in all 3 environments
85 *
86 * Revision 1.17 1996/05/23 00:33:23 jimz
87 * code cleanup: move all debug decls to rf_options.c, all extern
88 * debug decls to rf_options.h, all debug vars preceded by rf_
89 *
90 * Revision 1.16 1996/05/20 16:15:49 jimz
91 * switch to rf_{mutex,cond}_{init,destroy}
92 *
93 * Revision 1.15 1996/05/18 20:10:00 jimz
94 * bit of cleanup to compile cleanly in kernel, once again
95 *
96 * Revision 1.14 1996/05/18 19:51:34 jimz
97 * major code cleanup- fix syntax, make some types consistent,
98 * add prototypes, clean out dead code, et cetera
99 *
100 * Revision 1.13 1995/11/30 16:26:43 wvcii
101 * added copyright info
102 *
103 */
104
105 #ifdef _KERNEL
106 #define KERNEL
107 #endif
108
109 #include "rf_threadstuff.h"
110 #include "rf_types.h"
111 #include <sys/stat.h>
112 #include <sys/types.h>
113
114 #ifdef KERNEL
115 #ifndef __NetBSD__
116 #include <dfstrace.h>
117 #endif /* !__NetBSD__ */
118 #if DFSTRACE > 0
119 #include <sys/dfs_log.h>
120 #include <sys/dfstracebuf.h>
121 #endif /* DFSTRACE > 0 */
122 #endif /* KERNEL */
123
124 #include "rf_debugMem.h"
125 #include "rf_acctrace.h"
126 #include "rf_general.h"
127 #include "rf_raid.h"
128 #include "rf_etimer.h"
129 #include "rf_hist.h"
130 #include "rf_shutdown.h"
131 #include "rf_sys.h"
132
133 static long numTracesSoFar;
134 static int accessTraceBufCount = 0;
135 static RF_AccTraceEntry_t *access_tracebuf;
136 static long traceCount;
137
138 int rf_stopCollectingTraces;
139 RF_DECLARE_MUTEX(rf_tracing_mutex)
140 int rf_trace_fd;
141
142 static void rf_ShutdownAccessTrace(void *);
143
144 static void rf_ShutdownAccessTrace(ignored)
145 void *ignored;
146 {
147 if (rf_accessTraceBufSize) {
148 if (accessTraceBufCount) rf_FlushAccessTraceBuf();
149 #ifndef KERNEL
150 close(rf_trace_fd);
151 #endif /* !KERNEL */
152 RF_Free(access_tracebuf, rf_accessTraceBufSize * sizeof(RF_AccTraceEntry_t));
153 }
154 rf_mutex_destroy(&rf_tracing_mutex);
155 #if defined(KERNEL) && DFSTRACE > 0
156 printf("RAIDFRAME: %d trace entries were sent to dfstrace\n",traceCount);
157 #endif /* KERNEL && DFSTRACE > 0 */
158 }
159
160 int rf_ConfigureAccessTrace(listp)
161 RF_ShutdownList_t **listp;
162 {
163 int rc;
164
165 numTracesSoFar = accessTraceBufCount = rf_stopCollectingTraces = 0;
166 if (rf_accessTraceBufSize) {
167 RF_Malloc(access_tracebuf, rf_accessTraceBufSize * sizeof(RF_AccTraceEntry_t), (RF_AccTraceEntry_t *));
168 accessTraceBufCount = 0;
169 #ifndef KERNEL
170 rc = unlink("trace.dat");
171 if (rc && (errno != ENOENT)) {
172 perror("unlink");
173 RF_ERRORMSG("Unable to remove existing trace.dat\n");
174 return(errno);
175 }
176 if ((rf_trace_fd = open("trace.dat",O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0 ) {
177 perror("Unable to open trace.dat for output");
178 return(errno);
179 }
180 #endif /* !KERNEL */
181 }
182 traceCount = 0;
183 numTracesSoFar = 0;
184 rc = rf_mutex_init(&rf_tracing_mutex);
185 if (rc) {
186 RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__,
187 __LINE__, rc);
188 }
189 rc = rf_ShutdownCreate(listp, rf_ShutdownAccessTrace, NULL);
190 if (rc) {
191 RF_ERRORMSG3("Unable to add to shutdown list file %s line %d rc=%d\n", __FILE__,
192 __LINE__, rc);
193 if (rf_accessTraceBufSize) {
194 RF_Free(access_tracebuf, rf_accessTraceBufSize * sizeof(RF_AccTraceEntry_t));
195 #ifndef KERNEL
196 close(rf_trace_fd);
197 #endif /* !KERNEL */
198 rf_mutex_destroy(&rf_tracing_mutex);
199 }
200 }
201 return(rc);
202 }
203
204 /* install a trace record. cause a flush to disk or to the trace collector daemon
205 * if the trace buffer is at least 1/2 full.
206 */
207 void rf_LogTraceRec(raid, rec)
208 RF_Raid_t *raid;
209 RF_AccTraceEntry_t *rec;
210 {
211 RF_AccTotals_t *acc = &raid->acc_totals;
212 #if 0
213 RF_Etimer_t timer;
214 int i, n;
215 #endif
216
217 if (rf_stopCollectingTraces || ((rf_maxNumTraces >= 0) && (numTracesSoFar >= rf_maxNumTraces)))
218 return;
219
220 #ifndef KERNEL
221 if (rf_accessTraceBufSize) {
222 RF_LOCK_MUTEX(rf_tracing_mutex);
223 numTracesSoFar++;
224 bcopy((char *)rec, (char *)&access_tracebuf[ accessTraceBufCount++ ], sizeof(RF_AccTraceEntry_t));
225 if (accessTraceBufCount == rf_accessTraceBufSize)
226 rf_FlushAccessTraceBuf();
227 RF_UNLOCK_MUTEX(rf_tracing_mutex);
228 }
229 #endif /* !KERNEL */
230 #if defined(KERNEL) && DFSTRACE > 0
231 rec->index = traceCount++;
232 if (traceon & DFS_TRACE_RAIDFRAME) {
233 dfs_log(DFS_NOTE, (char *) rec, (int) sizeof(*rec), 0);
234 }
235 #endif /* KERNEL && DFSTRACE > 0 */
236 /* update AccTotals for this device */
237 if (!raid->keep_acc_totals)
238 return;
239 acc->num_log_ents++;
240 if (rec->reconacc) {
241 acc->recon_start_to_fetch_us += rec->specific.recon.recon_start_to_fetch_us;
242 acc->recon_fetch_to_return_us += rec->specific.recon.recon_fetch_to_return_us;
243 acc->recon_return_to_submit_us += rec->specific.recon.recon_return_to_submit_us;
244 acc->recon_num_phys_ios += rec->num_phys_ios;
245 acc->recon_phys_io_us += rec->phys_io_us;
246 acc->recon_diskwait_us += rec->diskwait_us;
247 acc->recon_reccount++;
248 }
249 else {
250 RF_HIST_ADD(acc->tot_hist, rec->total_us);
251 RF_HIST_ADD(acc->dw_hist, rec->diskwait_us);
252 /* count of physical ios which are too big. often due to thermal recalibration */
253 /* if bigvals > 0, you should probably ignore this data set */
254 if (rec->diskwait_us > 100000)
255 acc->bigvals++;
256 acc->total_us += rec->total_us;
257 acc->suspend_ovhd_us += rec->specific.user.suspend_ovhd_us;
258 acc->map_us += rec->specific.user.map_us;
259 acc->lock_us += rec->specific.user.lock_us;
260 acc->dag_create_us += rec->specific.user.dag_create_us;
261 acc->dag_retry_us += rec->specific.user.dag_retry_us;
262 acc->exec_us += rec->specific.user.exec_us;
263 acc->cleanup_us += rec->specific.user.cleanup_us;
264 acc->exec_engine_us += rec->specific.user.exec_engine_us;
265 acc->xor_us += rec->xor_us;
266 acc->q_us += rec->q_us;
267 acc->plog_us += rec->plog_us;
268 acc->diskqueue_us += rec->diskqueue_us;
269 acc->diskwait_us += rec->diskwait_us;
270 acc->num_phys_ios += rec->num_phys_ios;
271 acc->phys_io_us = rec->phys_io_us;
272 acc->user_reccount++;
273 }
274 }
275
276
277 /* assumes the tracing mutex is locked at entry. In order to allow this to be called
278 * from interrupt context, we don't do any copyouts here, but rather just wake trace
279 * buffer collector thread.
280 */
281 void rf_FlushAccessTraceBuf()
282 {
283 #ifndef KERNEL
284 int size = accessTraceBufCount * sizeof(RF_AccTraceEntry_t);
285
286 if (write(rf_trace_fd, (char *) access_tracebuf, size) < size ) {
287 fprintf(stderr, "Unable to write traces to file. tracing disabled\n");
288 RF_Free(access_tracebuf, rf_accessTraceBufSize * sizeof(RF_AccTraceEntry_t));
289 rf_accessTraceBufSize = 0;
290 close(rf_trace_fd);
291 }
292 #endif /* !KERNEL */
293 accessTraceBufCount = 0;
294 }
295