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

📄 scsi_target.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
intscsi_target_done(Target_Scsi_Cmnd * the_command){	the_command->state = ST_DEQUEUE;	/* awaken scsi_target_process_thread to dequeue stuff */	if (atomic_read(&target_data.target_sem.count) <= 0) {		up(&target_data.target_sem);	}	return 0;}/* * scsi_release: This function is called by a low-level driver when it * determines that it does not responses to certain commands. Situations * like this happen when for instance a LIP is received in a Fibre * Channel Loop or when a Logout is received in iSCSI before command * execution is completed. The low-level driver may no longer care about * receiving responses for those commands. This function can be called * from within interrupt context * INPUT: command to release * OUTPUT: 0 if success, < 0 if there is trouble */intscsi_release(Target_Scsi_Cmnd * cmnd){	cmnd->abort_code = CMND_RELEASED;	/*	 * if a command is processing, it is not nice to	 * dequeue a command, as we will get a response	 * anyways. This may be an inherent race condn	 * We catch what we can and move on. A second	 * check performed when hand_to_front_end is	 * called should catch the remaining commands	 * - Ashish	 */	if (cmnd->state != ST_PROCESSING)		cmnd->state = ST_DEQUEUE;	/* wake up scsi_process_target_thread so it can dequeue stuff */	if (atomic_read(&target_data.target_sem.count) <= 0) {		up(&target_data.target_sem);	}	return 0;}/* * rx_task_mgmt_fn: This function is called by a low-level driver to * indicate to the Mid-level that it has received a management function. * This function will decide the action to be taken in response to this * management function. This function will in turn create a message list * in the mid-level. CAN BE CALLED FROM INTERRUPT CONTEXT * INPUT: device, function, command - if relevant * OUTPUT: message or NULL if there is trouble * Definition of value: * 1. ABORT TASK * 	value = Target_Scsi_Cmnd * 2. ABORT TASK SET * 	This function cannot be directly performed since the Mid-Level * 	has no knowledge of what Initiators are logged in to the front- * 	end. This functionality can be achieved by issuing ABORTS to * 	various commands identified within the Task Set by the front * 	-end. value = N/A * 3. CLEAR ACA * 	I dont understand this one * 4. CLEAR TASK SET * 	Implement similar to ABORT Task Set - I know that all semantics * 	for this cannot be implemented (Any ideas ?) * 5. LUN RESET * 	set value = pointer to LUN * 6. TARGET RESET * 	set value = NULL */struct SM *rx_task_mgmt_fn(struct STD *dev, int fn, void *value){	unsigned long flags;	Target_Scsi_Message *msg;	if ((fn < TMF_ABORT_TASK) && (fn > TMF_TASK_REASSIGN)) {		printk("rx_task_mgmt_fn: Invalid value %d for Task Mgmt function\n",			   fn);		return NULL;	}	if ((fn == TMF_ABORT_TASK_SET) || (fn == TMF_CLEAR_ACA)		|| (fn == TMF_CLEAR_TASK_SET)) {		printk("rx_task_mgmt_fn: task mgmt function %d not implemented\n",			   fn);		return NULL;	}	if ((fn == TMF_ABORT_TASK) && (value == NULL)) {		printk("rx_task_mgmt_fn: Cannot abort a NULL command\n");		return NULL;	}	msg = (Target_Scsi_Message *)kmalloc(sizeof(Target_Scsi_Message),										 GFP_KERNEL | GFP_ATOMIC);	if (!msg) {		printk("rx_task_mgmt_fn: no space for scsi message\n");		return NULL;	}	msg->next = NULL;	msg->prev = NULL;	msg->device = dev;	msg->value = value;	msg->message = fn;	spin_lock_irqsave(&target_data.msg_lock, flags);	if (!target_data.msgq_start) {		target_data.msgq_start = target_data.msgq_end = msg;	} else {		target_data.msgq_end->next = msg;		target_data.msgq_end = msg;	}	spin_unlock_irqrestore(&target_data.msg_lock, flags);	/* wake up scsi_target_process_thread */	if (atomic_read(&target_data.target_sem.count) <= 0) {		up(&target_data.target_sem);	}	return msg;}# if defined (FILEIO) || defined (GENERICIO)/* * build_filp_table: builds up a table of open file descriptors. * INPUT: nothing * OUTPUT: 0 if all ok, < 0 if there was trouble */static intbuild_filp_table(void){	char *tmp;	int error;	int targ, lun, max_files, max_luns;	mm_segment_t old_fs;	struct file *dev_file;	struct target_map_item *this_item;	max_files = MAX_FILE_TARGETS;	if (max_files > MAX_TARGETS)		max_files = MAX_TARGETS;	max_luns = MAX_FILE_LUNS;	if (max_luns > MAX_LUNS)		max_luns = MAX_LUNS;	for (targ = 0; targ < max_files; targ++) {		for (lun = 0; lun < max_luns; lun++) {			this_item = &target_map[targ][lun];# if defined (GENERICIO)			if (targ == 0)				sprintf(this_item->file_name, "/dev/sg%d", lun);			else				sprintf(this_item->file_name, "dev/sg%d%d", targ, lun);# endif# if defined (FILEIO)			sprintf(this_item->file_name, "scsi_disk_file_%d_%d", targ, lun);# endif			printk("opening device %s\n", this_item->file_name);			old_fs = get_fs();			set_fs(get_ds());			tmp = getname(this_item->file_name);			set_fs(old_fs);			error = PTR_ERR(tmp);			if (IS_ERR(tmp)) {				printk("build_filp_table: getname returned error %d\n", error);				return -1;			}			/* open a file or a scsi_generic device */# ifdef GENERICIO			dev_file = filp_open(tmp, O_RDWR | O_NONBLOCK, 0600);# endif# ifdef FILEIO			dev_file = filp_open(tmp, O_RDWR | O_NONBLOCK | O_CREAT, 0600);# endif			putname(tmp);			if (IS_ERR(dev_file)) {				error = PTR_ERR(dev_file);				if (targ + lun == 0) {					printk("build_filp_table: filp_open returned error %d\n",							error);					return -1;				} else					goto out_of_loop;			} else {				/* mark this device "in-use" and save info about it */				this_item->the_file = dev_file;				this_item->max_blocks = FILESIZE;				this_item->bytes_per_block = BLOCKSIZE;				this_item->in_use = 1;				printk("opened file %s as id: %d lun: %d\n",						this_item->file_name, targ, lun);				target_count++;			}		}	}out_of_loop:# ifdef GENERICIO	/* also we spawn a second thread to receive signals */	init_MUTEX_LOCKED(&target_data.signal_sem);	init_MUTEX_LOCKED(&target_data.sig_thr_sem);	kernel_thread((int (*)(void *)) signal_process_thread, NULL, 0);# endif	return 0;}/* * close_filp_table: to close all the open file descriptors * INPUT: None * OUTPUT: None */static voidclose_filp_table(void){	__u32 targ, lun;	struct target_map_item *this_item;	if (!down_interruptible(&target_map_sem)) {		for (targ = 0; targ < MAX_TARGETS; targ++) {			for (lun = 0; lun < MAX_LUNS; lun++) {				this_item = &target_map[targ][lun];				if (this_item->the_file) {					filp_close(this_item->the_file, NULL);					this_item->the_file = NULL;					this_item->in_use = 0;				}			}		}		up(&target_map_sem);	}}# endif/* * : allocates scatter-gather buffers for the received command * The assumption is that all front-ends use scatter-gather and so do * the back-ends ... this may change. * INPUT: Scsi_Request for which space has to be allocated, space needed * OUTPUT: 0 if everything is okay, < 0 if there is trouble */static intget_space(Scsi_Request * req, int space /* in bytes */ ){	/* We assume that scatter gather is used universally */	struct scatterlist *st_buffer;	int buff_needed, i;	int count;	/* we assume that all buffers are split by page size */	/* get enough scatter gather entries */	buff_needed = space / PAGE_SIZE;	if (space > (buff_needed * PAGE_SIZE))		buff_needed++;	/*ramesh - added check for allocating memory */	if (buff_needed == 0)		buff_needed = 1;	st_buffer =		(struct scatterlist *)kmalloc(buff_needed *									   sizeof(struct scatterlist),									   GFP_KERNEL | GFP_ATOMIC);	if (!st_buffer) {		printk("get_space: no space for st_buffer\n");		return -1;	}	memset(st_buffer, 0, buff_needed * sizeof(struct scatterlist));	/* get necessary buffer space */	for (i = 0, count = space; i < buff_needed; i++, count -= PAGE_SIZE) {/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26		st_buffer[i].page = alloc_pages(GFP_DMA | GFP_KERNEL, 0);		if (!st_buffer[i].page) {			printk("get_space: no space for st_buffer[%d].page\n", i);			return -1;		}		sg_dma_address(st_buffer + i) = (dma_addr_t)kmap(st_buffer[i].page);		/* this should always be 0 */		st_buffer[i].offset = (unsigned long)			sg_dma_address(st_buffer + i) & ~PAGE_MASK;		if (count > PAGE_SIZE)			sg_dma_len(st_buffer + i) = PAGE_SIZE;		else			sg_dma_len(st_buffer + i) = count;#else		st_buffer[i].address =			(__u8 *) __get_free_pages(GFP_DMA | GFP_KERNEL, 0);		if (!st_buffer[i].address) {			printk("get_space: no space for st_buffer[%d].address\n", i);			return -1;		}		if (count > PAGE_SIZE)			st_buffer[i].length = PAGE_SIZE;		else			st_buffer[i].length = count;#endif/* df revised begin */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)/* Ming Zhang, mingz@ele.uri.edu */#ifndef K26		/* From 2.4.13, the structure scatterlist add a field "page", which is checked		 *   in pci_map_sg(pci.h), which is also changed from 2.4.13. So should set a NULL as		 *   initial value		 */		st_buffer[i].page = NULL;#endif#endif/* df revised end */# ifdef DEBUG_HANDLE_CMD/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26		printk("get_space: st_buffer[%d] = %d\n", i, sg_dma_len(st_buffer + i));#else		printk("get_space: st_buffer[%d] = %d\n", i, st_buffer[i].length);#endif# endif	}	req->sr_bufflen = space;	req->sr_buffer = st_buffer;	req->sr_sglist_len = buff_needed * sizeof(struct scatterlist);	req->sr_use_sg = buff_needed;	return 0;}#if !defined(DISKIO) || !defined(TRUST_CDB)/* * Returns size of space allocated for LUN list > 0 if all ok, * -1 on error after giving message */static intallocate_report_lun_space(Target_Scsi_Cmnd * cmnd){	int i, luns, size;# ifdef DEBUG_HANDLE_CMD	printk("REPORT_LUNS received\n");# endif	/* perform checks on Report LUNS - LATER */	if (cmnd->req->sr_cmnd[2] != 0) {		printk("%s Select_Report in report_luns not zero\n", current->comm);	}	/* set data direction */	cmnd->req->sr_data_direction = SCSI_DATA_READ;	/* get length */	if (cmnd->target_id >= MAX_TARGETS) {		printk("%s target id %u >= MAX_TARGETS %u\n",			   current->comm, cmnd->target_id, MAX_TARGETS);		return -1;	}	luns = 0;	if (!down_interruptible(&target_map_sem)) {		for (i = 0; i < MAX_LUNS; i++) {			if (target_map[cmnd->target_id][i].in_use)				luns++;		}		up(&target_map_sem);	}	if (luns == 0) {		printk("%s No luns in use for target id %u\n",			   current->comm, cmnd->target_id);		return -1;		}	printk("%s REPORT_LUNS: target id %u reporting %d luns\n",			current->comm, cmnd->target_id, luns);	/* allocate space */	size = luns * 8;	if (get_space(cmnd->req, size + 8)) {		printk("%s get_space returned an error for %d\n",			   current->comm, cmnd->id);		return -1;		}	return size;}/* * get_allocation_length: This function looks at the received command * and calculates the size of the buffer to be allocated in order to * execute the command. * INPUT: pointer to command received * OUTPUT: buffer needing to be allocated or < 0 if there is an error */static __u32 __attribute__ ((no_instrument_function))get_allocation_length(__u8 *cmd){	__u32 err = 0;	switch (cmd[0]) {	case INQUIRY:	case MODE_SENSE:	case MODE_SELECT:		{			err = cmd[ALLOC_LEN_6];# ifdef DEBUG_ALLOCN_LEN			printk				("get_allocation_length: INQUIRY/MODE SENSE/MODE SELECT length %d\n",				 err);# endif			break;		}	case WRITE_10:	case READ_10:	case VERIFY:		{			err = (cmd[ALLOC_LEN_10] << BYTE) + cmd[ALLOC_LEN_10 + 1];			err *= BLOCKSIZE;# ifdef DEBUG_ALLOCN_LEN			printk("get_allocation_length: READ_10/WRITE_10 length %d\n", err);# endif			break;		}		/* cdeng, August 24 2002, Report luns */	case REPORT_LUNS:		{			/* Bjorn Thordarson, 10 May 2004 */			/*****			err = (cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8) + cmd[9];			*****/			err = 0;# ifdef DEBUG_ALLOCN_LEN			printk("get_allocation_length: REPORT_LUNS length %d - FIXME\n", err);# endif			break;		}# ifdef TAPE_DEVICE	case READ_6:	case WRITE_6:		{			err = (cmd[2] << 16) + (cmd[3] << 8) + cmd[4];			if (1 == cmd[1]) {				err *= BLOCKSIZE;	/*ramesh - need to check the block size, right now it is fixed */			}# ifdef DEBUG_ALLOCN_LEN			printk("get_allocation_length: READ_6/WRITE_6 length %d\n", err);# endif			break;		}#else	case READ_6:	case WRITE_6:

⌨️ 快捷键说明

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