Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IDE: Report errors during drive reset back to user space

Make sure that each error condition during the execution of an
HDIO_DRIVE_RESET ioctl is actually reported to the calling process.
Also, unify the exit path of reset_pollfunc() when returning ide_stopped
since the need of ->port_ops->reset_poll() to be treated specially has
vanished (way back, it seems).

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>

authored by

Elias Oltmanns and committed by
Bartlomiej Zolnierkiewicz
64a8f00f bb7ee9b1

+20 -13
+2
Documentation/ioctl/hdio.txt
··· 508 508 509 509 error returns: 510 510 EACCES Access denied: requires CAP_SYS_ADMIN 511 + ENXIO No such device: phy dead or ctl_addr == 0 512 + EIO I/O error: reset timed out or hardware error 511 513 512 514 notes: 513 515
+11 -7
drivers/ide/ide-iops.c
··· 905 905 } 906 906 EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); 907 907 908 - static inline void ide_complete_drive_reset(ide_drive_t *drive) 908 + static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) 909 909 { 910 910 struct request *rq = drive->hwif->hwgroup->rq; 911 911 912 912 if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) 913 - ide_end_request(drive, 1, 0); 913 + ide_end_request(drive, err ? err : 1, 0); 914 914 } 915 915 916 916 /* needed below */ ··· 948 948 } 949 949 /* done polling */ 950 950 hwgroup->polling = 0; 951 - ide_complete_drive_reset(drive); 951 + ide_complete_drive_reset(drive, 0); 952 952 return ide_stopped; 953 953 } 954 954 ··· 964 964 ide_hwif_t *hwif = HWIF(drive); 965 965 const struct ide_port_ops *port_ops = hwif->port_ops; 966 966 u8 tmp; 967 + int err = 0; 967 968 968 969 if (port_ops && port_ops->reset_poll) { 969 - if (port_ops->reset_poll(drive)) { 970 + err = port_ops->reset_poll(drive); 971 + if (err) { 970 972 printk(KERN_ERR "%s: host reset_poll failure for %s.\n", 971 973 hwif->name, drive->name); 972 974 goto out; ··· 985 983 } 986 984 printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); 987 985 drive->failures++; 986 + err = -EIO; 988 987 } else { 989 988 printk("%s: reset: ", hwif->name); 990 989 tmp = ide_read_error(drive); ··· 1012 1009 if (tmp & 0x80) 1013 1010 printk("; slave: failed"); 1014 1011 printk("\n"); 1012 + err = -EIO; 1015 1013 } 1016 1014 } 1017 - hwgroup->polling = 0; /* done polling */ 1018 1015 out: 1019 - ide_complete_drive_reset(drive); 1016 + hwgroup->polling = 0; /* done polling */ 1017 + ide_complete_drive_reset(drive, err); 1020 1018 return ide_stopped; 1021 1019 } 1022 1020 ··· 1124 1120 1125 1121 if (io_ports->ctl_addr == 0) { 1126 1122 spin_unlock_irqrestore(&ide_lock, flags); 1127 - ide_complete_drive_reset(drive); 1123 + ide_complete_drive_reset(drive, -ENXIO); 1128 1124 return ide_stopped; 1129 1125 } 1130 1126
+6 -4
drivers/ide/ide.c
··· 529 529 return err; 530 530 } 531 531 532 - static void generic_drive_reset(ide_drive_t *drive) 532 + static int generic_drive_reset(ide_drive_t *drive) 533 533 { 534 534 struct request *rq; 535 + int ret = 0; 535 536 536 537 rq = blk_get_request(drive->queue, READ, __GFP_WAIT); 537 538 rq->cmd_type = REQ_TYPE_SPECIAL; 538 539 rq->cmd_len = 1; 539 540 rq->cmd[0] = REQ_DRIVE_RESET; 540 541 rq->cmd_flags |= REQ_SOFTBARRIER; 541 - blk_execute_rq(drive->queue, NULL, rq, 1); 542 + if (blk_execute_rq(drive->queue, NULL, rq, 1)) 543 + ret = rq->errors; 542 544 blk_put_request(rq); 545 + return ret; 543 546 } 544 547 545 548 int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, ··· 619 616 if (!capable(CAP_SYS_ADMIN)) 620 617 return -EACCES; 621 618 622 - generic_drive_reset(drive); 623 - return 0; 619 + return generic_drive_reset(drive); 624 620 625 621 case HDIO_GET_BUSSTATE: 626 622 if (!capable(CAP_SYS_ADMIN))
+1 -2
drivers/ide/pci/siimage.c
··· 421 421 if ((sata_stat & 0x03) != 0x03) { 422 422 printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", 423 423 hwif->name, sata_stat); 424 - HWGROUP(drive)->polling = 0; 425 - return ide_started; 424 + return -ENXIO; 426 425 } 427 426 } 428 427