📄 osst.c
字号:
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 + -