xref: /illumos-gate/usr/src/cmd/format/menu_analyze.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1991-2002 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * This file contains functions implementing the analyze menu commands.
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate #include <string.h>
33*7c478bd9Sstevel@tonic-gate #include "global.h"
34*7c478bd9Sstevel@tonic-gate #include "analyze.h"
35*7c478bd9Sstevel@tonic-gate #include "misc.h"
36*7c478bd9Sstevel@tonic-gate #include "menu_analyze.h"
37*7c478bd9Sstevel@tonic-gate #include "param.h"
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate /*
42*7c478bd9Sstevel@tonic-gate  * This routine implements the 'read' command.  It performs surface
43*7c478bd9Sstevel@tonic-gate  * analysis by reading the disk.  It is ok to run this command on
44*7c478bd9Sstevel@tonic-gate  * mounted file systems.
45*7c478bd9Sstevel@tonic-gate  */
46*7c478bd9Sstevel@tonic-gate int
47*7c478bd9Sstevel@tonic-gate a_read()
48*7c478bd9Sstevel@tonic-gate {
49*7c478bd9Sstevel@tonic-gate 	/*
50*7c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
51*7c478bd9Sstevel@tonic-gate 	 */
52*7c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
53*7c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
54*7c478bd9Sstevel@tonic-gate 		return (-1);
55*7c478bd9Sstevel@tonic-gate 	}
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate 	if (check(
58*7c478bd9Sstevel@tonic-gate "Ready to analyze (won't harm SunOS). This takes a long time, \n"
59*7c478bd9Sstevel@tonic-gate "but is interruptable with CTRL-C. Continue"))
60*7c478bd9Sstevel@tonic-gate 		return (-1);
61*7c478bd9Sstevel@tonic-gate 	return (do_scan(SCAN_VALID, F_NORMAL));
62*7c478bd9Sstevel@tonic-gate }
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate /*
65*7c478bd9Sstevel@tonic-gate  * This routine implements the 'refresh' command.  It performs surface
66*7c478bd9Sstevel@tonic-gate  * analysis by reading the disk then writing the same data back to the
67*7c478bd9Sstevel@tonic-gate  * disk.  It is ok to run this command on file systems, but not while
68*7c478bd9Sstevel@tonic-gate  * they are mounted.
69*7c478bd9Sstevel@tonic-gate  */
70*7c478bd9Sstevel@tonic-gate int
71*7c478bd9Sstevel@tonic-gate a_refresh()
72*7c478bd9Sstevel@tonic-gate {
73*7c478bd9Sstevel@tonic-gate 	/*
74*7c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
75*7c478bd9Sstevel@tonic-gate 	 */
76*7c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
77*7c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
78*7c478bd9Sstevel@tonic-gate 		return (-1);
79*7c478bd9Sstevel@tonic-gate 	}
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate 	if (check(
82*7c478bd9Sstevel@tonic-gate "Ready to analyze (won't harm data). This takes a long time, \n"
83*7c478bd9Sstevel@tonic-gate "but is interruptable with CTRL-C. Continue"))
84*7c478bd9Sstevel@tonic-gate 		return (-1);
85*7c478bd9Sstevel@tonic-gate 	return (do_scan(SCAN_VALID | SCAN_WRITE, F_NORMAL));
86*7c478bd9Sstevel@tonic-gate }
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate /*
89*7c478bd9Sstevel@tonic-gate  * This routine implements the 'test' command.  It performs surface
90*7c478bd9Sstevel@tonic-gate  * analysis by reading the disk, writing then reading a pattern on the disk,
91*7c478bd9Sstevel@tonic-gate  * then writing the original data back to the disk.
92*7c478bd9Sstevel@tonic-gate  * It is ok to run this command on file systems, but not while they are
93*7c478bd9Sstevel@tonic-gate  * mounted.
94*7c478bd9Sstevel@tonic-gate  */
95*7c478bd9Sstevel@tonic-gate int
96*7c478bd9Sstevel@tonic-gate a_test()
97*7c478bd9Sstevel@tonic-gate {
98*7c478bd9Sstevel@tonic-gate 	/*
99*7c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
100*7c478bd9Sstevel@tonic-gate 	 */
101*7c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
102*7c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
103*7c478bd9Sstevel@tonic-gate 		return (-1);
104*7c478bd9Sstevel@tonic-gate 	}
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 	if (check(
107*7c478bd9Sstevel@tonic-gate "Ready to analyze (won't harm data). This takes a long time, \n"
108*7c478bd9Sstevel@tonic-gate "but is interruptable with CTRL-C. Continue"))
109*7c478bd9Sstevel@tonic-gate 		return (-1);
110*7c478bd9Sstevel@tonic-gate 	return (do_scan(SCAN_VALID | SCAN_PATTERN | SCAN_WRITE, F_NORMAL));
111*7c478bd9Sstevel@tonic-gate }
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate /*
114*7c478bd9Sstevel@tonic-gate  * This routine implements the 'write' command.  It performs surface
115*7c478bd9Sstevel@tonic-gate  * analysis by writing a pattern to the disk then reading it back.
116*7c478bd9Sstevel@tonic-gate  * It is not ok to run this command on any data you want to keep.
117*7c478bd9Sstevel@tonic-gate  */
118*7c478bd9Sstevel@tonic-gate int
119*7c478bd9Sstevel@tonic-gate a_write()
120*7c478bd9Sstevel@tonic-gate {
121*7c478bd9Sstevel@tonic-gate 	/*
122*7c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
123*7c478bd9Sstevel@tonic-gate 	 */
124*7c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
125*7c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
126*7c478bd9Sstevel@tonic-gate 		return (-1);
127*7c478bd9Sstevel@tonic-gate 	}
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate 	if (check(
130*7c478bd9Sstevel@tonic-gate "Ready to analyze (will corrupt data). This takes a long time, \n"
131*7c478bd9Sstevel@tonic-gate "but is interruptable with CTRL-C. Continue"))
132*7c478bd9Sstevel@tonic-gate 		return (-1);
133*7c478bd9Sstevel@tonic-gate 	return (do_scan(SCAN_PATTERN, F_NORMAL));
134*7c478bd9Sstevel@tonic-gate }
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate /*
137*7c478bd9Sstevel@tonic-gate  * This routine implements the 'compare' command.  It performs surface
138*7c478bd9Sstevel@tonic-gate  * analysis by writing a pattern to the disk, reading it back, then
139*7c478bd9Sstevel@tonic-gate  * checking the data to be sure it's the same.
140*7c478bd9Sstevel@tonic-gate  * It is not ok to run this command on any data you want to keep.
141*7c478bd9Sstevel@tonic-gate  */
142*7c478bd9Sstevel@tonic-gate int
143*7c478bd9Sstevel@tonic-gate a_compare()
144*7c478bd9Sstevel@tonic-gate {
145*7c478bd9Sstevel@tonic-gate 	/*
146*7c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
147*7c478bd9Sstevel@tonic-gate 	 */
148*7c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
149*7c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
150*7c478bd9Sstevel@tonic-gate 		return (-1);
151*7c478bd9Sstevel@tonic-gate 	}
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	if (check(
154*7c478bd9Sstevel@tonic-gate "Ready to analyze (will corrupt data). This takes a long time, \n"
155*7c478bd9Sstevel@tonic-gate "but is interruptable with CTRL-C. Continue"))
156*7c478bd9Sstevel@tonic-gate 		return (-1);
157*7c478bd9Sstevel@tonic-gate 	return (do_scan(SCAN_PATTERN | SCAN_COMPARE, F_NORMAL));
158*7c478bd9Sstevel@tonic-gate }
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate /*
161*7c478bd9Sstevel@tonic-gate  * This routine implements the 'print' command.  It displays the data
162*7c478bd9Sstevel@tonic-gate  * buffer in hexadecimal.  It is only useful for checking the disk for
163*7c478bd9Sstevel@tonic-gate  * a specific set of data (by reading it then printing it).
164*7c478bd9Sstevel@tonic-gate  */
165*7c478bd9Sstevel@tonic-gate int
166*7c478bd9Sstevel@tonic-gate a_print()
167*7c478bd9Sstevel@tonic-gate {
168*7c478bd9Sstevel@tonic-gate 	int	i, j, lines, nomore = 0;
169*7c478bd9Sstevel@tonic-gate 	int	c, one_line = 0;
170*7c478bd9Sstevel@tonic-gate 	int	tty_lines = get_tty_lines();
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	/*
173*7c478bd9Sstevel@tonic-gate 	 * If we are running out of command file, don't page the output.
174*7c478bd9Sstevel@tonic-gate 	 * Otherwise we are running with a user.  Turn off echoing of
175*7c478bd9Sstevel@tonic-gate 	 * input characters so we can page the output.
176*7c478bd9Sstevel@tonic-gate 	 */
177*7c478bd9Sstevel@tonic-gate 	if (option_f || (!isatty(0)) || (!isatty(1)))
178*7c478bd9Sstevel@tonic-gate 		nomore++;
179*7c478bd9Sstevel@tonic-gate 	else {
180*7c478bd9Sstevel@tonic-gate 		enter_critical();
181*7c478bd9Sstevel@tonic-gate 		echo_off();
182*7c478bd9Sstevel@tonic-gate 		charmode_on();
183*7c478bd9Sstevel@tonic-gate 		exit_critical();
184*7c478bd9Sstevel@tonic-gate 	}
185*7c478bd9Sstevel@tonic-gate 	/*
186*7c478bd9Sstevel@tonic-gate 	 * Loop through the data buffer.
187*7c478bd9Sstevel@tonic-gate 	 */
188*7c478bd9Sstevel@tonic-gate 	lines = 0;
189*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < scan_size * SECSIZE / sizeof (int); i += 6) {
190*7c478bd9Sstevel@tonic-gate 		/*
191*7c478bd9Sstevel@tonic-gate 		 * Print the data.
192*7c478bd9Sstevel@tonic-gate 		 */
193*7c478bd9Sstevel@tonic-gate 		for (j = 0; j < 6; j++)
194*7c478bd9Sstevel@tonic-gate 			if (i + j < scan_size * SECSIZE / sizeof (int))
195*7c478bd9Sstevel@tonic-gate 				fmt_print("0x%08x  ",
196*7c478bd9Sstevel@tonic-gate 				*((int *)((int *)cur_buf + i + j)));
197*7c478bd9Sstevel@tonic-gate 		fmt_print("\n");
198*7c478bd9Sstevel@tonic-gate 		lines++;
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 		/*
201*7c478bd9Sstevel@tonic-gate 		 * If we are paging and hit the end of a page, wait for
202*7c478bd9Sstevel@tonic-gate 		 * the user to hit either space-bar, "q", return,
203*7c478bd9Sstevel@tonic-gate 		 * or ctrl-C before going on.
204*7c478bd9Sstevel@tonic-gate 		 */
205*7c478bd9Sstevel@tonic-gate 		if (one_line ||
206*7c478bd9Sstevel@tonic-gate 		    (!nomore && (lines % (tty_lines - 1) == 0))) {
207*7c478bd9Sstevel@tonic-gate 			/*
208*7c478bd9Sstevel@tonic-gate 			 * Print until first screenfull
209*7c478bd9Sstevel@tonic-gate 			 */
210*7c478bd9Sstevel@tonic-gate 			if (lines < (tty_lines -1))
211*7c478bd9Sstevel@tonic-gate 				continue;
212*7c478bd9Sstevel@tonic-gate 			/*
213*7c478bd9Sstevel@tonic-gate 			 * Get the next character.
214*7c478bd9Sstevel@tonic-gate 			 */
215*7c478bd9Sstevel@tonic-gate 			(void) printf("- hit space for more - ");
216*7c478bd9Sstevel@tonic-gate 			c = getchar();
217*7c478bd9Sstevel@tonic-gate 			(void) printf("\015");
218*7c478bd9Sstevel@tonic-gate 			one_line = 0;
219*7c478bd9Sstevel@tonic-gate 			/*
220*7c478bd9Sstevel@tonic-gate 			 * Handle display one line command (return key)
221*7c478bd9Sstevel@tonic-gate 			 */
222*7c478bd9Sstevel@tonic-gate 			if (c == '\012') {
223*7c478bd9Sstevel@tonic-gate 				one_line++;
224*7c478bd9Sstevel@tonic-gate 			}
225*7c478bd9Sstevel@tonic-gate 			/* Handle Quit command */
226*7c478bd9Sstevel@tonic-gate 			if (c == 'q') {
227*7c478bd9Sstevel@tonic-gate 				(void) printf(
228*7c478bd9Sstevel@tonic-gate 				"                       \015");
229*7c478bd9Sstevel@tonic-gate 				goto PRINT_EXIT;
230*7c478bd9Sstevel@tonic-gate 			}
231*7c478bd9Sstevel@tonic-gate 			/* handle ^D */
232*7c478bd9Sstevel@tonic-gate 			if (c == '\004')
233*7c478bd9Sstevel@tonic-gate 				fullabort();
234*7c478bd9Sstevel@tonic-gate 		}
235*7c478bd9Sstevel@tonic-gate 	}
236*7c478bd9Sstevel@tonic-gate 	/*
237*7c478bd9Sstevel@tonic-gate 	 * If we were doing paging, turn echoing back on.
238*7c478bd9Sstevel@tonic-gate 	 */
239*7c478bd9Sstevel@tonic-gate PRINT_EXIT:
240*7c478bd9Sstevel@tonic-gate 	if (!nomore) {
241*7c478bd9Sstevel@tonic-gate 		enter_critical();
242*7c478bd9Sstevel@tonic-gate 		charmode_off();
243*7c478bd9Sstevel@tonic-gate 		echo_on();
244*7c478bd9Sstevel@tonic-gate 		exit_critical();
245*7c478bd9Sstevel@tonic-gate 	}
246*7c478bd9Sstevel@tonic-gate 	return (0);
247*7c478bd9Sstevel@tonic-gate }
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate /*
250*7c478bd9Sstevel@tonic-gate  * This routine implements the 'setup' command.  It allows the user
251*7c478bd9Sstevel@tonic-gate  * to program the variables that drive surface analysis.  The approach
252*7c478bd9Sstevel@tonic-gate  * is to prompt the user for the value of each variable, with the current
253*7c478bd9Sstevel@tonic-gate  * value as the default.
254*7c478bd9Sstevel@tonic-gate  */
255*7c478bd9Sstevel@tonic-gate int
256*7c478bd9Sstevel@tonic-gate a_setup()
257*7c478bd9Sstevel@tonic-gate {
258*7c478bd9Sstevel@tonic-gate 	int			deflt;
259*7c478bd9Sstevel@tonic-gate 	uint64_t		size;
260*7c478bd9Sstevel@tonic-gate 	u_ioparam_t		ioparam;
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 	/*
263*7c478bd9Sstevel@tonic-gate 	 * Because of the polarity of the yes/no structure (yes is 0),
264*7c478bd9Sstevel@tonic-gate 	 * we have to invert the values for all yes/no questions.
265*7c478bd9Sstevel@tonic-gate 	 */
266*7c478bd9Sstevel@tonic-gate 	deflt = !scan_entire;
267*7c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
268*7c478bd9Sstevel@tonic-gate 	scan_entire = !input(FIO_MSTR, "Analyze entire disk", '?',
269*7c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
270*7c478bd9Sstevel@tonic-gate 	/*
271*7c478bd9Sstevel@tonic-gate 	 * If we are not scanning the whole disk, input the bounds of the scan.
272*7c478bd9Sstevel@tonic-gate 	 */
273*7c478bd9Sstevel@tonic-gate 	if (!scan_entire) {
274*7c478bd9Sstevel@tonic-gate 		ioparam.io_bounds.lower = 0;
275*7c478bd9Sstevel@tonic-gate 		if ((cur_ctype->ctype_flags & CF_SCSI) &&
276*7c478bd9Sstevel@tonic-gate 		    (cur_disk->label_type == L_TYPE_SOLARIS)) {
277*7c478bd9Sstevel@tonic-gate 		    ioparam.io_bounds.upper = datasects() - 1;
278*7c478bd9Sstevel@tonic-gate 		} else if (cur_disk->label_type == L_TYPE_SOLARIS) {
279*7c478bd9Sstevel@tonic-gate 		    ioparam.io_bounds.upper = physsects() - 1;
280*7c478bd9Sstevel@tonic-gate 		} else if (cur_disk->label_type == L_TYPE_EFI) {
281*7c478bd9Sstevel@tonic-gate 		    ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba;
282*7c478bd9Sstevel@tonic-gate 		}
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 		scan_lower = (diskaddr_t)input(FIO_BN,
285*7c478bd9Sstevel@tonic-gate 		    "Enter starting block number", ':',
286*7c478bd9Sstevel@tonic-gate 		    &ioparam, (int *)&scan_lower, DATA_INPUT);
287*7c478bd9Sstevel@tonic-gate 		ioparam.io_bounds.lower = scan_lower;
288*7c478bd9Sstevel@tonic-gate 		if (scan_upper < scan_lower)
289*7c478bd9Sstevel@tonic-gate 			scan_upper = scan_lower;
290*7c478bd9Sstevel@tonic-gate 		scan_upper = (diskaddr_t)input(FIO_BN,
291*7c478bd9Sstevel@tonic-gate 		    "Enter ending block number", ':',
292*7c478bd9Sstevel@tonic-gate 		    &ioparam, (int *)&scan_upper, DATA_INPUT);
293*7c478bd9Sstevel@tonic-gate 	}
294*7c478bd9Sstevel@tonic-gate 	deflt = !scan_loop;
295*7c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
296*7c478bd9Sstevel@tonic-gate 	scan_loop = !input(FIO_MSTR, "Loop continuously", '?',
297*7c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
298*7c478bd9Sstevel@tonic-gate 	/*
299*7c478bd9Sstevel@tonic-gate 	 * If we are not looping continuously, input the number of passes.
300*7c478bd9Sstevel@tonic-gate 	 */
301*7c478bd9Sstevel@tonic-gate 	if (!scan_loop) {
302*7c478bd9Sstevel@tonic-gate 		ioparam.io_bounds.lower = 1;
303*7c478bd9Sstevel@tonic-gate 		ioparam.io_bounds.upper = 100;
304*7c478bd9Sstevel@tonic-gate 		scan_passes = input(FIO_INT, "Enter number of passes", ':',
305*7c478bd9Sstevel@tonic-gate 		    &ioparam, &scan_passes, DATA_INPUT);
306*7c478bd9Sstevel@tonic-gate 	}
307*7c478bd9Sstevel@tonic-gate 	deflt = !scan_correct;
308*7c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
309*7c478bd9Sstevel@tonic-gate 	scan_correct = !input(FIO_MSTR, "Repair defective blocks", '?',
310*7c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
311*7c478bd9Sstevel@tonic-gate 	deflt = !scan_stop;
312*7c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
313*7c478bd9Sstevel@tonic-gate 	scan_stop = !input(FIO_MSTR, "Stop after first error", '?',
314*7c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
315*7c478bd9Sstevel@tonic-gate 	deflt = !scan_random;
316*7c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
317*7c478bd9Sstevel@tonic-gate 	scan_random = !input(FIO_MSTR, "Use random bit patterns", '?',
318*7c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
319*7c478bd9Sstevel@tonic-gate 	ioparam.io_bounds.lower = 1;
320*7c478bd9Sstevel@tonic-gate 	/*
321*7c478bd9Sstevel@tonic-gate 	 * The number of blocks per transfer is limited by the buffer
322*7c478bd9Sstevel@tonic-gate 	 * size, or the scan boundaries, whichever is smaller.
323*7c478bd9Sstevel@tonic-gate 	 */
324*7c478bd9Sstevel@tonic-gate 	if ((scan_entire) && (cur_disk->label_type == L_TYPE_SOLARIS)) {
325*7c478bd9Sstevel@tonic-gate 		size = physsects() - 1;
326*7c478bd9Sstevel@tonic-gate 	} else if ((scan_entire) && (cur_disk->label_type == L_TYPE_EFI)) {
327*7c478bd9Sstevel@tonic-gate 		size = cur_parts->etoc->efi_last_lba;
328*7c478bd9Sstevel@tonic-gate 	} else {
329*7c478bd9Sstevel@tonic-gate 		size = scan_upper - scan_lower + 1;
330*7c478bd9Sstevel@tonic-gate 	}
331*7c478bd9Sstevel@tonic-gate 	ioparam.io_bounds.upper = min(size, BUF_SECTS);
332*7c478bd9Sstevel@tonic-gate 	if (scan_size > ioparam.io_bounds.upper)
333*7c478bd9Sstevel@tonic-gate 		scan_size = ioparam.io_bounds.upper;
334*7c478bd9Sstevel@tonic-gate 	scan_size = input(FIO_BN, "Enter number of blocks per transfer", ':',
335*7c478bd9Sstevel@tonic-gate 	    &ioparam, &scan_size, DATA_INPUT);
336*7c478bd9Sstevel@tonic-gate 	deflt = !scan_auto;
337*7c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
338*7c478bd9Sstevel@tonic-gate 	scan_auto = !input(FIO_MSTR, "Verify media after formatting", '?',
339*7c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	deflt = !option_msg;
342*7c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
343*7c478bd9Sstevel@tonic-gate 	option_msg = !input(FIO_MSTR, "Enable extended messages", '?',
344*7c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
345*7c478bd9Sstevel@tonic-gate 	deflt = !scan_restore_defects;
346*7c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
347*7c478bd9Sstevel@tonic-gate 	scan_restore_defects = !input(FIO_MSTR, "Restore defect list", '?',
348*7c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
349*7c478bd9Sstevel@tonic-gate 	deflt = !scan_restore_label;
350*7c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
351*7c478bd9Sstevel@tonic-gate 	scan_restore_label = !input(FIO_MSTR, "Restore disk label", '?',
352*7c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
353*7c478bd9Sstevel@tonic-gate 	fmt_print("\n");
354*7c478bd9Sstevel@tonic-gate 	return (0);
355*7c478bd9Sstevel@tonic-gate }
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate /*
358*7c478bd9Sstevel@tonic-gate  * This routine implements the 'config' command.  It simply prints out
359*7c478bd9Sstevel@tonic-gate  * the values of all the variables controlling surface analysis.  It
360*7c478bd9Sstevel@tonic-gate  * is meant to complement the 'setup' command by allowing the user to
361*7c478bd9Sstevel@tonic-gate  * check the current setup.
362*7c478bd9Sstevel@tonic-gate  */
363*7c478bd9Sstevel@tonic-gate int
364*7c478bd9Sstevel@tonic-gate a_config()
365*7c478bd9Sstevel@tonic-gate {
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate 	fmt_print("        Analyze entire disk? ");
368*7c478bd9Sstevel@tonic-gate 	fmt_print(scan_entire ? "yes\n" : "no\n");
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate 	if (!scan_entire) {
371*7c478bd9Sstevel@tonic-gate 		fmt_print("        Starting block number: %llu (", scan_lower);
372*7c478bd9Sstevel@tonic-gate 		pr_dblock(fmt_print, scan_lower);
373*7c478bd9Sstevel@tonic-gate 		fmt_print(")\n        Ending block number: %llu (", scan_upper);
374*7c478bd9Sstevel@tonic-gate 		pr_dblock(fmt_print, scan_upper);
375*7c478bd9Sstevel@tonic-gate 		fmt_print(")\n");
376*7c478bd9Sstevel@tonic-gate 	}
377*7c478bd9Sstevel@tonic-gate 	fmt_print("        Loop continuously? ");
378*7c478bd9Sstevel@tonic-gate 	fmt_print(scan_loop ? "yes\n" : "no\n");
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate 	if (!scan_loop) {
381*7c478bd9Sstevel@tonic-gate 		fmt_print("        Number of passes: %d\n", scan_passes);
382*7c478bd9Sstevel@tonic-gate 	}
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	fmt_print("        Repair defective blocks? ");
385*7c478bd9Sstevel@tonic-gate 	fmt_print(scan_correct ? "yes\n" : "no\n");
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 	fmt_print("        Stop after first error? ");
388*7c478bd9Sstevel@tonic-gate 	fmt_print(scan_stop ? "yes\n" : "no\n");
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	fmt_print("        Use random bit patterns? ");
391*7c478bd9Sstevel@tonic-gate 	fmt_print(scan_random ? "yes\n" : "no\n");
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 	fmt_print("        Number of blocks per transfer: %d (", scan_size);
394*7c478bd9Sstevel@tonic-gate 	pr_dblock(fmt_print, (daddr_t)scan_size);
395*7c478bd9Sstevel@tonic-gate 	fmt_print(")\n");
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	fmt_print("        Verify media after formatting? ");
398*7c478bd9Sstevel@tonic-gate 	fmt_print(scan_auto ? "yes\n" : "no\n");
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 	fmt_print("        Enable extended messages? ");
401*7c478bd9Sstevel@tonic-gate 	fmt_print(option_msg ? "yes\n" : "no\n");
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 	fmt_print("        Restore defect list? ");
404*7c478bd9Sstevel@tonic-gate 	fmt_print(scan_restore_defects ? "yes\n" : "no\n");
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate 	fmt_print("        Restore disk label? ");
407*7c478bd9Sstevel@tonic-gate 	fmt_print(scan_restore_label ? "yes\n" : "no\n");
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate 	fmt_print("\n");
410*7c478bd9Sstevel@tonic-gate 	return (0);
411*7c478bd9Sstevel@tonic-gate }
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate /*
414*7c478bd9Sstevel@tonic-gate  * This routine implements the 'purge' command.  It purges the disk
415*7c478bd9Sstevel@tonic-gate  * by writing three patterns to the disk then reading the last one back.
416*7c478bd9Sstevel@tonic-gate  * It is not ok to run this command on any data you want to keep.
417*7c478bd9Sstevel@tonic-gate  */
418*7c478bd9Sstevel@tonic-gate int
419*7c478bd9Sstevel@tonic-gate a_purge()
420*7c478bd9Sstevel@tonic-gate {
421*7c478bd9Sstevel@tonic-gate 	int status = 0;
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate 	/*
424*7c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
425*7c478bd9Sstevel@tonic-gate 	 */
426*7c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
427*7c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
428*7c478bd9Sstevel@tonic-gate 		return (-1);
429*7c478bd9Sstevel@tonic-gate 	}
430*7c478bd9Sstevel@tonic-gate 	if (scan_random) {
431*7c478bd9Sstevel@tonic-gate 		fmt_print("The purge command does not write random data\n");
432*7c478bd9Sstevel@tonic-gate 		scan_random = 0;
433*7c478bd9Sstevel@tonic-gate 	}
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 	if (!scan_loop && (scan_passes <= NPPATTERNS)) {
436*7c478bd9Sstevel@tonic-gate 		if (scan_passes < NPPATTERNS) {
437*7c478bd9Sstevel@tonic-gate 			fmt_print("The purge command runs for a minimum of ");
438*7c478bd9Sstevel@tonic-gate 			fmt_print("%d passes plus a last pass if the\n",
439*7c478bd9Sstevel@tonic-gate 						NPPATTERNS);
440*7c478bd9Sstevel@tonic-gate 			fmt_print("first %d passes were successful.\n",
441*7c478bd9Sstevel@tonic-gate 					NPPATTERNS);
442*7c478bd9Sstevel@tonic-gate 		}
443*7c478bd9Sstevel@tonic-gate 		scan_passes = NPPATTERNS + 1;
444*7c478bd9Sstevel@tonic-gate 	}
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate 	if (check(
447*7c478bd9Sstevel@tonic-gate "Ready to purge (will corrupt data). This takes a long time, \n"
448*7c478bd9Sstevel@tonic-gate "but is interruptable with CTRL-C. Continue"))
449*7c478bd9Sstevel@tonic-gate 		return (-1);
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 	status = do_scan(SCAN_PATTERN | SCAN_PURGE, F_NORMAL);
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 	return (status);
454*7c478bd9Sstevel@tonic-gate }
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate /*
457*7c478bd9Sstevel@tonic-gate  * This routine implements the 'verify' command.  It writes the disk
458*7c478bd9Sstevel@tonic-gate  * by writing unique data for each block; after the write pass, it
459*7c478bd9Sstevel@tonic-gate  * reads the data and verifies for correctness. Note that the entire
460*7c478bd9Sstevel@tonic-gate  * disk (or the range of disk) is fully written first and then read.
461*7c478bd9Sstevel@tonic-gate  * This should eliminate any caching effect on the drives.
462*7c478bd9Sstevel@tonic-gate  * It is not ok to run this command on any data you want to keep.
463*7c478bd9Sstevel@tonic-gate  */
464*7c478bd9Sstevel@tonic-gate int
465*7c478bd9Sstevel@tonic-gate a_verify()
466*7c478bd9Sstevel@tonic-gate {
467*7c478bd9Sstevel@tonic-gate 	/*
468*7c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
469*7c478bd9Sstevel@tonic-gate 	 */
470*7c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
471*7c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
472*7c478bd9Sstevel@tonic-gate 		return (-1);
473*7c478bd9Sstevel@tonic-gate 	}
474*7c478bd9Sstevel@tonic-gate 	if (scan_random) {
475*7c478bd9Sstevel@tonic-gate 		fmt_print("The verify command does not write random data\n");
476*7c478bd9Sstevel@tonic-gate 		scan_random = 0;
477*7c478bd9Sstevel@tonic-gate 	}
478*7c478bd9Sstevel@tonic-gate 	if (scan_passes < 2 && !scan_loop) {
479*7c478bd9Sstevel@tonic-gate 		scan_passes = 2;
480*7c478bd9Sstevel@tonic-gate 		fmt_print("The verify command runs minimum of 2 passes, one"
481*7c478bd9Sstevel@tonic-gate 		    " for writing and \nanother for reading and verfying."
482*7c478bd9Sstevel@tonic-gate 		    " Resetting the number of passes to 2.\n");
483*7c478bd9Sstevel@tonic-gate 	}
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate 	if (check("Ready to verify (will corrupt data). This takes a long time,"
486*7c478bd9Sstevel@tonic-gate 	    "\nbut is interruptable with CTRL-C. Continue")) {
487*7c478bd9Sstevel@tonic-gate 		return (-1);
488*7c478bd9Sstevel@tonic-gate 	}
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 	return (do_scan(SCAN_WRITE | SCAN_VERIFY, F_NORMAL));
491*7c478bd9Sstevel@tonic-gate }
492