📄 zftape-compress.c
字号:
if (seg_dist < 0) { TRACE(ft_t_bug, "BUG: distance %d > 0, " "segment difference %d < 0", distance, seg_dist); result = -EIO; break; } new_seg = pos->seg_pos + seg_dist; if (new_seg > volume->end_seg) { new_seg = volume->end_seg; } if (old_seg == new_seg || /* loop */ seg_dist <= ZFT_SLOW_SEEK_THRESHOLD || fast_seek_trials >= ZFT_FAST_SEEK_MAX_TRIALS) { TRACE(ft_t_noise, "starting slow seek:\n" KERN_INFO "fast seek failed too often: %s\n" KERN_INFO "near target position : %s\n" KERN_INFO "looping between two segs : %s", (fast_seek_trials >= ZFT_FAST_SEEK_MAX_TRIALS) ? "yes" : "no", (seg_dist <= ZFT_SLOW_SEEK_THRESHOLD) ? "yes" : "no", (old_seg == new_seg) ? "yes" : "no"); result = slow_seek_forward(dest, &cseg, pos, volume, buf); break; } old_seg = new_seg; limit = volume->end_seg; fast_seek_trials ++; for (;;) { result = search_valid_segment(new_seg, limit, volume->size, pos, &cseg, volume, buf); if (result == 0 || result == -EINTR) { break; } if (new_seg == volume->start_seg) { result = -EIO; /* set errror * condition */ break; } limit = new_seg; new_seg -= ZFT_FAST_SEEK_BACKUP; if (new_seg < volume->start_seg) { new_seg = volume->start_seg; } } if (result < 0) { TRACE(ft_t_warn, "Couldn't find a readable segment"); break; } } else /* if (distance < 0) */ { if (seg_dist > 0) { TRACE(ft_t_bug, "BUG: distance %d < 0, " "segment difference %d >0", distance, seg_dist); result = -EIO; break; } new_seg = pos->seg_pos + seg_dist; if (fast_seek_trials > 0 && seg_dist == 0) { /* this avoids sticking to the same * segment all the time. On the other hand: * if we got here for the first time, and the * deblock_buffer still contains a valid * segment, then there is no need to skip to * the previous segment if the desired position * is inside this segment. */ new_seg --; } if (new_seg < volume->start_seg) { new_seg = volume->start_seg; } limit = pos->seg_pos; fast_seek_trials ++; for (;;) { result = search_valid_segment(new_seg, limit, pos->volume_pos, pos, &cseg, volume, buf); if (result == 0 || result == -EINTR) { break; } if (new_seg == volume->start_seg) { result = -EIO; /* set errror * condition */ break; } limit = new_seg; new_seg -= ZFT_FAST_SEEK_BACKUP; if (new_seg < volume->start_seg) { new_seg = volume->start_seg; } } if (result < 0) { TRACE(ft_t_warn, "Couldn't find a readable segment"); break; } } distance = dest - (pos->volume_pos >> 10); } TRACE_EXIT result;}/* advance inside the given segment at most to_do bytes. * of kilobytes moved */static int seek_in_segment(const unsigned int to_do, cmpr_info *c_info, const char *src_buf, const int seg_sz, const int seg_pos, const zft_volinfo *volume){ int result = 0; int blk_sz = volume->blk_sz >> 10; int remaining = to_do; TRACE_FUN(ft_t_flow); if (c_info->offset == 0) { /* new segment just read */ TRACE_CATCH(get_cseg(c_info, src_buf, seg_sz, volume),); c_info->cmpr_pos += c_info->count; DUMP_CMPR_INFO(ft_t_noise, "", c_info); } /* loop and uncompress until user buffer full or * deblock-buffer empty */ TRACE(ft_t_noise, "compressed_sz: %d, compos : %d", c_info->cmpr_sz, c_info->cmpr_pos); while (c_info->spans == 0 && remaining > 0) { if (c_info->cmpr_pos != 0) { /* cmpr buf is not empty */ result += blk_sz; remaining -= blk_sz; c_info->cmpr_pos = 0; } if (remaining > 0) { get_next_cluster(c_info, src_buf, seg_sz, volume->end_seg == seg_pos); if (c_info->count != 0) { c_info->cmpr_pos = c_info->count; c_info->offset += c_info->count; } else { break; } } /* Allow escape from this loop on signal! */ FT_SIGNAL_EXIT(_DONT_BLOCK); DUMP_CMPR_INFO(ft_t_noise, "", c_info); TRACE(ft_t_noise, "to_do: %d", remaining); } if (seg_sz - c_info->offset <= 18) { c_info->offset = seg_sz; } TRACE(ft_t_noise, "\n" KERN_INFO "segment size : %d\n" KERN_INFO "buf_pos_read : %d\n" KERN_INFO "remaining : %d", seg_sz, c_info->offset, seg_sz - c_info->offset); TRACE_EXIT result;} static int slow_seek_forward_until_error(const unsigned int distance, cmpr_info *c_info, zft_position *pos, const zft_volinfo *volume, __u8 *buf){ unsigned int remaining = distance; int seg_sz; int seg_pos; int result; TRACE_FUN(ft_t_flow); seg_pos = pos->seg_pos; do { TRACE_CATCH(seg_sz = zft_fetch_segment(seg_pos, buf, FT_RD_AHEAD),); /* now we have the contents of the actual segment in * the deblock buffer */ TRACE_CATCH(result = seek_in_segment(remaining, c_info, buf, seg_sz, seg_pos,volume),); remaining -= result; pos->volume_pos += result<<10; pos->seg_pos = seg_pos; pos->seg_byte_pos = c_info->offset; seg_pos ++; if (seg_pos <= volume->end_seg && c_info->offset == seg_sz) { pos->seg_pos ++; pos->seg_byte_pos = 0; c_info->offset = 0; } /* Allow escape from this loop on signal! */ FT_SIGNAL_EXIT(_DONT_BLOCK); TRACE(ft_t_noise, "\n" KERN_INFO "remaining: %d\n" KERN_INFO "seg_pos: %d\n" KERN_INFO "end_seg: %d\n" KERN_INFO "result: %d", remaining, seg_pos, volume->end_seg, result); } while (remaining > 0 && seg_pos <= volume->end_seg); TRACE_EXIT 0;}/* return segment id of next segment containing valid data, -EIO otherwise */static int search_valid_segment(unsigned int segment, const unsigned int end_seg, const unsigned int max_foffs, zft_position *pos, cmpr_info *c_info, const zft_volinfo *volume, __u8 *buf){ cmpr_info tmp_info; int seg_sz; TRACE_FUN(ft_t_flow); memset(&tmp_info, 0, sizeof(cmpr_info)); while (segment <= end_seg) { FT_SIGNAL_EXIT(_DONT_BLOCK); TRACE(ft_t_noise, "Searching readable segment between %d and %d", segment, end_seg); seg_sz = zft_fetch_segment(segment, buf, FT_RD_AHEAD); if ((seg_sz > 0) && (get_cseg (&tmp_info, buf, seg_sz, volume) >= 0) && (tmp_info.foffs != 0 || segment == volume->start_seg)) { if ((tmp_info.foffs>>10) > max_foffs) { TRACE_ABORT(-EIO, ft_t_noise, "\n" KERN_INFO "cseg.foff: %d\n" KERN_INFO "dest : %d", (int)(tmp_info.foffs >> 10), max_foffs); } DUMP_CMPR_INFO(ft_t_noise, "", &tmp_info); *c_info = tmp_info; pos->seg_pos = segment; pos->volume_pos = c_info->foffs; pos->seg_byte_pos = c_info->offset; TRACE(ft_t_noise, "found segment at %d", segment); TRACE_EXIT 0; } segment++; } TRACE_EXIT -EIO;}static int slow_seek_forward(unsigned int dest, cmpr_info *c_info, zft_position *pos, const zft_volinfo *volume, __u8 *buf){ unsigned int distance; int result = 0; TRACE_FUN(ft_t_flow); distance = dest - (pos->volume_pos >> 10); while ((distance > 0) && (result = slow_seek_forward_until_error(distance, c_info, pos, volume, buf)) < 0) { if (result == -EINTR) { break; } TRACE(ft_t_noise, "seg_pos: %d", pos->seg_pos); /* the failing segment is either pos->seg_pos or * pos->seg_pos + 1. There is no need to further try * that segment, because ftape_read_segment() already * has tried very much to read it. So we start with * following segment, which is pos->seg_pos + 1 */ if(search_valid_segment(pos->seg_pos+1, volume->end_seg, dest, pos, c_info, volume, buf) < 0) { TRACE(ft_t_noise, "search_valid_segment() failed"); result = -EIO; break; } distance = dest - (pos->volume_pos >> 10); result = 0; TRACE(ft_t_noise, "segment: %d", pos->seg_pos); /* found valid segment, retry the seek */ } TRACE_EXIT result;}static int compute_seg_pos(const unsigned int dest, zft_position *pos, const zft_volinfo *volume){ int segment; int distance = dest - (pos->volume_pos >> 10); unsigned int raw_size; unsigned int virt_size; unsigned int factor; TRACE_FUN(ft_t_flow); if (distance >= 0) { raw_size = volume->end_seg - pos->seg_pos + 1; virt_size = ((unsigned int)(volume->size>>10) - (unsigned int)(pos->volume_pos>>10) + FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS - 1); virt_size /= FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS; if (virt_size == 0 || raw_size == 0) { TRACE_EXIT 0; } if (raw_size >= (1<<25)) { factor = raw_size/(virt_size>>7); } else { factor = (raw_size<<7)/virt_size; } segment = distance/(FT_SECTORS_PER_SEGMENT-FT_ECC_SECTORS); segment = (segment * factor)>>7; } else { raw_size = pos->seg_pos - volume->start_seg + 1; virt_size = ((unsigned int)(pos->volume_pos>>10) + FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS - 1); virt_size /= FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS; if (virt_size == 0 || raw_size == 0) { TRACE_EXIT 0; } if (raw_size >= (1<<25)) { factor = raw_size/(virt_size>>7); } else { factor = (raw_size<<7)/virt_size; } segment = distance/(FT_SECTORS_PER_SEGMENT-FT_ECC_SECTORS); } TRACE(ft_t_noise, "factor: %d/%d", factor, 1<<7); TRACE_EXIT segment;}static struct zft_cmpr_ops cmpr_ops = { zftc_write, zftc_read, zftc_seek, zftc_lock, zftc_reset, zftc_cleanup};int zft_compressor_init(void){ TRACE_FUN(ft_t_flow); #ifdef MODULE printk(KERN_INFO "zftape compressor v1.00a 970514 for " FTAPE_VERSION "\n"); if (TRACE_LEVEL >= ft_t_info) { printk(KERN_INFO "(c) 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"KERN_INFO "Compressor for zftape (lzrw3 algorithm)\n"); }#else /* !MODULE */ /* print a short no-nonsense boot message */ printk(KERN_INFO "zftape compressor v1.00a 970514\n"); printk(KERN_INFO "For use with " FTAPE_VERSION "\n");#endif /* MODULE */ TRACE(ft_t_info, "zft_compressor_init @ 0x%p", zft_compressor_init); TRACE(ft_t_info, "installing compressor for zftape ..."); TRACE_CATCH(zft_cmpr_register(&cmpr_ops),); TRACE_EXIT 0;}#ifdef MODULEMODULE_AUTHOR( "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de");MODULE_DESCRIPTION("Compression routines for zftape. Uses the lzrw3 algorithm by Ross Williams");MODULE_LICENSE("GPL");/* Called by modules package when installing the driver */int init_module(void){ return zft_compressor_init();}#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -