📄 iscsid.c
字号:
return portal;}static char discovery_buffer[256 * 1024];static intfind_host_no(struct iscsi_session_config *config){ char isid[7], tpgt[10]; char *tname = config->target->TargetName; struct sysfs_attribute *attr1, *attr2, *attr3; struct sysfs_class_device *cldev; struct dlist *dev_list; struct sysfs_class *sfclass; int host_num = -1; sprintf(isid, "%02x%02x%02x%02x%02x%02x", config->isid[0], config->isid[1], config->isid[2], config->isid[3], config->isid[4], config->isid[5]); sprintf(tpgt, "%hu", config->portal->descriptor->tag); if(!(sfclass = sysfs_open_class(ISCSI_TRANSPORT_CLASS))) { errormsg(" error opening iscsi_transport_class in sysfs\n"); return host_num; } if(!(dev_list = sysfs_get_class_devices(sfclass))) { errormsg("error opening iscsi_transport_class in sysfs\n"); sysfs_close_class(sfclass); return host_num; } dlist_for_each_data(dev_list, cldev, struct sysfs_class_device) { attr1 = sysfs_get_classdev_attr(cldev, "isid"); attr2 = sysfs_get_classdev_attr(cldev, "target_name"); attr3 = sysfs_get_classdev_attr(cldev, "tpgt"); if (!strncmp(attr1->value, isid, strlen(isid)) && !strncmp(attr2->value, tname, strlen(tname)) && !strncmp(attr3->value, tpgt, strlen(tpgt))) { sscanf(cldev->name + 6, "%d", &host_num); break; } } if (host_num == -1) { errormsg("Session for target %s with isid %s, target portal" "group tag %s does not exist", tname, isid, tpgt); } sysfs_close_class(sfclass); return host_num;}voidoffline_warn(char *offline, struct iscsi_session_config *config){ int host_no; host_no = find_host_no(config); if (host_no > -1) logmsg(AS_ERROR, "%s has been received on Host %d on %s. Set " "ConnFailTimeout to a low value like 5 secs through " "sysfs. Unmount all the mounted devices of this host if " "any. Shutdown Host number %d through sysfs.\n", offline, host_no, config->portal->descriptor->address, host_no);}static voidupdate_async_data(struct iscsi_discovery_process *discovery, struct iscsi_config *config, struct iscsi_target_list *targets){ char *input, *line, *eol; char *address = NULL; int count; int tgtoffline = 0; int portoffline = 0; struct iscsi_target *target = NULL, *existing_target = NULL; input = discovery_buffer; for (;;) { /* read discovery info into the buffer, always leaving the * last byte for a NUL terminator */ count = read(discovery->pipe_fd, input, sizeof (discovery_buffer) - 1 - (input - discovery_buffer)); if (count > 0) { char *data = input; input += count; *input = '\0'; debugmsg(7, "discovery %p pipe %d, %d bytes input '%s'" , discovery, discovery->pipe_fd, count, data); discovery->in_progress = 1; } else if (count == 0) { /* end of file, guess we're done */ debugmsg(7, "discovery %p pipe at end of file", discovery, discovery->pipe_fd); close(discovery->pipe_fd); discovery->pipe_fd = -1; discovery->in_progress = 0; discovery_processes.changed = 1; /* so that we remove the discovery process */ return; } else if (errno != EINTR) { /* some sort of non-retryable error */ errormsg("error reading from discovery process %p", discovery); /* FIXME: maybe we should kill or restart * the discovery process. */ return; } /* scan the input for line boundaries, and process each line */ line = discovery_buffer; while (line < input) { if ((eol = strchr(line, '\n'))) { *eol = '\0'; debugmsg(7, "processing pipe line %p: %s", line, line); if (eol == line) { /* ignore blank lines */ } else if (strcmp(line, ";") == 0) { /* The target record has been * terminated we are done processing * the record */ } else if (strcmp(line, "!") == 0) { /* This means the end of data in pipe * we are done with reading data */ if (tgtoffline) /* * target offline occured need * to orphan the target */ delete_target(existing_target, targets); if (portoffline) process_targets_for_portal (address, targets, config); return; } else if (strncmp(line, "PF=", 3) == 0) { char *port; address = line + 3; if ((port = strrchr(line, ':'))) { *port = '\0'; port++; } debugmsg(1, "Failing over all targets " "using portal %s\n", address); portoffline = 1; } else if (strncmp(line, "TF=", 3) == 0) { char *name = line + 3; debugmsg(1, " Deleting target %s\n", name); tgtoffline = 1; /* start of a target description. If * the target has already been * discovered, we will need to delete * it */ if ((existing_target = find_target(name, targets))) { target = existing_target; /* track which discovery * process owns this target */ if (target->discovery == NULL) { target->discovery = discovery; target->discovered = 1; } else if (target->discovery == discovery) { target->discovered = 1; /* we found it again */ } } } else { debugmsg(1, " Could not read %s\n", line); } /* on to the next line */ line = eol + 1; } else { /* move any remaining input to the beginning of * the buffer, and wait for more input */ size_t bytes = input - line; debugmsg(7, "deferring partial pipe line %p: " "%s", line, line); memmove(discovery_buffer, line, bytes); line = input = discovery_buffer + bytes; break; } } if (line >= input) input = discovery_buffer; }}static voidmark_targets_undiscovered(struct iscsi_discovery_process *discovery, struct iscsi_target_list *targets){ struct iscsi_target *target; for (target = targets->head; target; target = target->next) { if (target->discovery == discovery) { debugmsg(3, "discovery %p expecting to rediscover " "target %p name %s", discovery, target, target->TargetName); target->discovered = 0; } }}static struct iscsi_auth_config *get_discovery_auth_options(struct iscsi_discovery_process *discovery){ struct iscsi_auth_config *discovery_auth_options = NULL; if (discovery->entry) { switch (discovery->entry->type) { case CONFIG_TYPE_SENDTARGETS: { struct iscsi_sendtargets_config *sendtargets = discovery->entry->config.sendtargets; debugmsg(7, "discovery %p will propagate " "authentication options to " "discovered targets", discovery); discovery_auth_options = &sendtargets->auth_options; break; } case CONFIG_TYPE_SLP: { struct iscsi_slp_config *slp = discovery->entry->config.slp; debugmsg(7, "discovery %p will propagate " "authentication options to " "discovered targets", discovery); discovery_auth_options = &slp->auth_options; break; } case CONFIG_TYPE_DISCOVERY_FILE: { struct iscsi_discovery_file_config *file = discovery->entry->config.file; debugmsg(7, "discovery %p will propagate " "authentication options to " "discovered targets", discovery); discovery_auth_options = &file->auth_options; break; } } } return discovery_auth_options;}static voiddiscovery_finished(struct iscsi_discovery_process *discovery, struct iscsi_target_list *targets){ int orphans = 0; struct iscsi_target *target; discovery->in_progress = 0; /* orphan any of our targets that we didn't rediscover this round, so * that some other discovery process can claim them. */ for (target = targets->head; target; target = target->next) { if ((target->discovery == discovery) && !target->discovered) { debugmsg(3, "discovery process %p orphaning " "undiscovered target %p name %s", discovery, target, target->TargetName); target->discovery = NULL; orphans = 1; } } if (orphans) { struct iscsi_discovery_process *other; /* trigger rediscover for all other discovery processes, in the * hopes that one of them will claim the targets we orphaned. */ for (other = discovery_processes.head; other; other = other-> next) { if (other != discovery) trigger_rediscovery(other); } }}static voidadd_new_target(struct iscsi_target *new_target, struct iscsi_portal_descriptor *first_portal, struct iscsi_config *config, struct iscsi_auth_config *discovery_auth_options, struct iscsi_target_list *targets){ struct iscsi_target_config *target_config; new_target->new_portals = first_portal; /* create the per-target configuration */ target_config = create_target_config(new_target->TargetName, first_portal, config, discovery_auth_options); if (target_config) { /* replace any unprocessed new config with the latest one */ if (new_target->new_config) { debugmsg(6, "freeing unused new target config %p " "for new target %p", new_target->new_config, new_target); free_target_config(new_target->new_config); } new_target->new_config = target_config; targets->check_configs = 1; debugmsg(6, "new target %p has new target config %p and " "portals %p", new_target, target_config, first_portal); } else { logmsg(AS_ERROR, "failed to allocate new target config for " "new target %p", new_target); } /* add the target to the list */ add_target(targets, new_target);}static voidupdate_existing_target(struct iscsi_target *existing_target, struct iscsi_target *target, struct iscsi_target_list *targets, struct iscsi_discovery_process *discovery, struct iscsi_auth_config *discovery_auth_options, struct iscsi_config *config, struct iscsi_portal_descriptor *first_portal){ int make_config = 0; struct iscsi_auth_config *auth_options = NULL; struct iscsi_portal_descriptor *port = NULL; struct iscsi_target_config *target_config; /* this target already exists, possibly update it */ if (!same_portal_descriptors(first_portal, existing_target->current_portals)) { debugmsg(1, "target %p portal descriptors have changed\n", existing_target); make_config = 1; /* stay with any existing auth credentials unless the * discovery overrides. */ if (existing_target->new_config) auth_options = &existing_target->new_config-> auth_options; else if (existing_target->current_config) auth_options = &existing_target->current_config-> auth_options; else auth_options = NULL; } else { for (port = existing_target->current_portals; port; port = port->next) debugmsg(7, "target %p portal descriptors have not " "changed\n", existing_target); } /* make a new config if we need to propagate different auth credentials * to prevent flapping if the same target is found by multiple * discovery processes, we only let the first process to discover the * target pass along auth credentials. * A config reload resets this, so that new credentials can be obtained * after a reload. Also, when the owning process stops discovering that * target, it will orphan it so that any other discovery processes that * still find it can propagate discovery credentials to it. */ if (discovery && ((target->discovery == NULL) || (target->discovery == discovery))) { /* check if the credentials need to change */ if (existing_target->current_config && discovery_auth_options) { if (memcmp(&existing_target->current_config-> auth_options, discovery_auth_options, sizeof (existing_target->current_config-> auth_options))) { debugmsg(1, "target %p discovered by %p needs " "to update to new auth credentials " "from discovery %p\n", existing_target, existing_target->discovery, discovery); auth_options = discovery_auth_options; make_config = 1; } else debugmsg(7, "target %p discovered by %p does " "not need to update to auth " "credentials from discovery %p\n", existing_target, existing_target->discovery, discovery); } /* ensure that only this discovery process gets to propagate * credentials to this target */ target->discovery = discovery; } else if (discovery_auth_options) { debugmsg(3, "target %p discovered by %p ignoring auth " "credentials from discovery %p", target, target->discovery, discovery); } if (make_config) { target_config = create_target_config(existing_target-> TargetName, first_portal, config, auth_options); if (target_config) { /* update the new_config */ if (existing_target->new_config) { debugmsg(6, "freeing unused new target config " "%p for target %p", existing_target->new_config, existing_target); free_target_config(existing_target-> new_config); } existing_target->new_config = target_config; /* update the new portals */ if (existing_target->new_portals) { debugmsg(6, "freeing unused new portal " "descriptors %p for target %p", existing_target->new_portals, existing_target); free_portal_descriptors(existing_target-> new_portals); } existing_target->new_portals = first_portal; targets->check_configs = 1; debugmsg(1, "existing target %p has new target config " "%p and new portals %p", existing_target, target_config, first_portal); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -