📄 zftape-vtbl.c
字号:
} #endif /* the end of the vtbl is indicated by an invalid signature */ while (vtbl_signature_valid(&entry[VTBL_SIG]) && (entry - buffer) < FT_SEGMENT_SIZE) { zft_new_vtbl_entry(); if (ft_format_code == fmt_big) { /* SCSI like vtbl, stores only the number of * segments used */ unsigned int num_segments= GET4(entry, VTBL_SCSI_SEGS); zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg; zft_last_vtbl->end_seg = zft_last_vtbl->start_seg + num_segments - 1; } else { /* `normal', QIC-80 like vtbl */ zft_last_vtbl->start_seg = GET2(entry, VTBL_START); zft_last_vtbl->end_seg = GET2(entry, VTBL_END); } zft_eom_vtbl->start_seg = zft_last_vtbl->end_seg + 1; /* check if we created this volume and get the * blk_sz */ zft_last_vtbl->zft_volume = check_volume(entry, zft_last_vtbl); if (zft_last_vtbl->zft_volume == 0) { extract_alien_volume(entry, zft_last_vtbl); } else { extract_zft_volume(entry, zft_last_vtbl); } DUMP_VOLINFO(ft_t_noise, &entry[VTBL_DESC], zft_last_vtbl); entry +=VTBL_SIZE; }#if 0/* * undefine to test end of tape handling */ zft_new_vtbl_entry(); zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg; zft_last_vtbl->end_seg = ft_last_data_segment - 10; zft_last_vtbl->blk_sz = zft_blk_sz; zft_last_vtbl->zft_volume = 1; zft_last_vtbl->qic113 = zft_qic113; zft_last_vtbl->size = (zft_calc_tape_pos(zft_last_vtbl->end_seg+1) - zft_calc_tape_pos(zft_last_vtbl->start_seg));#endif TRACE_EXIT 0;}/* this functions translates the failed_sector_log, misused as * EOF-marker list, into a virtual volume table. The table mustn't be * written to tape, because this would occupy the first data segment, * which should be the volume table, but is actually the first segment * that is filled with data (when using standard ftape). We assume, * that we get a non-empty failed_sector_log. */int zft_fake_volume_headers (eof_mark_union *eof_map, int num_failed_sectors){ unsigned int segment, sector; int have_eom = 0; int vol_no; TRACE_FUN(ft_t_flow); if ((num_failed_sectors >= 2) && (GET2(&eof_map[num_failed_sectors - 1].mark.segment, 0) == GET2(&eof_map[num_failed_sectors - 2].mark.segment, 0) + 1) && (GET2(&eof_map[num_failed_sectors - 1].mark.date, 0) == 1)) { /* this should be eom. We keep the remainder of the * tape as another volume. */ have_eom = 1; } zft_init_vtbl(); zft_eom_vtbl->start_seg = ft_first_data_segment; for(vol_no = 0; vol_no < num_failed_sectors - have_eom; vol_no ++) { zft_new_vtbl_entry(); segment = GET2(&eof_map[vol_no].mark.segment, 0); sector = GET2(&eof_map[vol_no].mark.date, 0); zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg; zft_last_vtbl->end_seg = segment; zft_eom_vtbl->start_seg = segment + 1; zft_last_vtbl->blk_sz = 1; zft_last_vtbl->size = (zft_calc_tape_pos(zft_last_vtbl->end_seg) - zft_calc_tape_pos(zft_last_vtbl->start_seg) + (sector-1) * FT_SECTOR_SIZE); TRACE(ft_t_noise, "failed sector log: segment: %d, sector: %d", segment, sector); DUMP_VOLINFO(ft_t_noise, "Faked volume", zft_last_vtbl); } if (!have_eom) { zft_new_vtbl_entry(); zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg; zft_last_vtbl->end_seg = ft_last_data_segment; zft_eom_vtbl->start_seg = ft_last_data_segment + 1; zft_last_vtbl->size = zft_capacity; zft_last_vtbl->size -= zft_calc_tape_pos(zft_last_vtbl->start_seg); zft_last_vtbl->blk_sz = 1; DUMP_VOLINFO(ft_t_noise, "Faked volume",zft_last_vtbl); } TRACE_EXIT 0;}/* update the internal volume table * * if before start of last volume: erase all following volumes if * inside a volume: set end of volume to infinity * * this function is intended to be called every time _ftape_write() is * called * * return: 0 if no new volume was created, 1 if a new volume was * created * * NOTE: we don't need to check for zft_mode as ftape_write() does * that already. This function gets never called without accessing * zftape via the *qft* devices */int zft_open_volume(zft_position *pos, int blk_sz, int use_compression){ TRACE_FUN(ft_t_flow); if (!zft_qic_mode) { TRACE_EXIT 0; } if (zft_tape_at_lbot(pos)) { zft_init_vtbl(); if(zft_old_ftape) { /* clear old ftape's eof marks */ zft_clear_ftape_file_marks(); zft_old_ftape = 0; /* no longer old ftape */ } zft_reset_position(pos); } if (pos->seg_pos != zft_last_vtbl->end_seg + 1) { TRACE_ABORT(-EIO, ft_t_bug, "BUG: seg_pos: %d, zft_last_vtbl->end_seg: %d", pos->seg_pos, zft_last_vtbl->end_seg); } TRACE(ft_t_noise, "create new volume"); if (zft_eom_vtbl->count >= ZFT_MAX_VOLUMES) { TRACE_ABORT(-ENOSPC, ft_t_err, "Error: maxmimal number of volumes exhausted " "(maxmimum is %d)", ZFT_MAX_VOLUMES); } zft_new_vtbl_entry(); pos->volume_pos = pos->seg_byte_pos = 0; zft_last_vtbl->start_seg = pos->seg_pos; zft_last_vtbl->end_seg = ft_last_data_segment; /* infinity */ zft_last_vtbl->blk_sz = blk_sz; zft_last_vtbl->size = zft_capacity; zft_last_vtbl->zft_volume = 1; zft_last_vtbl->use_compression = use_compression; zft_last_vtbl->qic113 = zft_qic113; zft_last_vtbl->new_volume = 1; zft_last_vtbl->open = 1; zft_volume_table_changed = 1; zft_eom_vtbl->start_seg = ft_last_data_segment + 1; TRACE_EXIT 0;}/* perform mtfsf, mtbsf, not allowed without zft_qic_mode */int zft_skip_volumes(int count, zft_position *pos){ const zft_volinfo *vtbl; TRACE_FUN(ft_t_flow); TRACE(ft_t_noise, "count: %d", count); vtbl= zft_find_volume(pos->seg_pos); while (count > 0 && vtbl != zft_eom_vtbl) { vtbl = list_entry(vtbl->node.next, zft_volinfo, node); count --; } while (count < 0 && vtbl != zft_first_vtbl) { vtbl = list_entry(vtbl->node.prev, zft_volinfo, node); count ++; } pos->seg_pos = vtbl->start_seg; pos->seg_byte_pos = 0; pos->volume_pos = 0; pos->tape_pos = zft_calc_tape_pos(pos->seg_pos); zft_just_before_eof = vtbl->size == 0; if (zft_cmpr_ops) { (*zft_cmpr_ops->reset)(); } zft_deblock_segment = -1; /* no need to keep cache */ TRACE(ft_t_noise, "repositioning to:\n" KERN_INFO "zft_seg_pos : %d\n" KERN_INFO "zft_seg_byte_pos : %d\n" KERN_INFO "zft_tape_pos : " LL_X "\n" KERN_INFO "zft_volume_pos : " LL_X "\n" KERN_INFO "file number : %d", pos->seg_pos, pos->seg_byte_pos, LL(pos->tape_pos), LL(pos->volume_pos), vtbl->count); zft_resid = count < 0 ? -count : count; TRACE_EXIT zft_resid ? -EINVAL : 0;}/* the following simply returns the raw data position of the EOM * marker, MTIOCSIZE ioctl */__s64 zft_get_eom_pos(void){ if (zft_qic_mode) { return zft_calc_tape_pos(zft_eom_vtbl->start_seg); } else { /* there is only one volume in raw mode */ return zft_capacity; }}/* skip to eom, used for MTEOM */void zft_skip_to_eom(zft_position *pos){ TRACE_FUN(ft_t_flow); pos->seg_pos = zft_eom_vtbl->start_seg; pos->seg_byte_pos = pos->volume_pos = zft_just_before_eof = 0; pos->tape_pos = zft_calc_tape_pos(pos->seg_pos); TRACE(ft_t_noise, "ftape positioned to segment %d, data pos " LL_X, pos->seg_pos, LL(pos->tape_pos)); TRACE_EXIT;}/* write an EOF-marker by setting zft_last_vtbl->end_seg to seg_pos. * NOTE: this function assumes that zft_last_vtbl points to a valid * vtbl entry * * NOTE: this routine always positions before the EOF marker */int zft_close_volume(zft_position *pos){ TRACE_FUN(ft_t_any); if (zft_vtbl_empty || !zft_last_vtbl->open) { /* should not happen */ TRACE(ft_t_noise, "There are no volumes to finish"); TRACE_EXIT -EIO; } if (pos->seg_byte_pos == 0 && pos->seg_pos != zft_last_vtbl->start_seg) { pos->seg_pos --; pos->seg_byte_pos = zft_get_seg_sz(pos->seg_pos); } zft_last_vtbl->end_seg = pos->seg_pos; zft_last_vtbl->size = pos->volume_pos; zft_volume_table_changed = 1; zft_just_before_eof = 1; zft_eom_vtbl->start_seg = zft_last_vtbl->end_seg + 1; zft_last_vtbl->open = 0; /* closed */ TRACE_EXIT 0;}/* write count file-marks at current position. * * The tape is positioned after the eof-marker, that is at byte 0 of * the segment following the eof-marker * * this function is only allowed in zft_qic_mode * * Only allowed when tape is at BOT or EOD. */int zft_weof(unsigned int count, zft_position *pos){ TRACE_FUN(ft_t_flow); if (!count) { /* write zero EOF marks should be a real no-op */ TRACE_EXIT 0; } zft_volume_table_changed = 1; if (zft_tape_at_lbot(pos)) { zft_init_vtbl(); if(zft_old_ftape) { /* clear old ftape's eof marks */ zft_clear_ftape_file_marks(); zft_old_ftape = 0; /* no longer old ftape */ } } if (zft_last_vtbl->open) { zft_close_volume(pos); zft_move_past_eof(pos); count --; } /* now it's easy, just append eof-marks, that is empty * volumes, to the end of the already recorded media. */ while (count > 0 && pos->seg_pos <= ft_last_data_segment && zft_eom_vtbl->count < ZFT_MAX_VOLUMES) { TRACE(ft_t_noise, "Writing zero sized file at segment %d", pos->seg_pos); zft_new_vtbl_entry(); zft_last_vtbl->start_seg = pos->seg_pos; zft_last_vtbl->end_seg = pos->seg_pos; zft_last_vtbl->size = 0; zft_last_vtbl->blk_sz = zft_blk_sz; zft_last_vtbl->zft_volume = 1; zft_last_vtbl->use_compression = 0; pos->tape_pos += zft_get_seg_sz(pos->seg_pos); zft_eom_vtbl->start_seg = ++ pos->seg_pos; count --; } if (count > 0) { /* there are two possibilities: end of tape, or the * maximum number of files is exhausted. */ zft_resid = count; TRACE(ft_t_noise,"Number of marks NOT written: %d", zft_resid); if (zft_eom_vtbl->count == ZFT_MAX_VOLUMES) { TRACE_ABORT(-EINVAL, ft_t_warn, "maximum allowed number of files " "exhausted: %d", ZFT_MAX_VOLUMES); } else { TRACE_ABORT(-ENOSPC, ft_t_noise, "reached end of tape"); } } TRACE_EXIT 0;}const zft_volinfo *zft_find_volume(unsigned int seg_pos){ TRACE_FUN(ft_t_flow); TRACE(ft_t_any, "called with seg_pos %d",seg_pos); if (!zft_qic_mode) { if (seg_pos > ft_last_data_segment) { TRACE_EXIT &eot_vtbl; } tape_vtbl.blk_sz = zft_blk_sz; TRACE_EXIT &tape_vtbl; } if (seg_pos < zft_first_vtbl->start_seg) { TRACE_EXIT (cur_vtbl = zft_first_vtbl); } while (seg_pos > cur_vtbl->end_seg) { cur_vtbl = list_entry(cur_vtbl->node.next, zft_volinfo, node); TRACE(ft_t_noise, "%d - %d", cur_vtbl->start_seg, cur_vtbl->end_seg); } while (seg_pos < cur_vtbl->start_seg) { cur_vtbl = list_entry(cur_vtbl->node.prev, zft_volinfo, node); TRACE(ft_t_noise, "%d - %d", cur_vtbl->start_seg, cur_vtbl->end_seg); } if (seg_pos > cur_vtbl->end_seg || seg_pos < cur_vtbl->start_seg) { TRACE(ft_t_bug, "This cannot happen"); } DUMP_VOLINFO(ft_t_noise, "", cur_vtbl); TRACE_EXIT cur_vtbl;}/* this function really assumes that we are just before eof */void zft_move_past_eof(zft_position *pos){ TRACE_FUN(ft_t_flow); TRACE(ft_t_noise, "old seg. pos: %d", pos->seg_pos); pos->tape_pos += zft_get_seg_sz(pos->seg_pos++) - pos->seg_byte_pos; pos->seg_byte_pos = 0; pos->volume_pos = 0; if (zft_cmpr_ops) { (*zft_cmpr_ops->reset)(); } zft_just_before_eof = 0; zft_deblock_segment = -1; /* no need to cache it anymore */ TRACE(ft_t_noise, "new seg. pos: %d", pos->seg_pos); TRACE_EXIT;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -