2004-01-24 19:33:22

by Darren Dupre

[permalink] [raw]
Subject: 2.6.1 Oops when attempting to access /dev/st0 without st module loaded

I was about to do a tape backup, so I did the following:

modprobe advansys (automaticaly loads scsi_mod first)

tar --exclude=/sys --exclude=/proc --exclude=/mnt -cvf /dev/st0 /
which results in a segmentation fault as soon as tar is executed.

If I load the st module and try to backup, it says no such device

I believe it did this because I forgot to modprobe st (shouldn't it be done
automatically?) which I normally do but forgot to do this time around. I
keep all this stuff as modules becuase I like to be able to unhook the tape
drive and use it on other machines without having to reboot.

This is what appears in the syslog after attempting to run tar:

Unable to handle kernel NULL pointer dereference at virtual address 00000004
printing eip:
c0158b81
*pde = 00000000
Oops: 0002 [#1]
CPU: 0
EIP: 0060:[<c0158b81>] Not tainted
EFLAGS: 00010296
EIP is at chrdev_open+0x1f1/0x210
eax: 00000000 ebx: def1c80c ecx: f78c35fc edx: def1c914
esi: f78c35c0 edi: 00000000 ebp: f78c35c0 esp: e5047f1c
ds: 007b es: 007b ss: 0068
Process tar (pid: 10649, threadinfo=e5046000 task=ef6bf940)
Stack: f7ff0c00 00900000 e5047f28 00000000 f7415540 def1c80c 00000001
f7ff4280
c014ecd2 def1c80c f7415540 c7f89380 00008241 00008241 cdcc0000
e5046000
c014eb82 c7f89380 f7ff4280 00008241 e5047f70 c7f89380 f7ff4280
cdcc0005
Call Trace:
[<c014ecd2>] dentry_open+0x142/0x210
[<c014eb82>] filp_open+0x62/0x70
[<c014f01b>] sys_open+0x5b/0x90
[<c0108ee5>] sysenter_past_esp+0x52/0x71

Code: 89 50 04 89 55 3c 31 ed 89 4a 04 e9 38 fe ff ff e8 0a 04 fc
<6>note: tar[10649] exited with preempt_count 1
bad: scheduling while atomic!
Call Trace:
[<c0118f93>] schedule+0x563/0x570
[<c01404e3>] unmap_page_range+0x43/0x70
[<c01406c4>] unmap_vmas+0x1b4/0x210
[<c01444ab>] exit_mmap+0x7b/0x190
[<c011a924>] mmput+0x64/0xc0
[<c011e87a>] do_exit+0x14a/0x400
[<c0116e70>] do_page_fault+0x0/0x50c
[<c010a081>] die+0xe1/0xf0
[<c011704e>] do_page_fault+0x1de/0x50c
[<c011a680>] autoremove_wake_function+0x0/0x50
[<c0154c6b>] bio_alloc+0xcb/0x1a0
[<c011a680>] autoremove_wake_function+0x0/0x50
[<c0188daf>] ext3_get_inode_loc+0x17f/0x260
[<c01890f3>] ext3_read_inode+0x203/0x2c0
[<c0116e70>] do_page_fault+0x0/0x50c
[<c01099b9>] error_code+0x2d/0x38
[<c0158b81>] chrdev_open+0x1f1/0x210
[<c014ecd2>] dentry_open+0x142/0x210
[<c014eb82>] filp_open+0x62/0x70
[<c014f01b>] sys_open+0x5b/0x90
[<c0108ee5>] sysenter_past_esp+0x52/0x71

bad: scheduling while atomic!
Call Trace:
[<c0118f93>] schedule+0x563/0x570
[<c01404e3>] unmap_page_range+0x43/0x70
[<c01406c4>] unmap_vmas+0x1b4/0x210
[<c01444ab>] exit_mmap+0x7b/0x190
[<c011a924>] mmput+0x64/0xc0
[<c011e87a>] do_exit+0x14a/0x400
[<c0116e70>] do_page_fault+0x0/0x50c
[<c010a081>] die+0xe1/0xf0
[<c011704e>] do_page_fault+0x1de/0x50c
[<c011a680>] autoremove_wake_function+0x0/0x50
[<c0154c6b>] bio_alloc+0xcb/0x1a0
[<c011a680>] autoremove_wake_function+0x0/0x50
[<c0188daf>] ext3_get_inode_loc+0x17f/0x260
[<c01890f3>] ext3_read_inode+0x203/0x2c0
[<c0116e70>] do_page_fault+0x0/0x50c
[<c01099b9>] error_code+0x2d/0x38
[<c0158b81>] chrdev_open+0x1f1/0x210
[<c014ecd2>] dentry_open+0x142/0x210
[<c014eb82>] filp_open+0x62/0x70
[<c014f01b>] sys_open+0x5b/0x90
[<c0108ee5>] sysenter_past_esp+0x52/0x71

Other possibly useful information:


KT133A chipset
Advansys 3940UW (I believe thats the model number.. its an Ultra/Wide
controller with both narrow and wide connectors internally and one wide
external connector) scsi0 : AdvanSys SCSI 3.3GJ: PCI Ultra-Wide: PCIMEM
0xF88E8F00-0xF88E8F3F, IRQ 0xA as reported by the kernel
Quantum DLT4000 DLT tape drive with the latest firmware I believe.

Please CC mails directly to me.

Darren Dupre


2004-01-24 20:23:29

by Kai Mäkisara (Kolumbus)

[permalink] [raw]
Subject: Re: 2.6.1 Oops when attempting to access /dev/st0 without st module loaded

On Sat, 24 Jan 2004, Darren Dupre wrote:

> I was about to do a tape backup, so I did the following:
>
> modprobe advansys (automaticaly loads scsi_mod first)
>
> tar --exclude=/sys --exclude=/proc --exclude=/mnt -cvf /dev/st0 /
> which results in a segmentation fault as soon as tar is executed.
>
> If I load the st module and try to backup, it says no such device
>
> I believe it did this because I forgot to modprobe st (shouldn't it be done
> automatically?) which I normally do but forgot to do this time around. I
> keep all this stuff as modules becuase I like to be able to unhook the tape
> drive and use it on other machines without having to reboot.
>
Have you loaded and unloaded the module after booting the kernel but
before this has happened? If you have, the patch at the end of this
message should help. (This is the same patch posted to linux-scsi earlier
today).

The problem is that st_remove() did not call cdev_umap() before
cdev_del(). The device was deleted but it was left in a list where chrdev_open()
finds this non-existing device.

If you have not loaded and unloaded the st module after reboot, then you
have another problem.

(The patch is against 2.6.2-rc1 but it should apply also to 2.6.1. It also
solves the "sleeping function called from invalid context" bug.)

--
Kai
---------------------------------------8<--------------------------------------
--- linux-2.6.2-rc1/drivers/scsi/st.c 2004-01-20 20:16:20.000000000 +0200
+++ linux-2.6.2-rc1-k1/drivers/scsi/st.c 2004-01-22 23:16:04.000000000 +0200
@@ -9,7 +9,7 @@
Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,
Michael Schaefer, J"org Weule, and Eric Youngdale.

- Copyright 1992 - 2003 Kai Makisara
+ Copyright 1992 - 2004 Kai Makisara
email [email protected]

Some small formal changes - aeb, 950809
@@ -17,7 +17,7 @@
Last modified: 18-JAN-1998 Richard Gooch <[email protected]> Devfs support
*/

-static char *verstr = "20031228";
+static char *verstr = "20040122";

#include <linux/module.h>

@@ -3846,27 +3846,53 @@
STm->default_compression = ST_DONT_TOUCH;
STm->default_blksize = (-1); /* No forced size */
STm->default_density = (-1); /* No forced density */
+ }
+
+ for (i = 0; i < ST_NBR_PARTITIONS; i++) {
+ STps = &(tpnt->ps[i]);
+ STps->rw = ST_IDLE;
+ STps->eof = ST_NOEOF;
+ STps->at_sm = 0;
+ STps->last_block_valid = FALSE;
+ STps->drv_block = (-1);
+ STps->drv_file = (-1);
+ }
+
+ tpnt->current_mode = 0;
+ tpnt->modes[0].defined = TRUE;

+ tpnt->density_changed = tpnt->compression_changed =
+ tpnt->blksize_changed = FALSE;
+ init_MUTEX(&tpnt->lock);
+
+ st_nr_dev++;
+ write_unlock(&st_dev_arr_lock);
+
+ for (mode = 0; mode < ST_NBR_MODES; ++mode) {
+ STm = &(tpnt->modes[mode]);
for (j=0; j < 2; j++) {
cdev = cdev_alloc();
if (!cdev) {
printk(KERN_ERR
- "st: out of memory. Device not attached.\n");
- goto out_put_disk;
+ "st%d: out of memory. Device not attached.\n",
+ dev_num);
+ goto out_free_tape;
}
snprintf(cdev->kobj.name, KOBJ_NAME_LEN, "%sm%d%s", disk->disk_name,
- i, j ? "n" : "");
+ mode, j ? "n" : "");
cdev->owner = THIS_MODULE;
cdev->ops = &st_fops;
- STm->cdevs[j] = cdev;

- error = cdev_add(STm->cdevs[j],
- MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, i, j)),
+ error = cdev_add(cdev,
+ MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, j)),
1);
if (error) {
printk(KERN_ERR "st%d: Can't add %s-rewind mode %d\n",
- dev_num, j ? "non" : "auto", i);
+ dev_num, j ? "non" : "auto", mode);
+ printk(KERN_ERR "st%d: Device not attached.\n", dev_num);
+ goto out_free_tape;
}
+ STm->cdevs[j] = cdev;

