diff mbox

[7/7] block: allocate block_pc data separate from struct request

Message ID 1429303042-12078-8-git-send-email-hch@lst.de (mailing list archive)
State New, archived
Headers show

Commit Message

Christoph Hellwig April 17, 2015, 8:37 p.m. UTC
Don't bloat struct request with BLOCK_PC specific fields.

WIP, breaks dm BLOCK_PC passthrough and the old IDE driver for now.
---
 block/blk-core.c                            | 23 ++++++---
 block/blk-exec.c                            | 17 -------
 block/blk-mq.c                              |  4 --
 block/bsg-lib.c                             | 10 ++--
 block/bsg.c                                 | 31 ++++--------
 block/scsi_ioctl.c                          | 68 +++++++++++--------------
 drivers/ata/libata-scsi.c                   |  2 +-
 drivers/block/pktcdvd.c                     |  9 ++--
 drivers/block/virtio_blk.c                  |  9 ++--
 drivers/cdrom/cdrom.c                       | 36 +++++++------
 drivers/md/dm.c                             |  4 ++
 drivers/message/fusion/mptsas.c             |  4 +-
 drivers/scsi/device_handler/scsi_dh_alua.c  | 78 ++++++++++++++---------------
 drivers/scsi/device_handler/scsi_dh_emc.c   | 52 +++++++++----------
 drivers/scsi/device_handler/scsi_dh_hp_sw.c | 38 ++++++++------
 drivers/scsi/device_handler/scsi_dh_rdac.c  | 43 ++++++++--------
 drivers/scsi/mpt2sas/mpt2sas_transport.c    |  4 +-
 drivers/scsi/mpt3sas/mpt3sas_transport.c    |  4 +-
 drivers/scsi/osd/osd_initiator.c            | 32 ++++++------
 drivers/scsi/osst.c                         | 10 ++--
 drivers/scsi/qla2xxx/qla_bsg.c              |  2 +-
 drivers/scsi/qla2xxx/qla_isr.c              |  6 ++-
 drivers/scsi/qla2xxx/qla_mr.c               |  2 +-
 drivers/scsi/scsi_error.c                   | 22 ++++----
 drivers/scsi/scsi_lib.c                     | 22 ++++----
 drivers/scsi/scsi_transport_fc.c            | 10 ++--
 drivers/scsi/sd.c                           | 47 ++---------------
 drivers/scsi/sg.c                           | 21 +++-----
 drivers/scsi/st.c                           | 21 ++++----
 drivers/target/target_core_pscsi.c          | 14 +++---
 include/linux/blkdev.h                      | 27 ++++++----
 include/linux/blktrace_api.h                |  4 +-
 include/scsi/scsi_cmnd.h                    |  2 +-
 kernel/trace/blktrace.c                     | 11 ++--
 34 files changed, 319 insertions(+), 370 deletions(-)

Comments

