📄 iscsi-discovery.c
字号:
goto set_address; } break; case ISCSI_STATUS_CLS_INITIATOR_ERR: /* FIXME: IPv6 */ logmsg(AS_ERROR, "discovery login to %u.%u.%u.%u rejected: " "initiator error (%02x/%02x), non-retryable, giving up", session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], status_class, status_detail); iscsi_disconnect(session); free_session(&session); exit(0); case ISCSI_STATUS_CLS_TARGET_ERR: /* FIXME: IPv6 */ logmsg(AS_ERROR, "discovery login to %u.%u.%u.%u rejected: " "target error (%02x/%02x)", session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], status_class, status_detail); iscsi_disconnect(session); login_failures++; goto reconnect; default: /* FIXME: IPv6 */ logmsg(AS_ERROR, "discovery login to %u.%u.%u.%u failed, response " "with unknown status class 0x%x, detail 0x%x", session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], status_class, status_detail); iscsi_disconnect(session); login_failures++; goto reconnect; } rediscover: /* reinitialize */ truncate_buffer(&sendtargets, 0); truncate_buffer(&info, 0); /* we're going to do a discovery regardless */ clear_timer(&async_timer); /* ask for targets */ if (!request_targets(session)) { goto reconnect; } active = 1; /* set timeouts */ if (long_lived) { clear_timer(&connection_timer); } else { set_timer(&connection_timer, session->active_timeout + session->ping_timeout); } /* prepare to poll */ memset(&pfd, 0, sizeof (pfd)); pfd.fd = session->socket_fd; pfd.events = POLLIN | POLLPRI; while (!iscsi_process_should_exit()) { /* check timers before blocking */ if (timer_expired(&connection_timer)) { if (long_lived || !lun_inventory_changed) { /* long-lived, or never finished the first * exchange (might be long-lived) */ clear_timer(&connection_timer); debugmsg(1, "discovery session to %s:%d " "reconnecting after connection timeout", config->address, config->port); goto reconnect; } else { logmsg(AS_NOTICE, "discovery session to %s:%d session " "logout, connection timer expired", config->address, config->port); iscsi_logout_and_disconnect(session); free_session(&session); exit(0); } } if (active) { /* ignore the async timer, we're in the middle * of a discovery */ timeout = msecs_until(&connection_timer); } else { /* to avoid doing LUN probing repeatedly, try to merge * multiple Async PDUs into one rediscovery by * deferring discovery until a timeout expires. */ if (timer_expired(&async_timer)) { debugmsg(4, "discovery session to %s:%d async " "timer expired, rediscovering", config->address, config->port); clear_timer(&async_timer); goto rediscover; } else timeout = soonest_msecs(NULL, &connection_timer, &async_timer); } /* block until we receive a PDU, a TCP FIN, a TCP RST, * or a timeout */ debugmsg(4, "discovery process %s:%d polling fd %d, " "timeout in %f seconds", config->address, config->port, pfd.fd, timeout / 1000.0); pfd.revents = 0; rc = poll(&pfd, 1, timeout); debugmsg(7, "discovery process to %s:%d returned from poll, rc %d", config->address, config->port, rc); if (rc > 0) { if (pfd.revents & (POLLIN | POLLPRI)) { /* put any PDU data into the * sendtargets buffer for now */ data = buffer_data(&sendtargets) + data_length(&sendtargets); end_of_data = data + unused_length(&sendtargets); timeout = msecs_until(&connection_timer); if (iscsi_recv_pdu (session, pdu, ISCSI_DIGEST_NONE, data, end_of_data - data, ISCSI_DIGEST_NONE, timeout)) { /* * process iSCSI PDU received */ rc = process_recvd_pdu( pdu, config, session, &sendtargets, &info, &lun_inventory_changed, default_port, process, &active, &long_lived, &async_timer, data); if (rc == DISCOVERY_NEED_RECONNECT) goto reconnect; /* reset timers after receiving a PDU */ if (long_lived) { clear_timer(&connection_timer); } else { if (active) set_timer (&connection_timer, session-> active_timeout); else /* * 3 minutes to try * to go long-lived */ set_timer(&connection_timer, 3 * 60); } } else { if (long_lived) { debugmsg(1, "discovery session to " "%s:%d failed to recv a " "PDU response, " "reconnecting", config->address, config->port); goto reconnect; } else { debugmsg(1, "discovery session to " "%s:%d failed to recv a " "PDU response, " "terminating", config->address, config->port); iscsi_disconnect(session); free_session(&session); exit(0); } } } if (pfd.revents & POLLHUP) { if (long_lived) { logmsg(AS_NOTICE, "discovery session to %s:%d " "reconnecting after hangup", config->address, config->port); goto reconnect; } else { logmsg(AS_NOTICE, "discovery session to %s:%d " "terminating after hangup", config->address, config->port); iscsi_disconnect(session); free_session(&session); exit(0); } } if (pfd.revents & POLLNVAL) { logmsg(AS_NOTICE, "discovery POLLNVAL"); sleep(1); goto reconnect; } if (pfd.revents & POLLERR) { logmsg(AS_NOTICE, "discovery POLLERR"); sleep(1); goto reconnect; } } else if (rc < 0) { if (errno == EINTR) { /* if we got SIGHUP, reconnect and rediscover */ if (rediscover) { rediscover = 0; debugmsg(1, "rediscovery requested"); goto reconnect; } } else { errormsg("poll error"); sleep(5); free_session(&session); exit(1); } } } debugmsg(1, "discovery process to %s:%d exiting", config->address, config->port);}static voiddiscovery_file_process(struct iscsi_discovery_process *process){ struct iscsi_discovery_file_config *config = process->entry->config.file; struct sigaction action; int fd; int luns_changed = 0; struct string_buffer sendtargets; struct string_buffer info; process->pid = getpid(); debugmsg(1, "discovery file process %d, pid %d, file %s, " "username %s, password %s", process->order, process->pid, config->filename, config->auth_options.username, config->auth_options.password); if (!config->filename || !config->filename[0]) { logmsg(AS_ERROR, "no discovery filename specified"); exit(0); } /* set SIGTERM, SIGINT, and SIGPIPE to kill the process */ memset(&action, 0, sizeof (struct sigaction)); action.sa_sigaction = NULL; action.sa_flags = 0; action.sa_handler = SIG_DFL; sigaction(SIGTERM, &action, NULL); sigaction(SIGINT, &action, NULL); sigaction(SIGPIPE, &action, NULL); /* set SIGHUP to loop again and report LUN INVENTORY CHANGED for testing */ action.sa_handler = sighup_handler; sigaction(SIGHUP, &action, NULL); /* check if a signal arrived before we reset the handler */ if (iscsi_process_should_exit()) { debugmsg(1, "discovery file process %p pid %d file %s exiting\n", process, process->pid, config->filename); exit(0); } /* allocate data buffers for SendTargets data and pipe info */ init_string_buffer(&sendtargets, 32 * 1024); init_string_buffer(&info, 8 * 1024); repeat: truncate_buffer(&sendtargets, 0); truncate_buffer(&info, 0); if ((fd = open(config->filename, 0))) { char *data = buffer_data(&sendtargets); int rc; int final = 0; debugmsg(4, "discovery process %p pid %d opened discovery file %s", process, process->pid, config->filename); do { char *start = buffer_data(&sendtargets) + data_length(&sendtargets); char *end = start + config->read_size; /* don't overflow the buffer */ if (end > (start + unused_length(&sendtargets))) end = start + unused_length(&sendtargets); data = start; /* read a chunk of data */ do { rc = read(fd, data, end - data); if (rc > 0) { data += rc; enlarge_data(&sendtargets, rc); debugmsg(7, "discovery process %p pid %d " "read %d bytes from %s", process, process->pid, rc, config->filename); } else if (rc < 0) { errormsg ("discovery process %p pid %d " "error reading discovery file %s", process, process->pid, config->filename); final = 1; break; } else { debugmsg(4, "discovery process %p pid %d " "read to the end of " "discovery file %s", process, process->pid, config->filename); end = data; final = 1; break; } } while (data < end); /* convert all the whitespace to NULs */ for (data = start; data < end; data++) { if ((*data == '\n') || (*data == ' ') || (*data == '\t')) *data = '\0'; } /* process the data */ process_sendtargets_response(&sendtargets, &info, final, luns_changed, config->address, config->port, process->pipe_fd); } while (!final); } else { errormsg ("discovery process %p pid %d couldn't open " "discovery file %s", process, process->pid, config->filename); } while (config->continuous) { /* wait for a signal, then repeat */ luns_changed = 1; debugmsg(7, "discovery file process waiting for signals"); poll(NULL, 0, -1); if (rediscover) { rediscover = 0; goto repeat; } } exit(0);}#ifdef SLP_ENABLEvoidslp_discovery_process(struct iscsi_discovery_process *discovery){ struct iscsi_slp_config *config = discovery->entry->config.slp; struct sigaction action; char *pl; unsigned short flag = 0; memset(&action, 0, sizeof (struct sigaction)); action.sa_sigaction = NULL; action.sa_flags = 0; action.sa_handler = SIG_DFL; sigaction(SIGTERM, &action, NULL); sigaction(SIGINT, &action, NULL); sigaction(SIGPIPE, &action, NULL); action.sa_handler = sighup_handler; sigaction(SIGHUP, &action, NULL); if (iscsi_process_should_exit()) { debugmsg(1, "slp discovery process %p exiting\n", discovery); exit(0); } discovery->pid = getpid(); pl = generate_predicate_list(discovery, &flag); while (1) { if (flag == SLP_MULTICAST_ENABLED) { discovery->flag = SLP_MULTICAST_ENABLED; slp_multicast_srv_query(discovery, pl, GENERIC_QUERY); } if (flag == SLP_UNICAST_ENABLED) { discovery->flag = SLP_UNICAST_ENABLED; slp_unicast_srv_query(discovery, pl, GENERIC_QUERY); } sleep(config->poll_interval); } exit(0);}#endifvoiddiscovery_process(struct iscsi_discovery_process *discovery){ if (discovery->entry) { switch (discovery->entry->type) { case CONFIG_TYPE_DISCOVERY_FILE: discovery_file_process(discovery); break; case CONFIG_TYPE_SENDTARGETS: sendtargets_discovery_process(discovery); break; case CONFIG_TYPE_SLP:#ifdef SLP_ENABLE slp_discovery_process(discovery);#else logmsg(AS_ERROR, "this build does not support SLP"); exit(0);#endif break; default: logmsg(AS_ERROR, "can't fork unexpected discovery type %d", discovery->entry->type); break; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -