From: Ingo Molnar Date: Mon, 26 Jun 2006 07:26:17 +0000 (-0700) Subject: [PATCH] fix IDE deadlock in error reporting code X-Git-Tag: v2.6.18-rc1~728 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d1c1cc962cebaae6a70fd89a0adb29ad10a2a12;p=linux-2.6 [PATCH] fix IDE deadlock in error reporting code Michal Piotrowski reported the following validator assert: hdd: set_drive_speed_status: status=0x51 { DriveReady SeekComplete Error } hdd: set_drive_speed_status: error=0xb4 { AbortedCommand LastFailedSense=0x0b } ============================ [ BUG: illegal lock usage! ] ---------------------------- illegal {in-hardirq-W} -> {hardirq-on-W} usage. hdparm/1821 [HC0[0]:SC0[0]:HE1:SE1] takes: (ide_lock){++..}, at: [] ide_dump_opcode+0x13/0x9b [...] stack backtrace: [] show_trace+0x1b/0x20 [] dump_stack+0x1f/0x24 [] print_usage_bug+0x1a5/0x1b1 [] mark_lock+0x2ca/0x4f7 [] __lockdep_acquire+0x47e/0xaa4 [] lockdep_acquire+0x67/0x7f [] _spin_lock+0x24/0x32 [] ide_dump_opcode+0x13/0x9b [] ide_dump_status+0x4a6/0x4cc [] ide_config_drive_speed+0x32a/0x33a [] piix_tune_chipset+0x2ed/0x2f8 [] piix_config_drive_xfer_rate+0x61/0xb5 [] set_using_dma+0x2f/0x60 [] ide_write_setting+0x4a/0xc3 [] generic_ide_ioctl+0x8a/0x47f [] idecd_ioctl+0xfd/0x133 [ide_cd] [] blkdev_driver_ioctl+0x4b/0x5f [] blkdev_ioctl+0x770/0x7bd [] block_ioctl+0x1f/0x21 [] do_ioctl+0x27/0x6e [] vfs_ioctl+0x26a/0x280 [] sys_ioctl+0x4d/0x7e [] sysenter_past_esp+0x63/0xa1 in ide_dump_opcode() takes the ide_lock in an irq-unsafe manner, i.e. this function expects to be called with irqs disabled. But ide_dump_ata[pi]_status() doesnt do that - it enables interrupts specifically. That is a no-no - what guarantees that another IDE port couldnt generate an IDE interrupt while we are dumping this error? The fix is to turn the irq-enabling in these functions into irq-disabling. Signed-off-by: Ingo Molnar Cc: Michal Piotrowski Cc: Alan Cox Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 16a143133f..7ddb118287 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -485,7 +485,7 @@ static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat) unsigned long flags; u8 err = 0; - local_irq_set(flags); + local_irq_save(flags); printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); if (stat & BUSY_STAT) printk("Busy "); @@ -567,7 +567,7 @@ static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat) status.all = stat; error.all = 0; - local_irq_set(flags); + local_irq_save(flags); printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); if (status.b.bsy) printk("Busy ");