Skip to contentSkip to conversation

PROBLEM: 2.6.3 hangs when writing to scsi-dvd

DISCUSSION Joachim Feise 5 participants 10 messages Feb 19, 2004 – Feb 24, 2004

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

[1.] One line summary of the problem:
2.6.3 hangs when writing to scsi-dvd

[2.] Full description of the problem/report:

I have a DVD drive (BTC1004) connected via an IDE-SCSI bridge to an Adaptec 29160 host adapter.
With kernel 2.6.3, I experience a complete system hang whenever I try to record data on a DVD.
It requires a reboot.

[3.] Keywords (i.e., modules, networking, kernel):
SCSI

[4.] Kernel version (from /proc/version):
Linux version 2.6.3 (root@pv105234) (gcc version 3.2.2) #1 Wed Feb 18 04:26:46 PST 2004

[5.] Output of Oops.. message (if applicable) with symbolic information
resolved (see Documentation/oops-tracing.txt)
None.

[6.] A small shell script or example program which triggers the
problem (if possible)
growisofs -Z /dev/sr1 -R -J tmpdir/files
Where /dev/sr1 is the DVD device

[7.] Environment
[7.1.] Software (add the output of the ver_linux script here) Linux pv105234 2.6.3 #1 Wed Feb 18 04:26:46 PST 2004 i686 unknown

Gnu C                  3.2.2
Gnu make               3.80
util-linux             2.11z
mount                  2.11z
module-init-tools      0.9.13
e2fsprogs              1.32
jfsutils               1.1.1
reiserfsprogs          3.6.4
xfsprogs               2.3.5
pcmcia-cs              3.2.4
quota-tools            3.08.
PPP                    2.4.2
nfs-utils              1.0.1
Linux C Library        2.3.1
Dynamic linker (ldd)   2.3.1
Linux C++ Library      5.0.2
Procps                 3.1.6
Net-tools              1.60
Kbd                    1.08
Sh-utils               2.0
Modules Loaded         snd_seq_midi snd_seq_oss snd_seq_midi_event snd_seq snd_pcm_oss snd_mixer_oss

softdog ipv6 ohci_hcd ehci_hcd snd_cs46xx snd_rawmidi snd_seq_device snd_ac97_codec snd_pcm snd_timer snd soundcore gameport snd_page_alloc i2c_core ide_scsi ppp_mppe ppp_deflate ppp_generic slhc usb_storage

[7.2.] Processor information (from /proc/cpuinfo):
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 6
model name : Celeron (Mendocino)
stepping : 0
cpu MHz : 334.143
cache size : 128 KB
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 2
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 mmx fxsr
bogomips : 659.45

[7.3.] Module information (from /proc/modules):
snd_seq_midi 8384 0 - Live 0xd3d83000
snd_seq_oss 35104 0 - Live 0xd3dea000
snd_seq_midi_event 7744 2 snd_seq_midi,snd_seq_oss, Live 0xd3cec000
snd_seq 56592 5 snd_seq_midi,snd_seq_oss,snd_seq_midi_event, Live 0xd3dbe000
snd_pcm_oss 54564 1 - Live 0xd3dcf000
snd_mixer_oss 20096 2 snd_pcm_oss, Live 0xd3d7d000
softdog 4808 1 - Live 0xd3d35000
ipv6 258272 14 - Live 0xd3e08000
ohci_hcd 19328 0 - Live 0xd3d3c000
ehci_hcd 25888 0 - Live 0xd3d6e000
snd_cs46xx 90956 2 - Live 0xd3d88000
snd_rawmidi 25216 2 snd_seq_midi,snd_cs46xx, Live 0xd3d25000
snd_seq_device 8068 4 snd_seq_midi,snd_seq_oss,snd_seq,snd_rawmidi, Live 0xd3ce6000
snd_ac97_codec 63588 1 snd_cs46xx, Live 0xd3d5d000
snd_pcm 101856 2 snd_pcm_oss,snd_cs46xx, Live 0xd3d43000
snd_timer 26272 2 snd_seq,snd_pcm, Live 0xd3d0d000
snd 55492 12 snd_seq_midi,snd_seq_oss,snd_seq_midi_event,snd_seq,snd_pcm_oss,snd_mixer_oss,snd_cs46xx,snd_rawmidi,snd_seq_device,snd_ac97_codec,snd_pcm,snd_timer, Live 0xd3d16000
soundcore 10176 3 snd, Live 0xd3d00000
gameport 4736 1 snd_cs46xx, Live 0xd3ce9000
snd_page_alloc 12228 2 snd_cs46xx,snd_pcm, Live 0xd3cf7000
i2c_core 23488 0 - Live 0xd3cdf000
ide_scsi 15268 0 - Live 0xd3cda000
ppp_mppe 14304 0 - Live 0xd3cd5000
ppp_deflate 6144 0 - Live 0xd3cc1000
ppp_generic 31528 2 ppp_mppe,ppp_deflate, Live 0xd3ccc000
slhc 7296 1 ppp_generic, Live 0xd3cbe000
usb_storage 68064 0 - Live 0xd3b56000