Boaz Harrosh May 6, 2015, 11:46 a.m. UTC | #1
On 04/17/2015 11:37 PM, Christoph Hellwig wrote:
> Don't bloat struct request with BLOCK_PC specific fields.
> 
> WIP, breaks dm BLOCK_PC passthrough and the old IDE driver for now.
<>
> diff --git a/block/blk-core.c b/block/blk-core.c
> index 2e5020f..5d78a85 100644
> --- a/block/blk-core.c
> +++ b/block/blk-core.c
<>
> @@ -1274,15 +1270,24 @@ EXPORT_SYMBOL(blk_make_request);
>  /**
>   * blk_rq_set_block_pc - initialize a request to type BLOCK_PC
>   * @rq:		request to be initialized
> + * @cmd_len:	length of the CDB
> + * @gfp:	kmalloc flags
>   *
>   */
> -void blk_rq_set_block_pc(struct request *rq)
> +int blk_rq_set_block_pc(struct request *rq, unsigned short cmd_len,
> +		u8 *sense, gfp_t gfp)
>  {
>  	rq->cmd_type = REQ_TYPE_BLOCK_PC;
>  	rq->__data_len = 0;
>  	rq->__sector = (sector_t) -1;
>  	rq->bio = rq->biotail = NULL;
> -	memset(rq->__cmd, 0, sizeof(rq->__cmd));
> +
> +	rq->block_pc = kzalloc(sizeof(*rq->block_pc) + cmd_len, gfp);

I wish you would not embed a dynamic allocation here for any
driver regardless. This extra allocation does hurt a lot. See how in
SCSI fs commands you embedded it in scsi_cmnd so it catches as well
for multi-Q pre-allocation.

I think you need to just make it the same as *sense pass it from outside
and the allocation is the caller responsibility. The caller must have
an end-request call back set. (Or is a sync call)

Usually all users already have a structure to put this in. The only bit
more work is to take care of the free. If they are already passing sense
then they already need to free at end of request. Those that are synchronous
can have it on the stack. Only very few places need a bit of extra work.


> +	if (!rq->block_pc)
> +		return -ENOMEM;
> +	rq->block_pc->cmd_len = cmd_len;
> +	rq->block_pc->sense = sense;
> +	return 0;
>  }
>  EXPORT_SYMBOL(blk_rq_set_block_pc);
>  
> @@ -1379,6 +1384,10 @@ void __blk_put_request(struct request_queue *q, struct request *req)
>  	if (unlikely(!q))
>  		return;
>  
> +	/* could also be other type-specific data */
> +	if (req->block_pc)
> +		kfree(req->block_pc);
> +
>  	if (q->mq_ops) {
>  		blk_mq_free_request(req);
>  		return;
> diff --git a/block/blk-exec.c b/block/blk-exec.c
> index 3fec8a2..94e909e 100644
> --- a/block/blk-exec.c
> +++ b/block/blk-exec.c
> @@ -10,11 +10,6 @@
>  
>  #include "blk.h"
>  
> -/*
> - * for max sense size
> - */
> -#include <scsi/scsi_cmnd.h>
> -
>  /**
>   * blk_end_sync_rq - executes a completion event on a request
>   * @rq: request to complete
> @@ -100,16 +95,9 @@ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
>  		   struct request *rq, int at_head)
>  {
>  	DECLARE_COMPLETION_ONSTACK(wait);
> -	char sense[SCSI_SENSE_BUFFERSIZE];
>  	int err = 0;
>  	unsigned long hang_check;
>  
> -	if (!rq->sense) {
> -		memset(sense, 0, sizeof(sense));
> -		rq->sense = sense;
> -		rq->sense_len = 0;
> -	}
> -
>  	rq->end_io_data = &wait;
>  	blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
>  
> @@ -123,11 +111,6 @@ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
>  	if (rq->errors)
>  		err = -EIO;
>  
> -	if (rq->sense == sense)	{
> -		rq->sense = NULL;
> -		rq->sense_len = 0;
> -	}
> -
>  	return err;
>  }
>  EXPORT_SYMBOL(blk_execute_rq);
<>
> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> index 2da818a..e64a01b 100644
> --- a/include/linux/blkdev.h
> +++ b/include/linux/blkdev.h
> @@ -80,6 +80,16 @@ enum rq_cmd_type_bits {
>  #define BLK_MAX_CDB	16
>  
>  /*
> + * when request is used as a packet command carrier
> + */
> +struct block_pc_request {
> +	unsigned short cmd_len;
> +	unsigned int sense_len;
> +	void *sense;

Better move cmd_len here the short will combine well
with the char array.

> +	unsigned char cmd[];
> +};
> +
> +/*
>   * Try to put the fields that are referenced together in the same cacheline.
>   *
>   * If you modify this structure, make sure to update blk_rq_init() and
> @@ -172,23 +182,19 @@ struct request {
>  	int tag;
>  	int errors;
>  
> -	/*
> -	 * when request is used as a packet command carrier
> -	 */
> -	unsigned char __cmd[BLK_MAX_CDB];
> -	unsigned char *cmd;
> -	unsigned short cmd_len;
> -
>  	unsigned int extra_len;	/* length of alignment and padding */
> -	unsigned int sense_len;
>  	unsigned int resid_len;	/* residual count */
> -	void *sense;
>  
>  	unsigned long deadline;
>  	struct list_head timeout_list;
>  	unsigned int timeout;
>  	int retries;
>  
> +	union {
> +		struct block_pc_request *block_pc;
> +		void *drv_private;
> +	};
> +

Exactly. drv_private is allocated by caller we can do the same for
block_pc. Also If (theoretically) a driver needs both it is just the
same pointer right? (container_of)

>  	/*
>  	 * completion callback.
>  	 */
> @@ -769,7 +775,8 @@ extern void __blk_put_request(struct request_queue *, struct request *);
>  extern struct request *blk_get_request(struct request_queue *, int, gfp_t);
>  extern struct request *blk_make_request(struct request_queue *, struct bio *,
>  					gfp_t);
> -extern void blk_rq_set_block_pc(struct request *);
> +int blk_rq_set_block_pc(struct request *rq, unsigned short cmd_len,
> +		u8 *sense, gfp_t gfp);
>  extern void blk_requeue_request(struct request_queue *, struct request *);
>  extern void blk_add_request_payload(struct request *rq, struct page *page,
>  		unsigned int len);
<>
> diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
> index 9fc1aec..de6d7d0 100644
> --- a/include/scsi/scsi_cmnd.h
> +++ b/include/scsi/scsi_cmnd.h
> @@ -92,7 +92,7 @@ struct scsi_cmnd {
>  
>  	/* These elements define the operation we are about to perform */
>  	unsigned char *cmnd;
> -
> +	unsigned char __cmnd[32];
>  
>  	/* These elements define the operation we ultimately want to perform */
>  	struct scsi_data_buffer sdb;
<>

Thanks
Boaz

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christoph Hellwig May 11, 2015, 8 a.m. UTC | #2
On Wed, May 06, 2015 at 02:46:18PM +0300, Boaz Harrosh wrote:
> > -	memset(rq->__cmd, 0, sizeof(rq->__cmd));
> > +
> > +	rq->block_pc = kzalloc(sizeof(*rq->block_pc) + cmd_len, gfp);
> 
> I wish you would not embed a dynamic allocation here for any
> driver regardless. This extra allocation does hurt a lot. See how in
> SCSI fs commands you embedded it in scsi_cmnd so it catches as well
> for multi-Q pre-allocation.
> 
> I think you need to just make it the same as *sense pass it from outside
> and the allocation is the caller responsibility. The caller must have
> an end-request call back set. (Or is a sync call)
> 
> Usually all users already have a structure to put this in. The only bit
> more work is to take care of the free. If they are already passing sense
> then they already need to free at end of request. Those that are synchronous
> can have it on the stack. Only very few places need a bit of extra work.

Actually most don't have a structure ready, that's why I ressorted to this
version.  But once this is in you can easily add low-level version that
allows passing a preallocate cdb buffer for the OSD case.

> > +struct block_pc_request {
> > +	unsigned short cmd_len;
> > +	unsigned int sense_len;
> > +	void *sense;
> 
> Better move cmd_len here the short will combine well
> with the char array.

Thanks.

> > +	union {
> > +		struct block_pc_request *block_pc;
> > +		void *drv_private;
> > +	};
> > +
> 
> Exactly. drv_private is allocated by caller we can do the same for
> block_pc. Also If (theoretically) a driver needs both it is just the
> same pointer right? (container_of)

I probably need to rename the field.  It's only driver private when
the low-level driver itself submits the request, e.g. internal commands
in the LLDD.  But in that particular case what you suggest is fine.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/block/blk-core.c b/block/blk-core.c
index 2e5020f..5d78a85 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -105,8 +105,6 @@  void blk_rq_init(struct request_queue *q, struct request *rq)
 	rq->__sector = (sector_t) -1;
 	INIT_HLIST_NODE(&rq->hash);
 	RB_CLEAR_NODE(&rq->rb_node);
-	rq->cmd = rq->__cmd;
-	rq->cmd_len = BLK_MAX_CDB;
 	rq->tag = -1;
 	rq->start_time = jiffies;
 	set_start_time_ns(rq);
@@ -149,7 +147,7 @@  void blk_dump_rq_flags(struct request *rq, char *msg)
 	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
 		printk(KERN_INFO "  cdb: ");
 		for (bit = 0; bit < BLK_MAX_CDB; bit++)
-			printk("%02x ", rq->cmd[bit]);
+			printk("%02x ", rq->block_pc->cmd[bit]);
 		printk("\n");
 	}
 }
@@ -1253,8 +1251,6 @@  struct request *blk_make_request(struct request_queue *q, struct bio *bio,
 	if (IS_ERR(rq))
 		return rq;
 
-	blk_rq_set_block_pc(rq);
-
 	for_each_bio(bio) {
 		struct bio *bounce_bio = bio;
 		int ret;
@@ -1274,15 +1270,24 @@  EXPORT_SYMBOL(blk_make_request);
 /**
  * blk_rq_set_block_pc - initialize a request to type BLOCK_PC
  * @rq:		request to be initialized
+ * @cmd_len:	length of the CDB
+ * @gfp:	kmalloc flags
  *
  */
-void blk_rq_set_block_pc(struct request *rq)
+int blk_rq_set_block_pc(struct request *rq, unsigned short cmd_len,
+		u8 *sense, gfp_t gfp)
 {
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
 	rq->__data_len = 0;
 	rq->__sector = (sector_t) -1;
 	rq->bio = rq->biotail = NULL;
-	memset(rq->__cmd, 0, sizeof(rq->__cmd));
+
+	rq->block_pc = kzalloc(sizeof(*rq->block_pc) + cmd_len, gfp);
+	if (!rq->block_pc)
+		return -ENOMEM;
+	rq->block_pc->cmd_len = cmd_len;
+	rq->block_pc->sense = sense;
+	return 0;
 }
 EXPORT_SYMBOL(blk_rq_set_block_pc);
 
@@ -1379,6 +1384,10 @@  void __blk_put_request(struct request_queue *q, struct request *req)
 	if (unlikely(!q))
 		return;
 
+	/* could also be other type-specific data */
+	if (req->block_pc)
+		kfree(req->block_pc);
+
 	if (q->mq_ops) {
 		blk_mq_free_request(req);
 		return;
diff --git a/block/blk-exec.c b/block/blk-exec.c
index 3fec8a2..94e909e 100644
--- a/block/blk-exec.c
+++ b/block/blk-exec.c
@@ -10,11 +10,6 @@ 
 
 #include "blk.h"
 
-/*
- * for max sense size
- */
-#include <scsi/scsi_cmnd.h>
-
 /**
  * blk_end_sync_rq - executes a completion event on a request
  * @rq: request to complete
@@ -100,16 +95,9 @@  int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
 		   struct request *rq, int at_head)
 {
 	DECLARE_COMPLETION_ONSTACK(wait);
-	char sense[SCSI_SENSE_BUFFERSIZE];
 	int err = 0;
 	unsigned long hang_check;
 
-	if (!rq->sense) {
-		memset(sense, 0, sizeof(sense));
-		rq->sense = sense;
-		rq->sense_len = 0;
-	}
-
 	rq->end_io_data = &wait;
 	blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
 
@@ -123,11 +111,6 @@  int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
 	if (rq->errors)
 		err = -EIO;
 
-	if (rq->sense == sense)	{
-		rq->sense = NULL;
-		rq->sense_len = 0;
-	}
-
 	return err;
 }
 EXPORT_SYMBOL(blk_execute_rq);
diff --git a/block/blk-mq.c b/block/blk-mq.c
index ade8a2d..715e3c0 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -210,12 +210,8 @@  static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx,
 	/* tag was already set */
 	rq->errors = 0;
 
-	rq->cmd = rq->__cmd;
-
 	rq->extra_len = 0;
-	rq->sense_len = 0;
 	rq->resid_len = 0;
-	rq->sense = NULL;
 
 	INIT_LIST_HEAD(&rq->timeout_list);
 	rq->timeout = 0;
diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index 650f427..6b73dca 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -59,9 +59,9 @@  void bsg_job_done(struct bsg_job *job, int result,
 	err = job->req->errors = result;
 	if (err < 0)
 		/* we're only returning the result field in the reply */
-		job->req->sense_len = sizeof(u32);
+		job->req->block_pc->sense_len = sizeof(u32);
 	else
-		job->req->sense_len = job->reply_len;
+		job->req->block_pc->sense_len = job->reply_len;
 	/* we assume all request payload was transferred, residual == 0 */
 	req->resid_len = 0;
 
@@ -124,9 +124,9 @@  static int bsg_create_job(struct device *dev, struct request *req)
 	job->req = req;
 	if (q->bsg_job_size)
 		job->dd_data = (void *)&job[1];
-	job->request = req->cmd;
-	job->request_len = req->cmd_len;
-	job->reply = req->sense;
+	job->request = req->block_pc->cmd;
+	job->request_len = req->block_pc->cmd_len;
+	job->reply = req->block_pc->sense;
 	job->reply_len = SCSI_SENSE_BUFFERSIZE;	/* Size of sense buffer
 						 * allocated */
 	if (req->bio) {
diff --git a/block/bsg.c b/block/bsg.c
index d214e92..ebf0dc1 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -140,18 +140,13 @@  static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
 				struct sg_io_v4 *hdr, struct bsg_device *bd,
 				fmode_t has_write_perm)
 {
-	if (hdr->request_len > BLK_MAX_CDB) {
-		rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL);
-		if (!rq->cmd)
-			return -ENOMEM;
-	}
-
-	if (copy_from_user(rq->cmd, (void __user *)(unsigned long)hdr->request,
+	if (copy_from_user(rq->block_pc->cmd,
+			   (void __user *)(unsigned long)hdr->request,
 			   hdr->request_len))
 		return -EFAULT;
 
 	if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) {
-		if (blk_verify_command(rq->cmd, has_write_perm))
+		if (blk_verify_command(rq->block_pc->cmd, has_write_perm))
 			return -EPERM;
 	} else if (!capable(CAP_SYS_RAWIO))
 		return -EPERM;
@@ -159,8 +154,6 @@  static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
 	/*
 	 * fill in request structure
 	 */
-	rq->cmd_len = hdr->request_len;
-
 	rq->timeout = msecs_to_jiffies(hdr->timeout);
 	if (!rq->timeout)
 		rq->timeout = q->sg_timeout;
@@ -236,7 +229,10 @@  bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
 	rq = blk_get_request(q, rw, GFP_KERNEL);
 	if (IS_ERR(rq))
 		return rq;
-	blk_rq_set_block_pc(rq);
+
+	ret = blk_rq_set_block_pc(rq, hdr->request_len, sense, GFP_KERNEL);
+	if (ret)
+		goto out;
 
 	ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, bd, has_write_perm);
 	if (ret)
@@ -280,13 +276,8 @@  bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
 			goto out;
 	}
 
-	rq->sense = sense;
-	rq->sense_len = 0;
-
 	return rq;
 out:
-	if (rq->cmd != rq->__cmd)
-		kfree(rq->cmd);
 	blk_put_request(rq);
 	if (next_rq) {
 		blk_rq_unmap_user(next_rq->bio);
@@ -407,12 +398,12 @@  static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
 		hdr->info |= SG_INFO_CHECK;
 	hdr->response_len = 0;
 
-	if (rq->sense_len && hdr->response) {
+	if (rq->block_pc->sense_len && hdr->response) {
 		int len = min_t(unsigned int, hdr->max_response_len,
-					rq->sense_len);
+					rq->block_pc->sense_len);
 
 		ret = copy_to_user((void __user *)(unsigned long)hdr->response,
-				   rq->sense, len);
+				   rq->block_pc->sense, len);
 		if (!ret)
 			hdr->response_len = len;
 		else
@@ -439,8 +430,6 @@  static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
 		ret = rq->errors;
 
 	blk_rq_unmap_user(bio);
-	if (rq->cmd != rq->__cmd)
-		kfree(rq->cmd);
 	blk_put_request(rq);
 
 	return ret;
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 55b6f15..62f4e16 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -227,16 +227,14 @@  EXPORT_SYMBOL(blk_verify_command);
 static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
 			     struct sg_io_hdr *hdr, fmode_t mode)
 {
-	if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
+	if (copy_from_user(rq->block_pc->cmd, hdr->cmdp, hdr->cmd_len))
 		return -EFAULT;
-	if (blk_verify_command(rq->cmd, mode & FMODE_WRITE))
+	if (blk_verify_command(rq->block_pc->cmd, mode & FMODE_WRITE))
 		return -EPERM;
 
 	/*
 	 * fill in request structure
 	 */
-	rq->cmd_len = hdr->cmd_len;
-
 	rq->timeout = msecs_to_jiffies(hdr->timeout);
 	if (!rq->timeout)
 		rq->timeout = q->sg_timeout;
@@ -267,10 +265,11 @@  static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
 	hdr->resid = rq->resid_len;
 	hdr->sb_len_wr = 0;
 
-	if (rq->sense_len && hdr->sbp) {
-		int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len);
+	if (rq->block_pc->sense_len && hdr->sbp) {
+		int len = min((unsigned int) hdr->mx_sb_len,
+				rq->block_pc->sense_len);
 
-		if (!copy_to_user(hdr->sbp, rq->sense, len))
+		if (!copy_to_user(hdr->sbp, rq->block_pc->sense, len))
 			hdr->sb_len_wr = len;
 		else
 			ret = -EFAULT;
@@ -291,7 +290,6 @@  static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
 	int writing = 0;
 	int at_head = 0;
 	struct request *rq;
-	char sense[SCSI_SENSE_BUFFERSIZE];
 	struct bio *bio;
 
 	if (hdr->interface_id != 'S')
@@ -318,17 +316,14 @@  static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
 	rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL);
 	if (IS_ERR(rq))
 		return PTR_ERR(rq);
-	blk_rq_set_block_pc(rq);
 
-	if (hdr->cmd_len > BLK_MAX_CDB) {
-		rq->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL);
-		if (!rq->cmd)
-			goto out_put_request;
-	}
+	ret = blk_rq_set_block_pc(rq, hdr->cmd_len, NULL, GFP_KERNEL);
+	if (ret)
+		goto out_put_request;
 
 	ret = -EFAULT;
 	if (blk_fill_sghdr_rq(q, rq, hdr, mode))
-		goto out_free_cdb;
+		goto out_put_request;
 
 	ret = 0;
 	if (hdr->iovec_count) {
@@ -339,7 +334,7 @@  static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
 				   hdr->dxferp, hdr->iovec_count,
 				   0, &iov, &i);
 		if (ret < 0)
-			goto out_free_cdb;
+			goto out_put_request;
 
 		/* SG_IO howto says that the shorter of the two wins */
 		iov_iter_truncate(&i, hdr->dxfer_len);
@@ -351,12 +346,9 @@  static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
 				      GFP_KERNEL);
 
 	if (ret)
-		goto out_free_cdb;
+		goto out_put_request;
 
 	bio = rq->bio;
-	memset(sense, 0, sizeof(sense));
-	rq->sense = sense;
-	rq->sense_len = 0;
 	rq->retries = 0;
 
 	start_time = jiffies;
@@ -371,9 +363,6 @@  static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
 
 	ret = blk_complete_sghdr_rq(rq, hdr, bio);
 
-out_free_cdb:
-	if (rq->cmd != rq->__cmd)
-		kfree(rq->cmd);
 out_put_request:
 	blk_put_request(rq);
 	return ret;
@@ -449,22 +438,23 @@  int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
 		err = PTR_ERR(rq);
 		goto error_free_buffer;
 	}
-	blk_rq_set_block_pc(rq);
 
 	cmdlen = COMMAND_SIZE(opcode);
+	err = blk_rq_set_block_pc(rq, cmdlen, sense, GFP_KERNEL);
+	if (err)
+		goto error;
 
 	/*
 	 * get command and data to send to device, if any
 	 */
 	err = -EFAULT;
-	rq->cmd_len = cmdlen;
-	if (copy_from_user(rq->cmd, sic->data, cmdlen))
+	if (copy_from_user(rq->block_pc->cmd, sic->data, cmdlen))
 		goto error;
 
 	if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
 		goto error;
 
-	err = blk_verify_command(rq->cmd, mode & FMODE_WRITE);
+	err = blk_verify_command(rq->block_pc->cmd, mode & FMODE_WRITE);
 	if (err)
 		goto error;
 
@@ -500,18 +490,14 @@  int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
 		goto error;
 	}
 
-	memset(sense, 0, sizeof(sense));
-	rq->sense = sense;
-	rq->sense_len = 0;
-
 	blk_execute_rq(q, disk, rq, 0);
 
 	err = rq->errors & 0xff;	/* only 8 bit SCSI status */
 	if (err) {
-		if (rq->sense_len && rq->sense) {
-			bytes = (OMAX_SB_LEN > rq->sense_len) ?
-				rq->sense_len : OMAX_SB_LEN;
-			if (copy_to_user(sic->data, rq->sense, bytes))
+		if (rq->block_pc->sense_len) {
+			bytes = (OMAX_SB_LEN > rq->block_pc->sense_len) ?
+				rq->block_pc->sense_len : OMAX_SB_LEN;
+			if (copy_to_user(sic->data, rq->block_pc->sense, bytes))
 				err = -EFAULT;
 		}
 	} else {
@@ -539,14 +525,16 @@  static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
 	rq = blk_get_request(q, WRITE, __GFP_WAIT);
 	if (IS_ERR(rq))
 		return PTR_ERR(rq);
-	blk_rq_set_block_pc(rq);
+	err = blk_rq_set_block_pc(rq, 6, NULL, GFP_KERNEL);
+	if (err)
+		goto out_put_request;
+
 	rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
-	rq->cmd[0] = cmd;
-	rq->cmd[4] = data;
-	rq->cmd_len = 6;
+	rq->block_pc->cmd[0] = cmd;
+	rq->block_pc->cmd[4] = data;
 	err = blk_execute_rq(q, bd_disk, rq, 0);
+out_put_request:
 	blk_put_request(rq);
-
 	return err;
 }
 
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 3131adc..d8cb4ec 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1143,7 +1143,7 @@  static int atapi_drain_needed(struct request *rq)
 	if (!blk_rq_bytes(rq) || (rq->cmd_flags & REQ_WRITE))
 		return 0;
 
-	return atapi_cmd_type(rq->cmd[0]) == ATAPI_MISC;
+	return atapi_cmd_type(rq->block_pc->cmd[0]) == ATAPI_MISC;
 }
 
 static int ata_scsi_dev_config(struct scsi_device *sdev,
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 09e628da..51f919d 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -706,7 +706,11 @@  static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
 			     WRITE : READ, __GFP_WAIT);
 	if (IS_ERR(rq))
 		return PTR_ERR(rq);
-	blk_rq_set_block_pc(rq);
+
+	ret = blk_rq_set_block_pc(rq, COMMAND_SIZE(cgc->cmd[0]), NULL,
+			GFP_KERNEL);
+	if (ret)
+		goto out;
 
 	if (cgc->buflen) {
 		ret = blk_rq_map_kern(q, rq, cgc->buffer, cgc->buflen,
@@ -715,8 +719,7 @@  static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
 			goto out;
 	}
 
-	rq->cmd_len = COMMAND_SIZE(cgc->cmd[0]);
-	memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
+	memcpy(rq->block_pc->cmd, cgc->cmd, CDROM_PACKET_SIZE);
 
 	rq->timeout = 60*HZ;
 	if (cgc->quiet)
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index d4d05f0..cd3bcc0 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -90,7 +90,8 @@  static int __virtblk_add_req(struct virtqueue *vq,
 	 * inhdr with additional status information.
 	 */
 	if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) {
-		sg_init_one(&cmd, vbr->req->cmd, vbr->req->cmd_len);
+		sg_init_one(&cmd, vbr->req->block_pc->cmd,
+				vbr->req->block_pc->cmd_len);
 		sgs[num_out++] = &cmd;
 	}
 
@@ -102,7 +103,8 @@  static int __virtblk_add_req(struct virtqueue *vq,
 	}
 
 	if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) {
-		sg_init_one(&sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
+		sg_init_one(&sense, vbr->req->block_pc->sense,
+				SCSI_SENSE_BUFFERSIZE);
 		sgs[num_out + num_in++] = &sense;
 		sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr));
 		sgs[num_out + num_in++] = &inhdr;
@@ -122,7 +124,8 @@  static inline void virtblk_request_done(struct request *req)
 
 	if (req->cmd_type == REQ_TYPE_BLOCK_PC) {
 		req->resid_len = virtio32_to_cpu(vblk->vdev, vbr->in_hdr.residual);
-		req->sense_len = virtio32_to_cpu(vblk->vdev, vbr->in_hdr.sense_len);
+		req->block_pc->sense_len =
+			virtio32_to_cpu(vblk->vdev, vbr->in_hdr.sense_len);
 		req->errors = virtio32_to_cpu(vblk->vdev, vbr->in_hdr.errors);
 	} else if (req->cmd_type == REQ_TYPE_DRV_PRIV) {
 		req->errors = (error != 0);
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 5d28a45..7a5672a 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2160,6 +2160,7 @@  static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
 			       int lba, int nframes)
 {
 	struct request_queue *q = cdi->disk->queue;
+	struct request_sense sense;
 	struct request *rq;
 	struct bio *bio;
 	unsigned int len;
@@ -2184,7 +2185,14 @@  static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
 			ret = PTR_ERR(rq);
 			break;
 		}
-		blk_rq_set_block_pc(rq);
+
+		memset(&sense, 0, sizeof(sense));
+
+		ret = blk_rq_set_block_pc(rq, 10, (u8 *)&sense, GFP_KERNEL);
+		if (ret) {
+			blk_put_request(rq);
+			break;
+		}
 
 		ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL);
 		if (ret) {
@@ -2192,25 +2200,23 @@  static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
 			break;
 		}
 
-		rq->cmd[0] = GPCMD_READ_CD;
-		rq->cmd[1] = 1 << 2;
-		rq->cmd[2] = (lba >> 24) & 0xff;
-		rq->cmd[3] = (lba >> 16) & 0xff;
-		rq->cmd[4] = (lba >>  8) & 0xff;
-		rq->cmd[5] = lba & 0xff;
-		rq->cmd[6] = (nr >> 16) & 0xff;
-		rq->cmd[7] = (nr >>  8) & 0xff;
-		rq->cmd[8] = nr & 0xff;
-		rq->cmd[9] = 0xf8;
-
-		rq->cmd_len = 12;
+		rq->block_pc->cmd[0] = GPCMD_READ_CD;
+		rq->block_pc->cmd[1] = 1 << 2;
+		rq->block_pc->cmd[2] = (lba >> 24) & 0xff;
+		rq->block_pc->cmd[3] = (lba >> 16) & 0xff;
+		rq->block_pc->cmd[4] = (lba >>  8) & 0xff;
+		rq->block_pc->cmd[5] = lba & 0xff;
+		rq->block_pc->cmd[6] = (nr >> 16) & 0xff;
+		rq->block_pc->cmd[7] = (nr >>  8) & 0xff;
+		rq->block_pc->cmd[8] = nr & 0xff;
+		rq->block_pc->cmd[9] = 0xf8;
+
 		rq->timeout = 60 * HZ;
 		bio = rq->bio;
 
 		if (blk_execute_rq(q, cdi->disk, rq, 0)) {
-			struct request_sense *s = rq->sense;
 			ret = -EIO;
-			cdi->last_sense = s->sense_key;
+			cdi->last_sense = sense.sense_key;
 		}
 
 		if (blk_rq_unmap_user(bio))
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 8001fe9..17df896 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1069,6 +1069,7 @@  static void dm_end_request(struct request *clone, int error)
 	struct mapped_device *md = tio->md;
 	struct request *rq = tio->orig;
 
