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