[7.4.] Loaded driver and hardware information (/proc/ioports, /proc/iomem) cat /proc/ioports
00000000-0009fbff : System RAM
0009fc00-0009ffff : reserved
000a0000-000bffff : Video RAM area
000cb000-000d3fff : Extension ROM
000f0000-000fffff : System ROM
00100000-11ffffff : System RAM
00100000-003c88f2 : Kernel code
003c88f3-004db8ff : Kernel data
c056f000-c096f000 : Bigphysarea
c7900000-cf9fffff : PCI Bus #01
c8000000-cbffffff : 0000:01:00.0

    c8000000-c8ffffff : vesafb

d0000000-d3ffffff : 0000:00:00.0
d7b00000-efcfffff : PCI Bus #01
e0000000-e3ffffff : 0000:01:00.0
e4000000-e7ffffff : 0000:01:00.0
e8000000-ebffffff : 0000:01:00.0
efc80000-efcfffff : 0000:01:00.0
efe00000-efefffff : 0000:00:09.0
efe00000-efe02fff : CS46xx_BA1_data0
efe10000-efe137ff : CS46xx_BA1_data1
efe20000-efe26fff : CS46xx_BA1_pmem
efe30000-efe300ff : CS46xx_BA1_reg
efffc000-efffcfff : 0000:00:09.0
efffc000-efffcfff : CS46xx_BA0
efffee00-efffeeff : 0000:00:0d.0
efffee00-efffeeff : 8139too
efffef00-efffefff : 0000:00:0f.0
efffef00-efffefff : 8139too
effff000-efffffff : 0000:00:11.0
effff000-efffffff : aic7xxx
ffff0000-ffffffff : reserved

cat /proc/iomem
00000000-0009fbff : System RAM
0009fc00-0009ffff : reserved
000a0000-000bffff : Video RAM area
000cb000-000d3fff : Extension ROM
000f0000-000fffff : System ROM
00100000-11ffffff : System RAM
00100000-003c88f2 : Kernel code
003c88f3-004db8ff : Kernel data
c056f000-c096f000 : Bigphysarea
c7900000-cf9fffff : PCI Bus #01
c8000000-cbffffff : 0000:01:00.0

    c8000000-c8ffffff : vesafb

d0000000-d3ffffff : 0000:00:00.0
d7b00000-efcfffff : PCI Bus #01
e0000000-e3ffffff : 0000:01:00.0
e4000000-e7ffffff : 0000:01:00.0
e8000000-ebffffff : 0000:01:00.0
efc80000-efcfffff : 0000:01:00.0
efe00000-efefffff : 0000:00:09.0
efe00000-efe02fff : CS46xx_BA1_data0
efe10000-efe137ff : CS46xx_BA1_data1
efe20000-efe26fff : CS46xx_BA1_pmem
efe30000-efe300ff : CS46xx_BA1_reg
efffc000-efffcfff : 0000:00:09.0
efffc000-efffcfff : CS46xx_BA0
efffee00-efffeeff : 0000:00:0d.0
efffee00-efffeeff : 8139too
efffef00-efffefff : 0000:00:0f.0
efffef00-efffefff : 8139too
effff000-efffffff : 0000:00:11.0
effff000-efffffff : aic7xxx
ffff0000-ffffffff : reserved

[7.5.] PCI information ('lspci -vvv' as root)
00:00.0 Host bridge: Intel Corp. 440LX/EX - 82443LX/EX Host bridge (rev 03)

	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B-
	Status: Cap+ 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort+ >SERR- <PERR+
	Latency: 64
	Region 0: Memory at d0000000 (32-bit, prefetchable) [size=64M]
	Capabilities: [a0] AGP version 1.0
		Status: RQ=32 Iso- ArqSz=0 Cal=0 SBA+ ITACoh- GART64- HTrans- 64bit- FW- AGP3- Rate=x1,x2
		Command: RQ=1 ArqSz=0 Cal=0 SBA- AGP- GART64- 64bit- FW- Rate=<none>

00:01.0 PCI bridge: Intel Corp. 440LX/EX - 82443LX/EX AGP bridge (rev 03) (prog-if 00 [Normal decode])
Control: I/O+ Mem+ BusMaster+ SpecCycle+ MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B-
Status: Cap- 66Mhz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
Latency: 64
Bus: primary=00, secondary=01, subordinate=01, sec-latency=64
I/O behind bridge: 0000b000-0000bfff
Memory behind bridge: d7b00000-efcfffff
Prefetchable memory behind bridge: c7900000-cf9fffff
BridgeCtl: Parity+ SERR+ NoISA- VGA+ MAbort- >Reset- FastB2B-

00:07.0 ISA bridge: Intel Corp. 82371AB/EB/MB PIIX4 ISA (rev 02)
Control: I/O+ Mem+ BusMaster+ SpecCycle+ MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
Status: Cap- 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
Latency: 0

00:07.1 IDE interface: Intel Corp. 82371AB/EB/MB PIIX4 IDE (rev 01) (prog-if 80 [Master])
Control: I/O+ Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
Status: Cap- 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- Region 4: I/O ports at ffa0 [size=16]

