scsi_lib.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,742 行 · 第 1/4 页

C
1,742
字号
		blk_run_queue(sdev->request_queue);		spin_lock_irqsave(shost->host_lock, flags);		if (unlikely(!list_empty(&sdev->starved_entry)))			/*			 * sdev lost a race, and was put back on the			 * starved list. This is unlikely but without this			 * in theory we could loop forever.			 */			break;	}	spin_unlock_irqrestore(shost->host_lock, flags);	blk_run_queue(q);}/* * Function:	scsi_requeue_command() * * Purpose:	Handle post-processing of completed commands. * * Arguments:	q	- queue to operate on *		cmd	- command that may need to be requeued. * * Returns:	Nothing * * Notes:	After command completion, there may be blocks left *		over which weren't finished by the previous command *		this can be for a number of reasons - the main one is *		I/O errors in the middle of the request, in which case *		we need to request the blocks that come after the bad *		sector. */static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd){	cmd->request->flags &= ~REQ_DONTPREP;	blk_insert_request(q, cmd->request, 1, cmd, 1);	scsi_run_queue(q);}void scsi_next_command(struct scsi_cmnd *cmd){	struct request_queue *q = cmd->device->request_queue;	scsi_put_command(cmd);	scsi_run_queue(q);}void scsi_run_host_queues(struct Scsi_Host *shost){	struct scsi_device *sdev;	shost_for_each_device(sdev, shost)		scsi_run_queue(sdev->request_queue);}/* * Function:    scsi_end_request() * * Purpose:     Post-processing of completed commands called from interrupt *              handler or a bottom-half handler. * * Arguments:   cmd	 - command that is complete. *              uptodate - 1 if I/O indicates success, 0 for I/O error. *              sectors  - number of sectors we want to mark. *		requeue  - indicates whether we should requeue leftovers. *		frequeue - indicates that if we release the command block *			   that the queue request function should be called. * * Lock status: Assumed that lock is not held upon entry. * * Returns:     Nothing * * Notes:       This is called for block device requests in order to *              mark some number of sectors as complete. *  *		We are guaranteeing that the request queue will be goosed *		at some point during this call. */static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,					  int bytes, int requeue){	request_queue_t *q = cmd->device->request_queue;	struct request *req = cmd->request;	unsigned long flags;	/*	 * If there are blocks left over at the end, set up the command	 * to queue the remainder of them.	 */	if (end_that_request_chunk(req, uptodate, bytes)) {		int leftover = (req->hard_nr_sectors << 9);		if (blk_pc_request(req))			leftover = req->data_len;		/* kill remainder if no retrys */		if (!uptodate && blk_noretry_request(req))			end_that_request_chunk(req, 0, leftover);		else {			if (requeue)				/*				 * Bleah.  Leftovers again.  Stick the				 * leftovers in the front of the				 * queue, and goose the queue again.				 */				scsi_requeue_command(q, cmd);			return cmd;		}	}	add_disk_randomness(req->rq_disk);	spin_lock_irqsave(q->queue_lock, flags);	if (blk_rq_tagged(req))		blk_queue_end_tag(q, req);	end_that_request_last(req);	spin_unlock_irqrestore(q->queue_lock, flags);	/*	 * This will goose the queue request function at the end, so we don't	 * need to worry about launching another command.	 */	scsi_next_command(cmd);	return NULL;}static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, int gfp_mask){	struct scsi_host_sg_pool *sgp;	struct scatterlist *sgl;	BUG_ON(!cmd->use_sg);	switch (cmd->use_sg) {	case 1 ... 8:		cmd->sglist_len = 0;		break;	case 9 ... 16:		cmd->sglist_len = 1;		break;	case 17 ... 32:		cmd->sglist_len = 2;		break;#if (SCSI_MAX_PHYS_SEGMENTS > 32)	case 33 ... 64:		cmd->sglist_len = 3;		break;#if (SCSI_MAX_PHYS_SEGMENTS > 64)	case 65 ... 128:		cmd->sglist_len = 4;		break;#if (SCSI_MAX_PHYS_SEGMENTS  > 128)	case 129 ... 256:		cmd->sglist_len = 5;		break;#endif#endif#endif	default:		return NULL;	}	sgp = scsi_sg_pools + cmd->sglist_len;	sgl = mempool_alloc(sgp->pool, gfp_mask);	if (sgl)		memset(sgl, 0, sgp->size);	return sgl;}static void scsi_free_sgtable(struct scatterlist *sgl, int index){	struct scsi_host_sg_pool *sgp;	BUG_ON(index > SG_MEMPOOL_NR);	sgp = scsi_sg_pools + index;	mempool_free(sgl, sgp->pool);}/* * Function:    scsi_release_buffers() * * Purpose:     Completion processing for block device I/O requests. * * Arguments:   cmd	- command that we are bailing. * * Lock status: Assumed that no lock is held upon entry. * * Returns:     Nothing * * Notes:       In the event that an upper level driver rejects a *		command, we must release resources allocated during *		the __init_io() function.  Primarily this would involve *		the scatter-gather table, and potentially any bounce *		buffers. */static void scsi_release_buffers(struct scsi_cmnd *cmd){	struct request *req = cmd->request;	/*	 * Free up any indirection buffers we allocated for DMA purposes. 	 */	if (cmd->use_sg)		scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);	else if (cmd->request_buffer != req->buffer)		kfree(cmd->request_buffer);	/*	 * Zero these out.  They now point to freed memory, and it is	 * dangerous to hang onto the pointers.	 */	cmd->buffer  = NULL;	cmd->bufflen = 0;	cmd->request_buffer = NULL;	cmd->request_bufflen = 0;}/* * Function:    scsi_io_completion() * * Purpose:     Completion processing for block device I/O requests. * * Arguments:   cmd   - command that is finished. * * Lock status: Assumed that no lock is held upon entry. * * Returns:     Nothing * * Notes:       This function is matched in terms of capabilities to *              the function that created the scatter-gather list. *              In other words, if there are no bounce buffers *              (the normal case for most drivers), we don't need *              the logic to deal with cleaning up afterwards. * *		We must do one of several things here: * *		a) Call scsi_end_request.  This will finish off the *		   specified number of sectors.  If we are done, the *		   command block will be released, and the queue *		   function will be goosed.  If we are not done, then *		   scsi_end_request will directly goose the queue. * *		b) We can just use scsi_requeue_command() here.  This would *		   be used if we just wanted to retry, for example. */void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,			unsigned int block_bytes){	int result = cmd->result;	int this_count = cmd->bufflen;	request_queue_t *q = cmd->device->request_queue;	struct request *req = cmd->request;	int clear_errors = 1;	/*	 * Free up any indirection buffers we allocated for DMA purposes. 	 * For the case of a READ, we need to copy the data out of the	 * bounce buffer and into the real buffer.	 */	if (cmd->use_sg)		scsi_free_sgtable(cmd->buffer, cmd->sglist_len);	else if (cmd->buffer != req->buffer) {		if (rq_data_dir(req) == READ) {			unsigned long flags;			char *to = bio_kmap_irq(req->bio, &flags);			memcpy(to, cmd->buffer, cmd->bufflen);			bio_kunmap_irq(to, &flags);		}		kfree(cmd->buffer);	}	if (blk_pc_request(req)) { /* SG_IO ioctl from block level */		req->errors = (driver_byte(result) & DRIVER_SENSE) ?			      (CHECK_CONDITION << 1) : (result & 0xff);		if (result) {			clear_errors = 0;			if (cmd->sense_buffer[0] & 0x70) {				int len = 8 + cmd->sense_buffer[7];				if (len > SCSI_SENSE_BUFFERSIZE)					len = SCSI_SENSE_BUFFERSIZE;				memcpy(req->sense, cmd->sense_buffer,  len);				req->sense_len = len;			}		} else			req->data_len -= cmd->bufflen;	}	/*	 * Zero these out.  They now point to freed memory, and it is	 * dangerous to hang onto the pointers.	 */	cmd->buffer  = NULL;	cmd->bufflen = 0;	cmd->request_buffer = NULL;	cmd->request_bufflen = 0;	/*	 * Next deal with any sectors which we were able to correctly	 * handle.	 */	if (good_bytes >= 0) {		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;		/*		 * If multiple sectors are requested in one buffer, then		 * they will have been finished off by the first command.		 * If not, then we have a multi-buffer command.		 *		 * If block_bytes != 0, it means we had a medium error		 * of some sort, and that we want to mark some number of		 * sectors as not uptodate.  Thus we want to inhibit		 * requeueing right here - we will requeue down below		 * when we handle the bad sectors.		 */		cmd = scsi_end_request(cmd, 1, good_bytes, result == 0);		/*		 * If the command completed without error, then either finish off the		 * rest of the command, or start a new one.		 */		if (result == 0 || cmd == NULL ) {			return;		}	}	/*	 * Now, if we were good little boys and girls, Santa left us a request	 * sense buffer.  We can extract information from this, so we	 * can choose a block to remap, etc.	 */	if (driver_byte(result) != 0) {		if ((cmd->sense_buffer[0] & 0x7f) == 0x70) {			/*			 * If the device is in the process of becoming ready,			 * retry.			 */			if (cmd->sense_buffer[12] == 0x04 &&			    cmd->sense_buffer[13] == 0x01) {				scsi_requeue_command(q, cmd);				return;			}			if ((cmd->sense_buffer[2] & 0xf) == UNIT_ATTENTION) {				if (cmd->device->removable) {					/* detected disc change.  set a bit 					 * and quietly refuse further access.		 			 */					cmd->device->changed = 1;					cmd = scsi_end_request(cmd, 0,							this_count, 1);					return;				} else {					/*				 	* Must have been a power glitch, or a				 	* bus reset.  Could not have been a				 	* media change, so we just retry the				 	* request and see what happens.  				 	*/					scsi_requeue_command(q, cmd);					return;				}			}		}		/*		 * If we had an ILLEGAL REQUEST returned, then we may have		 * performed an unsupported command.  The only thing this		 * should be would be a ten byte read where only a six byte		 * read was supported.  Also, on a system where READ CAPACITY		 * failed, we may have read past the end of the disk.		 */		switch (cmd->sense_buffer[2]) {		case ILLEGAL_REQUEST:			if (cmd->device->use_10_for_rw &&			    (cmd->cmnd[0] == READ_10 ||			     cmd->cmnd[0] == WRITE_10)) {				cmd->device->use_10_for_rw = 0;				/*				 * This will cause a retry with a 6-byte				 * command.				 */				scsi_requeue_command(q, cmd);				result = 0;			} else {				cmd = scsi_end_request(cmd, 0, this_count, 1);				return;			}			break;		case NOT_READY:			printk(KERN_INFO "Device %s not ready.\n",			       req->rq_disk ? req->rq_disk->disk_name : "");			cmd = scsi_end_request(cmd, 0, this_count, 1);			return;			break;		case MEDIUM_ERROR:		case VOLUME_OVERFLOW:			printk("scsi%d: ERROR on channel %d, id %d, lun %d, CDB: ",			       cmd->device->host->host_no, (int) cmd->device->channel,			       (int) cmd->device->id, (int) cmd->device->lun);			__scsi_print_command(cmd->data_cmnd);			scsi_print_sense("", cmd);			cmd = scsi_end_request(cmd, 0, block_bytes, 1);			return;		default:			break;		}	}			/* driver byte != 0 */	if (host_byte(result) == DID_RESET) {		/*		 * Third party bus reset or reset for error		 * recovery reasons.  Just retry the request		 * and see what happens.  		 */		scsi_requeue_command(q, cmd);		return;	}	if (result) {		printk("SCSI error : <%d %d %d %d> return code = 0x%x\n",		       cmd->device->host->host_no,		       cmd->device->channel,		       cmd->device->id,		       cmd->device->lun, result);		if (driver_byte(result) & DRIVER_SENSE)			scsi_print_sense("", cmd);		/*		 * Mark a single buffer as not uptodate.  Queue the remainder.		 * We sometimes get this cruft in the event that a medium error

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?