linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* SATA (libata) + sg oops in 2.4.28-pre1
@ 2004-08-16 21:04 Tony Battersby
  2005-02-19 17:28 ` Jeff Garzik
  0 siblings, 1 reply; 3+ messages in thread
From: Tony Battersby @ 2004-08-16 21:04 UTC (permalink / raw)
  To: jgarzik; +Cc: linux-ide

[-- Attachment #1: Type: text/plain, Size: 3592 bytes --]

I get an oops trying to get standard inquiry data from a SATA disk via
/dev/sg0 in kernel 2.4.28-pre1:

Unable to handle kernel NULL pointer dereference at virtual address
0000001b
 printing eip:
d0873f99
*pde = 00000000
Oops: 0000
ata_piix libata sg e1000
CPU:    0
EIP:    0010:[<d0873f99>]    Not tainted
EFLAGS: 00010002
EIP is at ata_scsi_rbuf_get+0x19/0x80 [libata]
eax: 00000000   ebx: d0874060   ecx: cf7c4000   edx: cf7908f4
esi: cfc42800   edi: cf80fd8c   ebp: cf790800   esp: cf80fd5c
ds: 0018   es: 0018   ss: 0018
Process cytdtest (pid: 264, stackpage=cf80f000)
Stack: d0874060 cf80fd8c d087401a cfc42800 cf80fd70 c0131d13 cfc42800
c01ac2e0
       c01ac2e0 d0874915 cf80fd8c d0874060 cf79087c cf7908f4 cfc42800
c01ac2e0
       cfc42800 cf79087c d08747f9 cf79087c cf7908f4 cfc42800 c01ac2e0
00000287
Call Trace:
 [<d0874060>] ata_scsiop_inq_std+0x0/0xd0 [libata]
 [<d087401a>] ata_scsi_rbuf_fill+0x1a/0x60 [libata]
 [<c0131d13>] kmalloc+0xa3/0x180 [kernel]
 [<c01ac2e0>] scsi_done+0x0/0xd0 [kernel]
 [<c01ac2e0>] scsi_done+0x0/0xd0 [kernel]
 [<d0874915>] ata_scsi_simulate+0xe5/0x144 [libata]
 [<d0874060>] ata_scsiop_inq_std+0x0/0xd0 [libata]
 [<c01ac2e0>] scsi_done+0x0/0xd0 [kernel]
 [<d08747f9>] ata_scsi_queuecmd+0xe9/0x120 [libata]
 [<c01ac2e0>] scsi_done+0x0/0xd0 [kernel]
 [<c01abaa5>] scsi_dispatch_cmd+0x195/0x380 [kernel]
 [<c01ac2e0>] scsi_done+0x0/0xd0 [kernel]
 [<c01b3cd4>] scsi_request_fn+0x354/0x3b0 [kernel]
 [<c01b2f9c>] __scsi_insert_special+0x6c/0x80 [kernel]
 [<c01b2ffa>] scsi_insert_special_req+0x1a/0x20 [kernel]
 [<c01abeb4>] scsi_do_req+0x174/0x1b0 [kernel]
 [<d08681d0>] sg_cmd_done_bh+0x0/0x380 [sg]
 [<d086706b>] sg_common_write+0x24b/0x260 [sg]
 [<d08681d0>] sg_cmd_done_bh+0x0/0x380 [sg]
 [<d0866df5>] sg_new_write+0x225/0x250 [sg]
 [<d08669d4>] sg_write+0x104/0x300 [sg]
 [<c01147a7>] do_page_fault+0x1a7/0x4eb [kernel]
 [<c012a2e6>] do_brk+0x206/0x250 [kernel]
 [<c013b456>] sys_write+0x96/0x110 [kernel]
 [<c013a9ad>] filp_open+0x4d/0x60 [kernel]
 [<c01290ca>] sys_brk+0xba/0xf0 [kernel]
 [<c0106ff3>] system_call+0x33/0x38 [kernel]

Code: 0f b6 50 1b 8b 14 95 88 f0 2e c0 8b ba c4 00 00 00 8b 9a c8

The same problem exists in kernel 2.4.27 with 2.4.27-rc3-libata1.patch
applied.

The program to reproduce the problem is attached.  *** NOTE *** You must
do "echo 1 > /proc/scsi/sg/allow_dio" before running the program for the
oops to happen.

The condition that triggers the oops is having struct scsi_cmnd::use_sg
!= 0 in ata_scsi_rbuf_get().  The attached test program accomplishes
this by using direct I/O with a user buffer that crosses page
boundaries.  The test program works just fine when using indirect I/O or
when using direct I/O with a user buffer that doesn't cross page
boundaries (in which case use_sg == 0).

Here is some extra dmesg output if useful:

libata version 1.02 loaded.
ata_piix version 1.02
PCI: Setting latency timer of device 00:1f.2 to 64
ata1: SATA max UDMA/133 cmd 0xC800 ctl 0xCC02 bmdma 0xD800 irq 10
ata2: SATA max UDMA/133 cmd 0xD000 ctl 0xD402 bmdma 0xD808 irq 10
ata1: dev 0 cfg 49:2f00 82:7c6b 83:7f09 84:4003 85:7c69 86:3e01 87:4003
88:207f
ata1: dev 0 ATA, max UDMA/133, 488397168 sectors: lba48
ata1: dev 0 configured for UDMA/133
ata2: SATA port has no device.
scsi0 : ata_piix
scsi1 : ata_piix
  Vendor: ATA       Model: Maxtor 7Y250M0    Rev: YAR5
  Type:   Direct-Access                      ANSI SCSI revision: 05
Attached scsi disk sda at scsi0, channel 0, id 0, lun 0
SCSI device sda: 488397168 512-byte hdwr sectors (250059 MB)
 sda: unknown partition table

Anthony J. Battersby
Cybernetics

[-- Attachment #2: inquiry.c --]
[-- Type: application/octet-stream, Size: 2264 bytes --]

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <scsi/sg.h>

#define TXFER_LEN 56

int main(int argc, char *argv[]) {
    char *sgd = (argc == 2) ? argv[1] : "/dev/sg0";
    sg_io_hdr_t io;
    uint8_t cdb[16];
    uint8_t *sense_data;
    uint8_t *buf;
    int pagesize = getpagesize();
    int fd;
    unsigned long addr;
    ssize_t len;

    fd = open(sgd, O_RDWR);
    if (fd == -1) {
        perror("open(/dev/sgX)");
        exit(EXIT_FAILURE);
    }

    buf = malloc(pagesize + TXFER_LEN);
    if (buf == NULL) {
        printf("OOM\n");
        exit(EXIT_FAILURE);
    }

    /* Force the buffer to cross a page boundary. */
    addr = (unsigned long) buf;
    addr = (addr & ~(pagesize - 1)) |
           (-(TXFER_LEN / 2) & (pagesize - 1));
    buf = (uint8_t *) addr;

    sense_data = malloc(0x100);
    if (sense_data == NULL) {
        printf("OOM\n");
        exit(EXIT_FAILURE);
    }

    memset(&io, 0, sizeof(io));

    io.interface_id = 'S';
    io.timeout      = UINT_MAX;

    io.sbp       = sense_data;
    io.mx_sb_len = 0xff;

    io.dxferp          = buf;
    io.dxfer_len       = TXFER_LEN;
    io.dxfer_direction = SG_DXFER_FROM_DEV;
    io.flags           = SG_FLAG_DIRECT_IO;

    io.cmdp = cdb;
    io.cmd_len = 6;
    cdb[0] = 0x12; /* inquiry */
    cdb[1] = 0x00;
    cdb[2] = 0x00;
    cdb[3] = 0x00;
    cdb[4] = TXFER_LEN;
    cdb[5] = 0x00;

    len = write(fd, &io, sizeof(io));
    if (len < 0) {
        perror("write /dev/sgX");
        exit(EXIT_FAILURE);
    }

    len = read(fd, &io, sizeof(io));
    if (len < 0) {
        perror("read /dev/sgX");
        exit(EXIT_FAILURE);
    }

    if ((io.status != 0) ||
        (io.host_status != 0) ||
        ((io.driver_status & 0x07) != 0)) {
        printf("error getting inquiry string\n");
        exit(EXIT_FAILURE);
    }

    printf("%.28s\n", &buf[8]);

    if (!(io.info & SG_INFO_DIRECT_IO)) {
        printf("You must do 'echo 1 > /proc/scsi/sg/allow_dio' for the oops to happen.\n");
    }

    return EXIT_SUCCESS;
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: SATA (libata) + sg oops in 2.4.28-pre1
  2004-08-16 21:04 SATA (libata) + sg oops in 2.4.28-pre1 Tony Battersby
@ 2005-02-19 17:28 ` Jeff Garzik
  2005-02-21 14:35   ` Tony Battersby
  0 siblings, 1 reply; 3+ messages in thread
From: Jeff Garzik @ 2005-02-19 17:28 UTC (permalink / raw)
  To: tonyb; +Cc: linux-ide

Tony Battersby wrote:
> I get an oops trying to get standard inquiry data from a SATA disk via
> /dev/sg0 in kernel 2.4.28-pre1:

Does this still occur, in 2.4.30-pre1?

	Jeff




^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: SATA (libata) + sg oops in 2.4.28-pre1
  2005-02-19 17:28 ` Jeff Garzik
@ 2005-02-21 14:35   ` Tony Battersby
  0 siblings, 0 replies; 3+ messages in thread
From: Tony Battersby @ 2005-02-21 14:35 UTC (permalink / raw)
  To: 'Jeff Garzik'; +Cc: linux-ide

> Tony Battersby wrote:
> > I get an oops trying to get standard inquiry data from a 
> SATA disk via
> > /dev/sg0 in kernel 2.4.28-pre1:
> 
> Does this still occur, in 2.4.30-pre1?

I don't have the hardware to test it right now.

Anthony J. Battersby
Cybernetics


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2005-02-21 14:35 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-16 21:04 SATA (libata) + sg oops in 2.4.28-pre1 Tony Battersby
2005-02-19 17:28 ` Jeff Garzik
2005-02-21 14:35   ` Tony Battersby

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).