📄 iscsid.c
字号:
} else { debugmsg(6, "freeing process %p with no config", process); } free(process);}static voidstop_session_process(struct iscsi_session_process *process){ debugmsg(1, "stopping session process %p pid %d", process, process->pid); remove_session_process(&session_processes, process); iscsi_kill_session(process); if (process->config) process->config->process = NULL; free_session_process(process);}static voidstop_session_processes(struct iscsi_session_process_list *session_processes){ struct iscsi_session_process *process; debugmsg(1, "stopping all session processes"); while ((process = session_processes->head)) { stop_session_process(process); }}static voidstart_discovery_processes(struct iscsi_config *config, struct iscsi_discovery_process_list *discovery_processes){ struct iscsi_config_entry *entry, *next; struct iscsi_discovery_process *discovery = NULL; struct iscsi_discovery_process *chk_discovery; int order = 1; int dup_addr = 0; if (config == NULL || config->head == NULL) { if (config) debugmsg(1, "no discovery processes have been " "configured, config %p, head %p, tail %p", config, config->head, config->tail); else debugmsg(1, "no discovery processes have been " "configured"); logmsg(AS_ERROR, "Configuration file is empty, exiting the " "discovery process\n"); return; } debugmsg(1, "starting discovery processes"); /* scan the config looking for SendTargets or SLP configs */ entry = config->head; while (entry) { /* save the next config to process, since we may * splice out the current one. */ next = entry->next; debugmsg(7, "start discovery checking config entry %p, " "type %d", entry, entry->type); switch (entry->type) { case CONFIG_TYPE_SENDTARGETS: case CONFIG_TYPE_DISCOVERY_FILE: case CONFIG_TYPE_SLP: /* grab the discovery entries out of the config, * since nothing else needs them */ discovery = calloc(1, sizeof (*discovery)); if (discovery) { discovery->order = order++; discovery->in_progress = 1; /* splice out the config entry, since nothing * else will need it */ remove_config_entry(config, entry); /* save the config for the process */ discovery->entry = entry; dup_addr = 0; for (chk_discovery = discovery_processes->head; chk_discovery; chk_discovery = discovery->next) { if (strcmp (chk_discovery->entry->config. sendtargets->address, discovery->entry->config. sendtargets->address) == 0) { logmsg(AS_ERROR, "ignoring " "duplicate discovery " "address %s in the " "config file\n", discovery->entry-> config.sendtargets-> address); dup_addr = 1; break; } } if (!dup_addr) { /* start the process */ /* add the process to the * discovery processes */ add_discovery(discovery_processes, discovery); fork_discovery_process(discovery); /* give it a chance to start before * we go on to the next */ usleep(10 * 1000); } } else { logmsg(AS_ERROR, "couldn't allocate discovery process"); } break; default: break; } entry = next; } debugmsg(1, "done starting discovery processes");}static voidstop_discovery_process(struct iscsi_discovery_process *process){ debugmsg(1, "stopping discovery process %p", process); remove_discovery(&discovery_processes, process); discovery_processes.changed = 1; kill_discovery(process); free_discovery(process);}static voidstop_discovery_processes(struct iscsi_discovery_process_list *discovery_processes){ struct iscsi_discovery_process *process; while ((process = discovery_processes->head)) { stop_discovery_process(process); discovery_processes->changed = 1; }}/* dynamic arrays for poll fds and process pointers */struct discovery_poll_info { size_t allocated_length; size_t valid_length; struct iscsi_discovery_process **processes; struct pollfd *poll_fds;};static intsetup_polling(struct discovery_poll_info *poll_info, struct iscsi_discovery_process_list *discovery_processes){ struct iscsi_discovery_process *discovery; struct iscsi_discovery_process **new_processes = NULL; struct pollfd *new_fds = NULL; int i; int needed = 0; /* determine how many fds are needed (pipe_fd >= 0) */ for (discovery = discovery_processes->head; discovery; discovery = discovery->next) { if (discovery->pipe_fd >= 0) needed++; } debugmsg(7, "need %d poll fds", needed); /* see if we need to allocate more memory */ if (poll_info->allocated_length < needed) { /* we need more */ new_fds = realloc(poll_info->poll_fds, needed * sizeof (*new_fds)); /* the actual pollfds to give to poll */ new_processes = realloc(poll_info->processes, needed * sizeof (*new_processes)); /* pointers to processes */ if (new_fds && new_processes) { /* update the poll info */ poll_info->allocated_length = needed; poll_info->poll_fds = new_fds; poll_info->processes = new_processes; /* initialize the added memory */ memset(poll_info->poll_fds + poll_info->valid_length, 0, (poll_info->allocated_length - poll_info->valid_length) * sizeof (struct pollfd)); for (i = poll_info->valid_length; i < poll_info->allocated_length; i++) { poll_info->processes[i] = NULL; } } else { /* failed */ logmsg(AS_ERROR, "couldn't realloc poll info, have %d," " needed %d", poll_info->allocated_length, needed); /* mark the process list changed, * so that we try again later */ discovery_processes->changed = 1; return 0; } } /* setup the poll info based on the current discovery processes */ i = 0; for (discovery = discovery_processes->head; discovery; discovery = discovery->next) { if (discovery->pipe_fd >= 0) { if (i >= poll_info->allocated_length) { /* should be impossible for the process list * to grow while we're running, but we're * paranoid */ logmsg(AS_ERROR, "couldn't set poll info[%d] " "for discovery %p, allocated length " "only %d", i, discovery, poll_info->allocated_length); break; } else { debugmsg(7, "poll_info[%d] = fd %d for " "discovery %p", i, discovery->pipe_fd, discovery); poll_info->processes[i] = discovery; poll_info->poll_fds[i].fd = discovery->pipe_fd; poll_info->poll_fds[i].events = POLLIN | POLLPRI; poll_info->poll_fds[i].revents = 0; i++; } } } /* record how many entries we're using */ poll_info->valid_length = i; /* success */ return 1;}static struct iscsi_target *find_target(char *name, struct iscsi_target_list *targets){ struct iscsi_target *target; if ((name == NULL) || (*name == '\0')) return NULL; for (target = targets->head; target; target = target->next) { if (strcmp(target->TargetName, name) == 0) return target; } return NULL;}static intupdate_target_list(struct iscsi_target_list *targets, struct iscsi_target *target){ struct iscsi_target *prev = NULL; struct iscsi_target *current = targets->head; if (targets == NULL) { return (-1); } while (current != NULL && strcmp(current->TargetName, target->TargetName)) { prev = current; current = current->next; } if (current == NULL) { return (-1); } else { if (prev == NULL) { targets->head = current->next; } else if (current->next == NULL) { targets->tail = prev; prev->next = current->next; } else { prev->next = current->next; } current->next = NULL; free(current); return (0); }}static voiddelete_target(struct iscsi_target *existing_target, struct iscsi_target_list *targets){ struct iscsi_session_config *existing_session = NULL, *new_session = NULL; struct iscsi_target_config *current_config = NULL, *new_config = NULL; struct iscsi_target *target = NULL; target = existing_target; target->discovery = NULL; current_config = target->current_config; new_config = target->new_config; existing_session = current_config->sessions; while (existing_session) { iscsi_config_changed(existing_session->process, new_session, existing_session); remove_session_process(&session_processes, existing_session->process); free_session_process(existing_session->process); existing_session->process = NULL; existing_session = existing_session->next; } current_config->sessions = NULL; if (current_config != NULL) free_target_config(current_config); target->current_config = NULL; if (new_config != NULL) free_target_config(new_config); target->new_config = NULL; if (target->current_portals) free_portal_descriptors(target->current_portals); target->current_portals = NULL; if (target->new_portals) free_portal_descriptors(target->new_portals); target->new_portals = NULL; free(target->TargetName); update_target_list(targets, target);}static voidprocess_targets_for_portal(char *address, struct iscsi_target_list *targets, struct iscsi_config *config){ /* * Check for targets using this particular portal so that we can * appropriately update the specific target and session config * information. 1) If the portal is used by this target and if this is the only portal, then delete the target and session config and ask the kernel to terminate the target session in the kernel. 2)Since multipath is enabled and more than one portal is available to the same target, remove the session config for the portal removed, and terminate the session. If only one path is now active and that portal is made offline, need to delete the target config and session config and terminate the session. * */ struct iscsi_session_config *session = NULL, *prev_session = NULL; struct iscsi_session_config *existing_session; struct iscsi_session_process *process; struct iscsi_target *target; struct iscsi_portal_descriptor *portal, *tmpportal, *new_portals, *desc; int num_portals; for (target = targets->head; target; target = target->next) { tmpportal = portal = target->current_portals; existing_session = target->current_config->sessions; process = existing_session->process; new_portals = NULL; /* Get the number of portals for this target */ num_portals = 0; for (portal = target->current_portals; portal; portal = portal->next) num_portals++; while (tmpportal != NULL && strcmp(address, tmpportal->address)) { new_portals = tmpportal; tmpportal = tmpportal->next; } if (tmpportal == NULL) { logmsg(AS_ERROR, "Portal %s to be deleted is not in " "the portal list of target %s\n", address, target->TargetName); return; } if (num_portals == 1) { /* Delete the target and session config completely */ delete_target(target, targets); } else { /* Delete the session config for this portal */ session = existing_session; desc = session->portal->descriptor; prev_session = NULL; while (session != NULL && !same_portal_descriptor(desc, tmpportal)) { prev_session = session; session = session->next; desc = session->portal->descriptor; } if (prev_session == NULL) target->current_config->sessions = session->next; else prev_session->next = session->next; session->next = NULL; offline_warn("Portal Offline", session); stop_session_process(session->process); session->process = NULL; session->target = NULL; if (target->current_portals) { session->portal->descriptor = NULL; session->portal = NULL; } free_session_config(session); } if (num_portals > 1) { if (target->new_config) free_target_config(target->new_config); target->new_config = NULL; if (tmpportal == NULL) { logmsg(AS_ERROR, " no portals are present\n"); } if (new_portals == NULL) { target->current_portals = tmpportal->next; } else { new_portals->next = tmpportal->next; } tmpportal->next = NULL; free(tmpportal->address); free(tmpportal); } }}static voidadd_target(struct iscsi_target_list *targets, struct iscsi_target *target){ target->next = NULL; if (targets->head) { targets->tail->next = target; targets->tail = target; } else { targets->head = targets->tail = target; }}struct iscsi_portal_descriptor *alloc_portal_descriptor(void){ struct iscsi_portal_descriptor *portal = calloc(1, sizeof (*portal)); if (portal) { /* defaults */ portal->address = NULL; portal->tag = PORTAL_GROUP_TAG_UNKNOWN; portal->port = ISCSI_LISTEN_PORT; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -