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

📄 iscsid.c

📁 ISCSI user client software.Client would be used to access the IPSAN server.
💻 C
📖 第 1 页 / 共 5 页
字号:
			/* Sendtargets returns with no data */			no_data = 1;		}		process_sendtarget_discovery_data(count, no_data,						  discovery, config, targets,						  discovery_auth_options);	}}/* make the target's new_config the current_config */static voiduse_new_target_config(struct iscsi_target *target){	struct iscsi_target_config *old_target_config = NULL;	struct iscsi_session_config *new_sessions, *existing_sessions, *tail;	struct iscsi_session_config *new_session, *existing_session;	struct iscsi_session_process *process;	int new_target_config = 0;	if (target->new_config == NULL)		return;	/* if the target config has changed, we consider all session	 * configs as changed.  we want to propagate the fact that the	 * per-target settings have changed to all session processes.	 */	if (!same_target_config(target->new_config, target->current_config)) {		debugmsg(1, "target config %p for target %p to %s has changed",			 target->new_config, target, target->TargetName);		new_target_config = 1;	}	/* we always switch to the new data structures, even when they're	 * the same, to simplify the memory management.  This way we	 * can always free the old stuff.	 */	new_sessions = target->new_config->sessions;	target->new_config->sessions = NULL;	if (target->current_config) {		old_target_config = target->current_config;		existing_sessions = target->current_config->sessions;		target->current_config->sessions = NULL;	} else		existing_sessions = NULL;	target->current_config = target->new_config;	target->new_config = NULL;	/* For simplicity, we use a sequential mapping from the new session	 * configs to the existing session configs.  If portals are reported	 * in a different order after a portal is added or removed, this may	 * cause us to change the config of every existing session just to	 * shuffle the portals around. Since portals don't change often, this	 * shouldn't cause any real problems.	 * We iterate over both the new session configs and the existing	 * session configs at the same time.	 *  - If both exist and have the same config, we do nothing.	 *  - If both exist with different configs, we call the	 *    config_changed() hook.	 *  - If a new session exists and there is no existing session, we	 *    add it.	 *  - If an existing session exists and there is no new session,	 *    we delete it.	 */	new_session = new_sessions;	existing_session = existing_sessions;	tail = NULL;	while ((new_session = new_sessions)) {		/* pop off a new session */		new_sessions = new_session->next;		new_session->next = NULL;		/* we always ignore any unbound new sessions */		if (new_session->target_id < 0) {			logmsg(AS_NOTICE, "discarding unbound session %p to "			       "%s",			       new_session, new_session->target->TargetName);			free_session_config(new_session);			continue;		}		/* append the new session to the existing sessions */		if (tail) {			tail->next = new_session;			tail = new_session;		} else {			target->current_config->sessions = tail = new_session;		}		/* get a process using this session config */		if (existing_session && (process =					 existing_session->process)) {			/* connect the new_config and the existing process */			new_session->process = process;			process->config = new_session;			if (new_target_config			    || !same_session_config(new_session,						    existing_session)) {				process->config_number++;				debugmsg(2, "new session config %p is "					 "different than existing session "					 "config %p, notifying process %p\n",					 new_session, existing_session,					 process);				/* notify platform-specific code of the				 * config change				 */				iscsi_config_changed(process, new_session,						     existing_session);			} else {				debugmsg(7, "new session config %p is the same"					 " as existing session config %p\n",					 new_session, existing_session);			}		} else {			/* try to start a new process */			process = calloc(1, sizeof (*process));			if (process == NULL) {				logmsg(AS_ERROR, "failed to allocate session "				       "process for session config %p",				       new_session);				free_session_config(new_session);				continue;			}			/* cross-link them */			process->config = new_session;			process->config_number = 1;			new_session->process = process;			debugmsg(1, "allocated session process %p for session "				 "config %p", process, new_session);			/* do we really need these in a separate list? */			add_session_process(&session_processes, process);			/* start the session */			fork_session_process(process);			/* and give it a chance to get going */			usleep(10 * 1000);		}		if (existing_session) {			/* pop the existing session config, and go on to the			 * next			 */			debugmsg(6, "popping and freeing existing session "				 "config %p", existing_session);			existing_sessions = existing_session->next;			free_session_config(existing_session);			existing_session = existing_sessions;		} else {			debugmsg(7, "no existing session config");		}	}	/* any other existing sessions need to be killed off */	while ((existing_session = existing_sessions)) {		/* pop an existing session */		existing_sessions = existing_session->next;		if (existing_session->process) {			debugmsg(1, "killing existing session process %p "				 "for bus %d target %d TargetName %s",				 existing_session, existing_session->iscsi_bus,				 existing_session->target_id,				 existing_session->target->TargetName);			stop_session_process(existing_session->process);			existing_session->process = NULL;		}		/* and free the obsolete session config */		free_session_config(existing_session);		existing_session = NULL;	}	/* we've already freed every old session, so the old target	 * config is no longer needed either	 */	if (old_target_config)		free_target_config(old_target_config);	if (target->new_portals) {		/* we're now done with the target's old portals. Everything has		 * been updated to use the new portals, even if they're		 * equivalent, so that we can free all of the old ones.		 */		if (target->current_portals)			free_portal_descriptors(target->current_portals);		target->current_portals = target->new_portals;		target->new_portals = NULL;	}}static intstart_polling(struct discovery_poll_info *poll_info,	      struct iscsi_config *config){	int rc;	int n;	int setup_poll;	rc = poll(poll_info->poll_fds, poll_info->valid_length, -1);	if (rc < 0)		debugmsg(7, "daemon returned from poll, rc %d, errno %d, %s",			 rc, errno, strerror(errno));	else		debugmsg(7, "daemon returned from poll, rc %d", rc);	while (rc > 0) {		setup_poll = 0;		if (iscsi_process_should_exit())			return -1;		/* if one or more pipes has discovery info, process them all		 */		for (n = 0; n < poll_info->valid_length; n++) {			if (poll_info->poll_fds[n].			    revents & (POLLIN | POLLPRI)) {				/* process discovery info from this pipe, and "				 * update sessions based on it				 */				debugmsg(7, "input on fd %d from discovery"					 " process %p",					 poll_info->poll_fds[n].fd,					 poll_info->processes[n]);				update_targets(poll_info->processes[n],					       config, &targets);			}			if (poll_info->poll_fds[n].revents & POLLHUP) {				debugmsg(1, "poll hangup on index %d, fd %d, "					 "discovery %p", n,					 poll_info->poll_fds[n].fd,					 poll_info->processes[n]);				if (poll_info->processes[n]->pipe_fd >= 0) {					close(poll_info->processes[n]->					      pipe_fd);					poll_info->processes[n]->pipe_fd = -1;					discovery_processes.changed = 1;					/* make sure we remove it later */				}				usleep(20 * 1000);				setup_poll = 1;			}			if (poll_info->poll_fds[n].revents & POLLNVAL) {				logmsg(AS_ERROR, "invalid poll on index %d, "				       "fd %d, discovery %p",				       n, poll_info->poll_fds[n].fd,				       poll_info->processes[n]);				usleep(20 * 1000);				setup_poll = 1;			}			if (poll_info->poll_fds[n].revents & POLLERR) {				logmsg(AS_ERROR, "poll error on index %d, fd "				       "%d, discovery %p",				       n, poll_info->poll_fds[n].fd,				       poll_info->processes[n]);				usleep(20 * 1000);				setup_poll = 1;			}			poll_info->poll_fds[n].revents = 0;		}		if (setup_poll) {			/* rebuild the pollfd array */			debugmsg(7, "rebuilding poll info after poll revents");			setup_polling(poll_info, &discovery_processes);		}		/* non-blocking poll to check for more input before		 * processing any config changes or new targets, so		 * that we tend to do that all at once.		 */		rc = poll(poll_info->poll_fds, poll_info->valid_length, 0);		if (rc < 0)			debugmsg(7, "daemon returned from non-blocking poll rc"				 " %d, errno %d, %s", rc, errno,				 strerror(errno));		else			debugmsg(7, "daemon returned from non-blocking "				 "poll, rc %d", rc);	}	return 1;}static voidreload_config(struct iscsi_config *config,	      struct discovery_poll_info *poll_info){	struct iscsi_session_process *process;	struct iscsi_target *target;	if (update_iscsi_config(daemon_config.config_file, config)) {		/* kill all the existing discovery processes */		stop_discovery_processes(&discovery_processes);		for (target = targets.head; target; target = target->next) {			struct iscsi_portal_descriptor *portals;			struct iscsi_target_config *target_config;			/* always use the most recent portal descriptors */			portals = target->new_portals ?				target->new_portals : target->current_portals;			/* let the first discovery process to rediscover this			 * target pass on new auth credentials			 */			target->discovery = NULL;			target->discovered = 0;			/* Propagate the current target config's auth			 * settings for now. These may change when the target			 * gets rediscovered, but for now we want to keep using			 * what we already have, since it may have been			 * propagated from a previous discovery, rather than a			 * global default. If it was a global default that			 * included the discovery entry, and that default has			 * changed, we'll switch to the new default when the			 * target gets rediscovered. If a global default			 * applies to a TargetName entry but not the discovery			 * entry, we'll probably lose it.  Propagation from			 * discovery and dynamic config reloads largely make it			 * impossible to configure auth credentials by			 * TargetName, but nobody has really asked for that yet			 * either, so as long as we train everyone put to put			 * global defaults before the discovery entries, there			 * shouldn't be any problems.			 */			target_config =	create_target_config(target->							     TargetName,							     portals, config,							     &target->							     current_config->							     auth_options);			if (target_config) {				/* replace any unused new config */				if (target->new_config) {					debugmsg(6, "freeing unused new target"						 " config %p for target %p "						 "after config reload",						 target->new_config, target);					free_target_config(target->new_config);				}				target->new_config = target_config;				targets.check_configs = 1;			} else {				logmsg(AS_ERROR, "failed to allocate target "				       "config for target %p after config "				       "reload\n", target);			}		}		for (process = session_processes.head; process;		     process = process->next) {			if (process->failed) {				/* restart any process that failed with no				 * retries. We treat a config reload as an				 * explicit user request to retry the failed				 * session				 */				debugmsg(1, "restarting failed session process"					 " %p", process);				process->restart = 1;				session_processes.changed = 1;			} else {				/* treat a config reload as a				 * request for a new LUN probe				 */				debugmsg(1, "assuming LUN inventory may have "					 "changed for session process %p",					 process);				process->lun_inventory_changed = 1;				session_processes.lun_inventory_changed = 1;			}		}		/* start new discovery processes based on the current config		 */		debugmsg(1, "restarting discovery after config reload");		start_discovery_processes(config, &discovery_processes);		setup_polling(poll_info, &discovery_processes);		/* give discovery a chance to produce some		 * results before we start LUN probing.		 */		usleep(100 * 1000);	} else {		logmsg(AS_ERROR, "failed to reload configuration file %s",		       daemon_config.config_file);		/* keep running with what we have */	}}static voidupdate_discovery_processes(struct discovery_poll_info *poll_info){	int setup_poll = 0;	struct iscsi_discovery_process *discovery;	discovery_processes.changed = 0;	/* scan the discovery list and make any changes needed	 */	discovery = discovery_processes.head;	while (discovery) {		debugmsg(7, "checking discovery process %p, pid %d pipe_fd %d,"			 " restart %d, remove %d, next %p", discovery,			 discovery->pid, discovery->pipe_fd,			 discovery->restart, discovery->remove,			 discovery->next);		if (discovery->restart) {			discovery->restart = 0;			if (discovery->pid == 0) {				debugmsg(1, "restarting discovery %p",					 discovery);				if (discovery->pipe_fd >= 0) {					close(discovery->pipe_fd);					discovery->pipe_fd = -1;				}				fork_discovery_process(discovery);				setup_poll = 1;			}			discovery = discovery->next;		} else if (discovery->pipe_fd == -1) {			struct iscsi_discovery_process *next = discovery->next;			struct iscsi_target *target;			/* no point keeping it around if we can't read from it.			 * we don't remove it right after SIGCHLD, since we			 * may still need to drain it's pipe.			 */			debugmsg(1, "removing discovery %p, pipe has closed",				 discovery);			/* any target first discovered by this process needs			 * it's discovery pointer cleared, so that there are			 * no stale pointers, and so that the next process to			 * discover this target can pass along auth			 * credentials.			 */			for (target = targets.head; target;			     target = target->next) {				if (target->discovery == discovery) {					target->discovery = NULL;				}			}			stop_discovery_process(discovery);			discovery 

⌨️ 快捷键说明

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