From cf6d7d728ac241a86939d1dcb89ad62ce9d8ce5d Mon Sep 17 00:00:00 2001 From: Tim Wright Date: Tue, 5 Aug 2008 00:30:07 +0000 Subject: [PATCH] SCSI: block: Fix miscalculation of sg_io timeout in CDROM_SEND_PACKET handler. commit ad337591f4fd20de6a0ca03d6715267a5c1d2b16 upstream It seems cdrwtool in the udftools has been unusable on "modern" kernels for some time. A Google search reveals many people with the same issue but no solution (cdrwtool fails to format the disk). After spending some time tracking down the issue, it comes down to the following: The udftools still use the older CDROM_SEND_PACKET interface to send things like FORMAT_UNIT through to the drive. They should really be updated, but that's another story. Since most distros are using libata now, the cd or dvd burner appears as a SCSI device, and we wind up in block/scsi_ioctl.c. Here, the code tries to take the "struct cdrom_generic_command" and translate it and stuff it into a "struct sg_io_hdr" structure so it can pass it to the modern sg_io() routine instead. Unfortunately, there is one error, or rather an omission in the translation. The timeout that is passed in in the "struct cdrom_generic_command" is in HZ=100 units, and this is modified and correctly converted to jiffies by use of clock_t_to_jiffies(). However, a little further down, this cgc.timeout value in jiffies is simply copied into the sg_io_hdr timeout, which should be in milliseconds. Since most modern x86 kernels seems to be getting build with HZ=250, the timeout that is passed to sg_io and eventually converted to the timeout_per_command member of the scsi_cmnd structure is now four times too small. Since cdrwtool tries to set the timeout to one hour for the FORMAT_UNIT command, and it takes about 20 minutes to format a 4x CDRW, the SCSI error-handler kicks in after the FORMAT_UNIT completes because it took longer than the incorrectly-calculated timeout. [jejb: fix up whitespace] Signed-off-by: Tim Wright Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- block/scsi_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index a2c3a936ebf9..84d8341f5e01 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -633,7 +633,7 @@ int scsi_cmd_ioctl(struct file *file, struct request_queue *q, hdr.sbp = cgc.sense; if (hdr.sbp) hdr.mx_sb_len = sizeof(struct request_sense); - hdr.timeout = cgc.timeout; + hdr.timeout = jiffies_to_msecs(cgc.timeout); hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd; hdr.cmd_len = sizeof(cgc.cmd); -- 2.39.5