⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 osst.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	while (attempts && time_before(jiffies, startwait + 60*HZ)) {		if (flag) {#if DEBUG			debugging = dbg;#endif			if (block < 2990 && block+skip+STp->cur_frames+pending >= 2990)				block = 3000-skip;#if DEBUG			printk(OSST_DEB_MSG "osst%d: Position to frame %d, re-write from lblk %d\n",					  dev, block+skip, STp->logical_blk_num-STp->cur_frames-pending);#endif			osst_set_frame_position(STp, aSRpnt, block + skip, 1);			flag = 0;			attempts--;		}		if (osst_get_frame_position(STp, aSRpnt) < 0) {		/* additional write error */#if DEBUG			printk(OSST_DEB_MSG "osst%d: Addl error, host %d, tape %d, buffer %d\n",					  dev, STp->first_frame_position,					  STp->last_frame_position, STp->cur_frames);#endif			block = STp->last_frame_position;			flag = 1;			continue;		}		if (pending && STp->cur_frames < 50) {			memset(cmd, 0, MAX_COMMAND_SIZE);			cmd[0] = WRITE_6;			cmd[1] = 1;			cmd[4] = 1;#if DEBUG			printk(OSST_DEB_MSG "osst%d: About to write pending lblk %d at frame %d\n",					  dev, STp->logical_blk_num-1, STp->first_frame_position);#endif			SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,						    STp->timeout, MAX_WRITE_RETRIES, TRUE);			*aSRpnt = SRpnt;			if (STp->buffer->syscall_result) {		/* additional write error */				if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 &&				     SRpnt->sr_sense_buffer[12]         ==  0 &&				     SRpnt->sr_sense_buffer[13]         ==  2) {					printk(OSST_DEB_MSG					       "osst%d: Volume overflow in write error recovery\n",					       dev);					break;				/* hit end of tape = fail */				}				flag = 1;			}			else				pending = 0;			continue;		}		if (STp->cur_frames == 0) {#if DEBUG			debugging = dbg;			printk(OSST_DEB_MSG "osst%d: Wait re-write finished\n", dev);#endif			return 0;		}#if DEBUG		if (debugging) {			printk(OSST_DEB_MSG "osst%d: Sleeping in re-write wait ready\n", dev);			printk(OSST_DEB_MSG "osst%d: Turning off debugging for a while\n", dev);			debugging = 0;		}#endif		schedule_timeout(HZ / 10);	}	printk(KERN_ERR "osst%d: Failed to find valid tape media\n", dev);#if DEBUG	debugging = dbg;#endif	return (-EIO);}/* * Error recovery algorithm for the OnStream tape. */static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending){	Scsi_Request * SRpnt  = * aSRpnt;	ST_partstat  * STps   = & STp->ps[STp->partition];	int            dev    = TAPE_NR(STp->devt);	int            retval = 0;	int            rw_state;	unsigned int   block, skip;	rw_state = STps->rw;	if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) != 3	  || SRpnt->sr_sense_buffer[12]         != 12	  || SRpnt->sr_sense_buffer[13]         != 0) {#if DEBUG		printk(OSST_DEB_MSG "osst%d: Write error recovery cannot handle %02x:%02x:%02x\n",			dev, SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);#endif		return (-EIO);	}	block =	(SRpnt->sr_sense_buffer[3] << 24) |		(SRpnt->sr_sense_buffer[4] << 16) |		(SRpnt->sr_sense_buffer[5] <<  8) |		 SRpnt->sr_sense_buffer[6];	skip  =  SRpnt->sr_sense_buffer[9]; #if DEBUG	printk(OSST_DEB_MSG "osst%d: Detected physical bad block at %u, advised to skip %d\n", dev, block, skip);#endif	osst_get_frame_position(STp, aSRpnt);#if DEBUG	printk(OSST_DEB_MSG "osst%d: reported frame positions: host = %d, tape = %d\n",			dev, STp->first_frame_position, STp->last_frame_position);#endif	switch (STp->write_type) {	   case OS_WRITE_DATA:	   case OS_WRITE_EOD:	   case OS_WRITE_NEW_MARK:		printk(KERN_WARNING "osst%d: Relocating %d buffered logical blocks to physical block %u\n",			dev, STp->cur_frames, block + skip);		if (STp->os_fw_rev >= 10600)			retval = osst_reposition_and_retry(STp, aSRpnt, block, skip, pending);		else			retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, block, skip, pending);		break;	   case OS_WRITE_LAST_MARK:		printk(KERN_ERR "osst%d: Bad block in update last marker, fatal\n", dev);		osst_set_frame_position(STp, aSRpnt, block + STp->cur_frames + pending, 0);		retval = -EIO;		break;	   case OS_WRITE_HEADER:		printk(KERN_WARNING "osst%d: Bad block in header partition, skipped\n", dev);		retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, block, 1, pending);		break;	   default:		printk(KERN_WARNING "osst%d: Bad block in filler, ignored\n", dev);		osst_set_frame_position(STp, aSRpnt, block + STp->cur_frames + pending, 0);	}	osst_get_frame_position(STp, aSRpnt);#if DEBUG	printk(KERN_ERR "osst%d: Positioning complete, cur_frames %d, pos %d, tape pos %d\n", 			dev, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);	printk(OSST_DEB_MSG "osst%d: next logical block to write: %d\n", dev, STp->logical_blk_num);#endif	if (retval == 0) {		STp->recover_count++;		STp->recover_erreg++;	}	STps->rw = rw_state;	return retval;}static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,								 int mt_op, int mt_count){	int     dev = TAPE_NR(STp->devt);	int     cnt;	int     last_mark_ppos = -1;#if DEBUG	printk(OSST_DEB_MSG "osst%d: Reached space_over_filemarks_backwards %d %d\n", dev, mt_op, mt_count);#endif	if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) {		printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks_bwd\n", dev);		return -EIO;	}	if (STp->linux_media_version >= 4) {		/*		 * direct lookup in header filemark list		 */		cnt = ntohl(STp->buffer->aux->filemark_cnt);		if (STp->header_ok                         && 		    STp->header_cache != NULL              &&		    (cnt - mt_count)  >= 0                 &&		    (cnt - mt_count)   < OS_FM_TAB_MAX     &&		    (cnt - mt_count)   < STp->filemark_cnt &&		    STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)			last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);#if 1 //DEBUG		if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)			printk(OSST_DEB_MSG "osst%i: Filemark lookup fail due to %s\n", dev,			       STp->header_cache == NULL?"lack of header cache":"count out of range");		else			printk(OSST_DEB_MSG "osst%i: Filemark lookup: prev mark %d (%s), skip %d to %d\n",				dev, cnt,				((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||				 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==					 STp->buffer->aux->last_mark_ppos))?"match":"error",			       mt_count, last_mark_ppos);#endif		if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {			osst_set_frame_position(STp, aSRpnt, last_mark_ppos, 0);			if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) {				printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev);				return (-EIO);			}			if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {				printk(KERN_INFO "osst%i: Expected to find marker at block %d, not found\n",						 dev, last_mark_ppos);				return (-EIO);			}			if (mt_op == MTBSFM) {				STp->logical_blk_num++;				STp->logical_blk_in_buffer = 0;			}			return 0;		}		printk(KERN_INFO "osst%i: Reverting to scan filemark backwards\n", dev);	}	cnt = 0;	while (cnt != mt_count) {		last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);		if (last_mark_ppos == -1)			return (-EIO);#if DEBUG		printk(OSST_DEB_MSG "osst%i: Positioning to last mark at %d\n", dev, last_mark_ppos);#endif		osst_set_frame_position(STp, aSRpnt, last_mark_ppos, 0);		cnt++;		if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) {			printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev);			return (-EIO);		}		if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {			printk(KERN_INFO "osst%i: Expected to find marker at block %d, not found\n", dev, last_mark_ppos);			return (-EIO);		}	}	if (mt_op == MTBSFM) {		STp->logical_blk_num++;		STp->logical_blk_in_buffer = 0;	}	return 0;}/* * ADRL 1.1 compatible "slow" space filemarks fwd version * * Just scans for the filemark sequentially. */static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,								     int mt_op, int mt_count){	int	dev = TAPE_NR(STp->devt);	int	cnt = 0;#if DEBUG	printk(OSST_DEB_MSG "osst%d: Reached space_over_filemarks_forward_slow %d %d\n", dev, mt_op, mt_count);#endif	if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) {		printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks_fwd\n", dev);		return (-EIO);	}	while (1) {		if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) {			printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev);			return (-EIO);		}		if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)			cnt++;		if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {#if DEBUG			printk(OSST_DEB_MSG "osst%i: space_fwd: EOD reached\n", dev);#endif			if (STp->first_frame_position > STp->eod_frame_ppos+1) {#if DEBUG				printk(OSST_DEB_MSG "osst%i: EOD position corrected (%d=>%d)\n",					       	dev, STp->eod_frame_ppos, STp->first_frame_position-1);#endif				STp->eod_frame_ppos = STp->first_frame_position-1;			}			return (-EIO);		}		if (cnt == mt_count)			break;		STp->logical_blk_in_buffer = 0;	}	if (mt_op == MTFSF) {		STp->logical_blk_num++;		STp->logical_blk_in_buffer = 0;	}	return 0;}/* * Fast linux specific version of OnStream FSF */static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,								     int mt_op, int mt_count){	int	dev = TAPE_NR(STp->devt);	int	cnt = 0,		next_mark_ppos = -1;#if DEBUG	printk(OSST_DEB_MSG "osst%d: Reached space_over_filemarks_forward_fast %d %d\n", dev, mt_op, mt_count);#endif	if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) {		printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks_fwd\n", dev);		return (-EIO);	}	if (STp->linux_media_version >= 4) {		/*		 * direct lookup in header filemark list		 */		cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;		if (STp->header_ok                         && 		    STp->header_cache != NULL              &&		    (cnt + mt_count)   < OS_FM_TAB_MAX     &&		    (cnt + mt_count)   < STp->filemark_cnt &&		    ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||		     (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))			next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);#if 1 //DEBUG		if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)			printk(OSST_DEB_MSG "osst%i: Filemark lookup fail due to %s\n", dev,			       STp->header_cache == NULL?"lack of header cache":"count out of range");		else			printk(OSST_DEB_MSG "osst%i: Filemark lookup: prev mark %d (%s), skip %d to %d\n", dev, cnt,			       ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||				(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==					 STp->buffer->aux->last_mark_ppos))?"match":"error",			       mt_count, next_mark_ppos);#endif		if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {			printk(KERN_INFO "osst%i: Reverting to slow filemark space\n", dev);			return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);		} else {			osst_set_frame_position(STp, aSRpnt, next_mark_ppos, 0);			if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) {				printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev);				return (-EIO);			}			if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {				printk(KERN_INFO "osst%i: Expected to find marker at block %d, not found\n",						 dev, next_mark_ppos);				return (-EIO);			}			if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {				printk(KERN_INFO "osst%i: Expected to find marker %d at block %d, not %d\n",						 dev, cnt+mt_count, next_mark_ppos,						 ntohl(STp->buffer->aux->filemark_cnt));       				return (-EIO);			}		}	} else {		/*		 * Find nearest (usually previous) marker, then jump from marker to marker		 */		while (1) {			if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)				break;			if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {#if DEBUG				printk(OSST_DEB_MSG "osst%i: space_fwd: EOD reached\n", dev);#endif				return (-EIO);			}			if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {				if (STp->first_mark_ppos == -1) {					printk(KERN_INFO "osst%i: Reverting to slow filemark space\n", dev);					return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);				}				osst_set_frame_position(STp, aSRpnt, STp->first_mark_ppos, 0);				if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) {					printk(KERN_INFO					       "osst%i: Couldn't get logical blk num in space_filemarks_fwd_fast\n",					       dev);					return (-EIO);				}				if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {					printk(KERN_INFO "osst%i: Expected to find filemark at %d\n",							 dev, STp->first_mark_ppos);					return (-EIO);				}			} else {				if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)					return (-EIO);				mt_count++;			}		}		cnt++;		while (cnt != mt_count) {			next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);			if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {				printk(KERN_INFO "osst%i: Reverting to slow filemark space\n", dev);				return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);			}#if DEBUG			else printk(OSST_DEB_MSG "osst%i: Positioning to next mark at %d\n", dev, next_mark_ppos);#endif			osst_set_frame_position(STp, aSRpnt, next_mark_ppos, 0);			cnt++;			if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) {				printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -