diff --git a/Rakefile b/Rakefile index 590db27..ba5c813 100644 --- a/Rakefile +++ b/Rakefile @@ -96,8 +96,23 @@ file check("acl") => gcc_link t.name, t.prerequisites + [LIBCHECK] end +file check("serve") => +%w{tests/check_serve.c + build/self_pipe.o + build/nbdtypes.o + build/control.o + build/readwrite.o + build/parse.o + build/client.o + build/serve.o + build/acl.o + build/ioutil.o + build/util.o} do |t| + gcc_link t.name, t.prerequisites + [LIBCHECK] +end -(TEST_MODULES- %w{acl client}).each do |m| + +(TEST_MODULES- %w{acl client serve}).each do |m| deps = ["tests/check_#{m}.c", "build/ioutil.o", "build/util.o"] maybe_obj_name = "build/#{m}.o" diff --git a/src/control.c b/src/control.c index 67e7c30..8c36212 100644 --- a/src/control.c +++ b/src/control.c @@ -273,8 +273,7 @@ int control_acl(struct control_params* client, int linesc, char** lines) acl_destroy( new_acl ); } else { - client->serve->acl = new_acl; - acl_destroy( old_acl ); + server_replace_acl( client->serve, new_acl ); write_socket("0: updated"); } diff --git a/src/serve.c b/src/serve.c index b6e5000..384780b 100644 --- a/src/serve.c +++ b/src/serve.c @@ -314,6 +314,20 @@ void server_close_clients( struct server *params ) } +void server_replace_acl( struct server *serve, struct acl * new_acl ) +{ + NULLCHECK(serve); + NULLCHECK(new_acl); + + struct acl * old_acl = serve->acl; + + serve->acl = new_acl; + + if ( old_acl ) { acl_destroy( old_acl ); } + self_pipe_signal( serve->acl_updated_signal ); +} + + /** Accept either an NBD or control socket connection, dispatch appropriately */ void serve_accept_loop(struct server* params) { @@ -402,6 +416,7 @@ void serve_cleanup(struct server* params) close(params->proxy_fd); self_pipe_destroy( params->close_signal ); + self_pipe_destroy( params->acl_updated_signal ); free(params->allocation_map); @@ -426,9 +441,9 @@ void do_serve(struct server* params) pthread_mutex_init(¶ms->l_io, NULL); params->close_signal = self_pipe_create(); - if ( NULL == params->close_signal) { - SERVER_ERROR( "close signal creation failed" ); - } + NULLCHECK( params->close_signal ); + params->acl_updated_signal = self_pipe_create(); + NULLCHECK( params->acl_updated_signal ); serve_open_server_socket(params); serve_open_control_socket(params); diff --git a/src/serve.h b/src/serve.h index f96222b..3d0d4c4 100644 --- a/src/serve.h +++ b/src/serve.h @@ -3,14 +3,14 @@ #define _GNU_SOURCE -#ifndef _LARGEFILE64_SOURCE -# define _LARGEFILE64_SOURCE -#endif +#define _LARGEFILE64_SOURCE + +#include +#include #include "parse.h" #include "acl.h" -#include static const int block_allocation_resolution = 4096;//128<<10; @@ -69,6 +69,11 @@ struct server { /** to interrupt accept loop and clients, write() to close_signal[1] */ struct self_pipe * close_signal; + /** acl_updated_signal will be signalled after the acl struct + * has been replaced + */ + struct self_pipe * acl_updated_signal; + struct mirror_status* mirror; int server_fd; int control_fd; diff --git a/tests/check_serve.c b/tests/check_serve.c new file mode 100644 index 0000000..b14c93d --- /dev/null +++ b/tests/check_serve.c @@ -0,0 +1,65 @@ +#include "serve.h" +#include "self_pipe.h" + +#include +#include + + +START_TEST( test_replaces_acl ) +{ + struct server s; + s.acl_updated_signal = self_pipe_create(); + struct acl * acl = acl_create( 0, NULL, 0 ); + + server_replace_acl( &s, acl ); + + fail_unless( s.acl == acl, "ACL wasn't replaced." ); + self_pipe_destroy( s.acl_updated_signal ); +} +END_TEST + + +START_TEST( test_signals_acl_updated ) +{ + struct server s; + struct acl * new_acl = acl_create( 0, NULL, 0 ); + + s.acl_updated_signal = self_pipe_create(); + s.acl = acl_create( 0, NULL, 0); + + + server_replace_acl( &s, new_acl ); + + fail_unless( 1 == self_pipe_signal_clear( s.acl_updated_signal ), + "No signal sent." ); + self_pipe_destroy( s.acl_updated_signal ); +} +END_TEST + + +Suite* serve_suite() +{ + Suite *s = suite_create("serve"); + TCase *tc_acl_update = tcase_create("acl_update"); + + tcase_add_test(tc_acl_update, test_replaces_acl); + tcase_add_test(tc_acl_update, test_signals_acl_updated); + + suite_add_tcase(s, tc_acl_update); + + return s; +} + + +int main(void) +{ + set_debug(1); + int number_failed; + Suite *s = serve_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; +} +