[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Need help with patch for broken IDE-tape driver



Hello all,

After upgrading from Potato to Woody (kernel version 2.4.18), I have had 
problems making backups to my CONNER CTT8000-A (IDE-tape drive; Travan TR-4 
compatible). During verify and restore operations I get an error message 
"Unexpected EOF in archive".

I found a note in the kernel TODO list that the ide-tape driver was broken.
(See: http://linux24.sourceforge.net/ 9. To Do). But my analysis of the 
problem is not quite covered by the description.

The problem occurs when I do 'tar cvf /dev/ht0 --verify *'.
I found the problem does not occur when the verify option is omitted. The 
error is fairly easy to reproduce by executing the command above from a 
fairly small directory (I tested with 25kB worth of data).

I did some debugging by 'echo "debug_level:4" >/proc/ide/hdc/settings' and 
compared the two situations.

The cause problem seems to be as follows.
When you do tar without verify the function idetape_chrdev_release is called 
after the data is written to tape, which calls idetape_write_release, which 
writes a filemark and EOD.
When you do tar with verify idetape_chrdev_release is not called, but after 
writing the backup a IOCTL command is executed (function 
idetape_chrdev_ioctl) to space back the tape for the verification of the 
backup. Before the IOCTL command is executed, the write-buffer is emptied, 
but no filemark or EOD are written (as I think they should be).

I have attached a patch that solves the problem, but as I am not a 
C-programmer and a complete newbie in kernel programming and ide-drivers, I 
would appreciate your help in verifying my patch and getting the patch 
upstream.
(I also did some small other corrections.)

The patch makes sure that when a switch is made from writing to performing a 
IOCTL command, a filemark and EOD are written. After that the tape is 
repositioned before the filemark because otherwise the verify is not 
performed.

I have the following questions.
- Is my thinking correct?
- Is the patch likely to break the driver in other situations?
- Should I also write a new header (as in function idetape_write_release)?
- I am not completely happy with having to reposition before the filemark; I 
think this could cause problems in other situations; any thoughts?
- Should the same correction be included in the function 
idetape_initialize_read?

Thanks,

Frans Pop

Note: please CC any responses to my address as I am not on the list.
*** ide-tape.c.sv	Fri Jan 10 09:35:47 2003
--- ide-tape.c	Sat Jan 11 18:04:48 2003
***************
*** 2104,2108 ****
  #if IDETAPE_DEBUG_LOG
  			if (tape->debug_level >= 1)
! 				printk (KERN_INFO "ide-tape: %s: I/O error, ",tape->name);
  #endif /* IDETAPE_DEBUG_LOG */
  			if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
--- 2104,2108 ----
  #if IDETAPE_DEBUG_LOG
  			if (tape->debug_level >= 1)
! 				printk (KERN_INFO "ide-tape: %s: I/O error, \n",tape->name);
  #endif /* IDETAPE_DEBUG_LOG */
  			if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
***************
*** 3097,3104 ****
  	idetape_read_position_result_t *result;
  	
! //#if IDETAPE_DEBUG_LOG
! //	if (tape->debug_level >= 4)
  		printk (KERN_INFO "ide-tape: Reached idetape_read_position_callback\n");
! //#endif /* IDETAPE_DEBUG_LOG */
  
  	if (!tape->pc->error) {
--- 3097,3104 ----
  	idetape_read_position_result_t *result;
  	
! #if IDETAPE_DEBUG_LOG
! 	if (tape->debug_level >= 4)
  		printk (KERN_INFO "ide-tape: Reached idetape_read_position_callback\n");
! #endif /* IDETAPE_DEBUG_LOG */
  
  	if (!tape->pc->error) {
***************
*** 3274,3281 ****
  	int position;
  
! //#if IDETAPE_DEBUG_LOG
! //        if (tape->debug_level >= 4)
  	printk (KERN_INFO "ide-tape: Reached idetape_read_position\n");
! //#endif /* IDETAPE_DEBUG_LOG */
  
  #ifdef NO_LONGER_REQUIRED
--- 3274,3281 ----
  	int position;
  
! #if IDETAPE_DEBUG_LOG
!         if (tape->debug_level >= 4)
  	printk (KERN_INFO "ide-tape: Reached idetape_read_position\n");
! #endif /* IDETAPE_DEBUG_LOG */
  
  #ifdef NO_LONGER_REQUIRED
***************
*** 5242,5246 ****
  	struct mtget mtget;
  	struct mtpos mtpos;
! 	int block_offset = 0, position = tape->first_frame_position;
  
  #if IDETAPE_DEBUG_LOG
--- 5242,5246 ----
  	struct mtget mtget;
  	struct mtpos mtpos;
! 	int block_offset = 0, position = tape->first_frame_position, write_end_position;
  
  #if IDETAPE_DEBUG_LOG
***************
*** 5252,5255 ****
--- 5252,5267 ----
  	if (tape->chrdev_direction == idetape_direction_write) {
  		idetape_empty_write_pipeline (drive);
+ 		/* FJP filemark and EOD missing after backup is completed */
+ 		write_end_position = idetape_read_position(drive);
+ 		tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0);
+ 		if (tape->merge_stage != NULL) {
+ 			idetape_pad_zeros (drive, tape->tape_block_size * (tape->user_bs_factor - 1));
+ 			__idetape_kfree_stage (tape->merge_stage);
+ 			tape->merge_stage = NULL;
+ 		}
+ 		idetape_write_filemark (drive);
+ 		idetape_write_eod (drive);
+ 		idetape_position_tape(drive, write_end_position, 0, 0);
+ 		/* FJP end */
  		idetape_flush_tape_buffers (drive);
  	}

Reply to: