xref: /illumos-gate/usr/src/cmd/format/menu_analyze.c (revision b12aaafb)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5342440ecSPrasad Singamsetty  * Common Development and Distribution License (the "License").
6342440ecSPrasad Singamsetty  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
2265908c77Syu, larry liu - Sun Microsystems - Beijing China  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * This file contains functions implementing the analyze menu commands.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate #include "global.h"
317c478bd9Sstevel@tonic-gate #include "analyze.h"
327c478bd9Sstevel@tonic-gate #include "misc.h"
337c478bd9Sstevel@tonic-gate #include "menu_analyze.h"
347c478bd9Sstevel@tonic-gate #include "param.h"
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate /*
377c478bd9Sstevel@tonic-gate  * This routine implements the 'read' command.  It performs surface
387c478bd9Sstevel@tonic-gate  * analysis by reading the disk.  It is ok to run this command on
397c478bd9Sstevel@tonic-gate  * mounted file systems.
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate int
a_read(void)42*b12aaafbSToomas Soome a_read(void)
437c478bd9Sstevel@tonic-gate {
447c478bd9Sstevel@tonic-gate 	/*
457c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
467c478bd9Sstevel@tonic-gate 	 */
477c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
487c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
497c478bd9Sstevel@tonic-gate 		return (-1);
507c478bd9Sstevel@tonic-gate 	}
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate 	if (check(
537c478bd9Sstevel@tonic-gate "Ready to analyze (won't harm SunOS). This takes a long time, \n"
54d5f26e6cSbo zhou - Sun Microsystems - Beijing China "but is interruptible with CTRL-C. Continue"))
557c478bd9Sstevel@tonic-gate 		return (-1);
567c478bd9Sstevel@tonic-gate 	return (do_scan(SCAN_VALID, F_NORMAL));
577c478bd9Sstevel@tonic-gate }
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate  * This routine implements the 'refresh' command.  It performs surface
617c478bd9Sstevel@tonic-gate  * analysis by reading the disk then writing the same data back to the
627c478bd9Sstevel@tonic-gate  * disk.  It is ok to run this command on file systems, but not while
637c478bd9Sstevel@tonic-gate  * they are mounted.
647c478bd9Sstevel@tonic-gate  */
657c478bd9Sstevel@tonic-gate int
a_refresh(void)66*b12aaafbSToomas Soome a_refresh(void)
677c478bd9Sstevel@tonic-gate {
687c478bd9Sstevel@tonic-gate 	/*
697c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
707c478bd9Sstevel@tonic-gate 	 */
717c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
727c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
737c478bd9Sstevel@tonic-gate 		return (-1);
747c478bd9Sstevel@tonic-gate 	}
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	if (check(
777c478bd9Sstevel@tonic-gate "Ready to analyze (won't harm data). This takes a long time, \n"
78d5f26e6cSbo zhou - Sun Microsystems - Beijing China "but is interruptible with CTRL-C. Continue"))
797c478bd9Sstevel@tonic-gate 		return (-1);
807c478bd9Sstevel@tonic-gate 	return (do_scan(SCAN_VALID | SCAN_WRITE, F_NORMAL));
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate /*
847c478bd9Sstevel@tonic-gate  * This routine implements the 'test' command.  It performs surface
857c478bd9Sstevel@tonic-gate  * analysis by reading the disk, writing then reading a pattern on the disk,
867c478bd9Sstevel@tonic-gate  * then writing the original data back to the disk.
877c478bd9Sstevel@tonic-gate  * It is ok to run this command on file systems, but not while they are
887c478bd9Sstevel@tonic-gate  * mounted.
897c478bd9Sstevel@tonic-gate  */
907c478bd9Sstevel@tonic-gate int
a_test(void)91*b12aaafbSToomas Soome a_test(void)
927c478bd9Sstevel@tonic-gate {
937c478bd9Sstevel@tonic-gate 	/*
947c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
957c478bd9Sstevel@tonic-gate 	 */
967c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
977c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
987c478bd9Sstevel@tonic-gate 		return (-1);
997c478bd9Sstevel@tonic-gate 	}
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	if (check(
1027c478bd9Sstevel@tonic-gate "Ready to analyze (won't harm data). This takes a long time, \n"
103d5f26e6cSbo zhou - Sun Microsystems - Beijing China "but is interruptible with CTRL-C. Continue"))
1047c478bd9Sstevel@tonic-gate 		return (-1);
1057c478bd9Sstevel@tonic-gate 	return (do_scan(SCAN_VALID | SCAN_PATTERN | SCAN_WRITE, F_NORMAL));
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate  * This routine implements the 'write' command.  It performs surface
1107c478bd9Sstevel@tonic-gate  * analysis by writing a pattern to the disk then reading it back.
1117c478bd9Sstevel@tonic-gate  * It is not ok to run this command on any data you want to keep.
1127c478bd9Sstevel@tonic-gate  */
1137c478bd9Sstevel@tonic-gate int
a_write(void)114*b12aaafbSToomas Soome a_write(void)
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate 	/*
1177c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
1187c478bd9Sstevel@tonic-gate 	 */
1197c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
1207c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
1217c478bd9Sstevel@tonic-gate 		return (-1);
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	if (check(
1257c478bd9Sstevel@tonic-gate "Ready to analyze (will corrupt data). This takes a long time, \n"
126d5f26e6cSbo zhou - Sun Microsystems - Beijing China "but is interruptible with CTRL-C. Continue"))
1277c478bd9Sstevel@tonic-gate 		return (-1);
1287c478bd9Sstevel@tonic-gate 	return (do_scan(SCAN_PATTERN, F_NORMAL));
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate  * This routine implements the 'compare' command.  It performs surface
1337c478bd9Sstevel@tonic-gate  * analysis by writing a pattern to the disk, reading it back, then
1347c478bd9Sstevel@tonic-gate  * checking the data to be sure it's the same.
1357c478bd9Sstevel@tonic-gate  * It is not ok to run this command on any data you want to keep.
1367c478bd9Sstevel@tonic-gate  */
1377c478bd9Sstevel@tonic-gate int
a_compare(void)138*b12aaafbSToomas Soome a_compare(void)
1397c478bd9Sstevel@tonic-gate {
1407c478bd9Sstevel@tonic-gate 	/*
1417c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
1427c478bd9Sstevel@tonic-gate 	 */
1437c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
1447c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
1457c478bd9Sstevel@tonic-gate 		return (-1);
1467c478bd9Sstevel@tonic-gate 	}
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	if (check(
1497c478bd9Sstevel@tonic-gate "Ready to analyze (will corrupt data). This takes a long time, \n"
150d5f26e6cSbo zhou - Sun Microsystems - Beijing China "but is interruptible with CTRL-C. Continue"))
1517c478bd9Sstevel@tonic-gate 		return (-1);
1527c478bd9Sstevel@tonic-gate 	return (do_scan(SCAN_PATTERN | SCAN_COMPARE, F_NORMAL));
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate /*
1567c478bd9Sstevel@tonic-gate  * This routine implements the 'print' command.  It displays the data
1577c478bd9Sstevel@tonic-gate  * buffer in hexadecimal.  It is only useful for checking the disk for
1587c478bd9Sstevel@tonic-gate  * a specific set of data (by reading it then printing it).
1597c478bd9Sstevel@tonic-gate  */
1607c478bd9Sstevel@tonic-gate int
a_print(void)161*b12aaafbSToomas Soome a_print(void)
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate 	int	i, j, lines, nomore = 0;
1647c478bd9Sstevel@tonic-gate 	int	c, one_line = 0;
1657c478bd9Sstevel@tonic-gate 	int	tty_lines = get_tty_lines();
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	/*
1687c478bd9Sstevel@tonic-gate 	 * If we are running out of command file, don't page the output.
1697c478bd9Sstevel@tonic-gate 	 * Otherwise we are running with a user.  Turn off echoing of
1707c478bd9Sstevel@tonic-gate 	 * input characters so we can page the output.
1717c478bd9Sstevel@tonic-gate 	 */
1727c478bd9Sstevel@tonic-gate 	if (option_f || (!isatty(0)) || (!isatty(1)))
1737c478bd9Sstevel@tonic-gate 		nomore++;
1747c478bd9Sstevel@tonic-gate 	else {
1757c478bd9Sstevel@tonic-gate 		enter_critical();
1767c478bd9Sstevel@tonic-gate 		echo_off();
1777c478bd9Sstevel@tonic-gate 		charmode_on();
1787c478bd9Sstevel@tonic-gate 		exit_critical();
1797c478bd9Sstevel@tonic-gate 	}
1807c478bd9Sstevel@tonic-gate 	/*
1817c478bd9Sstevel@tonic-gate 	 * Loop through the data buffer.
1827c478bd9Sstevel@tonic-gate 	 */
1837c478bd9Sstevel@tonic-gate 	lines = 0;
18465908c77Syu, larry liu - Sun Microsystems - Beijing China 	for (i = 0; i < scan_size * cur_blksz / sizeof (int); i += 6) {
1857c478bd9Sstevel@tonic-gate 		/*
1867c478bd9Sstevel@tonic-gate 		 * Print the data.
1877c478bd9Sstevel@tonic-gate 		 */
1887c478bd9Sstevel@tonic-gate 		for (j = 0; j < 6; j++)
18965908c77Syu, larry liu - Sun Microsystems - Beijing China 			if (i + j < scan_size * cur_blksz / sizeof (int))
1907c478bd9Sstevel@tonic-gate 				fmt_print("0x%08x  ",
1917c478bd9Sstevel@tonic-gate 				    *((int *)((int *)cur_buf + i + j)));
1927c478bd9Sstevel@tonic-gate 		fmt_print("\n");
1937c478bd9Sstevel@tonic-gate 		lines++;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 		/*
1967c478bd9Sstevel@tonic-gate 		 * If we are paging and hit the end of a page, wait for
1977c478bd9Sstevel@tonic-gate 		 * the user to hit either space-bar, "q", return,
1987c478bd9Sstevel@tonic-gate 		 * or ctrl-C before going on.
1997c478bd9Sstevel@tonic-gate 		 */
2007c478bd9Sstevel@tonic-gate 		if (one_line ||
2017c478bd9Sstevel@tonic-gate 		    (!nomore && (lines % (tty_lines - 1) == 0))) {
2027c478bd9Sstevel@tonic-gate 			/*
2037c478bd9Sstevel@tonic-gate 			 * Print until first screenfull
2047c478bd9Sstevel@tonic-gate 			 */
2057c478bd9Sstevel@tonic-gate 			if (lines < (tty_lines -1))
2067c478bd9Sstevel@tonic-gate 				continue;
2077c478bd9Sstevel@tonic-gate 			/*
2087c478bd9Sstevel@tonic-gate 			 * Get the next character.
2097c478bd9Sstevel@tonic-gate 			 */
2107c478bd9Sstevel@tonic-gate 			(void) printf("- hit space for more - ");
2117c478bd9Sstevel@tonic-gate 			c = getchar();
2127c478bd9Sstevel@tonic-gate 			(void) printf("\015");
2137c478bd9Sstevel@tonic-gate 			one_line = 0;
2147c478bd9Sstevel@tonic-gate 			/*
2157c478bd9Sstevel@tonic-gate 			 * Handle display one line command (return key)
2167c478bd9Sstevel@tonic-gate 			 */
2177c478bd9Sstevel@tonic-gate 			if (c == '\012') {
2187c478bd9Sstevel@tonic-gate 				one_line++;
2197c478bd9Sstevel@tonic-gate 			}
2207c478bd9Sstevel@tonic-gate 			/* Handle Quit command */
2217c478bd9Sstevel@tonic-gate 			if (c == 'q') {
2227c478bd9Sstevel@tonic-gate 				(void) printf(
2237c478bd9Sstevel@tonic-gate 				"                       \015");
2247c478bd9Sstevel@tonic-gate 				goto PRINT_EXIT;
2257c478bd9Sstevel@tonic-gate 			}
2267c478bd9Sstevel@tonic-gate 			/* handle ^D */
2277c478bd9Sstevel@tonic-gate 			if (c == '\004')
2287c478bd9Sstevel@tonic-gate 				fullabort();
2297c478bd9Sstevel@tonic-gate 		}
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 	/*
2327c478bd9Sstevel@tonic-gate 	 * If we were doing paging, turn echoing back on.
2337c478bd9Sstevel@tonic-gate 	 */
2347c478bd9Sstevel@tonic-gate PRINT_EXIT:
2357c478bd9Sstevel@tonic-gate 	if (!nomore) {
2367c478bd9Sstevel@tonic-gate 		enter_critical();
2377c478bd9Sstevel@tonic-gate 		charmode_off();
2387c478bd9Sstevel@tonic-gate 		echo_on();
2397c478bd9Sstevel@tonic-gate 		exit_critical();
2407c478bd9Sstevel@tonic-gate 	}
2417c478bd9Sstevel@tonic-gate 	return (0);
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate  * This routine implements the 'setup' command.  It allows the user
2467c478bd9Sstevel@tonic-gate  * to program the variables that drive surface analysis.  The approach
2477c478bd9Sstevel@tonic-gate  * is to prompt the user for the value of each variable, with the current
2487c478bd9Sstevel@tonic-gate  * value as the default.
2497c478bd9Sstevel@tonic-gate  */
2507c478bd9Sstevel@tonic-gate int
a_setup(void)251*b12aaafbSToomas Soome a_setup(void)
2527c478bd9Sstevel@tonic-gate {
2537c478bd9Sstevel@tonic-gate 	int			deflt;
2547c478bd9Sstevel@tonic-gate 	uint64_t		size;
2557c478bd9Sstevel@tonic-gate 	u_ioparam_t		ioparam;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	/*
2587c478bd9Sstevel@tonic-gate 	 * Because of the polarity of the yes/no structure (yes is 0),
2597c478bd9Sstevel@tonic-gate 	 * we have to invert the values for all yes/no questions.
2607c478bd9Sstevel@tonic-gate 	 */
2617c478bd9Sstevel@tonic-gate 	deflt = !scan_entire;
2627c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
2637c478bd9Sstevel@tonic-gate 	scan_entire = !input(FIO_MSTR, "Analyze entire disk", '?',
2647c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
2657c478bd9Sstevel@tonic-gate 	/*
2667c478bd9Sstevel@tonic-gate 	 * If we are not scanning the whole disk, input the bounds of the scan.
2677c478bd9Sstevel@tonic-gate 	 */
2687c478bd9Sstevel@tonic-gate 	if (!scan_entire) {
2697c478bd9Sstevel@tonic-gate 		ioparam.io_bounds.lower = 0;
2707c478bd9Sstevel@tonic-gate 		if ((cur_ctype->ctype_flags & CF_SCSI) &&
2717c478bd9Sstevel@tonic-gate 		    (cur_disk->label_type == L_TYPE_SOLARIS)) {
2727c478bd9Sstevel@tonic-gate 			ioparam.io_bounds.upper = datasects() - 1;
2737c478bd9Sstevel@tonic-gate 		} else if (cur_disk->label_type == L_TYPE_SOLARIS) {
2747c478bd9Sstevel@tonic-gate 			ioparam.io_bounds.upper = physsects() - 1;
2757c478bd9Sstevel@tonic-gate 		} else if (cur_disk->label_type == L_TYPE_EFI) {
2767c478bd9Sstevel@tonic-gate 			ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba;
2777c478bd9Sstevel@tonic-gate 		}
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 		scan_lower = (diskaddr_t)input(FIO_BN,
2807c478bd9Sstevel@tonic-gate 		    "Enter starting block number", ':',
2817c478bd9Sstevel@tonic-gate 		    &ioparam, (int *)&scan_lower, DATA_INPUT);
2827c478bd9Sstevel@tonic-gate 		ioparam.io_bounds.lower = scan_lower;
2837c478bd9Sstevel@tonic-gate 		if (scan_upper < scan_lower)
2847c478bd9Sstevel@tonic-gate 			scan_upper = scan_lower;
2857c478bd9Sstevel@tonic-gate 		scan_upper = (diskaddr_t)input(FIO_BN,
2867c478bd9Sstevel@tonic-gate 		    "Enter ending block number", ':',
2877c478bd9Sstevel@tonic-gate 		    &ioparam, (int *)&scan_upper, DATA_INPUT);
2887c478bd9Sstevel@tonic-gate 	}
2897c478bd9Sstevel@tonic-gate 	deflt = !scan_loop;
2907c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
2917c478bd9Sstevel@tonic-gate 	scan_loop = !input(FIO_MSTR, "Loop continuously", '?',
2927c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
2937c478bd9Sstevel@tonic-gate 	/*
2947c478bd9Sstevel@tonic-gate 	 * If we are not looping continuously, input the number of passes.
2957c478bd9Sstevel@tonic-gate 	 */
2967c478bd9Sstevel@tonic-gate 	if (!scan_loop) {
2977c478bd9Sstevel@tonic-gate 		ioparam.io_bounds.lower = 1;
2987c478bd9Sstevel@tonic-gate 		ioparam.io_bounds.upper = 100;
2997c478bd9Sstevel@tonic-gate 		scan_passes = input(FIO_INT, "Enter number of passes", ':',
3007c478bd9Sstevel@tonic-gate 		    &ioparam, &scan_passes, DATA_INPUT);
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 	deflt = !scan_correct;
3037c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3047c478bd9Sstevel@tonic-gate 	scan_correct = !input(FIO_MSTR, "Repair defective blocks", '?',
3057c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3067c478bd9Sstevel@tonic-gate 	deflt = !scan_stop;
3077c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3087c478bd9Sstevel@tonic-gate 	scan_stop = !input(FIO_MSTR, "Stop after first error", '?',
3097c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3107c478bd9Sstevel@tonic-gate 	deflt = !scan_random;
3117c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3127c478bd9Sstevel@tonic-gate 	scan_random = !input(FIO_MSTR, "Use random bit patterns", '?',
3137c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3147c478bd9Sstevel@tonic-gate 	ioparam.io_bounds.lower = 1;
3157c478bd9Sstevel@tonic-gate 	/*
3167c478bd9Sstevel@tonic-gate 	 * The number of blocks per transfer is limited by the buffer
3177c478bd9Sstevel@tonic-gate 	 * size, or the scan boundaries, whichever is smaller.
3187c478bd9Sstevel@tonic-gate 	 */
3197c478bd9Sstevel@tonic-gate 	if ((scan_entire) && (cur_disk->label_type == L_TYPE_SOLARIS)) {
3207c478bd9Sstevel@tonic-gate 		size = physsects() - 1;
3217c478bd9Sstevel@tonic-gate 	} else if ((scan_entire) && (cur_disk->label_type == L_TYPE_EFI)) {
3227c478bd9Sstevel@tonic-gate 		size = cur_parts->etoc->efi_last_lba;
3237c478bd9Sstevel@tonic-gate 	} else {
3247c478bd9Sstevel@tonic-gate 		size = scan_upper - scan_lower + 1;
3257c478bd9Sstevel@tonic-gate 	}
3267c478bd9Sstevel@tonic-gate 	ioparam.io_bounds.upper = min(size, BUF_SECTS);
3277c478bd9Sstevel@tonic-gate 	if (scan_size > ioparam.io_bounds.upper)
3287c478bd9Sstevel@tonic-gate 		scan_size = ioparam.io_bounds.upper;
329342440ecSPrasad Singamsetty 	scan_size = input(FIO_INT, "Enter number of blocks per transfer", ':',
330342440ecSPrasad Singamsetty 	    &ioparam, (int *)&scan_size, DATA_INPUT);
3317c478bd9Sstevel@tonic-gate 	deflt = !scan_auto;
3327c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3337c478bd9Sstevel@tonic-gate 	scan_auto = !input(FIO_MSTR, "Verify media after formatting", '?',
3347c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	deflt = !option_msg;
3377c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3387c478bd9Sstevel@tonic-gate 	option_msg = !input(FIO_MSTR, "Enable extended messages", '?',
3397c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3407c478bd9Sstevel@tonic-gate 	deflt = !scan_restore_defects;
3417c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3427c478bd9Sstevel@tonic-gate 	scan_restore_defects = !input(FIO_MSTR, "Restore defect list", '?',
3437c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3447c478bd9Sstevel@tonic-gate 	deflt = !scan_restore_label;
3457c478bd9Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3467c478bd9Sstevel@tonic-gate 	scan_restore_label = !input(FIO_MSTR, "Restore disk label", '?',
3477c478bd9Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3487c478bd9Sstevel@tonic-gate 	fmt_print("\n");
3497c478bd9Sstevel@tonic-gate 	return (0);
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate /*
3537c478bd9Sstevel@tonic-gate  * This routine implements the 'config' command.  It simply prints out
3547c478bd9Sstevel@tonic-gate  * the values of all the variables controlling surface analysis.  It
3557c478bd9Sstevel@tonic-gate  * is meant to complement the 'setup' command by allowing the user to
3567c478bd9Sstevel@tonic-gate  * check the current setup.
3577c478bd9Sstevel@tonic-gate  */
3587c478bd9Sstevel@tonic-gate int
a_config(void)359*b12aaafbSToomas Soome a_config(void)
3607c478bd9Sstevel@tonic-gate {
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	fmt_print("        Analyze entire disk? ");
3637c478bd9Sstevel@tonic-gate 	fmt_print(scan_entire ? "yes\n" : "no\n");
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	if (!scan_entire) {
3667c478bd9Sstevel@tonic-gate 		fmt_print("        Starting block number: %llu (", scan_lower);
3677c478bd9Sstevel@tonic-gate 		pr_dblock(fmt_print, scan_lower);
3687c478bd9Sstevel@tonic-gate 		fmt_print(")\n        Ending block number: %llu (", scan_upper);
3697c478bd9Sstevel@tonic-gate 		pr_dblock(fmt_print, scan_upper);
3707c478bd9Sstevel@tonic-gate 		fmt_print(")\n");
3717c478bd9Sstevel@tonic-gate 	}
3727c478bd9Sstevel@tonic-gate 	fmt_print("        Loop continuously? ");
3737c478bd9Sstevel@tonic-gate 	fmt_print(scan_loop ? "yes\n" : "no\n");
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	if (!scan_loop) {
3767c478bd9Sstevel@tonic-gate 		fmt_print("        Number of passes: %d\n", scan_passes);
3777c478bd9Sstevel@tonic-gate 	}
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	fmt_print("        Repair defective blocks? ");
3807c478bd9Sstevel@tonic-gate 	fmt_print(scan_correct ? "yes\n" : "no\n");
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	fmt_print("        Stop after first error? ");
3837c478bd9Sstevel@tonic-gate 	fmt_print(scan_stop ? "yes\n" : "no\n");
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	fmt_print("        Use random bit patterns? ");
3867c478bd9Sstevel@tonic-gate 	fmt_print(scan_random ? "yes\n" : "no\n");
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	fmt_print("        Number of blocks per transfer: %d (", scan_size);
389342440ecSPrasad Singamsetty 	pr_dblock(fmt_print, (diskaddr_t)scan_size);
3907c478bd9Sstevel@tonic-gate 	fmt_print(")\n");
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	fmt_print("        Verify media after formatting? ");
3937c478bd9Sstevel@tonic-gate 	fmt_print(scan_auto ? "yes\n" : "no\n");
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	fmt_print("        Enable extended messages? ");
3967c478bd9Sstevel@tonic-gate 	fmt_print(option_msg ? "yes\n" : "no\n");
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	fmt_print("        Restore defect list? ");
3997c478bd9Sstevel@tonic-gate 	fmt_print(scan_restore_defects ? "yes\n" : "no\n");
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	fmt_print("        Restore disk label? ");
4027c478bd9Sstevel@tonic-gate 	fmt_print(scan_restore_label ? "yes\n" : "no\n");
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	fmt_print("\n");
4057c478bd9Sstevel@tonic-gate 	return (0);
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate /*
4097c478bd9Sstevel@tonic-gate  * This routine implements the 'purge' command.  It purges the disk
4107c478bd9Sstevel@tonic-gate  * by writing three patterns to the disk then reading the last one back.
4117c478bd9Sstevel@tonic-gate  * It is not ok to run this command on any data you want to keep.
4127c478bd9Sstevel@tonic-gate  */
4137c478bd9Sstevel@tonic-gate int
a_purge(void)414*b12aaafbSToomas Soome a_purge(void)
4157c478bd9Sstevel@tonic-gate {
4167c478bd9Sstevel@tonic-gate 	int status = 0;
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	/*
4197c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
4207c478bd9Sstevel@tonic-gate 	 */
4217c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
4227c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
4237c478bd9Sstevel@tonic-gate 		return (-1);
4247c478bd9Sstevel@tonic-gate 	}
4257c478bd9Sstevel@tonic-gate 	if (scan_random) {
4267c478bd9Sstevel@tonic-gate 		fmt_print("The purge command does not write random data\n");
4277c478bd9Sstevel@tonic-gate 		scan_random = 0;
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	if (!scan_loop && (scan_passes <= NPPATTERNS)) {
4317c478bd9Sstevel@tonic-gate 		if (scan_passes < NPPATTERNS) {
4327c478bd9Sstevel@tonic-gate 			fmt_print("The purge command runs for a minimum of ");
4337c478bd9Sstevel@tonic-gate 			fmt_print("%d passes plus a last pass if the\n",
4347c478bd9Sstevel@tonic-gate 			    NPPATTERNS);
4357c478bd9Sstevel@tonic-gate 			fmt_print("first %d passes were successful.\n",
4367c478bd9Sstevel@tonic-gate 			    NPPATTERNS);
4377c478bd9Sstevel@tonic-gate 		}
4387c478bd9Sstevel@tonic-gate 		scan_passes = NPPATTERNS + 1;
4397c478bd9Sstevel@tonic-gate 	}
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	if (check(
4427c478bd9Sstevel@tonic-gate "Ready to purge (will corrupt data). This takes a long time, \n"
443d5f26e6cSbo zhou - Sun Microsystems - Beijing China "but is interruptible with CTRL-C. Continue"))
4447c478bd9Sstevel@tonic-gate 		return (-1);
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	status = do_scan(SCAN_PATTERN | SCAN_PURGE, F_NORMAL);
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 	return (status);
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate /*
4527c478bd9Sstevel@tonic-gate  * This routine implements the 'verify' command.  It writes the disk
4537c478bd9Sstevel@tonic-gate  * by writing unique data for each block; after the write pass, it
4547c478bd9Sstevel@tonic-gate  * reads the data and verifies for correctness. Note that the entire
4557c478bd9Sstevel@tonic-gate  * disk (or the range of disk) is fully written first and then read.
4567c478bd9Sstevel@tonic-gate  * This should eliminate any caching effect on the drives.
4577c478bd9Sstevel@tonic-gate  * It is not ok to run this command on any data you want to keep.
4587c478bd9Sstevel@tonic-gate  */
4597c478bd9Sstevel@tonic-gate int
a_verify(void)460*b12aaafbSToomas Soome a_verify(void)
4617c478bd9Sstevel@tonic-gate {
4627c478bd9Sstevel@tonic-gate 	/*
4637c478bd9Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
4647c478bd9Sstevel@tonic-gate 	 */
4657c478bd9Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
4667c478bd9Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
4677c478bd9Sstevel@tonic-gate 		return (-1);
4687c478bd9Sstevel@tonic-gate 	}
4697c478bd9Sstevel@tonic-gate 	if (scan_random) {
4707c478bd9Sstevel@tonic-gate 		fmt_print("The verify command does not write random data\n");
4717c478bd9Sstevel@tonic-gate 		scan_random = 0;
4727c478bd9Sstevel@tonic-gate 	}
4737c478bd9Sstevel@tonic-gate 	if (scan_passes < 2 && !scan_loop) {
4747c478bd9Sstevel@tonic-gate 		scan_passes = 2;
4757c478bd9Sstevel@tonic-gate 		fmt_print("The verify command runs minimum of 2 passes, one"
4767c478bd9Sstevel@tonic-gate 		    " for writing and \nanother for reading and verfying."
4777c478bd9Sstevel@tonic-gate 		    " Resetting the number of passes to 2.\n");
4787c478bd9Sstevel@tonic-gate 	}
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	if (check("Ready to verify (will corrupt data). This takes a long time,"
481d5f26e6cSbo zhou - Sun Microsystems - Beijing China 	    "\nbut is interruptible with CTRL-C. Continue")) {
4827c478bd9Sstevel@tonic-gate 		return (-1);
4837c478bd9Sstevel@tonic-gate 	}
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	return (do_scan(SCAN_WRITE | SCAN_VERIFY, F_NORMAL));
4867c478bd9Sstevel@tonic-gate }
487