⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsi_tgt_lib.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
{	struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);	int err;	dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request));	err = shost->hostt->transfer_response(cmd, scsi_tgt_cmd_done);	switch (err) {	case SCSI_MLQUEUE_HOST_BUSY:	case SCSI_MLQUEUE_DEVICE_BUSY:		return -EAGAIN;	}	return 0;}static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask){	struct request *rq = cmd->request;	int count;	cmd->use_sg = rq->nr_phys_segments;	cmd->request_buffer = scsi_alloc_sgtable(cmd, gfp_mask);	if (!cmd->request_buffer)		return -ENOMEM;	cmd->request_bufflen = rq->data_len;	dprintk("cmd %p cnt %d %lu\n", cmd, cmd->use_sg, rq_data_dir(rq));	count = blk_rq_map_sg(rq->q, rq, cmd->request_buffer);	if (likely(count <= cmd->use_sg)) {		cmd->use_sg = count;		return 0;	}	eprintk("cmd %p cnt %d\n", cmd, cmd->use_sg);	scsi_free_sgtable(cmd);	return -EINVAL;}/* TODO: test this crap and replace bio_map_user with new interface maybe */static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd,			       unsigned long uaddr, unsigned int len, int rw){	struct request_queue *q = cmd->request->q;	struct request *rq = cmd->request;	int err;	dprintk("%lx %u\n", uaddr, len);	err = blk_rq_map_user(q, rq, (void *)uaddr, len);	if (err) {		/*		 * TODO: need to fixup sg_tablesize, max_segment_size,		 * max_sectors, etc for modern HW and software drivers		 * where this value is bogus.		 *		 * TODO2: we can alloc a reserve buffer of max size		 * we can handle and do the slow copy path for really large		 * IO.		 */		eprintk("Could not handle request of size %u.\n", len);		return err;	}	tcmd->bio = rq->bio;	err = scsi_tgt_init_cmd(cmd, GFP_KERNEL);	if (err)		goto unmap_rq;	return 0;unmap_rq:	scsi_unmap_user_pages(tcmd);	return err;}static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr,				unsigned len){	char __user *p = (char __user *) uaddr;	if (copy_from_user(cmd->sense_buffer, p,			   min_t(unsigned, SCSI_SENSE_BUFFERSIZE, len))) {		printk(KERN_ERR "Could not copy the sense buffer\n");		return -EIO;	}	return 0;}static int scsi_tgt_abort_cmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd){	struct scsi_tgt_cmd *tcmd;	int err;	err = shost->hostt->eh_abort_handler(cmd);	if (err)		eprintk("fail to abort %p\n", cmd);	tcmd = cmd->request->end_io_data;	scsi_tgt_cmd_destroy(&tcmd->work);	return err;}static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag){	struct scsi_tgt_queuedata *qdata = q->queuedata;	struct request *rq = NULL;	struct list_head *head;	struct scsi_tgt_cmd *tcmd;	unsigned long flags;	head = &qdata->cmd_hash[cmd_hashfn(tag)];	spin_lock_irqsave(&qdata->cmd_hash_lock, flags);	list_for_each_entry(tcmd, head, hash_list) {		if (tcmd->tag == tag) {			rq = tcmd->rq;			list_del(&tcmd->hash_list);			break;		}	}	spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);	return rq;}int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag,			 unsigned long uaddr, u32 len, unsigned long sense_uaddr,			 u32 sense_len, u8 rw){	struct Scsi_Host *shost;	struct scsi_cmnd *cmd;	struct request *rq;	struct scsi_tgt_cmd *tcmd;	int err = 0;	dprintk("%d %llu %d %u %lx %u\n", host_no, (unsigned long long) tag,		result, len, uaddr, rw);	/* TODO: replace with a O(1) alg */	shost = scsi_host_lookup(host_no);	if (IS_ERR(shost)) {		printk(KERN_ERR "Could not find host no %d\n", host_no);		return -EINVAL;	}	if (!shost->uspace_req_q) {		printk(KERN_ERR "Not target scsi host %d\n", host_no);		goto done;	}	rq = tgt_cmd_hash_lookup(shost->uspace_req_q, tag);	if (!rq) {		printk(KERN_ERR "Could not find tag %llu\n",		       (unsigned long long) tag);		err = -EINVAL;		goto done;	}	cmd = rq->special;	dprintk("cmd %p scb %x result %d len %d bufflen %u %lu %x\n",		cmd, cmd->cmnd[0], result, len, cmd->request_bufflen,		rq_data_dir(rq), cmd->cmnd[0]);	if (result == TASK_ABORTED) {		scsi_tgt_abort_cmd(shost, cmd);		goto done;	}	/*	 * store the userspace values here, the working values are	 * in the request_* values	 */	tcmd = cmd->request->end_io_data;	cmd->result = result;	if (cmd->result == SAM_STAT_CHECK_CONDITION)		scsi_tgt_copy_sense(cmd, sense_uaddr, sense_len);	if (len) {		err = scsi_map_user_pages(rq->end_io_data, cmd, uaddr, len, rw);		if (err) {			/*			 * user-space daemon bugs or OOM			 * TODO: we can do better for OOM.			 */			struct scsi_tgt_queuedata *qdata;			struct list_head *head;			unsigned long flags;			eprintk("cmd %p ret %d uaddr %lx len %d rw %d\n",				cmd, err, uaddr, len, rw);			qdata = shost->uspace_req_q->queuedata;			head = &qdata->cmd_hash[cmd_hashfn(tcmd->tag)];			spin_lock_irqsave(&qdata->cmd_hash_lock, flags);			list_add(&tcmd->hash_list, head);			spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);			goto done;		}	}	err = scsi_tgt_transfer_response(cmd);done:	scsi_host_put(shost);	return err;}int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, u64 itn_id,			      int function, u64 tag, struct scsi_lun *scsilun,			      void *data){	int err;	/* TODO: need to retry if this fails. */	err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, itn_id,					    function, tag, scsilun, data);	if (err < 0)		eprintk("The task management request lost!\n");	return err;}EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request);int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result){	struct Scsi_Host *shost;	int err = -EINVAL;	dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid);	shost = scsi_host_lookup(host_no);	if (IS_ERR(shost)) {		printk(KERN_ERR "Could not find host no %d\n", host_no);		return err;	}	if (!shost->uspace_req_q) {		printk(KERN_ERR "Not target scsi host %d\n", host_no);		goto done;	}	err = shost->transportt->tsk_mgmt_response(shost, itn_id, mid, result);done:	scsi_host_put(shost);	return err;}int scsi_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id,			     char *initiator){	int err;	/* TODO: need to retry if this fails. */	err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, itn_id, 0,						    initiator);	if (err < 0)		eprintk("The i_t_neuxs request lost, %d %llx!\n",			shost->host_no, (unsigned long long)itn_id);	return err;}EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_create);int scsi_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id){	int err;	/* TODO: need to retry if this fails. */	err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no,						    itn_id, 1, NULL);	if (err < 0)		eprintk("The i_t_neuxs request lost, %d %llx!\n",			shost->host_no, (unsigned long long)itn_id);	return err;}EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_destroy);int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result){	struct Scsi_Host *shost;	int err = -EINVAL;	dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid);	shost = scsi_host_lookup(host_no);	if (IS_ERR(shost)) {		printk(KERN_ERR "Could not find host no %d\n", host_no);		return err;	}	if (!shost->uspace_req_q) {		printk(KERN_ERR "Not target scsi host %d\n", host_no);		goto done;	}	err = shost->transportt->it_nexus_response(shost, itn_id, result);done:	scsi_host_put(shost);	return err;}static int __init scsi_tgt_init(void){	int err;	scsi_tgt_cmd_cache = kmem_cache_create("scsi_tgt_cmd",					       sizeof(struct scsi_tgt_cmd),					       0, 0, NULL);	if (!scsi_tgt_cmd_cache)		return -ENOMEM;	scsi_tgtd = create_workqueue("scsi_tgtd");	if (!scsi_tgtd) {		err = -ENOMEM;		goto free_kmemcache;	}	err = scsi_tgt_if_init();	if (err)		goto destroy_wq;	return 0;destroy_wq:	destroy_workqueue(scsi_tgtd);free_kmemcache:	kmem_cache_destroy(scsi_tgt_cmd_cache);	return err;}static void __exit scsi_tgt_exit(void){	destroy_workqueue(scsi_tgtd);	scsi_tgt_if_exit();	kmem_cache_destroy(scsi_tgt_cmd_cache);}module_init(scsi_tgt_init);module_exit(scsi_tgt_exit);MODULE_DESCRIPTION("SCSI target core");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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