📄 osst.c
字号:
/* Onstream specific Routines *//* * Initialize the OnStream AUX */static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int frame_seq_number, int logical_blk_num, int blk_sz, int blk_cnt){ os_aux_t *aux = STp->buffer->aux; os_partition_t *par = &aux->partition; os_dat_t *dat = &aux->dat; if (STp->raw) return; memset(aux, 0, sizeof(*aux)); aux->format_id = htonl(0); memcpy(aux->application_sig, "LIN4", 4); aux->hdwr = htonl(0); aux->frame_type = frame_type; switch (frame_type) { case OS_FRAME_TYPE_HEADER: aux->update_frame_cntr = htonl(STp->update_frame_cntr); par->partition_num = OS_CONFIG_PARTITION; par->par_desc_ver = OS_PARTITION_VERSION; par->wrt_pass_cntr = htons(0xffff); /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */ par->first_frame_ppos = htonl(0); par->last_frame_ppos = htonl(0xbb7); aux->frame_seq_num = htonl(0); aux->logical_blk_num_high = htonl(0); aux->logical_blk_num = htonl(0); aux->next_mark_ppos = htonl(STp->first_mark_ppos); break; case OS_FRAME_TYPE_DATA: case OS_FRAME_TYPE_MARKER: dat->dat_sz = 8; dat->reserved1 = 0; dat->entry_cnt = 1; dat->reserved3 = 0; dat->dat_list[0].blk_sz = htonl(blk_sz); dat->dat_list[0].blk_cnt = htons(blk_cnt); dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER? OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA; dat->dat_list[0].reserved = 0; case OS_FRAME_TYPE_EOD: aux->update_frame_cntr = htonl(0); par->partition_num = OS_DATA_PARTITION; par->par_desc_ver = OS_PARTITION_VERSION; par->wrt_pass_cntr = htons(STp->wrt_pass_cntr); par->first_frame_ppos = htonl(STp->first_data_ppos); par->last_frame_ppos = htonl(STp->capacity); aux->frame_seq_num = htonl(frame_seq_number); aux->logical_blk_num_high = htonl(0); aux->logical_blk_num = htonl(logical_blk_num); break; default: ; /* probably FILL */ } aux->filemark_cnt = ntohl(STp->filemark_cnt); aux->phys_fm = ntohl(0xffffffff); aux->last_mark_ppos = ntohl(STp->last_mark_ppos); aux->last_mark_lbn = ntohl(STp->last_mark_lbn);}/* * Verify that we have the correct tape frame */static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet){ os_aux_t * aux = STp->buffer->aux; os_partition_t * par = &(aux->partition); ST_partstat * STps = &(STp->ps[STp->partition]); int dev = TAPE_NR(STp->devt); int blk_cnt, blk_sz, i; if (STp->raw) { if (STp->buffer->syscall_result) { for (i=0; i < STp->buffer->sg_segs; i++) memset(STp->buffer->sg[i].address, 0, STp->buffer->sg[i].length); strcpy(STp->buffer->b_data, "READ ERROR ON FRAME"); } else STp->buffer->buffer_bytes = OS_FRAME_SIZE; return 1; } if (STp->buffer->syscall_result) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Skipping frame, read error\n", dev);#endif return 0; } if (ntohl(aux->format_id) != 0) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Skipping frame, format_id %u\n", dev, ntohl(aux->format_id));#endif goto err_out; } if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 && (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Skipping frame, incorrect application signature\n", dev);#endif goto err_out; } if (par->partition_num != OS_DATA_PARTITION) { if (!STp->linux_media || STp->linux_media_version != 2) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Skipping frame, partition num %d\n", dev, par->partition_num);#endif goto err_out; } } if (par->par_desc_ver != OS_PARTITION_VERSION) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Skipping frame, partition version %d\n", dev, par->par_desc_ver);#endif goto err_out; } if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n", dev, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);#endif goto err_out; } if (aux->frame_type != OS_FRAME_TYPE_DATA && aux->frame_type != OS_FRAME_TYPE_EOD && aux->frame_type != OS_FRAME_TYPE_MARKER) { if (!quiet)#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Skipping frame, frame type %x\n", dev, aux->frame_type);#endif goto err_out; } if (aux->frame_type == OS_FRAME_TYPE_EOD && STp->first_frame_position < STp->eod_frame_ppos) { printk(KERN_INFO "osst%d:I: Skipping premature EOD frame %d\n", dev, STp->first_frame_position); goto err_out; } STp->frame_in_buffer = 1; if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) { if (!quiet)#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Skipping frame, sequence number %u (expected %d)\n", dev, ntohl(aux->frame_seq_num), frame_seq_number);#endif goto err_out; } if (aux->frame_type == OS_FRAME_TYPE_MARKER) { STps->eof = ST_FM_HIT; i = ntohl(aux->filemark_cnt); if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt || STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: %s filemark %d at frame pos %d\n", dev, STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected", i, STp->first_frame_position - 1);#endif STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1); if (i >= STp->filemark_cnt) STp->filemark_cnt = i+1; } } if (aux->frame_type == OS_FRAME_TYPE_EOD) { STps->eof = ST_EOD_1; } if (aux->frame_type == OS_FRAME_TYPE_DATA) { blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt); blk_sz = ntohl(aux->dat.dat_list[0].blk_sz); STp->buffer->buffer_bytes = blk_cnt * blk_sz; STp->buffer->read_pointer = 0; /* See what block size was used to write file */ if (STp->block_size != blk_sz && blk_sz > 0) { printk(KERN_INFO "osst%d:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n", dev, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k', STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k'); STp->block_size = blk_sz; STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz; } STps->eof = ST_NOEOF; } STp->frame_seq_number = ntohl(aux->frame_seq_num); STp->logical_blk_num = ntohl(aux->logical_blk_num); return 1;err_out: if (STp->read_error_frame == 0) STp->read_error_frame = STp->first_frame_position - 1; return 0;}/* * Wait for the unit to become Ready */static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout){ unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt; long startwait = jiffies;#if DEBUG int dbg = debugging; int dev = TAPE_NR(STp->devt); printk(OSST_DEB_MSG "osst%d:D: Reached onstream wait ready\n", dev);#endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = TEST_UNIT_READY; SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE); *aSRpnt = SRpnt; if (!SRpnt) return (-EBUSY); while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) && (( SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 && (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8) ) || ( SRpnt->sr_sense_buffer[2] == 6 && SRpnt->sr_sense_buffer[12] == 0x28 && SRpnt->sr_sense_buffer[13] == 0 ) )) {#if DEBUG if (debugging) { printk(OSST_DEB_MSG "osst%d:D: Sleeping in onstream wait ready\n", dev); printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev); debugging = 0; }#endif set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 10); 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); } *aSRpnt = SRpnt;#if DEBUG debugging = dbg;#endif if ( STp->buffer->syscall_result && osst_write_error_recovery(STp, aSRpnt, 0) ) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Abnormal exit from onstream wait ready\n", dev); printk(OSST_DEB_MSG "osst%d:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", dev, STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);#endif return (-EIO); }#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Normal exit from onstream wait ready\n", dev);#endif return 0;}/* * Wait for a tape to be inserted in the unit */static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout){ unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt; long startwait = jiffies;#if DEBUG int dbg = debugging; int dev = TAPE_NR(STp->devt); printk(OSST_DEB_MSG "osst%d:D: Reached onstream wait for medium\n", dev);#endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = TEST_UNIT_READY; SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE); *aSRpnt = SRpnt; if (!SRpnt) return (-EBUSY); while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) && SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 0x3a && SRpnt->sr_sense_buffer[13] == 0 ) {#if DEBUG if (debugging) { printk(OSST_DEB_MSG "osst%d:D: Sleeping in onstream wait medium\n", dev); printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev); debugging = 0; }#endif set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 10); 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); } *aSRpnt = SRpnt;#if DEBUG debugging = dbg;#endif if ( STp->buffer->syscall_result && SRpnt->sr_sense_buffer[2] != 2 && SRpnt->sr_sense_buffer[12] != 4 && SRpnt->sr_sense_buffer[13] == 1) {#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Abnormal exit from onstream wait medium\n", dev); printk(OSST_DEB_MSG "osst%d:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", dev, STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);#endif return 0; }#if DEBUG printk(OSST_DEB_MSG "osst%d:D: Normal exit from onstream wait medium\n", dev);#endif return 1;}static int osst_position_tape_and_confirm(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame){ int retval; osst_wait_ready(STp, aSRpnt, 15 * 60); /* TODO - can this catch a write error? */ retval = osst_set_frame_position(STp, aSRpnt, frame, 0); if (retval) return (retval); osst_wait_ready(STp, aSRpnt, 15 * 60); return (osst_get_frame_position(STp, aSRpnt));}/* * Wait for write(s) to complete */static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt){ unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt; int result = 0;#if DEBUG int dev = TAPE_NR(STp->devt); printk(OSST_DEB_MSG "osst%d:D: Reached onstream flush drive buffer (write filemark)\n", dev);#endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = WRITE_FILEMARKS; cmd[1] = 1; SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE); *aSRpnt = SRpnt; if (!SRpnt) return (-EBUSY); if ((STp->buffer)->syscall_result) result = osst_write_error_recovery(STp, aSRpnt, 0); result |= osst_wait_ready(STp, aSRpnt, 5 * 60); STp->ps[STp->partition].rw = OS_WRITING_COMPLETE; return (result);}#define OSST_POLL_PER_SEC 10static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, int minlast, int to){ long startwait = jiffies; int dev = TAPE_NR(STp->devt);#if DEBUG char notyetprinted = 1;#endif if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING) printk(KERN_ERR "osst%i:A: Waiting for frame without having initialized read!\n", dev); while (time_before (jiffies, startwait + to*HZ)) { int result; result = osst_get_frame_position (STp, aSRpnt); if (result == -EIO) if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0) return 0; /* successful recovery leaves drive ready for frame */ if (result < 0) break; if (STp->first_frame_position == curr && ((minlast < 0 && (signed)STp->last_frame_position > (signed)curr + minlast) || (minlast >= 0 && STp->cur_frames > minlast) ) && result >= 0) {#if DEBUG if (debugging || jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC) printk (OSST_DEB_MSG "osst%d:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n", dev, curr, curr+minlast, STp->first_frame_position, STp->last_frame_position, STp->cur_frames, result, (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);#endif return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -