zftape-compress.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:40k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *      Copyright (C) 1994-1997 Claus-Justus Heine
  3.  This program is free software; you can redistribute it and/or
  4.  modify it under the terms of the GNU General Public License as
  5.  published by the Free Software Foundation; either version 2, or (at
  6.  your option) any later version.
  7.  
  8.  This program is distributed in the hope that it will be useful, but
  9.  WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.  General Public License for more details.
  12.  
  13.  You should have received a copy of the GNU General Public License
  14.  along with this program; see the file COPYING.  If not, write to
  15.  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
  16.  USA.
  17.  
  18.  *
  19.  *     This file implements a "generic" interface between the *
  20.  *     zftape-driver and a compression-algorithm. The *
  21.  *     compression-algorithm currently used is a LZ77. I use the *
  22.  *     implementation lzrw3 by Ross N. Williams (Renaissance *
  23.  *     Software). The compression program itself is in the file
  24.  *     lzrw3.c * and lzrw3.h.  To adopt another compression algorithm
  25.  *     the functions * zft_compress() and zft_uncompress() must be
  26.  *     changed * appropriately. See below.
  27.  */
  28.  char zftc_src[] ="$Source: /homes/cvs/ftape-stacked/ftape/compressor/zftape-compress.c,v $";
  29.  char zftc_rev[] = "$Revision: 1.1.6.1 $";
  30.  char zftc_dat[] = "$Date: 1997/11/16 15:15:56 $";
  31. #include <linux/errno.h>
  32. #include <linux/mm.h>
  33. #include <linux/module.h>
  34. #include <linux/zftape.h>
  35. #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,6)
  36. #include <asm/uaccess.h>
  37. #else
  38. #include <asm/segment.h>
  39. #endif
  40. #include "../zftape/zftape-init.h"
  41. #include "../zftape/zftape-eof.h"
  42. #include "../zftape/zftape-ctl.h"
  43. #include "../zftape/zftape-write.h"
  44. #include "../zftape/zftape-read.h"
  45. #include "../zftape/zftape-rw.h"
  46. #include "../compressor/zftape-compress.h"
  47. #include "../zftape/zftape-vtbl.h"
  48. #include "../compressor/lzrw3.h"
  49. /*
  50.  *   global variables
  51.  */
  52. /* I handle the allocation of this buffer as a special case, because
  53.  * it's size varies depending on the tape length inserted.
  54.  */
  55. /* local variables 
  56.  */
  57. static int keep_module_locked = 1;
  58. static void *zftc_wrk_mem = NULL;
  59. static __u8 *zftc_buf     = NULL;
  60. static void *zftc_scratch_buf  = NULL;
  61. /* compression statistics 
  62.  */
  63. static unsigned int zftc_wr_uncompressed = 0;
  64. static unsigned int zftc_wr_compressed   = 0;
  65. static unsigned int zftc_rd_uncompressed = 0;
  66. static unsigned int zftc_rd_compressed   = 0;
  67. /* forward */
  68. static int  zftc_write(int *write_cnt,
  69.        __u8 *dst_buf, const int seg_sz,
  70.        const __u8 *src_buf, const int req_len,
  71.        const zft_position *pos, const zft_volinfo *volume);
  72. static int  zftc_read(int *read_cnt,
  73.       __u8  *dst_buf, const int to_do,
  74.       const __u8 *src_buf, const int seg_sz,
  75.       const zft_position *pos, const zft_volinfo *volume);
  76. static int  zftc_seek(unsigned int new_block_pos, 
  77.       zft_position *pos, const zft_volinfo *volume,
  78.       __u8 *buffer);
  79. static void zftc_lock   (void);
  80. static void zftc_reset  (void);
  81. static void zftc_cleanup(void);
  82. static void zftc_stats      (void);
  83. /* compressed segment. This conforms to QIC-80-MC, Revision K.
  84.  * 
  85.  * Rev. K applies to tapes with `fixed length format' which is
  86.  * indicated by format code 2,3 and 5. See below for format code 4 and 6
  87.  *
  88.  * 2 bytes: offset of compression segment structure
  89.  *          29k > offset >= 29k-18: data from previous segment ens in this
  90.  *                                  segment and no compressed block starts
  91.  *                                  in this segment
  92.  *                     offset == 0: data from previous segment occupies entire
  93.  *                                  segment and continues in next segment
  94.  * n bytes: remainder from previous segment
  95.  * 
  96.  * Rev. K:  
  97.  * 4 bytes: 4 bytes: files set byte offset
  98.  * Post Rev. K and QIC-3020/3020:
  99.  * 8 bytes: 8 bytes: files set byte offset
  100.  * 2 bytes: byte count N (amount of data following)
  101.  *          bit 15 is set if data is compressed, bit 15 is not
  102.  *          set if data is uncompressed
  103.  * N bytes: data (as much as specified in the byte count)
  104.  * 2 bytes: byte count N_1 of next cluster
  105.  * N_1 bytes: data of next cluset
  106.  * 2 bytes: byte count N_2 of next cluster
  107.  * N_2 bytes: ...  
  108.  *
  109.  * Note that the `N' byte count accounts only for the bytes that in the
  110.  * current segment if the cluster spans to the next segment.
  111.  */
  112. typedef struct
  113. {
  114. int cmpr_pos;             /* actual position in compression buffer */
  115. int cmpr_sz;              /* what is left in the compression buffer
  116.    * when copying the compressed data to the
  117.    * deblock buffer
  118.    */
  119. unsigned int first_block; /* location of header information in
  120.    * this segment
  121.    */
  122. unsigned int count;       /* amount of data of current block
  123.    * contained in current segment 
  124.    */
  125. unsigned int offset;      /* offset in current segment */
  126. unsigned int spans:1;     /* might continue in next segment */
  127. unsigned int uncmpr;      /* 0x8000 if this block contains
  128.    * uncompressed data 
  129.    */
  130. __s64 foffs;              /* file set byte offset, same as in 
  131.    * compression map segment
  132.    */
  133. } cmpr_info;
  134. static cmpr_info cseg; /* static data. Must be kept uptodate and shared by 
  135. * read, write and seek functions
  136. */
  137. #define DUMP_CMPR_INFO(level, msg, info)
  138. TRACE(level, msg "n"
  139.       KERN_INFO "cmpr_pos   : %dn"
  140.       KERN_INFO "cmpr_sz    : %dn"
  141.       KERN_INFO "first_block: %dn"
  142.       KERN_INFO "count      : %dn"
  143.       KERN_INFO "offset     : %dn"
  144.       KERN_INFO "spans      : %dn"
  145.       KERN_INFO "uncmpr     : 0x%04xn"
  146.       KERN_INFO "foffs      : " LL_X,
  147.       (info)->cmpr_pos, (info)->cmpr_sz, (info)->first_block,
  148.       (info)->count, (info)->offset, (info)->spans == 1,
  149.       (info)->uncmpr, LL((info)->foffs))
  150. /*   dispatch compression segment info, return error code
  151.  *  
  152.  *   afterwards, cseg->offset points to start of data of the NEXT
  153.  *   compressed block, and cseg->count contains the amount of data
  154.  *   left in the actual compressed block. cseg->spans is set to 1 if
  155.  *   the block is continued in the following segment. Otherwise it is
  156.  *   set to 0. 
  157.  */
  158. static int get_cseg (cmpr_info *cinfo, const __u8 *buff, 
  159.      const unsigned int seg_sz,
  160.      const zft_volinfo *volume)
  161. {
  162. TRACE_FUN(ft_t_flow);
  163.   cinfo->first_block = GET2(buff, 0);
  164. if (cinfo->first_block == 0) { /* data spans to next segment */
  165. cinfo->count  = seg_sz - sizeof(__u16);
  166. cinfo->offset = seg_sz;
  167. cinfo->spans = 1;
  168. } else { /* cluster definetely ends in this segment */
  169. if (cinfo->first_block > seg_sz) {
  170. /* data corrupted */
  171. TRACE_ABORT(-EIO, ft_t_err, "corrupted data:n"
  172.     KERN_INFO "segment size: %dn"
  173.     KERN_INFO "first block : %d",
  174.     seg_sz, cinfo->first_block);
  175. }
  176.         cinfo->count  = cinfo->first_block - sizeof(__u16);
  177. cinfo->offset = cinfo->first_block;
  178. cinfo->spans = 0;
  179. }
  180. /* now get the offset the first block should have in the
  181.  * uncompressed data stream.
  182.  *
  183.  * For this magic `18' refer to CRF-3 standard or QIC-80MC,
  184.  * Rev. K.  
  185.  */
  186. if ((seg_sz - cinfo->offset) > 18) {
  187. if (volume->qic113) { /* > revision K */
  188. TRACE(ft_t_data_flow, "New QIC-113 compliance");
  189. cinfo->foffs = GET8(buff, cinfo->offset);
  190. cinfo->offset += sizeof(__s64); 
  191. } else {
  192. TRACE(/* ft_t_data_flow */ ft_t_noise, "pre QIC-113 version");
  193. cinfo->foffs   = (__s64)GET4(buff, cinfo->offset);
  194. cinfo->offset += sizeof(__u32); 
  195. }
  196. }
  197. if (cinfo->foffs > volume->size) {
  198. TRACE_ABORT(-EIO, ft_t_err, "Inconsistency:n"
  199.     KERN_INFO "offset in current volume: %dn"
  200.     KERN_INFO "size of current volume  : %d",
  201.     (int)(cinfo->foffs>>10), (int)(volume->size>>10));
  202. }
  203. if (cinfo->cmpr_pos + cinfo->count > volume->blk_sz) {
  204. TRACE_ABORT(-EIO, ft_t_err, "Inconsistency:n"
  205.     KERN_INFO "block size : %dn"
  206.     KERN_INFO "data record: %d",
  207.     volume->blk_sz, cinfo->cmpr_pos + cinfo->count);
  208. }
  209. DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */, "", cinfo);
  210. TRACE_EXIT 0;
  211. }
  212. /*  This one is called, when a new cluster starts in same segment.
  213.  *  
  214.  *  Note: if this is the first cluster in the current segment, we must
  215.  *  not check whether there are more than 18 bytes available because
  216.  *  this have already been done in get_cseg() and there may be less
  217.  *  than 18 bytes available due to header information.
  218.  * 
  219.  */
  220. static void get_next_cluster(cmpr_info *cluster, const __u8 *buff, 
  221.      const int seg_sz, const int finish)
  222. {
  223. TRACE_FUN(ft_t_flow);
  224. if (seg_sz - cluster->offset > 18 || cluster->foffs != 0) {
  225. cluster->count   = GET2(buff, cluster->offset);
  226. cluster->uncmpr  = cluster->count & 0x8000;
  227. cluster->count  -= cluster->uncmpr;
  228. cluster->offset += sizeof(__u16);
  229. cluster->foffs   = 0;
  230. if ((cluster->offset + cluster->count) < seg_sz) {
  231. cluster->spans = 0;
  232. } else if (cluster->offset + cluster->count == seg_sz) {
  233. cluster->spans = !finish;
  234. } else {
  235. /* either an error or a volume written by an 
  236.  * old version. If this is a data error, then we'll
  237.  * catch it later.
  238.  */
  239. TRACE(ft_t_data_flow, "Either error or old volume");
  240. cluster->spans = 1;
  241. cluster->count = seg_sz - cluster->offset;
  242. }
  243. } else {
  244. cluster->count = 0;
  245. cluster->spans = 0;
  246. cluster->foffs = 0;
  247. }
  248. DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */ , "", cluster);
  249. TRACE_EXIT;
  250. }
  251. static void zftc_lock(void)
  252. {
  253. #if LINUX_VERSION_CODE < KERNEL_VER(2,1,18)
  254. if (!MOD_IN_USE) {
  255. MOD_INC_USE_COUNT;
  256. }
  257. #else
  258. MOD_INC_USE_COUNT; /*  sets MOD_VISITED and MOD_USED_ONCE,
  259.     *  locking is done with can_unload()
  260.     */
  261. #endif
  262. keep_module_locked = 1;
  263. }
  264. /*  this function is needed for zftape_reset_position in zftape-io.c 
  265.  */
  266. static void zftc_reset(void)
  267. {
  268. TRACE_FUN(ft_t_flow);
  269. memset((void *)&cseg, '', sizeof(cseg));
  270. zftc_stats();
  271. #if LINUX_VERSION_CODE < KERNEL_VER(2,1,18)
  272. if (MOD_IN_USE) {
  273. MOD_DEC_USE_COUNT;
  274. }
  275. #endif
  276. keep_module_locked = 0;
  277. TRACE_EXIT;
  278. }
  279. static int cmpr_mem_initialized = 0;
  280. static unsigned int alloc_blksz = 0;
  281. static int zft_allocate_cmpr_mem(unsigned int blksz)
  282. {
  283. TRACE_FUN(ft_t_flow);
  284. if (cmpr_mem_initialized && blksz == alloc_blksz) {
  285. TRACE_EXIT 0;
  286. }
  287. TRACE_CATCH(zft_vmalloc_once(&zftc_wrk_mem, CMPR_WRK_MEM_SIZE),
  288.     zftc_cleanup());
  289. TRACE_CATCH(zft_vmalloc_always(&zftc_buf, blksz + CMPR_OVERRUN),
  290.     zftc_cleanup());
  291. alloc_blksz = blksz;
  292. TRACE_CATCH(zft_vmalloc_always(&zftc_scratch_buf, blksz+CMPR_OVERRUN),
  293.     zftc_cleanup());
  294. cmpr_mem_initialized = 1;
  295. TRACE_EXIT 0;
  296. }
  297. static void zftc_cleanup(void)
  298. {
  299. TRACE_FUN(ft_t_flow);
  300. zft_vfree(&zftc_wrk_mem, CMPR_WRK_MEM_SIZE);
  301. zft_vfree(&zftc_buf, alloc_blksz + CMPR_OVERRUN);
  302. zft_vfree(&zftc_scratch_buf, alloc_blksz + CMPR_OVERRUN);
  303. cmpr_mem_initialized = alloc_blksz = 0;
  304. TRACE_EXIT;
  305. }
  306. /*****************************************************************************
  307.  *                                                                           *
  308.  *  The following two functions "ftape_compress()" and                       *
  309.  *  "ftape_uncompress()" are the interface to the actual compression         *
  310.  *  algorithm (i.e. they are calling the "compress()" function from          *
  311.  *  the lzrw3 package for now). These routines could quite easily be         *
  312.  *  changed to adopt another compression algorithm instead of lzrw3,         *
  313.  *  which currently is used.                                                 *
  314.  *                                                                           *
  315.  *****************************************************************************/
  316. /* called by zft_compress_write() to perform the compression. Must
  317.  * return the size of the compressed data.
  318.  *
  319.  * NOTE: The size of the compressed data should not exceed the size of
  320.  *       the uncompressed data. Most compression algorithms have means
  321.  *       to store data unchanged if the "compressed" data amount would
  322.  *       exceed the original one. Mostly this is done by storing some
  323.  *       flag-bytes in front of the compressed data to indicate if it
  324.  *       is compressed or not. Thus the worst compression result
  325.  *       length is the original length plus those flag-bytes.
  326.  *
  327.  *       We don't want that, as the QIC-80 standard provides a means
  328.  *       of marking uncompressed blocks by simply setting bit 15 of
  329.  *       the compressed block's length. Thus a compessed block can
  330.  *       have at most a length of 2^15-1 bytes. The QIC-80 standard
  331.  *       restricts the block-length even further, allowing only 29k -
  332.  *       6 bytes.
  333.  *
  334.  *       Currently, the maximum blocksize used by zftape is 28k.
  335.  *
  336.  *       In short: don't exceed the length of the input-package, set
  337.  *       bit 15 of the compressed size to 1 if you have copied data
  338.  *       instead of compressing it.
  339.  */
  340. static int zft_compress(__u8 *in_buffer, unsigned int in_sz, __u8 *out_buffer)
  341. __s32 compressed_sz;
  342. TRACE_FUN(ft_t_flow);
  343. lzrw3_compress(COMPRESS_ACTION_COMPRESS, zftc_wrk_mem,
  344.        in_buffer, in_sz, out_buffer, &compressed_sz);
  345. if (TRACE_LEVEL >= ft_t_info) {
  346. /*  the compiler will optimize this away when
  347.  *  compiled with NO_TRACE_AT_ALL option
  348.  */
  349. TRACE(ft_t_data_flow, "n"
  350.       KERN_INFO "before compression: %d bytesn"
  351.       KERN_INFO "after compresison : %d bytes", 
  352.       in_sz, 
  353.       (int)(compressed_sz < 0 
  354.       ? -compressed_sz : compressed_sz));
  355. /*  for statistical purposes
  356.  */
  357. zftc_wr_compressed   += (compressed_sz < 0 
  358.    ? -compressed_sz : compressed_sz);
  359. zftc_wr_uncompressed += in_sz;
  360. }
  361. TRACE_EXIT (int)compressed_sz;
  362. }
  363. /* called by zft_compress_read() to decompress the data. Must
  364.  * return the size of the decompressed data for sanity checks
  365.  * (compared with zft_blk_sz)
  366.  *
  367.  * NOTE: Read the note for zft_compress() above!  If bit 15 of the
  368.  *       parameter in_sz is set, then the data in in_buffer isn't
  369.  *       compressed, which must be handled by the un-compression
  370.  *       algorithm. (I changed lzrw3 to handle this.)
  371.  *
  372.  *  The parameter max_out_sz is needed to prevent buffer overruns when 
  373.  *  uncompressing corrupt data.
  374.  */
  375. static unsigned int zft_uncompress(__u8 *in_buffer, 
  376.    int in_sz, 
  377.    __u8 *out_buffer,
  378.    unsigned int max_out_sz)
  379. TRACE_FUN(ft_t_flow);
  380. lzrw3_compress(COMPRESS_ACTION_DECOMPRESS, zftc_wrk_mem,
  381.        in_buffer, (__s32)in_sz,
  382.        out_buffer, (__u32 *)&max_out_sz);
  383. if (TRACE_LEVEL >= ft_t_info) {
  384. TRACE(ft_t_data_flow, "n"
  385.       KERN_INFO "before decompression: %d bytesn"
  386.       KERN_INFO "after decompression : %d bytes", 
  387.       in_sz < 0 ? -in_sz : in_sz,(int)max_out_sz);
  388. /*  for statistical purposes
  389.  */
  390. zftc_rd_compressed   += in_sz < 0 ? -in_sz : in_sz;
  391. zftc_rd_uncompressed += max_out_sz;
  392. }
  393. TRACE_EXIT (unsigned int)max_out_sz;
  394. }
  395. /* print some statistics about the efficiency of the compression to
  396.  * the kernel log 
  397.  */
  398. static void zftc_stats(void)
  399. {
  400. TRACE_FUN(ft_t_flow);
  401. if (TRACE_LEVEL < ft_t_info) {
  402. TRACE_EXIT;
  403. }
  404. if (zftc_wr_uncompressed != 0) {
  405. if (zftc_wr_compressed > (1<<14)) {
  406. TRACE(ft_t_info, "compression statistics (writing):n"
  407.       KERN_INFO " compr./uncmpr.   : %3d %%",
  408.       (((zftc_wr_compressed>>10) * 100)
  409.        / (zftc_wr_uncompressed>>10)));
  410. } else {
  411. TRACE(ft_t_info, "compression statistics (writing):n"
  412.       KERN_INFO " compr./uncmpr.   : %3d %%",
  413.       ((zftc_wr_compressed * 100)
  414.        / zftc_wr_uncompressed));
  415. }
  416. }
  417. if (zftc_rd_uncompressed != 0) {
  418. if (zftc_rd_compressed > (1<<14)) {
  419. TRACE(ft_t_info, "compression statistics (reading):n"
  420.       KERN_INFO " compr./uncmpr.   : %3d %%",
  421.       (((zftc_rd_compressed>>10) * 100)
  422.        / (zftc_rd_uncompressed>>10)));
  423. } else {
  424. TRACE(ft_t_info, "compression statistics (reading):n"
  425.       KERN_INFO " compr./uncmpr.   : %3d %%",
  426.       ((zftc_rd_compressed * 100)
  427.        / zftc_rd_uncompressed));
  428. }
  429. }
  430. /* only print it once: */
  431. zftc_wr_uncompressed = 
  432. zftc_wr_compressed  =
  433. zftc_rd_uncompressed =
  434. zftc_rd_compressed   = 0;
  435. TRACE_EXIT;
  436. }
  437. /* start new compressed block 
  438.  */
  439. static int start_new_cseg(cmpr_info *cluster, 
  440.   char *dst_buf, 
  441.   const zft_position *pos,
  442.   const unsigned int blk_sz,
  443.   const char *src_buf,
  444.   const int this_segs_sz,
  445.   const int qic113)
  446. {
  447. int size_left;
  448. int cp_cnt;
  449. int buf_pos;
  450. TRACE_FUN(ft_t_flow);
  451. size_left = this_segs_sz - sizeof(__u16) - cluster->cmpr_sz;
  452. TRACE(ft_t_data_flow,"n" 
  453.       KERN_INFO "segment size   : %dn"
  454.       KERN_INFO "compressed_sz: %dn"
  455.       KERN_INFO "size_left      : %d",
  456.       this_segs_sz, cluster->cmpr_sz, size_left);
  457. if (size_left > 18) { /* start a new cluseter */
  458. cp_cnt = cluster->cmpr_sz;
  459. cluster->cmpr_sz = 0;
  460. buf_pos = cp_cnt + sizeof(__u16);
  461. PUT2(dst_buf, 0, buf_pos);
  462. if (qic113) {
  463. __s64 foffs = pos->volume_pos;
  464. if (cp_cnt) foffs += (__s64)blk_sz;
  465. TRACE(ft_t_data_flow, "new style QIC-113 header");
  466. PUT8(dst_buf, buf_pos, foffs);
  467. buf_pos += sizeof(__s64);
  468. } else {
  469. __u32 foffs = (__u32)pos->volume_pos;
  470. if (cp_cnt) foffs += (__u32)blk_sz;
  471. TRACE(ft_t_data_flow, "old style QIC-80MC header");
  472. PUT4(dst_buf, buf_pos, foffs);
  473. buf_pos += sizeof(__u32);
  474. }
  475. } else if (size_left >= 0) {
  476. cp_cnt = cluster->cmpr_sz;
  477. cluster->cmpr_sz = 0;
  478. buf_pos = cp_cnt + sizeof(__u16);
  479. PUT2(dst_buf, 0, buf_pos);  
  480. /* zero unused part of segment. */
  481. memset(dst_buf + buf_pos, '', size_left);
  482. buf_pos = this_segs_sz;
  483. } else { /* need entire segment and more space */
  484. PUT2(dst_buf, 0, 0); 
  485. cp_cnt = this_segs_sz - sizeof(__u16);
  486. cluster->cmpr_sz  -= cp_cnt;
  487. buf_pos = this_segs_sz;
  488. }
  489. memcpy(dst_buf + sizeof(__u16), src_buf + cluster->cmpr_pos, cp_cnt);
  490. cluster->cmpr_pos += cp_cnt;
  491. TRACE_EXIT buf_pos;
  492. }
  493. /* return-value: the number of bytes removed from the user-buffer
  494.  *               `src_buf' or error code
  495.  *
  496.  *  int *write_cnt           : how much actually has been moved to the
  497.  *                             dst_buf. Need not be initialized when
  498.  *                             function returns with an error code
  499.  *                             (negativ return value) 
  500.  *  __u8 *dst_buf            : kernel space buffer where the has to be
  501.  *                             copied to. The contents of this buffers
  502.  *                             goes to a specific segment.
  503.  *  const int seg_sz         : the size of the segment dst_buf will be
  504.  *                             copied to.
  505.  *  const zft_position *pos  : struct containing the coordinates in
  506.  *                             the current volume (byte position,
  507.  *                             segment id of current segment etc)
  508.  *  const zft_volinfo *volume: information about the current volume,
  509.  *                             size etc.
  510.  *  const __u8 *src_buf      : user space buffer that contains the
  511.  *                             data the user wants to be written to
  512.  *                             tape.
  513.  *  const int req_len        : the amount of data the user wants to be
  514.  *                             written to tape.
  515.  */
  516. static int zftc_write(int *write_cnt,
  517.       __u8 *dst_buf, const int seg_sz,
  518.       const __u8 *src_buf, const int req_len,
  519.       const zft_position *pos, const zft_volinfo *volume)
  520. {
  521. int req_len_left = req_len;
  522. int result;
  523. int len_left;
  524. int buf_pos_write = pos->seg_byte_pos;
  525. TRACE_FUN(ft_t_flow);
  526. keep_module_locked = 1;
  527. #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,18)
  528. MOD_INC_USE_COUNT; /*  sets MOD_VISITED and MOD_USED_ONCE,
  529.     *  locking is done with can_unload()
  530.     */
  531. #else
  532. if (!MOD_IN_USE) {
  533. MOD_INC_USE_COUNT;
  534. }
  535. #endif
  536. /* Note: we do not unlock the module because
  537.  * there are some values cached in that `cseg' variable.  We
  538.  * don't don't want to use this information when being
  539.  * unloaded by kerneld even when the tape is full or when we
  540.  * cannot allocate enough memory.
  541.  */
  542. if (pos->tape_pos > (volume->size-volume->blk_sz-ZFT_CMPR_OVERHEAD)) {
  543. TRACE_EXIT -ENOSPC;
  544. }    
  545. if (zft_allocate_cmpr_mem(volume->blk_sz) < 0) {
  546. /* should we unlock the module? But it shouldn't 
  547.  * be locked anyway ...
  548.  */
  549. TRACE_EXIT -ENOMEM;
  550. }
  551. if (buf_pos_write == 0) { /* fill a new segment */
  552. *write_cnt = buf_pos_write = start_new_cseg(&cseg,
  553.     dst_buf,
  554.     pos,
  555.     volume->blk_sz,
  556.     zftc_buf, 
  557.     seg_sz,
  558.     volume->qic113);
  559. if (cseg.cmpr_sz == 0 && cseg.cmpr_pos != 0) {
  560. req_len_left -= result = volume->blk_sz;
  561. cseg.cmpr_pos  = 0;
  562. } else {
  563. result = 0;
  564. }
  565. } else {
  566. *write_cnt = result = 0;
  567. }
  568. len_left = seg_sz - buf_pos_write;
  569. while ((req_len_left > 0) && (len_left > 18)) {
  570. /* now we have some size left for a new compressed
  571.  * block.  We know, that the compression buffer is
  572.  * empty (else there wouldn't be any space left).  
  573.  */
  574. #if LINUX_VERSION_CODE > KERNEL_VER(2,1,3)
  575. if (copy_from_user(zftc_scratch_buf, src_buf + result, 
  576.    volume->blk_sz) != 0) {
  577. TRACE_EXIT -EFAULT;
  578. }
  579. #else
  580. TRACE_CATCH(verify_area(VERIFY_READ, src_buf + result, 
  581. volume->blk_sz),);
  582. memcpy_fromfs(zftc_scratch_buf, src_buf + result, 
  583.       volume->blk_sz);
  584. #endif
  585. req_len_left -= volume->blk_sz;
  586. cseg.cmpr_sz = zft_compress(zftc_scratch_buf, volume->blk_sz, 
  587.     zftc_buf);
  588. if (cseg.cmpr_sz < 0) {
  589. cseg.uncmpr = 0x8000;
  590. cseg.cmpr_sz = -cseg.cmpr_sz;
  591. } else {
  592. cseg.uncmpr = 0;
  593. }
  594. /* increment "result" iff we copied the entire
  595.  * compressed block to the zft_deblock_buf 
  596.  */
  597. len_left -= sizeof(__u16);
  598. if (len_left >= cseg.cmpr_sz) {
  599. len_left -= cseg.count = cseg.cmpr_sz;
  600. cseg.cmpr_pos = cseg.cmpr_sz = 0;
  601. result += volume->blk_sz;
  602. } else {
  603. cseg.cmpr_sz       -= 
  604. cseg.cmpr_pos =
  605. cseg.count    = len_left;
  606. len_left = 0;
  607. }
  608. PUT2(dst_buf, buf_pos_write, cseg.uncmpr | cseg.count);
  609. buf_pos_write += sizeof(__u16);
  610. memcpy(dst_buf + buf_pos_write, zftc_buf, cseg.count);
  611. buf_pos_write += cseg.count;
  612. *write_cnt    += cseg.count + sizeof(__u16);
  613. FT_SIGNAL_EXIT(_DONT_BLOCK);
  614. }
  615. /* erase the remainder of the segment if less than 18 bytes
  616.  * left (18 bytes is due to the QIC-80 standard) 
  617.  */
  618. if (len_left <= 18) {
  619. memset(dst_buf + buf_pos_write, '', len_left);
  620. (*write_cnt) += len_left;
  621. }
  622. TRACE(ft_t_data_flow, "returning %d", result);
  623. TRACE_EXIT result;
  624. }   
  625. /* out:
  626.  *
  627.  * int *read_cnt: the number of bytes we removed from the zft_deblock_buf
  628.  *                (result)
  629.  * int *to_do   : the remaining size of the read-request.
  630.  *
  631.  * in:
  632.  *
  633.  * char *buff          : buff is the address of the upper part of the user
  634.  *                       buffer, that hasn't been filled with data yet.
  635.  * int buf_pos_read    : copy of from _ftape_read()
  636.  * int buf_len_read    : copy of buf_len_rd from _ftape_read()
  637.  * char *zft_deblock_buf: zft_deblock_buf
  638.  * unsigned short blk_sz: the block size valid for this volume, may differ
  639.  *                            from zft_blk_sz.
  640.  * int finish: if != 0 means that this is the last segment belonging
  641.  *  to this volume
  642.  * returns the amount of data actually copied to the user-buffer
  643.  *
  644.  * to_do MUST NOT SHRINK except to indicate an EOF. In this case *to_do has to
  645.  * be set to 0 
  646.  */
  647. static int zftc_read (int *read_cnt, 
  648.       __u8  *dst_buf, const int to_do, 
  649.       const __u8 *src_buf, const int seg_sz, 
  650.       const zft_position *pos, const zft_volinfo *volume)
  651. {          
  652. int uncompressed_sz;         
  653. int result = 0;
  654. int remaining = to_do;
  655. TRACE_FUN(ft_t_flow);
  656. keep_module_locked = 1;
  657. #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,18)
  658. MOD_INC_USE_COUNT; /*  sets MOD_VISITED and MOD_USED_ONCE,
  659.     *  locking is done with can_unload()
  660.     */
  661. #else
  662. if (!MOD_IN_USE) {
  663. MOD_INC_USE_COUNT;
  664. }
  665. #endif
  666. TRACE_CATCH(zft_allocate_cmpr_mem(volume->blk_sz),);
  667. if (pos->seg_byte_pos == 0) {
  668. /* new segment just read
  669.  */
  670. TRACE_CATCH(get_cseg(&cseg, src_buf, seg_sz, volume),
  671.     *read_cnt = 0);
  672. memcpy(zftc_buf + cseg.cmpr_pos, src_buf + sizeof(__u16), 
  673.        cseg.count);
  674. cseg.cmpr_pos += cseg.count;
  675. *read_cnt      = cseg.offset;
  676. DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */, "", &cseg);
  677. } else {
  678. *read_cnt = 0;
  679. }
  680. /* loop and uncompress until user buffer full or
  681.  * deblock-buffer empty 
  682.  */
  683. TRACE(ft_t_data_flow, "compressed_sz: %d, compos : %d, *read_cnt: %d",
  684.       cseg.cmpr_sz, cseg.cmpr_pos, *read_cnt);
  685. while ((cseg.spans == 0) && (remaining > 0)) {
  686. if (cseg.cmpr_pos  != 0) { /* cmpr buf is not empty */
  687. uncompressed_sz = 
  688. zft_uncompress(zftc_buf,
  689.        cseg.uncmpr == 0x8000 ?
  690.        -cseg.cmpr_pos : cseg.cmpr_pos,
  691.        zftc_scratch_buf,
  692.        volume->blk_sz);
  693. if (uncompressed_sz != volume->blk_sz) {
  694. *read_cnt = 0;
  695. TRACE_ABORT(-EIO, ft_t_warn,
  696.       "Uncompressed blk (%d) != blk size (%d)",
  697.       uncompressed_sz, volume->blk_sz);
  698. }       
  699. #if LINUX_VERSION_CODE > KERNEL_VER(2,1,3)
  700. if (copy_to_user(dst_buf + result, 
  701.  zftc_scratch_buf, 
  702.  uncompressed_sz) != 0 ) {
  703. TRACE_EXIT -EFAULT;
  704. }
  705. #else
  706. memcpy_tofs(dst_buf + result, zftc_scratch_buf, 
  707.     uncompressed_sz);
  708. #endif
  709. remaining      -= uncompressed_sz;
  710. result     += uncompressed_sz;
  711. cseg.cmpr_pos  = 0;
  712. }                                              
  713. if (remaining > 0) {
  714. get_next_cluster(&cseg, src_buf, seg_sz, 
  715.  volume->end_seg == pos->seg_pos);
  716. if (cseg.count != 0) {
  717. memcpy(zftc_buf, src_buf + cseg.offset,
  718.        cseg.count);
  719. cseg.cmpr_pos = cseg.count;
  720. cseg.offset  += cseg.count;
  721. *read_cnt += cseg.count + sizeof(__u16);
  722. } else {
  723. remaining = 0;
  724. }
  725. }
  726. TRACE(ft_t_data_flow, "n" 
  727.       KERN_INFO "compressed_sz: %dn"
  728.       KERN_INFO "compos       : %dn"
  729.       KERN_INFO "*read_cnt    : %d",
  730.       cseg.cmpr_sz, cseg.cmpr_pos, *read_cnt);
  731. }
  732. if (seg_sz - cseg.offset <= 18) {
  733. *read_cnt += seg_sz - cseg.offset;
  734. TRACE(ft_t_data_flow, "expanding read cnt to: %d", *read_cnt);
  735. }
  736. TRACE(ft_t_data_flow, "n"
  737.       KERN_INFO "segment size   : %dn"
  738.       KERN_INFO "read count     : %dn"
  739.       KERN_INFO "buf_pos_read   : %dn"
  740.       KERN_INFO "remaining      : %d",
  741. seg_sz, *read_cnt, pos->seg_byte_pos, 
  742. seg_sz - *read_cnt - pos->seg_byte_pos);
  743. TRACE(ft_t_data_flow, "returning: %d", result);
  744. TRACE_EXIT result;
  745. }                
  746. /* seeks to the new data-position. Reads sometimes a segment.
  747.  *  
  748.  * start_seg and end_seg give the boundaries of the current volume
  749.  * blk_sz is the blk_sz of the current volume as stored in the
  750.  * volume label
  751.  *
  752.  * We don't allow blocksizes less than 1024 bytes, therefore we don't need
  753.  * a 64 bit argument for new_block_pos.
  754.  */
  755. static int seek_in_segment(const unsigned int to_do, cmpr_info  *c_info,
  756.    const char *src_buf, const int seg_sz, 
  757.    const int seg_pos, const zft_volinfo *volume);
  758. static int slow_seek_forward_until_error(const unsigned int distance,
  759.  cmpr_info *c_info, zft_position *pos, 
  760.  const zft_volinfo *volume, __u8 *buf);
  761. static int search_valid_segment(unsigned int segment,
  762. const unsigned int end_seg,
  763. const unsigned int max_foffs,
  764. zft_position *pos, cmpr_info *c_info,
  765. const zft_volinfo *volume, __u8 *buf);
  766. static int slow_seek_forward(unsigned int dest, cmpr_info *c_info,
  767.      zft_position *pos, const zft_volinfo *volume,
  768.      __u8 *buf);
  769. static int compute_seg_pos(unsigned int dest, zft_position *pos,
  770.    const zft_volinfo *volume);
  771. #define ZFT_SLOW_SEEK_THRESHOLD  10 /* segments */
  772. #define ZFT_FAST_SEEK_MAX_TRIALS 10 /* times */
  773. #define ZFT_FAST_SEEK_BACKUP     10 /* segments */
  774. static int zftc_seek(unsigned int new_block_pos,
  775.      zft_position *pos, const zft_volinfo *volume, __u8 *buf)
  776. {
  777. unsigned int dest;
  778. int limit;
  779. int distance;
  780. int result = 0;
  781. int seg_dist;
  782. int new_seg;
  783. int old_seg = 0;
  784. int fast_seek_trials = 0;
  785. TRACE_FUN(ft_t_flow);
  786. keep_module_locked = 1;
  787. #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,18)
  788. MOD_INC_USE_COUNT; /*  sets MOD_VISITED and MOD_USED_ONCE,
  789.     *  locking is done with can_unload()
  790.     */
  791. #else
  792. if (!MOD_IN_USE) {
  793. MOD_INC_USE_COUNT;
  794. }
  795. #endif
  796. if (new_block_pos == 0) {
  797. pos->seg_pos      = volume->start_seg;
  798. pos->seg_byte_pos = 0;
  799. pos->volume_pos   = 0;
  800. zftc_reset();
  801. TRACE_EXIT 0;
  802. }
  803. dest = new_block_pos * (volume->blk_sz >> 10);
  804. distance = dest - (pos->volume_pos >> 10);
  805. while (distance != 0) {
  806. seg_dist = compute_seg_pos(dest, pos, volume);
  807. TRACE(ft_t_noise, "n"
  808.       KERN_INFO "seg_dist: %dn"
  809.       KERN_INFO "distance: %dn"
  810.       KERN_INFO "dest    : %dn"
  811.       KERN_INFO "vpos    : %dn"
  812.       KERN_INFO "seg_pos : %dn"
  813.       KERN_INFO "trials  : %d",
  814.       seg_dist, distance, dest,
  815.       (unsigned int)(pos->volume_pos>>10), pos->seg_pos,
  816.       fast_seek_trials);
  817. if (distance > 0) {
  818. if (seg_dist < 0) {
  819. TRACE(ft_t_bug, "BUG: distance %d > 0, "
  820.       "segment difference %d < 0",
  821.       distance, seg_dist);
  822. result = -EIO;
  823. break;
  824. }
  825. new_seg = pos->seg_pos + seg_dist;
  826. if (new_seg > volume->end_seg) {
  827. new_seg = volume->end_seg;
  828. }
  829. if (old_seg == new_seg || /* loop */
  830.     seg_dist <= ZFT_SLOW_SEEK_THRESHOLD ||
  831.     fast_seek_trials >= ZFT_FAST_SEEK_MAX_TRIALS) {
  832. TRACE(ft_t_noise, "starting slow seek:n"
  833.    KERN_INFO "fast seek failed too often: %sn"
  834.    KERN_INFO "near target position      : %sn"
  835.    KERN_INFO "looping between two segs  : %s",
  836.       (fast_seek_trials >= 
  837.        ZFT_FAST_SEEK_MAX_TRIALS)
  838.       ? "yes" : "no",
  839.       (seg_dist <= ZFT_SLOW_SEEK_THRESHOLD) 
  840.       ? "yes" : "no",
  841.       (old_seg == new_seg)
  842.       ? "yes" : "no");
  843. result = slow_seek_forward(dest, &cseg, 
  844.    pos, volume, buf);
  845. break;
  846. }
  847. old_seg = new_seg;
  848. limit = volume->end_seg;
  849. fast_seek_trials ++;
  850. for (;;) {
  851. result = search_valid_segment(new_seg, limit,
  852.       volume->size,
  853.       pos, &cseg,
  854.       volume, buf);
  855. if (result == 0 || result == -EINTR) {
  856. break;
  857. }
  858. if (new_seg == volume->start_seg) {
  859. result = -EIO; /* set errror 
  860. * condition
  861. */
  862. break;
  863. }
  864. limit    = new_seg;
  865. new_seg -= ZFT_FAST_SEEK_BACKUP;
  866. if (new_seg < volume->start_seg) {
  867. new_seg = volume->start_seg;
  868. }
  869. }
  870. if (result < 0) {
  871. TRACE(ft_t_warn,
  872.       "Couldn't find a readable segment");
  873. break;
  874. }
  875. } else /* if (distance < 0) */ {
  876. if (seg_dist > 0) {
  877. TRACE(ft_t_bug, "BUG: distance %d < 0, "
  878.       "segment difference %d >0",
  879.       distance, seg_dist);
  880. result = -EIO;
  881. break;
  882. }
  883. new_seg = pos->seg_pos + seg_dist;
  884. if (fast_seek_trials > 0 && seg_dist == 0) {
  885. /* this avoids sticking to the same
  886.  * segment all the time. On the other hand:
  887.  * if we got here for the first time, and the
  888.  * deblock_buffer still contains a valid
  889.  * segment, then there is no need to skip to 
  890.  * the previous segment if the desired position
  891.  * is inside this segment.
  892.  */
  893. new_seg --;
  894. }
  895. if (new_seg < volume->start_seg) {
  896. new_seg = volume->start_seg;
  897. }
  898. limit   = pos->seg_pos;
  899. fast_seek_trials ++;
  900. for (;;) {
  901. result = search_valid_segment(new_seg, limit,
  902.       pos->volume_pos,
  903.       pos, &cseg,
  904.       volume, buf);
  905. if (result == 0 || result == -EINTR) {
  906. break;
  907. }
  908. if (new_seg == volume->start_seg) {
  909. result = -EIO; /* set errror 
  910. * condition
  911. */
  912. break;
  913. }
  914. limit    = new_seg;
  915. new_seg -= ZFT_FAST_SEEK_BACKUP;
  916. if (new_seg < volume->start_seg) {
  917. new_seg = volume->start_seg;
  918. }
  919. }
  920. if (result < 0) {
  921. TRACE(ft_t_warn,
  922.       "Couldn't find a readable segment");
  923. break;
  924. }
  925. }
  926. distance = dest - (pos->volume_pos >> 10);
  927. }
  928. TRACE_EXIT result;
  929. }
  930. /*  advance inside the given segment at most to_do bytes.
  931.  *  of kilobytes moved
  932.  */
  933. static int seek_in_segment(const unsigned int to_do,
  934.    cmpr_info  *c_info,
  935.    const char *src_buf, 
  936.    const int seg_sz, 
  937.    const int seg_pos,
  938.    const zft_volinfo *volume)
  939. {
  940. int result = 0;
  941. int blk_sz = volume->blk_sz >> 10;
  942. int remaining = to_do;
  943. TRACE_FUN(ft_t_flow);
  944. if (c_info->offset == 0) {
  945. /* new segment just read
  946.  */
  947. TRACE_CATCH(get_cseg(c_info, src_buf, seg_sz, volume),);
  948. c_info->cmpr_pos += c_info->count;
  949. DUMP_CMPR_INFO(ft_t_noise, "", c_info);
  950. }
  951. /* loop and uncompress until user buffer full or
  952.  * deblock-buffer empty 
  953.  */
  954. TRACE(ft_t_noise, "compressed_sz: %d, compos : %d",
  955.       c_info->cmpr_sz, c_info->cmpr_pos);
  956. while (c_info->spans == 0 && remaining > 0) {
  957. if (c_info->cmpr_pos  != 0) { /* cmpr buf is not empty */
  958. result       += blk_sz;
  959. remaining    -= blk_sz;
  960. c_info->cmpr_pos = 0;
  961. }
  962. if (remaining > 0) {
  963. get_next_cluster(c_info, src_buf, seg_sz, 
  964.  volume->end_seg == seg_pos);
  965. if (c_info->count != 0) {
  966. c_info->cmpr_pos = c_info->count;
  967. c_info->offset  += c_info->count;
  968. } else {
  969. break;
  970. }
  971. }
  972. /*  Allow escape from this loop on signal!
  973.  */
  974. FT_SIGNAL_EXIT(_DONT_BLOCK);
  975. DUMP_CMPR_INFO(ft_t_noise, "", c_info);
  976. TRACE(ft_t_noise, "to_do: %d", remaining);
  977. }
  978. if (seg_sz - c_info->offset <= 18) {
  979. c_info->offset = seg_sz;
  980. }
  981. TRACE(ft_t_noise, "n"
  982.       KERN_INFO "segment size   : %dn"
  983.       KERN_INFO "buf_pos_read   : %dn"
  984.       KERN_INFO "remaining      : %d",
  985.       seg_sz, c_info->offset,
  986.       seg_sz - c_info->offset);
  987. TRACE_EXIT result;
  988. }                
  989. static int slow_seek_forward_until_error(const unsigned int distance,
  990.  cmpr_info *c_info,
  991.  zft_position *pos, 
  992.  const zft_volinfo *volume,
  993.  __u8 *buf)
  994. {
  995. unsigned int remaining = distance;
  996. int seg_sz;
  997. int seg_pos;
  998. int result;
  999. TRACE_FUN(ft_t_flow);
  1000. seg_pos = pos->seg_pos;
  1001. do {
  1002. TRACE_CATCH(seg_sz = zft_fetch_segment(seg_pos, buf, 
  1003.        FT_RD_AHEAD),);
  1004. /* now we have the contents of the actual segment in
  1005.  * the deblock buffer
  1006.  */
  1007. TRACE_CATCH(result = seek_in_segment(remaining, c_info, buf,
  1008.      seg_sz, seg_pos,volume),);
  1009. remaining        -= result;
  1010. pos->volume_pos  += result<<10;
  1011. pos->seg_pos      = seg_pos;
  1012. pos->seg_byte_pos = c_info->offset;
  1013. seg_pos ++;
  1014. if (seg_pos <= volume->end_seg && c_info->offset == seg_sz) {
  1015. pos->seg_pos ++;
  1016. pos->seg_byte_pos = 0;
  1017. c_info->offset = 0;
  1018. }
  1019. /*  Allow escape from this loop on signal!
  1020.  */
  1021. FT_SIGNAL_EXIT(_DONT_BLOCK);
  1022. TRACE(ft_t_noise, "n"
  1023.       KERN_INFO "remaining:  %dn"
  1024.       KERN_INFO "seg_pos:    %dn"
  1025.       KERN_INFO "end_seg:    %dn"
  1026.       KERN_INFO "result:     %d",
  1027.       remaining, seg_pos, volume->end_seg, result);  
  1028. } while (remaining > 0 && seg_pos <= volume->end_seg);
  1029. TRACE_EXIT 0;
  1030. }
  1031. /* return segment id of next segment containing valid data, -EIO otherwise
  1032.  */
  1033. static int search_valid_segment(unsigned int segment,
  1034. const unsigned int end_seg,
  1035. const unsigned int max_foffs,
  1036. zft_position *pos,
  1037. cmpr_info *c_info,
  1038. const zft_volinfo *volume,
  1039. __u8 *buf)
  1040. {
  1041. cmpr_info tmp_info;
  1042. int seg_sz;
  1043. TRACE_FUN(ft_t_flow);
  1044. memset(&tmp_info, 0, sizeof(cmpr_info));
  1045. while (segment <= end_seg) {
  1046. FT_SIGNAL_EXIT(_DONT_BLOCK);
  1047. TRACE(ft_t_noise,
  1048.       "Searching readable segment between %d and %d",
  1049.       segment, end_seg);
  1050. seg_sz = zft_fetch_segment(segment, buf, FT_RD_AHEAD);
  1051. if ((seg_sz > 0) &&
  1052.     (get_cseg (&tmp_info, buf, seg_sz, volume) >= 0) &&
  1053.     (tmp_info.foffs != 0 || segment == volume->start_seg)) {
  1054. if ((tmp_info.foffs>>10) > max_foffs) {
  1055. TRACE_ABORT(-EIO, ft_t_noise, "n"
  1056.     KERN_INFO "cseg.foff: %dn"
  1057.     KERN_INFO "dest     : %d",
  1058.     (int)(tmp_info.foffs >> 10),
  1059.     max_foffs);
  1060. }
  1061. DUMP_CMPR_INFO(ft_t_noise, "", &tmp_info);
  1062. *c_info           = tmp_info;
  1063. pos->seg_pos      = segment;
  1064. pos->volume_pos   = c_info->foffs;
  1065. pos->seg_byte_pos = c_info->offset;
  1066. TRACE(ft_t_noise, "found segment at %d", segment);
  1067. TRACE_EXIT 0;
  1068. }
  1069. segment++;
  1070. }
  1071. TRACE_EXIT -EIO;
  1072. }
  1073. static int slow_seek_forward(unsigned int dest,
  1074.      cmpr_info *c_info,
  1075.      zft_position *pos,
  1076.      const zft_volinfo *volume,
  1077.      __u8 *buf)
  1078. {
  1079. unsigned int distance;
  1080. int result = 0;
  1081. TRACE_FUN(ft_t_flow);
  1082. distance = dest - (pos->volume_pos >> 10);
  1083. while ((distance > 0) &&
  1084.        (result = slow_seek_forward_until_error(distance,
  1085.        c_info,
  1086.        pos,
  1087.        volume,
  1088.        buf)) < 0) {
  1089. if (result == -EINTR) {
  1090. break;
  1091. }
  1092. TRACE(ft_t_noise, "seg_pos: %d", pos->seg_pos);
  1093. /* the failing segment is either pos->seg_pos or
  1094.  * pos->seg_pos + 1. There is no need to further try
  1095.  * that segment, because ftape_read_segment() already
  1096.  * has tried very much to read it. So we start with
  1097.  * following segment, which is pos->seg_pos + 1
  1098.  */
  1099. if(search_valid_segment(pos->seg_pos+1, volume->end_seg, dest,
  1100. pos, c_info,
  1101. volume, buf) < 0) {
  1102. TRACE(ft_t_noise, "search_valid_segment() failed");
  1103. result = -EIO;
  1104. break;
  1105. }
  1106. distance = dest - (pos->volume_pos >> 10);
  1107. result = 0;
  1108. TRACE(ft_t_noise, "segment: %d", pos->seg_pos);
  1109. /* found valid segment, retry the seek */
  1110. }
  1111. TRACE_EXIT result;
  1112. }
  1113. static int compute_seg_pos(const unsigned int dest,
  1114.    zft_position *pos,
  1115.    const zft_volinfo *volume)
  1116. {
  1117. int segment;
  1118. int distance = dest - (pos->volume_pos >> 10);
  1119. unsigned int raw_size;
  1120. unsigned int virt_size;
  1121. unsigned int factor;
  1122. TRACE_FUN(ft_t_flow);
  1123. if (distance >= 0) {
  1124. raw_size  = volume->end_seg - pos->seg_pos + 1;
  1125. virt_size = ((unsigned int)(volume->size>>10) 
  1126.      - (unsigned int)(pos->volume_pos>>10)
  1127.      + FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS - 1);
  1128. virt_size /= FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS;
  1129. if (virt_size == 0 || raw_size == 0) {
  1130. TRACE_EXIT 0;
  1131. }
  1132. if (raw_size >= (1<<25)) {
  1133. factor = raw_size/(virt_size>>7);
  1134. } else {
  1135. factor = (raw_size<<7)/virt_size;
  1136. }
  1137. segment = distance/(FT_SECTORS_PER_SEGMENT-FT_ECC_SECTORS);
  1138. segment = (segment * factor)>>7;
  1139. } else {
  1140. raw_size  = pos->seg_pos - volume->start_seg + 1;
  1141. virt_size = ((unsigned int)(pos->volume_pos>>10)
  1142.      + FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS - 1);
  1143. virt_size /= FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS;
  1144. if (virt_size == 0 || raw_size == 0) {
  1145. TRACE_EXIT 0;
  1146. }
  1147. if (raw_size >= (1<<25)) {
  1148. factor = raw_size/(virt_size>>7);
  1149. } else {
  1150. factor = (raw_size<<7)/virt_size;
  1151. }
  1152. segment = distance/(FT_SECTORS_PER_SEGMENT-FT_ECC_SECTORS);
  1153. }
  1154. TRACE(ft_t_noise, "factor: %d/%d", factor, 1<<7);
  1155. TRACE_EXIT segment;
  1156. }
  1157. static struct zft_cmpr_ops cmpr_ops = {
  1158. zftc_write,
  1159. zftc_read,
  1160. zftc_seek,
  1161. zftc_lock,
  1162. zftc_reset,
  1163. zftc_cleanup
  1164. };
  1165. int zft_compressor_init(void)
  1166. {
  1167. TRACE_FUN(ft_t_flow);
  1168. #ifdef MODULE
  1169. printk(KERN_INFO "zftape compressor v1.00a 970514 for " FTAPE_VERSION "n");
  1170.         if (TRACE_LEVEL >= ft_t_info) {
  1171. printk(
  1172. KERN_INFO "(c) 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)n"
  1173. KERN_INFO "Compressor for zftape (lzrw3 algorithm)n"
  1174. KERN_INFO "Compiled for kernel version %s"
  1175. #ifdef MODVERSIONS
  1176. " with versioned symbols"
  1177. #endif
  1178. "n", UTS_RELEASE);
  1179.         }
  1180. #else /* !MODULE */
  1181. /* print a short no-nonsense boot message */
  1182. printk("zftape compressor v1.00a 970514 for Linux " UTS_RELEASE "n");
  1183. printk("For use with " FTAPE_VERSION "n");
  1184. #endif /* MODULE */
  1185. TRACE(ft_t_info, "zft_compressor_init @ 0x%p", zft_compressor_init);
  1186. TRACE(ft_t_info, "installing compressor for zftape ...");
  1187. TRACE_CATCH(zft_cmpr_register(&cmpr_ops),);
  1188. TRACE_EXIT 0;
  1189. }
  1190. #ifdef MODULE
  1191. MODULE_AUTHOR(
  1192. "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de");
  1193. MODULE_DESCRIPTION(
  1194. "Compression routines for zftape. Uses the lzrw3 algorithm by Ross Williams");
  1195. MODULE_LICENSE("GPL");
  1196. #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,18)
  1197. static int can_unload(void)
  1198. {
  1199. return keep_module_locked ? -EBUSY : 0;
  1200. }
  1201. #endif
  1202. /* Called by modules package when installing the driver
  1203.  */
  1204. int init_module(void)
  1205. {
  1206. int result;
  1207. #if LINUX_VERSION_CODE < KERNEL_VER(2,1,18)
  1208. register_symtab(0); /* remove global ftape symbols */
  1209. #else
  1210. if (!mod_member_present(&__this_module, can_unload))
  1211. return -EBUSY;
  1212. __this_module.can_unload = can_unload;
  1213. EXPORT_NO_SYMBOLS;
  1214. #endif
  1215. result = zft_compressor_init();
  1216. keep_module_locked = 0;
  1217. return result;
  1218. }
  1219. /* Called by modules package when removing the driver 
  1220.  */
  1221. void cleanup_module(void)
  1222. {
  1223. TRACE_FUN(ft_t_flow);
  1224. if (zft_cmpr_unregister() != &cmpr_ops) {
  1225. TRACE(ft_t_info, "failed");
  1226. } else {
  1227. TRACE(ft_t_info, "successful");
  1228. }
  1229. zftc_cleanup();
  1230.         printk(KERN_INFO "zft-compressor successfully unloaded.n");
  1231. TRACE_EXIT;
  1232. }
  1233. #endif /* MODULE */