diff -aurp open-iscsi-2.0-872-rc1-bnx2i.base/usr/discoveryd.c open-iscsi-2.0-872-rc1-bnx2i.work/usr/discoveryd.c --- open-iscsi-2.0-872-rc1-bnx2i.base/usr/discoveryd.c 2010-05-18 17:58:00.000000000 -0500 +++ open-iscsi-2.0-872-rc1-bnx2i.work/usr/discoveryd.c 2010-05-19 03:09:54.000000000 -0500 @@ -54,6 +54,7 @@ #define DISC_DEF_POLL_INVL 30 static LIST_HEAD(iscsi_targets); +static int stop_discoveryd; static LIST_HEAD(isns_initiators); static LIST_HEAD(isns_refresh_list); @@ -66,27 +67,64 @@ static void isns_reg_refresh_by_eid_qry( typedef void (do_disc_and_login_fn)(const char *def_iname, char *addr, int port, int poll_inval); -static int logout_stale_session(void *data, struct list_head *list, - struct session_info *info) +static int logout_session(void *data, struct list_head *list, + struct session_info *info) { - struct list_head *stale_rec_list = data; + struct list_head *rec_list = data; struct node_rec *rec; - list_for_each_entry(rec, stale_rec_list, list) { + list_for_each_entry(rec, rec_list, list) { if (iscsi_match_session(rec, info)) return iscsi_logout_portal(info, list); } return -1; } -static void free_curr_targets(void) +static void discoveryd_stop(void) { struct node_rec *rec, *tmp_rec; + int nr_found = 0; + if (list_empty(&iscsi_targets)) + goto done; + + /* + * User requested to just login and exit. + */ + if (!stop_discoveryd) + goto done; + + iscsi_logout_portals(&iscsi_targets, &nr_found, 1, logout_session); list_for_each_entry_safe(rec, tmp_rec, &iscsi_targets, list) { list_del(&rec->list); free(rec); } + +done: + exit(0); +} + +static void catch_signal(int signo) +{ + log_debug(1, "%d caught signal -%d...", signo, getpid()); + switch (signo) { + case SIGTERM: + stop_discoveryd = 1; + break; + default: + break; + } +} + +static void setup_signal_handler(void) +{ + struct sigaction sa_old; + struct sigaction sa_new; + + sa_new.sa_handler = catch_signal; + sigemptyset(&sa_new.sa_mask); + sa_new.sa_flags = 0; + sigaction(SIGTERM, &sa_new, &sa_old ); } /* @@ -158,7 +196,7 @@ static void update_sessions(struct list_ if (!list_empty(&stale_rec_list)) { iscsi_logout_portals(&stale_rec_list, &nr_found, 0, - logout_stale_session); + logout_session); list_for_each_entry_safe(rec, tmp_rec, &stale_rec_list, list) { list_del(&rec->list); free(rec); @@ -194,6 +232,7 @@ static void do_disc_to_addrs(const char pid = fork(); if (pid == 0) { + setup_signal_handler(); do_disc_and_login(def_iname, ip_str, portn, poll_inval); exit(0); } else if (pid < 0) @@ -201,6 +240,7 @@ static void do_disc_to_addrs(const char "to perform discovery to %s.\n", errno, strerror(errno), ip_str); else { + shutdown_callback(pid); log_debug(1, "iSCSI disc and login helper pid=%d", pid); reap_inc(); } @@ -872,8 +912,7 @@ static int isns_scn_recv(isns_server_t * log_debug(1, "isns_scn_recv"); - while (1) { - + while (!stop_discoveryd) { /* reap disc/login procs */ reap_proc(); /* @@ -999,7 +1038,6 @@ static int isns_eventd(const char *def_i isns_cancel_refresh_timers(); fail: isns_clear_refresh_list(); - free_curr_targets(); list_for_each_entry_safe(node, tmp_node, &isns_initiators, list) { list_del(&node->list); @@ -1028,6 +1066,7 @@ static void start_isns(const char *def_i rc = isns_eventd(def_iname, disc_addr, port, poll_inval); log_debug(1, "start isns done %d.", rc); + discoveryd_stop(); } /* SendTargets */ @@ -1087,9 +1126,9 @@ static void do_st_disc_and_login(const c __do_st_disc_and_login(disc_addr, port); if (!poll_inval) break; - } while (!sleep(poll_inval)); + } while (!stop_discoveryd && !sleep(poll_inval)); - free_curr_targets(); + discoveryd_stop(); } void discoveryd_start(const char *def_iname) diff -aurp open-iscsi-2.0-872-rc1-bnx2i.base/usr/event_poll.c open-iscsi-2.0-872-rc1-bnx2i.work/usr/event_poll.c --- open-iscsi-2.0-872-rc1-bnx2i.base/usr/event_poll.c 2010-05-18 17:58:00.000000000 -0500 +++ open-iscsi-2.0-872-rc1-bnx2i.work/usr/event_poll.c 2010-05-19 04:26:20.000000000 -0500 @@ -62,21 +62,75 @@ void reap_proc(void) } } +static LIST_HEAD(shutdown_callbacks); + +struct shutdown_callback { + struct list_head list; + pid_t pid; +}; + +int shutdown_callback(pid_t pid) +{ + struct shutdown_callback *cb; + + cb = calloc(1, sizeof(*cb)); + if (!cb) + return ENOMEM; + + INIT_LIST_HEAD(&cb->list); + cb->pid = pid; + log_debug(1, "adding %d for shutdown cb\n", pid); + list_add_tail(&cb->list, &shutdown_callbacks); + return 0; +} + +static void shutdown_notify_pids(void) +{ + struct shutdown_callback *cb; + + list_for_each_entry(cb, &shutdown_callbacks, list) { + log_debug(1, "Killing %d\n", cb->pid); + kill(cb->pid, SIGTERM); + } +} + +static int shutdown_wait_pids(void) +{ + struct shutdown_callback *cb, *tmp; + + list_for_each_entry_safe(cb, tmp, &shutdown_callbacks, list) { + /* + * the proc reaper could clean it up, so wait for any + * sign that it is gone. + */ + if (waitpid(cb->pid, NULL, WNOHANG)) { + log_debug(1, "%d done\n", cb->pid); + list_del(&cb->list); + free(cb); + } + } + + return list_empty(&shutdown_callbacks); +} + #define POLL_CTRL 0 #define POLL_IPC 1 #define POLL_MAX 2 static int event_loop_stop; +static queue_task_t *shutdown_qtask; + -void event_loop_exit(void) +void event_loop_exit(queue_task_t *qtask) { + shutdown_qtask = qtask; event_loop_stop = 1; } void event_loop(struct iscsi_ipc *ipc, int control_fd, int mgmt_ipc_fd) { struct pollfd poll_array[POLL_MAX]; - int res; + int res, has_shutdown_children = 0; poll_array[POLL_CTRL].fd = control_fd; poll_array[POLL_CTRL].events = POLLIN; @@ -84,7 +138,16 @@ void event_loop(struct iscsi_ipc *ipc, i poll_array[POLL_IPC].events = POLLIN; event_loop_stop = 0; - while (!event_loop_stop) { + while (1) { + if (event_loop_stop) { + if (!has_shutdown_children) { + has_shutdown_children = 1; + shutdown_notify_pids(); + } + if (shutdown_wait_pids()) + break; + } + res = poll(poll_array, POLL_MAX, ACTOR_RESOLUTION); if (res > 0) { log_debug(6, "poll result %d", res); @@ -110,4 +173,6 @@ void event_loop(struct iscsi_ipc *ipc, i */ sysfs_cleanup(); } + if (shutdown_qtask) + mgmt_ipc_write_rsp(shutdown_qtask, MGMT_IPC_OK); } diff -aurp open-iscsi-2.0-872-rc1-bnx2i.base/usr/event_poll.h open-iscsi-2.0-872-rc1-bnx2i.work/usr/event_poll.h --- open-iscsi-2.0-872-rc1-bnx2i.base/usr/event_poll.h 2010-05-18 17:58:00.000000000 -0500 +++ open-iscsi-2.0-872-rc1-bnx2i.work/usr/event_poll.h 2010-05-19 03:24:24.000000000 -0500 @@ -20,10 +20,12 @@ #define EVENT_POLL_H struct iscsi_ipc; +struct queue_task; +int shutdown_callback(pid_t pid); void reap_proc(void); void reap_inc(void); void event_loop(struct iscsi_ipc *ipc, int control_fd, int mgmt_ipc_fd); -void event_loop_exit(void); +void event_loop_exit(struct queue_task *qtask); #endif diff -aurp open-iscsi-2.0-872-rc1-bnx2i.base/usr/mgmt_ipc.c open-iscsi-2.0-872-rc1-bnx2i.work/usr/mgmt_ipc.c --- open-iscsi-2.0-872-rc1-bnx2i.base/usr/mgmt_ipc.c 2010-05-18 17:58:00.000000000 -0500 +++ open-iscsi-2.0-872-rc1-bnx2i.work/usr/mgmt_ipc.c 2010-05-19 03:24:33.000000000 -0500 @@ -74,7 +74,7 @@ mgmt_ipc_listen(void) void mgmt_ipc_close(int fd) { - event_loop_exit(); + event_loop_exit(NULL); if (fd >= 0) close(fd); } @@ -190,8 +190,7 @@ mgmt_ipc_conn_add(queue_task_t *qtask) static mgmt_ipc_err_e mgmt_ipc_immediate_stop(queue_task_t *qtask) { - event_loop_exit(); - mgmt_ipc_write_rsp(qtask, MGMT_IPC_OK); + event_loop_exit(qtask); return MGMT_IPC_OK; }