All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC/RFT 2/4] add scsi helpers
@ 2005-09-14 22:19 Mike Christie
  2005-09-15 10:13 ` Christoph Hellwig
  0 siblings, 1 reply; 5+ messages in thread
From: Mike Christie @ 2005-09-14 22:19 UTC (permalink / raw)
  To: linux-scsi

add scsi helper scsi_execute_async_iov_req() and
convert some functions to user it. 

Also add a __scsi_request struct that is only used internally
in scsi_lib.c for our request's end_io_data. Hopefully this will
be all that is left of scsi_request.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>

diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1366,23 +1366,6 @@ int scsi_decide_disposition(struct scsi_
 }
 
 /**
- * scsi_eh_lock_done - done function for eh door lock request
- * @scmd:	SCSI command block for the door lock request
- *
- * Notes:
- * 	We completed the asynchronous door lock request, and it has either
- * 	locked the door or failed.  We must free the command structures
- * 	associated with this request.
- **/
-static void scsi_eh_lock_done(struct scsi_cmnd *scmd)
-{
-	struct scsi_request *sreq = scmd->sc_request;
-
-	scsi_release_request(sreq);
-}
-
-
-/**
  * scsi_eh_lock_door - Prevent medium removal for the specified device
  * @sdev:	SCSI device to prevent medium removal
  *
@@ -1404,29 +1387,17 @@ static void scsi_eh_lock_done(struct scs
  **/
 static void scsi_eh_lock_door(struct scsi_device *sdev)
 {
-	struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
-
-	if (unlikely(!sreq)) {
-		printk(KERN_ERR "%s: request allocate failed,"
-		       "prevent media removal cmd not sent\n", __FUNCTION__);
-		return;
-	}
+	unsigned char cmnd[MAX_COMMAND_SIZE];
 
-	sreq->sr_cmnd[0] = ALLOW_MEDIUM_REMOVAL;
-	sreq->sr_cmnd[1] = 0;
-	sreq->sr_cmnd[2] = 0;
-	sreq->sr_cmnd[3] = 0;
-	sreq->sr_cmnd[4] = SCSI_REMOVAL_PREVENT;
-	sreq->sr_cmnd[5] = 0;
-	sreq->sr_data_direction = DMA_NONE;
-	sreq->sr_bufflen = 0;
-	sreq->sr_buffer = NULL;
-	sreq->sr_allowed = 5;
-	sreq->sr_done = scsi_eh_lock_done;
-	sreq->sr_timeout_per_command = 10 * HZ;
-	sreq->sr_cmd_len = COMMAND_SIZE(sreq->sr_cmnd[0]);
+	cmnd[0] = ALLOW_MEDIUM_REMOVAL;
+	cmnd[1] = 0;
+	cmnd[2] = 0;
+	cmnd[3] = 0;
+	cmnd[4] = SCSI_REMOVAL_PREVENT;
+	cmnd[5] = 0;
 
-	scsi_insert_special_req(sreq, 1);
+	scsi_execute_async_iov_req(sdev, cmnd, DMA_NONE, NULL, 0, 10 * HZ,
+				   5, NULL, NULL);
 }
 
 
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -63,39 +63,6 @@ static struct scsi_host_sg_pool scsi_sg_
 }; 	
 #undef SP
 
-
-/*
- * Function:    scsi_insert_special_req()
- *
- * Purpose:     Insert pre-formed request into request queue.
- *
- * Arguments:   sreq	- request that is ready to be queued.
- *              at_head	- boolean.  True if we should insert at head
- *                        of queue, false if we should insert at tail.
- *
- * Lock status: Assumed that lock is not held upon entry.
- *
- * Returns:     Nothing
- *
- * Notes:       This function is called from character device and from
- *              ioctl types of functions where the caller knows exactly
- *              what SCSI command needs to be issued.   The idea is that
- *              we merely inject the command into the queue (at the head
- *              for now), and then call the queue request function to actually
- *              process it.
- */
-int scsi_insert_special_req(struct scsi_request *sreq, int at_head)
-{
-	/*
-	 * Because users of this function are apt to reuse requests with no
-	 * modification, we have to sanitise the request flags here
-	 */
-	sreq->sr_request->flags &= ~REQ_DONTPREP;
-	blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request,
-		       	   at_head, sreq);
-	return 0;
-}
-
 static void scsi_run_queue(struct request_queue *q);
 static void scsi_release_buffers(struct scsi_cmnd *cmd);
 
@@ -254,8 +221,13 @@ void scsi_do_req(struct scsi_request *sr
 
 	/*
 	 * head injection *required* here otherwise quiesce won't work
+	 *
+	 * Because users of this function are apt to reuse requests with no
+	 * modification, we have to sanitise the request flags here
 	 */
-	scsi_insert_special_req(sreq, 1);
+	sreq->sr_request->flags &= ~REQ_DONTPREP;
+	blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request,
+		       	   1, sreq);
 }
 EXPORT_SYMBOL(scsi_do_req);
 
@@ -381,6 +353,68 @@ int scsi_execute_req(struct scsi_device 
 }
 EXPORT_SYMBOL(scsi_execute_req);
 
+struct __scsi_request {
+	void *data;
+	void (*done)(void *data, char *sense, int result, int resid);
+	char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+static void scsi_end_async_req(struct request *req)
+{
+	struct __scsi_request *sreq = req->end_io_data;
+
+	if (sreq->done)
+		sreq->done(sreq->data, sreq->sense, req->errors, req->data_len);
+
+	kfree(sreq);
+	__blk_put_request(req->q, req);
+}
+
+int scsi_execute_async_iov_req(struct scsi_device *sdev,
+			       const unsigned char *cmd, int data_direction,
+			       struct kvec *vec, int vec_count, int timeout,
+			       int retries, void *privdata,
+			       void (*done)(void *, char *, int, int))
+{
+	struct request *req;
+	struct __scsi_request *sreq;
+	int write = (data_direction == DMA_TO_DEVICE);
+
+	sreq = kzalloc(sizeof(*sreq), GFP_ATOMIC);
+	if (!sreq) {
+		return DRIVER_ERROR << 24;
+	}
+
+	req = blk_get_request(sdev->request_queue, write, GFP_ATOMIC);
+	if (!req)
+		goto free_sense;
+
+	if (vec && vec_count &&
+	    blk_rq_map_kern_iov(req->q, req, vec, vec_count, GFP_ATOMIC))
+		goto free_req;
+
+	req->cmd_len = COMMAND_SIZE(cmd[0]);
+	memcpy(req->cmd, cmd, req->cmd_len);
+	req->sense = sreq->sense;
+	req->sense_len = 0;
+	req->timeout = timeout;
+	req->flags |= REQ_BLOCK_PC | REQ_QUIET;
+	req->end_io_data = sreq;
+
+	sreq->data = privdata;
+	sreq->done = done;
+
+	blk_execute_rq_nowait(req->q, NULL, req, 1, scsi_end_async_req);
+	return 0;
+
+free_req:
+	blk_put_request(req);
+free_sense:
+	kfree(sreq);
+	return DRIVER_ERROR << 24;
+}
+EXPORT_SYMBOL_GPL(scsi_execute_async_iov_req);
+
 /*
  * Function:    scsi_init_cmd_errh()
  *
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -41,7 +41,6 @@ extern void scsi_exit_hosts(void);
 extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
 extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
 extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
-extern int scsi_insert_special_req(struct scsi_request *sreq, int);
 extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd,
 		struct scsi_request *sreq);
 extern void __scsi_release_request(struct scsi_request *sreq);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -264,6 +264,11 @@ extern int scsi_execute(struct scsi_devi
 extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
 			    int data_direction, void *buffer, unsigned bufflen,
 			    struct scsi_sense_hdr *, int timeout, int retries);
+extern int scsi_execute_async_iov_req(struct scsi_device *sdev,
+				  const unsigned char *cmd, int data_direction,
+				  struct kvec *vec, int vec_count,
+				  int timeout, int retries, void *data,
+				  void (*done)(void *, char *, int, int));
 
 static inline int scsi_device_online(struct scsi_device *sdev)
 {



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

* Re: [PATCH RFC/RFT 2/4] add scsi helpers
  2005-09-14 22:19 [PATCH RFC/RFT 2/4] add scsi helpers Mike Christie
@ 2005-09-15 10:13 ` Christoph Hellwig
  2005-09-15 17:30   ` Mike Christie
  0 siblings, 1 reply; 5+ messages in thread
From: Christoph Hellwig @ 2005-09-15 10:13 UTC (permalink / raw)
  To: Mike Christie; +Cc: linux-scsi

> +struct __scsi_request {
> +	void *data;
> +	void (*done)(void *data, char *sense, int result, int resid);
> +	char sense[SCSI_SENSE_BUFFERSIZE];
> +};

I don't think this is a good structure name.  Just something like
iocontext  or similar?

> +int scsi_execute_async_iov_req(struct scsi_device *sdev,
> +			       const unsigned char *cmd, int data_direction,
> +			       struct kvec *vec, int vec_count, int timeout,
> +			       int retries, void *privdata,
> +			       void (*done)(void *, char *, int, int))

If you passed an request_queue_t instead of th scsi_device this function
would not have any knowledge about scsi internals and could be moved up
to the block layer.  not sure that's actually a good idea.

If we stick to putting it into the scsi layer the done callback could
normalize the sense data, though.

> +	struct request *req;
> +	struct __scsi_request *sreq;
> +	int write = (data_direction == DMA_TO_DEVICE);

What about just passing in a write parameter directly?

> +
> +	sreq = kzalloc(sizeof(*sreq), GFP_ATOMIC);
> +	if (!sreq) {
> +		return DRIVER_ERROR << 24;
> +	}
> +
> +	req = blk_get_request(sdev->request_queue, write, GFP_ATOMIC);

can you add a gfp_mask argument instead of hardcoding GFP_ATOMIC?


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

* Re: [PATCH RFC/RFT 2/4] add scsi helpers
  2005-09-15 10:13 ` Christoph Hellwig