00:07.2 USB Controller: Intel Corp. 82371AB/EB/MB PIIX4 USB (rev 01) (prog-if 00 [UHCI])
Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
Status: Cap- 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
Latency: 64
Interrupt: pin D routed to IRQ 11
Region 4: I/O ports at d800 [size=32]

00:07.3 Bridge: Intel Corp. 82371AB/EB/MB PIIX4 ACPI (rev 02)
Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
Status: Cap- 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
Interrupt: pin ? routed to IRQ 9

00:09.0 Multimedia audio controller: Cirrus Logic CS 4614/22/24 [CrystalClear SoundFusion Audio Accelerator] (rev 01)
Subsystem: Voyetra Technologies: Unknown device 3357
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B-
Status: Cap+ 66Mhz- UDF- FastB2B- ParErr- DEVSEL=slow >TAbort- <TAbort- <MAbort- >SERR- <PERR-
Latency: 64 (1000ns min, 6000ns max)
Interrupt: pin A routed to IRQ 11
Region 0: Memory at efffc000 (32-bit, non-prefetchable) [size=4K]
Region 1: Memory at efe00000 (32-bit, non-prefetchable) [size=1M]
Capabilities: [40] Power Management version 2
Flags: PMEClk- DSI+ D1+ D2+ AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 PME-Enable- DSel=0 DScale=0 PME-

00:0d.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8139/8139C/8139C+ (rev 10)
Subsystem: D-Link System Inc DFE-538TX
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B-
Status: Cap+ 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
Latency: 64 (8000ns min, 16000ns max)
Interrupt: pin A routed to IRQ 11
Region 0: I/O ports at da00 [size=256]
Region 1: Memory at efffee00 (32-bit, non-prefetchable) [size=256]
Capabilities: [50] Power Management version 2
Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0-,D1+,D2+,D3hot+,D3cold-)
Status: D0 PME-Enable- DSel=0 DScale=0 PME-

00:0f.0 Ethernet controller: D-Link System Inc RTL8139 Ethernet (rev 10)
Subsystem: D-Link System Inc DFE-530TX+ 10/100 Ethernet Adapter
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B-
Status: Cap+ 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
Latency: 64 (8000ns min, 16000ns max)
Interrupt: pin A routed to IRQ 10
Region 0: I/O ports at dc00 [size=256]
Region 1: Memory at efffef00 (32-bit, non-prefetchable) [size=256]
Capabilities: [50] Power Management version 2
Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0-,D1+,D2+,D3hot+,D3cold-)
Status: D0 PME-Enable- DSel=0 DScale=0 PME-

00:11.0 SCSI storage controller: Adaptec AIC-7892A U160/m (rev 02)
Subsystem: Adaptec 29160 Ultra160 SCSI Controller
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV+ VGASnoop- ParErr- Stepping- SERR+ FastB2B-
Status: Cap+ 66Mhz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
Latency: 64 (10000ns min, 6250ns max), cache line size 08
Interrupt: pin A routed to IRQ 9
BIST result: 00
Region 0: I/O ports at de00 [disabled] [size=256]
Region 1: Memory at effff000 (64-bit, non-prefetchable) [size=4K]
Expansion ROM at effc0000 [disabled] [size=128K]
Capabilities: [dc] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 PME-Enable- DSel=0 DScale=0 PME-

00:13.0 Class 6120: Unknown device 0002:0400 (rev de) (prog-if 11)
Subsystem: Unknown device 0008:0000
Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR+
Interrupt: pin A routed to IRQ 0
Region 2: Memory at <unassigned> (32-bit, prefetchable) [disabled]
Region 3: Memory at <unassigned> (32-bit, prefetchable) [disabled]

01:00.0 VGA compatible controller: S3 Inc. 86C410 Savage 2000 (rev 02) (prog-if 00 [VGA])

	Subsystem: S3 Inc. 86C410 Savage 2000
	Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
	Status: Cap+ 66Mhz+ UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
	Latency: 248 (3000ns min, 4000ns max), cache line size 08
	Interrupt: pin A routed to IRQ 0
	Region 0: Memory at efc80000 (32-bit, non-prefetchable) [size=512K]
	Region 1: Memory at c8000000 (32-bit, prefetchable) [size=64M]
	Region 2: Memory at e8000000 (32-bit, non-prefetchable) [size=64M]
	Region 3: Memory at e4000000 (32-bit, non-prefetchable) [size=64M]
	Region 4: Memory at e0000000 (32-bit, non-prefetchable) [size=64M]
	Expansion ROM at efc70000 [disabled] [size=64K]
	Capabilities: [dc] Power Management version 1
		Flags: PMEClk- DSI+ D1+ D2+ AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
		Status: D0 PME-Enable- DSel=0 DScale=0 PME-
	Capabilities: [80] AGP version 2.0
		Status: RQ=32 Iso- ArqSz=0 Cal=0 SBA+ ITACoh- GART64- HTrans- 64bit- FW- AGP3- Rate=x1,x2,x4
		Command: RQ=1 ArqSz=0 Cal=0 SBA- AGP- GART64- 64bit- FW- Rate=<none>

[7.6.] SCSI information (from /proc/scsi/scsi) Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
Vendor: QUANTUM Model: ATLAS10K3_36_WLS Rev: 020W
Type: Direct-Access ANSI SCSI revision: 03
Host: scsi0 Channel: 00 Id: 03 Lun: 00
Vendor: YAMAHA Model: CRW-F1S Rev: 1.0c
Type: CD-ROM ANSI SCSI revision: 02
Host: scsi0 Channel: 00 Id: 04 Lun: 00
Vendor: DVDRW Model: IDE1004 Rev: 0048
Type: CD-ROM ANSI SCSI revision: 02
Host: scsi0 Channel: 00 Id: 06 Lun: 00
Vendor: NAKAMICH Model: MJ-5.16S Rev: 1.06
Type: CD-ROM ANSI SCSI revision: 02
Host: scsi0 Channel: 00 Id: 06 Lun: 01
Vendor: NAKAMICH Model: MJ-5.16S Rev: 1.06
Type: CD-ROM ANSI SCSI revision: 02
Host: scsi0 Channel: 00 Id: 06 Lun: 02
Vendor: NAKAMICH Model: MJ-5.16S Rev: 1.06
Type: CD-ROM ANSI SCSI revision: 02
Host: scsi0 Channel: 00 Id: 06 Lun: 03
Vendor: NAKAMICH Model: MJ-5.16S Rev: 1.06
Type: CD-ROM ANSI SCSI revision: 02
Host: scsi0 Channel: 00 Id: 06 Lun: 04
Vendor: NAKAMICH Model: MJ-5.16S Rev: 1.06
Type: CD-ROM ANSI SCSI revision: 02
Host: scsi1 Channel: 00 Id: 00 Lun: 00
Vendor: Model: USB DISK Rev: 1.17
Type: Direct-Access ANSI SCSI revision: 02

[7.7.] Other information that might be relevant to the problem
(please look in /proc and include all information that you think to be relevant):
[X.] Other notes, patches, fixes, workarounds:
It worked fine with 2.6.2.

#1 lore raw

Joachim Feise wrote on 2/19/2004 11:47:

Quoted 10 lines

[1.] One line summary of the problem:
2.6.3 hangs when writing to scsi-dvd

[2.] Full description of the problem/report:

I have a DVD drive (BTC1004) connected via an IDE-SCSI bridge to an Adaptec 29160 host adapter.
With kernel 2.6.3, I experience a complete system hang whenever I try to record data on a DVD.
It requires a reboot.

More info:
on the cdwrite list, somebody reported a similar problem
(http://lists.debian.org/cdwrite/2004/cdwrite-200402/msg00081.html)

His quick-n-dirty fix works for me:

drivers/scsi/scsi_lib.c 2004-02-20 13:52:46.000000000 -0800 renamed from drivers/scsi/scsi_lib.c.orig 2004-02-17 19:57:57.000000000 -0800 +1 -1
@@ -1292,7 +1292,7 @@
         * host adapters.  A host driver can alter this mask in its
         * slave_alloc() or slave_configure() callback if necessary.
         */
-       blk_queue_dma_alignment(q, (8 - 1));
+       /* blk_queue_dma_alignment(q, (8 - 1)); */
 
        if (!shost->use_clustering)
                clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);

But without knowing what this particular line does, it is impossible for me to say if commenting out the line is the right thing to do.

-Joe

#2 lore raw

Please trim the cc list as appropriate. I am including all of the people from the various messages related to probably one problem to get all of us on the same track. Jens is included because he might directly see a solution.

Quoted 31 lines · Joachim Feise

Joachim Feise wrote on 2/19/2004 11:47:

Quoted 10 lines

[1.] One line summary of the problem:
2.6.3 hangs when writing to scsi-dvd

[2.] Full description of the problem/report:

I have a DVD drive (BTC1004) connected via an IDE-SCSI bridge to an Adaptec 29160 host adapter.
With kernel 2.6.3, I experience a complete system hang whenever I try to record data on a DVD.
It requires a reboot.

More info:
on the cdwrite list, somebody reported a similar problem
(http://lists.debian.org/cdwrite/2004/cdwrite-200402/msg00081.html)

His quick-n-dirty fix works for me:

drivers/scsi/scsi_lib.c 2004-02-20 13:52:46.000000000 -0800 renamed from drivers/scsi/scsi_lib.c.orig 2004-02-17 19:57:57.000000000 -0800 +1 -1
@@ -1292,7 +1292,7 @@
         * host adapters.  A host driver can alter this mask in its
         * slave_alloc() or slave_configure() callback if necessary.
         */
-       blk_queue_dma_alignment(q, (8 - 1));
+       /* blk_queue_dma_alignment(q, (8 - 1)); */
 
        if (!shost->use_clustering)
                clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
Quoted 3 lines

But without knowing what this particular line does, it is impossible for me to say if commenting out the line is the right thing to do.

This line has has several duties. For me, it sets the alignment constaint used by st for deciding whether to use direct i/o or internal buffer. For other people more important is that it is used for similar purpose in linux/fs/bio.c. The beginning of __bio_map_user contains the following:

        /*
         * transfer and buffer must be aligned to at least hardsector
         * size for now, in the future we can relax this restriction
         */
        if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q)))
                return NULL;

