aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide.c
diff options
context:
space:
mode:
authorElias Oltmanns <eo@nebensachen.de>2008-07-16 14:33:48 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-07-16 14:33:48 -0400
commit79e36a9f54aaf4a52eb2d9520953aa3960e99294 (patch)
tree70fae17d64a1facde8541184d7139c4bc12d03bf /drivers/ide/ide.c
parent72a3d651b2fe341a8ae2ca164c395aa3007350cd (diff)
IDE: Fix HDIO_DRIVE_RESET handling
Currently, the code path executing an HDIO_DRIVE_RESET ioctl is broken in various ways. Most importantly, it is treated as an out of band request in an illegal way which may very likely lead to system lock ups. Use the drive's request queue to avoid this problem (and fix a locking issue for free along the way). Signed-off-by: Elias Oltmanns <eo@nebensachen.de> Cc: "Alan Cox" <alan@lxorguk.ukuu.org.uk> Cc: "Randy Dunlap" <randy.dunlap@oracle.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r--drivers/ide/ide.c41
1 files changed, 15 insertions, 26 deletions
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 90ae00d4aaf5..1ec983b00511 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -529,6 +529,19 @@ static int generic_ide_resume(struct device *dev)
529 return err; 529 return err;
530} 530}
531 531
532static void generic_drive_reset(ide_drive_t *drive)
533{
534 struct request *rq;
535
536 rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
537 rq->cmd_type = REQ_TYPE_SPECIAL;
538 rq->cmd_len = 1;
539 rq->cmd[0] = REQ_DRIVE_RESET;
540 rq->cmd_flags |= REQ_SOFTBARRIER;
541 blk_execute_rq(drive->queue, NULL, rq, 1);
542 blk_put_request(rq);
543}
544
532int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, 545int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
533 unsigned int cmd, unsigned long arg) 546 unsigned int cmd, unsigned long arg)
534{ 547{
@@ -603,33 +616,9 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
603 if (!capable(CAP_SYS_ADMIN)) 616 if (!capable(CAP_SYS_ADMIN))
604 return -EACCES; 617 return -EACCES;
605 618
606 /* 619 generic_drive_reset(drive);
607 * Abort the current command on the
608 * group if there is one, taking
609 * care not to allow anything else
610 * to be queued and to die on the
611 * spot if we miss one somehow
612 */
613
614 spin_lock_irqsave(&ide_lock, flags);
615
616 if (HWGROUP(drive)->resetting) {
617 spin_unlock_irqrestore(&ide_lock, flags);
618 return -EBUSY;
619 }
620
621 ide_abort(drive, "drive reset");
622
623 BUG_ON(HWGROUP(drive)->handler);
624
625 /* Ensure nothing gets queued after we
626 drop the lock. Reset will clear the busy */
627
628 HWGROUP(drive)->busy = 1;
629 spin_unlock_irqrestore(&ide_lock, flags);
630 (void) ide_do_reset(drive);
631
632 return 0; 620 return 0;
621
633 case HDIO_GET_BUSSTATE: 622 case HDIO_GET_BUSSTATE:
634 if (!capable(CAP_SYS_ADMIN)) 623 if (!capable(CAP_SYS_ADMIN))
635 return -EACCES; 624 return -EACCES;