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