All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] IDE: Fix HDIO_DRIVE_RESET handling
@ 2008-06-18 23:35 Elias Oltmanns
  2008-06-18 23:41 ` Elias Oltmanns
  2008-06-19 20:47 ` Bartlomiej Zolnierkiewicz
  0 siblings, 2 replies; 30+ messages in thread
From: Elias Oltmanns @ 2008-06-18 23:35 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz; +Cc: linux-ide

Hi Bart,

currently, the code path executing an HDIO_DRIVE_RESET ioctl is broken
in various ways.  Firstly, ide_abort() is called with the ide_lock held
and may call ide_end_request() further down the line which will try to
grab the same lock again.  More importantly though, the whole concept of
aborting an inflight request is flawed -- at least as far as ide_abort()
is concerned.

The patch below tries to address these issues by handling the
HDIO_DRIVE_RESET ioctl in-band.  I wonder whether this approach is
acceptable and may be extended to other applications like a modified
version of the disk shock protection patches.  Also, I abstained from
using op codes 0x0 to 0x1f since at least part of this range is used by
ULDs like ide-floppy, ide-tape, etc.  On the other hand, there really
should be no conflict because those ULDs will always set ->rq_disk thus
preventing ide_special_rq() from snatching away what should be passed on
to ->do_request().  So, what's you're advice on this one?  Finally,
shouldn't op codes like REQ_DRIVE_RESET really be declared in a private
header file in drivers/ide/?

Signed-off-by: Elias Oltmanns <eo@nebensachen.de>
---

 drivers/ide/ide-io.c |   16 +++++++++++++++-
 drivers/ide/ide.c    |   40 ++++++++++++++--------------------------
 include/linux/ide.h  |    6 ++++++
 3 files changed, 35 insertions(+), 27 deletions(-)

diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 6965253..b3a37b1 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -788,6 +788,19 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
  	return ide_stopped;
 }
 
+static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
+{
+	switch (rq->cmd[0]) {
+	case REQ_DRIVE_RESET:
+		ide_end_request(drive, 1, 0);
+		return ide_do_reset(drive);
+	default:
+		blk_dump_rq_flags(rq, "ide_special_rq - bad request");
+		ide_end_request(drive, 0, 0);
+		return ide_stopped;
+	}
+}
+
 static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
 {
 	struct request_pm_state *pm = rq->data;
@@ -891,7 +904,8 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
 			    pm->pm_step == ide_pm_state_completed)
 				ide_complete_pm_request(drive, rq);
 			return startstop;
-		}
+		} else if (!rq->rq_disk && blk_special_request(rq))
+			return ide_special_rq(drive, rq);
 
 		drv = *(ide_driver_t **)rq->rq_disk->private_data;
 		return drv->do_request(drive, rq, block);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index c758dcb..4f9c796 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -623,6 +623,19 @@ static int generic_ide_resume(struct device *dev)
 	return err;
 }
 
+static void generic_drive_reset(ide_drive_t *drive)
+{
+	struct request *rq;
+
+	rq = blk_get_request(drive->queue, 0, __GFP_WAIT);
+	/* Should we call ide_init_drive_cmd() here? */
+
+	rq->cmd[0] = REQ_DRIVE_RESET;
+	rq->cmd_type = REQ_TYPE_SPECIAL;
+	rq->cmd_flags |= REQ_SOFTBARRIER;
+	ide_do_drive_cmd(drive, rq, ide_end);
+}
+
 int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
 			unsigned int cmd, unsigned long arg)
 {
@@ -697,32 +710,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
 			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
 
-			/*
-			 *	Abort the current command on the
-			 *	group if there is one, taking
-			 *	care not to allow anything else
-			 *	to be queued and to die on the
-			 *	spot if we miss one somehow
-			 */
-
-			spin_lock_irqsave(&ide_lock, flags);
-
-			if (HWGROUP(drive)->resetting) {
-				spin_unlock_irqrestore(&ide_lock, flags);
-				return -EBUSY;
-			}
-
-			ide_abort(drive, "drive reset");
-
-			BUG_ON(HWGROUP(drive)->handler);
-
-			/* Ensure nothing gets queued after we
-			   drop the lock. Reset will clear the busy */
-
-			HWGROUP(drive)->busy = 1;
-			spin_unlock_irqrestore(&ide_lock, flags);
-			(void) ide_do_reset(drive);
-
+			generic_drive_reset(drive);
 			return 0;
 		case HDIO_GET_BUSSTATE:
 			if (!capable(CAP_SYS_ADMIN))
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 9918772..4c3e802 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -842,6 +842,12 @@ int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long);
 
 extern ide_startstop_t ide_do_reset (ide_drive_t *);
 
+/*
+ * Op codes for special requests to be handled by ide_special_rq().
+ * Values should be in the range of 0x20 to 0x3f.
+ */
+#define REQ_DRIVE_RESET		0x20
+
 extern void ide_init_drive_cmd (struct request *rq);
 
 /*

^ permalink raw reply related	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2008-06-25 20:33 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-18 23:35 [PATCH] IDE: Fix HDIO_DRIVE_RESET handling Elias Oltmanns
2008-06-18 23:41 ` Elias Oltmanns
2008-06-19 20:47 ` Bartlomiej Zolnierkiewicz
2008-06-22 23:23   ` Elias Oltmanns
2008-06-22 23:28     ` Elias Oltmanns
2008-06-23  7:47       ` Elias Oltmanns
2008-06-23 22:47         ` Bartlomiej Zolnierkiewicz
2008-06-23  9:16       ` Alan Cox
2008-06-24  7:02         ` Elias Oltmanns
2008-06-24  9:10           ` Alan Cox
2008-06-23 22:41       ` Bartlomiej Zolnierkiewicz
2008-06-24  7:12         ` Elias Oltmanns
2008-06-22 23:32     ` [PATCH 2/4] IDE: Remove unused code Elias Oltmanns
2008-06-22 23:35     ` [PATCH 3/4] Update documentation of HDIO_DRIVE_RESET ioctl Elias Oltmanns
2008-06-22 23:38     ` [PATCH 4/4] IDE: Report errors during drive reset back to user space Elias Oltmanns
2008-06-23  9:18     ` [PATCH] IDE: Fix HDIO_DRIVE_RESET handling Alan Cox
2008-06-23 22:41     ` Bartlomiej Zolnierkiewicz
2008-06-24  7:23       ` Elias Oltmanns
2008-06-24 11:06         ` Bartlomiej Zolnierkiewicz
2008-06-24 12:32           ` Alan Cox
2008-06-24 13:21             ` Bartlomiej Zolnierkiewicz
2008-06-24 13:35               ` Alan Cox
2008-06-24 14:19                 ` Bartlomiej Zolnierkiewicz
2008-06-24 14:33                   ` Bartlomiej Zolnierkiewicz
2008-06-25 11:23                   ` Elias Oltmanns
2008-06-25 11:27                     ` [PATCH 1/4 v2] " Elias Oltmanns
2008-06-25 11:28                     ` [PATCH 2/4 v2] IDE: Remove unused code Elias Oltmanns
2008-06-25 11:29                     ` [PATCH 3/4 v2] Update documentation of HDIO_DRIVE_RESET ioctl Elias Oltmanns
2008-06-25 11:30                     ` [PATCH 4/4 v2] IDE: Report errors during drive reset back to user space Elias Oltmanns
2008-06-25 20:24                     ` [PATCH] IDE: Fix HDIO_DRIVE_RESET handling Bartlomiej Zolnierkiewicz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.