error = sysfs_create_link(&STm->cdevs[j]->kobj, &SDp->sdev_gendev.kobj,
"device");
@@ -3884,35 +3910,15 @@
dev_num);
}

- for (i = 0; i < ST_NBR_PARTITIONS; i++) {
- STps = &(tpnt->ps[i]);
- STps->rw = ST_IDLE;
- STps->eof = ST_NOEOF;
- STps->at_sm = 0;
- STps->last_block_valid = FALSE;
- STps->drv_block = (-1);
- STps->drv_file = (-1);
- }
-
- tpnt->current_mode = 0;
- tpnt->modes[0].defined = TRUE;
-
- tpnt->density_changed = tpnt->compression_changed =
- tpnt->blksize_changed = FALSE;
- init_MUTEX(&tpnt->lock);
-
- st_nr_dev++;
- write_unlock(&st_dev_arr_lock);
-
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
- /* Rewind entry */
- devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5)),
- S_IFCHR | S_IRUGO | S_IWUGO,
- "%s/mt%s", SDp->devfs_name, st_formats[mode]);
- /* No-rewind entry */
- devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128),
- S_IFCHR | S_IRUGO | S_IWUGO,
- "%s/mt%sn", SDp->devfs_name, st_formats[mode]);
+ /* Rewind entry */
+ devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5)),
+ S_IFCHR | S_IRUGO | S_IWUGO,
+ "%s/mt%s", SDp->devfs_name, st_formats[mode]);
+ /* No-rewind entry */
+ devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128),
+ S_IFCHR | S_IRUGO | S_IWUGO,
+ "%s/mt%sn", SDp->devfs_name, st_formats[mode]);
}
disk->number = devfs_register_tape(SDp->devfs_name);

@@ -3924,18 +3930,30 @@

return 0;

+out_free_tape:
+ for (mode=0; mode < ST_NBR_MODES; mode++) {
+ STm = &(tpnt->modes[mode]);
+ for (j=0; j < 2; j++) {
+ if (STm->cdevs[j]) {
+ if (cdev == STm->cdevs[j])
+ cdev = NULL;
+ sysfs_remove_link(&STm->cdevs[j]->kobj, "device");
+ cdev_unmap(MKDEV(SCSI_TAPE_MAJOR,
+ TAPE_MINOR(dev_num, mode, j)), 1);
+ cdev_del(STm->cdevs[j]);
+ }
+ }
+ }
+ if (cdev)
+ kobject_put(&cdev->kobj);
+ write_lock(&st_dev_arr_lock);
+ scsi_tapes[dev_num] = NULL;
+ st_nr_dev--;
+ write_unlock(&st_dev_arr_lock);
out_put_disk:
put_disk(disk);
- if (tpnt) {
- for (i=0; i < ST_NBR_MODES; i++) {
- STm = &(tpnt->modes[i]);
- if (STm->cdevs[0])
- kobject_put(&STm->cdevs[0]->kobj);
- if (STm->cdevs[1])
- kobject_put(&STm->cdevs[1]->kobj);
- }
+ if (tpnt)
kfree(tpnt);
- }
out_buffer_free:
kfree(buffer);
out:
@@ -3964,6 +3982,8 @@
for (j=0; j < 2; j++) {
sysfs_remove_link(&tpnt->modes[mode].cdevs[j]->kobj,
"device");
+ cdev_unmap(MKDEV(SCSI_TAPE_MAJOR,
+ TAPE_MINOR(i, mode, j)), 1);
cdev_del(tpnt->modes[mode].cdevs[j]);
tpnt->modes[mode].cdevs[j] = NULL;
}