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/0x71bad: 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
Quoted 7 lines · Darren Dupre
I was about to do a tape backup, so I did the following:
modprobe advansys (automaticaly loads
scsi_modfirst)tar --exclude=/sys --exclude=/proc --exclude=/mnt -cvf
/dev/st0/ which results in a segmentation fault as soon as tar is executed.
Quoted 7 lines
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.)
Signature · 176 lines
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;
}