📄 dteei.c
字号:
}#if defined(STEELOS) && defined(MUNSA) /* * On Wave4, a we must catch path failures and attempt to re-open * the tape, so we: * * 1) the tape driver looks for another path (multi-pathing) * 2) DRD will find a new server for this tape device. * * Again, for reference, here's the EEI_DEVPATH_FAILURE mapping: * * EEI_DEVPATH_FAILURE == ( CAM_PATH_INVALID || * CAM_DEV_NOT_THERE || * CAM_SEL_TIMEOUT || * CAM_NO_HBA || * CAM_LUN_INVALID || * CAM_TID_INVALID ) * */ if (eei->status == EEI_DEVPATH_FAILURE) { dip->di_devpath_failure = TRUE; dip->di_reset_condition = TRUE; return (TRUE); /* Re-open to find next path. */ }#endif /* defined(STEELOS) && defined(MUNSA) */ return (FALSE);}boolis_StatusRetryable( struct dinfo *dip, DEV_EEI_STATUS *eei ){ /* * Personally, I'm starting to think using EEI status mappings * is problematic, since its' groupings are subjective, and the * actual underlying status codes are hidden, so confusing :-) * * For Reference: * * EEI_DEVBUSY_FAILURE == SCSI_STAT_BUSY * * EEI_ABORTIO_FAILURE == ( CAM_REQ_ABORTED || CAM_CMD_TIMEOUT ) */ if ( (eei->status == EEI_DEVBUSY_FAILURE) || (eei->status == EEI_ABORTIO_FAILURE) ) { return (TRUE); /* Retry please! */ } else if ( (eei->status == EEI_NO_STATUS) && dip->di_proc_eei) { /* * Occasionally, while processing a reset condition on V4.0F, the * first mtop (rewind) is error'ed out with no EEI status. This is * probably broken in the tape driver, but like any good application * we must try our best to workaround these anomalies :-) */ return (TRUE); /* Retry please! */ } switch (eei->arch.cam.cam_status) { /* * Most of these CAM status' are mapped to EEI_DEVBIO_FAILURE, * but this grouping also contains status codes which should * NOT be retried. (IMHO) * * At this time, EEI_DEVBIO_FAILURE also includes CAM_BDR_SENT * which is used for Reset detection above :-) */ case CAM_SCSI_BUSY: /* SCSI bus busy. */ case CAM_CMD_TIMEOUT: /* Command timeout. */ case CAM_MSG_REJECT_REC: /* Message reject received. */ case CAM_UNCOR_PARITY: /* Uncorrectable parity error. */ case CAM_DATA_RUN_ERR: /* Data overrun/underrun error. */ case CAM_SEQUENCE_FAIL: /* Target bus phase sequence. */ case CAM_UNEXP_BUSFREE: /* Unexpected BUS free. */ /* * This status is NOT retried for cluster systems, since this * is the primary status code used to initiate service failover. * [ Changed my mind... we should NOT normally get this error. ] */#if 0 /* !defined(MUNSA) */ case CAM_SEL_TIMEOUT: /* Target selection timeout. */#endif /* !defined(MUNSA) */ return (TRUE); /* Retry these please! */ default: return (FALSE); /* Don't retry. */ }}/* * Check for retryable EEI status on non-open tape device. */boolcheck_eei_status(struct dinfo *dip, bool retry){ struct mtget mt; char *file = dip->di_dname; int oflags = (dip->di_oflags | O_NONBLOCK); int fd, status; int saved_errno = errno; if (debug_flag) { Printf ( "Attempting to open %s file '%s', open flags = %#o...\n", (dip->di_ftype == INPUT_FILE) ? "input" : "output", file, oflags); } if ( (fd = open (file, oflags)) == FAILURE) { report_error ("check_eei_status open", FALSE); errno = saved_errno; return (FALSE); } status = get_eei_status(fd, &mt); if (status != ESUCCESS) { (void) close (fd); errno = saved_errno; return (FALSE); } if (debug_flag) print_mtstatus(fd, &mt, FALSE); (void) close (fd); errno = saved_errno; if (!retry) return (FALSE); if ( is_ResetCondition(dip, &mt.eei) || is_StatusRetryable(dip, &mt.eei) ) { return (TRUE); } else { return (FALSE); }}/* * Clear Tape EEI Status - Necessary since EEI is persistent. */voidclear_eei_status(int fd, bool startup){ struct mtget mt; int status; if (debug_flag) Printf("Clearing EEI data...\n"); if ( get_eei_status(fd, &mt) != ESUCCESS) return; if (debug_flag) print_mtstatus(fd, &mt, FALSE); if (startup) { /* * blkno/fileno == -1 when invalid! */ if ( (mt_blkno = mt.mt_blkno) < 0L) { mt_blkno = 0L; } if ( (mt_fileno = mt.mt_fileno) < 0L) { mt_fileno = 0L; } } return;}intget_eei_status(int fd, struct mtget *mt){ int status; if ( (status = ioctl(fd, MTIOCGET, (char *)mt)) < 0) { report_error ("MTIOCGET failed", FALSE); } return (status);}/* * Print out tape status based on deviocget and mtiocget. */voidprint_mtstatus(int fd, struct mtget *mt, bool print_all){ /* * When processing EEI Reset requests, we do not display * the DEVIOCGET or DEVGETINFO, since these IOCTL's issue * SCSI commands which can interfere with our recovery. * [ Driver does Mode Sense to determine current density ] */ if ( print_all ) { print_devio(fd); } print_mtio(fd, mt);}/* * Display the contents of the mtget struct. * Args: fd a file descriptor of the already opened tape device. */voidprint_mtio(int fd, struct mtget *mt){ Fprint("\n"); Fprint("MTIOCGET ELEMENT CONTENTS\n"); Fprint("---------------- --------\n"); Fprint("mt_type "); switch(mt->mt_type) { case MT_ISTS: Fprint("MT_ISTS\n"); break; case MT_ISHT: Fprint("MT_ISHT\n"); break; case MT_ISTM: Fprint("MT_ISTM\n"); break; case MT_ISMT: Fprint("MT_ISMT\n"); break; case MT_ISUT: Fprint("MT_ISUT\n"); break; case MT_ISTMSCP: Fprint("MT_ISTMSCP\n"); break; case MT_ISST: Fprint("MT_ISST\n"); break; case MT_ISSCSI: Fprint("MT_ISSCSI\n"); break; default: Fprint("Unknown mt_type = 0x%x\n", mt->mt_type); } if ( mt->mt_type != MT_ISSCSI ) { Fprint("mt_dsreg 0x%X\n", mt->mt_dsreg); Fprint("mt_erreg 0x%X\n\n", mt->mt_erreg); Fprint("mt_resid %d\n", mt->mt_resid); return; } /* * The rest deals with functionality built into the SCSI tape * driver which does not exist in TMSCP. */ Fprint("mt_dsreg 0x%X\n", mt->mt_dsreg); if (mt->mt_dsreg) print_stat(mt->mt_dsreg); Fprint("mt_erreg 0x%X ", mt->mt_erreg); print_erreg(mt->mt_erreg); Fprint("mt_resid %d\n", mt->mt_resid); Fprint("mt_fileno %ld %s\n", mt->mt_fileno, (mt->mt_fileno < 0L) ? "(invalid)" : ""); Fprint("mt_blkno %ld %s\n", mt->mt_blkno, (mt->mt_blkno < 0L) ? "(invalid)" : ""); /* * Display the Extended Error Information (EEI) Status. */ print_eei(&mt->eei); Fprint("\n"); return;}#if defined(ZULUOS)void print_status( v1_device_info_t *p_info );/* * Display the contents of the device_info struct. * Args: fd a file descriptor of the already opened tape device. */voidprint_devio(int fd){ int status; device_info_t devinfo; v1_device_info_t *p_info; /* * Attempt to use preferred DEVGETINFO, if it fails: use DEVIOCGET */ status = ioctl( fd, DEVGETINFO, &devinfo ); if ( status || ( devinfo.version != VERSION_1 ) ) { struct devget devget; status = ioctl( fd, DEVIOCGET, (void *)&devget ); if( status ) { report_error ("DEVIOCGET failed", FALSE); return; } devio_2_devgetinfo( &devget, &devinfo ); } /* * At this point we have a valid devinfo struct */ p_info = &devinfo.v1; /* * We keep the "status" information EXACTLY the same as before * as there are most likely are user entities outthere that parse * the "status" output. We'll follow the normal output with the * additional devgetinfo information, if applicable. */ Fprint( "\n" ); Fprint( "DEVIOGET ELEMENT CONTENTS\n" ); Fprint( "---------------- --------\n" ); Fprint( "category " ); switch( p_info->category ) { case DEV_TAPE : Fprint( "DEV_TAPE\n" ); break; case DEV_DISK : Fprint( "DEV_DISK\n" ); break; case DEV_TERMINAL : Fprint( "DEV_TERMINAL\n" ); break; case DEV_PRINTER : Fprint( "DEV_PRINTER\n" ); break; case DEV_SPECIAL : Fprint( "DEV_SPECIAL\n" ); break; default : Fprint( "UNDEFINED VALUE (0x%x)\n", p_info->category ); break; } Fprint( "bus " ); switch( p_info->bus ) { case DEV_UB : Fprint( "DEV_UB\n" ); break; case DEV_QB : Fprint( "DEV_QB\n" ); break; case DEV_MB : Fprint( "DEV_MB\n" ); break; case DEV_BI : Fprint( "DEV_BI\n" ); break; case DEV_CI : Fprint( "DEV_CI\n" ); break; case DEV_NB : Fprint( "DEV_NB\n" ); break; case DEV_MSI : Fprint( "DEV_MSI\n" ); break; case DEV_SCSI : Fprint( "DEV_SCSI\n" ); break; case DEV_UNKBUS : Fprint( "DEV_UNKBUS\n" ); break; default : Fprint( "UNDEFINED VALUE (0x%x)\n", p_info->bus ); break; } Fprint( "interface %s\n", p_info->interface ); Fprint( "device %s\n", p_info->device ); Fprint( "adpt_num %d\n", p_info->businfo.adpt_num ); Fprint( "nexus_num %d\n", p_info->businfo.nexus_num ); Fprint( "bus_num %d\n", p_info->businfo.bus_num ); Fprint( "ctlr_num %d\n", p_info->businfo.ctlr_num ); Fprint( "slave_num %d\n", p_info->businfo.slave_num ); Fprint( "dev_name %s\n", p_info->dev_name ); Fprint( "unit_num %d\n", p_info->businfo.unit_num ); Fprint( "soft_count %u\n", p_info->soft_count ); Fprint( "hard_count %u\n", p_info->hard_count ); /* * New info status fields: */ print_status( p_info ); return;}/* * Dissect the status field of the device_info struct */voidprint_status( v1_device_info_t *p_info ){ v1_disk_dev_info_t *p_disk; v1_tape_dev_info_t *p_tape; switch( p_info->category ) { case DEV_DISK : p_disk = &p_info->devinfo.disk; if( !p_disk->status ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -