⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zftape-compress.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	TRACE_EXIT (unsigned int)max_out_sz;}/* print some statistics about the efficiency of the compression to * the kernel log  */static void zftc_stats(void){	TRACE_FUN(ft_t_flow);	if (TRACE_LEVEL < ft_t_info) {		TRACE_EXIT;	}	if (zftc_wr_uncompressed != 0) {		if (zftc_wr_compressed > (1<<14)) {			TRACE(ft_t_info, "compression statistics (writing):\n"			      KERN_INFO " compr./uncmpr.   : %3d %%",			      (((zftc_wr_compressed>>10) * 100)			       / (zftc_wr_uncompressed>>10)));		} else {			TRACE(ft_t_info, "compression statistics (writing):\n"			      KERN_INFO " compr./uncmpr.   : %3d %%",			      ((zftc_wr_compressed * 100)			       / zftc_wr_uncompressed));		}	}	if (zftc_rd_uncompressed != 0) {		if (zftc_rd_compressed > (1<<14)) {			TRACE(ft_t_info, "compression statistics (reading):\n"			      KERN_INFO " compr./uncmpr.   : %3d %%",			      (((zftc_rd_compressed>>10) * 100)			       / (zftc_rd_uncompressed>>10)));		} else {			TRACE(ft_t_info, "compression statistics (reading):\n"			      KERN_INFO " compr./uncmpr.   : %3d %%",			      ((zftc_rd_compressed * 100)			       / zftc_rd_uncompressed));		}	}	/* only print it once: */	zftc_wr_uncompressed = 		zftc_wr_compressed  =		zftc_rd_uncompressed =		zftc_rd_compressed   = 0;	TRACE_EXIT;}/* start new compressed block  */static int start_new_cseg(cmpr_info *cluster, 			  char *dst_buf, 			  const zft_position *pos,			  const unsigned int blk_sz,			  const char *src_buf,			  const int this_segs_sz,			  const int qic113){	int size_left;	int cp_cnt;	int buf_pos;	TRACE_FUN(ft_t_flow);	size_left = this_segs_sz - sizeof(__u16) - cluster->cmpr_sz;	TRACE(ft_t_data_flow,"\n" 	      KERN_INFO "segment size   : %d\n"	      KERN_INFO "compressed_sz: %d\n"	      KERN_INFO "size_left      : %d",	      this_segs_sz, cluster->cmpr_sz, size_left);	if (size_left > 18) { /* start a new cluseter */		cp_cnt = cluster->cmpr_sz;		cluster->cmpr_sz = 0;		buf_pos = cp_cnt + sizeof(__u16);		PUT2(dst_buf, 0, buf_pos);		if (qic113) {			__s64 foffs = pos->volume_pos;			if (cp_cnt) foffs += (__s64)blk_sz;			TRACE(ft_t_data_flow, "new style QIC-113 header");			PUT8(dst_buf, buf_pos, foffs);			buf_pos += sizeof(__s64);		} else {			__u32 foffs = (__u32)pos->volume_pos;			if (cp_cnt) foffs += (__u32)blk_sz;						TRACE(ft_t_data_flow, "old style QIC-80MC header");			PUT4(dst_buf, buf_pos, foffs);			buf_pos += sizeof(__u32);		}	} else if (size_left >= 0) {		cp_cnt = cluster->cmpr_sz;		cluster->cmpr_sz = 0;		buf_pos = cp_cnt + sizeof(__u16);		PUT2(dst_buf, 0, buf_pos);  		/* zero unused part of segment. */		memset(dst_buf + buf_pos, '\0', size_left);		buf_pos = this_segs_sz;	} else { /* need entire segment and more space */		PUT2(dst_buf, 0, 0); 		cp_cnt = this_segs_sz - sizeof(__u16);		cluster->cmpr_sz  -= cp_cnt;		buf_pos = this_segs_sz;	}	memcpy(dst_buf + sizeof(__u16), src_buf + cluster->cmpr_pos, cp_cnt);	cluster->cmpr_pos += cp_cnt;	TRACE_EXIT buf_pos;}/* return-value: the number of bytes removed from the user-buffer *               `src_buf' or error code * *  int *write_cnt           : how much actually has been moved to the *                             dst_buf. Need not be initialized when *                             function returns with an error code *                             (negativ return value)  *  __u8 *dst_buf            : kernel space buffer where the has to be *                             copied to. The contents of this buffers *                             goes to a specific segment. *  const int seg_sz         : the size of the segment dst_buf will be *                             copied to. *  const zft_position *pos  : struct containing the coordinates in *                             the current volume (byte position, *                             segment id of current segment etc) *  const zft_volinfo *volume: information about the current volume, *                             size etc. *  const __u8 *src_buf      : user space buffer that contains the *                             data the user wants to be written to *                             tape. *  const int req_len        : the amount of data the user wants to be *                             written to tape. */static int zftc_write(int *write_cnt,		      __u8 *dst_buf, const int seg_sz,		      const __u8 __user *src_buf, const int req_len,		      const zft_position *pos, const zft_volinfo *volume){	int req_len_left = req_len;	int result;	int len_left;	int buf_pos_write = pos->seg_byte_pos;	TRACE_FUN(ft_t_flow);		/* Note: we do not unlock the module because	 * there are some values cached in that `cseg' variable.  We	 * don't don't want to use this information when being	 * unloaded by kerneld even when the tape is full or when we	 * cannot allocate enough memory.	 */	if (pos->tape_pos > (volume->size-volume->blk_sz-ZFT_CMPR_OVERHEAD)) {		TRACE_EXIT -ENOSPC;	}    	if (zft_allocate_cmpr_mem(volume->blk_sz) < 0) {		/* should we unlock the module? But it shouldn't 		 * be locked anyway ...		 */		TRACE_EXIT -ENOMEM;	}	if (buf_pos_write == 0) { /* fill a new segment */		*write_cnt = buf_pos_write = start_new_cseg(&cseg,							    dst_buf,							    pos,							    volume->blk_sz,							    zftc_buf, 							    seg_sz,							    volume->qic113);		if (cseg.cmpr_sz == 0 && cseg.cmpr_pos != 0) {			req_len_left -= result = volume->blk_sz;			cseg.cmpr_pos  = 0;		} else {			result = 0;		}	} else {		*write_cnt = result = 0;	}		len_left = seg_sz - buf_pos_write;	while ((req_len_left > 0) && (len_left > 18)) {		/* now we have some size left for a new compressed		 * block.  We know, that the compression buffer is		 * empty (else there wouldn't be any space left).  		 */		if (copy_from_user(zftc_scratch_buf, src_buf + result, 				   volume->blk_sz) != 0) {			TRACE_EXIT -EFAULT;		}		req_len_left -= volume->blk_sz;		cseg.cmpr_sz = zft_compress(zftc_scratch_buf, volume->blk_sz, 					    zftc_buf);		if (cseg.cmpr_sz < 0) {			cseg.uncmpr = 0x8000;			cseg.cmpr_sz = -cseg.cmpr_sz;		} else {			cseg.uncmpr = 0;		}		/* increment "result" iff we copied the entire		 * compressed block to the zft_deblock_buf 		 */		len_left -= sizeof(__u16);		if (len_left >= cseg.cmpr_sz) {			len_left -= cseg.count = cseg.cmpr_sz;			cseg.cmpr_pos = cseg.cmpr_sz = 0;			result += volume->blk_sz;		} else {			cseg.cmpr_sz       -= 				cseg.cmpr_pos =				cseg.count    = len_left;			len_left = 0;		}		PUT2(dst_buf, buf_pos_write, cseg.uncmpr | cseg.count);		buf_pos_write += sizeof(__u16);		memcpy(dst_buf + buf_pos_write, zftc_buf, cseg.count);		buf_pos_write += cseg.count;		*write_cnt    += cseg.count + sizeof(__u16);		FT_SIGNAL_EXIT(_DONT_BLOCK);	}	/* erase the remainder of the segment if less than 18 bytes	 * left (18 bytes is due to the QIC-80 standard) 	 */	if (len_left <= 18) {		memset(dst_buf + buf_pos_write, '\0', len_left);		(*write_cnt) += len_left;	}	TRACE(ft_t_data_flow, "returning %d", result);	TRACE_EXIT result;}   /* out: * * int *read_cnt: the number of bytes we removed from the zft_deblock_buf *                (result) * int *to_do   : the remaining size of the read-request. * * in: * * char *buff          : buff is the address of the upper part of the user *                       buffer, that hasn't been filled with data yet. * int buf_pos_read    : copy of from _ftape_read() * int buf_len_read    : copy of buf_len_rd from _ftape_read() * char *zft_deblock_buf: zft_deblock_buf * unsigned short blk_sz: the block size valid for this volume, may differ *                            from zft_blk_sz. * int finish: if != 0 means that this is the last segment belonging *  to this volume * returns the amount of data actually copied to the user-buffer * * to_do MUST NOT SHRINK except to indicate an EOF. In this case *to_do has to * be set to 0  */static int zftc_read (int *read_cnt, 		      __u8  __user *dst_buf, const int to_do, 		      const __u8 *src_buf, const int seg_sz, 		      const zft_position *pos, const zft_volinfo *volume){          	int uncompressed_sz;         	int result = 0;	int remaining = to_do;	TRACE_FUN(ft_t_flow);	TRACE_CATCH(zft_allocate_cmpr_mem(volume->blk_sz),);	if (pos->seg_byte_pos == 0) {		/* new segment just read		 */		TRACE_CATCH(get_cseg(&cseg, src_buf, seg_sz, volume),			    *read_cnt = 0);		memcpy(zftc_buf + cseg.cmpr_pos, src_buf + sizeof(__u16), 		       cseg.count);		cseg.cmpr_pos += cseg.count;		*read_cnt      = cseg.offset;		DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */, "", &cseg);	} else {		*read_cnt = 0;	}	/* loop and uncompress until user buffer full or	 * deblock-buffer empty 	 */	TRACE(ft_t_data_flow, "compressed_sz: %d, compos : %d, *read_cnt: %d",	      cseg.cmpr_sz, cseg.cmpr_pos, *read_cnt);	while ((cseg.spans == 0) && (remaining > 0)) {		if (cseg.cmpr_pos  != 0) { /* cmpr buf is not empty */			uncompressed_sz = 				zft_uncompress(zftc_buf,					       cseg.uncmpr == 0x8000 ?					       -cseg.cmpr_pos : cseg.cmpr_pos,					       zftc_scratch_buf,					       volume->blk_sz);			if (uncompressed_sz != volume->blk_sz) {				*read_cnt = 0;				TRACE_ABORT(-EIO, ft_t_warn,				      "Uncompressed blk (%d) != blk size (%d)",				      uncompressed_sz, volume->blk_sz);			}       			if (copy_to_user(dst_buf + result, 					 zftc_scratch_buf, 					 uncompressed_sz) != 0 ) {				TRACE_EXIT -EFAULT;			}			remaining      -= uncompressed_sz;			result     += uncompressed_sz;			cseg.cmpr_pos  = 0;		}                                              		if (remaining > 0) {			get_next_cluster(&cseg, src_buf, seg_sz, 					 volume->end_seg == pos->seg_pos);			if (cseg.count != 0) {				memcpy(zftc_buf, src_buf + cseg.offset,				       cseg.count);				cseg.cmpr_pos = cseg.count;				cseg.offset  += cseg.count;				*read_cnt += cseg.count + sizeof(__u16);			} else {				remaining = 0;			}		}		TRACE(ft_t_data_flow, "\n" 		      KERN_INFO "compressed_sz: %d\n"		      KERN_INFO "compos       : %d\n"		      KERN_INFO "*read_cnt    : %d",		      cseg.cmpr_sz, cseg.cmpr_pos, *read_cnt);	}	if (seg_sz - cseg.offset <= 18) {		*read_cnt += seg_sz - cseg.offset;		TRACE(ft_t_data_flow, "expanding read cnt to: %d", *read_cnt);	}	TRACE(ft_t_data_flow, "\n"	      KERN_INFO "segment size   : %d\n"	      KERN_INFO "read count     : %d\n"	      KERN_INFO "buf_pos_read   : %d\n"	      KERN_INFO "remaining      : %d",		seg_sz, *read_cnt, pos->seg_byte_pos, 		seg_sz - *read_cnt - pos->seg_byte_pos);	TRACE(ft_t_data_flow, "returning: %d", result);	TRACE_EXIT result;}                /* seeks to the new data-position. Reads sometimes a segment. *   * start_seg and end_seg give the boundaries of the current volume * blk_sz is the blk_sz of the current volume as stored in the * volume label * * We don't allow blocksizes less than 1024 bytes, therefore we don't need * a 64 bit argument for new_block_pos. */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);static int slow_seek_forward_until_error(const unsigned int distance,					 cmpr_info *c_info, zft_position *pos, 					 const zft_volinfo *volume, __u8 *buf);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);static int slow_seek_forward(unsigned int dest, cmpr_info *c_info,			     zft_position *pos, const zft_volinfo *volume,			     __u8 *buf);static int compute_seg_pos(unsigned int dest, zft_position *pos,			   const zft_volinfo *volume);#define ZFT_SLOW_SEEK_THRESHOLD  10 /* segments */#define ZFT_FAST_SEEK_MAX_TRIALS 10 /* times */#define ZFT_FAST_SEEK_BACKUP     10 /* segments */static int zftc_seek(unsigned int new_block_pos,		     zft_position *pos, const zft_volinfo *volume, __u8 *buf){	unsigned int dest;	int limit;	int distance;	int result = 0;	int seg_dist;	int new_seg;	int old_seg = 0;	int fast_seek_trials = 0;	TRACE_FUN(ft_t_flow);	if (new_block_pos == 0) {		pos->seg_pos      = volume->start_seg;		pos->seg_byte_pos = 0;		pos->volume_pos   = 0;		zftc_reset();		TRACE_EXIT 0;	}	dest = new_block_pos * (volume->blk_sz >> 10);	distance = dest - (pos->volume_pos >> 10);	while (distance != 0) {		seg_dist = compute_seg_pos(dest, pos, volume);		TRACE(ft_t_noise, "\n"		      KERN_INFO "seg_dist: %d\n"		      KERN_INFO "distance: %d\n"		      KERN_INFO "dest    : %d\n"		      KERN_INFO "vpos    : %d\n"		      KERN_INFO "seg_pos : %d\n"		      KERN_INFO "trials  : %d",		      seg_dist, distance, dest,		      (unsigned int)(pos->volume_pos>>10), pos->seg_pos,		      fast_seek_trials);		if (distance > 0) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -