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