+#if 0
 	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
 		rq->errors = clone->errors;
 		rq->resid_len = clone->resid_len;
@@ -1081,6 +1082,7 @@  static void dm_end_request(struct request *clone, int error)
 			 */
 			rq->sense_len = clone->sense_len;
 	}
+#endif
 
 	free_rq_clone(clone);
 	blk_end_request_all(rq, error);
@@ -1773,9 +1775,11 @@  static int setup_clone(struct request *clone, struct request *rq,
 	if (r)
 		return r;
 
+#if 0
 	clone->cmd = rq->cmd;
 	clone->cmd_len = rq->cmd_len;
 	clone->sense = rq->sense;
+#endif
 	clone->end_io = end_clone_request;
 	clone->end_io_data = tio;
 
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 5bdaae1..34127ac 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -2321,8 +2321,8 @@  static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 		SmpPassthroughReply_t *smprep;
 
 		smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
-		memcpy(req->sense, smprep, sizeof(*smprep));
-		req->sense_len = sizeof(*smprep);
+		memcpy(req->block_pc->sense, smprep, sizeof(*smprep));
+		req->block_pc->sense_len = sizeof(*smprep);
 		req->resid_len = 0;
 		rsp->resid_len -= smprep->ResponseDataLength;
 	} else {
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 854b568..9d2d781 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -107,7 +107,7 @@  static int realloc_buffer(struct alua_dh_data *h, unsigned len)
 }
 
 static struct request *get_alua_req(struct scsi_device *sdev,
-				    void *buffer, unsigned buflen, int rw)
+		struct alua_dh_data *h, unsigned buflen, int rw)
 {
 	struct request *rq;
 	struct request_queue *q = sdev->request_queue;
@@ -119,9 +119,16 @@  static struct request *get_alua_req(struct scsi_device *sdev,
 			    "%s: blk_get_request failed\n", __func__);
 		return NULL;
 	}
-	blk_rq_set_block_pc(rq);
 
