Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30b0c37b authored by Boaz Harrosh's avatar Boaz Harrosh Committed by James Bottomley
Browse files

[SCSI] implement scsi_data_buffer



In preparation for bidi we abstract all IO members of scsi_cmnd,
that will need to duplicate, into a substructure.

- Group all IO members of scsi_cmnd into a scsi_data_buffer
  structure.
- Adjust accessors to new members.
- scsi_{alloc,free}_sgtable receive a scsi_data_buffer instead of
  scsi_cmnd. And work on it.
- Adjust scsi_init_io() and  scsi_release_buffers() for above
  change.
- Fix other parts of scsi_lib/scsi.c to members migration. Use
  accessors where appropriate.

- fix Documentation about scsi_cmnd in scsi_host.h

- scsi_error.c
  * Changed needed members of struct scsi_eh_save.
  * Careful considerations in scsi_eh_prep/restore_cmnd.

- sd.c and sr.c
  * sd and sr would adjust IO size to align on device's block
    size so code needs to change once we move to scsi_data_buff
    implementation.
  * Convert code to use scsi_for_each_sg
  * Use data accessors where appropriate.

- tgt: convert libsrp to use scsi_data_buffer

- isd200: This driver still bangs on scsi_cmnd IO members,
  so need changing

[jejb: rebased on top of sg_table patches fixed up conflicts
and used the synergy to eliminate use_sg and sg_count]

Signed-off-by: default avatarBoaz Harrosh <bharrosh@panasas.com>
Signed-off-by: default avatarFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent bb52d82f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -426,8 +426,8 @@ int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info,

	sc->SCp.ptr = info;
	memcpy(sc->cmnd, cmd->cdb, MAX_COMMAND_SIZE);
	sc->request_bufflen = len;
	sc->request_buffer = (void *) (unsigned long) addr;
	sc->sdb.length = len;
	sc->sdb.table.sgl = (void *) (unsigned long) addr;
	sc->tag = tag;
	err = scsi_tgt_queue_command(sc, itn_id, (struct scsi_lun *)&cmd->lun,
				     cmd->tag);
+1 −1
Original line number Diff line number Diff line
@@ -757,7 +757,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
				"Notifying upper driver of completion "
				"(result %x)\n", cmd->result));

	good_bytes = cmd->request_bufflen;
	good_bytes = scsi_bufflen(cmd);
        if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
		drv = scsi_cmd_to_driver(cmd);
		if (drv->done)
+11 −19
Original line number Diff line number Diff line
@@ -617,29 +617,25 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
	ses->cmd_len = scmd->cmd_len;
	memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
	ses->data_direction = scmd->sc_data_direction;
	ses->bufflen = scmd->request_bufflen;
	ses->buffer = scmd->request_buffer;
	ses->use_sg = scmd->use_sg;
	ses->resid = scmd->resid;
	ses->sdb = scmd->sdb;
	ses->result = scmd->result;

	memset(&scmd->sdb, 0, sizeof(scmd->sdb));

	if (sense_bytes) {
		scmd->request_bufflen = min_t(unsigned,
		                       SCSI_SENSE_BUFFERSIZE, sense_bytes);
		scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE,
					 sense_bytes);
		sg_init_one(&ses->sense_sgl, scmd->sense_buffer,
		                                       scmd->request_bufflen);
		scmd->request_buffer = &ses->sense_sgl;
			    scmd->sdb.length);
		scmd->sdb.table.sgl = &ses->sense_sgl;
		scmd->sc_data_direction = DMA_FROM_DEVICE;
		scmd->use_sg = 1;
		scmd->sdb.table.nents = 1;
		memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
		scmd->cmnd[0] = REQUEST_SENSE;
		scmd->cmnd[4] = scmd->request_bufflen;
		scmd->cmnd[4] = scmd->sdb.length;
		scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
	} else {
		scmd->request_buffer = NULL;
		scmd->request_bufflen = 0;
		scmd->sc_data_direction = DMA_NONE;
		scmd->use_sg = 0;
		if (cmnd) {
			memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
			memcpy(scmd->cmnd, cmnd, cmnd_size);
@@ -676,10 +672,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
	scmd->cmd_len = ses->cmd_len;
	memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
	scmd->sc_data_direction = ses->data_direction;
	scmd->request_bufflen = ses->bufflen;
	scmd->request_buffer = ses->buffer;
	scmd->use_sg = ses->use_sg;
	scmd->resid = ses->resid;
	scmd->sdb = ses->sdb;
	scmd->result = ses->result;
}
EXPORT_SYMBOL(scsi_eh_restore_cmnd);
@@ -1700,8 +1693,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
	memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
    
	scmd->scsi_done		= scsi_reset_provider_done_command;
	scmd->request_buffer		= NULL;
	scmd->request_bufflen		= 0;
	memset(&scmd->sdb, 0, sizeof(scmd->sdb));

	scmd->cmd_len			= 0;

+25 −38
Original line number Diff line number Diff line
@@ -440,7 +440,7 @@ EXPORT_SYMBOL_GPL(scsi_execute_async);
static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
{
	cmd->serial_number = 0;
	cmd->resid = 0;
	scsi_set_resid(cmd, 0);
	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
	if (cmd->cmd_len == 0)
		cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
@@ -746,25 +746,25 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask)
	return mempool_alloc(sgp->pool, gfp_mask);
}

static int scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents,
			      gfp_t gfp_mask)
{
	int ret;

	BUG_ON(!cmd->use_sg);
	BUG_ON(!nents);

	ret = __sg_alloc_table(&cmd->sg_table, cmd->use_sg,
			       SCSI_MAX_SG_SEGMENTS, gfp_mask, scsi_sg_alloc);
	ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS,
			       gfp_mask, scsi_sg_alloc);
	if (unlikely(ret))
		__sg_free_table(&cmd->sg_table, SCSI_MAX_SG_SEGMENTS,
		__sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS,
				scsi_sg_free);

	cmd->request_buffer = cmd->sg_table.sgl;
	return ret;
}

static void scsi_free_sgtable(struct scsi_cmnd *cmd)
static void scsi_free_sgtable(struct scsi_data_buffer *sdb)
{
	__sg_free_table(&cmd->sg_table, SCSI_MAX_SG_SEGMENTS, scsi_sg_free);
	__sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, scsi_sg_free);
}

/*
@@ -786,15 +786,10 @@ static void scsi_free_sgtable(struct scsi_cmnd *cmd)
 */
void scsi_release_buffers(struct scsi_cmnd *cmd)
{
	if (cmd->use_sg)
		scsi_free_sgtable(cmd);
	if (cmd->sdb.table.nents)
		scsi_free_sgtable(&cmd->sdb);

	/*
	 * Zero these out.  They now point to freed memory, and it is
	 * dangerous to hang onto the pointers.
	 */
	cmd->request_buffer = NULL;
	cmd->request_bufflen = 0;
	memset(&cmd->sdb, 0, sizeof(cmd->sdb));
}
EXPORT_SYMBOL(scsi_release_buffers);

@@ -829,7 +824,7 @@ EXPORT_SYMBOL(scsi_release_buffers);
void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
{
	int result = cmd->result;
	int this_count = cmd->request_bufflen;
	int this_count = scsi_bufflen(cmd);
	struct request_queue *q = cmd->device->request_queue;
	struct request *req = cmd->request;
	int clear_errors = 1;
@@ -837,8 +832,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
	int sense_valid = 0;
	int sense_deferred = 0;

	scsi_release_buffers(cmd);

	if (result) {
		sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
		if (sense_valid)
@@ -861,9 +854,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
				req->sense_len = len;
			}
		}
		req->data_len = cmd->resid;
		req->data_len = scsi_get_resid(cmd);
	}

	scsi_release_buffers(cmd);

	/*
	 * Next deal with any sectors which we were able to correctly
	 * handle.
@@ -871,7 +866,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
	SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, "
				      "%d bytes done.\n",
				      req->nr_sectors, good_bytes));
	SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n", cmd->use_sg));

	if (clear_errors)
		req->errors = 0;
@@ -1002,35 +996,30 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
{
	struct request     *req = cmd->request;
	int		   count;

	/*
	 * We used to not use scatter-gather for single segment request,
	 * but now we do (it makes highmem I/O easier to support without
	 * kmapping pages)
	 */
	cmd->use_sg = req->nr_phys_segments;
	struct scsi_data_buffer *sdb = &cmd->sdb;

	/*
	 * If sg table allocation fails, requeue request later.
	 */
	if (unlikely(scsi_alloc_sgtable(cmd, gfp_mask))) {
	if (unlikely(scsi_alloc_sgtable(sdb, req->nr_phys_segments,
					gfp_mask))) {
		scsi_unprep_request(req);
		return BLKPREP_DEFER;
	}

	req->buffer = NULL;
	if (blk_pc_request(req))
		cmd->request_bufflen = req->data_len;
		sdb->length = req->data_len;
	else
		cmd->request_bufflen = req->nr_sectors << 9;
		sdb->length = req->nr_sectors << 9;

	/* 
	 * Next, walk the list, and fill in the addresses and sizes of
	 * each segment.
	 */
	count = blk_rq_map_sg(req->q, req, cmd->request_buffer);
	BUG_ON(count > cmd->use_sg);
	cmd->use_sg = count;
	count = blk_rq_map_sg(req->q, req, sdb->table.sgl);
	BUG_ON(count > sdb->table.nents);
	sdb->table.nents = count;
	return BLKPREP_OK;
}
EXPORT_SYMBOL(scsi_init_io);
@@ -1086,9 +1075,7 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
		BUG_ON(req->data_len);
		BUG_ON(req->data);

		cmd->request_bufflen = 0;
		cmd->request_buffer = NULL;
		cmd->use_sg = 0;
		memset(&cmd->sdb, 0, sizeof(cmd->sdb));
		req->buffer = NULL;
	}

+2 −2
Original line number Diff line number Diff line
@@ -519,7 +519,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
		SCpnt->cmnd[4] = (unsigned char) this_count;
		SCpnt->cmnd[5] = 0;
	}
	SCpnt->request_bufflen = this_count * sdp->sector_size;
	SCpnt->sdb.length = this_count * sdp->sector_size;

	/*
	 * We shouldn't disconnect in the middle of a sector, so with a dumb
@@ -926,7 +926,7 @@ static struct block_device_operations sd_fops = {
static int sd_done(struct scsi_cmnd *SCpnt)
{
	int result = SCpnt->result;
 	unsigned int xfer_size = SCpnt->request_bufflen;
	unsigned int xfer_size = scsi_bufflen(SCpnt);
 	unsigned int good_bytes = result ? 0 : xfer_size;
 	u64 start_lba = SCpnt->request->sector;
 	u64 bad_lba;
Loading