Without the call to blk_queue_alignment() in scsi_lib.c, the queue alignment is to 512 byte boundary and the transfer size must be a multiple of 512 bytes. With the calls, the unit is 8 bytes.

The function sg_io in linux/drivers/scsi/scsi_ioctl.c contains this:

                /*
                 * first try to map it into a bio. reading from device will
                 * be a write to vm.
                 */
                bio = bio_map_user(q, NULL, (unsigned long) hdr->dxferp,
                                   hdr->dxfer_len, reading);

                /*
                 * if bio setup failed, fall back to slow approach
                 */
                if (!bio) {

bio_map_user() calls __bio_map_user() and so the previous conditions are used in sg_io() to decide on bouncing.

I made a test program that uses sg_io() to send a command to a SCSI device. I tested it with a SCSI tape device. Without any changes the program hung. The SCSI driver was sym53c8xx_2 and it loops on the following error:

Feb 23 13:24:17 box kernel: sym1:5:0:extraneous data discarded.
Feb 23 13:24:17 box kernel: sym1:5:0:COMMAND FAILED (87 0 1).
Feb 23 13:24:17 box kernel: SCSI error : <1 0 5 0> return code = 0x70000

The I modified the program to align the buffer to 512 byte boundary. This did not help. The next step was to set the transfer size to 512 bytes. This helps!! Restoring the non-512 byte alignment did not cause any problems.

The conclusion at this phase is that _the tranfer length in bio must be a multiple of 512 bytes_.

I hope someone sees no where the real problem is.

Signature · 1 line
Kai
#3 lore raw
Quoted 88 lines · Kai Makisara

Please trim the cc list as appropriate. I am including all of the people from the various messages related to probably one problem to get all of us on the same track. Jens is included because he might directly see a solution.

Quoted 31 lines · Joachim Feise

Joachim Feise wrote on 2/19/2004 11:47:

Quoted 10 lines

[1.] One line summary of the problem:
2.6.3 hangs when writing to scsi-dvd

[2.] Full description of the problem/report:

I have a DVD drive (BTC1004) connected via an IDE-SCSI bridge to an Adaptec 29160 host adapter.
With kernel 2.6.3, I experience a complete system hang whenever I try to record data on a DVD.
It requires a reboot.

More info:
on the cdwrite list, somebody reported a similar problem
(http://lists.debian.org/cdwrite/2004/cdwrite-200402/msg00081.html)

His quick-n-dirty fix works for me:

drivers/scsi/scsi_lib.c 2004-02-20 13:52:46.000000000 -0800 renamed from drivers/scsi/scsi_lib.c.orig 2004-02-17 19:57:57.000000000 -0800 +1 -1
@@ -1292,7 +1292,7 @@
         * host adapters.  A host driver can alter this mask in its
         * slave_alloc() or slave_configure() callback if necessary.
         */
-       blk_queue_dma_alignment(q, (8 - 1));
+       /* blk_queue_dma_alignment(q, (8 - 1)); */
 
        if (!shost->use_clustering)
                clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
Quoted 3 lines

But without knowing what this particular line does, it is impossible for me to say if commenting out the line is the right thing to do.

This line has has several duties. For me, it sets the alignment constaint used by st for deciding whether to use direct i/o or internal buffer. For other people more important is that it is used for similar purpose in linux/fs/bio.c. The beginning of __bio_map_user contains the following:

        /*
         * transfer and buffer must be aligned to at least hardsector
         * size for now, in the future we can relax this restriction
         */
        if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q)))
                return NULL;

Without the call to blk_queue_alignment() in scsi_lib.c, the queue alignment is to 512 byte boundary and the transfer size must be a multiple of 512 bytes. With the calls, the unit is 8 bytes.

The function sg_io in linux/drivers/scsi/scsi_ioctl.c contains this:

                /*
                 * first try to map it into a bio. reading from device will
                 * be a write to vm.
                 */
                bio = bio_map_user(q, NULL, (unsigned long) hdr->dxferp,
                                   hdr->dxfer_len, reading);

                /*
                 * if bio setup failed, fall back to slow approach
                 */
                if (!bio) {

bio_map_user() calls __bio_map_user() and so the previous conditions are used in sg_io() to decide on bouncing.

I made a test program that uses sg_io() to send a command to a SCSI device. I tested it with a SCSI tape device. Without any changes the program hung. The SCSI driver was sym53c8xx_2 and it loops on the following error:

Feb 23 13:24:17 box kernel: sym1:5:0:extraneous data discarded.
Feb 23 13:24:17 box kernel: sym1:5:0:COMMAND FAILED (87 0 1).
Feb 23 13:24:17 box kernel: SCSI error : <1 0 5 0> return code = 0x70000

The I modified the program to align the buffer to 512 byte boundary. This did not help. The next step was to set the transfer size to 512 bytes. This helps!! Restoring the non-512 byte alignment did not cause any problems.

Quoted 4 lines

The conclusion at this phase is that _the tranfer length in bio must be a multiple of 512 bytes_.

I hope someone sees no where the real problem is.

SCSI io completion path (sr/sd/st rw_intr() -> scsi_io_completion() -> scsi_end_request()) doesn't properly handle non-sector aligned data transfers. This patch should fix it up. Warning: untested.

===== drivers/scsi/scsi_lib.c 1.118 vs edited =====

drivers/scsi/scsi_lib.c +20 -15
@@ -493,7 +493,7 @@
  *		at some point during this call.
  */
 static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
-					  int sectors, int requeue)
+					  int bytes, int requeue)
 {
 	request_queue_t *q = cmd->device->request_queue;
 	struct request *req = cmd->request;
@@ -503,12 +503,15 @@
 	 * If there are blocks left over at the end, set up the command
 	 * to queue the remainder of them.
 	 */
-	if (end_that_request_first(req, uptodate, sectors)) {
-		int leftover = req->hard_nr_sectors - sectors;
+	if (end_that_request_chunk(req, uptodate, bytes)) {
+		int leftover = (req->hard_nr_sectors << 9) - bytes;
+
+		if (blk_pc_request(req))
+			leftover = req->data_len - bytes;
 
 		/* kill remainder if no retrys */
 		if (!uptodate && blk_noretry_request(req))
-			end_that_request_first(req, 0, leftover);
+			end_that_request_chunk(req, 0, leftover);
 		else {
 			if (requeue)
 				/*
@@ -649,11 +652,11 @@
  *		b) We can just use scsi_requeue_command() here.  This would
  *		   be used if we just wanted to retry, for example.
  */
-void scsi_io_completion(struct scsi_cmnd *cmd, int good_sectors,
-			int block_sectors)
+void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
+			unsigned int block_bytes)
 {
 	int result = cmd->result;
-	int this_count = cmd->bufflen >> 9;
+	int this_count = cmd->bufflen;
 	request_queue_t *q = cmd->device->request_queue;
 	struct request *req = cmd->request;
 	int clear_errors = 1;
@@ -705,9 +708,9 @@
 	 * Next deal with any sectors which we were able to correctly
 	 * handle.
 	 */
-	if (good_sectors >= 0) {
-		SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, %d sectors done.\n",
-					      req->nr_sectors, good_sectors));
+	if (good_bytes >= 0) {
+		SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, %d bytes done.\n",
+					      req->nr_sectors, good_bytes));
 		SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n", cmd->use_sg));
 
 		if (clear_errors)
@@ -717,13 +720,13 @@
 		 * they will have been finished off by the first command.
 		 * If not, then we have a multi-buffer command.
 		 *
-		 * If block_sectors != 0, it means we had a medium error
+		 * If block_bytes != 0, it means we had a medium error
 		 * of some sort, and that we want to mark some number of
 		 * sectors as not uptodate.  Thus we want to inhibit
 		 * requeueing right here - we will requeue down below
 		 * when we handle the bad sectors.
 		 */
-		cmd = scsi_end_request(cmd, 1, good_sectors, result == 0);
+		cmd = scsi_end_request(cmd, 1, good_bytes, result == 0);
 
 		/*
 		 * If the command completed without error, then either finish off the
@@ -808,7 +811,7 @@
 			       (int) cmd->device->id, (int) cmd->device->lun);
 			print_command(cmd->data_cmnd);
 			print_sense("", cmd);
-			cmd = scsi_end_request(cmd, 0, block_sectors, 1);
+			cmd = scsi_end_request(cmd, 0, block_bytes, 1);
 			return;
 		default:
 			break;
@@ -837,8 +840,10 @@
 		 * We sometimes get this cruft in the event that a medium error
 		 * isn't properly reported.
 		 */
-		cmd = scsi_end_request(cmd, 0, req->current_nr_sectors, 1);
-		return;
+		block_bytes = req->hard_cur_sectors << 9;
+		if (!block_bytes)
+			block_bytes = req->data_len;
+		cmd = scsi_end_request(cmd, 0, block_bytes, 1);
 	}
 }
 

===== drivers/scsi/sd.c 1.140 vs edited =====

drivers/scsi/sd.c +9 -7
@@ -661,8 +661,8 @@
 static void sd_rw_intr(struct scsi_cmnd * SCpnt)
 {
 	int result = SCpnt->result;
-	int this_count = SCpnt->bufflen >> 9;
-	int good_sectors = (result == 0 ? this_count : 0);
+	int this_count = SCpnt->bufflen;
+	int good_bytes = (result == 0 ? this_count : 0);
 	sector_t block_sectors = 1;
 	sector_t error_sector;
 #ifdef CONFIG_SCSI_LOGGING
@@ -688,6 +688,8 @@
 		case MEDIUM_ERROR:
 			if (!(SCpnt->sense_buffer[0] & 0x80))
 				break;
+			if (!blk_fs_request(SCpnt->request))
+				break;
 			error_sector = (SCpnt->sense_buffer[3] << 24) |
 			(SCpnt->sense_buffer[4] << 16) |
 			(SCpnt->sense_buffer[5] << 8) |
@@ -718,9 +720,9 @@
 			}
 
 			error_sector &= ~(block_sectors - 1);
-			good_sectors = error_sector - SCpnt->request->sector;
-			if (good_sectors < 0 || good_sectors >= this_count)
-				good_sectors = 0;
+			good_bytes = (error_sector - SCpnt->request->sector) << 9;
+			if (good_bytes < 0 || good_bytes >= this_count)
+				good_bytes = 0;
 			break;
 
 		case RECOVERED_ERROR:
@@ -732,7 +734,7 @@
 			print_sense("sd", SCpnt);
 			SCpnt->result = 0;
 			SCpnt->sense_buffer[0] = 0x0;
-			good_sectors = this_count;
+			good_bytes = this_count;
 			break;
 
 		case ILLEGAL_REQUEST:
@@ -755,7 +757,7 @@
 	 * how many actual sectors finished, and how many sectors we need
 	 * to say have failed.
 	 */
-	scsi_io_completion(SCpnt, good_sectors, block_sectors);
+	scsi_io_completion(SCpnt, good_bytes, block_sectors << 9);
 }
 
 static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp)

===== drivers/scsi/sr.c 1.98 vs edited =====

drivers/scsi/sr.c +10 -8
@@ -179,14 +179,14 @@
 static void rw_intr(struct scsi_cmnd * SCpnt)
 {
 	int result = SCpnt->result;
-	int this_count = SCpnt->bufflen >> 9;
-	int good_sectors = (result == 0 ? this_count : 0);
+	int this_count = SCpnt->bufflen;
+	int good_bytes = (result == 0 ? this_count : 0);
 	int block_sectors = 0;
 	long error_sector;
 	struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk);
 
 #ifdef DEBUG
-	printk("sr.c done: %x %p\n", result, SCpnt->request->bh->b_data);
+	printk("sr.c done: %x\n", result);
 #endif
 
 	/*
@@ -203,6 +203,8 @@
 		case ILLEGAL_REQUEST:
 			if (!(SCpnt->sense_buffer[0] & 0x90))
 				break;
+			if (!blk_fs_request(SCpnt->request))
+				break;
 			error_sector = (SCpnt->sense_buffer[3] << 24) |
 				(SCpnt->sense_buffer[4] << 16) |
 				(SCpnt->sense_buffer[5] << 8) |
@@ -215,9 +217,9 @@
 			if (cd->device->sector_size == 2048)
 				error_sector <<= 2;
 			error_sector &= ~(block_sectors - 1);
-			good_sectors = error_sector - SCpnt->request->sector;
-			if (good_sectors < 0 || good_sectors >= this_count)
-				good_sectors = 0;
+			good_bytes = (error_sector - SCpnt->request->sector) << 9;
+			if (good_bytes < 0 || good_bytes >= this_count)
+				good_bytes = 0;
 			/*
 			 * The SCSI specification allows for the value
 			 * returned by READ CAPACITY to be up to 75 2K
@@ -241,7 +243,7 @@
 			print_sense("sr", SCpnt);
 			SCpnt->result = 0;
 			SCpnt->sense_buffer[0] = 0x0;
-			good_sectors = this_count;
+			good_bytes = this_count;
 			break;
 
 		default:
@@ -254,7 +256,7 @@
 	 * how many actual sectors finished, and how many sectors we need
 	 * to say have failed.
 	 */
-	scsi_io_completion(SCpnt, good_sectors, block_sectors);
+	scsi_io_completion(SCpnt, good_bytes, block_sectors << 9);
 }
 
 static int sr_init_command(struct scsi_cmnd * SCpnt)

===== drivers/scsi/st.c 1.77 vs edited =====

drivers/scsi/st.c +1 -1
@@ -4011,7 +4011,7 @@
 
 static void st_intr(struct scsi_cmnd *SCpnt)
 {
-	scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen >> 9), 1);
+	scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen), 1);
 }
 
 /*

===== include/scsi/scsi_cmnd.h 1.3 vs edited =====

include/scsi/scsi_cmnd.h +1 -1
@@ -158,6 +158,6 @@
 
 extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, int);
 extern void scsi_put_command(struct scsi_cmnd *);
-extern void scsi_io_completion(struct scsi_cmnd *, int, int);
+extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
 
 #endif /* _SCSI_SCSI_CMND_H */
Signature · 1 line
Jens Axboe
#4 lore raw
Quoted 1 line · Jens Axboe

On Mon, Feb 23 2004, Kai Makisara wrote:

...

Quoted 6 lines
Quoted 1 line

I hope someone sees no where the real problem is.

SCSI io completion path (sr/sd/st rw_intr() -> scsi_io_completion() -> scsi_end_request()) doesn't properly handle non-sector aligned data transfers. This patch should fix it up. Warning: untested.

Now it is slightly tested: it works with my SCSI tape test program. Since the program only does an inquiry, I tried it with the SCSI system disk without problems. Unfortunately, I don't have access to a SCSI CDROM now.

Signature · 1 line
Kai
#5 lore raw
Quoted 6 lines · Kai Makisara
Quoted 1 line · Jens Axboe