-	if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) {
+	memset(h->sense, 0, SCSI_SENSE_BUFFERSIZE);
+	h->senselen = 0;
+
+	if (blk_rq_set_block_pc(rq, 16, h->sense, GFP_NOIO)) {
+		blk_put_request(rq);
+		return NULL;
+	}
+
+	if (buflen && blk_rq_map_kern(q, rq, h->buff, buflen, GFP_NOIO)) {
 		blk_put_request(rq);
 		sdev_printk(KERN_INFO, sdev,
 			    "%s: blk_rq_map_kern failed\n", __func__);
@@ -145,27 +152,23 @@  static int submit_vpd_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
 	struct request *rq;
 	int err = SCSI_DH_RES_TEMP_UNAVAIL;
 
-	rq = get_alua_req(sdev, h->buff, h->bufflen, READ);
+	rq = get_alua_req(sdev, h, h->bufflen, READ);
 	if (!rq)
 		goto done;
 
 	/* Prepare the command. */
-	rq->cmd[0] = INQUIRY;
-	rq->cmd[1] = 1;
-	rq->cmd[2] = 0x83;
-	rq->cmd[4] = h->bufflen;
-	rq->cmd_len = COMMAND_SIZE(INQUIRY);
-
-	rq->sense = h->sense;
-	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-	rq->sense_len = h->senselen = 0;
+	rq->block_pc->cmd[0] = INQUIRY;
+	rq->block_pc->cmd[1] = 1;
+	rq->block_pc->cmd[2] = 0x83;
+	rq->block_pc->cmd[4] = h->bufflen;
+	rq->block_pc->cmd_len = COMMAND_SIZE(INQUIRY);
 
 	err = blk_execute_rq(rq->q, NULL, rq, 1);
 	if (err == -EIO) {
 		sdev_printk(KERN_INFO, sdev,
 			    "%s: evpd inquiry failed with %x\n",
 			    ALUA_DH_NAME, rq->errors);
-		h->senselen = rq->sense_len;
+		h->senselen = rq->block_pc->sense_len;
 		err = SCSI_DH_IO;
 	}
 	blk_put_request(rq);
@@ -183,32 +186,28 @@  static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h,
 	struct request *rq;
 	int err = SCSI_DH_RES_TEMP_UNAVAIL;
 
-	rq = get_alua_req(sdev, h->buff, h->bufflen, READ);
+	rq = get_alua_req(sdev, h, h->bufflen, READ);
 	if (!rq)
 		goto done;
 
 	/* Prepare the command. */
-	rq->cmd[0] = MAINTENANCE_IN;
+	rq->block_pc->cmd[0] = MAINTENANCE_IN;
 	if (rtpg_ext_hdr_req)
-		rq->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
+		rq->block_pc->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
 	else
-		rq->cmd[1] = MI_REPORT_TARGET_PGS;
-	rq->cmd[6] = (h->bufflen >> 24) & 0xff;
-	rq->cmd[7] = (h->bufflen >> 16) & 0xff;
-	rq->cmd[8] = (h->bufflen >>  8) & 0xff;
-	rq->cmd[9] = h->bufflen & 0xff;
-	rq->cmd_len = COMMAND_SIZE(MAINTENANCE_IN);
-
-	rq->sense = h->sense;
-	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-	rq->sense_len = h->senselen = 0;
+		rq->block_pc->cmd[1] = MI_REPORT_TARGET_PGS;
+	rq->block_pc->cmd[6] = (h->bufflen >> 24) & 0xff;
+	rq->block_pc->cmd[7] = (h->bufflen >> 16) & 0xff;
+	rq->block_pc->cmd[8] = (h->bufflen >>  8) & 0xff;
+	rq->block_pc->cmd[9] = h->bufflen & 0xff;
+	rq->block_pc->cmd_len = COMMAND_SIZE(MAINTENANCE_IN);
 
 	err = blk_execute_rq(rq->q, NULL, rq, 1);
 	if (err == -EIO) {
 		sdev_printk(KERN_INFO, sdev,
 			    "%s: rtpg failed with %x\n",
 			    ALUA_DH_NAME, rq->errors);
-		h->senselen = rq->sense_len;
+		h->senselen = rq->block_pc->sense_len;
 		err = SCSI_DH_IO;
 	}
 	blk_put_request(rq);
@@ -237,7 +236,7 @@  static void stpg_endio(struct request *req, int error)
 		goto done;
 	}
 
-	if (req->sense_len > 0) {
+	if (req->block_pc->sense_len > 0) {
 		err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
 					   &sense_hdr);
 		if (!err) {
@@ -293,22 +292,19 @@  static unsigned submit_stpg(struct alua_dh_data *h)
 	h->buff[6] = (h->group_id >> 8) & 0xff;
 	h->buff[7] = h->group_id & 0xff;
 
-	rq = get_alua_req(sdev, h->buff, stpg_len, WRITE);
+	rq = get_alua_req(sdev, h, stpg_len, WRITE);
 	if (!rq)
 		return SCSI_DH_RES_TEMP_UNAVAIL;
 
 	/* Prepare the command. */
-	rq->cmd[0] = MAINTENANCE_OUT;
-	rq->cmd[1] = MO_SET_TARGET_PGS;
-	rq->cmd[6] = (stpg_len >> 24) & 0xff;
-	rq->cmd[7] = (stpg_len >> 16) & 0xff;
-	rq->cmd[8] = (stpg_len >>  8) & 0xff;
-	rq->cmd[9] = stpg_len & 0xff;
-	rq->cmd_len = COMMAND_SIZE(MAINTENANCE_OUT);
-
-	rq->sense = h->sense;
-	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-	rq->sense_len = h->senselen = 0;
+	rq->block_pc->cmd[0] = MAINTENANCE_OUT;
+	rq->block_pc->cmd[1] = MO_SET_TARGET_PGS;
+	rq->block_pc->cmd[6] = (stpg_len >> 24) & 0xff;
+	rq->block_pc->cmd[7] = (stpg_len >> 16) & 0xff;
+	rq->block_pc->cmd[8] = (stpg_len >>  8) & 0xff;
+	rq->block_pc->cmd[9] = stpg_len & 0xff;
+	rq->block_pc->cmd_len = COMMAND_SIZE(MAINTENANCE_OUT);
+
 	rq->end_io_data = h;
 
 	blk_execute_rq_nowait(rq->q, NULL, rq, 1, stpg_endio);
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c
index 6ed1caa..a009bf2 100644
--- a/drivers/scsi/device_handler/scsi_dh_emc.c
+++ b/drivers/scsi/device_handler/scsi_dh_emc.c
@@ -267,8 +267,8 @@  out:
  * Uses data and sense buffers in hardware handler context structure and
  * assumes serial servicing of commands, both issuance and completion.
  */
-static struct request *get_req(struct scsi_device *sdev, int cmd,
-				unsigned char *buffer)
+static struct request *get_req(struct scsi_device *sdev,
+		struct clariion_dh_data *csdev, int cmd)
 {
 	struct request *rq;
 	int len = 0;
@@ -280,25 +280,31 @@  static struct request *get_req(struct scsi_device *sdev, int cmd,
 		return NULL;
 	}
 
-	blk_rq_set_block_pc(rq);
-	rq->cmd_len = COMMAND_SIZE(cmd);
-	rq->cmd[0] = cmd;
+	memset(csdev->sense, 0, SCSI_SENSE_BUFFERSIZE);
+	csdev->senselen = 0;
+
+	if (blk_rq_set_block_pc(rq, COMMAND_SIZE(cmd),
+			csdev->sense, GFP_NOIO)) {
+		blk_put_request(rq);
+		return NULL;
+	}
+	rq->block_pc->cmd[0] = cmd;
 
 	switch (cmd) {
 	case MODE_SELECT:
 		len = sizeof(short_trespass);
-		rq->cmd[1] = 0x10;
-		rq->cmd[4] = len;
+		rq->block_pc->cmd[1] = 0x10;
+		rq->block_pc->cmd[4] = len;
 		break;
 	case MODE_SELECT_10:
 		len = sizeof(long_trespass);
-		rq->cmd[1] = 0x10;
-		rq->cmd[8] = len;
+		rq->block_pc->cmd[1] = 0x10;
+		rq->block_pc->cmd[8] = len;
 		break;
 	case INQUIRY:
 		len = CLARIION_BUFFER_SIZE;
-		rq->cmd[4] = len;
-		memset(buffer, 0, len);
+		rq->block_pc->cmd[4] = len;
+		memset(csdev->buffer, 0, len);
 		break;
 	default:
 		BUG_ON(1);
@@ -310,7 +316,7 @@  static struct request *get_req(struct scsi_device *sdev, int cmd,
 	rq->timeout = CLARIION_TIMEOUT;
 	rq->retries = CLARIION_RETRIES;
 
-	if (blk_rq_map_kern(rq->q, rq, buffer, len, GFP_NOIO)) {
+	if (blk_rq_map_kern(rq->q, rq, csdev->buffer, len, GFP_NOIO)) {
 		blk_put_request(rq);
 		return NULL;
 	}
@@ -321,20 +327,16 @@  static struct request *get_req(struct scsi_device *sdev, int cmd,
 static int send_inquiry_cmd(struct scsi_device *sdev, int page,
 			    struct clariion_dh_data *csdev)
 {
-	struct request *rq = get_req(sdev, INQUIRY, csdev->buffer);
+	struct request *rq = get_req(sdev, csdev, INQUIRY);
 	int err;
 
 	if (!rq)
 		return SCSI_DH_RES_TEMP_UNAVAIL;
 
-	rq->sense = csdev->sense;
-	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-	rq->sense_len = csdev->senselen = 0;
-
-	rq->cmd[0] = INQUIRY;
+	rq->block_pc->cmd[0] = INQUIRY;
 	if (page != 0) {
-		rq->cmd[1] = 1;
-		rq->cmd[2] = page;
+		rq->block_pc->cmd[1] = 1;
+		rq->block_pc->cmd[2] = page;
 	}
 	err = blk_execute_rq(sdev->request_queue, NULL, rq, 1);
 	if (err == -EIO) {
@@ -342,7 +344,7 @@  static int send_inquiry_cmd(struct scsi_device *sdev, int page,
 			    "%s: failed to send %s INQUIRY: %x\n",
 			    CLARIION_NAME, page?"EVPD":"standard",
 			    rq->errors);
-		csdev->senselen = rq->sense_len;
+		csdev->senselen = rq->block_pc->sense_len;
 		err = SCSI_DH_IO;
 	}
 
@@ -376,17 +378,13 @@  static int send_trespass_cmd(struct scsi_device *sdev,
 	BUG_ON((len > CLARIION_BUFFER_SIZE));
 	memcpy(csdev->buffer, page22, len);
 
-	rq = get_req(sdev, cmd, csdev->buffer);
+	rq = get_req(sdev, csdev, cmd);
 	if (!rq)
 		return SCSI_DH_RES_TEMP_UNAVAIL;
 
-	rq->sense = csdev->sense;
-	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-	rq->sense_len = csdev->senselen = 0;
-
 	err = blk_execute_rq(sdev->request_queue, NULL, rq, 1);
 	if (err == -EIO) {
-		if (rq->sense_len) {
+		if (rq->block_pc->sense_len) {
 			err = trespass_endio(sdev, csdev->sense);
 		} else {
 			sdev_printk(KERN_INFO, sdev,
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
index 485d995..06f2c36 100644
--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
@@ -119,19 +119,21 @@  retry:
 	if (IS_ERR(req))
 		return SCSI_DH_RES_TEMP_UNAVAIL;
 
-	blk_rq_set_block_pc(req);
+	memset(h->sense, 0, SCSI_SENSE_BUFFERSIZE);
+
+	ret = blk_rq_set_block_pc(req, 16, h->sense, GFP_NOIO);
+	if (ret)
+		goto out;
+
 	req->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
 			  REQ_FAILFAST_DRIVER;
-	req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY);
-	req->cmd[0] = TEST_UNIT_READY;
+	req->block_pc->cmd_len = COMMAND_SIZE(TEST_UNIT_READY);
+	req->block_pc->cmd[0] = TEST_UNIT_READY;
 	req->timeout = HP_SW_TIMEOUT;
-	req->sense = h->sense;
-	memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
-	req->sense_len = 0;
 
 	ret = blk_execute_rq(req->q, NULL, req, 1);
 	if (ret == -EIO) {
-		if (req->sense_len > 0) {
+		if (req->block_pc->sense_len > 0) {
 			ret = tur_done(sdev, h->sense);
 		} else {
 			sdev_printk(KERN_WARNING, sdev,
@@ -152,8 +154,8 @@  retry:
 		ret = SCSI_DH_OK;
 	}
 
+out:
 	blk_put_request(req);
-
 	return ret;
 }
 
@@ -212,7 +214,7 @@  static void start_stop_endio(struct request *req, int error)
 		goto done;
 	}
 
-	if (req->sense_len > 0) {
+	if (req->block_pc->sense_len > 0) {
 		err = start_done(h->sdev, h->sense);
 		if (err == SCSI_DH_RETRY) {
 			err = SCSI_DH_IO;
@@ -249,16 +251,20 @@  static int hp_sw_start_stop(struct hp_sw_dh_data *h)
 	if (IS_ERR(req))
 		return SCSI_DH_RES_TEMP_UNAVAIL;
 
-	blk_rq_set_block_pc(req);
+	memset(h->sense, 0, SCSI_SENSE_BUFFERSIZE);
+
+	if (blk_rq_set_block_pc(req, 16, h->sense, GFP_ATOMIC) < 0) {
+		blk_put_request(req);
+		return SCSI_DH_RES_TEMP_UNAVAIL;
+	}
+		
 	req->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
 			  REQ_FAILFAST_DRIVER;
-	req->cmd_len = COMMAND_SIZE(START_STOP);
-	req->cmd[0] = START_STOP;
-	req->cmd[4] = 1;	/* Start spin cycle */
+	req->block_pc->cmd_len = COMMAND_SIZE(START_STOP);
+	req->block_pc->cmd[0] = START_STOP;
+	req->block_pc->cmd[4] = 1;	/* Start spin cycle */
 	req->timeout = HP_SW_TIMEOUT;
-	req->sense = h->sense;
-	memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
-	req->sense_len = 0;
+
 	req->end_io_data = h;
 
 	blk_execute_rq_nowait(req->q, NULL, req, 1, start_stop_endio);
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index b46ace3..78552ae 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -266,7 +266,7 @@  static inline struct rdac_dh_data *get_rdac_data(struct scsi_device *sdev)
 }
 
 static struct request *get_rdac_req(struct scsi_device *sdev,
-			void *buffer, unsigned buflen, int rw)
+		struct rdac_dh_data *h, void *buffer, unsigned buflen, int rw)
 {
 	struct request *rq;
 	struct request_queue *q = sdev->request_queue;
@@ -278,7 +278,12 @@  static struct request *get_rdac_req(struct scsi_device *sdev,
 				"get_rdac_req: blk_get_request failed.\n");
 		return NULL;
 	}
-	blk_rq_set_block_pc(rq);
+
+	memset(h->sense, 0, SCSI_SENSE_BUFFERSIZE);
+	if (blk_rq_set_block_pc(rq, 16, h->sense, GFP_NOIO)) {
+		blk_put_request(rq);
+		return NULL;
+	}
 
 	if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) {
 		blk_put_request(rq);
@@ -336,24 +341,20 @@  static struct request *rdac_failover_get(struct scsi_device *sdev,
 	}
 
 	/* get request for block layer packet command */
-	rq = get_rdac_req(sdev, &h->ctlr->mode_select, data_size, WRITE);
+	rq = get_rdac_req(sdev, h, &h->ctlr->mode_select, data_size, WRITE);
 	if (!rq)
 		return NULL;
 
 	/* Prepare the command. */
 	if (h->ctlr->use_ms10) {
-		rq->cmd[0] = MODE_SELECT_10;
-		rq->cmd[7] = data_size >> 8;
-		rq->cmd[8] = data_size & 0xff;
+		rq->block_pc->cmd[0] = MODE_SELECT_10;
+		rq->block_pc->cmd[7] = data_size >> 8;
+		rq->block_pc->cmd[8] = data_size & 0xff;
 	} else {
-		rq->cmd[0] = MODE_SELECT;
-		rq->cmd[4] = data_size;
+		rq->block_pc->cmd[0] = MODE_SELECT;
+		rq->block_pc->cmd[4] = data_size;
 	}
-	rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
-
-	rq->sense = h->sense;
-	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-	rq->sense_len = 0;
+	rq->block_pc->cmd_len = COMMAND_SIZE(rq->block_pc->cmd[0]);
 
 	return rq;
 }
@@ -409,20 +410,16 @@  static int submit_inquiry(struct scsi_device *sdev, int page_code,
 	struct request_queue *q = sdev->request_queue;
 	int err = SCSI_DH_RES_TEMP_UNAVAIL;
 
-	rq = get_rdac_req(sdev, &h->inq, len, READ);
+	rq = get_rdac_req(sdev, h, &h->inq, len, READ);
 	if (!rq)
 		goto done;
 
 	/* Prepare the command. */
-	rq->cmd[0] = INQUIRY;
-	rq->cmd[1] = 1;
-	rq->cmd[2] = page_code;
-	rq->cmd[4] = len;
-	rq->cmd_len = COMMAND_SIZE(INQUIRY);
-
-	rq->sense = h->sense;
-	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-	rq->sense_len = 0;
+	rq->block_pc->cmd[0] = INQUIRY;
+	rq->block_pc->cmd[1] = 1;
+	rq->block_pc->cmd[2] = page_code;
+	rq->block_pc->cmd[4] = len;
+	rq->block_pc->cmd_len = COMMAND_SIZE(INQUIRY);
 
 	err = blk_execute_rq(q, NULL, rq, 1);
 	if (err == -EIO)
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index ff2500a..672597c 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -2094,8 +2094,8 @@  _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 		    ioc->name, __func__,
 		    le16_to_cpu(mpi_reply->ResponseDataLength)));
 
-		memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
-		req->sense_len = sizeof(*mpi_reply);
+		memcpy(req->block_pc->sense, mpi_reply, sizeof(*mpi_reply));
+		req->block_pc->sense_len = sizeof(*mpi_reply);
 		req->resid_len = 0;
 		rsp->resid_len -=
 		    le16_to_cpu(mpi_reply->ResponseDataLength);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index efb98af..b558442 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -2054,8 +2054,8 @@  _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 		    ioc->name, __func__,
 		    le16_to_cpu(mpi_reply->ResponseDataLength)));
 
-		memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
-		req->sense_len = sizeof(*mpi_reply);
+		memcpy(req->block_pc->sense, mpi_reply, sizeof(*mpi_reply));
+		req->block_pc->sense_len = sizeof(*mpi_reply);
 		req->resid_len = 0;
 		rsp->resid_len -=
 		    le16_to_cpu(mpi_reply->ResponseDataLength);
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 0cccd60..055714d 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -480,7 +480,7 @@  static void _set_error_resid(struct osd_request *or, struct request *req,
 {
 	or->async_error = error;
 	or->req_errors = req->errors ? : error;
-	or->sense_len = req->sense_len;
+	or->sense_len = req->block_pc->sense_len;
 	if (or->out.req)
 		or->out.residual = or->out.req->resid_len;
 	if (or->in.req)
@@ -1563,16 +1563,8 @@  static struct request *_make_request(struct request_queue *q, bool has_write,
 {
 	if (oii->bio)
 		return blk_make_request(q, oii->bio, flags);
-	else {
-		struct request *req;
-
-		req = blk_get_request(q, has_write ? WRITE : READ, flags);
-		if (IS_ERR(req))
-			return req;
-
-		blk_rq_set_block_pc(req);
-		return req;
-	}
+	else 
+		return blk_get_request(q, has_write ? WRITE : READ, flags);
 }
 
 static int _init_blk_request(struct osd_request *or,
@@ -1590,13 +1582,22 @@  static int _init_blk_request(struct osd_request *or,
 		goto out;
 	}
 
+	/* 
+	 * XXX: allocating max size here to avoid having to reorder all
+	 * the code below.
+	 */
+	ret = blk_rq_set_block_pc(req, 255, req->block_pc->sense, flags);
+	if (ret) {
+		blk_put_request(req);
+		goto out;
+	}
+
 	or->request = req;
 	req->cmd_flags |= REQ_QUIET;
 
 	req->timeout = or->timeout;
 	req->retries = or->retries;
-	req->sense = or->sense;
-	req->sense_len = 0;
+	req->block_pc->sense_len = 0;
 
 	if (has_out) {
 		or->out.req = req;
@@ -1608,7 +1609,6 @@  static int _init_blk_request(struct osd_request *or,
 				ret = PTR_ERR(req);
 				goto out;
 			}
-			blk_rq_set_block_pc(req);
 			or->in.req = or->request->next_rq = req;
 		}
 	} else if (has_in)
@@ -1695,8 +1695,8 @@  int osd_finalize_request(struct osd_request *or,
 
 	osd_sec_sign_cdb(&or->cdb, cap_key);
 
-	or->request->cmd = or->cdb.buff;
-	or->request->cmd_len = _osd_req_cdb_len(or);
+	memcpy(or->request->block_pc->cmd, or->cdb.buff, _osd_req_cdb_len(or));
+	or->request->block_pc->cmd_len = _osd_req_cdb_len(or);
 
 	return 0;
 }
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 5033223..79b57fe 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -367,7 +367,9 @@  static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
 	if (IS_ERR(req))
 		return DRIVER_ERROR << 24;
 
-	blk_rq_set_block_pc(req);
+	err = blk_rq_set_block_pc(req, cmd_len, SRpnt->sense, GFP_KERNEL);
+	if (err)
+		goto free_req;
 	req->cmd_flags |= REQ_QUIET;
 
 	SRpnt->bio = NULL;
@@ -404,11 +406,7 @@  static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
 			goto free_req;
 	}
 
-	req->cmd_len = cmd_len;
-	memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
-	memcpy(req->cmd, cmd, req->cmd_len);
-	req->sense = SRpnt->sense;
-	req->sense_len = 0;
+	memcpy(req->block_pc->cmd, cmd, cmd_len);
 	req->timeout = timeout;
 	req->retries = retries;
 	req->end_io_data = SRpnt;
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 2e2bb6f..f6bf256 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -909,7 +909,7 @@  qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 
 	bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
 	    sizeof(response) + sizeof(uint8_t);
-	fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
+	fw_sts_ptr = ((uint8_t *)bsg_job->req->block_pc->sense) +
 	    sizeof(struct fc_bsg_reply);
 	memcpy(fw_sts_ptr, response, sizeof(response));
 	fw_sts_ptr += sizeof(response);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 6dc14cd..724eaa4 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1418,7 +1418,8 @@  qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 			    type, sp->handle, comp_status, fw_status[1], fw_status[2],
 			    le16_to_cpu(((struct els_sts_entry_24xx *)
 				pkt)->total_byte_count));
-			fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
+			fw_sts_ptr = ((uint8_t*)bsg_job->req->block_pc->sense) +
+					sizeof(struct fc_bsg_reply);
 			memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
 		}
 		else {
@@ -1432,7 +1433,8 @@  qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 				    pkt)->error_subcode_2));
 			res = DID_ERROR << 16;
 			bsg_job->reply->reply_payload_rcv_len = 0;
-			fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
+			fw_sts_ptr = ((uint8_t*)bsg_job->req->block_pc->sense) +
+					sizeof(struct fc_bsg_reply);
 			memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
 		}
 		ql_dump_buffer(ql_dbg_user + ql_dbg_buffer, vha, 0x5056,
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index 6d190b4..2ac1886 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -2242,7 +2242,7 @@  qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req,
 		memcpy(fstatus.reserved_3,
 		    pkt->reserved_2, 20 * sizeof(uint8_t));
 
-		fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
+		fw_sts_ptr = ((uint8_t *)bsg_job->req->block_pc->sense) +
 		    sizeof(struct fc_bsg_reply);
 
 		memcpy(fw_sts_ptr, (uint8_t *)&fstatus,
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index c95a4e9..85d659e 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1968,16 +1968,18 @@  static void scsi_eh_lock_door(struct scsi_device *sdev)
 	if (IS_ERR(req))
 		return;
 
-	blk_rq_set_block_pc(req);
-
-	req->cmd[0] = ALLOW_MEDIUM_REMOVAL;
-	req->cmd[1] = 0;
-	req->cmd[2] = 0;
-	req->cmd[3] = 0;
-	req->cmd[4] = SCSI_REMOVAL_PREVENT;
-	req->cmd[5] = 0;
+	if (blk_rq_set_block_pc(req, COMMAND_SIZE(ALLOW_MEDIUM_REMOVAL),
+				NULL, GFP_KERNEL) < 0) {
+		blk_put_request(req);
+		return;
+	}
 
-	req->cmd_len = COMMAND_SIZE(req->cmd[0]);
+	req->block_pc->cmd[0] = ALLOW_MEDIUM_REMOVAL;
+	req->block_pc->cmd[1] = 0;
+	req->block_pc->cmd[2] = 0;
+	req->block_pc->cmd[3] = 0;
+	req->block_pc->cmd[4] = SCSI_REMOVAL_PREVENT;
+	req->block_pc->cmd[5] = 0;
 
 	req->cmd_flags |= REQ_QUIET;
 	req->timeout = 10 * HZ;
@@ -2332,8 +2334,6 @@  scsi_ioctl_reset(struct scsi_device *dev, int __user *arg)
 	blk_rq_init(NULL, &req);
 	scmd->request = &req;
 
-	scmd->cmnd = req.cmd;
-
 	scmd->scsi_done		= scsi_reset_provider_done_command;
 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
 
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index b1a2631..29e0cd6 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -224,16 +224,15 @@  int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
 	req = blk_get_request(sdev->request_queue, write, __GFP_WAIT);
 	if (IS_ERR(req))
 		return ret;
-	blk_rq_set_block_pc(req);
+
+	if (blk_rq_set_block_pc(req, COMMAND_SIZE(cmd[0]), sense, GFP_KERNEL))
+		goto out;
 
 	if (bufflen &&	blk_rq_map_kern(sdev->request_queue, req,
 					buffer, bufflen, __GFP_WAIT))
 		goto out;
 
-	req->cmd_len = COMMAND_SIZE(cmd[0]);
-	memcpy(req->cmd, cmd, req->cmd_len);
-	req->sense = sense;
-	req->sense_len = 0;
+	memcpy(req->block_pc->cmd, cmd, req->block_pc->cmd_len);
 	req->retries = retries;
 	req->timeout = timeout;
 	req->cmd_flags |= flags | REQ_QUIET | REQ_PREEMPT;
@@ -835,7 +834,7 @@  void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 
 	if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */
 		if (result) {
-			if (sense_valid && req->sense) {
+			if (sense_valid && req->block_pc->sense) {
 				/*
 				 * SG_IO wants current and deferred errors
 				 */
@@ -843,8 +842,8 @@  void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 
 				if (len > SCSI_SENSE_BUFFERSIZE)
 					len = SCSI_SENSE_BUFFERSIZE;
-				memcpy(req->sense, cmd->sense_buffer,  len);
-				req->sense_len = len;
+				memcpy(req->block_pc->sense, cmd->sense_buffer,  len);
+				req->block_pc->sense_len = len;
 			}
 			if (!sense_deferred)
 				error = __scsi_error_from_host_byte(cmd, result);
@@ -1208,7 +1207,6 @@  static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
 	cmd->tag = req->tag;
 	cmd->request = req;
 
-	cmd->cmnd = req->cmd;
 	cmd->prot_op = SCSI_PROT_NORMAL;
 
 	return cmd;
@@ -1234,7 +1232,8 @@  static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 		memset(&cmd->sdb, 0, sizeof(cmd->sdb));
 	}
 
-	cmd->cmd_len = req->cmd_len;
+	cmd->cmd_len = req->block_pc->cmd_len;
+	cmd->cmnd = req->block_pc->cmd;
 	cmd->transfersize = blk_rq_bytes(req);
 	cmd->allowed = req->retries;
 	return BLKPREP_OK;
@@ -1255,7 +1254,7 @@  static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
 			return ret;
 	}
 
-	memset(cmd->cmnd, 0, BLK_MAX_CDB);
+	cmd->cmnd = cmd->__cmnd;
 	return scsi_cmd_to_driver(cmd)->init_command(cmd);
 }
 
@@ -1911,7 +1910,6 @@  static int scsi_mq_prep_fn(struct request *req)
 
 	cmd->tag = req->tag;
 
-	cmd->cmnd = req->cmd;
 	cmd->prot_op = SCSI_PROT_NORMAL;
 
 	INIT_LIST_HEAD(&cmd->list);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 24eaaf6..6024e6c 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -3593,9 +3593,9 @@  fc_bsg_jobdone(struct fc_bsg_job *job)
 
 	if (err < 0)
 		/* we're only returning the result field in the reply */
-		job->req->sense_len = sizeof(uint32_t);
+		job->req->block_pc->sense_len = sizeof(uint32_t);
 	else
-		job->req->sense_len = job->reply_len;
+		job->req->block_pc->sense_len = job->reply_len;
 
 	/* we assume all request payload was transferred, residual == 0 */
 	req->resid_len = 0;
@@ -3725,9 +3725,9 @@  fc_req_to_bsgjob(struct Scsi_Host *shost, struct fc_rport *rport,
 	if (i->f->dd_bsg_size)
 		job->dd_data = (void *)&job[1];
 	spin_lock_init(&job->job_lock);
-	job->request = (struct fc_bsg_request *)req->cmd;
-	job->request_len = req->cmd_len;
-	job->reply = req->sense;
+	job->request = (struct fc_bsg_request *)req->block_pc->cmd;
+	job->request_len = req->block_pc->cmd_len;
+	job->reply = req->block_pc->sense;
 	job->reply_len = SCSI_SENSE_BUFFERSIZE;	/* Size of sense buffer
 						 * allocated */
 	if (req->bio) {
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index dcc4244..7883fd9 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -126,9 +126,6 @@  static DEFINE_IDA(sd_index_ida);
  * object after last put) */
 static DEFINE_MUTEX(sd_ref_mutex);
 
-static struct kmem_cache *sd_cdb_cache;
-static mempool_t *sd_cdb_pool;
-
 static const char *sd_cache_types[] = {
 	"write through", "none", "write back",
 	"write back, no read (daft)"
@@ -1016,13 +1013,6 @@  static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
 		protect = 0;
 
 	if (protect && sdkp->protection_type == SD_DIF_TYPE2_PROTECTION) {
-		SCpnt->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC);
-
-		if (unlikely(SCpnt->cmnd == NULL)) {
-			ret = BLKPREP_DEFER;
-			goto out;
-		}
-
 		SCpnt->cmd_len = SD_EXT_CDB_SIZE;
 		memset(SCpnt->cmnd, 0, SCpnt->cmd_len);
 		SCpnt->cmnd[0] = VARIABLE_LENGTH_CMD;
@@ -1138,12 +1128,6 @@  static void sd_uninit_command(struct scsi_cmnd *SCpnt)
 
 	if (rq->cmd_flags & REQ_DISCARD)
 		__free_page(rq->completion_data);
-
-	if (SCpnt->cmnd != rq->cmd) {
-		mempool_free(SCpnt->cmnd, sd_cdb_pool);
-		SCpnt->cmnd = NULL;
-		SCpnt->cmd_len = 0;
-	}
 }
 
 /**
@@ -3221,38 +3205,17 @@  static int __init init_sd(void)
 
 	err = class_register(&sd_disk_class);
 	if (err)
-		goto err_out;
-
-	sd_cdb_cache = kmem_cache_create("sd_ext_cdb", SD_EXT_CDB_SIZE,
-					 0, 0, NULL);
-	if (!sd_cdb_cache) {
-		printk(KERN_ERR "sd: can't init extended cdb cache\n");
-		err = -ENOMEM;
-		goto err_out_class;
-	}
-
-	sd_cdb_pool = mempool_create_slab_pool(SD_MEMPOOL_SIZE, sd_cdb_cache);
-	if (!sd_cdb_pool) {
-		printk(KERN_ERR "sd: can't init extended cdb pool\n");
-		err = -ENOMEM;
-		goto err_out_cache;
-	}
+		goto out_unregister_blkdev;
 
 	err = scsi_register_driver(&sd_template.gendrv);
 	if (err)
-		goto err_out_driver;
+		goto out_unregister_class;
 
 	return 0;
 
-err_out_driver:
-	mempool_destroy(sd_cdb_pool);
-
-err_out_cache:
-	kmem_cache_destroy(sd_cdb_cache);
-
-err_out_class:
+out_unregister_class:
 	class_unregister(&sd_disk_class);
-err_out:
+out_unregister_blkdev:
 	for (i = 0; i < SD_MAJORS; i++)
 		unregister_blkdev(sd_major(i), "sd");
 	return err;
@@ -3270,8 +3233,6 @@  static void __exit exit_sd(void)
 	SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
 
 	scsi_unregister_driver(&sd_template.gendrv);
-	mempool_destroy(sd_cdb_pool);
-	kmem_cache_destroy(sd_cdb_cache);
 
 	class_unregister(&sd_disk_class);
 
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9d7b7db..a266319 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1297,7 +1297,7 @@  sg_rq_end_io(struct request *rq, int uptodate)
 	if (unlikely(atomic_read(&sdp->detaching)))
 		pr_info("%s: device detaching\n", __func__);
 
-	sense = rq->sense;
+	sense = rq->block_pc->sense;
 	result = rq->errors;
 	resid = rq->resid_len;
 
@@ -1342,8 +1342,6 @@  sg_rq_end_io(struct request *rq, int uptodate)
 	 * blk_rq_unmap_user() can be called from user context.
 	 */
 	srp->rq = NULL;
-	if (rq->cmd != rq->__cmd)
-		kfree(rq->cmd);
 	__blk_put_request(rq->q, rq);
 
 	write_lock_irqsave(&sfp->rq_list_lock, iflags);
@@ -1701,16 +1699,16 @@  sg_start_req(Sg_request *srp, unsigned char *cmd)
 		return PTR_ERR(rq);
 	}
 
-	blk_rq_set_block_pc(rq);
+	res = blk_rq_set_block_pc(rq, hp->cmd_len, srp->sense_b, GFP_KERNEL);
+	if (res) {
+		blk_put_request(rq);
+		return res;
+	}
 
-	if (hp->cmd_len > BLK_MAX_CDB)
-		rq->cmd = long_cmdp;
-	memcpy(rq->cmd, cmd, hp->cmd_len);
-	rq->cmd_len = hp->cmd_len;
+	memcpy(rq->block_pc->cmd, cmd, hp->cmd_len);
 
 	srp->rq = rq;
 	rq->end_io_data = srp;
-	rq->sense = srp->sense_b;
 	rq->retries = SG_DEFAULT_RETRIES;
 
 	if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE))
@@ -1785,11 +1783,8 @@  sg_finish_rem_req(Sg_request *srp)
 	if (srp->bio)
 		ret = blk_rq_unmap_user(srp->bio);
 
-	if (srp->rq) {
-		if (srp->rq->cmd != srp->rq->__cmd)
-			kfree(srp->rq->cmd);
+	if (srp->rq)
 		blk_put_request(srp->rq);
-	}
 
 	if (srp->res_used)
 		sg_unlink_reserve(sfp, srp);
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 9a1c342..7b4445f 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -502,7 +502,10 @@  static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd,
 	if (IS_ERR(req))
 		return DRIVER_ERROR << 24;
 
-	blk_rq_set_block_pc(req);
+	err = blk_rq_set_block_pc(req, COMMAND_SIZE(cmd[0]), SRpnt->sense,
+			GFP_KERNEL);
+	if (err)
+		goto out_put_request;
 	req->cmd_flags |= REQ_QUIET;
 
 	mdata->null_mapped = 1;
@@ -510,24 +513,22 @@  static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd,
 	if (bufflen) {
 		err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen,
 				      GFP_KERNEL);
-		if (err) {
-			blk_put_request(req);
-			return DRIVER_ERROR << 24;
-		}
+		if (err)
+			goto out_put_request;
 	}
 
 	SRpnt->bio = req->bio;
-	req->cmd_len = COMMAND_SIZE(cmd[0]);
-	memset(req->cmd, 0, BLK_MAX_CDB);
-	memcpy(req->cmd, cmd, req->cmd_len);
-	req->sense = SRpnt->sense;
-	req->sense_len = 0;
+	memcpy(req->block_pc->cmd, cmd, req->block_pc->cmd_len);
 	req->timeout = timeout;
 	req->retries = retries;
 	req->end_io_data = SRpnt;
 
 	blk_execute_rq_nowait(req->q, NULL, req, 1, st_scsi_execute_end);
 	return 0;
+
+out_put_request:
+	blk_put_request(req);
+	return DRIVER_ERROR << 24;
 }
 
 /* Do the scsi command. Waits until command performed if do_wait is true.
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index f6c954c..023accd 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -1064,8 +1064,6 @@  pscsi_execute_cmd(struct se_cmd *cmd)
 			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 			goto fail;
 		}
-
-		blk_rq_set_block_pc(req);
 	} else {
 		BUG_ON(!cmd->data_length);
 
@@ -1082,12 +1080,16 @@  pscsi_execute_cmd(struct se_cmd *cmd)
 		}
 	}
 
+	if (blk_rq_set_block_pc(req, scsi_command_size(pt->pscsi_cdb),
+			&pt->pscsi_sense[0], GFP_KERNEL)) {
+		blk_put_request(req);
+		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+		goto fail;
+	}
+
 	req->end_io = pscsi_req_done;
 	req->end_io_data = cmd;
-	req->cmd_len = scsi_command_size(pt->pscsi_cdb);
-	req->cmd = &pt->pscsi_cdb[0];
-	req->sense = &pt->pscsi_sense[0];
-	req->sense_len = 0;
+	memcpy(req->block_pc->cmd, &pt->pscsi_cdb[0], req->block_pc->cmd_len);
 	if (pdv->pdv_sd->type == TYPE_DISK)
 		req->timeout = PS_TIMEOUT_DISK;
 	else
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 2da818a..e64a01b 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -80,6 +80,16 @@  enum rq_cmd_type_bits {
 #define BLK_MAX_CDB	16
 
 /*
+ * when request is used as a packet command carrier
+ */
+struct block_pc_request {
+	unsigned short cmd_len;
+	unsigned int sense_len;
+	void *sense;
+	unsigned char cmd[];
+};
+
+/*
  * Try to put the fields that are referenced together in the same cacheline.
  *
  * If you modify this structure, make sure to update blk_rq_init() and
@@ -172,23 +182,19 @@  struct request {
 	int tag;
 	int errors;
 
-	/*
-	 * when request is used as a packet command carrier
-	 */
-	unsigned char __cmd[BLK_MAX_CDB];
-	unsigned char *cmd;
-	unsigned short cmd_len;
-
 	unsigned int extra_len;	/* length of alignment and padding */
-	unsigned int sense_len;
 	unsigned int resid_len;	/* residual count */
-	void *sense;
 
 	unsigned long deadline;
 	struct list_head timeout_list;
 	unsigned int timeout;
 	int retries;
 
+	union {
+		struct block_pc_request *block_pc;
+		void *drv_private;
+	};
+
 	/*
 	 * completion callback.
 	 */
@@ -769,7 +775,8 @@  extern void __blk_put_request(struct request_queue *, struct request *);
 extern struct request *blk_get_request(struct request_queue *, int, gfp_t);
 extern struct request *blk_make_request(struct request_queue *, struct bio *,
 					gfp_t);
-extern void blk_rq_set_block_pc(struct request *);
+int blk_rq_set_block_pc(struct request *rq, unsigned short cmd_len,
+		u8 *sense, gfp_t gfp);
 extern void blk_requeue_request(struct request_queue *, struct request *);
 extern void blk_add_request_payload(struct request *rq, struct page *page,
 		unsigned int len);
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
index afc1343..8c63eca 100644
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -105,7 +105,9 @@  struct compat_blk_user_trace_setup {
 
 static inline int blk_cmd_buf_len(struct request *rq)
 {
-	return (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? rq->cmd_len * 3 : 1;
+	if (rq->cmd_type == REQ_TYPE_BLOCK_PC)
+		return rq->block_pc->cmd_len * 3;
+	return 1;
 }
 
 extern void blk_dump_cmd(char *buf, struct request *rq);
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 9fc1aec..de6d7d0 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -92,7 +92,7 @@  struct scsi_cmnd {
 
 	/* These elements define the operation we are about to perform */
 	unsigned char *cmnd;
-
+	unsigned char __cmnd[32];
 
 	/* These elements define the operation we ultimately want to perform */
 	struct scsi_data_buffer sdb;
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 483cecf..e87c0ac 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -720,7 +720,9 @@  static void blk_add_trace_rq(struct request_queue *q, struct request *rq,
 	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
 		what |= BLK_TC_ACT(BLK_TC_PC);
 		__blk_add_trace(bt, 0, nr_bytes, rq->cmd_flags,
-				what, rq->errors, rq->cmd_len, rq->cmd);
+				what, rq->errors,
+				rq->block_pc->cmd_len,
+				rq->block_pc->cmd);
 	} else  {
 		what |= BLK_TC_ACT(BLK_TC_FS);
 		__blk_add_trace(bt, blk_rq_pos(rq), nr_bytes,
@@ -1762,14 +1764,17 @@  void blk_trace_remove_sysfs(struct device *dev)
 void blk_dump_cmd(char *buf, struct request *rq)
 {
 	int i, end;
-	int len = rq->cmd_len;
-	unsigned char *cmd = rq->cmd;
+	int len;
+	unsigned char *cmd;
 
 	if (rq->cmd_type != REQ_TYPE_BLOCK_PC) {
 		buf[0] = '\0';
 		return;
 	}
 
+	len = rq->block_pc->cmd_len;
+	cmd = rq->block_pc->cmd;
+
 	for (end = len - 1; end >= 0; end--)
 		if (cmd[end])
 			break;