From: Elias Oltmanns <eo@nebensachen.de>
To: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Cc: linux-ide@vger.kernel.org
Subject: [PATCH] IDE: Fix HDIO_DRIVE_RESET handling
Date: Thu, 19 Jun 2008 01:35:01 +0200 [thread overview]
Message-ID: <87k5gmz596.fsf@denkblock.local> (raw)
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);
/*
next reply other threads:[~2008-06-18 23:35 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-18 23:35 Elias Oltmanns [this message]
2008-06-18 23:41 ` [PATCH] IDE: Fix HDIO_DRIVE_RESET handling 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87k5gmz596.fsf@denkblock.local \
--to=eo@nebensachen.de \
--cc=bzolnier@gmail.com \
--cc=linux-ide@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).