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 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).