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

📄 osst.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (STps->rw != ST_READING) {         /* Initialize read operation */		if (STps->rw == ST_WRITING) {			osst_flush_write_buffer(STp, aSRpnt, 1);			osst_flush_drive_buffer(STp, aSRpnt);		}		STps->rw = ST_READING;		STp->logical_blk_in_buffer = 0;		/*		 *      Issue a read 0 command to get the OnStream drive		 *      read blocks into its buffer.		 */		memset(cmd, 0, MAX_COMMAND_SIZE);		cmd[0] = READ_6;		cmd[1] = 1;#if DEBUG		printk(OSST_DEB_MSG "osst%i: Start Read Ahead on OnStream tape\n", dev);#endif		SRpnt   = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);		*aSRpnt = SRpnt;		retval  = STp->buffer->syscall_result;	}	return retval;}static int osst_get_logical_blk(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int logical_blk_num, int quiet){	ST_partstat * STps  = &(STp->ps[STp->partition]);	int           dev   = TAPE_NR(STp->devt);	int           cnt   = 0,		      bad   = 0,		      past  = 0,		      x,		      position;	/*	 * Search and wait for the next logical tape block	 */	while (1) {		if (cnt++ > 400) {			printk(KERN_WARNING "osst%d: Couldn't find logical block %d, aborting\n",					    dev, logical_blk_num);			if (STp->read_error_frame) {				osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);#if 1 //DEBUG                        	printk(OSST_DEB_MSG "osst%d: Repositioning tape to bad block %d\n",						    dev, STp->read_error_frame);#endif				STp->read_error_frame = 0;			}			return (-EIO);		}#if DEBUG		if (debugging)			printk(OSST_DEB_MSG "osst%d: Looking for block %d, attempt %d\n",					  dev, logical_blk_num, cnt);#endif		if ( osst_initiate_read(STp, aSRpnt)		|| ( (!STp->logical_blk_in_buffer) && osst_read_block(STp, aSRpnt, 30) ) ) {			position = osst_get_frame_position(STp, aSRpnt);			if (position >= 0xbae && position < 0xbb8)				position = 0xbb8;			else if (position > STp->eod_frame_ppos || ++bad == 10) {printk(OSST_DEB_MSG "osst%d: start again from pos %d, eod %d, bad %d\n", dev, position, STp->eod_frame_ppos, bad); /*FIXME*/				position = STp->read_error_frame - 1;			}			else {				position += 39;				cnt += 20;			}#if DEBUG			printk(OSST_DEB_MSG "osst%d: Bad block detected, positioning tape to block %d\n",					 dev, position);#endif			osst_set_frame_position(STp, aSRpnt, position, 0);			continue;		}		if (osst_verify_frame(STp, logical_blk_num, quiet))			break;		if (osst_verify_frame(STp, -1, quiet)) {			x = ntohl(STp->buffer->aux->logical_blk_num);			if (STp->fast_open) {#if 1 //DEBUG				printk(OSST_DEB_MSG				       "osst%d: Found logical block %d instead of %d after fast open\n",				       dev, x, logical_blk_num);#endif				STp->header_ok = 0;				STp->read_error_frame = 0;				return (-EIO);			}			if (x > logical_blk_num) {				if (++past > 3) {					/* positioning backwards did not bring us to the desired block */					position = STp->read_error_frame - 1;				}				else			        	position = osst_get_frame_position(STp, aSRpnt)					         + logical_blk_num - x - 1;#if 1 //DEBUG                                printk(OSST_DEB_MSG				       "osst%d: Found logical block %d while looking for %d: back up %d\n",						dev, x, logical_blk_num,					       	STp->first_frame_position - position);#endif                        	osst_set_frame_position(STp, aSRpnt, position, 0);				cnt += 10;			}			else				past = 0;		}		if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {#if DEBUG			printk(OSST_DEB_MSG "osst%d: Skipping config partition\n", dev);#endif			osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);			cnt--;		}		STp->logical_blk_in_buffer = 0;	}	if (cnt > 1) {		STp->recover_count++;		STp->recover_erreg++; 	}	STp->logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num);#if DEBUG	if (debugging || STps->eof)		printk(OSST_DEB_MSG "osst%i: Exit get logical block (%d=>%d) from OnStream tape with code %d\n",							 dev, logical_blk_num, STp->logical_blk_num, STps->eof);#endif	STp->fast_open = FALSE;	STp->read_error_frame = 0;	return (STps->eof);}static int osst_seek_logical_blk(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int logical_blk_num){	int  estimate;	int  retries = 0;	int  dev     = TAPE_NR(STp->devt);	if (logical_blk_num < 0) logical_blk_num = 0;	/* FIXME -- this may not be valid for foreign formats */	if (logical_blk_num < 2980) estimate  = logical_blk_num + 10;	else			    estimate  = logical_blk_num + 20;#if DEBUG	printk(OSST_DEB_MSG "osst%d: Seeking logical block %d (now at %d)\n",			  dev, logical_blk_num, STp->logical_blk_num);#endif	while (++retries < 10) {	   osst_set_frame_position(STp, aSRpnt, estimate, 0);	   if (osst_get_logical_blk(STp, aSRpnt, logical_blk_num, 1) >= 0)	      return 0;	   if (osst_get_logical_blk(STp, aSRpnt, -1, 1) < 0)	      goto error;	   if (STp->logical_blk_num != logical_blk_num)	      estimate += logical_blk_num - STp->logical_blk_num;	   else	      break;	}error:	printk(KERN_WARNING "osst%d: Couldn't seek to logical block %d (at %d), %d retries\n", 			    dev, logical_blk_num, STp->logical_blk_num, retries);	return (-EIO);}static int osst_seek_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame){	ST_partstat   * STps = &(STp->ps[STp->partition]);	int		r;	if (frame < 0 || frame >= STp->capacity) return (-ENXIO);	if (frame <= STp->first_data_ppos) {		STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;		return (osst_set_frame_position(STp, aSRpnt, frame, 0));	}	r = osst_set_frame_position(STp, aSRpnt, frame-1, 0);	if (r < 0) return r;	r = osst_get_logical_blk(STp, aSRpnt, -1, 1);	if (r < 0) return r;	if (osst_get_frame_position(STp, aSRpnt) != frame) return (-EIO);	STp->logical_blk_num++;	STp->logical_blk_in_buffer = 0;	STps->drv_file  = htonl(STp->buffer->aux->filemark_cnt);	STps->drv_block = -1;	STps->eof       = ST_NOEOF;	return 0;}/* * Read back the drive's internal buffer contents, as a part * of the write error recovery mechanism for old OnStream * firmware revisions. */static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,					unsigned int block, unsigned int skip, int pending){	Scsi_Request  * SRpnt = * aSRpnt;	unsigned char * buffer, * p;	unsigned char	cmd[MAX_COMMAND_SIZE];	int             frames, flag, new_block, i, logical_blk_num;	int		dev  = TAPE_NR(STp->devt);	long		startwait = jiffies;#if DEBUG	int		dbg = debugging;#endif	frames = STp->cur_frames;	if ((buffer = (unsigned char *)vmalloc((frames + pending) * OS_DATA_SIZE)) == NULL)		return (-EIO);	logical_blk_num = STp->logical_blk_num - frames - pending;	printk(KERN_INFO "osst%d: Reading back %d frames from drive buffer%s\n",			 dev, frames, pending?" and one that was pending":"");	if (pending) {		osst_copy_from_buffer(STp->buffer, (p = &buffer[frames * OS_DATA_SIZE]));//		memcpy((p = &buffer[frames * OS_DATA_SIZE]), STp->buffer->b_data, OS_DATA_SIZE);#if DEBUG		if (debugging)			printk(OSST_DEB_MSG "osst%d: Pending logical block %d, data %x %x %x %x\n",					  dev, logical_blk_num + frames, p[0], p[1], p[2], p[3]);#endif	}	for (i = 0, p = buffer; i < frames; i++, p += OS_DATA_SIZE) {		memset(cmd, 0, MAX_COMMAND_SIZE);		cmd[0] = 0x3C;		/* Buffer Read           */		cmd[1] = 6;		/* Retrieve Faulty Block */		cmd[7] = 32768 >> 8;		cmd[8] = 32768 & 0xff;		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,					    STp->timeout, MAX_RETRIES, TRUE);			if ((STp->buffer)->syscall_result) {			printk(KERN_ERR "osst%d: Failed to read block back from OnStream buffer\n", dev);			vfree((void *)buffer);			*aSRpnt = SRpnt;			return (-EIO);		}		osst_copy_from_buffer(STp->buffer, p);//		memcpy(p, STp->buffer->b_data, OS_DATA_SIZE);#if DEBUG		if (debugging)			printk(OSST_DEB_MSG "osst%d: Read back logical block %d, data %x %x %x %x\n",					  dev, logical_blk_num + i, p[0], p[1], p[2], p[3]);#endif	}	*aSRpnt = SRpnt;	osst_get_frame_position(STp, aSRpnt);#if DEBUG	printk(OSST_DEB_MSG "osst%d: Frames left in buffer: %d\n", dev, STp->cur_frames);#endif	/* Write synchronously so we can be sure we're OK again and don't have to recover recursively */	/* In the header we don't actually re-write the blocks that fail, just the ones after them */	for (flag=1, new_block=block, p=buffer, i=0; i < frames + pending; ) {		if (flag) {			if (STp->write_type == OS_WRITE_HEADER) {				i += skip;				p += skip * OS_DATA_SIZE;			}			else if (new_block < 2990 && new_block+skip+frames+pending >= 2990)				new_block = 3000-i;			else				new_block += skip;#if DEBUG			printk(OSST_DEB_MSG "osst%d: Position to frame %d, write lblk %d\n",						dev, new_block+i, logical_blk_num+i); /* FIXME var blk sz */#endif			osst_set_frame_position(STp, aSRpnt, new_block + i, 0);			osst_wait_ready(STp, aSRpnt, 60);			osst_get_frame_position(STp, aSRpnt);			SRpnt = * aSRpnt;			if (new_block > block + 1000) {				printk(KERN_ERR "osst%d: Failed to find valid tape media\n", dev);				vfree((void *)buffer);				return (-EIO);			}			flag = 0;			if ( i >= frames + pending ) break;		}		osst_copy_to_buffer(STp->buffer, p);//		memcpy(STp->buffer->b_data, p, OS_DATA_SIZE);		/*		 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!		 */		osst_init_aux(STp, STp->buffer->aux->frame_type, logical_blk_num+i );		memset(cmd, 0, MAX_COMMAND_SIZE);		cmd[0] = WRITE_6;		cmd[1] = 1;		cmd[4] = 1;#if DEBUG		if (debugging)			printk(OSST_DEB_MSG "osst%d: About to attempt to write to frame %d\n", dev, new_block+i);#endif		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,					    STp->timeout, MAX_WRITE_RETRIES, TRUE);		if (STp->buffer->syscall_result)			flag = 1;		else {			p += OS_DATA_SIZE; i++;			/* if we just sent the last frame, wait till all successfully written */			if ( i == frames + pending ) {#if DEBUG				printk(OSST_DEB_MSG "osst%d: Check re-write successful\n", dev);#endif				memset(cmd, 0, MAX_COMMAND_SIZE);				cmd[0] = WRITE_FILEMARKS;				cmd[1] = 1;				SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,							    STp->timeout, MAX_WRITE_RETRIES, TRUE);#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				flag = STp->buffer->syscall_result;				while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {					memset(cmd, 0, MAX_COMMAND_SIZE);					cmd[0] = TEST_UNIT_READY;					SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout,									 MAX_READY_RETRIES, TRUE);					if (SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&					    (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8)) {						/* in the process of becoming ready */						schedule_timeout(HZ / 10);						continue;					}					if (STp->buffer->syscall_result)						flag = 1;					break;				}#if DEBUG				debugging = dbg;				printk(OSST_DEB_MSG "osst%d: Wait re-write finished\n", dev);#endif			}		}		if (flag) {			if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 &&			     SRpnt->sr_sense_buffer[12]         ==  0 &&			     SRpnt->sr_sense_buffer[13]         ==  2) {				printk(KERN_ERR "osst%d: Volume overflow in write error recovery\n", dev);				vfree((void *)buffer);				return (-EIO);			/* hit end of tape = fail */			}			i = ((SRpnt->sr_sense_buffer[3] << 24) |			     (SRpnt->sr_sense_buffer[4] << 16) |			     (SRpnt->sr_sense_buffer[5] <<  8) |			      SRpnt->sr_sense_buffer[6]        ) - new_block;			p = &buffer[i * OS_DATA_SIZE];#if DEBUG			printk(OSST_DEB_MSG "osst%d: Additional write error at %d\n", dev, new_block+i);#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		}		*aSRpnt = SRpnt;	}    	vfree((void *)buffer);	return 0;}static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,					unsigned int block, unsigned int skip, int pending){	unsigned char	cmd[MAX_COMMAND_SIZE];	Scsi_Request  * SRpnt     = * aSRpnt;	int		dev       = TAPE_NR(STp->devt);	int		attempts  = 1000 / skip;	int		flag      = 1;	long		startwait = jiffies;#if DEBUG	int		dbg       = debugging;#endif

⌨️ 快捷键说明

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