📄 osst.c
字号:
osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0); retval = -EIO; break; case OS_WRITE_HEADER: printk(KERN_WARNING "osst%d:I: Bad frame in header partition, skipped\n", dev); retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending); break; default: printk(KERN_INFO "osst%d:I: Bad frame in filler, ignored\n", dev); osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0); } osst_get_frame_position(STp, aSRpnt);#if DEBUG printk(OSST_DEB_MSG "osst%d: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:D: next logical frame 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:D: Reached space_over_filemarks_backwards %d %d\n", dev, mt_op, mt_count);#endif if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_bwd\n", dev);#endif 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 DEBUG if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX) printk(OSST_DEB_MSG "osst%d:D: 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%d:D: 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_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos); if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);#endif return (-EIO); } if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) { printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n", dev, last_mark_ppos); return (-EIO); } if (mt_op == MTBSFM) { STp->frame_seq_number++; STp->frame_in_buffer = 0; STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); } return 0; }#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Reverting to scan filemark backwards\n", dev);#endif } 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%d:D: Positioning to last mark at %d\n", dev, last_mark_ppos);#endif osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos); cnt++; if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);#endif return (-EIO); } if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) { printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n", dev, last_mark_ppos); return (-EIO); } } if (mt_op == MTBSFM) { STp->frame_seq_number++; STp->frame_in_buffer = 0; STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); } 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 cnt = 0;#if DEBUG int dev = TAPE_NR(STp->devt); printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_forward_slow %d %d\n", dev, mt_op, mt_count);#endif if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd\n", dev);#endif return (-EIO); } while (1) { if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);#endif 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%d:D: space_fwd: EOD reached\n", dev);#endif if (STp->first_frame_position > STp->eod_frame_ppos+1) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: 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->frame_in_buffer = 0; } if (mt_op == MTFSF) { STp->frame_seq_number++; STp->frame_in_buffer = 0; STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); } 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:D: Reached space_over_filemarks_forward_fast %d %d\n", dev, mt_op, mt_count);#endif if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd\n", dev);#endif 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 DEBUG if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX) printk(OSST_DEB_MSG "osst%d:D: 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%d:D: 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) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev);#endif return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count); } else { osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos); if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);#endif return (-EIO); } if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) { printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n", dev, next_mark_ppos); return (-EIO); } if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) { printk(KERN_WARNING "osst%d:W: Expected to find marker %d at ppos %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%d:D: space_fwd: EOD reached\n", dev);#endif return (-EIO); } if (ntohl(STp->buffer->aux->filemark_cnt) == 0) { if (STp->first_mark_ppos == -1) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev);#endif return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count); } osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos); if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n", dev);#endif return (-EIO); } if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) { printk(KERN_WARNING "osst%d:W: 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) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev);#endif return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt); }#if DEBUG else printk(OSST_DEB_MSG "osst%d:D: Positioning to next mark at %d\n", dev, next_mark_ppos);#endif osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos); cnt++; if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);#endif return (-EIO); } if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) { printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n", dev, next_mark_ppos); return (-EIO); } } } if (mt_op == MTFSF) { STp->frame_seq_number++; STp->frame_in_buffer = 0; STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); } return 0;}/* * In debug mode, we want to see as many errors as possible * to test the error recovery mechanism. */#if DEBUGstatic void osst_set_retries(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int retries){ unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt = * aSRpnt; int dev = TAPE_NR(STp->devt); memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = MODE_SELECT; cmd[1] = 0x10; cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH; (STp->buffer)->b_data[0] = cmd[4] - 1; (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */ (STp->buffer)->b_data[2] = 0; /* Reserved */ (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */ (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7); (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2; (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4; (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries; if (debugging) printk(OSST_DEB_MSG "osst%d:D: Setting number of retries on OnStream tape to %d\n", dev, retries); SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE); *aSRpnt = SRpnt; if ((STp->buffer)->syscall_result) printk (KERN_ERR "osst%d:D: Couldn't set retries to %d\n", dev, retries);}#endifstatic int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt){ int result; int this_mark_ppos = STp->first_frame_position; int this_mark_lbn = STp->logical_blk_num;#if DEBUG int dev = TAPE_NR(STp->devt);#endif if (STp->raw) return 0; STp->write_type = OS_WRITE_NEW_MARK;#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n", dev, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);#endif STp->dirty = 1; result = osst_flush_write_buffer(STp, aSRpnt); result |= osst_flush_drive_buffer(STp, aSRpnt); STp->last_mark_ppos = this_mark_ppos; STp->last_mark_lbn = this_mark_lbn; if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX) STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos); if (STp->filemark_cnt++ == 0) STp->first_mark_ppos = this_mark_ppos; return result;}static int osst_write_eod(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt){ int result;#if DEBUG int dev = TAPE_NR(STp->devt);#endif if (STp->raw
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -