Rename serve->has_control to serve->success.

This makes the use of this variable to signal an unexpected SIGTERM
while migrating less confusing.
This commit is contained in:
Alex Young
2012-10-09 17:20:39 +01:00
parent a039ceffcb
commit 161d2fccf1
9 changed files with 128 additions and 104 deletions

View File

@@ -235,7 +235,7 @@ void * control_runner( void * control_uncast )
control_serve( control ); control_serve( control );
control_cleanup( control, 0 ); control_cleanup( control, 0 );
return NULL; pthread_exit( NULL );
} }

View File

@@ -51,7 +51,7 @@ int flexnbd_build_signal_fd(void)
sigaddset( &mask, SIGQUIT ); sigaddset( &mask, SIGQUIT );
sigaddset( &mask, SIGINT ); sigaddset( &mask, SIGINT );
FATAL_UNLESS( 0 == pthread_sigmask( SIG_BLOCK, &mask, NULL ), FATAL_UNLESS( 0 == pthread_sigmask( SIG_BLOCK, &mask, NULL ),
"Signal blocking failed" ); "Signal blocking failed" );
sfd = signalfd( -1, &mask, 0 ); sfd = signalfd( -1, &mask, 0 );
@@ -62,12 +62,12 @@ int flexnbd_build_signal_fd(void)
void flexnbd_create_shared( void flexnbd_create_shared(
struct flexnbd * flexnbd, struct flexnbd * flexnbd,
const char * s_ctrl_sock) const char * s_ctrl_sock)
{ {
NULLCHECK( flexnbd ); NULLCHECK( flexnbd );
if ( s_ctrl_sock ){ if ( s_ctrl_sock ){
flexnbd->control = flexnbd->control =
control_create( flexnbd, s_ctrl_sock ); control_create( flexnbd, s_ctrl_sock );
} }
else { else {
@@ -89,37 +89,37 @@ struct flexnbd * flexnbd_create_serving(
int max_nbd_clients) int max_nbd_clients)
{ {
struct flexnbd * flexnbd = xmalloc( sizeof( struct flexnbd ) ); struct flexnbd * flexnbd = xmalloc( sizeof( struct flexnbd ) );
flexnbd->serve = server_create( flexnbd->serve = server_create(
flexnbd, flexnbd,
s_ip_address, s_ip_address,
s_port, s_port,
s_file, s_file,
default_deny, default_deny,
acl_entries, acl_entries,
s_acl_entries, s_acl_entries,
max_nbd_clients, max_nbd_clients,
1); 1);
flexnbd_create_shared( flexnbd, flexnbd_create_shared( flexnbd,
s_ctrl_sock ); s_ctrl_sock );
return flexnbd; return flexnbd;
} }
struct flexnbd * flexnbd_create_listening( struct flexnbd * flexnbd_create_listening(
char* s_ip_address, char* s_ip_address,
char* s_port, char* s_port,
char* s_file, char* s_file,
char *s_ctrl_sock, char *s_ctrl_sock,
int default_deny, int default_deny,
int acl_entries, int acl_entries,
char** s_acl_entries ) char** s_acl_entries )
{ {
struct flexnbd * flexnbd = xmalloc( sizeof( struct flexnbd ) ); struct flexnbd * flexnbd = xmalloc( sizeof( struct flexnbd ) );
flexnbd->serve = server_create( flexnbd->serve = server_create(
flexnbd, flexnbd,
s_ip_address, s_ip_address,
s_port, s_port,
s_file, s_file,
default_deny, default_deny,
acl_entries, acl_entries,
s_acl_entries, s_acl_entries,
@@ -136,10 +136,10 @@ void flexnbd_spawn_control(struct flexnbd * flexnbd )
pthread_t * control_thread = &flexnbd->control->thread; pthread_t * control_thread = &flexnbd->control->thread;
FATAL_UNLESS( 0 == pthread_create( FATAL_UNLESS( 0 == pthread_create(
control_thread, control_thread,
NULL, NULL,
control_runner, control_runner,
flexnbd->control ), flexnbd->control ),
"Couldn't create the control thread" ); "Couldn't create the control thread" );
} }
@@ -150,8 +150,10 @@ void flexnbd_stop_control( struct flexnbd * flexnbd )
NULLCHECK( flexnbd->control ); NULLCHECK( flexnbd->control );
control_signal_close( flexnbd->control ); control_signal_close( flexnbd->control );
FATAL_UNLESS( 0 == pthread_join( flexnbd->control->thread, NULL ), pthread_t tid = flexnbd->control->thread;
"Failed joining the control thread" ); FATAL_UNLESS( 0 == pthread_join( tid, NULL ),
"Failed joining the control thread" );
debug( "Control thread %p pthread_join returned", tid );
} }
@@ -191,7 +193,7 @@ struct status * flexnbd_status_create( struct flexnbd * flexnbd )
{ {
NULLCHECK( flexnbd ); NULLCHECK( flexnbd );
struct status * status; struct status * status;
status = status_create( flexnbd_server( flexnbd ) ); status = status_create( flexnbd_server( flexnbd ) );
return status; return status;
} }
@@ -240,6 +242,7 @@ int flexnbd_serve( struct flexnbd * flexnbd )
} }
success = do_serve( flexnbd->serve ); success = do_serve( flexnbd->serve );
debug("do_serve success is %d", success );
if ( flexnbd->control ) { if ( flexnbd->control ) {
debug( "Stopping control thread" ); debug( "Stopping control thread" );

View File

@@ -11,6 +11,7 @@
#include "util.h" #include "util.h"
#include "bitset.h" #include "bitset.h"
int build_allocation_map(struct bitset_mapping* allocation_map, int fd) int build_allocation_map(struct bitset_mapping* allocation_map, int fd)
{ {
/* break blocking ioctls down */ /* break blocking ioctls down */
@@ -19,8 +20,8 @@ int build_allocation_map(struct bitset_mapping* allocation_map, int fd)
unsigned long offset = 0; unsigned long offset = 0;
struct { struct {
struct fiemap fiemap; struct fiemap fiemap;
struct fiemap_extent extents[max_extents]; struct fiemap_extent extents[max_extents];
} fiemap_static; } fiemap_static;
struct fiemap* fiemap = (struct fiemap*) &fiemap_static; struct fiemap* fiemap = (struct fiemap*) &fiemap_static;
@@ -31,31 +32,33 @@ int build_allocation_map(struct bitset_mapping* allocation_map, int fd)
unsigned int i; unsigned int i;
fiemap->fm_start = offset; fiemap->fm_start = offset;
fiemap->fm_length = max_length; fiemap->fm_length = max_length;
if (offset + max_length > allocation_map->size) if ( offset + max_length > allocation_map->size ) {
fiemap->fm_length = allocation_map->size-offset; fiemap->fm_length = allocation_map->size-offset;
}
fiemap->fm_flags = FIEMAP_FLAG_SYNC; fiemap->fm_flags = FIEMAP_FLAG_SYNC;
fiemap->fm_extent_count = max_extents; fiemap->fm_extent_count = max_extents;
fiemap->fm_mapped_extents = 0; fiemap->fm_mapped_extents = 0;
if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) { if ( ioctl( fd, FS_IOC_FIEMAP, fiemap ) < 0 ) {
debug( "Couldn't get fiemap, returning no allocation_map" ); debug( "Couldn't get fiemap, returning no allocation_map" );
free(allocation_map); free(allocation_map);
return NULL; allocation_map = NULL;
break;
} }
else {
for (i=0;i<fiemap->fm_mapped_extents;i++) { for ( i = 0; i < fiemap->fm_mapped_extents; i++ ) {
bitset_set_range( bitset_set_range( allocation_map,
allocation_map, fiemap->fm_extents[i].fe_logical,
fiemap->fm_extents[i].fe_logical, fiemap->fm_extents[i].fe_length );
fiemap->fm_extents[i].fe_length }
);
//debug("range from %ld + %ld", fiemap->fm_extents[i].fe_logical, fiemap->fm_extents[i].fe_length);
} }
} }
debug("Successfully built allocation map"); debug("Successfully built allocation map");
return allocation_map; return NULL != allocation_map;
} }

View File

@@ -144,7 +144,7 @@ static struct option break_options[] = {
{0} {0}
}; };
static char break_short_options[] = "hs:" SOPT_QUIET SOPT_VERBOSE; static char break_short_options[] = "hs:" SOPT_QUIET SOPT_VERBOSE;
static char break_help_text[] = static char break_help_text[] =
"Usage: flexnbd " CMD_BREAK " <options>\n\n" "Usage: flexnbd " CMD_BREAK " <options>\n\n"
"Stop mirroring from the server with control socket SOCK.\n\n" "Stop mirroring from the server with control socket SOCK.\n\n"
HELP_LINE HELP_LINE
@@ -228,11 +228,11 @@ void read_serve_param( int c, char **ip_addr, char **ip_port, char **file, char
} }
void read_listen_param( int c, void read_listen_param( int c,
char **ip_addr, char **ip_addr,
char **ip_port, char **ip_port,
char **file, char **file,
char **sock, char **sock,
int *default_deny ) int *default_deny )
{ {
switch(c){ switch(c){
@@ -328,8 +328,8 @@ void read_acl_param( int c, char **sock )
read_sock_param( c, sock, acl_help_text ); read_sock_param( c, sock, acl_help_text );
} }
void read_mirror_param( void read_mirror_param(
int c, int c,
char **sock, char **sock,
char **ip_addr, char **ip_addr,
char **ip_port, char **ip_port,
@@ -406,6 +406,8 @@ int mode_serve( int argc, char *argv[] )
int default_deny = 0; // not on by default int default_deny = 0; // not on by default
int err = 0; int err = 0;
int success;
struct flexnbd * flexnbd; struct flexnbd * flexnbd;
while (1) { while (1) {
@@ -427,10 +429,10 @@ int mode_serve( int argc, char *argv[] )
flexnbd = flexnbd_create_serving( ip_addr, ip_port, file, sock, default_deny, argc - optind, argv + optind, MAX_NBD_CLIENTS ); flexnbd = flexnbd_create_serving( ip_addr, ip_port, file, sock, default_deny, argc - optind, argv + optind, MAX_NBD_CLIENTS );
info( "Serving file %s", file ); info( "Serving file %s", file );
flexnbd_serve( flexnbd ); success = flexnbd_serve( flexnbd );
flexnbd_destroy( flexnbd ); flexnbd_destroy( flexnbd );
return 0; return success ? 0 : 1;
} }
@@ -452,7 +454,7 @@ int mode_listen( int argc, char *argv[] )
c = getopt_long(argc, argv, listen_short_options, listen_options, NULL); c = getopt_long(argc, argv, listen_short_options, listen_options, NULL);
if ( c == -1 ) { break; } if ( c == -1 ) { break; }
read_listen_param( c, &ip_addr, &ip_port, read_listen_param( c, &ip_addr, &ip_port,
&file, &sock, &default_deny ); &file, &sock, &default_deny );
} }
@@ -466,13 +468,13 @@ int mode_listen( int argc, char *argv[] )
} }
if ( err ) { exit_err( listen_help_text ); } if ( err ) { exit_err( listen_help_text ); }
flexnbd = flexnbd_create_listening( flexnbd = flexnbd_create_listening(
ip_addr, ip_addr,
ip_port, ip_port,
file, file,
sock, sock,
default_deny, default_deny,
argc - optind, argc - optind,
argv + optind); argv + optind);
success = flexnbd_serve( flexnbd ); success = flexnbd_serve( flexnbd );
flexnbd_destroy( flexnbd ); flexnbd_destroy( flexnbd );
@@ -516,7 +518,7 @@ void params_readwrite(
s_ip_address s_ip_address
); );
if (s_bind_address != NULL && if (s_bind_address != NULL &&
parse_ip_to_sockaddr(&out->connect_from.generic, s_bind_address) == 0) { parse_ip_to_sockaddr(&out->connect_from.generic, s_bind_address) == 0) {
fatal("Couldn't parse bind address '%s'", s_bind_address); fatal("Couldn't parse bind address '%s'", s_bind_address);
} }
@@ -660,11 +662,11 @@ int mode_mirror( int argc, char *argv[] )
while (1) { while (1) {
c = getopt_long( argc, argv, mirror_short_options, mirror_options, NULL); c = getopt_long( argc, argv, mirror_short_options, mirror_options, NULL);
if ( -1 == c ) { break; } if ( -1 == c ) { break; }
read_mirror_param( c, read_mirror_param( c,
&sock, &sock,
&remote_argv[0], &remote_argv[0],
&remote_argv[1], &remote_argv[1],
&unlink, &unlink,
&remote_argv[3] ); &remote_argv[3] );
} }
@@ -678,7 +680,7 @@ int mode_mirror( int argc, char *argv[] )
} }
if ( err ) { exit_err( mirror_help_text ); } if ( err ) { exit_err( mirror_help_text ); }
if ( unlink ) { remote_argv[2] = "unlink"; } if ( unlink ) { remote_argv[2] = "unlink"; }
if (remote_argv[3] == NULL) { if (remote_argv[3] == NULL) {
do_remote_command( "mirror", sock, 3, remote_argv ); do_remote_command( "mirror", sock, 3, remote_argv );
} }

View File

@@ -45,13 +45,13 @@ struct server * server_create (
int acl_entries, int acl_entries,
char** s_acl_entries, char** s_acl_entries,
int max_nbd_clients, int max_nbd_clients,
int has_control) int success)
{ {
NULLCHECK( flexnbd ); NULLCHECK( flexnbd );
struct server * out; struct server * out;
out = xmalloc( sizeof( struct server ) ); out = xmalloc( sizeof( struct server ) );
out->flexnbd = flexnbd; out->flexnbd = flexnbd;
out->has_control = has_control; out->success = success;
out->max_nbd_clients = max_nbd_clients; out->max_nbd_clients = max_nbd_clients;
out->nbd_client = xmalloc( max_nbd_clients * sizeof( struct client_tbl_entry ) ); out->nbd_client = xmalloc( max_nbd_clients * sizeof( struct client_tbl_entry ) );
@@ -678,23 +678,24 @@ int server_mirror_can_start( struct server *serve )
} }
void serve_handle_signal( struct server *params ) /* Queries to see if we are currently mirroring. If we are, we need
* to communicate that via the process exit status. because otherwise
* the supervisor will assume the migration completed.
*/
int serve_shutdown_is_graceful( struct server *params )
{ {
int should_die = 0; int is_mirroring = 0;
server_lock_start_mirror( params ); server_lock_start_mirror( params );
{ {
if ( server_is_mirroring( params ) ) { if ( server_is_mirroring( params ) ) {
should_die = 1; is_mirroring = 1;
warn( "Stop signal received while mirroring." );
server_prevent_mirror_start( params ); server_prevent_mirror_start( params );
} }
} }
server_unlock_start_mirror( params ); server_unlock_start_mirror( params );
if ( should_die ){ return !is_mirroring;
fatal( "Stop signal received while mirroring." );
} else {
server_close_clients( params );
}
} }
@@ -710,6 +711,7 @@ int server_accept( struct server * params )
/* We select on this fd to receive OS signals (only a few of /* We select on this fd to receive OS signals (only a few of
* which we're interested in, see flexnbd.c */ * which we're interested in, see flexnbd.c */
int signal_fd = flexnbd_signal_fd( params->flexnbd ); int signal_fd = flexnbd_signal_fd( params->flexnbd );
int should_continue = 1;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(params->server_fd, &fds); FD_SET(params->server_fd, &fds);
@@ -722,17 +724,15 @@ int server_accept( struct server * params )
if ( self_pipe_fd_isset( params->close_signal, &fds ) ){ if ( self_pipe_fd_isset( params->close_signal, &fds ) ){
server_close_clients( params ); server_close_clients( params );
return 0; should_continue = 0;
} }
if ( 0 < signal_fd && FD_ISSET( signal_fd, &fds ) ){ if ( 0 < signal_fd && FD_ISSET( signal_fd, &fds ) ){
debug( "Stop signal received." ); debug( "Stop signal received." );
serve_handle_signal( params ); server_close_clients( params );
params->success = serve_shutdown_is_graceful( params );
/* serve_handle_signal will fatal() if it has to, so it should_continue = 0;
* might not return at all.
*/
return 0;
} }
@@ -747,7 +747,7 @@ int server_accept( struct server * params )
accept_nbd_client(params, client_fd, &client_address); accept_nbd_client(params, client_fd, &client_address);
} }
return 1; return should_continue;
} }
@@ -765,7 +765,7 @@ void* build_allocation_map_thread(void* serve_uncast)
int fd = open(serve->filename, O_RDONLY); int fd = open(serve->filename, O_RDONLY);
FATAL_IF_NEGATIVE(fd, "Couldn't open %s", serve->filename); FATAL_IF_NEGATIVE(fd, "Couldn't open %s", serve->filename);
serve->allocation_map = serve->allocation_map =
bitset_alloc(serve->size, block_allocation_resolution); bitset_alloc(serve->size, block_allocation_resolution);
if (build_allocation_map(serve->allocation_map, fd)) { if (build_allocation_map(serve->allocation_map, fd)) {
@@ -794,8 +794,8 @@ void serve_init_allocation_map(struct server* params)
params->size = size; params->size = size;
FATAL_IF_NEGATIVE(size, "Couldn't find size of %s", FATAL_IF_NEGATIVE(size, "Couldn't find size of %s",
params->filename); params->filename);
FATAL_IF_NEGATIVE(pthread_create(&params->allocation_map_builder_thread, FATAL_IF_NEGATIVE(pthread_create(&params->allocation_map_builder_thread,
NULL, build_allocation_map_thread, params), NULL, build_allocation_map_thread, params),
"Couldn't create thread"); "Couldn't create thread");
} }
@@ -825,13 +825,15 @@ void server_control_arrived( struct server *serve )
{ {
NULLCHECK( serve ); NULLCHECK( serve );
if ( !serve->has_control ) { if ( !serve->success ) {
serve->has_control = 1; serve->success = 1;
serve_signal_close( serve ); serve_signal_close( serve );
} }
} }
void flexnbd_stop_control( struct flexnbd * flexnbd );
/** Closes sockets, frees memory and waits for all client threads to finish */ /** Closes sockets, frees memory and waits for all client threads to finish */
void serve_cleanup(struct server* params, void serve_cleanup(struct server* params,
int fatal __attribute__ ((unused)) ) int fatal __attribute__ ((unused)) )
@@ -851,7 +853,7 @@ void serve_cleanup(struct server* params,
if (params->allocation_map) { if (params->allocation_map) {
free(params->allocation_map); free(params->allocation_map);
} }
int need_mirror_lock; int need_mirror_lock;
need_mirror_lock = !server_start_mirror_locked( params ); need_mirror_lock = !server_start_mirror_locked( params );
@@ -864,7 +866,6 @@ void serve_cleanup(struct server* params,
} }
if ( need_mirror_lock ) { server_unlock_start_mirror( params ); } if ( need_mirror_lock ) { server_unlock_start_mirror( params ); }
for (i=0; i < params->max_nbd_clients; i++) { for (i=0; i < params->max_nbd_clients; i++) {
pthread_t thread_id = params->nbd_client[i].thread; pthread_t thread_id = params->nbd_client[i].thread;
@@ -882,6 +883,15 @@ void serve_cleanup(struct server* params,
server_unlock_acl( params ); server_unlock_acl( params );
} }
/* if( params->flexnbd ) { */
/* if ( params->flexnbd->control ) { */
/* flexnbd_stop_control( params->flexnbd ); */
/* } */
/* flexnbd_destroy( params->flexnbd ); */
/* } */
/* server_destroy( params ); */
debug( "Cleanup done"); debug( "Cleanup done");
} }
@@ -889,7 +899,7 @@ void serve_cleanup(struct server* params,
int server_is_in_control( struct server *serve ) int server_is_in_control( struct server *serve )
{ {
NULLCHECK( serve ); NULLCHECK( serve );
return serve->has_control; return serve->success;
} }
int server_is_mirroring( struct server * serve ) int server_is_mirroring( struct server * serve )
@@ -911,7 +921,9 @@ void server_abandon_mirror( struct server * serve )
* the next pass. * the next pass.
* */ * */
serve->mirror->signal_abandon = 1; serve->mirror->signal_abandon = 1;
pthread_join( serve->mirror_super->thread, NULL ); pthread_t tid = serve->mirror_super->thread;
pthread_join( tid, NULL );
debug( "Mirror thread %p pthread_join returned", tid );
} }
} }
@@ -926,15 +938,15 @@ int do_serve(struct server* params)
{ {
NULLCHECK( params ); NULLCHECK( params );
int has_control; int success;
error_set_handler((cleanup_handler*) serve_cleanup, params); error_set_handler((cleanup_handler*) serve_cleanup, params);
serve_open_server_socket(params); serve_open_server_socket(params);
serve_init_allocation_map(params); serve_init_allocation_map(params);
serve_accept_loop(params); serve_accept_loop(params);
has_control = params->has_control; success = params->success;
serve_cleanup(params, 0); serve_cleanup(params, 0);
return has_control; return success;
} }

View File

@@ -40,7 +40,7 @@ struct server {
/** Claims around any I/O to this file */ /** Claims around any I/O to this file */
struct flexthread_mutex * l_io; struct flexthread_mutex * l_io;
/** to interrupt accept loop and clients, write() to close_signal[1] */ /** to interrupt accept loop and clients, write() to close_signal[1] */
struct self_pipe * close_signal; struct self_pipe * close_signal;
@@ -59,20 +59,20 @@ struct server {
struct flexthread_mutex * l_start_mirror; struct flexthread_mutex * l_start_mirror;
struct mirror* mirror; struct mirror* mirror;
struct mirror_super * mirror_super; struct mirror_super * mirror_super;
/* This is used to stop the mirror from starting after we /* This is used to stop the mirror from starting after we
* receive a SIGTERM */ * receive a SIGTERM */
int mirror_can_start; int mirror_can_start;
int server_fd; int server_fd;
int control_fd; int control_fd;
/* the allocation_map keeps track of which blocks in the backing file /* the allocation_map keeps track of which blocks in the backing file
* have been allocated, or part-allocated on disc, with unallocated * have been allocated, or part-allocated on disc, with unallocated
* blocks presumed to contain zeroes (i.e. represented as sparse files * blocks presumed to contain zeroes (i.e. represented as sparse files
* by the filesystem). We can use this information when receiving * by the filesystem). We can use this information when receiving
* incoming writes, and avoid writing zeroes to unallocated sections * incoming writes, and avoid writing zeroes to unallocated sections
* of the file which would needlessly increase disc usage. This * of the file which would needlessly increase disc usage. This
* bitmap will start at all-zeroes for an empty file, and tend towards * bitmap will start at all-zeroes for an empty file, and tend towards
* all-ones as the file is written to (i.e. we assume that allocated * all-ones as the file is written to (i.e. we assume that allocated
* blocks can never become unallocated again, as is the case with ext3 * blocks can never become unallocated again, as is the case with ext3
@@ -83,7 +83,7 @@ struct server {
pthread_t allocation_map_builder_thread; pthread_t allocation_map_builder_thread;
/* when the thread has finished, it sets this to 1 */ /* when the thread has finished, it sets this to 1 */
volatile sig_atomic_t allocation_map_built; volatile sig_atomic_t allocation_map_built;
int max_nbd_clients; int max_nbd_clients;
struct client_tbl_entry *nbd_client; struct client_tbl_entry *nbd_client;
@@ -91,20 +91,23 @@ struct server {
/* Marker for whether this server has control over the data in /* Marker for whether this server has control over the data in
* the file, or if we're waiting to receive it from an inbound * the file, or if we're waiting to receive it from an inbound
* migration which hasn't yet finished. * migration which hasn't yet finished.
*
* It's the value which controls the exit status of a serve or
* listen process.
*/ */
int has_control; int success;
}; };
struct server * server_create( struct server * server_create(
struct flexnbd * flexnbd, struct flexnbd * flexnbd,
char* s_ip_address, char* s_ip_address,
char* s_port, char* s_port,
char* s_file, char* s_file,
int default_deny, int default_deny,
int acl_entries, int acl_entries,
char** s_acl_entries, char** s_acl_entries,
int max_nbd_clients, int max_nbd_clients,
int has_control ); int success );
void server_destroy( struct server * ); void server_destroy( struct server * );
int server_is_closed(struct server* serve); int server_is_closed(struct server* serve);
void server_dirty(struct server *serve, off64_t from, int len); void server_dirty(struct server *serve, off64_t from, int len);

View File

@@ -6,10 +6,10 @@ struct status * status_create( struct server * serve )
{ {
NULLCHECK( serve ); NULLCHECK( serve );
struct status * status; struct status * status;
status = xmalloc( sizeof( struct status ) ); status = xmalloc( sizeof( struct status ) );
status->pid = getpid(); status->pid = getpid();
status->has_control = serve->has_control; status->has_control = server_is_in_control( serve );
status->is_mirroring = NULL != serve->mirror; status->is_mirroring = NULL != serve->mirror;
return status; return status;

View File

@@ -310,13 +310,14 @@ module FlexNBD
debug( cmd ) debug( cmd )
@pid = @executor.run( cmd ) @pid = @executor.run( cmd )
start_wait_thread( @pid )
while !File.socket?(ctrl) while !File.socket?(ctrl)
pid, status = Process.wait2(@pid, Process::WNOHANG) pid, status = Process.wait2(@pid, Process::WNOHANG)
raise "server did not start (#{cmd})" if pid raise "server did not start (#{cmd})" if pid
sleep 0.1 sleep 0.1
end end
start_wait_thread( @pid )
at_exit { kill } at_exit { kill }
end end
private :run_serve_cmd private :run_serve_cmd

View File

@@ -20,7 +20,7 @@ class TestSourceErrorHandling < Test::Unit::TestCase
def expect_term_during_migration def expect_term_during_migration
@env.nbd1.can_die(6,9) @env.nbd1.can_die(1,9)
end end