On Mon, Feb 23 2004, Kai Makisara wrote:

...

Quoted 2 lines
Quoted 1 line

I hope someone sees no where the real problem is.

Quoted 7 lines
Quoted 4 lines

SCSI io completion path (sr/sd/st rw_intr() -> scsi_io_completion() -> scsi_end_request()) doesn't properly handle non-sector aligned data transfers. This patch should fix it up. Warning: untested.

Now it is slightly tested: it works with my SCSI tape test program. Since the program only does an inquiry, I tried it with the SCSI system disk without problems. Unfortunately, I don't have access to a SCSI CDROM now.

Great, that's promising (code like this tends to either break at first access, or work :-). Thanks for testing.

Signature · 1 line
Jens Axboe
#6 lore raw
Quoted 6 lines · Jens Axboe
Quoted 6 lines
Quoted 5 lines
Quoted 1 line

I hope someone sees no where the real problem is.

SCSI io completion path (sr/sd/st rw_intr() -> scsi_io_completion() -> scsi_end_request()) doesn't properly handle non-sector aligned data transfers. This patch should fix it up. Warning: untested.

Quoted 6 lines
Quoted 3 lines

Now it is slightly tested: it works with my SCSI tape test program. Since the program only does an inquiry, I tried it with the SCSI system disk without problems. Unfortunately, I don't have access to a SCSI CDROM now.

Great, that's promising (code like this tends to either break at first access, or work :-). Thanks for testing.

Hello all,
yes, this fix works! I can open k3b now without problems.
And yes, my other SCSI devices are still working, also my SATA disks using libata.
Thank you ver much,
Frank

#7 lore raw
Quoted 11 lines · Frank Pieczynski
Quoted 10 lines · Jens Axboe
Quoted 9 lines
Quoted 5 lines
Quoted 1 line

I hope someone sees no where the real problem is.

SCSI io completion path (sr/sd/st rw_intr() -> scsi_io_completion() -> scsi_end_request()) doesn't properly handle non-sector aligned data transfers. This patch should fix it up. Warning: untested.

Now it is slightly tested: it works with my SCSI tape test program. Since the program only does an inquiry, I tried it with the SCSI system disk without problems. Unfortunately, I don't have access to a SCSI CDROM now.

Quoted 8 lines
Quoted 2 lines

Great, that's promising (code like this tends to either break at first access, or work :-). Thanks for testing.

Hello all,
yes, this fix works! I can open k3b now without problems.
And yes, my other SCSI devices are still working, also my SATA disks using libata.
Thank you ver much,

Andrew, care to shake it down in -mm for a release? IMO it's clearly the way to go (changing io completion to be byte based instead of sectors), and the patch looks ok to me (well obviously :-)

Signature · 1 line
Jens Axboe
#8 lore raw
In reply to Jens Axboe
Quoted 7 lines · Jens Axboe
Quoted 3 lines · Kai Makisara

Now it is slightly tested: it works with my SCSI tape test program. Since the program only does an inquiry, I tried it with the SCSI system disk without problems. Unfortunately, I don't have access to a SCSI CDROM now.

Great, that's promising (code like this tends to either break at first access, or work :-). Thanks for testing.

I tried it with my SCSI DVD. Writing to and reading from DVD+RW works fine.
Thanks for the fix.

-Joe

#9 lore raw
In reply to Kai Makisara
Quoted 9 lines · Kai Makisara
Quoted 9 lines
drivers/scsi/scsi_lib.c 2004-02-20 13:52:46.000000000 -0800 renamed from drivers/scsi/scsi_lib.c.orig 2004-02-17 19:57:57.000000000 -0800 +1 -1
@@ -1292,7 +1292,7 @@
         * host adapters.  A host driver can alter this mask in its
         * slave_alloc() or slave_configure() callback if necessary.
         */
-       blk_queue_dma_alignment(q, (8 - 1));
+       /* blk_queue_dma_alignment(q, (8 - 1)); */ 
 
Quoted 7 lines
Quoted 6 lines
drivers/scsi/scsi_lib.c 2004-02-20 13:52:46.000000000 -0800 renamed from drivers/scsi/scsi_lib.c.orig 2004-02-17 19:57:57.000000000 -0800 +0 -0
        if (!shost->use_clustering)
                clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); 

But without knowing what this particular line does, it is impossible for me to say if commenting out the line is the right thing to do.

This line has has several duties. For me, it sets the alignment constaint used by st for deciding whether to use direct i/o or internal buffer. For other people more important is that it is used for similar purpose in linux/fs/bio.c. The beginning of __bio_map_user contains the following:

<snip>

Thanks for the info. Since my problem occured with an external firewire
burner I asked Ben Collins (maintainer of the sbp2 driver) about it this weekend.
The USB2 port of the burner worked without any problems, so we took a look at the USB mass-storage driver.
It calls blk_queue_dma_alignment(q, (512 - 1)) in slave_configure.
We decided to add a slave_configure in sbp2 too and it works now.
I know that this doesn't solve the problem for other users, but it seems to be the fastest solution for devices connected via sbp2.

Michael