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: