📄 dteei.c
字号:
#if defined(EEI)/**************************************************************************** * * * COPYRIGHT (c) 1990 - 2004 * * This Software Provided * * By * * Robin's Nest Software Inc. * * * * Permission to use, copy, modify, distribute and sell this software and * * its documentation for any purpose and without fee is hereby granted, * * provided that the above copyright notice appear in all copies and that * * both that copyright notice and this permission notice appear in the * * supporting documentation, and that the name of the author not be used * * in advertising or publicity pertaining to distribution of the software * * without specific, written prior permission. * * * * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * * NO EVENT SHALL HE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL * * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF * * THIS SOFTWARE. * * * ****************************************************************************//* * Module: dteei.c * Author: Robin T. Miller * Date: September 13, 1997 * * Description: * This file contains functions for support of DEC EEI interface. * * Modification History: * * November 17th, 2003 by Robin Miller. * Breakup output to stdout or stderr, rather than writing * all output to stderr. If output file is stdout ('-') or a log * file is specified, then all output reverts to stderr. * * April 21st, 2000 by Robin Miller. * Converted tabs to spaces in all messages, so formatting is not * screwed up when messages are prefixed by a timestamp or process ID. * * April 10th, 2000 by Robin Miller. * For Wave4, added logic to handle EEI_DEVPATH_FAILURE, so we try * to re-open the tape device to 1) find another path (multi-pathing) or * 2) force DRD failover (find another server for the tape). * * February 19th, 2000 by Robin Miller. * While processing a reset condition, if another operation errors * with no EEI status (EEI_NO_STATUS), then retry that operation. This * may be a driver related problem, but we wish to recover from this. * If not compiled for Tru64 clusters, retry target selection timeouts. * * February 14th, 2000 by Robin Miller. * Merge Mike Gilmore's changes: * - change the data format from DEVIOCGET to DEVGETINFO. * * March 25, 1999 by Robin Miller. * Fix problem with my fileno going negative (bad check). * * February 25, 1999 by Robin Miller. * Add support for multiple reset conditions. * * December 21, 1998 by Robin Miller. * Add HandleTapeResets() to reposition the tape after resets. * * March 11, 1998 by George Bittner. * Remove unnecessary include files for building in steelos. * */#include "dt.h"#include <sys/fcntl.h>#include <sys/ioctl.h>#include <sys/ioctl_compat.h>#include <sys/mtio.h>#include <io/common/iotypes.h>#include <io/common/devio.h>#include <io/common/devgetinfo.h>#include <io/cam/cam.h>#include <io/cam/scsi_all.h>#include <io/cam/scsi_status.h>#if !defined(STEELOS)# include <io/common/kds.h># include <io/cam/camdb.h># include <io/cam/cam_tape.h>#endif /* !defined(STEELOS) *//* * These three defines are, unfortunately, not defined in the CAM code * because they are always used only as bit fields in the entire sense * data structure. All we have available is the sense key itself. */#define ILI 0x20#define EOM 0x40#define FILE_MARK 0x80#define DNL 0 /* Disable newline. */#define PNL 1 /* Print newline. *//* * Declare CAM Debugging Definitions: */#define CDBG_BRIEF 0 /* Brief message text. */#define CDBG_FULL 1 /* Full message text. *//* * Additional Sense Code Table Entry Format: */struct sense_entry { u_char sense_code; /* Additional sense code. */ u_char sense_qualifier; /* Sense code qualifier. */ char *sense_message; /* Error message text. */};static char *not_valid_str = "<Not Valid>";long mt_blkno; /* Starting tape block number. */long mt_fileno; /* Starting tape file number. *//* * Forward References: */bool is_ResetCondition(struct dinfo *dip, DEV_EEI_STATUS *eei);bool is_StatusRetryable(struct dinfo *dip, DEV_EEI_STATUS *eei);void print_eei(DEV_EEI_STATUS *eei);void print_devio(int fd);void print_erreg(short erreg);void print_stat(long stat);void print_category(long stat, device_info_t *devinfop);void PrintNumeric(char *field_str, u_long numeric_value, int nl_flag);void PrintDecimal(char *field_str, u_long numeric_value, int nl_flag);void PrintHex(char *field_str, u_long numeric_value, int nl_flag);void PrintAscii(char *field_str, char *ascii_str, int nl_flag);void PrintFields(u_char *bptr, int length);char *cdbg_SenseKeyTable[];char *cdbg_CamStatus(u_char cam_status, int report_format);char *cdbg_ScsiStatus(u_char scsi_status, int report_format);char *cdbg_SenseMessage(struct all_req_sns_data *sdp);char *cdbg_EEIStatus(u_int eei_status, int report_format);/* * HandleTapeResets() - Handle Tape Reset Conditions. * * Description: * This function is called to do reset processing for tape devices. * The idea is to reposition the tape to the file/record position prior * to the reset, then retry the operation. * * Inputs: dip = The device information pointer. * * Return Value: * TRUE/FALSE = Retry Operation/Error the Request. * */boolHandleTapeResets(struct dinfo *dip){ int status; int fd = dip->di_fd; struct mtget mtget, *mt; int saved_errno; u_long fileno, files, records; if (dip->di_proc_eei) { mt = &mtget; memset(mt, '\0', sizeof(*mt)); } else { mt = dip->di_mt; } saved_errno = errno; status = get_eei_status(fd, mt); if (status != ESUCCESS) { errno = saved_errno; return (FALSE); } if (dip->di_mode == READ_MODE) { files = dip->di_files_read; records = dip->di_records_read; } else { files = dip->di_files_written; records = dip->di_records_written; } if (dip->di_proc_eei) { if (debug_flag) print_mtstatus(fd, mt, FALSE); /* * See if we should retry this EEI status. */ if ( is_StatusRetryable(dip, &mt->eei) ) { if (dip->di_eei_retries-- == 0) { dip->di_eei_retries = EEI_RETRIES; return (FALSE); /* Exhausted retries. */ } if (verbose_flag) { Printf("Retry %d after %s status...\n", (EEI_RETRIES - dip->di_eei_retries), cdbg_EEIStatus(mt->eei.status, CDBG_BRIEF)); } (void)sleep(dip->di_eei_sleep); return (TRUE); /* Retry please! */ } else if ( is_ResetCondition(dip, &mt->eei) ) { return (FALSE); /* Don't retry. */ } else { if (!debug_flag) print_mtstatus(fd, mt, TRUE); return (FALSE); /* Don't retry. */ } } if ( is_StatusRetryable(dip, &mt->eei) ) { if (verbose_flag) { Printf("Retrying after %s status...\n", cdbg_EEIStatus(mt->eei.status, CDBG_BRIEF)); } (void)sleep(dip->di_eei_sleep); return (TRUE); } else if ( !is_ResetCondition(dip, &mt->eei) ) { print_mtstatus(fd, mt, TRUE); return (FALSE); } dip->di_proc_eei = TRUE; /* For recursion. */ dip->di_eei_retries = EEI_RETRIES; if (verbose_flag) { Printf("Processing reset condition (%s) - file %lu, record %lu\n", cdbg_EEIStatus(mt->eei.status, CDBG_BRIEF), mt->mt_fileno, mt->mt_blkno); } if (debug_flag) print_mtstatus(fd, mt, FALSE); /* * When writing tape files, the last file mark gets written * when closing the tape, so adjust file count appropriately. */ fileno = files; if ( (dip->di_mode == WRITE_MODE) && (files == file_limit) ) { if (fileno) fileno--; } /* * Sanity check the block and file counts. */ if (mt->mt_fileno != (fileno + mt_fileno)) { /* NFG if the no-rewind device is used! */ Fprintf( "File count sanity check failed, mt_fileno = %ld, my count = %ld\n", mt->mt_fileno, (fileno + mt_fileno));#if 0 return (FALSE);#endif /* Adjust and continue below... */ mt->mt_fileno = (fileno + mt_fileno); } /* * ??? mt_blkno doesn't always match my counts ??? */ if ( mt->mt_blkno != (records + mt_blkno) ) { Fprintf( "Record count sanity check failed, mt_blkno = %ld, my count = %ld\n", mt->mt_blkno, (records + mt_blkno));#if 0 return (FALSE);#endif /* Adjust and continue below... */ mt->mt_blkno = (records + mt_blkno); }reposition: dip->di_reset_condition = FALSE;#if defined(STEELOS) if (dip->di_devpath_failure) { dip->di_devpath_failure = FALSE; /* We terminate if we can't re-open the device. */ (void) (*dip->di_funcs->tf_reopen_file)(dip, dip->di_oflags); } else { /* * Rewind and reposition the tape. */ status = DoRewindTape(dip); if (status) { if (dip->di_reset_condition) goto reposition; dip->di_proc_eei = FALSE; return (FALSE); } /* * Bring the tape online, driver calls ctape_online(), to force * auto-density selection to be done. Otherwise, we may proceed * with the wrong tape density. */ status = DoTapeOnline(dip); if (status) { if (dip->di_reset_condition) goto reposition; dip->di_proc_eei = FALSE; return (FALSE); } }#else /* !defined(STEELOS) */ /* * NOTE: Re-open the tape (assumes we're using rewind device), * and reposition the tape. The re-open of the tape is necessary * to clear state flags (CTAPE_UNIT_ATTEN_STATE & CTAPE_RESET_STATE) * in the CAM tape driver. If this is NOT done, the close function * won't write file marks. [ Fixed in Steel, not earlier releases! ] */ (void) (*dip->di_funcs->tf_reopen_file)(dip, dip->di_oflags); /* * NOTE: reopen of the tape also brings the tape online. */#endif /* !defined(STEELOS) */ /* * Finally, reposition to the correct file and block numbers. */ if (mt->mt_fileno) { long fileno = mt->mt_fileno; if (verbose_flag) { Printf("Positioning to file %lu...\n", fileno); } status = DoForwardSpaceFile(dip, fileno); if (status) { if (dip->di_reset_condition) goto reposition; dip->di_proc_eei = FALSE; return (FALSE); } } if (mt->mt_blkno) { long record = MIN(mt->mt_blkno, records); if (record) { if (verbose_flag) { Printf("Positioning to record %lu...\n", record); } status = DoForwardSpaceRecord(dip, record); if (status) { if (dip->di_reset_condition) goto reposition; dip->di_proc_eei = FALSE; return (FALSE); } } } dip->di_proc_eei = FALSE; /* * Don't need to clear EEI status here, since this function is * called recursively when tape movement IOCTL errors occur. */ return (TRUE);}boolis_ResetCondition( struct dinfo *dip, DEV_EEI_STATUS *eei ){ /* * For Reference: * * EEI_DEVPATH_RESET == ( CAM_SCSI_BUS_RESET || ASCQ_PON_RESET * || ASCQ_POWER_ON * || ASCQ_BUS_RESET * || ASCQ_BDR_RESET * || ASCQ_FIRMWARE_REBOOT ) * * EEI_CNTBUSY_FAILURE == CAM_BUSY * * A status of CAM_BUSY indicates the SIM/HBA is in recovery, * and usually that recovery is the result of reset handling. * So in the case of tapes, we reposition on CAM_BUSY too. * * NOTE: CAM_BDR_SENT belongs with EEI_DEVPATH_RESET :-) */ if ( (eei->status == EEI_DEVPATH_RESET) || (eei->status == EEI_CNTBUSY_FAILURE) || (eei->status == EEI_TAPE_POS_LOST) || (eei->arch.cam.cam_status == CAM_BDR_SENT) ) { dip->di_reset_condition = TRUE; (void) sleep (EEI_RESET); return (TRUE); } else if (eei->status == EEI_DEVSTATE_FAILURE) { struct all_req_sns_data *sdp; sdp = (struct all_req_sns_data *)&eei->arch.cam.scsi_sense; if ( (eei->flags & EEI_SCSI_SENSE_VALID) && (sdp->sns_key == ALL_UNIT_ATTEN) ) { dip->di_reset_condition = TRUE; return (TRUE); /* Result of reset or power on. */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -