📄 iscsid.c
字号:
logmsg(AS_ERROR, "failed to allocate new target config" " for existing target %p", existing_target); /* free the unused new portals */ free_portal_descriptors(first_portal); } } else { /* free the unused new portals */ free_portal_descriptors(first_portal); }}static voidset_lun_inventory_changed(char *name, struct iscsi_target *target, struct iscsi_discovery_process *discovery){ struct iscsi_session_config *s; debugmsg(1, "target %p name %s rediscovered by process %p", target, name, discovery); if (target->current_config) { for (s = target->current_config->sessions; s; s = s->next) { if (s->process) { session_processes.lun_inventory_changed = 1; debugmsg(1, "target %p name %s session " "process %p LUN inventory may have " "changed", target, name, s->process); } } }}static voidexisting_target_discovered(char *line, char *name, struct iscsi_target *target, struct iscsi_discovery_process *discovery){ /* 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 */ } if (*line == 'L') { set_lun_inventory_changed(name, target, discovery); } else if (target->current_portals) { debugmsg(1, "target %p name %s rediscovered by process %p", target, name, discovery); } else { /* can this ever happen now? why would we have a target * with no portals? */ debugmsg(1, "target %p name %s discovered by process %p", target, name, discovery); }}static voidset_portal_address(char *address, struct iscsi_portal_descriptor *portal){ struct in_addr addr; portal->address = strdup(address); /* if we didn't get an RA line, the IP is on the TA line */ if (portal->ip_length == 0) { /* FIXME: IPv6 */ if (iscsi_inet_aton(address, &addr)) { memcpy(&portal->ip, &addr, 4); portal->ip_length = 4; } else { logmsg(AS_ERROR, "couldn't get IP address for %s", address); } }}static intscan_for_newline(char *input, int no_data, struct iscsi_config *config, struct iscsi_discovery_process *discovery, struct iscsi_target_list *targets, struct iscsi_auth_config *discovery_auth_options){ char *line, *eol; struct iscsi_target *target = NULL, *existing_target = NULL, *new_target = NULL; struct iscsi_portal_descriptor *portal = NULL; struct iscsi_portal_descriptor *first_portal = NULL, *last_portal = NULL; line = discovery_buffer; while (line < input) { if ((eol = strchr(line, '\n'))) { *eol = '\0'; debugmsg(7, "processing pipe line %p: %s", line, line); if (no_data) { /* No Sendtargets data received in the pipe */ no_data = 0; return 1; } if (eol == line) { /* ignore blank lines */ } /* process_line(line, eol, input, discovery, config, targets, discovery_auth_options); */ if (strcmp(line, ";") == 0) { /* a target record has been terminated */ if (new_target) { add_new_target(new_target, first_portal, config, discovery_auth_options, targets); target = new_target = NULL; first_portal = last_portal = NULL; } else if (existing_target) { update_existing_target(existing_target, target, targets, discovery, discovery_auth_options, config, first_portal); target = existing_target = NULL; first_portal = last_portal = NULL; } } else if (strcmp(line, ".") == 0) { /* we may want to stop reading now. The * discovery processes use these lines to mark * the end of a group of target records. More * records may be coming, but it may take a * while for them to arrive, so we may want to * stop reading now in order to avoid blocking. * For SendTargets, this corresponds to a * non-final PDU boundary. */ if (eol + 1 < input) { debugmsg(7, "discovery %p reached " "stopping point with more " "input remaining, continuing", discovery); } else { debugmsg(7, "discovery %p reached " "stopping point with no more " "input, stopping", discovery); return 1; } } else if (strcmp(line, "!") == 0) { /* a round of discovery is complete, mark the * discovery as no longer in progress. For * SendTargets, this means the PDU exchange is * done. */ if (eol + 1 < input) { debugmsg(7, "discovery %p round " "completed with more input " "remaining, continuing", discovery); /* keep reading, and start a new round * of discovery. We stay in progress, * but we need to mark all of the * targets we own undiscovered again. */ mark_targets_undiscovered(discovery, targets); } else { discovery_finished(discovery, targets); return 1; } } else if ((strncmp(line, "TN=", 3) == 0) || (strncmp(line, "LC=", 3) == 0)) { char *name = line + 3; /* start of a target description. * if the target has already been * discovered, we may need to update * it. if not, we need to add it. */ if ((existing_target = find_target(name, targets))) { target = existing_target; existing_target_discovered( line, name, target, discovery); } else { /* create a new target */ target =calloc(1, sizeof (*target)); if (target) { new_target = target; target->TargetName = strdup(name); /* record which process * found it first */ target->discovery = discovery; /* make sure it * doesn't get orphaned * immediately */ target->discovered = 1; debugmsg(1, "target %p" " name %s " "discovered " "by process " "%p", new_target, name, discovery); } else { logmsg(AS_ERROR, "failed to " "allocate a new" " target %s", name); } } } else if (strncmp(line, "TT=", 3) == 0) { char *tag = line + 3; if (portal == NULL) portal = alloc_portal_descriptor (); if (portal) { portal->tag = iscsi_strtoul(tag, NULL, 0); } else { logmsg(AS_ERROR, "failed to " "allocate a new portal " "for target %s", target->TargetName); } } else if (strncmp(line, "TP=", 3) == 0) { /* target TCP port number */ char *port = line + 3; if (portal == NULL) portal = alloc_portal_descriptor (); if (portal) { portal->port = iscsi_strtoul(port, NULL, 0); } } else if (strncmp(line, "RA=", 3) == 0) { char *address = line + 3; struct in_addr addr; /* resolved target ip address */ if (portal == NULL) portal = alloc_portal_descriptor (); if (portal) { /* FIXME: IPv6 */ if (iscsi_inet_aton (address, &addr)) { memcpy(&portal->ip, &addr, 4); portal->ip_length = 4; } else { logmsg(AS_ERROR, "couldn't get " "IP address " "for %s", address); } } } else if (strncmp(line, "TA=", 3) == 0) { char *address = line + 3; /*struct in_addr addr;*/ /* ip address or DNS name * of target portal */ if (portal == NULL) portal = alloc_portal_descriptor (); if (portal) { set_portal_address(address, portal); /* we now have all the info for * this portal, so add it to * the list and get ready for * the next portal. */ if (first_portal) { last_portal->next = portal; last_portal = portal; } else { first_portal = last_portal = portal; } debugmsg(1, "target %p portal " "descriptor %p = " "address %s, ip " "%u.%u.%u.%u " "length %u, port %d, " "tag %d", target, portal, portal-> address, portal->ip[0], portal->ip[1], portal->ip[2], portal->ip[3], portal->ip_length, portal->port, portal->tag); portal = NULL; } } /* 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; return 0;}static voidprocess_sendtarget_discovery_data(int count, int no_data, struct iscsi_discovery_process *discovery, struct iscsi_config *config, struct iscsi_target_list *targets, struct iscsi_auth_config * discovery_auth_options){ char *input; int discovery_finished = 0; 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 */ discovery_finished = scan_for_newline(input, no_data, config, discovery, targets, discovery_auth_options); if (discovery_finished) return; }}/* process discovery info and update targets */static voidupdate_targets(struct iscsi_discovery_process *discovery, struct iscsi_config *config, struct iscsi_target_list *targets){ char ip[10]; int count; int no_data = 0; struct iscsi_auth_config *discovery_auth_options; /* FIXME: for now, for backwards compatibility with the old config file * semantics, pass on authentication settings from the discovery * process to the targets it discovers. * This will behave oddly if the same target is discovered from * multiple discovery processes, and they have different * authentication settings. */ discovery_auth_options = get_discovery_auth_options(discovery); /* we're about to start a round of discovery for this process. * Mark all targets formerly discovered by the process as not * discovered, so that any target that we don't rediscover in * this round can be orphaned, and possibly get taken over by * a different discovery process that can still find it. */ if (!discovery->in_progress) { mark_targets_undiscovered(discovery, targets); } /* We determine the data coming in the pipe, * whether it is sendtargets data or async data */ count = read(discovery->pipe_fd, &ip[0], 1); ip[2] = '\0'; if (count > 0 && ip[0] == 'A') { debugmsg(1, "Received Async data from the pipe %c\n", ip[0]); update_async_data(discovery, config, targets); } else { if (count > 0 && ip[0] == 'D') { debugmsg(1, "Received Sendtargets data from the pipe " "%c\n", ip[0]); } else if (count > 0 && ip[0] == '!') {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -