10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57563SPrasad.Singamsetty@Sun.COM * Common Development and Distribution License (the "License"). 67563SPrasad.Singamsetty@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*9889SLarry.Liu@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* 270Sstevel@tonic-gate * This file contains functions implementing the analyze menu commands. 280Sstevel@tonic-gate */ 290Sstevel@tonic-gate #include <string.h> 300Sstevel@tonic-gate #include "global.h" 310Sstevel@tonic-gate #include "analyze.h" 320Sstevel@tonic-gate #include "misc.h" 330Sstevel@tonic-gate #include "menu_analyze.h" 340Sstevel@tonic-gate #include "param.h" 350Sstevel@tonic-gate 360Sstevel@tonic-gate 370Sstevel@tonic-gate 380Sstevel@tonic-gate /* 390Sstevel@tonic-gate * This routine implements the 'read' command. It performs surface 400Sstevel@tonic-gate * analysis by reading the disk. It is ok to run this command on 410Sstevel@tonic-gate * mounted file systems. 420Sstevel@tonic-gate */ 430Sstevel@tonic-gate int 440Sstevel@tonic-gate a_read() 450Sstevel@tonic-gate { 460Sstevel@tonic-gate /* 470Sstevel@tonic-gate * The current disk must be formatted before disk analysis. 480Sstevel@tonic-gate */ 490Sstevel@tonic-gate if (!(cur_flags & DISK_FORMATTED)) { 500Sstevel@tonic-gate err_print("Current Disk is unformatted.\n"); 510Sstevel@tonic-gate return (-1); 520Sstevel@tonic-gate } 530Sstevel@tonic-gate 540Sstevel@tonic-gate if (check( 550Sstevel@tonic-gate "Ready to analyze (won't harm SunOS). This takes a long time, \n" 567964SBo.Zhou@Sun.COM "but is interruptible with CTRL-C. Continue")) 570Sstevel@tonic-gate return (-1); 580Sstevel@tonic-gate return (do_scan(SCAN_VALID, F_NORMAL)); 590Sstevel@tonic-gate } 600Sstevel@tonic-gate 610Sstevel@tonic-gate /* 620Sstevel@tonic-gate * This routine implements the 'refresh' command. It performs surface 630Sstevel@tonic-gate * analysis by reading the disk then writing the same data back to the 640Sstevel@tonic-gate * disk. It is ok to run this command on file systems, but not while 650Sstevel@tonic-gate * they are mounted. 660Sstevel@tonic-gate */ 670Sstevel@tonic-gate int 680Sstevel@tonic-gate a_refresh() 690Sstevel@tonic-gate { 700Sstevel@tonic-gate /* 710Sstevel@tonic-gate * The current disk must be formatted before disk analysis. 720Sstevel@tonic-gate */ 730Sstevel@tonic-gate if (!(cur_flags & DISK_FORMATTED)) { 740Sstevel@tonic-gate err_print("Current Disk is unformatted.\n"); 750Sstevel@tonic-gate return (-1); 760Sstevel@tonic-gate } 770Sstevel@tonic-gate 780Sstevel@tonic-gate if (check( 790Sstevel@tonic-gate "Ready to analyze (won't harm data). This takes a long time, \n" 807964SBo.Zhou@Sun.COM "but is interruptible with CTRL-C. Continue")) 810Sstevel@tonic-gate return (-1); 820Sstevel@tonic-gate return (do_scan(SCAN_VALID | SCAN_WRITE, F_NORMAL)); 830Sstevel@tonic-gate } 840Sstevel@tonic-gate 850Sstevel@tonic-gate /* 860Sstevel@tonic-gate * This routine implements the 'test' command. It performs surface 870Sstevel@tonic-gate * analysis by reading the disk, writing then reading a pattern on the disk, 880Sstevel@tonic-gate * then writing the original data back to the disk. 890Sstevel@tonic-gate * It is ok to run this command on file systems, but not while they are 900Sstevel@tonic-gate * mounted. 910Sstevel@tonic-gate */ 920Sstevel@tonic-gate int 930Sstevel@tonic-gate a_test() 940Sstevel@tonic-gate { 950Sstevel@tonic-gate /* 960Sstevel@tonic-gate * The current disk must be formatted before disk analysis. 970Sstevel@tonic-gate */ 980Sstevel@tonic-gate if (!(cur_flags & DISK_FORMATTED)) { 990Sstevel@tonic-gate err_print("Current Disk is unformatted.\n"); 1000Sstevel@tonic-gate return (-1); 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate if (check( 1040Sstevel@tonic-gate "Ready to analyze (won't harm data). This takes a long time, \n" 1057964SBo.Zhou@Sun.COM "but is interruptible with CTRL-C. Continue")) 1060Sstevel@tonic-gate return (-1); 1070Sstevel@tonic-gate return (do_scan(SCAN_VALID | SCAN_PATTERN | SCAN_WRITE, F_NORMAL)); 1080Sstevel@tonic-gate } 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate /* 1110Sstevel@tonic-gate * This routine implements the 'write' command. It performs surface 1120Sstevel@tonic-gate * analysis by writing a pattern to the disk then reading it back. 1130Sstevel@tonic-gate * It is not ok to run this command on any data you want to keep. 1140Sstevel@tonic-gate */ 1150Sstevel@tonic-gate int 1160Sstevel@tonic-gate a_write() 1170Sstevel@tonic-gate { 1180Sstevel@tonic-gate /* 1190Sstevel@tonic-gate * The current disk must be formatted before disk analysis. 1200Sstevel@tonic-gate */ 1210Sstevel@tonic-gate if (!(cur_flags & DISK_FORMATTED)) { 1220Sstevel@tonic-gate err_print("Current Disk is unformatted.\n"); 1230Sstevel@tonic-gate return (-1); 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate if (check( 1270Sstevel@tonic-gate "Ready to analyze (will corrupt data). This takes a long time, \n" 1287964SBo.Zhou@Sun.COM "but is interruptible with CTRL-C. Continue")) 1290Sstevel@tonic-gate return (-1); 1300Sstevel@tonic-gate return (do_scan(SCAN_PATTERN, F_NORMAL)); 1310Sstevel@tonic-gate } 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /* 1340Sstevel@tonic-gate * This routine implements the 'compare' command. It performs surface 1350Sstevel@tonic-gate * analysis by writing a pattern to the disk, reading it back, then 1360Sstevel@tonic-gate * checking the data to be sure it's the same. 1370Sstevel@tonic-gate * It is not ok to run this command on any data you want to keep. 1380Sstevel@tonic-gate */ 1390Sstevel@tonic-gate int 1400Sstevel@tonic-gate a_compare() 1410Sstevel@tonic-gate { 1420Sstevel@tonic-gate /* 1430Sstevel@tonic-gate * The current disk must be formatted before disk analysis. 1440Sstevel@tonic-gate */ 1450Sstevel@tonic-gate if (!(cur_flags & DISK_FORMATTED)) { 1460Sstevel@tonic-gate err_print("Current Disk is unformatted.\n"); 1470Sstevel@tonic-gate return (-1); 1480Sstevel@tonic-gate } 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate if (check( 1510Sstevel@tonic-gate "Ready to analyze (will corrupt data). This takes a long time, \n" 1527964SBo.Zhou@Sun.COM "but is interruptible with CTRL-C. Continue")) 1530Sstevel@tonic-gate return (-1); 1540Sstevel@tonic-gate return (do_scan(SCAN_PATTERN | SCAN_COMPARE, F_NORMAL)); 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate /* 1580Sstevel@tonic-gate * This routine implements the 'print' command. It displays the data 1590Sstevel@tonic-gate * buffer in hexadecimal. It is only useful for checking the disk for 1600Sstevel@tonic-gate * a specific set of data (by reading it then printing it). 1610Sstevel@tonic-gate */ 1620Sstevel@tonic-gate int 1630Sstevel@tonic-gate a_print() 1640Sstevel@tonic-gate { 1650Sstevel@tonic-gate int i, j, lines, nomore = 0; 1660Sstevel@tonic-gate int c, one_line = 0; 1670Sstevel@tonic-gate int tty_lines = get_tty_lines(); 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate /* 1700Sstevel@tonic-gate * If we are running out of command file, don't page the output. 1710Sstevel@tonic-gate * Otherwise we are running with a user. Turn off echoing of 1720Sstevel@tonic-gate * input characters so we can page the output. 1730Sstevel@tonic-gate */ 1740Sstevel@tonic-gate if (option_f || (!isatty(0)) || (!isatty(1))) 1750Sstevel@tonic-gate nomore++; 1760Sstevel@tonic-gate else { 1770Sstevel@tonic-gate enter_critical(); 1780Sstevel@tonic-gate echo_off(); 1790Sstevel@tonic-gate charmode_on(); 1800Sstevel@tonic-gate exit_critical(); 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate /* 1830Sstevel@tonic-gate * Loop through the data buffer. 1840Sstevel@tonic-gate */ 1850Sstevel@tonic-gate lines = 0; 186*9889SLarry.Liu@Sun.COM for (i = 0; i < scan_size * cur_blksz / sizeof (int); i += 6) { 1870Sstevel@tonic-gate /* 1880Sstevel@tonic-gate * Print the data. 1890Sstevel@tonic-gate */ 1900Sstevel@tonic-gate for (j = 0; j < 6; j++) 191*9889SLarry.Liu@Sun.COM if (i + j < scan_size * cur_blksz / sizeof (int)) 1920Sstevel@tonic-gate fmt_print("0x%08x ", 1937563SPrasad.Singamsetty@Sun.COM *((int *)((int *)cur_buf + i + j))); 1940Sstevel@tonic-gate fmt_print("\n"); 1950Sstevel@tonic-gate lines++; 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate /* 1980Sstevel@tonic-gate * If we are paging and hit the end of a page, wait for 1990Sstevel@tonic-gate * the user to hit either space-bar, "q", return, 2000Sstevel@tonic-gate * or ctrl-C before going on. 2010Sstevel@tonic-gate */ 2020Sstevel@tonic-gate if (one_line || 2030Sstevel@tonic-gate (!nomore && (lines % (tty_lines - 1) == 0))) { 2040Sstevel@tonic-gate /* 2050Sstevel@tonic-gate * Print until first screenfull 2060Sstevel@tonic-gate */ 2070Sstevel@tonic-gate if (lines < (tty_lines -1)) 2080Sstevel@tonic-gate continue; 2090Sstevel@tonic-gate /* 2100Sstevel@tonic-gate * Get the next character. 2110Sstevel@tonic-gate */ 2120Sstevel@tonic-gate (void) printf("- hit space for more - "); 2130Sstevel@tonic-gate c = getchar(); 2140Sstevel@tonic-gate (void) printf("\015"); 2150Sstevel@tonic-gate one_line = 0; 2160Sstevel@tonic-gate /* 2170Sstevel@tonic-gate * Handle display one line command (return key) 2180Sstevel@tonic-gate */ 2190Sstevel@tonic-gate if (c == '\012') { 2200Sstevel@tonic-gate one_line++; 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate /* Handle Quit command */ 2230Sstevel@tonic-gate if (c == 'q') { 2240Sstevel@tonic-gate (void) printf( 2250Sstevel@tonic-gate " \015"); 2260Sstevel@tonic-gate goto PRINT_EXIT; 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate /* handle ^D */ 2290Sstevel@tonic-gate if (c == '\004') 2300Sstevel@tonic-gate fullabort(); 2310Sstevel@tonic-gate } 2320Sstevel@tonic-gate } 2330Sstevel@tonic-gate /* 2340Sstevel@tonic-gate * If we were doing paging, turn echoing back on. 2350Sstevel@tonic-gate */ 2360Sstevel@tonic-gate PRINT_EXIT: 2370Sstevel@tonic-gate if (!nomore) { 2380Sstevel@tonic-gate enter_critical(); 2390Sstevel@tonic-gate charmode_off(); 2400Sstevel@tonic-gate echo_on(); 2410Sstevel@tonic-gate exit_critical(); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate return (0); 2440Sstevel@tonic-gate } 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate /* 2470Sstevel@tonic-gate * This routine implements the 'setup' command. It allows the user 2480Sstevel@tonic-gate * to program the variables that drive surface analysis. The approach 2490Sstevel@tonic-gate * is to prompt the user for the value of each variable, with the current 2500Sstevel@tonic-gate * value as the default. 2510Sstevel@tonic-gate */ 2520Sstevel@tonic-gate int 2530Sstevel@tonic-gate a_setup() 2540Sstevel@tonic-gate { 2550Sstevel@tonic-gate int deflt; 2560Sstevel@tonic-gate uint64_t size; 2570Sstevel@tonic-gate u_ioparam_t ioparam; 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate /* 2600Sstevel@tonic-gate * Because of the polarity of the yes/no structure (yes is 0), 2610Sstevel@tonic-gate * we have to invert the values for all yes/no questions. 2620Sstevel@tonic-gate */ 2630Sstevel@tonic-gate deflt = !scan_entire; 2640Sstevel@tonic-gate ioparam.io_charlist = confirm_list; 2650Sstevel@tonic-gate scan_entire = !input(FIO_MSTR, "Analyze entire disk", '?', 2660Sstevel@tonic-gate &ioparam, &deflt, DATA_INPUT); 2670Sstevel@tonic-gate /* 2680Sstevel@tonic-gate * If we are not scanning the whole disk, input the bounds of the scan. 2690Sstevel@tonic-gate */ 2700Sstevel@tonic-gate if (!scan_entire) { 2710Sstevel@tonic-gate ioparam.io_bounds.lower = 0; 2720Sstevel@tonic-gate if ((cur_ctype->ctype_flags & CF_SCSI) && 2730Sstevel@tonic-gate (cur_disk->label_type == L_TYPE_SOLARIS)) { 2747563SPrasad.Singamsetty@Sun.COM ioparam.io_bounds.upper = datasects() - 1; 2750Sstevel@tonic-gate } else if (cur_disk->label_type == L_TYPE_SOLARIS) { 2767563SPrasad.Singamsetty@Sun.COM ioparam.io_bounds.upper = physsects() - 1; 2770Sstevel@tonic-gate } else if (cur_disk->label_type == L_TYPE_EFI) { 2787563SPrasad.Singamsetty@Sun.COM ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; 2790Sstevel@tonic-gate } 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate scan_lower = (diskaddr_t)input(FIO_BN, 2820Sstevel@tonic-gate "Enter starting block number", ':', 2830Sstevel@tonic-gate &ioparam, (int *)&scan_lower, DATA_INPUT); 2840Sstevel@tonic-gate ioparam.io_bounds.lower = scan_lower; 2850Sstevel@tonic-gate if (scan_upper < scan_lower) 2860Sstevel@tonic-gate scan_upper = scan_lower; 2870Sstevel@tonic-gate scan_upper = (diskaddr_t)input(FIO_BN, 2880Sstevel@tonic-gate "Enter ending block number", ':', 2890Sstevel@tonic-gate &ioparam, (int *)&scan_upper, DATA_INPUT); 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate deflt = !scan_loop; 2920Sstevel@tonic-gate ioparam.io_charlist = confirm_list; 2930Sstevel@tonic-gate scan_loop = !input(FIO_MSTR, "Loop continuously", '?', 2940Sstevel@tonic-gate &ioparam, &deflt, DATA_INPUT); 2950Sstevel@tonic-gate /* 2960Sstevel@tonic-gate * If we are not looping continuously, input the number of passes. 2970Sstevel@tonic-gate */ 2980Sstevel@tonic-gate if (!scan_loop) { 2990Sstevel@tonic-gate ioparam.io_bounds.lower = 1; 3000Sstevel@tonic-gate ioparam.io_bounds.upper = 100; 3010Sstevel@tonic-gate scan_passes = input(FIO_INT, "Enter number of passes", ':', 3020Sstevel@tonic-gate &ioparam, &scan_passes, DATA_INPUT); 3030Sstevel@tonic-gate } 3040Sstevel@tonic-gate deflt = !scan_correct; 3050Sstevel@tonic-gate ioparam.io_charlist = confirm_list; 3060Sstevel@tonic-gate scan_correct = !input(FIO_MSTR, "Repair defective blocks", '?', 3070Sstevel@tonic-gate &ioparam, &deflt, DATA_INPUT); 3080Sstevel@tonic-gate deflt = !scan_stop; 3090Sstevel@tonic-gate ioparam.io_charlist = confirm_list; 3100Sstevel@tonic-gate scan_stop = !input(FIO_MSTR, "Stop after first error", '?', 3110Sstevel@tonic-gate &ioparam, &deflt, DATA_INPUT); 3120Sstevel@tonic-gate deflt = !scan_random; 3130Sstevel@tonic-gate ioparam.io_charlist = confirm_list; 3140Sstevel@tonic-gate scan_random = !input(FIO_MSTR, "Use random bit patterns", '?', 3150Sstevel@tonic-gate &ioparam, &deflt, DATA_INPUT); 3160Sstevel@tonic-gate ioparam.io_bounds.lower = 1; 3170Sstevel@tonic-gate /* 3180Sstevel@tonic-gate * The number of blocks per transfer is limited by the buffer 3190Sstevel@tonic-gate * size, or the scan boundaries, whichever is smaller. 3200Sstevel@tonic-gate */ 3210Sstevel@tonic-gate if ((scan_entire) && (cur_disk->label_type == L_TYPE_SOLARIS)) { 3220Sstevel@tonic-gate size = physsects() - 1; 3230Sstevel@tonic-gate } else if ((scan_entire) && (cur_disk->label_type == L_TYPE_EFI)) { 3240Sstevel@tonic-gate size = cur_parts->etoc->efi_last_lba; 3250Sstevel@tonic-gate } else { 3260Sstevel@tonic-gate size = scan_upper - scan_lower + 1; 3270Sstevel@tonic-gate } 3280Sstevel@tonic-gate ioparam.io_bounds.upper = min(size, BUF_SECTS); 3290Sstevel@tonic-gate if (scan_size > ioparam.io_bounds.upper) 3300Sstevel@tonic-gate scan_size = ioparam.io_bounds.upper; 3317563SPrasad.Singamsetty@Sun.COM scan_size = input(FIO_INT, "Enter number of blocks per transfer", ':', 3327563SPrasad.Singamsetty@Sun.COM &ioparam, (int *)&scan_size, DATA_INPUT); 3330Sstevel@tonic-gate deflt = !scan_auto; 3340Sstevel@tonic-gate ioparam.io_charlist = confirm_list; 3350Sstevel@tonic-gate scan_auto = !input(FIO_MSTR, "Verify media after formatting", '?', 3360Sstevel@tonic-gate &ioparam, &deflt, DATA_INPUT); 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate deflt = !option_msg; 3390Sstevel@tonic-gate ioparam.io_charlist = confirm_list; 3400Sstevel@tonic-gate option_msg = !input(FIO_MSTR, "Enable extended messages", '?', 3410Sstevel@tonic-gate &ioparam, &deflt, DATA_INPUT); 3420Sstevel@tonic-gate deflt = !scan_restore_defects; 3430Sstevel@tonic-gate ioparam.io_charlist = confirm_list; 3440Sstevel@tonic-gate scan_restore_defects = !input(FIO_MSTR, "Restore defect list", '?', 3450Sstevel@tonic-gate &ioparam, &deflt, DATA_INPUT); 3460Sstevel@tonic-gate deflt = !scan_restore_label; 3470Sstevel@tonic-gate ioparam.io_charlist = confirm_list; 3480Sstevel@tonic-gate scan_restore_label = !input(FIO_MSTR, "Restore disk label", '?', 3490Sstevel@tonic-gate &ioparam, &deflt, DATA_INPUT); 3500Sstevel@tonic-gate fmt_print("\n"); 3510Sstevel@tonic-gate return (0); 3520Sstevel@tonic-gate } 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate /* 3550Sstevel@tonic-gate * This routine implements the 'config' command. It simply prints out 3560Sstevel@tonic-gate * the values of all the variables controlling surface analysis. It 3570Sstevel@tonic-gate * is meant to complement the 'setup' command by allowing the user to 3580Sstevel@tonic-gate * check the current setup. 3590Sstevel@tonic-gate */ 3600Sstevel@tonic-gate int 3610Sstevel@tonic-gate a_config() 3620Sstevel@tonic-gate { 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate fmt_print(" Analyze entire disk? "); 3650Sstevel@tonic-gate fmt_print(scan_entire ? "yes\n" : "no\n"); 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate if (!scan_entire) { 3680Sstevel@tonic-gate fmt_print(" Starting block number: %llu (", scan_lower); 3690Sstevel@tonic-gate pr_dblock(fmt_print, scan_lower); 3700Sstevel@tonic-gate fmt_print(")\n Ending block number: %llu (", scan_upper); 3710Sstevel@tonic-gate pr_dblock(fmt_print, scan_upper); 3720Sstevel@tonic-gate fmt_print(")\n"); 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate fmt_print(" Loop continuously? "); 3750Sstevel@tonic-gate fmt_print(scan_loop ? "yes\n" : "no\n"); 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate if (!scan_loop) { 3780Sstevel@tonic-gate fmt_print(" Number of passes: %d\n", scan_passes); 3790Sstevel@tonic-gate } 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate fmt_print(" Repair defective blocks? "); 3820Sstevel@tonic-gate fmt_print(scan_correct ? "yes\n" : "no\n"); 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate fmt_print(" Stop after first error? "); 3850Sstevel@tonic-gate fmt_print(scan_stop ? "yes\n" : "no\n"); 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate fmt_print(" Use random bit patterns? "); 3880Sstevel@tonic-gate fmt_print(scan_random ? "yes\n" : "no\n"); 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate fmt_print(" Number of blocks per transfer: %d (", scan_size); 3917563SPrasad.Singamsetty@Sun.COM pr_dblock(fmt_print, (diskaddr_t)scan_size); 3920Sstevel@tonic-gate fmt_print(")\n"); 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate fmt_print(" Verify media after formatting? "); 3950Sstevel@tonic-gate fmt_print(scan_auto ? "yes\n" : "no\n"); 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate fmt_print(" Enable extended messages? "); 3980Sstevel@tonic-gate fmt_print(option_msg ? "yes\n" : "no\n"); 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate fmt_print(" Restore defect list? "); 4010Sstevel@tonic-gate fmt_print(scan_restore_defects ? "yes\n" : "no\n"); 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate fmt_print(" Restore disk label? "); 4040Sstevel@tonic-gate fmt_print(scan_restore_label ? "yes\n" : "no\n"); 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate fmt_print("\n"); 4070Sstevel@tonic-gate return (0); 4080Sstevel@tonic-gate } 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate /* 4110Sstevel@tonic-gate * This routine implements the 'purge' command. It purges the disk 4120Sstevel@tonic-gate * by writing three patterns to the disk then reading the last one back. 4130Sstevel@tonic-gate * It is not ok to run this command on any data you want to keep. 4140Sstevel@tonic-gate */ 4150Sstevel@tonic-gate int 4160Sstevel@tonic-gate a_purge() 4170Sstevel@tonic-gate { 4180Sstevel@tonic-gate int status = 0; 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate /* 4210Sstevel@tonic-gate * The current disk must be formatted before disk analysis. 4220Sstevel@tonic-gate */ 4230Sstevel@tonic-gate if (!(cur_flags & DISK_FORMATTED)) { 4240Sstevel@tonic-gate err_print("Current Disk is unformatted.\n"); 4250Sstevel@tonic-gate return (-1); 4260Sstevel@tonic-gate } 4270Sstevel@tonic-gate if (scan_random) { 4280Sstevel@tonic-gate fmt_print("The purge command does not write random data\n"); 4290Sstevel@tonic-gate scan_random = 0; 4300Sstevel@tonic-gate } 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate if (!scan_loop && (scan_passes <= NPPATTERNS)) { 4330Sstevel@tonic-gate if (scan_passes < NPPATTERNS) { 4340Sstevel@tonic-gate fmt_print("The purge command runs for a minimum of "); 4350Sstevel@tonic-gate fmt_print("%d passes plus a last pass if the\n", 4367563SPrasad.Singamsetty@Sun.COM NPPATTERNS); 4370Sstevel@tonic-gate fmt_print("first %d passes were successful.\n", 4387563SPrasad.Singamsetty@Sun.COM NPPATTERNS); 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate scan_passes = NPPATTERNS + 1; 4410Sstevel@tonic-gate } 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate if (check( 4440Sstevel@tonic-gate "Ready to purge (will corrupt data). This takes a long time, \n" 4457964SBo.Zhou@Sun.COM "but is interruptible with CTRL-C. Continue")) 4460Sstevel@tonic-gate return (-1); 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate status = do_scan(SCAN_PATTERN | SCAN_PURGE, F_NORMAL); 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate return (status); 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate /* 4540Sstevel@tonic-gate * This routine implements the 'verify' command. It writes the disk 4550Sstevel@tonic-gate * by writing unique data for each block; after the write pass, it 4560Sstevel@tonic-gate * reads the data and verifies for correctness. Note that the entire 4570Sstevel@tonic-gate * disk (or the range of disk) is fully written first and then read. 4580Sstevel@tonic-gate * This should eliminate any caching effect on the drives. 4590Sstevel@tonic-gate * It is not ok to run this command on any data you want to keep. 4600Sstevel@tonic-gate */ 4610Sstevel@tonic-gate int 4620Sstevel@tonic-gate a_verify() 4630Sstevel@tonic-gate { 4640Sstevel@tonic-gate /* 4650Sstevel@tonic-gate * The current disk must be formatted before disk analysis. 4660Sstevel@tonic-gate */ 4670Sstevel@tonic-gate if (!(cur_flags & DISK_FORMATTED)) { 4680Sstevel@tonic-gate err_print("Current Disk is unformatted.\n"); 4690Sstevel@tonic-gate return (-1); 4700Sstevel@tonic-gate } 4710Sstevel@tonic-gate if (scan_random) { 4720Sstevel@tonic-gate fmt_print("The verify command does not write random data\n"); 4730Sstevel@tonic-gate scan_random = 0; 4740Sstevel@tonic-gate } 4750Sstevel@tonic-gate if (scan_passes < 2 && !scan_loop) { 4760Sstevel@tonic-gate scan_passes = 2; 4770Sstevel@tonic-gate fmt_print("The verify command runs minimum of 2 passes, one" 4780Sstevel@tonic-gate " for writing and \nanother for reading and verfying." 4790Sstevel@tonic-gate " Resetting the number of passes to 2.\n"); 4800Sstevel@tonic-gate } 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate if (check("Ready to verify (will corrupt data). This takes a long time," 4837964SBo.Zhou@Sun.COM "\nbut is interruptible with CTRL-C. Continue")) { 4840Sstevel@tonic-gate return (-1); 4850Sstevel@tonic-gate } 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate return (do_scan(SCAN_WRITE | SCAN_VERIFY, F_NORMAL)); 4880Sstevel@tonic-gate } 489