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

📄 scsi_target.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (!strcmp(st_dev_curr->template->name, the_template->name)) {# ifdef DEBUG_DEREGISTER				printk("dereg...tmpt: Match found for %s%d\n",					   st_dev_curr->template->name, (int) st_dev_curr->id);# endif				deregister_target_front_end(st_dev_curr);				st_dev_curr = target_data.st_device_list;	// Edward				break;			} else {				st_dev_curr = st_dev_curr->next;				if (st_dev_curr) {					printk						("dereg..tmpt: Error ... no device found with the required template %s\n",						 the_template->name);					return -1;				}			}		}	}	/* remove template from device list */	for (st_current = target_data.st_target_template; st_current != NULL;		 st_current = st_current->next) {# ifdef DEBUG_DEREGISTER		printk("Looping dereg template\n");# endif		if (!strcmp(st_current->name, the_template->name)) {# ifdef DEBUG_DEREGISTER			/* match found */			printk("deregister_template: template match found\n");# endif			/* check if there are any devices using this template */			if (!st_current->device_usage) {				/* this template can be removed */				if (!st_prev)	/* First element */					target_data.st_target_template =						target_data.st_target_template->next;				else			/* middle of the road */					st_prev->next = st_current->next;				break;			} else {			/* A device still uses the template */				printk("scsi_target: Non-zero device usage ouch !!\n");				return -1;	/* should never get here */			}		} else			st_prev = st_current;	}# ifdef DEBUG_DEREGISTER	printk("Decreasing module count\n");# endif/* Ming Zhang, mingz@ele.uri.edu */#ifndef K26	MOD_DEC_USE_COUNT;#endif	return 0;}/* * register_target_front_end: * FUNCTION: 	to register the individual device with the mid-level * 		to allocate the device an device id etc * 		start a thread that will be responsible for the target * INPUT:	pointer to a struct STD * OUTPUT:	Scsi_Target_Device - if everything is okay * 		else NULL if there is trouble */Scsi_Target_Device *register_target_front_end(Scsi_Target_Template * tmpt){	Scsi_Target_Device *the_device;	the_device =		(Scsi_Target_Device *)kmalloc(sizeof(Scsi_Target_Device), GFP_KERNEL);	if (!the_device) {		printk			("register_target_front_end: Could not allocate space for the device\n");		return NULL;	}	if (!tmpt) {		printk			("register_target_front_end: Cannot register NULL device template !!!\n");		return NULL;	}	/* fill up the struct */	the_device->template = tmpt;	the_device->next = target_data.st_device_list;	if (the_device->next)		the_device->id = the_device->next->id + 1;	else		the_device->id = 0;		/* first device */	target_data.st_device_list = the_device;# ifdef DEBUG_DEREGISTER	printk("reg..end: device %s%d added\n", tmpt->name, (int) the_device->id);# endif	/* Added by naren for proc support */#ifdef CONFIG_PROC_FS	build_proc_target_dir_entries(the_device);#endif	tmpt->device_usage++;	return the_device;}/* * deregister_target_front_end: * FUNCTION:	to allow removal of the individual device from the * 		midlevel * 		free up the device id number for future use * 		close the thread responsible for the target after making * 		sure that all existing commands have been responded to * 		we need to do serious error checking since this can be * 		called by different front-ends * 		CANNOT BE CALLED FROM INTERRUPT CONTEXT * INPUT:	pointer to a struct STD to be removed * OUTPUT:	int - 0 if everything is okay * 		else < 0 if there is trouble */intderegister_target_front_end(Scsi_Target_Device * the_device){	Scsi_Target_Device *curr, *previous = NULL;	Target_Scsi_Cmnd *cmnd;	unsigned long flags;	if (!the_device) {		printk			("dereg...end: cannot remove NULL devices corresponding to a NULL template\n");		return -1;	}	if (!the_device->template->device_usage) {		printk			("dereg...end: 0 device usage and a device to deregister ... a contradiction me thinks\n");	}	/*	 * go through the device list till we get to this device and	 * then remove it from the list	 */	for (curr = target_data.st_device_list; curr != NULL; curr = curr->next) {		if (curr == the_device) {# ifdef DEBUG_DEREGISTER			printk("dereg..end: We have a match\n");# endif			break;		} else			previous = curr;	}	if (!curr) {				/* No match found */		printk("dereg..end: No match found\n");		return -1;	}	/* remove it from the list */	if (previous)				/* not the first device */		previous->next = curr->next;	else		target_data.st_device_list = curr->next;	/* release the device */	if (curr->template->release) {		if (curr->template->release(curr)) {			printk("dereg...end: release of device failed\n");			return -1;		}	}	/* mark all commands corresponding to this device for dequeuing */	spin_lock_irqsave(&target_data.cmd_queue_lock, flags);	list_for_each_entry(cmnd, &target_data.cmd_queue, link) {		if (cmnd->dev_id == curr->id)			cmnd->state = ST_DEQUEUE;	}	spin_unlock_irqrestore(&target_data.cmd_queue_lock, flags);	/* wake up scsi_target_process_thread so it can dequeue stuff */	if (atomic_read(&target_data.target_sem.count) <= 0) {		up(&target_data.target_sem);	}	/* reduce device usage */	curr->template->device_usage--;	/* freeing things */	kfree(curr);	curr = NULL;	return 0;}# ifdef GENERICIO# define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC)/* * signal_process_thread: This thread is responsible for receiving SIGIO * signals when SCSI generic is used for processing. This receives the * SIGIO signal, changes the state of the oldest command that is in the * ST_PROCESSING state and goes back to sleep. I found this to be * necessary because signals tend to screw up the processing of the scsi * generic commands. Hopefully this will clear things up */voidsignal_process_thread(void *param){	int i, sigioflag = 0;	struct file *dev_file;	Target_Scsi_Cmnd *cmd_curr;	unsigned long arg;	unsigned long flags;	__u32 targ, lun;	lock_kernel();/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26	daemonize(#else	daemonize();	strcpy(current->comm,#endif		   "signal_thread");#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 18)	/*	 * Arne Redlich, agr1@users.sourceforge.net:	 * This prevents the signal thread from becoming a zombie after it exits.	 */	reparent_to_init();#endif	/* also we want to be able to receive SIGIO */	siginitsetinv(&current->blocked, IO_SIGS);	/* mark that this signal thread is alive */	target_data.signal_id = current;	unlock_kernel();	printk("%s Starting pid %d\n", current->comm, current->pid);	/*	 * we must now prepare this thread to receive the SIGIO signal	 * for the opened SCSI device(s)	 */	down_interruptible(&target_map_sem);	for (targ = 0; targ < MAX_TARGETS; targ++) {		for (lun = 0; lun < MAX_LUNS; lun++) {			if ((dev_file = target_map[targ][lun].the_file)) {				arg = dev_file->f_flags | FASYNC;				lock_kernel();				/* equal to fcntl (fd, F_SETOWN, getpid()) */				dev_file->f_owner.pid = current->pid;				dev_file->f_owner.uid = current->uid;				dev_file->f_owner.euid = current->euid;				/* equal to fcntl (fd,F_SETFL,flags|O_ASYNC) */				if ((arg ^ dev_file->f_flags) & FASYNC) {					if (dev_file->f_op && dev_file->f_op->fasync) {						i = dev_file->f_op->fasync(0, dev_file,												   (arg & FASYNC) != 0);						if (i < 0) {							unlock_kernel();							up(&target_map_sem);							printk("si..thread: fasync returned %d\n", i);							return;						}					}				}				/* required for strict SunOS emulation */				/*				   if (O_NONBLOCK != O_NDELAY)				   if (arg & O_NDELAY)				   arg |= O_NONBLOCK;				 */				dev_file->f_flags =					(arg & SETFL_MASK) | (dev_file->f_flags & ~SETFL_MASK);				unlock_kernel();			}		}	}	up(&target_map_sem);	while (1) {		down_interruptible(&target_data.sig_thr_sem);		sigioflag = 0;#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 18)		if (signal_pending(current)) {			spin_lock_irq(&current->sigmask_lock);			if (sigismember(&current->pending.signal, SIGIO)) {# ifdef DEBUG_SCSI_THREAD				printk("SIGIO received\n");# endif				sigioflag = 1;				sigdelset(&current->pending.signal, SIGIO);			}			recalc_sigpending(current);			spin_unlock_irq(&current->sigmask_lock);			if (!sigioflag) {				printk("si...thread: time to die\n");				break;			}		}#else		if (signal_pending(current)) {			spin_lock_irq(&current->sighand->siglock);			if (sigtestsetmask(&current->pending.signal, sigmask(SIGIO))) {# ifdef DEBUG_SCSI_THREAD				printk("SIGIO received\n");# endif				sigioflag = 1;				sigdelsetmask(&current->pending.signal, sigmask(SIGIO));			}			recalc_sigpending_tsk(current);			spin_unlock_irq(&current->sighand->siglock);			if (!sigioflag) {				printk("si...thread: time to die\n");				break;			}		}#endif		/* change the state of all PROCESSING commands */		spin_lock_irqsave(&target_data.cmd_queue_lock, flags);		list_for_each_entry(cmd_curr, &target_data.cmd_queue, link) {			if (cmd_curr->state == ST_PROCESSING) {				cmd_curr->state = ST_PROCESSED;				/* wake up scsi_target_process_thread */				if (atomic_read(&target_data.target_sem.count) <= 0) {					up(&target_data.target_sem);				}			}		}		spin_unlock_irqrestore(&target_data.cmd_queue_lock, flags);	}	up(&target_data.signal_sem);	printk("%s Exiting pid %d\n", current->comm, current->pid);}# endif/* * scsi_target_process_thread: this is the mid-level target thread that * is responsible for processing commands. */voidscsi_target_process_thread(void *param){	int i, found;# ifdef GENERICIO	mm_segment_t old_fs;	struct file *dev_file;# endif	struct scatterlist *st_list;	Target_Scsi_Cmnd *cmd_curr;	Target_Scsi_Message *msg;	unsigned long flags;	__u32 lun;# ifdef DISKIO	Scsi_Device *this_device = NULL;	struct target_map_item *this_item;# endif	struct list_head *lptr, *next;	lock_kernel();/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26	daemonize(#else	daemonize();	strcpy(current->comm,#endif		   "target_thread");#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 18)	/*	 * Arne Redlich, agr1@users.sourceforge.net:	 * This prevents the target thread from becoming a zombie after it exits.	 */	reparent_to_init();#endif	siginitsetinv(&current->blocked, SHUTDOWN_SIGS);	/* mark that this target thread is alive */	target_data.thread_id = current;	unlock_kernel();	printk("%s Starting pid %d\n", current->comm, current->pid);	while (1) {		if (down_interruptible(&target_data.target_sem))			goto scsi_thread_out;# ifdef DEBUG_SCSI_THREAD		printk("%s awake (%p)\n", current->comm, current);# endif		/* is message received */		while (target_data.msgq_start) {			/* house keeping */			spin_lock_irqsave(&target_data.msg_lock, flags);			msg = target_data.msgq_start;			target_data.msgq_start = msg->next;			if (!target_data.msgq_start)				target_data.msgq_end = NULL;			spin_unlock_irqrestore(&target_data.msg_lock, flags);			/* execute function */			switch (msg->message) {			case TMF_ABORT_TASK:				{					Target_Scsi_Cmnd *cmnd;					cmnd = (Target_Scsi_Cmnd *)msg->value;					found = 0;					spin_lock_irqsave(&target_data.cmd_queue_lock, flags);					list_for_each_entry(cmd_curr,&target_data.cmd_queue,link) {						if ((cmd_curr->id == cmnd->id)							&& (cmd_curr->lun == cmnd->lun)) {							found = 1;							break;						}					}					spin_unlock_irqrestore(&target_data.cmd_queue_lock, flags);					if (found) {						cmd_curr->abort_code = CMND_ABORTED;						//if (cmd_curr->state != ST_PROCESSING)						//	cmd_curr->state = ST_DEQUEUE;						if (abort_notify(msg)) {							printk("%s err aborting command with id %d lun %d\n",								   current->comm, cmd_curr->id, cmd_curr->lun);							goto scsi_thread_out;						}					} else						printk("%s no command with id %d lun %d in list\n",								current->comm, cmnd->id, cmnd->lun);					break;				}			case TMF_LUN_RESET:				{					/* BAD BAD REALLY BAD */					__u64 lun = *((__u64 *)msg->value);					spin_lock_irqsave(&target_data.cmd_queue_lock, flags);					list_for_each_entry(cmd_curr,&target_data.cmd_queue,link) {						if (cmd_curr->lun == lun)							scsi_release(cmd_curr);					}					spin_unlock_irqrestore(&target_data.cmd_queue_lock, flags);					aen_notify(msg->message, lun);					break;				}

⌨️ 快捷键说明

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