From: Elias Oltmanns <eo@nebensachen.de>
To: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org,
Jens Axboe <jens.axboe@oracle.com>
Subject: [PATCH 2/4] disk-protect: SCSI support for REQ_TYPE_LINUX_BLOCK requests
Date: Fri, 07 Mar 2008 19:25:48 +0100 [thread overview]
Message-ID: <20080307181750.9981.73383.stgit@denkblock.local> (raw)
In-Reply-To: 87bq5qfm2v.fsf@denkblock.local
Add the necessary infrastructure to the SCSI midlayer so it can handle
REQ_TYPE_LINUX_BLOCK requests. It is rather simple at this stage and may
have to be adapted as new REQ_LB_OP* commands are introduced.
Signed-off-by: Elias Oltmanns <eo@nebensachen.de>
---
drivers/scsi/scsi_lib.c | 56 ++++++++++++++++++++++++++++++++++++++++++++--
drivers/scsi/sd.c | 9 +++++++
include/linux/blkdev.h | 1 +
include/scsi/scsi_host.h | 22 ++++++++++++++++++
4 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index a9ac5b1..c25201b 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1448,12 +1448,30 @@ static void scsi_kill_request(struct request *req, struct request_queue *q)
__scsi_done(cmd);
}
+static void scsi_finish_lb_req(struct request *req)
+{
+ struct request_queue *q = req->q;
+ struct scsi_device *sdev = q->queuedata;
+ unsigned long flags;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ end_that_request_last(req, 1);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+ put_device(&sdev->sdev_gendev);
+}
+
static void scsi_softirq_done(struct request *rq)
{
struct scsi_cmnd *cmd = rq->completion_data;
- unsigned long wait_for = (cmd->allowed + 1) * cmd->timeout_per_command;
+ unsigned long wait_for;
int disposition;
+ if (blk_lb_request(rq)) {
+ scsi_finish_lb_req(rq);
+ return;
+ }
+
+ wait_for = (cmd->allowed + 1) * cmd->timeout_per_command;
INIT_LIST_HEAD(&cmd->eh_entry);
disposition = scsi_decide_disposition(cmd);
@@ -1483,6 +1501,24 @@ static void scsi_softirq_done(struct request *rq)
}
}
+static void scsi_exec_lb_req(struct request *req)
+{
+ struct scsi_device *sdev = req->q->queuedata;
+ struct scsi_host_template *shostt = sdev->host->hostt;
+ int rc;
+
+ if (shostt->lb_request_fn)
+ rc = shostt->lb_request_fn(req);
+ else
+ rc = FAILED;
+
+ if (rc == FAILED)
+ req->errors = -EIO;
+ else if (rc == QUEUED)
+ return;
+ blk_complete_request(req);
+}
+
/*
* Function: scsi_request_fn()
*
@@ -1525,7 +1561,23 @@ static void scsi_request_fn(struct request_queue *q)
* accept it.
*/
req = elv_next_request(q);
- if (!req || !scsi_dev_queue_ready(q, sdev))
+ if (!req)
+ break;
+
+ /*
+ * We do not account for linux blk req in the device
+ * or host busy accounting because it is not necessarily
+ * a scsi command that is sent to some object. The lower
+ * level can translate it into a request/scsi_cmnd, if
+ * necessary, and then queue that up using REQ_TYPE_BLOCK_PC.
+ */
+ if (blk_lb_request(req)) {
+ blkdev_dequeue_request(req);
+ scsi_exec_lb_req(req);
+ continue;
+ }
+
+ if (!scsi_dev_queue_ready(q, sdev))
break;
if (unlikely(!scsi_device_online(sdev))) {
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index cfd859a..1be9821 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -357,6 +357,15 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
ret = scsi_setup_blk_pc_cmnd(sdp, rq);
goto out;
+ } else if (rq->cmd_type == REQ_TYPE_LINUX_BLOCK) {
+ get_device(&sdp->sdev_gendev);
+ /*
+ * Since these requests don't need preparation, we'll
+ * basically just accept them unconditionally at this
+ * point.
+ */
+ ret = BLKPREP_OK;
+ goto out;
} else if (rq->cmd_type != REQ_TYPE_FS) {
ret = BLKPREP_KILL;
goto out;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index d18ee67..5955b57 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -521,6 +521,7 @@ enum {
#define blk_fs_request(rq) ((rq)->cmd_type == REQ_TYPE_FS)
#define blk_pc_request(rq) ((rq)->cmd_type == REQ_TYPE_BLOCK_PC)
+#define blk_lb_request(rq) ((rq)->cmd_type == REQ_TYPE_LINUX_BLOCK)
#define blk_special_request(rq) ((rq)->cmd_type == REQ_TYPE_SPECIAL)
#define blk_sense_request(rq) ((rq)->cmd_type == REQ_TYPE_SENSE)
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 0fd4746..c2946d0 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -8,6 +8,7 @@
#include <linux/mutex.h>
struct request_queue;
+struct request;
struct block_device;
struct completion;
struct module;
@@ -152,6 +153,27 @@ struct scsi_host_template {
void (*done)(struct scsi_cmnd *));
/*
+ * The lb_request_fn function is used to pass
+ * REQ_TYPE_LINUX_BLOCK requests to the LLDD. The return value
+ * FAILED indicates that the command opcode has not been known
+ * by lb_request_fn. In contrast, the return value SUCCESS
+ * means that the opcode has been recognised and the request
+ * has been processed accordingly. Note, however, that SUCCESS
+ * does not necessarily mean that all actions have been
+ * performed successfully; errors are recorded in req->errors.
+ * lb_request_fn can also return QUEUED in order to prevent
+ * midlayer from enqueueng the request for completion.
+ * Obviously, the LLDD must take care that the request will be
+ * completed by means of blk_complete_request eventually.
+ *
+ * Status: OPTIONAL
+ */
+ /* TODO: We might need to accept a return value NEEDS_RETRY some
+ * time.
+ */
+ int (* lb_request_fn)(struct request *req);
+
+ /*
* This is an error handling strategy routine. You don't need to
* define one of these if you don't want to - there is a default
* routine that is present that should work in most cases. For those
next prev parent reply other threads:[~2008-03-07 18:25 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-02-25 23:56 [RFC] Disk shock protection (revisited) Elias Oltmanns
2008-02-26 0:02 ` Jeff Garzik
2008-02-26 0:30 ` Elias Oltmanns
2008-02-26 1:33 ` Henrique de Moraes Holschuh
2008-02-26 12:39 ` Alan Cox
2008-02-28 8:24 ` Elias Oltmanns
2008-02-28 11:13 ` Alan Cox
2008-02-24 18:03 ` Pavel Machek
2008-02-28 17:00 ` Greg Freemyer
2008-03-07 18:03 ` Elias Oltmanns
2008-03-07 18:25 ` [PATCH 1/4] disk-protect: Add disk shock protection helpers to libata Elias Oltmanns
2008-03-15 12:39 ` Pavel Machek
2008-03-20 14:13 ` Alan Cox
2008-03-07 18:25 ` Elias Oltmanns [this message]
2008-03-07 18:26 ` [PATCH 3/4] disk-protect: Add a REQ_TYPE_LINUX_BLOCK request handler " Elias Oltmanns
2008-03-15 12:42 ` Pavel Machek
2008-03-07 18:26 ` [PATCH 4/4] disk-protect: Add a generic block layer queue freezing facility Elias Oltmanns
2008-03-15 12:49 ` Pavel Machek
2008-03-16 16:16 ` Elias Oltmanns
2008-03-17 23:00 ` Elias Oltmanns
2008-03-07 22:43 ` [RFC] Disk shock protection (revisited) Alan Cox
2008-03-13 14:51 ` Elias Oltmanns
2008-03-15 14:30 ` Alan Cox
2008-02-26 20:47 ` Willy Tarreau
2008-02-28 10:10 ` Elias Oltmanns
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=20080307181750.9981.73383.stgit@denkblock.local \
--to=eo@nebensachen.de \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=jens.axboe@oracle.com \
--cc=linux-ide@vger.kernel.org \
--cc=linux-kernel@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 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.