int server_stop(void) { proc_session_parse(ctrl_fd, &conn_close_ops, NULL); while (proc_session_parse(ctrl_fd, &shutdown_wait_ops, NULL) < 0) sleep(1); proc_session_parse(ctrl_fd, &target_del_ops, NULL); isns_exit(); return 0; }
int main(int argc, char *argv[]) { char optstring[] = "i:p:dfs:vh"; struct option longopts[] = { {"isns-server", 1, NULL, 'i'}, {"isns-port", 1, NULL, 'p'}, {"debug", 0, NULL, 'd'}, {"foreground", 0, NULL, 'f'}, {"configfs-iscsi-path", 1, NULL, 's'}, {"version", 0, NULL, 'v'}, {"help", 0, NULL, 'h'}, {NULL, 0, NULL, 0} }; int option; int longindex = 0; int ifd = -1, sfd = -1, tfd = -1; struct epoll_event events[EPOLL_MAX_FD]; ssize_t nr_events; bool daemon = true; int ret = EXIT_FAILURE; size_t configsz; conffile_read(); while ((option = getopt_long(argc, argv, optstring, longopts, &longindex)) != -1) { switch (option) { case 'i': configsz = sizeof(config.isns_server); strncpy(config.isns_server, optarg, configsz); config.isns_server[configsz - 1] = '\0'; break; case 'p': sscanf(optarg, "%hu", &config.isns_port); break; case 'd': config.log_level = LOG_DEBUG; daemon = false; break; case 'f': daemon = false; break; case 's': configsz = sizeof(config.configfs_iscsi_path); strncpy(config.configfs_iscsi_path, optarg, configsz); config.configfs_iscsi_path[configsz - 1] = '\0'; break; case 'v': printf(PROGNAME " version " TARGET_ISNS_VERSION "\n"); exit(EXIT_SUCCESS); break; case 'h': print_usage(); exit(EXIT_SUCCESS); break; case ':': case '?': exit(EXIT_FAILURE); break; } } if (!configfs_iscsi_path_exists()) { fprintf(stderr, "Error: configfs is not mounted or the " "target and iSCSI modules are not loaded.\n"); fprintf(stderr, "Error: %s missing.\n", config.configfs_iscsi_path); exit(EXIT_FAILURE); } if (daemon) { daemonize(); pidfile_create(); } log_init(PROGNAME, daemon, config.log_level); log_print(LOG_INFO, PROGNAME " version " TARGET_ISNS_VERSION " started"); epoll_init_fds(); if (isns_init(config.isns_server, config.isns_port) == -1) { log_print(LOG_ERR, "failed to initialize iSNS client"); goto err_init; } if ((epoll_fd = epoll_create1(0)) == -1) { log_print(LOG_ERR, "failed to create epoll instance"); goto err_epoll_fd; } if ((tfd = isns_registration_timer_init()) == -1) { log_print(LOG_ERR, "failed to create timerfd instance"); goto err_tfd; } epoll_set_fd(EPOLL_REGISTRATION_TIMER, tfd); if ((ifd = configfs_inotify_init()) == -1) { log_print(LOG_ERR, "failed to create inotify instance"); goto err_ifd; } epoll_set_fd(EPOLL_INOTIFY, ifd); if ((sfd = signal_init()) == -1) { log_print(LOG_ERR, "failed to create signalfd instance"); goto err_sfd; } epoll_set_fd(EPOLL_SIGNAL, sfd); isns_start(); while (true) { nr_events = epoll_wait(epoll_fd, events, ARRAY_SIZE(events), -1); for (int i = 0; i < nr_events; i++) { int fd = events[i].data.fd; if (fd == epoll_set[EPOLL_SIGNAL]) { if (signal_is_quit(fd)) goto quit; } else if (fd == epoll_set[EPOLL_INOTIFY]) configfs_inotify_events_handle(); else if (fd == epoll_set[EPOLL_REGISTRATION_TIMER]) isns_registration_refresh(); else if (fd == epoll_set[EPOLL_ISNS]) isns_handle(); else if (fd == epoll_set[EPOLL_SCN_LISTEN]) isns_scn_handle(true); else if (fd == epoll_set[EPOLL_SCN]) isns_scn_handle(false); } } quit: ret = EXIT_SUCCESS; isns_stop(); sleep(1); close(sfd); err_sfd: configfs_inotify_cleanup(); /* closes ifd */ err_ifd: close(tfd); err_tfd: close(epoll_fd); err_epoll_fd: isns_exit(); err_init: log_print(LOG_INFO, PROGNAME " stopped"); log_close(); if (daemon) pidfile_remove(); return ret; }