@ 2005-09-15 17:30   ` Mike Christie
  2005-09-15 17:55     ` Mike Christie
  0 siblings, 1 reply; 5+ messages in thread
From: Mike Christie @ 2005-09-15 17:30 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-scsi

Christoph Hellwig wrote:
>>+struct __scsi_request {
>>+	void *data;
>>+	void (*done)(void *data, char *sense, int result, int resid);
>>+	char sense[SCSI_SENSE_BUFFERSIZE];
>>+};
> 
> 
> I don't think this is a good structure name.  Just something like
> iocontext  or similar?

ok.

> 
> 
>>+int scsi_execute_async_iov_req(struct scsi_device *sdev,
>>+			       const unsigned char *cmd, int data_direction,
>>+			       struct kvec *vec, int vec_count, int timeout,
>>+			       int retries, void *privdata,
>>+			       void (*done)(void *, char *, int, int))
> 
> 
> If you passed an request_queue_t instead of th scsi_device this function
> would not have any knowledge about scsi internals and could be moved up
> to the block layer.  not sure that's actually a good idea.

Did you want to move scsi_execute too?


> 
> If we stick to putting it into the scsi layer the done callback could
> normalize the sense data, though.
> 
> 
>>+	struct request *req;
>>+	struct __scsi_request *sreq;
>>+	int write = (data_direction == DMA_TO_DEVICE);
> 
> 
> What about just passing in a write parameter directly?

