Mercurial > illumos > illumos-gate
changeset 3801:315605685c9e
6530235 libdlpi integration exposed race condition between iSCSI target daemon and zfs share
author | mcneal |
---|---|
date | Mon, 12 Mar 2007 10:41:50 -0700 |
parents | 3d29f956e474 |
children | 6d539848fb03 |
files | usr/src/cmd/iscsi/iscsitgtd/main.c |
diffstat | 1 files changed, 79 insertions(+), 32 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/iscsi/iscsitgtd/main.c Mon Mar 12 09:44:38 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/main.c Mon Mar 12 10:41:50 2007 -0700 @@ -800,6 +800,13 @@ } } +/*ARGSUSED*/ +void +exit_after_door_setup(int sig, siginfo_t *sip, void *v) +{ + exit(SMF_EXIT_OK); +} + int main(int argc, char **argv) { @@ -842,14 +849,6 @@ (void) sigignore(SIGPIPE); /* - * Look at the function lu_buserr_handler() in t10_sam.c to see the - * details of why we need to handle segmentation violations. - */ - bzero(&act, sizeof (act)); - act.sa_sigaction = lu_buserr_handler; - act.sa_flags = SA_SIGINFO; - - /* * Setup memory caches */ if ((iscsi_cmd_cache = umem_cache_create("iSCSI conn cmds", @@ -869,6 +868,14 @@ exit(SMF_EXIT_ERR_CONFIG); } + /* + * Look at the function lu_buserr_handler() in t10_sam.c to see the + * details of why we need to handle segmentation violations. + */ + bzero(&act, sizeof (act)); + act.sa_sigaction = lu_buserr_handler; + act.sa_flags = SA_SIGINFO; + if (sigaction(SIGBUS, &act, NULL) == -1) { perror("sigaction"); exit(SMF_EXIT_ERR_CONFIG); @@ -877,29 +884,6 @@ if (process_config(config_file) == False) exit(SMF_EXIT_ERR_CONFIG); - if (process_target_config() == False) - exit(SMF_EXIT_ERR_CONFIG); - - (void) tgt_find_value_boolean(main_config, XML_ELEMENT_DBGDAEMON, - &daemonize); - if (daemonize == True) { - switch (fork()) { - case 0: - /* ---- I'm the daemon, continue running ---- */ - break; - - case -1: - /* ---- Failed to fork!. Trouble ---- */ - exit(SMF_EXIT_ERR_CONFIG); - - default: - exit(SMF_EXIT_OK); - } - closefrom(0); - } - - q = queue_alloc(); - /* * During the normal corse of events 'target_basedir' will be * free when the administrator changes the base directory. Instead @@ -912,6 +896,70 @@ if (target_basedir == NULL) target_basedir = strdup(DEFAULT_TARGET_BASEDIR); + if (process_target_config() == False) + exit(SMF_EXIT_ERR_CONFIG); + + (void) tgt_find_value_boolean(main_config, XML_ELEMENT_DBGDAEMON, + &daemonize); + + q = queue_alloc(); + if (daemonize == True) { + closefrom(0); + + /* + * Set up a signal handler to catch SIGUSR2. Once the child + * has setup the door, it will signal the parent that it's + * safe to exit. Without doing this it's possible that the + * daemon will start and the parent exit before the child has + * setup the door. If that happens 'zfs share -a iscsi' which + * is run from svc-iscsitgt will fail to open the door and try + * to wait for the iscsitgt service to come online. Since + * the zfs command is part of the service start, the service + * will not come online and we'll fail to share any ZVOLs. + */ + bzero(&act, sizeof (act)); + act.sa_sigaction = exit_after_door_setup; + act.sa_flags = SA_SIGINFO; + if (sigaction(SIGUSR2, &act, NULL) == -1) { + perror("sigaction"); + exit(SMF_EXIT_ERR_CONFIG); + } + + switch (fork()) { + case 0: + /* + * As the child process, setup the door and then + * signal the parent that it can exit since the child + * is now ready to start accepting requests on the + * door. + */ + setup_door(q, door_name); + (void) kill(getppid(), SIGUSR2); + break; + + case -1: + /* ---- Failed to fork!. Trouble ---- */ + exit(SMF_EXIT_ERR_CONFIG); + + default: + /* + * If pause() returns with an error something + * interrupted the process which was not a SIGUSR2. + * Exit with an error code such that SMF can flag + * this problem. + */ + if (pause() == -1) + exit(SMF_EXIT_ERR_CONFIG); + } + } else { + + /* + * The daemon is working in debug mode, so go ahead and + * setup the door now. + */ + setup_door(q, door_name); + } + /* * Initialize the various subsystems. In most cases these are * just initializing mutexs. @@ -951,7 +999,6 @@ port1.port_num = iscsi_port; (void) pthread_create(&junk, NULL, port_watcher, &port1); - setup_door(q, door_name); if ((tgt_find_value_int(main_config, XML_ELEMENT_MGMTPORT, &port2.port_num) == True) && (port2.port_num != -1)) { port2.port_mgmtq = q;