| From stable-bounces@linux.kernel.org Tue May 13 12:10:47 2008 |
| From: James Bottomley <James.Bottomley@HansenPartnership.com> |
| Date: Tue, 13 May 2008 19:10:15 GMT |
| Subject: SCSI: aha152x: Fix oops on module removal |
| To: jejb@kernel.org, stable@kernel.org |
| Message-ID: <200805131910.m4DJAFIr007608@hera.kernel.org> |
| |
| From: James Bottomley <James.Bottomley@HansenPartnership.com> |
| |
| commit 64976a0387835a7ac61bbe2a99b27ccae34eac5d upstream |
| |
| Reported-by: Frank de Jong <frapex@xs4all.nl> |
| > after trying to unload the module: |
| > BUG: unable to handle kernel paging request at 00100100 |
| > IP: [<fb9ff667>] :aha152x:aha152x_exit+0x47/0x6a |
| > *pde = 00000000 |
| > Oops: 0000 [#1] PREEMPT SMP |
| > Modules linked in: aha152x(-) w83781d hwmon_vid tun ne 8390 bonding |
| > usb_storage snd_usb_audio snd_usb_lib snd_rawmidi pwc snd_seq_device |
| > compat_ioctl32 snd_hwdep videodev v4l1_compat 3c59x mii intel_agp |
| > agpgart snd_pcm_oss snd_pcm snd_timer snd_page_alloc snd_mixer_oss snd |
| > |
| > Pid: 2837, comm: rmmod Not tainted (2.6.25.3 #1) |
| > EIP: 0060:[<fb9ff667>] EFLAGS: 00210212 CPU: 0 |
| > EIP is at aha152x_exit+0x47/0x6a [aha152x] |
| > EAX: 00000001 EBX: 000ffdc4 ECX: f7c517a8 EDX: 00000001 |
| > ESI: 00000000 EDI: 00000003 EBP: e7880000 ESP: e7881f58 |
| > DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 |
| > Process rmmod (pid: 2837, ti=e7880000 task=f27eb580 task.ti=e7880000) |
| > Stack: fba03700 c01419d2 31616861 00783235 e795ee70 c0157709 b7f24000 e79ae000 |
| > c0158271 ffffffff b7f25000 e79ae004 e795e370 b7f25000 e795e37c e795e370 |
| > 009ae000 fba03700 00000880 e7881fa8 00000000 bf93ec20 bf93ec20 c0102faa |
| > Call Trace: |
| > [<c01419d2>] sys_delete_module+0x112/0x1a0 |
| > [<c0157709>] remove_vma+0x39/0x50 |
| > [<c0158271>] do_munmap+0x181/0x1f0 |
| > [<c0102faa>] sysenter_past_esp+0x5f/0x85 |
| > [<c0490000>] rsc_parse+0x0/0x3c0 |
| |
| The problem is that the driver calls aha152x_release() under a |
| list_for_each_entry(). Unfortunately, aha152x_release() deletes from |
| the list in question. Fix this by using list_for_each_entry_safe(). |
| |
| Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/scsi/aha152x.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/scsi/aha152x.c |
| +++ b/drivers/scsi/aha152x.c |
| @@ -3919,9 +3919,9 @@ static int __init aha152x_init(void) |
| |
| static void __exit aha152x_exit(void) |
| { |
| - struct aha152x_hostdata *hd; |
| + struct aha152x_hostdata *hd, *tmp; |
| |
| - list_for_each_entry(hd, &aha152x_host_list, host_list) { |
| + list_for_each_entry_safe(hd, tmp, &aha152x_host_list, host_list) { |
| struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata); |
| |
| aha152x_release(shost); |