1 /* @(#)rand_rw.c 1.27 18/02/19 Copyright 1993-2018 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)rand_rw.c 1.27 18/02/19 Copyright 1993-2018 J. Schilling";
6 #endif
7 /*
8 * Copyright (c) 1993-2018 J. Schilling
9 */
10 /*
11 * The contents of this file are subject to the terms of the
12 * Common Development and Distribution License, Version 1.0 only
13 * (the "License"). You may not use this file except in compliance
14 * with the License.
15 *
16 * See the file CDDL.Schily.txt in this distribution for details.
17 * A copy of the CDDL is also available via the Internet at
18 * http://www.opensource.org/licenses/cddl1.txt
19 *
20 * When distributing Covered Code, include this CDDL HEADER in each
21 * file and include the License file CDDL.Schily.txt from this distribution.
22 */
23
24 #include <schily/param.h> /* Include various defs needed with some OS */
25 #include <schily/stdio.h>
26 #include <schily/standard.h>
27 #include <schily/stdlib.h>
28 #include <schily/time.h>
29 #include <schily/signal.h>
30 #include <schily/schily.h>
31 #include <scg/scgcmd.h>
32 #include <scg/scsireg.h>
33 #include <scg/scsidefs.h>
34 #include <scg/scsitransp.h>
35
36 #include "scsicmds.h"
37
38 #include "fmt.h"
39 #include "rand_rw.h"
40
41 #undef min
42 #define min(a, b) ((a) < (b) ? (a) : (b))
43 #define MAXBAD (127)
44
45 extern long RW;
46 extern int debug;
47
48 struct bb_list *bad_blocks;
49
50 int rwbad = 0;
51 int rand_rw_intr = 0;
52
53 EXPORT int random_rw_test __PR((SCSI *scgp, long first, long last));
54 EXPORT int random_v_test __PR((SCSI *scgp, long first, long last));
55 LOCAL int random_rwv_test __PR((SCSI *scgp, long first, long last, BOOL isrw));
56 LOCAL void sighandler __PR((int));
57 LOCAL int rand_rw __PR((SCSI *scgp, long first, long last));
58 LOCAL int rand_v __PR((SCSI *scgp, long first, long last));
59 LOCAL void pr_percent __PR((long));
60 LOCAL int check_fault __PR((SCSI *scgp,
61 int (*) (SCSI *scgp, caddr_t bp, long addr, int cnt),
62 char *, long, long));
63 LOCAL void add_bad __PR((long, u_char));
64 LOCAL void display_bad __PR((void));
65 LOCAL void display_code __PR((u_char));
66
67 #define rw_verify (int (*) __PR((SCSI *, caddr_t bp, long addr, int cnt)))verify
68
69 EXPORT int
random_rw_test(scgp,first,last)70 random_rw_test(scgp, first, last)
71 SCSI *scgp;
72 long first;
73 long last;
74 {
75 return (random_rwv_test(scgp, first, last, TRUE));
76 }
77
78 EXPORT int
random_v_test(scgp,first,last)79 random_v_test(scgp, first, last)
80 SCSI *scgp;
81 long first;
82 long last;
83 {
84 return (random_rwv_test(scgp, first, last, FALSE));
85 }
86
87 LOCAL int
random_rwv_test(scgp,first,last,isrw)88 random_rwv_test(scgp, first, last, isrw)
89 SCSI *scgp;
90 long first;
91 long last;
92 BOOL isrw;
93 {
94 int ret = 0;
95
96 if ((bad_blocks = (struct bb_list *) malloc((unsigned)((MAXBAD+1) *
97 sizeof (struct bb_list)))) == 0) {
98 comerr("No memory for bad block list.\n");
99 /* NOTREACHED */
100 }
101 fillbytes((char *)bad_blocks,
102 ((MAXBAD+1) * sizeof (struct bb_list)), '\0');
103
104 getstarttime();
105 if (isrw)
106 ret = rand_rw(scgp, first, last);
107 else
108 ret = rand_v(scgp, first, last);
109
110 if (!is_ccs(scgp->dev)) {
111 bad_to_def(scgp);
112 }
113 prstats();
114 display_bad();
115 return (ret);
116 }
117
118 LOCAL void
sighandler(sig)119 sighandler(sig)
120 int sig;
121 {
122 rand_rw_intr++;
123 }
124
125 LOCAL int
rand_rw(scgp,first,last)126 rand_rw(scgp, first, last)
127 SCSI *scgp;
128 long first;
129 long last;
130 {
131 void (*osig) __PR((int));
132 long i;
133 long start = 0;
134 long end = scgp->cap->c_baddr;
135 long amount;
136 long bad_block = -1;
137 long pos[2];
138 int ret = 0;
139 char *buf[2];
140
141 for (i = 0; i < 2; i++) {
142 buf[i] = malloc((unsigned)scgp->cap->c_bsize);
143 pos[i] = 0L;
144 }
145
146 osig = signal(SIGINT, sighandler);
147
148 start = first;
149 end = scgp->cap->c_baddr;
150 if (start < 0 || start > end)
151 start = 0L;
152 if (last > 0 && last < end)
153 end = last;
154 amount = end - start;
155 /*
156 * Do not write to Disk Label or Sinfo Block.
157 */
158 if (start == 0)
159 start++;
160 if (start + amount <= scgp->cap->c_baddr)
161 amount++; /* If not full disk, include last block */
162 if (debug)
163 printf("start: %ld end: %ld amount: %ld last baddr: %ld\n",
164 start, end, amount, (long)scgp->cap->c_baddr);
165
166 if (RW == -1)
167 RW = amount / 50;
168 printf("RAND R/W - %ld loops\n", RW);
169 i = RW;
170
171 #ifdef HAVE_DRAND48
172 pos[i%2] = drand48() * amount + start;
173 #else
174 pos[i%2] = rand() % amount + start;
175 #endif
176 while (read_scsi(scgp, buf[i%2], pos[i%2], 1) < 0) {
177 ret = check_fault(scgp, read_scsi, buf[i%2],
178 pos[i%2], pos[(i+1)%2]);
179 add_bad(pos[i%2], ret | READ_FAULT);
180 #ifdef HAVE_DRAND48
181 pos[i%2] = drand48() * amount + start;
182 #else
183 pos[i%2] = rand() % amount + start;
184 #endif
185 }
186 while (--i >= 0) {
187 #ifdef HAVE_DRAND48
188 pos[i%2] = drand48() * amount + start;
189 #else
190 pos[i%2] = rand() % amount + start;
191 #endif
192 while (read_scsi(scgp, buf[i%2], pos[i%2], 1) < 0) {
193 ret = check_fault(scgp, read_scsi, buf[i%2],
194 pos[i%2], pos[(i+1)%2]);
195 add_bad(pos[i%2], ret | READ_FAULT);
196 #ifdef HAVE_DRAND48
197 pos[i%2] = drand48() * amount + start;
198 #else
199 pos[i%2] = rand() % amount + start;
200 #endif
201 }
202
203 if (write_scsi(scgp, buf[(i+1)%2], pos[(i+1)%2], 1) < 0) {
204 int j;
205 ret = check_fault(scgp, write_scsi, buf[(i+1)%2],
206 pos[(i+1)%2], pos[i%2]);
207 scgp->silent++;
208 for (j = 100; --j >= 0; ) {
209 if (write_scsi(scgp, buf[(i+1)%2],
210 pos[(i+1)%2], 1) >= 0)
211 break;
212 }
213 scgp->silent--;
214 add_bad(pos[(i+1)%2],
215 ret | WRITE_FAULT | (j < 0?DATA_LOST:0));
216 } else {
217 if (verify(scgp, pos[(i+1)%2], 1, &bad_block) < 0) {
218 ret = check_fault(scgp, rw_verify, (char *)0,
219 pos[(i+1)%2], pos[i%2]);
220 add_bad(pos[(i+1)%2], ret | VERIFY_FAULT);
221 }
222 }
223 pr_percent(i);
224 if (rand_rw_intr > 0) {
225 printf("\n%lu loops done ( %ld%% ).\n",
226 RW - i, (((RW - i) * 100) / RW));
227 break;
228 }
229 }
230 signal(SIGINT, osig);
231 printf("\n");
232 return (ret);
233 }
234
235 LOCAL int
rand_v(scgp,first,last)236 rand_v(scgp, first, last)
237 SCSI *scgp;
238 long first;
239 long last;
240 {
241 void (*osig) __PR((int));
242 long i;
243 long start = 0;
244 long end = scgp->cap->c_baddr;
245 long amount;
246 long bad_block = -1;
247 long pos;
248 int ret = 0;
249
250 osig = signal(SIGINT, sighandler);
251
252 start = first;
253 end = scgp->cap->c_baddr;
254 if (start < 0 || start > end)
255 start = 0L;
256 if (last > 0 && last < end)
257 end = last;
258 amount = end - start;
259
260 /*
261 * Include "last" block
262 */
263 amount++;
264 if (debug)
265 printf("start: %ld end: %ld amount: %ld last baddr: %ld\n",
266 start, end, amount, (long)scgp->cap->c_baddr);
267
268 if (RW == -1)
269 RW = amount / 50;
270 printf("RAND V - %ld loops\n", RW);
271 i = RW;
272
273 while (--i >= 0) {
274 #ifdef HAVE_DRAND48
275 pos = drand48() * amount + start;
276 #else
277 pos = rand() % amount + start;
278 #endif
279
280 if (verify(scgp, pos, 1, &bad_block) < 0) {
281 ret = check_fault(scgp, rw_verify, (char *)0,
282 pos, pos);
283 add_bad(pos, ret | VERIFY_FAULT);
284 }
285 pr_percent(i);
286 if (rand_rw_intr > 0) {
287 printf("\n%lu loops done ( %ld%% ).\n",
288 RW - i, (((RW - i) * 100) / RW));
289 break;
290 }
291 }
292 signal(SIGINT, osig);
293 printf("\n");
294 return (ret);
295 }
296
297 LOCAL void
pr_percent(loops)298 pr_percent(loops)
299 long loops;
300 {
301 int prozent;
302 static int prozent_last = -1;
303
304 prozent = ((RW - loops) * 100) / RW;
305 if (prozent > prozent_last) {
306 printf("\r %d%% ", prozent);
307 flush();
308 }
309 prozent_last = prozent;
310 }
311
312 LOCAL int
check_fault(scgp,op,buf,cur_pos,last_pos)313 check_fault(scgp, op, buf, cur_pos, last_pos)
314 SCSI *scgp;
315 int (*op) __PR((SCSI *scgp, caddr_t bp, long addr, int cnt));
316 char *buf;
317 long cur_pos;
318 long last_pos;
319 {
320 long bad_block;
321 int i;
322
323 if (scgp->scmd->error <= SCG_RETRYABLE) {
324 error("\rBad Block found at: %ld\n", cur_pos);
325 for (i = 0; i < 100; i++) {
326 if (op == rw_verify) {
327 if (verify(scgp, cur_pos, 1, &bad_block) < 0)
328 break;
329 } else {
330 if ((*op)(scgp, buf, cur_pos, 1) < 0)
331 break;
332 }
333 }
334 if (i >= 100) {
335 for (i = 0; i < 100; i++) {
336 if (seek_scsi(scgp, last_pos) < 0)
337 return (SEEK_FAULT);
338 if (op == rw_verify) {
339 if (verify(scgp, cur_pos, 1,
340 &bad_block) < 0)
341 break;
342 } else {
343 if ((*op)(scgp, buf, cur_pos, 1) < 0)
344 break;
345 }
346 }
347 if (i < 100) {
348 error("SOFT DATA ERROR !!!!\n");
349 return (SOFT_FAULT);
350 } else {
351 error("NO ERROR ????\n");
352 return (NO_FAULT);
353 }
354 }
355 error("HARD ERROR !!!!\n");
356 return (HARD_FAULT);
357 }
358 return (DRV_ERR);
359 }
360
361 LOCAL void
362 #ifdef __STDC__
add_bad(long bb,u_char err)363 add_bad(long bb, u_char err)
364 #else
365 add_bad(bb, err)
366 long bb;
367 u_char err;
368 #endif
369 {
370 register int i;
371
372 if (get_nbad() >= MAXBAD) {
373 display_bad();
374 comerrno(EX_BAD, "Too many bad blocks (max is %d)\n", MAXBAD);
375 /* NOTREACHED */
376 }
377 for (i = 0; i < rwbad; i++) {
378 if (bad_blocks[i].block == bb && bad_blocks[i].code == err) {
379 bad_blocks[i].count++;
380 return;
381 }
382 }
383 bad_blocks[rwbad].block = bb;
384 bad_blocks[rwbad].code = err;
385 bad_blocks[rwbad].count = 1;
386 insert_bad(bb);
387 rwbad++;
388 }
389
390 LOCAL void
display_bad()391 display_bad()
392 {
393 int i;
394
395 if (rwbad > 0)
396 printf("Count Block Code\n");
397 else
398 printf("no errors\n");
399 for (i = 0; i < rwbad; i++) {
400 printf("%d %lu ",
401 bad_blocks[i].count,
402 bad_blocks[i].block);
403 display_code(bad_blocks[i].code);
404 }
405 }
406
407 LOCAL void
408 #ifdef __STDC__
display_code(u_char code)409 display_code(u_char code)
410 #else
411 display_code(code)
412 u_char code;
413 #endif
414 {
415 if ((code & DRV_ERR) == DRV_ERR) {
416 printf("FATAL ERROR.\n");
417 return;
418 }
419
420 if (code & READ_FAULT)
421 printf("READ:");
422 if (code & WRITE_FAULT)
423 printf("WRITE:");
424 if (code & VERIFY_FAULT)
425 printf("VERIFY:");
426 if (code & SEEK_FAULT)
427 printf("SEEK:");
428
429 if (code & DATA_LOST)
430 printf(" DATA LOST");
431 if (code & HARD_FAULT)
432 printf(" constant error");
433 if (code & SOFT_FAULT)
434 printf(" partial error");
435 if (code & NO_FAULT)
436 printf(" not reproducable error");
437
438 printf(".\n");
439 }
440