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 + -
显示快捷键?