I thought most users would just have the DMA_* value so it would be 
nicer for them to pass that down. It also then works like 
scsi_execute_req/scsi_execute. I guess if we move one of those functions 
to the block layer it would be better to pass in write/read for the 
block layer versions.


> 
> 
>>+
>>+	sreq = kzalloc(sizeof(*sreq), GFP_ATOMIC);
>>+	if (!sreq) {
>>+		return DRIVER_ERROR << 24;
>>+	}
>>+
>>+	req = blk_get_request(sdev->request_queue, write, GFP_ATOMIC);
> 
> 
> can you add a gfp_mask argument instead of hardcoding GFP_ATOMIC?
> 

yeah will do. I think I got lazy :)

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

* Re: [PATCH RFC/RFT 2/4] add scsi helpers
  2005-09-15 17:30   ` Mike Christie
@ 2005-09-15 17:55     ` Mike Christie
  2005-09-15 18:29       ` Christoph Hellwig
  0 siblings, 1 reply; 5+ messages in thread
From: Mike Christie @ 2005-09-15 17:55 UTC (permalink / raw)
  To: Mike Christie; +Cc: Christoph Hellwig, linux-scsi

Mike Christie wrote:
>>
>>
>>> +int scsi_execute_async_iov_req(struct scsi_device *sdev,
>>> +                   const unsigned char *cmd, int data_direction,
>>> +                   struct kvec *vec, int vec_count, int timeout,
>>> +                   int retries, void *privdata,
>>> +                   void (*done)(void *, char *, int, int))
>>
>>
>>
>> If you passed an request_queue_t instead of th scsi_device this function
>> would not have any knowledge about scsi internals and could be moved up
>> to the block layer.  not sure that's actually a good idea.
> 
> 
> Did you want to move scsi_execute too?
> 

Actually after talking with Jens, I think it is better to keep the 
function in scsi_lib and move my blk_rq_map_iov() function there. The 
problem is that sg and st have some special needs and as a result do 
some things like partial setup themselves. It looks like nobody wants 
the burdon of having these special case fucntions :) but since SCSI's 
ULDs are the only user and probably will be the only user does it make 
sense to keep them there?

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

* Re: [PATCH RFC/RFT 2/4] add scsi helpers
  2005-09-15 17:55     ` Mike Christie
@ 2005-09-15 18:29       ` Christoph Hellwig
  0 siblings, 0 replies; 5+ messages in thread
From: Christoph Hellwig @ 2005-09-15 18:29 UTC (permalink / raw)
  To: Mike Christie; +Cc: Christoph Hellwig, linux-scsi

On Thu, Sep 15, 2005 at 12:55:18PM -0500, Mike Christie wrote:
> Actually after talking with Jens, I think it is better to keep the 
> function in scsi_lib and move my blk_rq_map_iov() function there. The 
> problem is that sg and st have some special needs and as a result do 
> some things like partial setup themselves. It looks like nobody wants 
> the burdon of having these special case fucntions :) but since SCSI's 
> ULDs are the only user and probably will be the only user does it make 
> sense to keep them there?

ok, makes sense

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

end of thread, other threads:[~2005-09-15 18:29 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-14 22:19 [PATCH RFC/RFT 2/4] add scsi helpers Mike Christie
2005-09-15 10:13 ` Christoph Hellwig
2005-09-15 17:30   ` Mike Christie
2005-09-15 17:55     ` Mike Christie
2005-09-15 18:29       ` Christoph Hellwig

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.