usr/src/cmd/format/analyze.c
author sjelinek
Thu, 27 Oct 2005 09:01:18 -0700
changeset 767 0aa24dfb5d87
parent 0 68f95e015346
child 5421 872db5a31484
permissions -rw-r--r--
PSARC 2004/776 device checking for fs utilities PSARC 2005/461 Device in use checking environment variables 5084421 libdiskmgt needs to detect in use ZFS data 5085739 remove workaround for bug 4725434 6194015 Device in use checking for Solaris utilities-PSARC/2004/776 6261853 libdiskmgt does not work correctly in all cases on amd64 6268374 libdiskmgt allocates incorrect size for readdir_r() dirent argument 6291309 PSARC/2005/461 - libdiskmgt should enable bypassing of inuse checking 6301815 PSARC/2005/461-Need Sun private libdiskmgt flag for use during install to disable sysevent starting
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 * with the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
767
0aa24dfb5d87 PSARC 2004/776 device checking for fs utilities
sjelinek
parents: 0
diff changeset
    23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
 * This file contains routines to analyze the surface of a disk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
#include "global.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
#include "analyze.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
#include <stdlib.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
#include <errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
#include "misc.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
#include "defect.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
#include "label.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
#include "param.h"
767
0aa24dfb5d87 PSARC 2004/776 device checking for fs utilities
sjelinek
parents: 0
diff changeset
    40
#include "checkdev.h"
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
 * These global variables control the surface analysis process.  They
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
 * are set from a command in the defect menu.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
int	scan_entire = 1;		/* scan whole disk flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
diskaddr_t	scan_lower = 0;			/* lower bound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
diskaddr_t	scan_upper = 0;			/* upper bound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
int	scan_correct = 1;		/* correct errors flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
int	scan_stop = 0;			/* stop after error flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
int	scan_loop = 0;			/* loop forever flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
int	scan_passes = 2;		/* number of passes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
int	scan_random = 0;		/* random patterns flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
int	scan_size = 0;			/* sectors/scan operation */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
int	scan_auto = 1;			/* scan after format flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
int	scan_restore_defects = 1;	/* restore defect list after writing */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
int	scan_restore_label = 1;		/* restore label after writing */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
 * These are summary variables to print out info after analysis.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
 * Values less than 0 imply they are invalid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
offset_t	scan_cur_block = -1;		/* current block */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
int64_t		scan_blocks_fixed = -1;		/* # blocks repaired */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
 * This variable is used to tell whether the most recent surface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
 * analysis error was caused by a media defect or some other problem.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
int	media_error;			/* error was caused by defect */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
int	disk_error;			/* disk errors during analysis */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
 * These are the data patterns used if random patterns are not chosen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
 * They are designed to show pattern dependent errors.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
static unsigned int	scan_patterns[] = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
	0xc6dec6de,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
	0x6db6db6d,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
	0x00000000,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
	0xffffffff,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
	0xaaaaaaaa,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
#define	NPATTERNS	5		/* number of predefined patterns */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
 * These are the data patterns from the SunFed requirements document.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
static unsigned int purge_patterns[] = {	/* patterns to be written */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
	0xaaaaaaaa,		/* 10101010... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
	0x55555555,		/* 01010101...  == UUUU... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
	0xaaaaaaaa,		/* 10101010... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
	0xaaaaaaaa,		/* 10101010... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
static unsigned int alpha_pattern =  0x40404040;   /* 10000000...  == @@@@... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
/* Function prototypes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
#ifdef	__STDC__
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
static int	scan_repair(diskaddr_t bn, int mode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
static int	analyze_blocks(int flags, diskaddr_t blkno, int blkcnt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
		unsigned data, int init, int driver_flags, int *xfercntp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
static int	handle_error_conditions(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
static int	verify_blocks(int flags, diskaddr_t blkno, int blkcnt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
		unsigned data, int driver_flags, int *xfercntp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
#else	/* __STDC__ */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
static int	scan_repair();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
static int	analyze_blocks();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
static int	handle_error_conditions();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
static int	verify_blocks();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
#endif	/* __STDC__ */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
 * This routine performs a surface analysis based upon the global
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
 * parameters.  It is called from several commands in the defect menu,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
 * and from the format command in the command menu (if post-format
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
 * analysis is enable).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
do_scan(flags, mode)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
	int	flags, mode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
	diskaddr_t	start, end, curnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
	int	pass, size, needinit, data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
	int	status, founderr, i, j;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
	int	error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
	int	pattern = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
	int	xfercnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
	 * Check to be sure we aren't correcting without a defect list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
	 * if the controller can correct the defect.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
	if (scan_correct && !EMBEDDED_SCSI && (cur_ops->op_repair != NULL) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
			(cur_list.list == NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
		err_print("Current Defect List must be initialized ");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
		err_print("to do automatic repair.\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
	 * Define the bounds of the scan.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
	if (scan_entire) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
		start = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
	    if (cur_label == L_TYPE_SOLARIS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
		if (cur_ctype->ctype_flags & CF_SCSI)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
			end = datasects() - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
			end = physsects() - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
	    } else if (cur_label == L_TYPE_EFI) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
		end = cur_parts->etoc->efi_last_lba;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
	    }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
		start = scan_lower;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
		end = scan_upper;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
	 * Make sure the user knows if we are scanning over a mounted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
	 * partition.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
	if ((flags & (SCAN_PATTERN | SCAN_WRITE)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
	    (checkmount(start, end))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
		err_print("Cannot do analysis on a mounted partition.\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
	 * Make sure the user knows if we are scanning over a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
	 * partition being used for swapping.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
	if ((flags & (SCAN_PATTERN | SCAN_WRITE)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
	    (checkswap(start, end))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
		err_print("Cannot do analysis on a partition \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
which is currently being used for swapping.\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
	 * If we are scanning destructively over certain sectors,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
	 * we mark the defect list and/or label dirty so it will get rewritten.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
	if (flags & (SCAN_PATTERN | SCAN_WRITE)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
	    if (cur_label == L_TYPE_SOLARIS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
		if (start < (daddr_t)totalsects() &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
				end >= (daddr_t)datasects()) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
			if (!EMBEDDED_SCSI) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
				cur_list.flags |= LIST_DIRTY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
			if (cur_disk->disk_flags & DSK_LABEL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
				cur_flags |= LABEL_DIRTY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
	    }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
	    if (start == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
		if (cur_disk->disk_flags & DSK_LABEL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
			cur_flags |= LABEL_DIRTY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
	    }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
	 * Initialize the summary info on sectors repaired.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
	scan_blocks_fixed = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
	 * Loop through the passes of the scan. If required, loop forever.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
	for (pass = 0; pass < scan_passes || scan_loop; pass++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
		 * Determine the data pattern to use if pattern testing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
		 * is to be done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
		if (flags & SCAN_PATTERN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
			if (scan_random)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
				data = (int)mrand48();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
				data = scan_patterns[pass % NPPATTERNS];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
			if (flags & SCAN_PURGE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
				flags &= ~(SCAN_PURGE_READ_PASS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
						| SCAN_PURGE_ALPHA_PASS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
				switch (pattern % (NPPATTERNS + 1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
				case NPPATTERNS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
					pattern = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
					if (!error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
					    fmt_print(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
"\nThe last %d passes were successful, running alpha pattern pass", NPPATTERNS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
					    flags |= SCAN_PURGE_ALPHA_PASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
					    data = alpha_pattern;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
					} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
					    data = purge_patterns[pattern];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
					    pattern++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
					};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
				case READPATTERN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
					flags |=  SCAN_PURGE_READ_PASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
				default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
					data = purge_patterns[pattern];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
					pattern++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
			fmt_print("\n        pass %d", pass);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
			fmt_print(" - pattern = 0x%x", data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
		} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
			fmt_print("\n        pass %d", pass);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
		fmt_print("\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
		 * Mark the pattern buffer as corrupt, since it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
		 * hasn't been initialized.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
		needinit = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
		 * Print the first block number to the log file if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
		 * logging is on so there is some record of what
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
		 * analysis was performed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
		if (log_file) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
			pr_dblock(log_print, start);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
			log_print("\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
		 * Loop through this pass, each time analyzing an amount
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
		 * specified by the global parameters.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
		xfercnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
		for (curnt = start; curnt <= end; curnt += size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
			if ((end - curnt) < scan_size)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
				size = end - curnt + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
				size = scan_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
			 * Print out where we are, so we don't look dead.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
			 * Also store it in summary info for logging.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
			scan_cur_block = curnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
			nolog_print("   ");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
			pr_dblock(nolog_print, curnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
			nolog_print("  \015");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
			(void) fflush(stdout);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
			disk_error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
			 * Do the actual analysis.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
			status = analyze_blocks(flags, (daddr_t)curnt, size,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
			    (unsigned)data, needinit, (F_ALLERRS | F_SILENT),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
			    &xfercnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
			 * If there were no errors, the pattern buffer is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
			 * still initialized, and we just loop to next chunk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
			needinit = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
			if (!status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
			 * There was an error. Check if surface analysis
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
			 * can be continued.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
			if (handle_error_conditions()) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
				scan_blocks_fixed = scan_cur_block = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
				return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
			 * There was an error. Mark the pattern buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
			 * corrupt so it will get reinitialized.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
			needinit = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
			 * If it was not a media error, ignore it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
			if (!media_error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
			 * Loop 5 times through each sector of the chunk,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
			 * analyzing them individually.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
			nolog_print("   ");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
			pr_dblock(nolog_print, curnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
			nolog_print("  \015");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
			(void) fflush(stdout);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
			founderr = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
			for (j = 0; j < size * 5; j++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
				i = j % size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
				disk_error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
				status = analyze_blocks(flags, (daddr_t)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
				    (curnt + i), 1, (unsigned)data, needinit,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
				    F_ALLERRS, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
				needinit = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
				if (!status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
				 * There was an error. Check if surface analysis
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
				 * can be continued.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
				if (handle_error_conditions()) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
					scan_blocks_fixed = scan_cur_block = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
					return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
				 * An error occurred.  Mark the buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
				 * corrupt and see if it was media
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
				 * related.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
				needinit = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
				if (!media_error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
				 * We found a bad sector. Print out a message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
				 * and fix it if required.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
				founderr = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
				if (scan_correct && (flags != SCAN_VALID)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
					if (scan_repair(curnt+i, mode)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
						error = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
				} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
					err_print("\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
				 * Stop after the error if required.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
				if (scan_stop)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
					goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
			 * Mark the pattern buffer corrupt to be safe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
			needinit = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
			 * We didn't find an individual sector that was bad.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
			 * Print out a warning.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
			if (!founderr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
				err_print("Warning: unable to pinpoint ");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
				err_print("defective block.\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
		 * Print the end of each pass to the log file.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
		enter_critical();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
		if (log_file) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
			pr_dblock(log_print, scan_cur_block);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
			log_print("\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
		scan_cur_block = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
		exit_critical();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
		fmt_print("\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
		 * alternate the read and write for SCAN_VERIFY test
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
		if (flags & SCAN_VERIFY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
			flags ^= SCAN_VERIFY_READ_PASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
	 * We got here either by giving up after an error or falling
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
	 * through after all passes were completed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
	fmt_print("\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
	enter_critical();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
	 * If the defect list is dirty, write it to disk,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
	 * if scan_restore_defects (the default) is true.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
	if (!EMBEDDED_SCSI && (cur_list.flags & LIST_DIRTY) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
				(scan_restore_defects)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
		cur_list.flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
		write_deflist(&cur_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
	 * If the label is dirty, write it to disk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
	 * if scan_restore_label (the default) is true.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
	if ((cur_flags & LABEL_DIRTY) && (scan_restore_label)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
		cur_flags &= ~LABEL_DIRTY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
		(void) write_label();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
	 * If we dropped down to here after an error, we need to write
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
	 * the final block number to the log file for record keeping.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
	if (log_file && scan_cur_block >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
		pr_dblock(log_print, scan_cur_block);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
		log_print("\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
	fmt_print("Total of %lld defective blocks repaired.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
		scan_blocks_fixed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
	 * Reinitialize the logging variables so they don't get used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
	 * when they are not really valid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
	scan_blocks_fixed = scan_cur_block = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
	exit_critical();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
 * This routine is called to repair a bad block discovered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
 * during a scan operation.  Return 0 for success, 1 for failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
 * (This has been extracted out of do_scan(), to simplify it.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
scan_repair(bn, mode)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
	diskaddr_t	bn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
	int	mode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
	int	status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
	int	result = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
	char	buf[SECSIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
	int	buf_is_good;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
	if (cur_ops->op_repair == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
		err_print("Warning: Controller does ");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
		err_print("not support repairing.\n\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
		return (result);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
	enter_critical();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
	 * Determine if the error appears to be hard or soft.  We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
	 * already assume there's an error.  If we can get any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
	 * good data out of the sector, write that data back
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
	 * after the repair.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
	buf_is_good = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
	for (i = 0; i < 5; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
		status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
				buf, F_SILENT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
		if (status == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
			buf_is_good = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
	fmt_print("Repairing %s error on %llu (",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
				buf_is_good ? "soft" : "hard", bn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
	pr_dblock(fmt_print, bn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
	fmt_print(")...");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
	status = (*cur_ops->op_repair)(bn, mode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
	if (status) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
		 * If the repair failed, we note it and will return the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
		 * failure. However, the analysis goes on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
		fmt_print("failed.\n\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
		 * The repair worked.  Write the good data we could
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
		 * recover from the failed block, if possible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
		 * If not, zero the block.  In doing so, try to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
		 * determine if the new block appears ok.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
		if (!buf_is_good) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
			bzero(buf, SECSIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
			fmt_print("Warning: Block %llu zero-filled.\n", bn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
			fmt_print("ok.\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
		status = (*cur_ops->op_rdwr)(DIR_WRITE, cur_file, bn,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
					1, buf, (F_SILENT | F_ALLERRS), NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
		if (status == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
			status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, bn,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
					1, buf, (F_SILENT | F_ALLERRS), NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
		if (status) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
			fmt_print("The new block also appears defective.\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
		fmt_print("\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
		 * add the defect to the list and write the list out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
		 * Also, kill the working list so it will get resynced
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
		 * with the current list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
		 * For embedded scsi, we don't require a defect list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
		 * However, if we have one, add the defect if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
		 * list includes the grown list.  If not, kill it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
		 * to force a resync if we need the list later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
		if (EMBEDDED_SCSI) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
			if (cur_list.list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
				if (cur_list.flags & LIST_PGLIST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
					add_ldef(bn, &cur_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
					kill_deflist(&cur_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
		 * The next "if" statement reflects the fix for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
		 * bug id 1026096 where format keeps adding the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
		 * same defect to the defect list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
		} else if (cur_ctype->ctype_flags & CF_WLIST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
			kill_deflist(&cur_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
			(*cur_ops->op_ex_cur)(&cur_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
			fmt_print("Current list updated\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
			add_ldef(bn, &cur_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
			write_deflist(&cur_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
		kill_deflist(&work_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
		/* Log the repair.  */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
		scan_blocks_fixed++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
		/* return ok */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
		result = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
	exit_critical();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
	return (result);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
 * This routine analyzes a set of sectors on the disk.  It simply returns
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
 * an error if a defect is found.  It is called by do_scan().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
analyze_blocks(flags, blkno, blkcnt, data, init, driver_flags, xfercntp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
	int	flags, driver_flags, blkcnt, init;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
	register unsigned data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
	diskaddr_t	blkno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
	int	*xfercntp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
	int	corrupt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
	register int	status, i, nints;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
	register unsigned *ptr = (uint_t *)pattern_buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
	media_error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
	if (flags & SCAN_VERIFY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
		return (verify_blocks(flags, blkno, blkcnt, data,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
		    driver_flags, xfercntp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
	 * Initialize the pattern buffer if necessary.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
	nints = blkcnt * SECSIZE / sizeof (int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
	if ((flags & SCAN_PATTERN) && init) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
		for (i = 0; i < nints; i++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
			*((int *)((int *)pattern_buf + i)) = data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
	 * Lock out interrupts so we can insure valid data will get
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
	 * restored. This is necessary because there are modes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
	 * of scanning that corrupt the disk data then restore it at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
	 * the end of the analysis.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
	enter_critical();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
	 * If the disk data is valid, read it into the data buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
	if (flags & SCAN_VALID) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
		status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, blkno,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
		    blkcnt, (caddr_t)cur_buf, driver_flags, xfercntp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
		if (status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
			goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
	 * If we are doing pattern testing, write and read the pattern
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
	 * from the pattern buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
	if (flags & SCAN_PATTERN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
		 * If the disk data was valid, mark it corrupt so we know
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
		 * to restore it later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
		if (flags & SCAN_VALID)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
			corrupt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
		 * Only write if we're not on the read pass of SCAN_PURGE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
		if (!(flags & SCAN_PURGE_READ_PASS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
			status = (*cur_ops->op_rdwr)(DIR_WRITE, cur_file, blkno,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
			    blkcnt, (caddr_t)pattern_buf, driver_flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
			    xfercntp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
			if (status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
			    goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
		 * Only read if we are on the read pass of SCAN_PURGE, if we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
		 * are purging.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
		if ((!(flags & SCAN_PURGE)) || (flags & SCAN_PURGE_READ_PASS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
			status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, blkno,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
			    blkcnt, (caddr_t)pattern_buf, driver_flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
			    xfercntp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
			if (status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
			    goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
	 * If we are doing a data compare, make sure the pattern
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
	 * came back intact.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
	 * Only compare if we are on the read pass of SCAN_PURGE, or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
	 * we wrote random data instead of the expected data pattern.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
	if ((flags & SCAN_COMPARE) || (flags & SCAN_PURGE_READ_PASS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
		for (i = nints, ptr = (uint_t *)pattern_buf; i; i--)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
			if (*ptr++ != data) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
				err_print("Data miscompare error (expecting ");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
				err_print("0x%x, got 0x%x) at ", data,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
					*((int *)((int *)pattern_buf +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
					(nints - i))));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
				pr_dblock(err_print, blkno);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
				err_print(", offset = 0x%x.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
					(nints - i) * sizeof (int));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
	 * If we are supposed to write data out, do so.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
	if (flags & SCAN_WRITE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
		status = (*cur_ops->op_rdwr)(DIR_WRITE, cur_file, blkno,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
		    blkcnt, (caddr_t)cur_buf, driver_flags, xfercntp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
		if (status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
			goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
	exit_critical();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
	 * No errors occurred, return ok.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
bad:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
	 * There was an error.  If the data was corrupted, we write it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
	 * out from the data buffer to restore it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
	if (corrupt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
		if ((*cur_ops->op_rdwr)(DIR_WRITE, cur_file, blkno,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
				blkcnt, (caddr_t)cur_buf, F_NORMAL, xfercntp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
		err_print("Warning: unable to restore original data.\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
	exit_critical();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
	 * Return the error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
	return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
 * This routine analyzes a set of sectors on the disk. It simply returns
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
 * an error if a defect is found.  It is called by analyze_blocks().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
 * For simplicity, this is done as a separate function instead of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
 * making the analyze_block routine complex.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
 * This routine implements the 'verify' command.  It writes the disk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
 * by writing unique data for each block; after the write pass, it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
 * reads the data and verifies for correctness. Note that the entire
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
 * disk (or the range of disk) is fully written first and then read.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
 * This should eliminate any caching effect on the drives.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
verify_blocks(int flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
		diskaddr_t blkno,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
		int blkcnt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
		unsigned data,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
		int driver_flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
		int *xfercntp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
	int		status, i, nints;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
	unsigned	*ptr = (uint_t *)pattern_buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
	nints = SECSIZE / sizeof (int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
	 * Initialize the pattern buffer if we are in write pass.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
	 * Use the block number itself as data, each block has unique
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
	 * buffer data that way.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
	if (!(flags & SCAN_VERIFY_READ_PASS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
		for (data = blkno; data < blkno + blkcnt; data++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
			for (i = 0; i < nints; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
				*ptr++ = data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
		ptr = (uint_t *)pattern_buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
	 * Only write if we're not on the read pass of SCAN_VERIFY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
	if (!(flags & SCAN_VERIFY_READ_PASS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
		status = (*cur_ops->op_rdwr)(DIR_WRITE, cur_file, blkno,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
		    blkcnt, (caddr_t)pattern_buf, driver_flags, xfercntp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
		if (status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
			goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
		 * Only read if we are on the read pass of SCAN_VERIFY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
		status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, blkno,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
		    blkcnt, (caddr_t)pattern_buf, driver_flags, xfercntp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
		if (status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
			goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
		 * compare and make sure the pattern came back intact.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
		for (data = blkno; data < blkno + blkcnt; data++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
		    for (i = 0; i < nints; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
			if (*ptr++ != data) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
			    ptr--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
			    err_print("Data miscompare error (expecting "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
				"0x%x, got 0x%x) at ", data, *ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
			    pr_dblock(err_print, blkno);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
			    err_print(", offset = 0x%x.\n", (ptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
				(uint_t *)pattern_buf) * sizeof (int));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
			    goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
		    }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
	 * No errors occurred, return ok.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
bad:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
	return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
handle_error_conditions()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
	 * Check if the errno is ENXIO.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
	if (errno == ENXIO) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
		fmt_print("\n\nWarning:Cannot access drive, ");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
		fmt_print("aborting surface analysis.\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
	 * check for disk errors
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
	switch (disk_error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
	case DISK_STAT_RESERVED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
	case DISK_STAT_UNAVAILABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
		fmt_print("\n\nWarning:Drive may be reserved ");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
		fmt_print("or has been removed, ");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
		fmt_print("aborting surface analysis.\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
	case DISK_STAT_NOTREADY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
		fmt_print("\n\nWarning: Drive not ready, ");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
		fmt_print("aborting surface analysis.\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
	case DISK_STAT_DATA_PROTECT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
		fmt_print("\n\nWarning: Drive is write protected, ");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
		fmt_print("aborting surface analysis.\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
}