From 1d5b315f1773660689b5b55cc7081d7e999aa5ef Mon Sep 17 00:00:00 2001 From: "James F. Carter" Date: Wed, 10 Jan 2018 13:49:22 +0000 Subject: [PATCH 01/71] apply tcp keepalive to serving sockets --- src/common/sockutil.c | 28 ++++++++++++++++++++++++++++ src/common/sockutil.h | 15 +++++++++++++++ src/server/serve.c | 3 +++ src/server/serve.h | 3 +++ 4 files changed, 49 insertions(+) diff --git a/src/common/sockutil.c b/src/common/sockutil.c index a924026..23bb97c 100644 --- a/src/common/sockutil.c +++ b/src/common/sockutil.c @@ -68,6 +68,34 @@ int sock_set_reuseaddr( int fd, int optval ) return setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval) ); } +int sock_set_keepalive_params( int fd, int time, int intvl, int probes) +{ + return sock_set_keepalive(fd, 1) || + sock_set_tcp_keepidle(fd, time) || + sock_set_tcp_keepintvl(fd, intvl) || + sock_set_tcp_keepcnt(fd, probes); +} + +int sock_set_keepalive( int fd, int optval ) +{ + return setsockopt( fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval) ); +} + +int sock_set_tcp_keepidle( int fd, int optval ) +{ + return setsockopt( fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, sizeof(optval) ); +} + +int sock_set_tcp_keepintvl( int fd, int optval ) +{ + return setsockopt( fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, sizeof(optval) ); +} + +int sock_set_tcp_keepcnt( int fd, int optval ) +{ + return setsockopt( fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(optval) ); +} + /* Set the tcp_nodelay option */ int sock_set_tcp_nodelay( int fd, int optval ) { diff --git a/src/common/sockutil.h b/src/common/sockutil.h index e79b566..94dbf85 100644 --- a/src/common/sockutil.h +++ b/src/common/sockutil.h @@ -14,9 +14,24 @@ size_t sockaddr_size(const struct sockaddr* sa); */ const char* sockaddr_address_string(const struct sockaddr* sa, char* dest, size_t len); +/* Configure TCP keepalive on a socket */ +int sock_set_keepalive_params( int fd, int time, int intvl, int probes); + +/* Set the SOL_KEEPALIVE otion */ +int sock_set_keepalive(int fd, int optval); + /* Set the SOL_REUSEADDR otion */ int sock_set_reuseaddr(int fd, int optval); +/* Set the tcp_keepidle option */ +int sock_set_tcp_keepidle(int fd, int optval); + +/* Set the tcp_keepintvl option */ +int sock_set_tcp_keepintvl(int fd, int optval); + +/* Set the tcp_keepcnt option */ +int sock_set_tcp_keepcnt(int fd, int optval); + /* Set the tcp_nodelay option */ int sock_set_tcp_nodelay(int fd, int optval); diff --git a/src/server/serve.c b/src/server/serve.c index de6b871..225e384 100644 --- a/src/server/serve.c +++ b/src/server/serve.c @@ -422,6 +422,9 @@ void accept_nbd_client( int slot; char s_client_address[64] = {0}; + FATAL_IF_NEGATIVE( sock_set_keepalive_params( client_fd, CLIENT_KEEPALIVE_TIME, CLIENT_KEEPALIVE_INTVL, CLIENT_KEEPALIVE_PROBES), + "Error setting keepalive parameters on client socket fd %d", client_fd ); + if ( !server_should_accept_client( params, client_address, s_client_address, 64 ) ) { FATAL_IF_NEGATIVE( close( client_fd ), diff --git a/src/server/serve.h b/src/server/serve.h index 5d04e14..1b697f2 100644 --- a/src/server/serve.h +++ b/src/server/serve.h @@ -21,6 +21,9 @@ struct client_tbl_entry { #define MAX_NBD_CLIENTS 16 +#define CLIENT_KEEPALIVE_TIME 30 +#define CLIENT_KEEPALIVE_INTVL 10 +#define CLIENT_KEEPALIVE_PROBES 3 struct server { /* The flexnbd wrapper this server is attached to */ struct flexnbd * flexnbd; From 0c668f17766608dca7f3e37919252899419bf612 Mon Sep 17 00:00:00 2001 From: "James F. Carter" Date: Wed, 10 Jan 2018 13:54:26 +0000 Subject: [PATCH 02/71] remember how || works in C --- src/common/sockutil.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/common/sockutil.c b/src/common/sockutil.c index 23bb97c..158e8cd 100644 --- a/src/common/sockutil.c +++ b/src/common/sockutil.c @@ -70,10 +70,13 @@ int sock_set_reuseaddr( int fd, int optval ) int sock_set_keepalive_params( int fd, int time, int intvl, int probes) { - return sock_set_keepalive(fd, 1) || + if (sock_set_keepalive(fd, 1) || sock_set_tcp_keepidle(fd, time) || sock_set_tcp_keepintvl(fd, intvl) || - sock_set_tcp_keepcnt(fd, probes); + sock_set_tcp_keepcnt(fd, probes)) { + return -1; + } + return 0; } int sock_set_keepalive( int fd, int optval ) From 884a7147448f734247e20792766dadaaebe98acc Mon Sep 17 00:00:00 2001 From: "James F. Carter" Date: Wed, 10 Jan 2018 13:55:05 +0000 Subject: [PATCH 03/71] whitespace fix --- src/common/sockutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/sockutil.c b/src/common/sockutil.c index 158e8cd..56d728f 100644 --- a/src/common/sockutil.c +++ b/src/common/sockutil.c @@ -74,7 +74,7 @@ int sock_set_keepalive_params( int fd, int time, int intvl, int probes) sock_set_tcp_keepidle(fd, time) || sock_set_tcp_keepintvl(fd, intvl) || sock_set_tcp_keepcnt(fd, probes)) { - return -1; + return -1; } return 0; } From d62b069ce4a3c162d20363fd123156c311aad4b7 Mon Sep 17 00:00:00 2001 From: "James F. Carter" Date: Wed, 10 Jan 2018 13:58:11 +0000 Subject: [PATCH 04/71] debian: update changelog --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index de8ee40..0403ca2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +flexnbd (0.1.8) UNRELEASED; urgency=medium + + * Set TCP keepalive on sockets so broken connections are reaped (#33, !33) + + -- James Carter Wed, 10 Jan 2018 13:57:10 +0000 + flexnbd (0.1.7) stable; urgency=medium * Return bytes_left in migration statistics. From 2702e73a26fa038cfc98dd62c643ed7563c89227 Mon Sep 17 00:00:00 2001 From: "James F. Carter" Date: Thu, 11 Jan 2018 10:01:42 +0000 Subject: [PATCH 05/71] add a log_context, a string output as part of any log message --- src/common/util.c | 1 + src/common/util.h | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/common/util.c b/src/common/util.c index 1c72266..b6a279b 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -13,6 +13,7 @@ pthread_key_t cleanup_handler_key; int log_level = 2; +char *log_context = ""; void error_init(void) { diff --git a/src/common/util.h b/src/common/util.h index cb20bca..3f05e78 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -21,6 +21,9 @@ extern int log_level; /* set up the error globals */ void error_init(void); +/* some context for the overall process that appears on each log line */ +extern char *log_context; + void exit_err( const char * ); @@ -92,7 +95,7 @@ uint64_t monotonic_time_ms(void); #define levstr(i) (i==0?'D':(i==1?'I':(i==2?'W':(i==3?'E':'F')))) -#define myloglev(level, msg, ...) mylog( level, "%"PRIu64":%c:%d %p %s:%d: "msg"\n", monotonic_time_ms(), levstr(level), getpid(),pthread_self(), __FILE__, __LINE__, ##__VA_ARGS__ ) +#define myloglev(level, msg, ...) mylog( level, "%"PRIu64":%c:%d %p %s %s:%d: "msg"\n", monotonic_time_ms(), levstr(level), getpid(),pthread_self(), log_context, __FILE__, __LINE__, ##__VA_ARGS__ ) #ifdef DEBUG # define debug(msg, ...) myloglev(0, msg, ##__VA_ARGS__) From 1cb11bfd38ef58e3b0aedce7f665002bc2dd35fc Mon Sep 17 00:00:00 2001 From: "James F. Carter" Date: Thu, 11 Jan 2018 10:03:16 +0000 Subject: [PATCH 06/71] serve sets the disc's backing file as its log context --- src/server/serve.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/server/serve.c b/src/server/serve.c index 225e384..d88e9f4 100644 --- a/src/server/serve.c +++ b/src/server/serve.c @@ -78,6 +78,8 @@ struct server * server_create ( NULLCHECK( out->close_signal ); NULLCHECK( out->acl_updated_signal ); + log_context = s_file; + return out; } From fa75de0a8b8312c7ab5e395d627da3595668c818 Mon Sep 17 00:00:00 2001 From: "James F. Carter" Date: Thu, 11 Jan 2018 10:04:18 +0000 Subject: [PATCH 07/71] proxy sets the upstream address and port as its log context --- src/proxy/proxy.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/proxy/proxy.c b/src/proxy/proxy.c index 31e3ff4..bdc1407 100644 --- a/src/proxy/proxy.c +++ b/src/proxy/proxy.c @@ -79,6 +79,9 @@ struct proxier* proxy_create( out->req.buf = xmalloc( NBD_MAX_SIZE ); out->rsp.buf = xmalloc( NBD_MAX_SIZE ); + log_context = xmalloc( strlen(s_upstream_address) + strlen(s_upstream_port) + 2 ); + sprintf(log_context, "%s:%s", s_upstream_address, s_upstream_port); + return out; } From 6d96d751d8cb2aee1eafc63d899a8c2276b7bea6 Mon Sep 17 00:00:00 2001 From: "James F. Carter" Date: Thu, 11 Jan 2018 10:06:03 +0000 Subject: [PATCH 08/71] debian: update changelog --- debian/changelog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 0403ca2..2e3d4de 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,9 @@ flexnbd (0.1.8) UNRELEASED; urgency=medium * Set TCP keepalive on sockets so broken connections are reaped (#33, !33) + * Add a context to logs to make debugging problems easier (#34, !34) - -- James Carter Wed, 10 Jan 2018 13:57:10 +0000 + -- James Carter Thu, 11 Jan 2018 10:05:35 +0000 flexnbd (0.1.7) stable; urgency=medium From ceb3328261f22e3ad79a31e03158ec2c4224260b Mon Sep 17 00:00:00 2001 From: Chris Cottam Date: Thu, 18 Jan 2018 16:52:24 +0000 Subject: [PATCH 09/71] increasing the NBD max size to see if it fixes an issue with qemu-2.11.0 --- src/common/nbdtypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/nbdtypes.h b/src/common/nbdtypes.h index 49139c4..6e1b124 100644 --- a/src/common/nbdtypes.h +++ b/src/common/nbdtypes.h @@ -16,7 +16,7 @@ /* 1MiB is the de-facto standard for maximum size of header + data */ -#define NBD_MAX_SIZE ( 1024 * 1024 ) +#define NBD_MAX_SIZE ( 16 * 1024 * 1024 ) #define NBD_REQUEST_SIZE ( sizeof( struct nbd_request_raw ) ) #define NBD_REPLY_SIZE ( sizeof( struct nbd_reply_raw ) ) From c37627a5b9d18dce32536357444d821ce674a46a Mon Sep 17 00:00:00 2001 From: Chris Cottam Date: Thu, 18 Jan 2018 17:08:32 +0000 Subject: [PATCH 10/71] not high enough, trying 32MB --- src/common/nbdtypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/nbdtypes.h b/src/common/nbdtypes.h index 6e1b124..3e3db22 100644 --- a/src/common/nbdtypes.h +++ b/src/common/nbdtypes.h @@ -16,7 +16,7 @@ /* 1MiB is the de-facto standard for maximum size of header + data */ -#define NBD_MAX_SIZE ( 16 * 1024 * 1024 ) +#define NBD_MAX_SIZE ( 32 * 1024 * 1024 ) #define NBD_REQUEST_SIZE ( sizeof( struct nbd_request_raw ) ) #define NBD_REPLY_SIZE ( sizeof( struct nbd_reply_raw ) ) From 9b1781164ab8468b279da2b980a6c78e949a539a Mon Sep 17 00:00:00 2001 From: "James F. Carter" Date: Fri, 26 Jan 2018 15:03:44 +0000 Subject: [PATCH 11/71] avoid fatal error on client connection timeout --- src/server/client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/server/client.c b/src/server/client.c index 8b57b47..0614a6d 100644 --- a/src/server/client.c +++ b/src/server/client.c @@ -234,6 +234,10 @@ int client_read_request( struct client * client , struct nbd_request *out_reques debug( "Connection reset while" " reading request" ); return 0; + case ETIMEDOUT: + debug( "Connection timed out while" + " reading request" ); + return 0; default: /* FIXME: I've seen this happen, but I * couldn't reproduce it so I'm leaving From b2007c9dad6c94dd9b8852107191ced34e00ee2b Mon Sep 17 00:00:00 2001 From: "James F. Carter" Date: Fri, 26 Jan 2018 15:06:26 +0000 Subject: [PATCH 12/71] debian: uodate changelog --- debian/changelog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 2e3d4de..a99a8dc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ flexnbd (0.1.8) UNRELEASED; urgency=medium - * Set TCP keepalive on sockets so broken connections are reaped (#33, !33) + * Set TCP keepalive on sockets so broken connections are reaped (#33, !33, + !36) * Add a context to logs to make debugging problems easier (#34, !34) -- James Carter Thu, 11 Jan 2018 10:05:35 +0000 From 25cc084108f03b248a7163e817b7015de9148c39 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Thu, 1 Feb 2018 19:25:36 +0000 Subject: [PATCH 13/71] First steps towards implementing flags as part of oldstyle negotiation --- src/common/nbdtypes.c | 2 ++ src/common/nbdtypes.h | 16 ++++++++++++---- src/server/client.c | 4 +++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/common/nbdtypes.c b/src/common/nbdtypes.c index 18bd419..08dc0c9 100644 --- a/src/common/nbdtypes.c +++ b/src/common/nbdtypes.c @@ -13,6 +13,7 @@ void nbd_r2h_init( struct nbd_init_raw * from, struct nbd_init * to ) memcpy( to->passwd, from->passwd, 8 ); to->magic = be64toh( from->magic ); to->size = be64toh( from->size ); + to->flags = be32toh( from->flags ); } void nbd_h2r_init( struct nbd_init * from, struct nbd_init_raw * to) @@ -20,6 +21,7 @@ void nbd_h2r_init( struct nbd_init * from, struct nbd_init_raw * to) memcpy( to->passwd, from->passwd, 8 ); to->magic = htobe64( from->magic ); to->size = htobe64( from->size ); + to->flags = htobe32( from->flags ); } diff --git a/src/common/nbdtypes.h b/src/common/nbdtypes.h index 3e3db22..bc4f413 100644 --- a/src/common/nbdtypes.h +++ b/src/common/nbdtypes.h @@ -11,6 +11,14 @@ #define REQUEST_WRITE 1 #define REQUEST_DISCONNECT 2 +#define NBD_FLAG_HAS_FLAGS (1 << 0) +#define NBD_FLAG_READ_ONLY (1 << 1) +#define NBD_FLAG_SEND_FLUSH (1 << 2) +#define NBD_FLAG_SEND_FUA (1 << 3) +#define NBD_FLAG_ROTATIONAL (1 << 4) +#define NBD_FLAG_SEND_TRIM (1 << 5) +#define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) + /* The top 2 bytes of the type field are overloaded and can contain flags */ #define REQUEST_MASK 0x0000ffff @@ -38,7 +46,8 @@ struct nbd_init_raw { char passwd[8]; __be64 magic; __be64 size; - char reserved[128]; + __be32 flags; + char reserved[124]; }; struct nbd_request_raw { @@ -55,13 +64,12 @@ struct nbd_reply_raw { nbd_handle_t handle; /* handle you got from request */ }; - - struct nbd_init { char passwd[8]; uint64_t magic; uint64_t size; - char reserved[128]; + uint32_t flags; + char reserved[124]; }; struct nbd_request { diff --git a/src/server/client.c b/src/server/client.c index 0614a6d..9c23a4d 100644 --- a/src/server/client.c +++ b/src/server/client.c @@ -307,7 +307,9 @@ void client_write_init( struct client * client, uint64_t size ) memcpy( init.passwd, INIT_PASSWD, sizeof( init.passwd ) ); init.magic = INIT_MAGIC; init.size = size; - memset( init.reserved, 0, 128 ); + // TODO actually implement these flags! + init.flags = NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA; + // memset( init.reserved, 0, 124 ); nbd_h2r_init( &init, &init_raw ); From 1f0ef0aad671341ac61ddbce55caac55282fdfb9 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Thu, 1 Feb 2018 22:13:59 +0000 Subject: [PATCH 14/71] Implement FLUSH command and honour FUA flag I changed the request struct to break the 32 bits reserved for the request type into two. The first part of this is used for the flags (such as FUA), and the second part for the command type. Previously we'd masked the top two bytes, thus ignoring any flags. --- src/common/nbdtypes.c | 6 ++++-- src/common/nbdtypes.h | 31 ++++++++++++++++++++----------- src/proxy/proxy.c | 10 +++++----- src/server/client.c | 26 +++++++++++++++++++++----- 4 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/common/nbdtypes.c b/src/common/nbdtypes.c index 08dc0c9..f45bf0f 100644 --- a/src/common/nbdtypes.c +++ b/src/common/nbdtypes.c @@ -28,7 +28,8 @@ void nbd_h2r_init( struct nbd_init * from, struct nbd_init_raw * to) void nbd_r2h_request( struct nbd_request_raw *from, struct nbd_request * to ) { to->magic = htobe32( from->magic ); - to->type = htobe32( from->type ); + to->flags = htobe16( from->flags ); + to->type = htobe16( from->type ); to->handle.w = from->handle.w; to->from = htobe64( from->from ); to->len = htobe32( from->len ); @@ -37,7 +38,8 @@ void nbd_r2h_request( struct nbd_request_raw *from, struct nbd_request * to ) void nbd_h2r_request( struct nbd_request * from, struct nbd_request_raw * to ) { to->magic = be32toh( from->magic ); - to->type = be32toh( from->type ); + to->flags = be16toh( from->flags ); + to->type = be16toh( from->type ); to->handle.w = from->handle.w; to->from = be64toh( from->from ); to->len = be32toh( from->len ); diff --git a/src/common/nbdtypes.h b/src/common/nbdtypes.h index bc4f413..7f406c2 100644 --- a/src/common/nbdtypes.h +++ b/src/common/nbdtypes.h @@ -8,20 +8,27 @@ #define REQUEST_MAGIC 0x25609513 #define REPLY_MAGIC 0x67446698 #define REQUEST_READ 0 + #define REQUEST_WRITE 1 #define REQUEST_DISCONNECT 2 +#define REQUEST_FLUSH 3 +#define REQUEST_TRIM 4 +#define REQUEST_WRITE_ZEROES 6 -#define NBD_FLAG_HAS_FLAGS (1 << 0) -#define NBD_FLAG_READ_ONLY (1 << 1) -#define NBD_FLAG_SEND_FLUSH (1 << 2) -#define NBD_FLAG_SEND_FUA (1 << 3) -#define NBD_FLAG_ROTATIONAL (1 << 4) -#define NBD_FLAG_SEND_TRIM (1 << 5) -#define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) +#define FLAG_HAS_FLAGS (1 << 0) +#define FLAG_READ_ONLY (1 << 1) +#define FLAG_SEND_FLUSH (1 << 2) +#define FLAG_SEND_FUA (1 << 3) +#define FLAG_ROTATIONAL (1 << 4) +#define FLAG_SEND_TRIM (1 << 5) +#define FLAG_SEND_WRITE_ZEROES (1 << 6) +#define FLAG_CAN_MULTI_CONN (1 << 8) /* multiple connections are okay */ + +#define CMD_FLAG_FUA (1 << 0) +#define CMD_FLAG_NO_HOLE (1 << 1) /* The top 2 bytes of the type field are overloaded and can contain flags */ -#define REQUEST_MASK 0x0000ffff - +// #define REQUEST_MASK 0x0000ffff /* 1MiB is the de-facto standard for maximum size of header + data */ #define NBD_MAX_SIZE ( 32 * 1024 * 1024 ) @@ -52,7 +59,8 @@ struct nbd_init_raw { struct nbd_request_raw { __be32 magic; - __be32 type; /* == READ || == WRITE */ + __be16 flags; + __be16 type; /* == READ || == WRITE || == FLUSH */ nbd_handle_t handle; __be64 from; __be32 len; @@ -74,7 +82,8 @@ struct nbd_init { struct nbd_request { uint32_t magic; - uint32_t type; /* == READ || == WRITE || == DISCONNECT */ + uint16_t flags; + uint16_t type; /* == READ || == WRITE || == DISCONNECT || == FLUSH */ nbd_handle_t handle; uint64_t from; uint32_t len; diff --git a/src/proxy/proxy.c b/src/proxy/proxy.c index bdc1407..c8af40e 100644 --- a/src/proxy/proxy.c +++ b/src/proxy/proxy.c @@ -305,7 +305,7 @@ int proxy_prefetch_for_request( struct proxier* proxy, int state ) struct nbd_request_raw* req_raw = (struct nbd_request_raw*) proxy->req.buf; struct nbd_reply_raw *rsp_raw = (struct nbd_reply_raw*) proxy->rsp.buf; - int is_read = ( req->type & REQUEST_MASK ) == REQUEST_READ; + int is_read = req->type == REQUEST_READ; if ( is_read ) { /* See if we can respond with what's in our prefetch @@ -435,19 +435,19 @@ int proxy_read_from_downstream( struct proxier *proxy, int state ) if ( proxy->req.needle == NBD_REQUEST_SIZE ) { nbd_r2h_request( request_raw, request ); - if ( ( request->type & REQUEST_MASK ) == REQUEST_DISCONNECT ) { + if ( request->type == REQUEST_DISCONNECT ) { info( "Received disconnect request from client" ); return EXIT; } /* Simple validations */ - if ( ( request->type & REQUEST_MASK ) == REQUEST_READ ) { + if ( request->type == REQUEST_READ ) { if (request->len > ( NBD_MAX_SIZE - NBD_REPLY_SIZE ) ) { warn( "NBD read request size %"PRIu32" too large", request->len ); return EXIT; } } - if ( (request->type & REQUEST_MASK ) == REQUEST_WRITE ) { + if ( request->type == REQUEST_WRITE ) { if (request->len > ( NBD_MAX_SIZE - NBD_REQUEST_SIZE ) ) { warn( "NBD write request size %"PRIu32" too large", request->len ); return EXIT; @@ -607,7 +607,7 @@ int proxy_read_from_upstream( struct proxier* proxy, int state ) goto disconnect; } - if ( ( proxy->req_hdr.type & REQUEST_MASK ) == REQUEST_READ ) { + if ( proxy->req_hdr.type == REQUEST_READ ) { /* Get the read reply data too. */ proxy->rsp.size += proxy->req_hdr.len; } diff --git a/src/server/client.c b/src/server/client.c index 9c23a4d..58ba199 100644 --- a/src/server/client.c +++ b/src/server/client.c @@ -308,7 +308,7 @@ void client_write_init( struct client * client, uint64_t size ) init.magic = INIT_MAGIC; init.size = size; // TODO actually implement these flags! - init.flags = NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA; + init.flags = FLAG_HAS_FLAGS | FLAG_SEND_FLUSH | FLAG_SEND_FUA; // memset( init.reserved, 0, 124 ); nbd_h2r_init( &init, &init_raw ); @@ -385,8 +385,8 @@ int client_request_needs_reply( struct client * client, } debug( - "request type=%"PRIu32", from=%"PRIu64", len=%"PRIu32", handle=0x%08X", - request.type, request.from, request.len, request.handle + "request type=%"PRIu16", flags=%"PRIu16", from=%"PRIu64", len=%"PRIu32", handle=0x%08X", + request.type, request.flags, request.from, request.len, request.handle ); /* check it's not out of range */ @@ -413,7 +413,8 @@ int client_request_needs_reply( struct client * client, debug("request disconnect"); client->disconnect = 1; return 0; - + case REQUEST_FLUSH: + break; default: fatal("Unknown request 0x%08X", request.type); } @@ -474,7 +475,8 @@ void client_reply_to_write( struct client* client, struct nbd_request request ) bitset_set_range(client->serve->allocation_map, request.from, request.len); } - if (1) /* not sure whether this is necessary... */ + // Only flush if FUA is set + if (request.flags & CMD_FLAG_FUA) { /* multiple of 4K page size */ uint64_t from_rounded = request.from & (!0xfff); @@ -490,6 +492,17 @@ void client_reply_to_write( struct client* client, struct nbd_request request ) client_write_reply( client, &request, 0); } +void client_reply_to_flush( struct client* client, struct nbd_request request ) +{ + debug("request flush from=%"PRIu64", len=%"PRIu32", handle=0x%08X", request.from, request.len, request.handle); + + ERROR_IF_NEGATIVE( + fsync(client->fileno), + "flush failed" + ); + + client_write_reply( client, &request, 0); +} void client_reply( struct client* client, struct nbd_request request ) { @@ -500,6 +513,9 @@ void client_reply( struct client* client, struct nbd_request request ) case REQUEST_WRITE: client_reply_to_write( client, request ); break; + case REQUEST_FLUSH: + client_reply_to_flush( client, request ); + break; } } From 68a196e93d38d09dac2da8396a8ca63d22a2ba75 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 10:30:40 +0000 Subject: [PATCH 15/71] Allow the proxy connection to pass through flags from upstream. --- src/common/readwrite.c | 20 +++++++++++++------- src/common/readwrite.h | 8 ++++---- src/proxy/proxy.c | 31 +++++++++++++++++++++++++------ src/proxy/proxy.h | 5 ++++- src/server/mirror.c | 3 ++- 5 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/common/readwrite.c b/src/common/readwrite.c index 30f63f6..81de855 100644 --- a/src/common/readwrite.c +++ b/src/common/readwrite.c @@ -41,7 +41,7 @@ int socket_connect(struct sockaddr* to, struct sockaddr* from) return fd; } -int nbd_check_hello( struct nbd_init_raw* init_raw, uint64_t* out_size ) +int nbd_check_hello( struct nbd_init_raw* init_raw, uint64_t* out_size, uint32_t* out_flags ) { if ( strncmp( init_raw->passwd, INIT_PASSWD, 8 ) != 0 ) { warn( "wrong passwd" ); @@ -55,6 +55,10 @@ int nbd_check_hello( struct nbd_init_raw* init_raw, uint64_t* out_size ) if ( NULL != out_size ) { *out_size = be64toh( init_raw->size ); } + + if ( NULL != out_flags ) { + *out_flags = be32toh( init_raw->flags ); + } return 1; fail: @@ -62,7 +66,7 @@ fail: } -int socket_nbd_read_hello( int fd, uint64_t* out_size ) +int socket_nbd_read_hello( int fd, uint64_t* out_size, uint32_t* out_flags ) { struct nbd_init_raw init_raw; @@ -72,16 +76,17 @@ int socket_nbd_read_hello( int fd, uint64_t* out_size ) return 0; } - return nbd_check_hello( &init_raw, out_size ); + return nbd_check_hello( &init_raw, out_size, out_flags ); } -void nbd_hello_to_buf( struct nbd_init_raw *buf, off64_t out_size ) +void nbd_hello_to_buf( struct nbd_init_raw *buf, off64_t out_size, uint32_t out_flags ) { struct nbd_init init; memcpy( &init.passwd, INIT_PASSWD, 8 ); init.magic = INIT_MAGIC; init.size = out_size; + init.flags = out_flags; memset( buf, 0, sizeof( struct nbd_init_raw ) ); // ensure reserved is 0s nbd_h2r_init( &init, buf ); @@ -89,10 +94,10 @@ void nbd_hello_to_buf( struct nbd_init_raw *buf, off64_t out_size ) return; } -int socket_nbd_write_hello(int fd, off64_t out_size) +int socket_nbd_write_hello( int fd, off64_t out_size, uint32_t out_flags ) { struct nbd_init_raw init_raw; - nbd_hello_to_buf( &init_raw, out_size ); + nbd_hello_to_buf( &init_raw, out_size, out_flags ); if ( 0 > writeloop( fd, &init_raw, sizeof( init_raw ) ) ) { warn( SHOW_ERRNO( "failed to write hello to socket" ) ); @@ -213,7 +218,8 @@ int socket_nbd_disconnect( int fd ) #define CHECK_RANGE(error_type) { \ uint64_t size;\ - int success = socket_nbd_read_hello(params->client, &size); \ + uint32_t flags;\ + int success = socket_nbd_read_hello(params->client, &size, &flags); \ if ( success ) {\ uint64_t endpoint = params->from + params->len; \ if (endpoint > size || \ diff --git a/src/common/readwrite.h b/src/common/readwrite.h index 04b12c6..8b7371b 100644 --- a/src/common/readwrite.h +++ b/src/common/readwrite.h @@ -7,8 +7,8 @@ #include "nbdtypes.h" int socket_connect(struct sockaddr* to, struct sockaddr* from); -int socket_nbd_read_hello(int fd, uint64_t* size); -int socket_nbd_write_hello(int fd, uint64_t size); +int socket_nbd_read_hello(int fd, uint64_t* size, uint32_t* flags); +int socket_nbd_write_hello(int fd, uint64_t size, uint32_t flags); void socket_nbd_read(int fd, uint64_t from, uint32_t len, int out_fd, void* out_buf, int timeout_secs); void socket_nbd_write(int fd, uint64_t from, uint32_t len, int out_fd, void* out_buf, int timeout_secs); int socket_nbd_disconnect( int fd ); @@ -16,8 +16,8 @@ int socket_nbd_disconnect( int fd ); /* as you can see, we're slowly accumulating code that should really be in an * NBD library */ -void nbd_hello_to_buf( struct nbd_init_raw* buf, uint64_t out_size ); -int nbd_check_hello( struct nbd_init_raw* init_raw, uint64_t* out_size ); +void nbd_hello_to_buf( struct nbd_init_raw* buf, uint64_t out_size, uint32_t out_flags ); +int nbd_check_hello( struct nbd_init_raw* init_raw, uint64_t* out_size, uint32_t* out_flags ); #endif diff --git a/src/proxy/proxy.c b/src/proxy/proxy.c index c8af40e..78726ca 100644 --- a/src/proxy/proxy.c +++ b/src/proxy/proxy.c @@ -106,7 +106,7 @@ void proxy_destroy( struct proxier* proxy ) } /* Shared between our two different connect_to_upstream paths */ -void proxy_finish_connect_to_upstream( struct proxier *proxy, uint64_t size ); +void proxy_finish_connect_to_upstream( struct proxier *proxy, uint64_t size, uint32_t flags ); /* Try to establish a connection to our upstream server. Return 1 on success, * 0 on failure. this is a blocking call that returns a non-blocking socket. @@ -120,12 +120,13 @@ int proxy_connect_to_upstream( struct proxier* proxy ) int fd = socket_connect( &proxy->connect_to.generic, connect_from ); uint64_t size = 0; + uint32_t flags = 0; if ( -1 == fd ) { return 0; } - if( !socket_nbd_read_hello( fd, &size ) ) { + if( !socket_nbd_read_hello( fd, &size, &flags ) ) { WARN_IF_NEGATIVE( sock_try_close( fd ), "Couldn't close() after failed read of NBD hello on fd %i", fd @@ -135,7 +136,7 @@ int proxy_connect_to_upstream( struct proxier* proxy ) proxy->upstream_fd = fd; sock_set_nonblock( fd, 1 ); - proxy_finish_connect_to_upstream( proxy, size ); + proxy_finish_connect_to_upstream( proxy, size, flags ); return 1; } @@ -191,7 +192,7 @@ error: return; } -void proxy_finish_connect_to_upstream( struct proxier *proxy, uint64_t size ) { +void proxy_finish_connect_to_upstream( struct proxier *proxy, uint64_t size, uint32_t flags ) { if ( proxy->upstream_size == 0 ) { info( "Size of upstream image is %"PRIu64" bytes", size ); @@ -203,6 +204,17 @@ void proxy_finish_connect_to_upstream( struct proxier *proxy, uint64_t size ) { } proxy->upstream_size = size; + + if ( proxy->upstream_flags == 0 ) { + info( "Upstream transmission flags set to %"PRIu32"", flags ); + } else if ( proxy->upstream_flags != flags ) { + warn( + "Upstream transmission flags changed from %"PRIu32" to %"PRIu32"", + proxy->upstream_flags, flags + ); + } + + proxy->upstream_flags = flags; if ( AF_UNIX != proxy->connect_to.family ) { if ( sock_set_tcp_nodelay( proxy->upstream_fd, 1 ) == -1 ) { @@ -516,11 +528,18 @@ int proxy_read_init_from_upstream( struct proxier* proxy, int state ) if ( proxy->init.needle == proxy->init.size ) { uint64_t upstream_size; - if ( !nbd_check_hello( (struct nbd_init_raw*) proxy->init.buf, &upstream_size ) ) { + uint32_t upstream_flags; + if ( !nbd_check_hello( (struct nbd_init_raw*) proxy->init.buf, &upstream_size, &upstream_flags ) ) { warn( "Upstream sent invalid init" ); goto disconnect; } + /* record the flags, and log the reconnection */ + // TODO: Should we call this at all here? We lose the + // upstream_size and flags otherwise, but then we can't + // renegotiate anyway. + // proxy_finish_connect_to_upstream( proxy, upstream_size, upstream_flags ); + /* Currently, we only get disconnected from upstream (so needing to come * here) when we have an outstanding request. If that becomes false, * we'll need to choose the right state to return to here */ @@ -683,7 +702,7 @@ void proxy_session( struct proxier* proxy ) /* First action: Write hello to downstream */ - nbd_hello_to_buf( (struct nbd_init_raw *) proxy->rsp.buf, proxy->upstream_size ); + nbd_hello_to_buf( (struct nbd_init_raw *) proxy->rsp.buf, proxy->upstream_size, proxy->upstream_flags ); proxy->rsp.size = sizeof( struct nbd_init_raw ); proxy->rsp.needle = 0; state = WRITE_TO_DOWNSTREAM; diff --git a/src/proxy/proxy.h b/src/proxy/proxy.h index 5bf24dd..4173fb7 100644 --- a/src/proxy/proxy.h +++ b/src/proxy/proxy.h @@ -46,10 +46,13 @@ struct proxier { /* This is the size we advertise to the downstream server */ uint64_t upstream_size; + /* These are thet transmission flags sent as part of the handshake */ + uint32_t upstream_flags; + /* We transform the raw request header into here */ struct nbd_request req_hdr; - /* We transform the raw reply header into here */ + /* We transform the raw reply header into here */ struct nbd_reply rsp_hdr; /* Used for our non-blocking negotiation with upstream. TODO: maybe use diff --git a/src/server/mirror.c b/src/server/mirror.c index b3d22d5..bd25008 100644 --- a/src/server/mirror.c +++ b/src/server/mirror.c @@ -293,7 +293,8 @@ int mirror_connect( struct mirror * mirror, uint64_t local_size ) if( FD_ISSET( mirror->client, &fds ) ){ uint64_t remote_size; - if ( socket_nbd_read_hello( mirror->client, &remote_size ) ) { + uint32_t remote_flags; + if ( socket_nbd_read_hello( mirror->client, &remote_size, &remote_flags ) ) { if( remote_size == local_size ){ connected = 1; mirror_set_state( mirror, MS_GO ); From 1883bee43c1b700610ff9ab4effe8ee188fbd556 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 14:52:26 +0000 Subject: [PATCH 16/71] Updated changelog for !35 --- debian/changelog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/debian/changelog b/debian/changelog index a99a8dc..c25a53e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,13 @@ flexnbd (0.1.8) UNRELEASED; urgency=medium + [ James Carter ] * Set TCP keepalive on sockets so broken connections are reaped (#33, !33, !36) * Add a context to logs to make debugging problems easier (#34, !34) + [ Chris Cottam ] + * Increased NBD_MAX_SIZE from 1MB to 32MB for qemu 2.11 (!35) + -- James Carter Thu, 11 Jan 2018 10:05:35 +0000 flexnbd (0.1.7) stable; urgency=medium From ad001cb83c26260c664ff8eea530cf7057ce7b8f Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 16:17:01 +0000 Subject: [PATCH 17/71] Tidy comments --- src/common/nbdtypes.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/common/nbdtypes.h b/src/common/nbdtypes.h index 7f406c2..0ca48ef 100644 --- a/src/common/nbdtypes.h +++ b/src/common/nbdtypes.h @@ -15,22 +15,24 @@ #define REQUEST_TRIM 4 #define REQUEST_WRITE_ZEROES 6 -#define FLAG_HAS_FLAGS (1 << 0) -#define FLAG_READ_ONLY (1 << 1) -#define FLAG_SEND_FLUSH (1 << 2) -#define FLAG_SEND_FUA (1 << 3) -#define FLAG_ROTATIONAL (1 << 4) -#define FLAG_SEND_TRIM (1 << 5) -#define FLAG_SEND_WRITE_ZEROES (1 << 6) -#define FLAG_CAN_MULTI_CONN (1 << 8) /* multiple connections are okay */ +/* values for flags field */ +#define FLAG_HAS_FLAGS (1 << 0) /* Flags are there */ +#define FLAG_SEND_FLUSH (1 << 2) /* Send FLUSH */ +#define FLAG_SEND_FUA (1 << 3) /* Send FUA (Force Unit Access) */ + +/* Not yet implemented by flexnbd */ +#define FLAG_READ_ONLY (1 << 1) /* Device is read-only */ +#define FLAG_ROTATIONAL (1 << 4) /* Use elevator algorithm - rotational media */ +#define FLAG_SEND_TRIM (1 << 5) /* Send TRIM (discard) */ +#define FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send NBD_CMD_WRITE_ZEROES */ +#define FLAG_CAN_MULTI_CONN (1 << 8) /* multiple connections are okay */ #define CMD_FLAG_FUA (1 << 0) #define CMD_FLAG_NO_HOLE (1 << 1) -/* The top 2 bytes of the type field are overloaded and can contain flags */ -// #define REQUEST_MASK 0x0000ffff - -/* 1MiB is the de-facto standard for maximum size of header + data */ +/* 32 MiB is the maximum qemu will send you: + * https://github.com/qemu/qemu/blob/v2.11.0/include/block/nbd.h#L183 + */ #define NBD_MAX_SIZE ( 32 * 1024 * 1024 ) #define NBD_REQUEST_SIZE ( sizeof( struct nbd_request_raw ) ) From b22b99d9b9e19e514acc87bb86399f7a9dac2fc4 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 20:28:00 +0000 Subject: [PATCH 18/71] Fix fill_request to set flags as well as type. --- src/common/readwrite.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/common/readwrite.c b/src/common/readwrite.c index 81de855..cae4ffa 100644 --- a/src/common/readwrite.c +++ b/src/common/readwrite.c @@ -106,10 +106,11 @@ int socket_nbd_write_hello( int fd, off64_t out_size, uint32_t out_flags ) return 1; } -void fill_request(struct nbd_request *request, int type, uint64_t from, uint32_t len) +void fill_request(struct nbd_request *request, uint16_t type, uint16_t flags, uint64_t from, uint32_t len) { request->magic = htobe32(REQUEST_MAGIC); - request->type = htobe32(type); + request->type = htobe16(type); + request->flags = htobe16(flags); request->handle.w = (((uint64_t)rand()) << 32) | ((uint64_t)rand()); request->from = htobe64(from); request->len = htobe32(len); @@ -158,7 +159,7 @@ void socket_nbd_read(int fd, uint64_t from, uint32_t len, int out_fd, void* out_ struct nbd_request request; struct nbd_reply reply; - fill_request(&request, REQUEST_READ, from, len); + fill_request(&request, REQUEST_READ, 0, from, len); FATAL_IF_NEGATIVE(writeloop(fd, &request, sizeof(request)), "Couldn't write request"); @@ -182,7 +183,7 @@ void socket_nbd_write(int fd, uint64_t from, uint32_t len, int in_fd, void* in_b struct nbd_request request; struct nbd_reply reply; - fill_request(&request, REQUEST_WRITE, from, len); + fill_request(&request, REQUEST_WRITE, 0, from, len); ERROR_IF_NEGATIVE(writeloop(fd, &request, sizeof(request)), "Couldn't write request"); @@ -207,7 +208,7 @@ int socket_nbd_disconnect( int fd ) int success = 1; struct nbd_request request; - fill_request( &request, REQUEST_DISCONNECT, 0, 0 ); + fill_request( &request, REQUEST_DISCONNECT, 0, 0, 0 ); /* FIXME: This shouldn't be a FATAL error. We should just drop * the mirror without affecting the main server. */ From 72c8c6f7576d33596b6dd5b95ec38ff268ea2b5e Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 20:30:39 +0000 Subject: [PATCH 19/71] Altered test to check for type as a 16-bit uint; added flags test --- tests/unit/check_nbdtypes.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tests/unit/check_nbdtypes.c b/tests/unit/check_nbdtypes.c index 63ab4e8..9124063 100644 --- a/tests/unit/check_nbdtypes.c +++ b/tests/unit/check_nbdtypes.c @@ -66,18 +66,35 @@ START_TEST(test_request_magic ) } END_TEST -START_TEST(test_request_type ) +START_TEST(test_request_type) { struct nbd_request_raw request_raw; struct nbd_request request; - request_raw.type = 12345; + request_raw.type = 123; nbd_r2h_request( &request_raw, &request ); - fail_unless( be32toh( 12345 ) == request.type, "Type was not converted." ); + fail_unless( be16toh( 123 ) == request.type, "Type was not converted." ); - request.type = 67890; + request.type = 234; nbd_h2r_request( &request, &request_raw ); - fail_unless( htobe32( 67890 ) == request_raw.type, "Type was not converted back." ); + fail_unless( htobe16( 234 ) == request_raw.type, "Type was not converted back." ); +} +END_TEST + + + +START_TEST(test_request_flags) +{ + struct nbd_request_raw request_raw; + struct nbd_request request; + + request_raw.flags = 123; + nbd_r2h_request( &request_raw, &request ); + fail_unless( be16toh( 123 ) == request.flags, "Flags were not converted." ); + + request.flags = 234; + nbd_h2r_request( &request, &request_raw ); + fail_unless( htobe16( 234 ) == request_raw.flags, "Flags were not converted back." ); } END_TEST From 6aa5907f5e6fd1c30a99ee17b19dc577cfa542ac Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 20:34:49 +0000 Subject: [PATCH 20/71] Tidied constants up a bit --- src/common/nbdtypes.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/common/nbdtypes.h b/src/common/nbdtypes.h index 0ca48ef..0557c44 100644 --- a/src/common/nbdtypes.h +++ b/src/common/nbdtypes.h @@ -7,28 +7,34 @@ #define INIT_MAGIC 0x0000420281861253 #define REQUEST_MAGIC 0x25609513 #define REPLY_MAGIC 0x67446698 -#define REQUEST_READ 0 +#define REQUEST_READ 0 #define REQUEST_WRITE 1 #define REQUEST_DISCONNECT 2 #define REQUEST_FLUSH 3 -#define REQUEST_TRIM 4 -#define REQUEST_WRITE_ZEROES 6 -/* values for flags field */ +/* values for transmission flag field */ #define FLAG_HAS_FLAGS (1 << 0) /* Flags are there */ #define FLAG_SEND_FLUSH (1 << 2) /* Send FLUSH */ #define FLAG_SEND_FUA (1 << 3) /* Send FUA (Force Unit Access) */ +/* values for command flag field */ +#define CMD_FLAG_FUA (1 << 0) + +#if 0 /* Not yet implemented by flexnbd */ +#define REQUEST_TRIM 4 +#define REQUEST_WRITE_ZEROES 6 + #define FLAG_READ_ONLY (1 << 1) /* Device is read-only */ #define FLAG_ROTATIONAL (1 << 4) /* Use elevator algorithm - rotational media */ #define FLAG_SEND_TRIM (1 << 5) /* Send TRIM (discard) */ #define FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send NBD_CMD_WRITE_ZEROES */ #define FLAG_CAN_MULTI_CONN (1 << 8) /* multiple connections are okay */ -#define CMD_FLAG_FUA (1 << 0) #define CMD_FLAG_NO_HOLE (1 << 1) +#endif + /* 32 MiB is the maximum qemu will send you: * https://github.com/qemu/qemu/blob/v2.11.0/include/block/nbd.h#L183 From 9eb7072f4984927a07f7621db3e3e05b611e7dc4 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 20:46:25 +0000 Subject: [PATCH 21/71] Removed some extra spaces I'd added --- src/common/nbdtypes.h | 6 +++--- src/common/readwrite.c | 2 +- src/proxy/proxy.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common/nbdtypes.h b/src/common/nbdtypes.h index 0557c44..5d5b614 100644 --- a/src/common/nbdtypes.h +++ b/src/common/nbdtypes.h @@ -19,7 +19,7 @@ #define FLAG_SEND_FUA (1 << 3) /* Send FUA (Force Unit Access) */ /* values for command flag field */ -#define CMD_FLAG_FUA (1 << 0) +#define CMD_FLAG_FUA (1 << 0) #if 0 /* Not yet implemented by flexnbd */ @@ -67,7 +67,7 @@ struct nbd_init_raw { struct nbd_request_raw { __be32 magic; - __be16 flags; + __be16 flags; __be16 type; /* == READ || == WRITE || == FLUSH */ nbd_handle_t handle; __be64 from; @@ -90,7 +90,7 @@ struct nbd_init { struct nbd_request { uint32_t magic; - uint16_t flags; + uint16_t flags; uint16_t type; /* == READ || == WRITE || == DISCONNECT || == FLUSH */ nbd_handle_t handle; uint64_t from; diff --git a/src/common/readwrite.c b/src/common/readwrite.c index cae4ffa..03bcb13 100644 --- a/src/common/readwrite.c +++ b/src/common/readwrite.c @@ -55,7 +55,7 @@ int nbd_check_hello( struct nbd_init_raw* init_raw, uint64_t* out_size, uint32_t if ( NULL != out_size ) { *out_size = be64toh( init_raw->size ); } - + if ( NULL != out_flags ) { *out_flags = be32toh( init_raw->flags ); } diff --git a/src/proxy/proxy.c b/src/proxy/proxy.c index 78726ca..bacffee 100644 --- a/src/proxy/proxy.c +++ b/src/proxy/proxy.c @@ -204,7 +204,7 @@ void proxy_finish_connect_to_upstream( struct proxier *proxy, uint64_t size, uin } proxy->upstream_size = size; - + if ( proxy->upstream_flags == 0 ) { info( "Upstream transmission flags set to %"PRIu32"", flags ); } else if ( proxy->upstream_flags != flags ) { From 051576df6d8e99331b4f2921aaa91b2da7b00846 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 20:46:46 +0000 Subject: [PATCH 22/71] Remove warnings about Object#timeout --- tests/acceptance/proxy_tests.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/acceptance/proxy_tests.rb b/tests/acceptance/proxy_tests.rb index 37b5a9d..d08f8e7 100644 --- a/tests/acceptance/proxy_tests.rb +++ b/tests/acceptance/proxy_tests.rb @@ -114,7 +114,7 @@ module ProxyTests sc2.write_data( b * 4096 ) # Check it to make sure it's correct - rsp = timeout(15) { client.read_response } + rsp = Timeout.timeout(15) { client.read_response } assert_equal ::FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 0, rsp[:error] assert_equal req1[:handle], rsp[:handle] @@ -163,7 +163,7 @@ module ProxyTests sc2.write_reply( req2[:handle] ) # Check it to make sure it's correct - rsp = timeout(15) { client.read_response } + rsp = Timeout.timeout(15) { client.read_response } assert_equal ::FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 0, rsp[:error] assert_equal req1[:handle], rsp[:handle] @@ -178,7 +178,7 @@ module ProxyTests c2 = nil assert_raises(Timeout::Error) do - timeout(1) do + Timeout.timeout(1) do c2 = FlexNBD::FakeSource.new(@env.ip, @env.port2, "Couldn't connect to proxy (2)") c2.read_hello end From 3410ccd4c5b5191ac436f8219842c25fc3cd30e9 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 20:50:48 +0000 Subject: [PATCH 23/71] Fixed up commenting around our advertised flags. --- src/server/client.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/server/client.c b/src/server/client.c index 58ba199..5cc1c17 100644 --- a/src/server/client.c +++ b/src/server/client.c @@ -307,9 +307,11 @@ void client_write_init( struct client * client, uint64_t size ) memcpy( init.passwd, INIT_PASSWD, sizeof( init.passwd ) ); init.magic = INIT_MAGIC; init.size = size; - // TODO actually implement these flags! + /* As more features are implemented, this is the place to advertise + * them. + */ init.flags = FLAG_HAS_FLAGS | FLAG_SEND_FLUSH | FLAG_SEND_FUA; - // memset( init.reserved, 0, 124 ); + memset( init.reserved, 0, 124 ); nbd_h2r_init( &init, &init_raw ); From 1b7b688f7a0dae949ccb9091fd211823dd4843c6 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 21:27:12 +0000 Subject: [PATCH 24/71] Tidied up nbd init test --- tests/acceptance/flexnbd/fake_source.rb | 24 +++++++++++------------- tests/acceptance/proxy_tests.rb | 2 +- tests/acceptance/test_serve_mode.rb | 6 +++++- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/tests/acceptance/flexnbd/fake_source.rb b/tests/acceptance/flexnbd/fake_source.rb index dfbce69..127e73c 100644 --- a/tests/acceptance/flexnbd/fake_source.rb +++ b/tests/acceptance/flexnbd/fake_source.rb @@ -28,21 +28,19 @@ module FlexNBD @sock.close end + def read_hello + timing_out(::FlexNBD::MS_HELLO_TIME_SECS, + 'Timed out waiting for hello.') do + fail 'No hello.' unless (hello = @sock.read(152)) && + hello.length == 152 - def read_hello() - timing_out( ::FlexNBD::MS_HELLO_TIME_SECS, - "Timed out waiting for hello." ) do - fail "No hello." unless (hello = @sock.read( 152 )) && - hello.length==152 + passwd_s = hello[0..7] + magic = hello[8..15].unpack('Q>').first + size = hello[16..23].unpack('Q>').first + flags = hello[24..27].unpack('L>').first + reserved = hello[28..-1] - magic_s = hello[0..7] - ignore_s= hello[8..15] - size_s = hello[16..23] - - size_h, size_l = size_s.unpack("NN") - size = (size_h << 32) + size_l - - return { :magic => magic_s, :size => size } + return { passwd: passwd_s, magic: magic, size: size, flags: flags, reserved: reserved } end end diff --git a/tests/acceptance/proxy_tests.rb b/tests/acceptance/proxy_tests.rb index d08f8e7..fb4d38e 100644 --- a/tests/acceptance/proxy_tests.rb +++ b/tests/acceptance/proxy_tests.rb @@ -15,7 +15,7 @@ module ProxyTests begin result = client.read_hello - assert_equal "NBDMAGIC", result[:magic] + assert_equal "NBDMAGIC", result[:passwd] assert_equal override_size || @env.file1.size, result[:size] yield client diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index 6cf383b..dbacfdb 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -1,6 +1,7 @@ require 'test/unit' require 'environment' require 'flexnbd/fake_source' +require 'pp' class TestServeMode < Test::Unit::TestCase @@ -21,8 +22,11 @@ class TestServeMode < Test::Unit::TestCase client = FlexNBD::FakeSource.new(@env.ip, @env.port1, "Connecting to server failed") begin result = client.read_hello - assert_equal "NBDMAGIC", result[:magic] + assert_equal 'NBDMAGIC', result[:passwd] + assert_equal 0x00420281861253, result[:magic] assert_equal @env.file1.size, result[:size] + assert_equal 13, result[:flags] + assert_equal "\x0" * 124, result[:reserved] yield client ensure client.close rescue nil From 9c48da82cc8113e06b0d7bf650a14ecff601a729 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 21:34:14 +0000 Subject: [PATCH 25/71] Rubocop --- tests/acceptance/environment.rb | 99 +++--- .../fakes/dest/break_after_hello.rb | 19 +- .../fakes/dest/close_after_entrust_reply.rb | 19 +- .../fakes/dest/close_after_hello.rb | 6 +- .../fakes/dest/close_after_write.rb | 6 +- .../fakes/dest/close_after_writes.rb | 12 +- tests/acceptance/fakes/dest/error_on_write.rb | 9 +- .../fakes/dest/hang_after_connect.rb | 10 +- .../acceptance/fakes/dest/hang_after_write.rb | 20 +- .../fakes/dest/hello_wrong_magic.rb | 12 +- .../acceptance/fakes/dest/hello_wrong_size.rb | 12 +- tests/acceptance/fakes/dest/reject_acl.rb | 6 +- .../fakes/dest/sigterm_after_hello.rb | 4 +- .../fakes/dest/write_wrong_magic.rb | 8 +- .../fakes/source/close_after_connect.rb | 14 +- .../fakes/source/close_after_entrust.rb | 11 +- .../fakes/source/close_after_entrust_reply.rb | 12 +- .../fakes/source/close_after_hello.rb | 5 +- .../fakes/source/close_after_write.rb | 8 +- .../fakes/source/close_after_write_data.rb | 10 +- .../acceptance/fakes/source/close_mid_read.rb | 7 +- .../fakes/source/connect_during_hello.rb | 4 +- .../fakes/source/connect_from_banned_ip.rb | 7 +- .../fakes/source/hang_after_hello.rb | 12 +- .../fakes/source/sigterm_after_hello.rb | 4 +- .../fakes/source/successful_transfer.rb | 7 +- .../fakes/source/write_out_of_range.rb | 18 +- tests/acceptance/file_writer.rb | 87 +++-- tests/acceptance/flexnbd.rb | 326 ++++++++---------- tests/acceptance/flexnbd/constants.rb | 28 +- tests/acceptance/flexnbd/fake_dest.rb | 116 +++---- tests/acceptance/flexnbd/fake_source.rb | 129 +++---- tests/acceptance/proxy_tests.rb | 64 ++-- tests/acceptance/test_dest_error_handling.rb | 61 ++-- tests/acceptance/test_happy_path.rb | 100 +++--- tests/acceptance/test_prefetch_proxy_mode.rb | 5 +- tests/acceptance/test_proxy_mode.rb | 4 +- tests/acceptance/test_serve_mode.rb | 45 ++- .../acceptance/test_source_error_handling.rb | 77 ++--- .../acceptance/test_write_during_migration.rb | 121 +++---- 40 files changed, 666 insertions(+), 858 deletions(-) diff --git a/tests/acceptance/environment.rb b/tests/acceptance/environment.rb index 514f814..9697227 100644 --- a/tests/acceptance/environment.rb +++ b/tests/acceptance/environment.rb @@ -1,22 +1,20 @@ -# encoding: utf-8 - require 'flexnbd' require 'file_writer' class Environment - attr_reader( :blocksize, :filename1, :filename2, :ip, - :port1, :port2, :nbd1, :nbd2, :file1, :file2 ) + attr_reader(:blocksize, :filename1, :filename2, :ip, + :port1, :port2, :nbd1, :nbd2, :file1, :file2) def initialize @blocksize = 1024 - @filename1 = "/tmp/.flexnbd.test.#{$$}.#{Time.now.to_i}.1" - @filename2 = "/tmp/.flexnbd.test.#{$$}.#{Time.now.to_i}.2" - @ip = "127.0.0.1" - @available_ports = [*40000..41000] - listening_ports + @filename1 = "/tmp/.flexnbd.test.#{$PROCESS_ID}.#{Time.now.to_i}.1" + @filename2 = "/tmp/.flexnbd.test.#{$PROCESS_ID}.#{Time.now.to_i}.2" + @ip = '127.0.0.1' + @available_ports = [*40_000..41_000] - listening_ports @port1 = @available_ports.shift @port2 = @available_ports.shift - @nbd1 = FlexNBD::FlexNBD.new("../../build/flexnbd", @ip, @port1) - @nbd2 = FlexNBD::FlexNBD.new("../../build/flexnbd", @ip, @port2) + @nbd1 = FlexNBD::FlexNBD.new('../../build/flexnbd', @ip, @port1) + @nbd2 = FlexNBD::FlexNBD.new('../../build/flexnbd', @ip, @port2) @fake_pid = nil end @@ -26,14 +24,14 @@ class Environment @nbd2.prefetch_proxy = true end - def proxy1(port=@port2) + def proxy1(port = @port2) @nbd1.proxy(@ip, port) end - def proxy2(port=@port1) + + def proxy2(port = @port1) @nbd2.proxy(@ip, port) end - def serve1(*acl) @nbd1.serve(@filename1, *acl) end @@ -42,29 +40,26 @@ class Environment @nbd2.serve(@filename2, *acl) end - - def listen1( *acl ) - @nbd1.listen( @filename1, *(acl.empty? ? @acl1: acl) ) + def listen1(*acl) + @nbd1.listen(@filename1, *(acl.empty? ? @acl1 : acl)) end - def listen2( *acl ) - @nbd2.listen( @filename2, *acl ) + def listen2(*acl) + @nbd2.listen(@filename2, *acl) end - def break1 @nbd1.break end - def acl1( *acl ) - @nbd1.acl( *acl ) + def acl1(*acl) + @nbd1.acl(*acl) end - def acl2( *acl ) - @nbd2.acl( *acl ) + def acl2(*acl) + @nbd2.acl(*acl) end - def status1 @nbd1.status.first end @@ -73,23 +68,20 @@ class Environment @nbd2.status.first end - - def mirror12 - @nbd1.mirror( @nbd2.ip, @nbd2.port ) + @nbd1.mirror(@nbd2.ip, @nbd2.port) end def mirror12_unchecked - @nbd1.mirror_unchecked( @nbd2.ip, @nbd2.port, nil, nil, 10 ) + @nbd1.mirror_unchecked(@nbd2.ip, @nbd2.port, nil, nil, 10) end def mirror12_unlink - @nbd1.mirror_unlink( @nbd2.ip, @nbd2.port, 2 ) + @nbd1.mirror_unlink(@nbd2.ip, @nbd2.port, 2) end - - def write1( data ) - @nbd1.write( 0, data ) + def write1(data) + @nbd1.write(0, data) end def writefile1(data) @@ -100,63 +92,54 @@ class Environment @file2 = FileWriter.new(@filename2, @blocksize).write(data) end - - def truncate1( size ) + def truncate1(size) system "truncate -s #{size} #{@filename1}" end - def listening_ports - `netstat -ltn`. - split("\n"). - map { |x| x.split(/\s+/) }[2..-1]. - map { |l| l[3].split(":")[-1].to_i } + `netstat -ltn` + .split("\n") + .map { |x| x.split(/\s+/) }[2..-1] + .map { |l| l[3].split(':')[-1].to_i } end - def cleanup if @fake_pid begin - Process.waitpid2( @fake_pid ) + Process.waitpid2(@fake_pid) rescue Errno::ESRCH end end - @nbd1.can_die(0) @nbd1.kill @nbd2.kill [@filename1, @filename2].each do |f| - File.unlink(f) if File.exists?(f) + File.unlink(f) if File.exist?(f) end end - - def run_fake( name, addr, port, sock=nil ) - fakedir = File.join( File.dirname( __FILE__ ), "fakes" ) - fakeglob = File.join( fakedir, name ) + "*" - fake = Dir[fakeglob].sort.find { |fn| - File.executable?( fn ) - } + def run_fake(name, addr, port, sock = nil) + fakedir = File.join(File.dirname(__FILE__), 'fakes') + fakeglob = File.join(fakedir, name) + '*' + fake = Dir[fakeglob].sort.find do |fn| + File.executable?(fn) + end raise "no fake executable at #{fakeglob}" unless fake - raise "no addr" unless addr - raise "no port" unless port + raise 'no addr' unless addr + raise 'no port' unless port @fake_pid = fork do - exec [fake, addr, port, @nbd1.pid, sock].map{|x| x.to_s}.join(" ") + exec [fake, addr, port, @nbd1.pid, sock].map(&:to_s).join(' ') end sleep(0.5) end - def fake_reports_success - _,status = Process.waitpid2( @fake_pid ) + _, status = Process.waitpid2(@fake_pid) @fake_pid = nil status.success? end - - end # class Environment - diff --git a/tests/acceptance/fakes/dest/break_after_hello.rb b/tests/acceptance/fakes/dest/break_after_hello.rb index 8a27cb7..c7fb980 100755 --- a/tests/acceptance/fakes/dest/break_after_hello.rb +++ b/tests/acceptance/fakes/dest/break_after_hello.rb @@ -1,6 +1,4 @@ #!/usr/bin/env ruby -# encoding: utf-8 - # Open a server, accept a client, then cancel the migration by issuing # a break command. @@ -8,28 +6,27 @@ require 'flexnbd/fake_dest' include FlexNBD addr, port, src_pid, sock = *ARGV -server = FakeDest.new( addr, port ) +server = FakeDest.new(addr, port) client = server.accept -ctrl = UNIXSocket.open( sock ) +ctrl = UNIXSocket.open(sock) -Process.kill("STOP", src_pid.to_i) -ctrl.write( "break\n" ) +Process.kill('STOP', src_pid.to_i) +ctrl.write("break\n") ctrl.close_write client.write_hello -Process.kill("CONT", src_pid.to_i) +Process.kill('CONT', src_pid.to_i) -fail "Unexpected control response" unless +raise 'Unexpected control response' unless ctrl.read =~ /0: mirror stopped/ client2 = nil begin - client2 = server.accept( "Expected timeout" ) - fail "Unexpected reconnection" + client2 = server.accept('Expected timeout') + raise 'Unexpected reconnection' rescue Timeout::Error # expected end client.close exit(0) - diff --git a/tests/acceptance/fakes/dest/close_after_entrust_reply.rb b/tests/acceptance/fakes/dest/close_after_entrust_reply.rb index e4f0189..3038ee4 100755 --- a/tests/acceptance/fakes/dest/close_after_entrust_reply.rb +++ b/tests/acceptance/fakes/dest/close_after_entrust_reply.rb @@ -1,6 +1,4 @@ #!/usr/bin/env ruby -# encoding: utf-8 - # Receive a mirror, and disconnect after sending the entrust reply but # before it can send the disconnect signal. # @@ -11,26 +9,25 @@ require 'flexnbd/fake_dest' include FlexNBD addr, port, src_pid = *ARGV -server = FakeDest.new( addr, port ) +server = FakeDest.new(addr, port) client = server.accept client.write_hello -while (req = client.read_request; req[:type] == 1) - client.read_data( req[:len] ) - client.write_reply( req[:handle] ) +while req = client.read_request; req[:type] == 1 + client.read_data(req[:len]) + client.write_reply(req[:handle]) end system "kill -STOP #{src_pid}" -client.write_reply( req[:handle] ) +client.write_reply(req[:handle]) client.close system "kill -CONT #{src_pid}" -sleep( 0.25 ) -client2 = server.accept( "Timed out waiting for a reconnection" ) +sleep(0.25) +client2 = server.accept('Timed out waiting for a reconnection') client2.close server.close -$stderr.puts "done" +warn 'done' exit(0) - diff --git a/tests/acceptance/fakes/dest/close_after_hello.rb b/tests/acceptance/fakes/dest/close_after_hello.rb index 1c903dd..6fe7693 100755 --- a/tests/acceptance/fakes/dest/close_after_hello.rb +++ b/tests/acceptance/fakes/dest/close_after_hello.rb @@ -10,12 +10,12 @@ require 'flexnbd/fake_dest' include FlexNBD addr, port = *ARGV -server = FakeDest.new( addr, port ) -client = server.accept( "Timed out waiting for a connection" ) +server = FakeDest.new(addr, port) +client = server.accept('Timed out waiting for a connection') client.write_hello client.close -new_client = server.accept( "Timed out waiting for a reconnection" ) +new_client = server.accept('Timed out waiting for a reconnection') new_client.close server.close diff --git a/tests/acceptance/fakes/dest/close_after_write.rb b/tests/acceptance/fakes/dest/close_after_write.rb index 7db5917..9777d0f 100755 --- a/tests/acceptance/fakes/dest/close_after_write.rb +++ b/tests/acceptance/fakes/dest/close_after_write.rb @@ -11,13 +11,13 @@ require 'flexnbd/fake_dest' include FlexNBD addr, port = *ARGV -server = FakeDest.new( addr, port ) -client = server.accept( "Timed out waiting for a connection" ) +server = FakeDest.new(addr, port) +client = server.accept('Timed out waiting for a connection') client.write_hello client.read_request client.close -new_client = server.accept( "Timed out waiting for a reconnection" ) +new_client = server.accept('Timed out waiting for a reconnection') new_client.close server.close diff --git a/tests/acceptance/fakes/dest/close_after_writes.rb b/tests/acceptance/fakes/dest/close_after_writes.rb index cd5dd21..468d831 100755 --- a/tests/acceptance/fakes/dest/close_after_writes.rb +++ b/tests/acceptance/fakes/dest/close_after_writes.rb @@ -1,6 +1,4 @@ #!/usr/bin/env ruby -# encoding: utf-8 - # Open a server, accept a client, then we expect a single write # followed by an entrust. However, we disconnect after the write so # the entrust will fail. We don't expect a reconnection: the sender @@ -10,16 +8,16 @@ require 'flexnbd/fake_dest' include FlexNBD addr, port, src_pid = *ARGV -server = FakeDest.new( addr, port ) +server = FakeDest.new(addr, port) client = server.accept client.write_hello req = client.read_request -data = client.read_data( req[:len] ) +data = client.read_data(req[:len]) -Process.kill("STOP", src_pid.to_i) -client.write_reply( req[:handle], 0 ) +Process.kill('STOP', src_pid.to_i) +client.write_reply(req[:handle], 0) client.close -Process.kill("CONT", src_pid.to_i) +Process.kill('CONT', src_pid.to_i) exit(0) diff --git a/tests/acceptance/fakes/dest/error_on_write.rb b/tests/acceptance/fakes/dest/error_on_write.rb index 8bab036..1793947 100755 --- a/tests/acceptance/fakes/dest/error_on_write.rb +++ b/tests/acceptance/fakes/dest/error_on_write.rb @@ -1,19 +1,16 @@ #!/usr/bin/env ruby -# encoding: utf-8 - require 'flexnbd/fake_dest' include FlexNBD addr, port = *ARGV -server = FakeDest.new( addr, port ) +server = FakeDest.new(addr, port) client = server.accept client.write_hello handle = client.read_request[:handle] -client.write_error( handle ) +client.write_error(handle) - -client2 = server.accept( "Timed out waiting for a reconnection" ) +client2 = server.accept('Timed out waiting for a reconnection') client.close client2.close diff --git a/tests/acceptance/fakes/dest/hang_after_connect.rb b/tests/acceptance/fakes/dest/hang_after_connect.rb index cb5bcba..e2af392 100755 --- a/tests/acceptance/fakes/dest/hang_after_connect.rb +++ b/tests/acceptance/fakes/dest/hang_after_connect.rb @@ -14,8 +14,8 @@ require 'flexnbd/fake_dest' include FlexNBD addr, port = *ARGV -server = FakeDest.new( addr, port ) -client = server.accept( "Client didn't make a connection" ) +server = FakeDest.new(addr, port) +client = server.accept("Client didn't make a connection") # Sleep for one second past the timeout (a bit of slop in case ruby # doesn't launch things quickly) @@ -26,10 +26,10 @@ client.close # Invert the sense of the timeout exception, since we *don't* want a # connection attempt begin - server.accept( "Expected timeout" ) - fail "Unexpected reconnection" + server.accept('Expected timeout') + raise 'Unexpected reconnection' rescue Timeout::Error - # expected + # expected end server.close diff --git a/tests/acceptance/fakes/dest/hang_after_write.rb b/tests/acceptance/fakes/dest/hang_after_write.rb index affda53..8c07ed8 100755 --- a/tests/acceptance/fakes/dest/hang_after_write.rb +++ b/tests/acceptance/fakes/dest/hang_after_write.rb @@ -1,6 +1,4 @@ #!/usr/bin/env ruby -# encoding: utf-8 - # Open a socket, say hello, receive a write, then sleep for > # MS_REQUEST_LIMIT_SECS seconds. This should tell the source that the # write has gone MIA, and we expect a reconnect. @@ -9,24 +7,24 @@ require 'flexnbd/fake_dest' include FlexNBD addr, port = *ARGV -server = FakeDest.new( addr, port ) -client1 = server.accept( server ) +server = FakeDest.new(addr, port) +client1 = server.accept(server) client1.write_hello client1.read_request t = Thread.start do - client2 = server.accept( "Timed out waiting for a reconnection", - FlexNBD::MS_REQUEST_LIMIT_SECS + 2 ) + client2 = server.accept('Timed out waiting for a reconnection', + FlexNBD::MS_REQUEST_LIMIT_SECS + 2) client2.close end -sleep_time = if ENV.has_key?('FLEXNBD_MS_REQUEST_LIMIT_SECS') - ENV['FLEXNBD_MS_REQUEST_LIMIT_SECS'].to_f -else - FlexNBD::MS_REQUEST_LIMIT_SECS +sleep_time = if ENV.key?('FLEXNBD_MS_REQUEST_LIMIT_SECS') + ENV['FLEXNBD_MS_REQUEST_LIMIT_SECS'].to_f + else + FlexNBD::MS_REQUEST_LIMIT_SECS end -sleep( sleep_time + 2.0 ) +sleep(sleep_time + 2.0) client1.close t.join diff --git a/tests/acceptance/fakes/dest/hello_wrong_magic.rb b/tests/acceptance/fakes/dest/hello_wrong_magic.rb index ce2f98f..098ca3f 100755 --- a/tests/acceptance/fakes/dest/hello_wrong_magic.rb +++ b/tests/acceptance/fakes/dest/hello_wrong_magic.rb @@ -7,21 +7,21 @@ include FlexNBD Thread.abort_on_exception addr, port = *ARGV -server = FakeDest.new( addr, port ) +server = FakeDest.new(addr, port) client1 = server.accept # We don't expect a reconnection attempt. t = Thread.new do begin - client2 = server.accept( "Timed out waiting for a reconnection", - FlexNBD::MS_RETRY_DELAY_SECS + 1 ) - fail "Unexpected reconnection" + client2 = server.accept('Timed out waiting for a reconnection', + FlexNBD::MS_RETRY_DELAY_SECS + 1) + raise 'Unexpected reconnection' rescue Timeout::Error - #expected + # expected end end -client1.write_hello( :magic => :wrong ) +client1.write_hello(magic: :wrong) t.join diff --git a/tests/acceptance/fakes/dest/hello_wrong_size.rb b/tests/acceptance/fakes/dest/hello_wrong_size.rb index 3e38e04..5521b40 100755 --- a/tests/acceptance/fakes/dest/hello_wrong_size.rb +++ b/tests/acceptance/fakes/dest/hello_wrong_size.rb @@ -9,7 +9,7 @@ include FlexNBD Thread.abort_on_exception = true addr, port = *ARGV -server = FakeDest.new( addr, port ) +server = FakeDest.new(addr, port) client = server.accept t = Thread.new do @@ -18,21 +18,21 @@ t = Thread.new do # so it makes no sense to continue. This means we have to invert the # sense of the exception. begin - client2 = server.accept( "Timed out waiting for a reconnection", - FlexNBD::MS_RETRY_DELAY_SECS + 1 ) + client2 = server.accept('Timed out waiting for a reconnection', + FlexNBD::MS_RETRY_DELAY_SECS + 1) client2.close - fail "Unexpected reconnection." + raise 'Unexpected reconnection.' rescue Timeout::Error end end -client.write_hello( :size => :wrong ) +client.write_hello(size: :wrong) t.join # Now check that the source closed the first socket (yes, this was an # actual bug) -fail "Didn't close socket" unless client.disconnected? +raise "Didn't close socket" unless client.disconnected? exit 0 diff --git a/tests/acceptance/fakes/dest/reject_acl.rb b/tests/acceptance/fakes/dest/reject_acl.rb index b75c562..3b4848f 100755 --- a/tests/acceptance/fakes/dest/reject_acl.rb +++ b/tests/acceptance/fakes/dest/reject_acl.rb @@ -7,18 +7,16 @@ require 'flexnbd/fake_dest' include FlexNBD addr, port = *ARGV -server = FakeDest.new( addr, port ) +server = FakeDest.new(addr, port) server.accept.close - begin server.accept - fail "Unexpected reconnection" + raise 'Unexpected reconnection' rescue Timeout::Error # expected end server.close - exit(0) diff --git a/tests/acceptance/fakes/dest/sigterm_after_hello.rb b/tests/acceptance/fakes/dest/sigterm_after_hello.rb index b4773f9..9fdbae8 100755 --- a/tests/acceptance/fakes/dest/sigterm_after_hello.rb +++ b/tests/acceptance/fakes/dest/sigterm_after_hello.rb @@ -8,8 +8,8 @@ require 'flexnbd/fake_dest' include FlexNBD addr, port, pid = *ARGV -server = FakeDest.new( addr, port ) -client = server.accept( "Timed out waiting for a connection" ) +server = FakeDest.new(addr, port) +client = server.accept('Timed out waiting for a connection') client.write_hello Process.kill(15, pid.to_i) diff --git a/tests/acceptance/fakes/dest/write_wrong_magic.rb b/tests/acceptance/fakes/dest/write_wrong_magic.rb index 9a14ff7..3f84311 100755 --- a/tests/acceptance/fakes/dest/write_wrong_magic.rb +++ b/tests/acceptance/fakes/dest/write_wrong_magic.rb @@ -1,6 +1,4 @@ #!/usr/bin/env ruby -# encoding: utf-8 - # Accept a connection, write hello, wait for a write request, read the # data, then write back a reply with a bad magic field. We then # expect a reconnect. @@ -9,13 +7,13 @@ require 'flexnbd/fake_dest' include FlexNBD addr, port = *ARGV -server = FakeDest.new( addr, port ) +server = FakeDest.new(addr, port) client = server.accept client.write_hello req = client.read_request -client.read_data( req[:len] ) -client.write_reply( req[:handle], 0, :magic => :wrong ) +client.read_data(req[:len]) +client.write_reply(req[:handle], 0, magic: :wrong) client2 = server.accept client.close diff --git a/tests/acceptance/fakes/source/close_after_connect.rb b/tests/acceptance/fakes/source/close_after_connect.rb index 5b05db8..c0e6a33 100755 --- a/tests/acceptance/fakes/source/close_after_connect.rb +++ b/tests/acceptance/fakes/source/close_after_connect.rb @@ -11,13 +11,13 @@ include FlexNBD addr, port = *ARGV -FakeSource.new( addr, port, "Failed to connect" ).close - # Sleep to be sure we don't try to connect too soon. That wouldn't - # be a problem for the destination, but it would prevent us from - # determining success or failure here in the case where we try to - # reconnect before the destination has tidied up after the first - # thread went away. +FakeSource.new(addr, port, 'Failed to connect').close +# Sleep to be sure we don't try to connect too soon. That wouldn't +# be a problem for the destination, but it would prevent us from +# determining success or failure here in the case where we try to +# reconnect before the destination has tidied up after the first +# thread went away. sleep(0.5) -FakeSource.new( addr, port, "Failed to reconnect" ).close +FakeSource.new(addr, port, 'Failed to reconnect').close exit 0 diff --git a/tests/acceptance/fakes/source/close_after_entrust.rb b/tests/acceptance/fakes/source/close_after_entrust.rb index 3c351e6..26f78c8 100755 --- a/tests/acceptance/fakes/source/close_after_entrust.rb +++ b/tests/acceptance/fakes/source/close_after_entrust.rb @@ -11,10 +11,10 @@ include FlexNBD addr, port, srv_pid = *ARGV -client = FakeSource.new( addr, port, "Timed out connecting" ) +client = FakeSource.new(addr, port, 'Timed out connecting') client.read_hello -client.write_write_request( 0, 8 ) -client.write_data( "12345678" ) +client.write_write_request(0, 8) +client.write_data('12345678') # Use system "kill" rather than Process.kill because Process.kill # doesn't seem to work @@ -25,12 +25,11 @@ client.close system "kill -CONT #{srv_pid}" - sleep(0.25) begin - client2 = FakeSource.new( addr, port, "Expected timeout" ) - fail "Unexpected reconnection" + client2 = FakeSource.new(addr, port, 'Expected timeout') + raise 'Unexpected reconnection' rescue Timeout::Error # expected end diff --git a/tests/acceptance/fakes/source/close_after_entrust_reply.rb b/tests/acceptance/fakes/source/close_after_entrust_reply.rb index c5858c9..6c50256 100755 --- a/tests/acceptance/fakes/source/close_after_entrust_reply.rb +++ b/tests/acceptance/fakes/source/close_after_entrust_reply.rb @@ -10,10 +10,10 @@ include FlexNBD addr, port, srv_pid = *ARGV -client = FakeSource.new( addr, port, "Timed out connecting" ) +client = FakeSource.new(addr, port, 'Timed out connecting') client.read_hello -client.write_write_request( 0, 8 ) -client.write_data( "12345678" ) +client.write_write_request(0, 8) +client.write_data('12345678') client.write_entrust_request client.read_response @@ -21,13 +21,11 @@ client.close sleep(0.25) - begin - client2 = FakeSource.new( addr, port, "Expected timeout" ) - fail "Unexpected reconnection" + client2 = FakeSource.new(addr, port, 'Expected timeout') + raise 'Unexpected reconnection' rescue Timeout::Error # expected end exit(0) - diff --git a/tests/acceptance/fakes/source/close_after_hello.rb b/tests/acceptance/fakes/source/close_after_hello.rb index 952fdf4..3283d53 100755 --- a/tests/acceptance/fakes/source/close_after_hello.rb +++ b/tests/acceptance/fakes/source/close_after_hello.rb @@ -12,13 +12,12 @@ include FlexNBD addr, port = *ARGV - -client = FakeSource.new( addr, port, "Timed out connecting." ) +client = FakeSource.new(addr, port, 'Timed out connecting.') client.read_hello client.close sleep(0.2) -FakeSource.new( addr, port, "Timed out reconnecting." ) +FakeSource.new(addr, port, 'Timed out reconnecting.') exit(0) diff --git a/tests/acceptance/fakes/source/close_after_write.rb b/tests/acceptance/fakes/source/close_after_write.rb index 250a462..304548e 100755 --- a/tests/acceptance/fakes/source/close_after_write.rb +++ b/tests/acceptance/fakes/source/close_after_write.rb @@ -1,6 +1,4 @@ #!/usr/bin/env ruby -# encoding: utf-8 - # We connect, pause the server, issue a write request, disconnect, # then cont the server. This ensures that our disconnect happens # while the server is trying to read the write data. @@ -10,11 +8,11 @@ include FlexNBD addr, port, srv_pid = *ARGV -client = FakeSource.new( addr, port, "Timed out connecting" ) +client = FakeSource.new(addr, port, 'Timed out connecting') client.read_hello system "kill -STOP #{srv_pid}" -client.write_write_request( 0, 8 ) +client.write_write_request(0, 8) client.close system "kill -CONT #{srv_pid}" @@ -24,7 +22,7 @@ system "kill -CONT #{srv_pid}" sleep(0.25) # ...and can we reconnect? -client2 = FakeSource.new( addr, port, "Timed out connecting" ) +client2 = FakeSource.new(addr, port, 'Timed out connecting') client2.close exit(0) diff --git a/tests/acceptance/fakes/source/close_after_write_data.rb b/tests/acceptance/fakes/source/close_after_write_data.rb index 8c23555..8ca6b00 100755 --- a/tests/acceptance/fakes/source/close_after_write_data.rb +++ b/tests/acceptance/fakes/source/close_after_write_data.rb @@ -1,6 +1,4 @@ #!/usr/bin/env ruby -# encoding: utf-8 - # We connect, pause the server, issue a write request, send data, # disconnect, then cont the server. This ensures that our disconnect # happens before the server can try to write the reply. @@ -10,13 +8,13 @@ include FlexNBD addr, port, srv_pid = *ARGV -client = FakeSource.new( addr, port, "Timed out connecting" ) +client = FakeSource.new(addr, port, 'Timed out connecting') client.read_hello system "kill -STOP #{srv_pid}" -client.write_write_request( 0, 8 ) -client.write_data( "12345678" ) +client.write_write_request(0, 8) +client.write_data('12345678') client.close system "kill -CONT #{srv_pid}" @@ -27,7 +25,7 @@ system "kill -CONT #{srv_pid}" sleep(0.25) # ...and can we reconnect? -client2 = FakeSource.new( addr, port, "Timed out reconnecting" ) +client2 = FakeSource.new(addr, port, 'Timed out reconnecting') client2.close exit(0) diff --git a/tests/acceptance/fakes/source/close_mid_read.rb b/tests/acceptance/fakes/source/close_mid_read.rb index 3b5fa20..b9149f5 100755 --- a/tests/acceptance/fakes/source/close_mid_read.rb +++ b/tests/acceptance/fakes/source/close_mid_read.rb @@ -8,10 +8,9 @@ include FlexNBD addr, port, srv_pid, newaddr, newport = *ARGV -client = FakeSource.new( addr, port, "Timed out connecting" ) -client.write_read_request( 0, 8 ) -client.read_raw( 4 ) +client = FakeSource.new(addr, port, 'Timed out connecting') +client.write_read_request(0, 8) +client.read_raw(4) client.close - exit(0) diff --git a/tests/acceptance/fakes/source/connect_during_hello.rb b/tests/acceptance/fakes/source/connect_during_hello.rb index fac5ab7..3c5296b 100755 --- a/tests/acceptance/fakes/source/connect_during_hello.rb +++ b/tests/acceptance/fakes/source/connect_during_hello.rb @@ -10,9 +10,9 @@ include FlexNBD addr, port = *ARGV -client1 = FakeSource.new( addr, port, "Timed out connecting" ) +client1 = FakeSource.new(addr, port, 'Timed out connecting') sleep(0.25) -client2 = FakeSource.new( addr, port, "Timed out connecting a second time" ) +client2 = FakeSource.new(addr, port, 'Timed out connecting a second time') # This is the expected source crashing after connect client1.close diff --git a/tests/acceptance/fakes/source/connect_from_banned_ip.rb b/tests/acceptance/fakes/source/connect_from_banned_ip.rb index aa16fa0..04ba1c8 100755 --- a/tests/acceptance/fakes/source/connect_from_banned_ip.rb +++ b/tests/acceptance/fakes/source/connect_from_banned_ip.rb @@ -1,6 +1,4 @@ #!/usr/bin/env ruby -# encoding: utf-8 - # We connect from a local address which should be blocked, sleep for a # bit, then try to read from the socket. We should get an instant EOF # as we've been cut off by the destination. @@ -11,10 +9,9 @@ include FlexNBD addr, port = *ARGV -client = FakeSource.new( addr, port, "Timed out connecting", "127.0.0.6" ) -sleep( 0.25 ) +client = FakeSource.new(addr, port, 'Timed out connecting', '127.0.0.6') +sleep(0.25) rsp = client.disconnected? ? 0 : 1 client.close exit(rsp) - diff --git a/tests/acceptance/fakes/source/hang_after_hello.rb b/tests/acceptance/fakes/source/hang_after_hello.rb index 6deb6d7..1ecfc17 100755 --- a/tests/acceptance/fakes/source/hang_after_hello.rb +++ b/tests/acceptance/fakes/source/hang_after_hello.rb @@ -7,10 +7,10 @@ # listening for an incoming migration. addr, port = *ARGV -require "flexnbd/fake_source" +require 'flexnbd/fake_source' include FlexNBD -client = FakeSource.new( addr, port, "Timed out connecting" ) +client = FakeSource.new(addr, port, 'Timed out connecting') client.read_hello # Now we do two things: @@ -24,16 +24,16 @@ client.read_hello kidpid = fork do client.close new_client = nil - sleep( FlexNBD::CLIENT_MAX_WAIT_SECS + 1 ) - new_client = FakeSource.new( addr, port, "Timed out reconnecting." ) + sleep(FlexNBD::CLIENT_MAX_WAIT_SECS + 1) + new_client = FakeSource.new(addr, port, 'Timed out reconnecting.') new_client.read_hello exit 0 end # Sleep for longer than the child, to give the flexnbd process a bit # of slop -sleep( FlexNBD::CLIENT_MAX_WAIT_SECS + 3 ) +sleep(FlexNBD::CLIENT_MAX_WAIT_SECS + 3) client.close -_,status = Process.waitpid2( kidpid ) +_, status = Process.waitpid2(kidpid) exit status.exitstatus diff --git a/tests/acceptance/fakes/source/sigterm_after_hello.rb b/tests/acceptance/fakes/source/sigterm_after_hello.rb index 6c7aaf9..e90eb3e 100755 --- a/tests/acceptance/fakes/source/sigterm_after_hello.rb +++ b/tests/acceptance/fakes/source/sigterm_after_hello.rb @@ -9,10 +9,10 @@ include FlexNBD addr, port, pid = *ARGV -client = FakeSource.new( addr, port, "Timed out connecting." ) +client = FakeSource.new(addr, port, 'Timed out connecting.') client.read_hello -Process.kill( "TERM", pid.to_i ) +Process.kill('TERM', pid.to_i) sleep(0.2) client.close diff --git a/tests/acceptance/fakes/source/successful_transfer.rb b/tests/acceptance/fakes/source/successful_transfer.rb index 4b06155..5078dc8 100755 --- a/tests/acceptance/fakes/source/successful_transfer.rb +++ b/tests/acceptance/fakes/source/successful_transfer.rb @@ -9,10 +9,9 @@ include FlexNBD addr, port, srv_pid, newaddr, newport = *ARGV -client = FakeSource.new( addr, port, "Timed out connecting" ) -client.send_mirror() +client = FakeSource.new(addr, port, 'Timed out connecting') +client.send_mirror sleep(1) - -exit( 0 ) +exit(0) diff --git a/tests/acceptance/fakes/source/write_out_of_range.rb b/tests/acceptance/fakes/source/write_out_of_range.rb index 2954fad..fade302 100755 --- a/tests/acceptance/fakes/source/write_out_of_range.rb +++ b/tests/acceptance/fakes/source/write_out_of_range.rb @@ -1,6 +1,4 @@ #!/usr/bin/env ruby -# encoding: utf-8 - # Connect, read the hello then make a write request with an impossible # (from,len) pair. We expect an error response, and not to be # disconnected. @@ -13,20 +11,20 @@ include FlexNBD addr, port = *ARGV -client = FakeSource.new( addr, port, "Timed out connecting" ) +client = FakeSource.new(addr, port, 'Timed out connecting') hello = client.read_hello -client.write_write_request( hello[:size]+1, 32, "myhandle" ) -client.write_data("1"*32) +client.write_write_request(hello[:size] + 1, 32, 'myhandle') +client.write_data('1' * 32) response = client.read_response -fail "Not an error" if response[:error] == 0 -fail "Wrong handle" unless "myhandle" == response[:handle] +raise 'Not an error' if response[:error] == 0 +raise 'Wrong handle' unless response[:handle] == 'myhandle' -client.write_write_request( 0, 32 ) -client.write_data( "2"*32 ) +client.write_write_request(0, 32) +client.write_data('2' * 32) success_response = client.read_response -fail "Second write failed" unless success_response[:error] == 0 +raise 'Second write failed' unless success_response[:error] == 0 client.close exit(0) diff --git a/tests/acceptance/file_writer.rb b/tests/acceptance/file_writer.rb index 92ad220..624c6c6 100644 --- a/tests/acceptance/file_writer.rb +++ b/tests/acceptance/file_writer.rb @@ -3,13 +3,13 @@ # class FileWriter def initialize(filename, blocksize) - @fh = File.open(filename, "w+") + @fh = File.open(filename, 'w+') @blocksize = blocksize - @pattern = "" + @pattern = '' end def size - @blocksize * @pattern.split("").size + @blocksize * @pattern.split('').size end # We write in fixed block sizes, given by "blocksize" @@ -20,8 +20,8 @@ class FileWriter def write(data) @pattern += data - data.split("").each do |code| - if code == "_" + data.split('').each do |code| + if code == '_' @fh.seek(@blocksize, IO::SEEK_CUR) else @fh.write(data(code)) @@ -31,15 +31,14 @@ class FileWriter self end - # Returns what the data ought to be at the given offset and length # - def read_original( off, len ) - patterns = @pattern.split( "" ) - patterns.zip( (0...patterns.length).to_a ). - map { |blk, blk_off| + def read_original(off, len) + patterns = @pattern.split('') + patterns.zip((0...patterns.length).to_a) + .map do |blk, blk_off| data(blk, blk_off) - }.join[off...(off+len)] + end.join[off...(off + len)] end # Read what's actually in the file @@ -60,68 +59,66 @@ class FileWriter protected - def data(code, at=@fh.tell) + def data(code, at = @fh.tell) case code - when "0", "_" - "\0" * @blocksize - when "X" - "X" * @blocksize - when "f" - r = "" - (@blocksize/4).times do - r += [at].pack("I") - at += 4 - end - r - else - raise "Unknown character '#{block}'" + when '0', '_' + "\0" * @blocksize + when 'X' + 'X' * @blocksize + when 'f' + r = '' + (@blocksize / 4).times do + r += [at].pack('I') + at += 4 + end + r + else + raise "Unknown character '#{block}'" end end - end -if __FILE__==$0 +if $PROGRAM_NAME == __FILE__ require 'tempfile' require 'test/unit' class FileWriterTest < Test::Unit::TestCase def test_read_original_zeros - Tempfile.open("test_read_original_zeros") do |tempfile| + Tempfile.open('test_read_original_zeros') do |tempfile| tempfile.close - file = FileWriter.new( tempfile.path, 4096 ) - file.write( "0" ) - assert_equal file.read( 0, 4096 ), file.read_original( 0, 4096 ) - assert( file.untouched?(0,4096) , "Untouched file was touched." ) + file = FileWriter.new(tempfile.path, 4096) + file.write('0') + assert_equal file.read(0, 4096), file.read_original(0, 4096) + assert(file.untouched?(0, 4096), 'Untouched file was touched.') end end def test_read_original_offsets - Tempfile.open("test_read_original_offsets") do |tempfile| + Tempfile.open('test_read_original_offsets') do |tempfile| tempfile.close - file = FileWriter.new( tempfile.path, 4096 ) - file.write( "f" ) - assert_equal file.read( 0, 4096 ), file.read_original( 0, 4096 ) - assert( file.untouched?(0,4096) , "Untouched file was touched." ) + file = FileWriter.new(tempfile.path, 4096) + file.write('f') + assert_equal file.read(0, 4096), file.read_original(0, 4096) + assert(file.untouched?(0, 4096), 'Untouched file was touched.') end end def test_file_size - Tempfile.open("test_file_size") do |tempfile| + Tempfile.open('test_file_size') do |tempfile| tempfile.close - file = FileWriter.new( tempfile.path, 4096 ) - file.write( "f" ) - assert_equal 4096, File.stat( tempfile.path ).size + file = FileWriter.new(tempfile.path, 4096) + file.write('f') + assert_equal 4096, File.stat(tempfile.path).size end end def test_read_original_size - Tempfile.open("test_read_original_offsets") do |tempfile| + Tempfile.open('test_read_original_offsets') do |tempfile| tempfile.close - file = FileWriter.new( tempfile.path, 4) - file.write( "f"*4 ) + file = FileWriter.new(tempfile.path, 4) + file.write('f' * 4) assert_equal 4, file.read_original(0, 4).length end end end end - diff --git a/tests/acceptance/flexnbd.rb b/tests/acceptance/flexnbd.rb index 417ed97..236fd58 100644 --- a/tests/acceptance/flexnbd.rb +++ b/tests/acceptance/flexnbd.rb @@ -7,25 +7,22 @@ require 'rexml/streamlistener' Thread.abort_on_exception = true - class Executor attr_reader :pid - def run( cmd ) - @pid = fork do exec cmd end + def run(cmd) + @pid = fork { exec cmd } end end # class Executor - class ValgrindExecutor attr_reader :pid - def run( cmd ) - @pid = fork do exec "valgrind --track-origins=yes --suppressions=custom.supp #{cmd}" end + def run(cmd) + @pid = fork { exec "valgrind --track-origins=yes --suppressions=custom.supp #{cmd}" } end end # class ValgrindExecutor - class ValgrindKillingExecutor attr_reader :pid @@ -33,10 +30,10 @@ class ValgrindKillingExecutor attr_accessor :what, :kind, :pid attr_reader :backtrace def initialize - @backtrace=[] - @what = "" - @kind = "" - @pid = "" + @backtrace = [] + @what = '' + @kind = '' + @pid = '' end def add_frame @@ -56,115 +53,104 @@ class ValgrindKillingExecutor end def to_s - ([@what + " (#{@kind}) in #{@pid}"] + @backtrace.map{|h| "#{h[:file]}:#{h[:line]} #{h[:fn]}" }).join("\n") + ([@what + " (#{@kind}) in #{@pid}"] + @backtrace.map { |h| "#{h[:file]}:#{h[:line]} #{h[:fn]}" }).join("\n") end - end # class Error - class ErrorListener include REXML::StreamListener - def initialize( killer ) + def initialize(killer) @killer = killer @error = Error.new @found = false end - def text( text ) + def text(text) @text = text end - def tag_start(tag, attrs) + def tag_start(tag, _attrs) case tag.to_s - when "error" + when 'error' @found = true - when "frame" + when 'frame' @error.add_frame end end def tag_end(tag) case tag.to_s - when "what" + when 'what' @error.what = @text if @found - @text = "" - when "kind" + @text = '' + when 'kind' @error.kind = @text if @found - when "file" - @error.add_file( @text ) if @found - when "fn" - @error.add_fn( @text ) if @found - when "line" - @error.add_line( @text ) if @found - when "error", "stack" - if @found - @killer.call( @error ) - end - when "pid" - @error.pid=@text + when 'file' + @error.add_file(@text) if @found + when 'fn' + @error.add_fn(@text) if @found + when 'line' + @error.add_line(@text) if @found + when 'error', 'stack' + @killer.call(@error) if @found + when 'pid' + @error.pid = @text end end end # class ErrorListener - class DebugErrorListener < ErrorListener - def text( txt ) + def text(txt) print txt - super( txt ) + super(txt) end - def tag_start( tag, attrs ) + def tag_start(tag, attrs) print "<#{tag}>" - super( tag, attrs ) + super(tag, attrs) end - def tag_end( tag ) + def tag_end(tag) print "" - super( tag ) + super(tag) end end - def initialize @pid = nil end - def run( cmd ) + def run(cmd) @io_r, io_w = IO.pipe - @pid = fork do exec( "valgrind --suppressions=custom.supp --xml=yes --xml-fd=#{io_w.fileno} " + cmd ) end - launch_watch_thread( @pid, @io_r ) + @pid = fork { exec("valgrind --suppressions=custom.supp --xml=yes --xml-fd=#{io_w.fileno} " + cmd) } + launch_watch_thread(@pid, @io_r) @pid end - - def call( err ) - $stderr.puts "*"*72 - $stderr.puts "* Valgrind error spotted:" - $stderr.puts err.to_s.split("\n").map{|s| " #{s}"} - $stderr.puts "*"*72 - Process.kill( "KILL", @pid ) + def call(err) + warn '*' * 72 + warn '* Valgrind error spotted:' + warn err.to_s.split("\n").map { |s| " #{s}" } + warn '*' * 72 + Process.kill('KILL', @pid) exit(1) end - private def pick_listener ENV['DEBUG'] ? DebugErrorListener : ErrorListener end - def launch_watch_thread(pid, io_r) + def launch_watch_thread(_pid, io_r) Thread.start do - io_source = REXML::IOSource.new( io_r ) - listener = pick_listener.new( self ) - REXML::Document.parse_stream( io_source, listener ) + io_source = REXML::IOSource.new(io_r) + listener = pick_listener.new(self) + REXML::Document.parse_stream(io_source, listener) end end - - end # class ValgrindExecutor - module FlexNBD # Noddy test class to exercise FlexNBD from the outside for testing. # @@ -173,7 +159,7 @@ module FlexNBD class << self def counter - Dir['tmp/*'].select{|f| File.file?(f)}.length + 1 + Dir['tmp/*'].select { |f| File.file?(f) }.length + 1 end end @@ -189,19 +175,18 @@ module FlexNBD end end - def build_debug_opt if @do_debug - "--verbose" + '--verbose' else - "--quiet" + '--quiet' end end attr_accessor :prefetch_proxy - def initialize( bin, ip, port ) - @bin = bin + def initialize(bin, ip, port) + @bin = bin @do_debug = ENV['DEBUG'] @debug = build_debug_opt raise "#{bin} not executable" unless File.executable?(bin) @@ -213,17 +198,15 @@ module FlexNBD @prefetch_proxy = false end - def debug? !!@do_debug end - def debug( msg ) - $stderr.puts msg if debug? + def debug(msg) + warn msg if debug? end - - def serve_cmd( file, acl ) + def serve_cmd(file, acl) "#{bin} serve "\ "--addr #{ip} "\ "--port #{port} "\ @@ -233,8 +216,7 @@ module FlexNBD "#{acl.join(' ')}" end - - def listen_cmd( file, acl ) + def listen_cmd(file, acl) "#{bin} listen "\ "--addr #{ip} "\ "--port #{port} "\ @@ -244,18 +226,17 @@ module FlexNBD "#{acl.join(' ')}" end - def proxy_cmd( connect_ip, connect_port ) + def proxy_cmd(connect_ip, connect_port) "#{bin}-proxy "\ "--addr #{ip} "\ "--port #{port} "\ "--conn-addr #{connect_ip} "\ "--conn-port #{connect_port} "\ - "#{prefetch_proxy ? "--cache " : ""}"\ + "#{prefetch_proxy ? '--cache ' : ''}"\ "#{@debug}" end - - def read_cmd( offset, length ) + def read_cmd(offset, length) "#{bin} read "\ "--addr #{ip} "\ "--port #{port} "\ @@ -264,8 +245,7 @@ module FlexNBD "--size #{length}" end - - def write_cmd( offset, data ) + def write_cmd(offset, data) "#{bin} write "\ "--addr #{ip} "\ "--port #{port} "\ @@ -274,30 +254,29 @@ module FlexNBD "--size #{data.length}" end - - def base_mirror_opts( dest_ip, dest_port ) + def base_mirror_opts(dest_ip, dest_port) "--addr #{dest_ip} "\ "--port #{dest_port} "\ "--sock #{ctrl} "\ end - def unlink_mirror_opts( dest_ip, dest_port ) - "#{base_mirror_opts( dest_ip, dest_port )} "\ - "--unlink " + def unlink_mirror_opts(dest_ip, dest_port) + "#{base_mirror_opts(dest_ip, dest_port)} "\ + '--unlink ' end - def base_mirror_cmd( opts ) + def base_mirror_cmd(opts) "#{@bin} mirror "\ "#{opts} "\ "#{@debug}" end def mirror_cmd(dest_ip, dest_port) - base_mirror_cmd( base_mirror_opts( dest_ip, dest_port ) ) + base_mirror_cmd(base_mirror_opts(dest_ip, dest_port)) end - def mirror_unlink_cmd( dest_ip, dest_port ) - base_mirror_cmd( unlink_mirror_opts( dest_ip, dest_port ) ) + def mirror_unlink_cmd(dest_ip, dest_port) + base_mirror_cmd(unlink_mirror_opts(dest_ip, dest_port)) end def break_cmd @@ -312,58 +291,64 @@ module FlexNBD "#{@debug}" end - def acl_cmd( *acl ) + def acl_cmd(*acl) "#{@bin} acl " \ "--sock #{ctrl} "\ "#{@debug} "\ - "#{acl.join " "}" + "#{acl.join ' '}" end - def run_serve_cmd(cmd) - File.unlink(ctrl) if File.exists?(ctrl) - debug( cmd ) + File.unlink(ctrl) if File.exist?(ctrl) + debug(cmd) - @pid = @executor.run( cmd ) + @pid = @executor.run(cmd) - while !File.socket?(ctrl) + until File.socket?(ctrl) pid, status = Process.wait2(@pid, Process::WNOHANG) raise "server did not start (#{cmd})" if pid sleep 0.1 end - - start_wait_thread( @pid ) + start_wait_thread(@pid) at_exit { kill } end private :run_serve_cmd - - def serve( file, *acl) - cmd = serve_cmd( file, acl ) - run_serve_cmd( cmd ) - sleep( 0.2 ) until File.exists?( ctrl ) + def serve(file, *acl) + cmd = serve_cmd(file, acl) + run_serve_cmd(cmd) + sleep(0.2) until File.exist?(ctrl) end - def listen(file, *acl) - run_serve_cmd( listen_cmd( file, acl ) ) + run_serve_cmd(listen_cmd(file, acl)) end def tcp_server_open? # raises if the other side doesn't accept() - sock = TCPSocket.new(ip, port) rescue nil + sock = begin + TCPSocket.new(ip, port) + rescue StandardError + nil + end success = !!sock - ( sock.close rescue nil) if sock + if sock + (begin + sock.close + rescue StandardError + nil + end) + end success end - def proxy( connect_ip, connect_port ) - cmd = proxy_cmd( connect_ip, connect_port ) - debug( cmd ) + def proxy(connect_ip, connect_port) + cmd = proxy_cmd(connect_ip, connect_port) + debug(cmd) - @pid = @executor.run( cmd ) + @pid = @executor.run(cmd) until tcp_server_open? pid, status = Process.wait2(@pid, Process::WNOHANG) @@ -371,31 +356,29 @@ module FlexNBD sleep 0.1 end - start_wait_thread( @pid ) + start_wait_thread(@pid) at_exit { kill } end - - def start_wait_thread( pid ) + def start_wait_thread(pid) @wait_thread = Thread.start do - _, status = Process.waitpid2( pid ) + _, status = Process.waitpid2(pid) if @kill if status.signaled? - fail "flexnbd quit with a bad signal: #{status.inspect}" unless + raise "flexnbd quit with a bad signal: #{status.inspect}" unless @kill.include? status.termsig else - fail "flexnbd quit with a bad status: #{status.inspect}" unless + raise "flexnbd quit with a bad status: #{status.inspect}" unless @kill.include? status.exitstatus end else - $stderr.puts "flexnbd #{self.pid} quit" - fail "flexnbd #{self.pid} quit early with status #{status.to_i}" + warn "flexnbd #{self.pid} quit" + raise "flexnbd #{self.pid} quit early with status #{status.to_i}" end end end - def can_die(*status) status = [0] if status.empty? @kill += status @@ -407,7 +390,7 @@ module FlexNBD can_die(1) if @pid begin - Process.kill("INT", @pid) + Process.kill('INT', @pid) rescue Errno::ESRCH => e # already dead. Presumably this means it went away after a # can_die() call. @@ -417,63 +400,60 @@ module FlexNBD end def read(offset, length) - cmd = read_cmd( offset, length ) - debug( cmd ) + cmd = read_cmd(offset, length) + debug(cmd) IO.popen(cmd) do |fh| return fh.read end - raise IOError.new "NBD read failed" unless $?.success? + raise IOError, 'NBD read failed' unless $CHILD_STATUS.success? out end def write(offset, data) - cmd = write_cmd( offset, data ) - debug( cmd ) + cmd = write_cmd(offset, data) + debug(cmd) - IO.popen(cmd, "w") do |fh| + IO.popen(cmd, 'w') do |fh| fh.write(data) end - raise IOError.new "NBD write failed" unless $?.success? + raise IOError, 'NBD write failed' unless $CHILD_STATUS.success? nil end - def join @wait_thread.join end + def mirror_unchecked(dest_ip, dest_port, _bandwidth = nil, _action = nil, timeout = nil) + cmd = mirror_cmd(dest_ip, dest_port) + debug(cmd) - def mirror_unchecked( dest_ip, dest_port, bandwidth=nil, action=nil, timeout=nil ) - cmd = mirror_cmd( dest_ip, dest_port) - debug( cmd ) - - maybe_timeout( cmd, timeout ) + maybe_timeout(cmd, timeout) end + def mirror_unlink(dest_ip, dest_port, timeout = nil) + cmd = mirror_unlink_cmd(dest_ip, dest_port) + debug(cmd) - def mirror_unlink( dest_ip, dest_port, timeout=nil ) - cmd = mirror_unlink_cmd( dest_ip, dest_port ) - debug( cmd ) - - maybe_timeout( cmd, timeout ) + maybe_timeout(cmd, timeout) end - - def maybe_timeout(cmd, timeout=nil ) - stdout, stderr = "","" + def maybe_timeout(cmd, timeout = nil) + stdout = '' + stderr = '' stat = nil - run = Proc.new do + run = proc do # Ruby 1.9 changed the popen3 api. instead of 3 args, the block # gets 4. Not only that, but it no longer sets $?, so we have to # go elsewhere for the process' exit status. - Open3.popen3( cmd ) do |io_in, io_out, io_err, maybe_thr| + Open3.popen3(cmd) do |io_in, io_out, io_err, maybe_thr| io_in.close stdout.replace io_out.read stderr.replace io_err.read stat = maybe_thr.value if maybe_thr end - stat ||= $? + stat ||= $CHILD_STATUS end if timeout @@ -485,85 +465,73 @@ module FlexNBD [stdout, stderr, stat] end - - def mirror(dest_ip, dest_port, bandwidth=nil, action=nil) - stdout, stderr, status = mirror_unchecked( dest_ip, dest_port, bandwidth, action ) - raise IOError.new( "Migrate command failed\n" + stderr) unless status.success? + def mirror(dest_ip, dest_port, bandwidth = nil, action = nil) + stdout, stderr, status = mirror_unchecked(dest_ip, dest_port, bandwidth, action) + raise IOError, "Migrate command failed\n" + stderr unless status.success? stdout end - - - def break(timeout=nil) + def break(timeout = nil) cmd = break_cmd - debug( cmd ) + debug(cmd) - maybe_timeout( cmd, timeout ) + maybe_timeout(cmd, timeout) end - def acl(*acl) - cmd = acl_cmd( *acl ) - debug( cmd ) + cmd = acl_cmd(*acl) + debug(cmd) - maybe_timeout( cmd, 2 ) + maybe_timeout(cmd, 2) end + def status(timeout = nil) + cmd = status_cmd + debug(cmd) - def status( timeout = nil ) - cmd = status_cmd() - debug( cmd ) - - o,e = maybe_timeout( cmd, timeout ) + o, e = maybe_timeout(cmd, timeout) [parse_status(o), e] end - def launched? !!@pid end - def paused - Process.kill( "STOP", @pid ) + Process.kill('STOP', @pid) yield ensure - Process.kill( "CONT", @pid ) + Process.kill('CONT', @pid) end - protected + def control_command(*args) - raise "Server not running" unless @pid + raise 'Server not running' unless @pid args = args.compact UNIXSocket.open(@ctrl) do |u| u.write(args.join("\n") + "\n") - code, message = u.readline.split(": ", 2) + code, message = u.readline.split(': ', 2) return [code, message] end end - - def parse_status( status ) + def parse_status(status) hsh = {} - status.split(" ").each do |part| + status.split(' ').each do |part| next if part.strip.empty? - a,b = part.split("=") + a, b = part.split('=') b.strip! - b = true if b == "true" - b = false if b == "false" + b = true if b == 'true' + b = false if b == 'false' hsh[a.strip] = b end hsh end - - end - end - diff --git a/tests/acceptance/flexnbd/constants.rb b/tests/acceptance/flexnbd/constants.rb index 0e75688..18ee7c0 100644 --- a/tests/acceptance/flexnbd/constants.rb +++ b/tests/acceptance/flexnbd/constants.rb @@ -1,10 +1,7 @@ -# encoding: utf-8 - module FlexNBD - - def self.binary( str ) + def self.binary(str) if str.respond_to? :force_encoding - str.force_encoding "ASCII-8BIT" + str.force_encoding 'ASCII-8BIT' else str end @@ -13,36 +10,33 @@ module FlexNBD # eeevil is his one and only name... def self.read_constants parents = [] - current = File.expand_path(".") - while current != "/" + current = File.expand_path('.') + while current != '/' parents << current - current = File.expand_path( File.join( current, ".." ) ) + current = File.expand_path(File.join(current, '..')) end source_root = parents.find do |dirname| - File.directory?( File.join( dirname, "src" ) ) + File.directory?(File.join(dirname, 'src')) end - fail "No source root!" unless source_root + raise 'No source root!' unless source_root - headers = Dir[File.join( source_root, "src", "{common,proxy,server}","*.h" ) ] + headers = Dir[File.join(source_root, 'src', '{common,proxy,server}', '*.h')] headers.each do |header_filename| - txt_lines = File.readlines( header_filename ) + txt_lines = File.readlines(header_filename) txt_lines.each do |line| if line =~ /^#\s*define\s+([A-Z0-9_]+)\s+(\d+)\s*$/ # Bodge until I can figure out what to do with #ifdefs - const_set($1, $2.to_i) unless const_defined?( $1 ) + const_set(Regexp.last_match(1), Regexp.last_match(2).to_i) unless const_defined?(Regexp.last_match(1)) end end end - end - read_constants() + read_constants REQUEST_MAGIC = binary("\x25\x60\x95\x13") unless defined?(REQUEST_MAGIC) REPLY_MAGIC = binary("\x67\x44\x66\x98") unless defined?(REPLY_MAGIC) - end # module FlexNBD - diff --git a/tests/acceptance/flexnbd/fake_dest.rb b/tests/acceptance/flexnbd/fake_dest.rb index c96dc2b..26d82bf 100644 --- a/tests/acceptance/flexnbd/fake_dest.rb +++ b/tests/acceptance/flexnbd/fake_dest.rb @@ -1,5 +1,3 @@ -# encoding: utf-8 - require 'socket' require 'timeout' @@ -7,114 +5,104 @@ require 'flexnbd/constants' module FlexNBD class FakeDest - class Client - def initialize( sock ) + def initialize(sock) @sock = sock end - - def write_hello( opts = {} ) - @sock.write( "NBDMAGIC" ) + def write_hello(opts = {}) + @sock.write('NBDMAGIC') if opts[:magic] == :wrong - write_rand( @sock, 8 ) + write_rand(@sock, 8) else - @sock.write( "\x00\x00\x42\x02\x81\x86\x12\x53" ) + @sock.write("\x00\x00\x42\x02\x81\x86\x12\x53") end if opts[:size] == :wrong - write_rand( @sock, 8 ) + write_rand(@sock, 8) else - @sock.write( "\x00\x00\x00\x00\x00\x00\x10\x00" ) + @sock.write("\x00\x00\x00\x00\x00\x00\x10\x00") end - @sock.write( "\x00" * 128 ) + @sock.write("\x00" * 128) end - - def write_rand( sock, len ) - len.times do sock.write( rand(256).chr ) end + def write_rand(sock, len) + len.times { sock.write(rand(256).chr) } end - - def read_request() + def read_request req = @sock.read(28) - magic_s = req[0 ... 4 ] - type_s = req[4 ... 8 ] - handle_s = req[8 ... 16] - from_s = req[16 ... 24] - len_s = req[24 ... 28] + magic_s = req[0...4] + type_s = req[4...8] + handle_s = req[8...16] + from_s = req[16...24] + len_s = req[24...28] { - :magic => magic_s, - :type => type_s.unpack("N").first, - :handle => handle_s, - :from => self.class.parse_be64( from_s ), - :len => len_s.unpack( "N").first + magic: magic_s, + type: type_s.unpack('N').first, + handle: handle_s, + from: self.class.parse_be64(from_s), + len: len_s.unpack('N').first } end - def write_error( handle ) - write_reply( handle, 1 ) + def write_error(handle) + write_reply(handle, 1) end def disconnected? - begin - Timeout.timeout(2) do - @sock.read(1) == nil - end - rescue Timeout::Error - return false + Timeout.timeout(2) do + @sock.read(1).nil? end + rescue Timeout::Error + return false end - def write_reply( handle, err=0, opts={} ) + def write_reply(handle, err = 0, opts = {}) if opts[:magic] == :wrong - write_rand( @sock, 4 ) + write_rand(@sock, 4) else - @sock.write( ::FlexNBD::REPLY_MAGIC ) + @sock.write(::FlexNBD::REPLY_MAGIC) end - @sock.write( [err].pack("N") ) - @sock.write( handle ) + @sock.write([err].pack('N')) + @sock.write(handle) end - def close @sock.close end - - def read_data( len ) - @sock.read( len ) + def read_data(len) + @sock.read(len) end - def write_data( len ) - @sock.write( len ) + def write_data(len) + @sock.write(len) end - def self.parse_be64(str) raise "String is the wrong length: 8 bytes expected (#{str.length} received)" unless str.length == 8 - top, bottom = str.unpack("NN") + top, bottom = str.unpack('NN') (top << 32) + bottom end - - def receive_mirror( opts = {} ) - write_hello() + def receive_mirror(opts = {}) + write_hello loop do req = read_request case req[:type] when 1 - read_data( req[:len] ) - write_reply( req[:handle] ) - when 65536 - write_reply( req[:handle], opts[:err] == :entrust ? 1 : 0 ) + read_data(req[:len]) + write_reply(req[:handle]) + when 65_536 + write_reply(req[:handle], opts[:err] == :entrust ? 1 : 0) break else raise "Unexpected request: #{req.inspect}" @@ -129,16 +117,13 @@ module FlexNBD raise "Not a disconnect: #{req.inspect}" end end - end # class Client - - def initialize( addr, port ) - @sock = TCPServer.new( addr, port ) + def initialize(addr, port) + @sock = TCPServer.new(addr, port) end - - def accept( err_msg = "Timed out waiting for a connection", timeout = 5) + def accept(err_msg = 'Timed out waiting for a connection', timeout = 5) client_sock = nil begin @@ -146,21 +131,16 @@ module FlexNBD client_sock = @sock.accept end rescue Timeout::Error - raise Timeout::Error.new(err_msg) + raise Timeout::Error, err_msg end client_sock - Client.new( client_sock ) + Client.new(client_sock) end - def close @sock.close end - - - end # module FakeDest end # module FlexNBD - diff --git a/tests/acceptance/flexnbd/fake_source.rb b/tests/acceptance/flexnbd/fake_source.rb index 127e73c..888ac33 100644 --- a/tests/acceptance/flexnbd/fake_source.rb +++ b/tests/acceptance/flexnbd/fake_source.rb @@ -1,29 +1,25 @@ -# encoding: utf-8 - require 'socket' -require "timeout" +require 'timeout' require 'flexnbd/constants' module FlexNBD class FakeSource - - def initialize( addr, port, err_msg, source_addr=nil, source_port=0 ) - timing_out( 2, err_msg ) do + def initialize(addr, port, err_msg, source_addr = nil, source_port = 0) + timing_out(2, err_msg) do begin @sock = if source_addr - TCPSocket.new( addr, port, source_addr, source_port ) + TCPSocket.new(addr, port, source_addr, source_port) else - TCPSocket.new( addr, port ) + TCPSocket.new(addr, port) end rescue Errno::ECONNREFUSED - $stderr.puts "Connection refused, retrying" + warn 'Connection refused, retrying' sleep(0.2) retry end end end - def close @sock.close end @@ -31,8 +27,8 @@ module FlexNBD def read_hello timing_out(::FlexNBD::MS_HELLO_TIME_SECS, 'Timed out waiting for hello.') do - fail 'No hello.' unless (hello = @sock.read(152)) && - hello.length == 152 + raise 'No hello.' unless (hello = @sock.read(152)) && + hello.length == 152 passwd_s = hello[0..7] magic = hello[8..15].unpack('Q>').first @@ -44,97 +40,86 @@ module FlexNBD end end + def send_request(type, handle = 'myhandle', from = 0, len = 0, magic = REQUEST_MAGIC) + raise 'Bad handle' unless handle.length == 8 - def send_request( type, handle="myhandle", from=0, len=0, magic=REQUEST_MAGIC ) - fail "Bad handle" unless handle.length == 8 - - @sock.write( magic ) - @sock.write( [type].pack( 'N' ) ) - @sock.write( handle ) - @sock.write( [n64( from )].pack( 'q' ) ) - @sock.write( [len].pack( 'N' ) ) + @sock.write(magic) + @sock.write([type].pack('N')) + @sock.write(handle) + @sock.write([n64(from)].pack('q')) + @sock.write([len].pack('N')) end - - def write_write_request( from, len, handle="myhandle" ) - send_request( 1, handle, from, len ) + def write_write_request(from, len, handle = 'myhandle') + send_request(1, handle, from, len) end - - def write_entrust_request( handle="myhandle" ) - send_request( 65536, handle ) + def write_entrust_request(handle = 'myhandle') + send_request(65_536, handle) end - def write_disconnect_request( handle="myhandle" ) - send_request( 2, handle ) + def write_disconnect_request(handle = 'myhandle') + send_request(2, handle) end - def write_read_request( from, len, handle="myhandle" ) - send_request( 0, "myhandle", from, len ) + def write_read_request(from, len, _handle = 'myhandle') + send_request(0, 'myhandle', from, len) end - - def write_data( data ) - @sock.write( data ) + def write_data(data) + @sock.write(data) end - # Handy utility - def read( from, len ) - timing_out( 2, "Timed out reading" ) do - send_request( 0, "myhandle", from, len ) - read_raw( len ) + def read(from, len) + timing_out(2, 'Timed out reading') do + send_request(0, 'myhandle', from, len) + read_raw(len) end end - def read_raw( len ) - @sock.read( len ) + def read_raw(len) + @sock.read(len) end def send_mirror - read_hello() - write( 0, "12345678" ) - read_response() - write_disconnect_request() - close() + read_hello + write(0, '12345678') + read_response + write_disconnect_request + close end - - def write( from, data ) - write_write_request( from, data.length ) - write_data( data ) + def write(from, data) + write_write_request(from, data.length) + write_data(data) end - def read_response magic = @sock.read(4) error_s = @sock.read(4) handle = @sock.read(8) { - :magic => magic, - :error => error_s.unpack("N").first, - :handle => handle + magic: magic, + error: error_s.unpack('N').first, + handle: handle } end - def disconnected? result = nil - Timeout.timeout( 2 ) { result = ( @sock.read(1) == nil ) } + Timeout.timeout(2) { result = @sock.read(1).nil? } result end - - def timing_out( time, msg ) - begin - Timeout.timeout( time ) do - yield - end - rescue Timeout::Error - $stderr.puts msg - exit 1 + def timing_out(time, msg) + Timeout.timeout(time) do + yield end + rescue Timeout::Error + warn msg + exit 1 end private @@ -144,15 +129,13 @@ module FlexNBD # ) def n64(b) ((b & 0xff00000000000000) >> 56) | - ((b & 0x00ff000000000000) >> 40) | - ((b & 0x0000ff0000000000) >> 24) | - ((b & 0x000000ff00000000) >> 8) | - ((b & 0x00000000ff000000) << 8) | - ((b & 0x0000000000ff0000) << 24) | - ((b & 0x000000000000ff00) << 40) | - ((b & 0x00000000000000ff) << 56) + ((b & 0x00ff000000000000) >> 40) | + ((b & 0x0000ff0000000000) >> 24) | + ((b & 0x000000ff00000000) >> 8) | + ((b & 0x00000000ff000000) << 8) | + ((b & 0x0000000000ff0000) << 24) | + ((b & 0x000000000000ff00) << 40) | + ((b & 0x00000000000000ff) << 56) end - end # class FakeSource end # module FlexNBD - diff --git a/tests/acceptance/proxy_tests.rb b/tests/acceptance/proxy_tests.rb index fb4d38e..c2623d1 100644 --- a/tests/acceptance/proxy_tests.rb +++ b/tests/acceptance/proxy_tests.rb @@ -1,4 +1,4 @@ -# encoding: utf-8 + require 'flexnbd/fake_source' require 'flexnbd/fake_dest' @@ -7,20 +7,23 @@ module ProxyTests "\xFF".b end - def with_proxied_client( override_size = nil ) + def with_proxied_client(override_size = nil) @env.serve1 unless @server_up @env.proxy2 unless @proxy_up @env.nbd2.can_die(0) client = FlexNBD::FakeSource.new(@env.ip, @env.port2, "Couldn't connect to proxy") begin - result = client.read_hello - assert_equal "NBDMAGIC", result[:passwd] + assert_equal 'NBDMAGIC', result[:passwd] assert_equal override_size || @env.file1.size, result[:size] yield client ensure - client.close rescue nil + begin + client.close + rescue StandardError + nil + end end end @@ -32,11 +35,11 @@ module ProxyTests with_proxied_client do |client| (0..3).each do |n| offset = n * 4096 - client.write_read_request(offset, 4096, "myhandle") + client.write_read_request(offset, 4096, 'myhandle') rsp = client.read_response assert_equal ::FlexNBD::REPLY_MAGIC, rsp[:magic] - assert_equal "myhandle", rsp[:handle] + assert_equal 'myhandle', rsp[:handle] assert_equal 0, rsp[:error] orig_data = @env.file1.read(offset, 4096) @@ -45,8 +48,8 @@ module ProxyTests assert_equal 4096, orig_data.size assert_equal 4096, data.size - assert_equal( orig_data, data, - "Returned data does not match on request #{n+1}" ) + assert_equal(orig_data, data, + "Returned data does not match on request #{n + 1}") end end end @@ -59,12 +62,12 @@ module ProxyTests rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] - assert_equal "myhandle", rsp[:handle] + assert_equal 'myhandle', rsp[:handle] assert_equal 0, rsp[:error] data = @env.file1.read(offset, 4096) - assert_equal( ( b * 4096 ), data, "Data not written correctly (offset is #{n})" ) + assert_equal((b * 4096), data, "Data not written correctly (offset is #{n})") end end end @@ -78,7 +81,7 @@ module ProxyTests sc = server.accept # just tell the supervisor we're up sc.write_hello - [ server, sc ] + [server, sc] end end @@ -89,7 +92,7 @@ module ProxyTests server, sc1 = maker.value # Send the read request to the proxy - client.write_read_request( 0, 4096 ) + client.write_read_request(0, 4096) # ensure we're given the read request req1 = sc1.read_request @@ -110,8 +113,8 @@ module ProxyTests assert_equal req1, req2 # The reply should be proxied back to the client. - sc2.write_reply( req2[:handle] ) - sc2.write_data( b * 4096 ) + sc2.write_reply(req2[:handle]) + sc2.write_data(b * 4096) # Check it to make sure it's correct rsp = Timeout.timeout(15) { client.read_response } @@ -119,13 +122,12 @@ module ProxyTests assert_equal 0, rsp[:error] assert_equal req1[:handle], rsp[:handle] - data = client.read_raw( 4096 ) - assert_equal( (b * 4096), data, "Wrong data returned" ) + data = client.read_raw(4096) + assert_equal((b * 4096), data, 'Wrong data returned') sc2.close server.close end - end def test_write_request_retried_when_upstream_dies_partway @@ -135,7 +137,7 @@ module ProxyTests server, sc1 = maker.value # Send the read request to the proxy - client.write( 0, ( b * 4096 ) ) + client.write(0, (b * 4096)) # ensure we're given the read request req1 = sc1.read_request @@ -143,8 +145,8 @@ module ProxyTests assert_equal ::FlexNBD::REQUEST_WRITE, req1[:type] assert_equal 0, req1[:from] assert_equal 4096, req1[:len] - data1 = sc1.read_data( 4096 ) - assert_equal( ( b * 4096 ), data1, "Data not proxied successfully" ) + data1 = sc1.read_data(4096) + assert_equal((b * 4096), data1, 'Data not proxied successfully') # Kill the server again, now we're sure the read request has been sent once sc1.close @@ -156,11 +158,11 @@ module ProxyTests # And once reconnected, it should resend an identical request. req2 = sc2.read_request assert_equal req1, req2 - data2 = sc2.read_data( 4096 ) + data2 = sc2.read_data(4096) assert_equal data1, data2 # The reply should be proxied back to the client. - sc2.write_reply( req2[:handle] ) + sc2.write_reply(req2[:handle]) # Check it to make sure it's correct rsp = Timeout.timeout(15) { client.read_response } @@ -174,8 +176,7 @@ module ProxyTests end def test_only_one_client_can_connect_to_proxy_at_a_time - with_proxied_client do |client| - + with_proxied_client do |_client| c2 = nil assert_raises(Timeout::Error) do Timeout.timeout(1) do @@ -183,12 +184,13 @@ module ProxyTests c2.read_hello end end - c2.close rescue nil if c2 + if c2 + begin + c2.close + rescue StandardError + nil + end + end end - - end - end - - diff --git a/tests/acceptance/test_dest_error_handling.rb b/tests/acceptance/test_dest_error_handling.rb index b4171ee..9c1341e 100644 --- a/tests/acceptance/test_dest_error_handling.rb +++ b/tests/acceptance/test_dest_error_handling.rb @@ -1,13 +1,10 @@ -# encoding: utf-8 - require 'test/unit' require 'environment' -class TestDestErrorHandling < Test::Unit::TestCase - +class TestDestErrorHandling < Test::Unit::TestCase def setup @env = Environment.new - @env.writefile1( "0" * 4 ) + @env.writefile1('0' * 4) @env.listen1 end @@ -15,89 +12,77 @@ class TestDestErrorHandling < Test::Unit::TestCase @env.cleanup end - def test_hello_blocked_by_disconnect_causes_error_not_fatal - run_fake( "source/close_after_connect" ) + run_fake('source/close_after_connect') assert_no_control end -=begin - # This is disabled while CLIENT_MAX_WAIT_SECS is removed - def test_hello_goes_astray_causes_timeout_error - run_fake( "source/hang_after_hello" ) - assert_no_control - end -=end + # # This is disabled while CLIENT_MAX_WAIT_SECS is removed + # def test_hello_goes_astray_causes_timeout_error + # run_fake( "source/hang_after_hello" ) + # assert_no_control + # end def test_sigterm_has_bad_exit_status @env.nbd1.can_die(1) - run_fake( "source/sigterm_after_hello" ) + run_fake('source/sigterm_after_hello') end def test_disconnect_after_hello_causes_error_not_fatal - run_fake( "source/close_after_hello" ) + run_fake('source/close_after_hello') assert_no_control end - def test_partial_read_causes_error - run_fake( "source/close_mid_read" ) + run_fake('source/close_mid_read') end def test_double_connect_during_hello - run_fake( "source/connect_during_hello" ) + run_fake('source/connect_during_hello') end - def test_acl_rejection - @env.acl1("127.0.0.1") - run_fake( "source/connect_from_banned_ip") + @env.acl1('127.0.0.1') + run_fake('source/connect_from_banned_ip') end - def test_bad_write - run_fake( "source/write_out_of_range" ) + run_fake('source/write_out_of_range') end - def test_disconnect_before_write_data_causes_error - run_fake( "source/close_after_write" ) + run_fake('source/close_after_write') end - def test_disconnect_before_write_reply_causes_error # Note that this is an odd case: writing the reply doesn't fail. # The test passes because the next attempt by flexnbd to read a # request returns EOF. - run_fake( "source/close_after_write_data" ) + run_fake('source/close_after_write_data') end - - def test_straight_migration @env.nbd1.can_die(0) - run_fake( "source/successful_transfer" ) + run_fake('source/successful_transfer') end - private - def run_fake( name ) - @env.run_fake( name, @env.ip, @env.port1 ) + + def run_fake(name) + @env.run_fake(name, @env.ip, @env.port1) assert @env.fake_reports_success, "#{name} failed." end def status - stat, _ = @env.status1 + stat, = @env.status1 stat end def assert_no_control - assert !status['has_control'], "Thought it had control" + assert !status['has_control'], 'Thought it had control' end def assert_control assert status['has_control'], "Didn't think it had control" end - end # class TestDestErrorHandling - diff --git a/tests/acceptance/test_happy_path.rb b/tests/acceptance/test_happy_path.rb index 0a286c8..b785060 100644 --- a/tests/acceptance/test_happy_path.rb +++ b/tests/acceptance/test_happy_path.rb @@ -1,5 +1,3 @@ -# encoding: utf-8 - require 'test/unit' require 'environment' require 'flexnbd/constants' @@ -19,20 +17,18 @@ class TestHappyPath < Test::Unit::TestCase @env.cleanup end - def test_read1 - @env.writefile1("f"*64) + @env.writefile1('f' * 64) @env.serve1 [0, 12, 63].each do |num| - assert_equal( - bin( @env.nbd1.read(num*@env.blocksize, @env.blocksize) ), - bin( @env.file1.read(num*@env.blocksize, @env.blocksize) ) + bin(@env.nbd1.read(num * @env.blocksize, @env.blocksize)), + bin(@env.file1.read(num * @env.blocksize, @env.blocksize)) ) end - [124, 1200, 10028, 25488].each do |num| + [124, 1200, 10_028, 25_488].each do |num| assert_equal(bin(@env.nbd1.read(num, 4)), bin(@env.file1.read(num, 4))) end end @@ -40,14 +36,14 @@ class TestHappyPath < Test::Unit::TestCase # Check that we're not # def test_writeread1 - @env.writefile1("0"*64) + @env.writefile1('0' * 64) @env.serve1 [0, 12, 63].each do |num| - data = "X"*@env.blocksize - @env.nbd1.write(num*@env.blocksize, data) - assert_equal(data, @env.file1.read(num*@env.blocksize, data.size)) - assert_equal(data, @env.nbd1.read(num*@env.blocksize, data.size)) + data = 'X' * @env.blocksize + @env.nbd1.write(num * @env.blocksize, data) + assert_equal(data, @env.file1.read(num * @env.blocksize, data.size)) + assert_equal(data, @env.nbd1.read(num * @env.blocksize, data.size)) end end @@ -55,115 +51,105 @@ class TestHappyPath < Test::Unit::TestCase # up. # def test_writeread2 - @env.writefile1("0"*1024) + @env.writefile1('0' * 1024) @env.serve1 - d0 = "\0"*@env.blocksize - d1 = "X"*@env.blocksize + d0 = "\0" * @env.blocksize + d1 = 'X' * @env.blocksize (0..63).each do |num| - @env.nbd1.write(num*@env.blocksize*2, d1) + @env.nbd1.write(num * @env.blocksize * 2, d1) end (0..63).each do |num| - assert_equal(d0, @env.nbd1.read(((2*num)+1)*@env.blocksize, d0.size)) + assert_equal(d0, @env.nbd1.read(((2 * num) + 1) * @env.blocksize, d0.size)) end end - def setup_to_mirror - @env.writefile1( "f"*4 ) + @env.writefile1('f' * 4) @env.serve1 - @env.writefile2( "0"*4 ) + @env.writefile2('0' * 4) @env.listen2 end - def test_mirror @env.nbd1.can_die @env.nbd2.can_die(0) - setup_to_mirror() + setup_to_mirror stdout, stderr = @env.mirror12 @env.nbd1.join @env.nbd2.join - assert( File.file?( @env.filename1 ), - "The source file was incorrectly deleted") - assert_equal(@env.file1.read_original( 0, @env.blocksize ), - @env.file2.read( 0, @env.blocksize ) ) + assert(File.file?(@env.filename1), + 'The source file was incorrectly deleted') + assert_equal(@env.file1.read_original(0, @env.blocksize), + @env.file2.read(0, @env.blocksize)) end - def test_mirror_unlink @env.nbd1.can_die(0) @env.nbd2.can_die(0) - setup_to_mirror() + setup_to_mirror - assert File.file?( @env.filename1 ) + assert File.file?(@env.filename1) stdout, stderr = @env.mirror12_unlink - assert_no_match( /unrecognized/, stderr ) + assert_no_match(/unrecognized/, stderr) + Timeout.timeout(10) { @env.nbd1.join } - Timeout.timeout(10) do @env.nbd1.join end - - assert !File.file?( @env.filename1 ) + assert !File.file?(@env.filename1) end - - def test_write_to_high_block - # - # This test does not work on 32 bit platforms. - # - skip("Not relevant on 32-bit platforms") if ( ["a"].pack("p").size < 8 ) + # + # This test does not work on 32 bit platforms. + # + skip('Not relevant on 32-bit platforms') if ['a'].pack('p').size < 8 # Create a large file, then try to write to somewhere after the 2G boundary - @env.truncate1 "4G" + @env.truncate1 '4G' @env.serve1 - @env.nbd1.write( 2**31+2**29, "12345678" ) + @env.nbd1.write(2**31 + 2**29, '12345678') sleep(1) - assert_equal "12345678", @env.nbd1.read( 2**31+2**29, 8 ) + assert_equal '12345678', @env.nbd1.read(2**31 + 2**29, 8) end - def test_set_acl # Just check that we get sane feedback here - @env.writefile1( "f"*4 ) + @env.writefile1('f' * 4) @env.serve1 - _,stderr = @env.acl1("127.0.0.1") - assert_no_match( /^(F|E):/, stderr ) + _, stderr = @env.acl1('127.0.0.1') + assert_no_match(/^(F|E):/, stderr) end - def test_write_more_than_one_run one_mb = 2**20 data = "\0" * 256 * one_mb - File.open(@env.filename1, "wb") do |f| f.write( "1" * 256 * one_mb ) end + File.open(@env.filename1, 'wb') { |f| f.write('1' * 256 * one_mb) } @env.serve1 sleep 5 - @env.write1( data ) + @env.write1(data) @env.nbd1.can_die(0) @env.nbd1.kill i = 0 - File.open(@env.filename1, "rb") do |f| - while mb = f.read( one_mb ) - unless "\0"*one_mb == mb - msg = "Read non-zeros after offset %x:\n"%(i * one_mb) + File.open(@env.filename1, 'rb') do |f| + while mb = f.read(one_mb) + unless "\0" * one_mb == mb + msg = format("Read non-zeros after offset %x:\n", (i * one_mb)) msg += `hexdump #{@env.filename1} | head -n5` - fail msg + raise msg end i += 1 end end end - end - diff --git a/tests/acceptance/test_prefetch_proxy_mode.rb b/tests/acceptance/test_prefetch_proxy_mode.rb index eb07454..26a4306 100644 --- a/tests/acceptance/test_prefetch_proxy_mode.rb +++ b/tests/acceptance/test_prefetch_proxy_mode.rb @@ -2,7 +2,6 @@ require 'test/unit' require 'environment' require 'proxy_tests' - class TestPrefetchProxyMode < Test::Unit::TestCase include ProxyTests @@ -10,7 +9,7 @@ class TestPrefetchProxyMode < Test::Unit::TestCase super @env = Environment.new @env.prefetch_proxy! - @env.writefile1( "f" * 16 ) + @env.writefile1('f' * 16) end def teardown @@ -18,5 +17,3 @@ class TestPrefetchProxyMode < Test::Unit::TestCase super end end - - diff --git a/tests/acceptance/test_proxy_mode.rb b/tests/acceptance/test_proxy_mode.rb index c38116d..87d10e2 100644 --- a/tests/acceptance/test_proxy_mode.rb +++ b/tests/acceptance/test_proxy_mode.rb @@ -2,14 +2,13 @@ require 'test/unit' require 'environment' require 'proxy_tests' - class TestProxyMode < Test::Unit::TestCase include ProxyTests def setup super @env = Environment.new - @env.writefile1( "f" * 16 ) + @env.writefile1('f' * 16) end def teardown @@ -17,4 +16,3 @@ class TestProxyMode < Test::Unit::TestCase super end end - diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index dbacfdb..1d12dd9 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -4,12 +4,11 @@ require 'flexnbd/fake_source' require 'pp' class TestServeMode < Test::Unit::TestCase - def setup super @b = "\xFF".b @env = Environment.new - @env.writefile1( "0" ) + @env.writefile1('0') @env.serve1 end @@ -19,7 +18,7 @@ class TestServeMode < Test::Unit::TestCase end def connect_to_server - client = FlexNBD::FakeSource.new(@env.ip, @env.port1, "Connecting to server failed") + client = FlexNBD::FakeSource.new(@env.ip, @env.port1, 'Connecting to server failed') begin result = client.read_hello assert_equal 'NBDMAGIC', result[:passwd] @@ -29,62 +28,63 @@ class TestServeMode < Test::Unit::TestCase assert_equal "\x0" * 124, result[:reserved] yield client ensure - client.close rescue nil + begin + client.close + rescue StandardError + nil + end end end def test_bad_request_magic_receives_error_response connect_to_server do |client| - # replace REQUEST_MAGIC with all 0s to make it look bad - client.send_request( 0, "myhandle", 0, 0, "\x00\x00\x00\x00" ) + client.send_request(0, 'myhandle', 0, 0, "\x00\x00\x00\x00") rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] - assert_equal "myhandle", rsp[:handle] + assert_equal 'myhandle', rsp[:handle] assert rsp[:error] != 0, "Server sent success reply back: #{rsp[:error]}" # The client should be disconnected now - assert client.disconnected?, "Server not disconnected" + assert client.disconnected?, 'Server not disconnected' end end def test_long_write_on_top_of_short_write_is_respected - connect_to_server do |client| # Start with a file of all-zeroes. - client.write( 0, "\x00" * @env.file1.size ) + client.write(0, "\x00" * @env.file1.size) rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 0, rsp[:error] - client.write( 0, @b ) + client.write(0, @b) rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 0, rsp[:error] - client.write( 0, @b * 2 ) + client.write(0, @b * 2) rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 0, rsp[:error] end - assert_equal @b * 2, @env.file1.read( 0, 2 ) + assert_equal @b * 2, @env.file1.read(0, 2) end - def test_read_request_out_of_bounds_receives_error_response connect_to_server do |client| - client.write_read_request( @env.file1.size, 4096 ) + client.write_read_request(@env.file1.size, 4096) rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] - assert_equal "myhandle", rsp[:handle] + assert_equal 'myhandle', rsp[:handle] assert rsp[:error] != 0, "Server sent success reply back: #{rsp[:error]}" # Ensure we're not disconnected by sending a request. We don't care about # whether the reply is good or not, here. - client.write_read_request( 0, 4096 ) + client.write_read_request(0, 4096) rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] end @@ -92,23 +92,18 @@ class TestServeMode < Test::Unit::TestCase def test_write_request_out_of_bounds_receives_error_response connect_to_server do |client| - client.write( @env.file1.size, "\x00" * 4096 ) + client.write(@env.file1.size, "\x00" * 4096) rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] - assert_equal "myhandle", rsp[:handle] + assert_equal 'myhandle', rsp[:handle] assert rsp[:error] != 0, "Server sent success reply back: #{rsp[:error]}" # Ensure we're not disconnected by sending a request. We don't care about # whether the reply is good or not, here. - client.write( 0, "\x00" * @env.file1.size ) + client.write(0, "\x00" * @env.file1.size) rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] end - end - - - end - diff --git a/tests/acceptance/test_source_error_handling.rb b/tests/acceptance/test_source_error_handling.rb index 7a233ad..909b12c 100644 --- a/tests/acceptance/test_source_error_handling.rb +++ b/tests/acceptance/test_source_error_handling.rb @@ -1,126 +1,105 @@ -# encoding: utf-8 - require 'test/unit' require 'environment' - class TestSourceErrorHandling < Test::Unit::TestCase - def setup @old_env = ENV['FLEXNBD_MS_REQUEST_LIMIT_SECS'] - ENV['FLEXNBD_MS_REQUEST_LIMIT_SECS'] = "4.0" + ENV['FLEXNBD_MS_REQUEST_LIMIT_SECS'] = '4.0' @env = Environment.new - @env.writefile1( "f" * 4 ) + @env.writefile1('f' * 4) @env.serve1 end - def teardown @env.nbd1.can_die(0) @env.cleanup ENV['FLEXNBD_MS_REQUEST_LIMIT_SECS'] = @old_env end - def expect_term_during_migration - @env.nbd1.can_die(1,9) + @env.nbd1.can_die(1, 9) end - def test_failure_to_connect_reported_in_mirror_cmd_response stdout, stderr = @env.mirror12_unchecked expect_term_during_migration - assert_match( /failed to connect/, stderr ) + assert_match(/failed to connect/, stderr) end - def test_sigterm_after_hello_quits_with_status_of_1 expect_term_during_migration - run_fake( "dest/sigterm_after_hello" ) + run_fake('dest/sigterm_after_hello') end - def test_destination_hangs_after_connect_reports_error_at_source - run_fake( "dest/hang_after_connect", - :err => /Remote server failed to respond/ ) + run_fake('dest/hang_after_connect', + err: /Remote server failed to respond/) end - def test_destination_rejects_connection_reports_error_at_source - run_fake( "dest/reject_acl", - :err => /Mirror was rejected/ ) + run_fake('dest/reject_acl', + err: /Mirror was rejected/) end - def test_wrong_size_causes_disconnect - run_fake( "dest/hello_wrong_size", - :err => /Remote size does not match local size/ ) + run_fake('dest/hello_wrong_size', + err: /Remote size does not match local size/) end - def test_wrong_magic_causes_disconnect expect_term_during_migration - run_fake( "dest/hello_wrong_magic", - :err => /Mirror was rejected/ ) + run_fake('dest/hello_wrong_magic', + err: /Mirror was rejected/) end - def test_disconnect_after_hello_causes_retry expect_term_during_migration - run_fake( "dest/close_after_hello", - :out => /Mirror started/ ) + run_fake('dest/close_after_hello', + out: /Mirror started/) end - def test_write_times_out_causes_retry expect_term_during_migration - run_fake( "dest/hang_after_write" ) + run_fake('dest/hang_after_write') end - def test_rejected_write_causes_retry expect_term_during_migration - run_fake( "dest/error_on_write" ) + run_fake('dest/error_on_write') end - def test_disconnect_before_write_reply_causes_retry expect_term_during_migration - run_fake( "dest/close_after_write" ) + run_fake('dest/close_after_write') end - def test_bad_write_reply_causes_retry expect_term_during_migration - run_fake( "dest/write_wrong_magic" ) + run_fake('dest/write_wrong_magic') end - def test_pre_entrust_disconnect_causes_retry expect_term_during_migration - run_fake( "dest/close_after_writes" ) + run_fake('dest/close_after_writes') end - def test_cancel_migration - run_fake( "dest/break_after_hello" ) + run_fake('dest/break_after_hello') end - private + def run_fake(name, opts = {}) - @env.run_fake( name, @env.ip, @env.port2, @env.nbd1.ctrl ) + @env.run_fake(name, @env.ip, @env.port2, @env.nbd1.ctrl) stdout, stderr = @env.mirror12_unchecked assert_success - assert_match( opts[:err], stderr ) if opts[:err] - assert_match( opts[:out], stdout ) if opts[:out] - return stdout, stderr + assert_match(opts[:err], stderr) if opts[:err] + assert_match(opts[:out], stdout) if opts[:out] + [stdout, stderr] end - def assert_success( msg=nil ) - assert @env.fake_reports_success, msg || "Fake failed" + def assert_success(msg = nil) + assert @env.fake_reports_success, msg || 'Fake failed' end - - end # class TestSourceErrorHandling diff --git a/tests/acceptance/test_write_during_migration.rb b/tests/acceptance/test_write_during_migration.rb index e89c9a7..dd259c5 100755 --- a/tests/acceptance/test_write_during_migration.rb +++ b/tests/acceptance/test_write_during_migration.rb @@ -9,102 +9,98 @@ require 'tmpdir' Thread.abort_on_exception = true class TestWriteDuringMigration < Test::Unit::TestCase - def setup - @flexnbd = File.expand_path("../../build/flexnbd") + @flexnbd = File.expand_path('../../build/flexnbd') - raise "No binary!" unless File.executable?( @flexnbd ) + raise 'No binary!' unless File.executable?(@flexnbd) - - @size = 20*1024*1024 # 20MB - @write_data = "foo!" * 2048 # 8K write + @size = 20 * 1024 * 1024 # 20MB + @write_data = 'foo!' * 2048 # 8K write @source_port = 9990 @dest_port = 9991 - @source_sock = "src.sock" - @dest_sock = "dst.sock" - @source_file = "src.file" - @dest_file = "dst.file" + @source_sock = 'src.sock' + @dest_sock = 'dst.sock' + @source_file = 'src.file' + @dest_file = 'dst.file' end - def teardown [@dst_proc, @src_proc].each do |pid| - if pid - Process.kill( "KILL", pid ) rescue nil + next unless pid + begin + Process.kill('KILL', pid) + rescue StandardError + nil end end end def debug_arg - ENV['DEBUG'] ? "--verbose" : "" + ENV['DEBUG'] ? '--verbose' : '' end - def launch_servers - @dst_proc = fork() { + @dst_proc = fork do cmd = "#{@flexnbd} listen -l 127.0.0.1 -p #{@dest_port} -f #{@dest_file} -s #{@dest_sock} #{debug_arg}" exec cmd - } + end - @src_proc = fork() { + @src_proc = fork do cmd = "#{@flexnbd} serve -l 127.0.0.1 -p #{@source_port} -f #{@source_file} -s #{@source_sock} #{debug_arg}" exec cmd - } + end begin awaiting = nil Timeout.timeout(10) do awaiting = :source - sleep 0.1 while !File.exists?( @source_sock ) + sleep 0.1 until File.exist?(@source_sock) awaiting = :dest - sleep 0.1 while !File.exists?( @dest_sock ) + sleep 0.1 until File.exist?(@dest_sock) end rescue Timeout::Error case awaiting when :source - fail "Couldn't get a source socket." + raise "Couldn't get a source socket." when :dest - fail "Couldn't get a destination socket." + raise "Couldn't get a destination socket." else - fail "Something went wrong I don't understand." + raise "Something went wrong I don't understand." end end end - - def make_files() + def make_files FileUtils.touch(@source_file) File.truncate(@source_file, @size) FileUtils.touch(@dest_file) File.truncate(@dest_file, @size) - File.open(@source_file, "wb"){|f| f.write "a"*@size } + File.open(@source_file, 'wb') { |f| f.write 'a' * @size } end - def start_mirror - UNIXSocket.open(@source_sock) {|sock| - sock.write(["mirror", "127.0.0.1", @dest_port.to_s, "exit"].join("\x0A") + "\x0A\x0A") + UNIXSocket.open(@source_sock) do |sock| + sock.write(['mirror', '127.0.0.1', @dest_port.to_s, 'exit'].join("\x0A") + "\x0A\x0A") sock.flush rsp = sock.readline - } + end end - - def wait_for_quit() - Timeout.timeout( 10 ) do - start_time = Time.now - dst_result = Process::waitpid2(@dst_proc) - src_result = Process::waitpid2(@src_proc) + def wait_for_quit + Timeout.timeout(10) do + start_time = Time.now + dst_result = Process.waitpid2(@dst_proc) + src_result = Process.waitpid2(@src_proc) end end def source_writer - client = FlexNBD::FakeSource.new( "127.0.0.1", @source_port, "Timed out connecting" ) - offsets = Range.new(0, (@size - @write_data.size) / 4096 ).to_a + client = FlexNBD::FakeSource.new('127.0.0.1', @source_port, 'Timed out connecting') + offsets = Range.new(0, (@size - @write_data.size) / 4096).to_a loop do begin client.write(offsets[rand(offsets.size)] * 4096, @write_data) - rescue => err + rescue StandardError => err # We expect a broken write at some point, so ignore it break end @@ -115,32 +111,32 @@ class TestWriteDuringMigration < Test::Unit::TestCase # puts `md5sum #{@source_file} #{@dest_file}` # Ensure each block matches - File.open(@source_file, "r") do |source| - File.open(@dest_file, "r") do |dest| - 0.upto( @size / 4096 ) do |block_num| - s_data = source.read( 4096 ) - d_data = dest.read( 4096 ) + File.open(@source_file, 'r') do |source| + File.open(@dest_file, 'r') do |dest| + 0.upto(@size / 4096) do |block_num| + s_data = source.read(4096) + d_data = dest.read(4096) assert s_data == d_data, "Block #{block_num} mismatch!" - source.seek( 4096, IO::SEEK_CUR ) - dest.seek( 4096, IO::SEEK_CUR ) + source.seek(4096, IO::SEEK_CUR) + dest.seek(4096, IO::SEEK_CUR) end end end end def test_write_during_migration - Dir.mktmpdir() do |tmpdir| - Dir.chdir( tmpdir ) do - make_files() + Dir.mktmpdir do |tmpdir| + Dir.chdir(tmpdir) do + make_files - launch_servers() + launch_servers src_writer = Thread.new { source_writer } - start_mirror() - wait_for_quit() + start_mirror + wait_for_quit src_writer.join assert_both_sides_identical end @@ -148,24 +144,21 @@ class TestWriteDuringMigration < Test::Unit::TestCase end def test_many_clients_during_migration - Dir.mktmpdir() do |tmpdir| - Dir.chdir( tmpdir ) do - make_files() + Dir.mktmpdir do |tmpdir| + Dir.chdir(tmpdir) do + make_files - launch_servers() + launch_servers src_writers_1 = (1..5).collect { Thread.new { source_writer } } - start_mirror() + start_mirror src_writers_2 = (1..5).collect { Thread.new { source_writer } } - wait_for_quit() - ( src_writers_1 + src_writers_2 ).each {|t| t.join } + wait_for_quit + (src_writers_1 + src_writers_2).each(&:join) assert_both_sides_identical end - end end - - + end end end - From 1d98ba1d3eda3dbd311e45262f164b7723ee2609 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 21:36:30 +0000 Subject: [PATCH 26/71] Further rubocopping --- tests/acceptance/nbd_scenarios | 2 +- tests/acceptance/test_write_during_migration.rb | 0 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 tests/acceptance/nbd_scenarios mode change 100755 => 100644 tests/acceptance/test_write_during_migration.rb diff --git a/tests/acceptance/nbd_scenarios b/tests/acceptance/nbd_scenarios old mode 100644 new mode 100755 index 039cee5..239ed49 --- a/tests/acceptance/nbd_scenarios +++ b/tests/acceptance/nbd_scenarios @@ -1,6 +1,6 @@ #!/usr/bin/ruby -test_files = Dir[File.dirname( __FILE__ ) + "/test*.rb"] +test_files = Dir[File.dirname(__FILE__) + '/test*.rb'] for filename in test_files require filename end diff --git a/tests/acceptance/test_write_during_migration.rb b/tests/acceptance/test_write_during_migration.rb old mode 100755 new mode 100644 From d6057a4244a35ed5f0d5f89447b2f6328170acdc Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 2 Feb 2018 21:41:07 +0000 Subject: [PATCH 27/71] Use 'English' in ruby --- tests/acceptance/flexnbd.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/acceptance/flexnbd.rb b/tests/acceptance/flexnbd.rb index 236fd58..04de991 100644 --- a/tests/acceptance/flexnbd.rb +++ b/tests/acceptance/flexnbd.rb @@ -4,6 +4,7 @@ require 'open3' require 'timeout' require 'rexml/document' require 'rexml/streamlistener' +require 'English' Thread.abort_on_exception = true From 4d9db4d6e95dc4a231e6f3ed2f69bb58d7aadee0 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Sat, 3 Feb 2018 20:10:47 +0000 Subject: [PATCH 28/71] Added basic FLUSH test --- tests/acceptance/flexnbd/fake_source.rb | 8 ++++++++ tests/acceptance/test_serve_mode.rb | 14 +++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/acceptance/flexnbd/fake_source.rb b/tests/acceptance/flexnbd/fake_source.rb index 888ac33..793b647 100644 --- a/tests/acceptance/flexnbd/fake_source.rb +++ b/tests/acceptance/flexnbd/fake_source.rb @@ -53,6 +53,10 @@ module FlexNBD def write_write_request(from, len, handle = 'myhandle') send_request(1, handle, from, len) end + + def write_flush_request(handle = 'myhandle') + send_request(3, handle, 0, 0) + end def write_entrust_request(handle = 'myhandle') send_request(65_536, handle) @@ -95,6 +99,10 @@ module FlexNBD write_data(data) end + def flush + write_flush_request + end + def read_response magic = @sock.read(4) error_s = @sock.read(4) diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index 1d12dd9..faa0ce0 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -24,7 +24,9 @@ class TestServeMode < Test::Unit::TestCase assert_equal 'NBDMAGIC', result[:passwd] assert_equal 0x00420281861253, result[:magic] assert_equal @env.file1.size, result[:size] - assert_equal 13, result[:flags] + # See src/common/nbdtypes.h for the various flags. At the moment we + # support HAS_FLAGS (1), SEND_FLUSH (4), SEND_FUA (8) + assert_equal (1 | 4 | 8), result[:flags] assert_equal "\x0" * 124, result[:reserved] yield client ensure @@ -106,4 +108,14 @@ class TestServeMode < Test::Unit::TestCase assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] end end + + def test_flush_is_accepted + connect_to_server do |client| + # Start with a file of all-zeroes. + client.flush + rsp = client.read_response + assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] + assert_equal 0, rsp[:error] + end + end end From 2b584688006d6065c1c2a414d149e2182ddedc0d Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Sat, 3 Feb 2018 20:29:15 +0000 Subject: [PATCH 29/71] Added test for FUA acceptance. Although I think this might be a bit useless as servers normally just ingore flags. --- src/server/client.c | 1 + tests/acceptance/flexnbd.rb | 1 + tests/acceptance/flexnbd/fake_source.rb | 16 +++++++++++++--- tests/acceptance/test_serve_mode.rb | 11 ++++++++++- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/server/client.c b/src/server/client.c index 5cc1c17..6d8543b 100644 --- a/src/server/client.c +++ b/src/server/client.c @@ -483,6 +483,7 @@ void client_reply_to_write( struct client* client, struct nbd_request request ) /* multiple of 4K page size */ uint64_t from_rounded = request.from & (!0xfff); uint64_t len_rounded = request.len + (request.from - from_rounded); + debug("Calling msync from=%"PRIu64", len=%"PRIu64"",from_rounded, len_rounded); FATAL_IF_NEGATIVE( msync( client->mapped + from_rounded, diff --git a/tests/acceptance/flexnbd.rb b/tests/acceptance/flexnbd.rb index 04de991..55662d6 100644 --- a/tests/acceptance/flexnbd.rb +++ b/tests/acceptance/flexnbd.rb @@ -195,6 +195,7 @@ module FlexNBD @ctrl = "/tmp/.flexnbd.ctrl.#{Time.now.to_i}.#{rand}" @ip = ip @port = port + @pid = @wait_thread = nil @kill = [] @prefetch_proxy = false end diff --git a/tests/acceptance/flexnbd/fake_source.rb b/tests/acceptance/flexnbd/fake_source.rb index 793b647..1691c4c 100644 --- a/tests/acceptance/flexnbd/fake_source.rb +++ b/tests/acceptance/flexnbd/fake_source.rb @@ -40,11 +40,12 @@ module FlexNBD end end - def send_request(type, handle = 'myhandle', from = 0, len = 0, magic = REQUEST_MAGIC) + def send_request(type, handle = 'myhandle', from = 0, len = 0, magic = REQUEST_MAGIC, flags = 0) raise 'Bad handle' unless handle.length == 8 @sock.write(magic) - @sock.write([type].pack('N')) + @sock.write([flags].pack('n')) + @sock.write([type].pack('n')) @sock.write(handle) @sock.write([n64(from)].pack('q')) @sock.write([len].pack('N')) @@ -53,7 +54,11 @@ module FlexNBD def write_write_request(from, len, handle = 'myhandle') send_request(1, handle, from, len) end - + + def write_write_request_with_fua(from, len, handle = 'myhandle') + send_request(1, handle, from, len, REQUEST_MAGIC, 1) + end + def write_flush_request(handle = 'myhandle') send_request(3, handle, 0, 0) end @@ -99,6 +104,11 @@ module FlexNBD write_data(data) end + def write_with_fua(from, data) + write_write_request_with_fua(from, data.length) + write_data(data) + end + def flush write_flush_request end diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index faa0ce0..b52eb1a 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -1,7 +1,6 @@ require 'test/unit' require 'environment' require 'flexnbd/fake_source' -require 'pp' class TestServeMode < Test::Unit::TestCase def setup @@ -118,4 +117,14 @@ class TestServeMode < Test::Unit::TestCase assert_equal 0, rsp[:error] end end + + def test_write_with_fua_is_accepted + connect_to_server do |client| + # Start with a file of all-zeroes. + client.write_with_fua(0, "\x00" * @env.file1.size) + rsp = client.read_response + assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] + assert_equal 0, rsp[:error] + end + end end From ba59a4c03f9a01c15efa659b366bef4c5d314103 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Mon, 5 Feb 2018 08:15:56 +0000 Subject: [PATCH 30/71] Updated changelog --- debian/changelog | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index c25a53e..b05e74d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -flexnbd (0.1.8) UNRELEASED; urgency=medium +flexnbd (0.2.0) UNRELEASED; urgency=medium [ James Carter ] * Set TCP keepalive on sockets so broken connections are reaped (#33, !33, @@ -8,6 +8,9 @@ flexnbd (0.1.8) UNRELEASED; urgency=medium [ Chris Cottam ] * Increased NBD_MAX_SIZE from 1MB to 32MB for qemu 2.11 (!35) + [ Patrick J Cherry ] + * Added FLUSH and FUA support (!38) + -- James Carter Thu, 11 Jan 2018 10:05:35 +0000 flexnbd (0.1.7) stable; urgency=medium From d1dc7392c2fdad84895c2364fa8b21077289885a Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Mon, 5 Feb 2018 16:15:36 +0000 Subject: [PATCH 31/71] Open file with O_NOATIME, not O_SYNC O_SYNC is not necessary as we're not doing direct writes to the file. O_NOATIME might give some speed boost. --- src/common/ioutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/ioutil.c b/src/common/ioutil.c index 6a8309a..4c1a4bd 100644 --- a/src/common/ioutil.c +++ b/src/common/ioutil.c @@ -85,7 +85,7 @@ int open_and_mmap(const char* filename, int* out_fd, uint64_t *out_size, void ** off64_t size; /* O_DIRECT should not be used with mmap() */ - *out_fd = open(filename, O_RDWR | O_SYNC ); + *out_fd = open(filename, O_RDWR | O_NOATIME ); if (*out_fd < 1) { warn("open(%s) failed: does it exist?", filename); From ad2014ac9de7dc756f5de61d0b57745046926980 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Mon, 5 Feb 2018 16:16:17 +0000 Subject: [PATCH 32/71] Fixed long-standing bug with h2r functions being back to front h2r seemd to be using beXXtoh functions instead of htobeXX. Foruntately ROT13 works symmetrically on our systems..! --- src/common/nbdtypes.c | 28 ++++++++++++++-------------- src/proxy/proxy.c | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/common/nbdtypes.c b/src/common/nbdtypes.c index f45bf0f..20020b4 100644 --- a/src/common/nbdtypes.c +++ b/src/common/nbdtypes.c @@ -26,16 +26,6 @@ void nbd_h2r_init( struct nbd_init * from, struct nbd_init_raw * to) void nbd_r2h_request( struct nbd_request_raw *from, struct nbd_request * to ) -{ - to->magic = htobe32( from->magic ); - to->flags = htobe16( from->flags ); - to->type = htobe16( from->type ); - to->handle.w = from->handle.w; - to->from = htobe64( from->from ); - to->len = htobe32( from->len ); -} - -void nbd_h2r_request( struct nbd_request * from, struct nbd_request_raw * to ) { to->magic = be32toh( from->magic ); to->flags = be16toh( from->flags ); @@ -45,18 +35,28 @@ void nbd_h2r_request( struct nbd_request * from, struct nbd_request_raw * to ) to->len = be32toh( from->len ); } - -void nbd_r2h_reply( struct nbd_reply_raw * from, struct nbd_reply * to ) +void nbd_h2r_request( struct nbd_request * from, struct nbd_request_raw * to ) { to->magic = htobe32( from->magic ); - to->error = htobe32( from->error ); + to->flags = htobe16( from->flags ); + to->type = htobe16( from->type ); to->handle.w = from->handle.w; + to->from = htobe64( from->from ); + to->len = htobe32( from->len ); } -void nbd_h2r_reply( struct nbd_reply * from, struct nbd_reply_raw * to ) + +void nbd_r2h_reply( struct nbd_reply_raw * from, struct nbd_reply * to ) { to->magic = be32toh( from->magic ); to->error = be32toh( from->error ); to->handle.w = from->handle.w; } +void nbd_h2r_reply( struct nbd_reply * from, struct nbd_reply_raw * to ) +{ + to->magic = htobe32( from->magic ); + to->error = htobe32( from->error ); + to->handle.w = from->handle.w; +} + diff --git a/src/proxy/proxy.c b/src/proxy/proxy.c index bacffee..39c1081 100644 --- a/src/proxy/proxy.c +++ b/src/proxy/proxy.c @@ -471,8 +471,8 @@ int proxy_read_from_downstream( struct proxier *proxy, int state ) if ( proxy->req.needle == proxy->req.size ) { debug( - "Received NBD request from downstream. type=%"PRIu32" from=%"PRIu64" len=%"PRIu32, - request->type, request->from, request->len + "Received NBD request from downstream. type=%"PRIu16" flags=%"PRIu16" from=%"PRIu64" len=%"PRIu32, + request->type, request->flags, request->from, request->len ); /* Finished reading, so advance state. Leave size untouched so the next From afa1bb0efba2816c7a7b269b9e1c8867a279dd6f Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Mon, 5 Feb 2018 17:01:32 +0000 Subject: [PATCH 33/71] Use msync rather than fsync to flush the entire disc This involves storing the size of the mapped disc in the client struct, and then supplying that to the msync command. --- src/server/client.c | 4 ++-- src/server/client.h | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/server/client.c b/src/server/client.c index 6d8543b..eb203b3 100644 --- a/src/server/client.c +++ b/src/server/client.c @@ -500,7 +500,7 @@ void client_reply_to_flush( struct client* client, struct nbd_request request ) debug("request flush from=%"PRIu64", len=%"PRIu32", handle=0x%08X", request.from, request.len, request.handle); ERROR_IF_NEGATIVE( - fsync(client->fileno), + msync(client->mapped, client->mapped_size, MS_SYNC | MS_INVALIDATE), "flush failed" ); @@ -697,7 +697,7 @@ void* client_serve(void* client_uncast) open_and_mmap( client->serve->filename, &client->fileno, - NULL, + &client->mapped_size, (void**) &client->mapped ), "Couldn't open/mmap file %s: %s", client->serve->filename, strerror( errno ) diff --git a/src/server/client.h b/src/server/client.h index 9110d7d..a03ea44 100644 --- a/src/server/client.h +++ b/src/server/client.h @@ -3,6 +3,7 @@ #include #include +#include /** CLIENT_HANDLER_TIMEOUT * This is the length of time (in seconds) any request can be outstanding for. @@ -31,6 +32,8 @@ struct client { int fileno; char* mapped; + uint64_t mapped_size; + struct self_pipe * stop_signal; struct server* serve; /* FIXME: remove above duplication */ From c423900f02e84e8611bccaa96198e0e2cf0d62b6 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Mon, 5 Feb 2018 17:04:23 +0000 Subject: [PATCH 34/71] Fix typo --- src/proxy/proxy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/proxy/proxy.h b/src/proxy/proxy.h index 4173fb7..4be93d5 100644 --- a/src/proxy/proxy.h +++ b/src/proxy/proxy.h @@ -46,7 +46,7 @@ struct proxier { /* This is the size we advertise to the downstream server */ uint64_t upstream_size; - /* These are thet transmission flags sent as part of the handshake */ + /* These are the transmission flags sent as part of the handshake */ uint32_t upstream_flags; /* We transform the raw request header into here */ From 6d6948af096e99ecd47617da5bbd1d9d4ad39b06 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Mon, 5 Feb 2018 23:05:00 +0000 Subject: [PATCH 35/71] Fix offset calculation for partial msyncs to go to nearest 4k block Previously they were always set to zero. --- src/server/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/client.c b/src/server/client.c index eb203b3..5e9e877 100644 --- a/src/server/client.c +++ b/src/server/client.c @@ -481,7 +481,7 @@ void client_reply_to_write( struct client* client, struct nbd_request request ) if (request.flags & CMD_FLAG_FUA) { /* multiple of 4K page size */ - uint64_t from_rounded = request.from & (!0xfff); + uint64_t from_rounded = request.from & (~0xfff); uint64_t len_rounded = request.len + (request.from - from_rounded); debug("Calling msync from=%"PRIu64", len=%"PRIu64"",from_rounded, len_rounded); From 3a86870c9f5324ad3aa25fda749710cd568a8177 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 6 Feb 2018 07:32:58 +0000 Subject: [PATCH 36/71] Use sysconf to determine actual page size for msync Also added comments in tests around testing for msync offsets/lengths. --- src/server/client.c | 4 ++-- tests/acceptance/environment.rb | 3 ++- tests/acceptance/test_serve_mode.rb | 14 +++++++++++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/server/client.c b/src/server/client.c index 5e9e877..3a72cb9 100644 --- a/src/server/client.c +++ b/src/server/client.c @@ -480,8 +480,8 @@ void client_reply_to_write( struct client* client, struct nbd_request request ) // Only flush if FUA is set if (request.flags & CMD_FLAG_FUA) { - /* multiple of 4K page size */ - uint64_t from_rounded = request.from & (~0xfff); + /* multiple of page size */ + uint64_t from_rounded = request.from & (~(sysconf(_SC_PAGE_SIZE)-1)); uint64_t len_rounded = request.len + (request.from - from_rounded); debug("Calling msync from=%"PRIu64", len=%"PRIu64"",from_rounded, len_rounded); diff --git a/tests/acceptance/environment.rb b/tests/acceptance/environment.rb index 9697227..f350525 100644 --- a/tests/acceptance/environment.rb +++ b/tests/acceptance/environment.rb @@ -6,7 +6,8 @@ class Environment :port1, :port2, :nbd1, :nbd2, :file1, :file2) def initialize - @blocksize = 1024 + # Make sure we have a few pages of memory so we can test msync offsets + @blocksize = Integer(`getconf PAGE_SIZE`) * 4 @filename1 = "/tmp/.flexnbd.test.#{$PROCESS_ID}.#{Time.now.to_i}.1" @filename2 = "/tmp/.flexnbd.test.#{$PROCESS_ID}.#{Time.now.to_i}.2" @ip = '127.0.0.1' diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index b52eb1a..a422da1 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -110,7 +110,6 @@ class TestServeMode < Test::Unit::TestCase def test_flush_is_accepted connect_to_server do |client| - # Start with a file of all-zeroes. client.flush rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] @@ -119,12 +118,21 @@ class TestServeMode < Test::Unit::TestCase end def test_write_with_fua_is_accepted + page_size = Integer(`getconf PAGESIZE`) connect_to_server do |client| - # Start with a file of all-zeroes. - client.write_with_fua(0, "\x00" * @env.file1.size) + # Write somewhere in the third page + pos = page_size * 3 + 100 + client.write_with_fua(pos, "\x00" * 33) rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 0, rsp[:error] + # TODO: test offset and length + # Should be rounded to the third page + # assert_equal(msync_offset, page_size *3) + + # Should be 100 + 33, as we've started writing 100 bytes into a page, for + # 33 bytes + # assert_equal(msync_length, 133) end end end From 7704f9e5c8ef865e189952a2dc92a17181a0cd76 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 6 Feb 2018 07:57:40 +0000 Subject: [PATCH 37/71] Fix tests to reflect new filesize. --- tests/acceptance/environment.rb | 2 ++ tests/acceptance/flexnbd/fake_dest.rb | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/acceptance/environment.rb b/tests/acceptance/environment.rb index f350525..cba6cbf 100644 --- a/tests/acceptance/environment.rb +++ b/tests/acceptance/environment.rb @@ -7,6 +7,8 @@ class Environment def initialize # Make sure we have a few pages of memory so we can test msync offsets + # NB If you change this, you need to match it in the flexnbd/fake_dest + # Flexnbd::FakeDest::Client#write_hello @blocksize = Integer(`getconf PAGE_SIZE`) * 4 @filename1 = "/tmp/.flexnbd.test.#{$PROCESS_ID}.#{Time.now.to_i}.1" @filename2 = "/tmp/.flexnbd.test.#{$PROCESS_ID}.#{Time.now.to_i}.2" diff --git a/tests/acceptance/flexnbd/fake_dest.rb b/tests/acceptance/flexnbd/fake_dest.rb index 26d82bf..0b0e414 100644 --- a/tests/acceptance/flexnbd/fake_dest.rb +++ b/tests/acceptance/flexnbd/fake_dest.rb @@ -22,7 +22,7 @@ module FlexNBD if opts[:size] == :wrong write_rand(@sock, 8) else - @sock.write("\x00\x00\x00\x00\x00\x00\x10\x00") + @sock.write("\x00\x00\x00\x00\x00\x01\x00\x00") end @sock.write("\x00" * 128) From da35187af0001dc9927ca10a90d303b86adc476e Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 6 Feb 2018 09:55:32 +0000 Subject: [PATCH 38/71] Allow blocksize to be changed in Environment This number is peppered all over the test suite, so changing @blocksize for everything is not a goer, when we really only need to change it for one test. --- tests/acceptance/environment.rb | 10 ++++++---- tests/acceptance/flexnbd/fake_dest.rb | 2 +- tests/acceptance/test_serve_mode.rb | 4 ++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/acceptance/environment.rb b/tests/acceptance/environment.rb index cba6cbf..a614066 100644 --- a/tests/acceptance/environment.rb +++ b/tests/acceptance/environment.rb @@ -6,10 +6,7 @@ class Environment :port1, :port2, :nbd1, :nbd2, :file1, :file2) def initialize - # Make sure we have a few pages of memory so we can test msync offsets - # NB If you change this, you need to match it in the flexnbd/fake_dest - # Flexnbd::FakeDest::Client#write_hello - @blocksize = Integer(`getconf PAGE_SIZE`) * 4 + @blocksize = 1024 @filename1 = "/tmp/.flexnbd.test.#{$PROCESS_ID}.#{Time.now.to_i}.1" @filename2 = "/tmp/.flexnbd.test.#{$PROCESS_ID}.#{Time.now.to_i}.2" @ip = '127.0.0.1' @@ -22,6 +19,11 @@ class Environment @fake_pid = nil end + def blocksize=(b) + raise RuntimeError, "Unable to change blocksize after files have been opened" if @file1 or @file2 + @blocksize = b + end + def prefetch_proxy! @nbd1.prefetch_proxy = true @nbd2.prefetch_proxy = true diff --git a/tests/acceptance/flexnbd/fake_dest.rb b/tests/acceptance/flexnbd/fake_dest.rb index 0b0e414..26d82bf 100644 --- a/tests/acceptance/flexnbd/fake_dest.rb +++ b/tests/acceptance/flexnbd/fake_dest.rb @@ -22,7 +22,7 @@ module FlexNBD if opts[:size] == :wrong write_rand(@sock, 8) else - @sock.write("\x00\x00\x00\x00\x00\x01\x00\x00") + @sock.write("\x00\x00\x00\x00\x00\x00\x10\x00") end @sock.write("\x00" * 128) diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index a422da1..462eb5b 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -119,6 +119,10 @@ class TestServeMode < Test::Unit::TestCase def test_write_with_fua_is_accepted page_size = Integer(`getconf PAGESIZE`) + @env = Environment.new + @env.blocksize = page_size * 10 + @env.writefile1('0') + @env.serve1 connect_to_server do |client| # Write somewhere in the third page pos = page_size * 3 + 100 From 9bf3b52d54586d6b7f22e6a169fb651893142a46 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 6 Feb 2018 10:02:16 +0000 Subject: [PATCH 39/71] Call proxy_finish_connect_to_upstream when reconnecting, setting TCP_NODELAY --- src/proxy/proxy.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/proxy/proxy.c b/src/proxy/proxy.c index 39c1081..8283d8c 100644 --- a/src/proxy/proxy.c +++ b/src/proxy/proxy.c @@ -534,11 +534,8 @@ int proxy_read_init_from_upstream( struct proxier* proxy, int state ) goto disconnect; } - /* record the flags, and log the reconnection */ - // TODO: Should we call this at all here? We lose the - // upstream_size and flags otherwise, but then we can't - // renegotiate anyway. - // proxy_finish_connect_to_upstream( proxy, upstream_size, upstream_flags ); + /* record the flags, and log the reconnection, set TCP_NODELAY */ + proxy_finish_connect_to_upstream( proxy, upstream_size, upstream_flags ); /* Currently, we only get disconnected from upstream (so needing to come * here) when we have an outstanding request. If that becomes false, From 55548cc969cf50c97b007a664c07ecd7b12ac238 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 6 Feb 2018 10:24:54 +0000 Subject: [PATCH 40/71] Change ordering of @env configuration/start so we can alter the blocksize. argh. --- tests/acceptance/test_serve_mode.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index 462eb5b..e67da83 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -7,8 +7,6 @@ class TestServeMode < Test::Unit::TestCase super @b = "\xFF".b @env = Environment.new - @env.writefile1('0') - @env.serve1 end def teardown @@ -17,6 +15,8 @@ class TestServeMode < Test::Unit::TestCase end def connect_to_server + @env.writefile1('0') + @env.serve1 client = FlexNBD::FakeSource.new(@env.ip, @env.port1, 'Connecting to server failed') begin result = client.read_hello @@ -119,10 +119,7 @@ class TestServeMode < Test::Unit::TestCase def test_write_with_fua_is_accepted page_size = Integer(`getconf PAGESIZE`) - @env = Environment.new @env.blocksize = page_size * 10 - @env.writefile1('0') - @env.serve1 connect_to_server do |client| # Write somewhere in the third page pos = page_size * 3 + 100 From 79181b3153369dfaaacc6da3d54e1fe484afcf4d Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Wed, 7 Feb 2018 21:45:20 +0000 Subject: [PATCH 41/71] Added LD_PRELOAD library to monitor msync calls in testing --- Makefile | 4 +- tests/acceptance/ld_preloads/Makefile | 13 ++++++ tests/acceptance/ld_preloads/msync_catcher.c | 33 +++++++++++++++ tests/acceptance/test_serve_mode.rb | 44 ++++++++++++++++---- 4 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 tests/acceptance/ld_preloads/Makefile create mode 100644 tests/acceptance/ld_preloads/msync_catcher.c diff --git a/Makefile b/Makefile index b6b101f..f7d1e63 100644 --- a/Makefile +++ b/Makefile @@ -85,7 +85,8 @@ check: $(OBJS) $(CHECK_BINS) r=true ; for bin in $(CHECK_BINS); do $$bin || r=false; done ; $$r acceptance: build - cd tests/acceptance && RUBYOPT='-I.' ruby nbd_scenarios -v + $(MAKE) -C tests/acceptance/ld_preloads all + cd tests/acceptance && LD_PRELOADS=$$(echo ld_preloads/*.o) RUBYOPT='-I.' ruby nbd_scenarios -v test: check acceptance @@ -108,6 +109,7 @@ install: clean: rm -rf build/* + $(RM) $(LD_PRELOAD_OBJ) .PHONY: clean objs check_objs all server proxy check_bins check doc build test acceptance diff --git a/tests/acceptance/ld_preloads/Makefile b/tests/acceptance/ld_preloads/Makefile new file mode 100644 index 0000000..1c5f9ad --- /dev/null +++ b/tests/acceptance/ld_preloads/Makefile @@ -0,0 +1,13 @@ + +SRC := $(wildcard *.c) +OBJS := $(SRC:%.c=%.o) + +all: $(OBJS) + +clean: + $(RM) $(OBJS) + +%.o: %.c + gcc -shared -fPIC -ldl -o $@ $< + +.PHONY: all clean diff --git a/tests/acceptance/ld_preloads/msync_catcher.c b/tests/acceptance/ld_preloads/msync_catcher.c new file mode 100644 index 0000000..18ef284 --- /dev/null +++ b/tests/acceptance/ld_preloads/msync_catcher.c @@ -0,0 +1,33 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include + +typedef int (*real_msync_t)(void *addr, size_t length, int flags); + +int real_msync(void *addr, size_t length, int flags) { + return ((real_msync_t)dlsym(RTLD_NEXT, "msync"))(addr, length, flags); +} + +/* + * Noddy LD_PRELOAD wrapper to catch msync calls, and log them to a file. + */ + +int msync(void *addr, size_t length, int flags) { + FILE *fd; + char *fn; + int retval; + + retval = real_msync(addr, length, flags); + + fn = getenv("MSYNC_CATCHER_OUTPUT"); + if ( fn != NULL ) { + fd = fopen(fn,"a"); + fprintf(fd,"msync:%d:%i:%i:%i\n", addr, length, flags, retval); + fclose(fd); + } + + return retval; +} diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index e67da83..cdf3e58 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -1,6 +1,7 @@ require 'test/unit' require 'environment' require 'flexnbd/fake_source' +require 'tempfile' class TestServeMode < Test::Unit::TestCase def setup @@ -11,6 +12,7 @@ class TestServeMode < Test::Unit::TestCase def teardown @env.cleanup + teardown_msync_catcher super end @@ -37,6 +39,26 @@ class TestServeMode < Test::Unit::TestCase end end + def setup_msync_catcher + @msync_catcher = Tempfile.new('msync') + ENV['MSYNC_CATCHER_OUTPUT'] = @msync_catcher.path + end + + def parse_msync_output + op = [] + until @msync_catcher.eof? + op << @msync_catcher.readline.chomp.split(':').map do |e| + e =~ /^\d+$/ ? e.to_i : e + end + end + op + end + + def teardown_msync_catcher + @msync_catcher.close if @msync_catcher + ENV.delete 'MSYNC_CATCHER_OUTPUT' + end + def test_bad_request_magic_receives_error_response connect_to_server do |client| # replace REQUEST_MAGIC with all 0s to make it look bad @@ -109,15 +131,21 @@ class TestServeMode < Test::Unit::TestCase end def test_flush_is_accepted + setup_msync_catcher connect_to_server do |client| client.flush rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 0, rsp[:error] end + op = parse_msync_output + assert_equal 1, op.count, 'Only one msync expected' + assert_equal @env.blocksize, op.first[2], 'msync length wrong' + assert_equal 6, op.first[3], 'msync called with incorrect flags' end def test_write_with_fua_is_accepted + setup_msync_catcher page_size = Integer(`getconf PAGESIZE`) @env.blocksize = page_size * 10 connect_to_server do |client| @@ -127,13 +155,15 @@ class TestServeMode < Test::Unit::TestCase rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 0, rsp[:error] - # TODO: test offset and length - # Should be rounded to the third page - # assert_equal(msync_offset, page_size *3) - - # Should be 100 + 33, as we've started writing 100 bytes into a page, for - # 33 bytes - # assert_equal(msync_length, 133) end + + op = parse_msync_output + assert_equal 1, op.count, 'Only one msync expected' + + # Should be 100 + 33, as we've started writing 100 bytes into a page, for + # 33 bytes + assert_equal 133, op.first[2], 'msync length wrong' + assert_equal 6, op.first[3], 'msync called with incorrect flags' end + end From f71b87262242377d0fa2aeea8c0d24d3924d237f Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Wed, 7 Feb 2018 22:05:07 +0000 Subject: [PATCH 42/71] Only set up LD_PRELOAD for tests that actually need it. --- Makefile | 5 +---- tests/acceptance/test_serve_mode.rb | 11 ++++++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index f7d1e63..e8869db 100644 --- a/Makefile +++ b/Makefile @@ -85,8 +85,7 @@ check: $(OBJS) $(CHECK_BINS) r=true ; for bin in $(CHECK_BINS); do $$bin || r=false; done ; $$r acceptance: build - $(MAKE) -C tests/acceptance/ld_preloads all - cd tests/acceptance && LD_PRELOADS=$$(echo ld_preloads/*.o) RUBYOPT='-I.' ruby nbd_scenarios -v + cd tests/acceptance && RUBYOPT='-I.' ruby nbd_scenarios -v test: check acceptance @@ -109,8 +108,6 @@ install: clean: rm -rf build/* - $(RM) $(LD_PRELOAD_OBJ) - .PHONY: clean objs check_objs all server proxy check_bins check doc build test acceptance diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index cdf3e58..5aa8912 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -40,10 +40,17 @@ class TestServeMode < Test::Unit::TestCase end def setup_msync_catcher + `make -C ld_preloads/ msync_catcher.o` + omit 'LD_PRELOAD library not found' unless + File.exist?('ld_preloads/msync_catcher.o') + @msync_catcher = Tempfile.new('msync') ENV['MSYNC_CATCHER_OUTPUT'] = @msync_catcher.path + + @ld_preload_orig = ENV['LD_PRELOAD'] + ENV['LD_PRELOAD'] = 'ld_preloads/msync_catcher.o' end - + def parse_msync_output op = [] until @msync_catcher.eof? @@ -56,7 +63,9 @@ class TestServeMode < Test::Unit::TestCase def teardown_msync_catcher @msync_catcher.close if @msync_catcher + ENV.delete 'MSYNC_CATCHER_OUTPUT' + ENV['LD_PRELOAD'] = @ld_preload_orig end def test_bad_request_magic_receives_error_response From 8beb3f0af6633fdb67dc99fabcef00f6cd49cbb7 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Thu, 8 Feb 2018 13:19:51 +0000 Subject: [PATCH 43/71] Allow proxy to pass NBD protocol errors downstream; server returns EINVAL/ENOSPC appropriately Previously the proxy would just disconnect when it saw an NBD protocol error, and retry the operation it was in the middle of. Additionally, the server needs to return the correct error types when this happens. --- src/proxy/proxy.c | 5 ----- src/server/client.c | 13 ++++++++++--- tests/acceptance/proxy_tests.rb | 14 ++++++++++++++ tests/acceptance/test_serve_mode.rb | 24 ++++++++++++++++++++++-- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/proxy/proxy.c b/src/proxy/proxy.c index 8283d8c..b323c68 100644 --- a/src/proxy/proxy.c +++ b/src/proxy/proxy.c @@ -618,11 +618,6 @@ int proxy_read_from_upstream( struct proxier* proxy, int state ) goto disconnect; } - if ( reply->error != 0 ) { - warn( "NBD error returned from upstream: %"PRIu32, reply->error ); - goto disconnect; - } - if ( proxy->req_hdr.type == REQUEST_READ ) { /* Get the read reply data too. */ proxy->rsp.size += proxy->req_hdr.len; diff --git a/src/server/client.c b/src/server/client.c index 3a72cb9..8ca4d2a 100644 --- a/src/server/client.c +++ b/src/server/client.c @@ -391,7 +391,9 @@ int client_request_needs_reply( struct client * client, request.type, request.flags, request.from, request.len, request.handle ); - /* check it's not out of range */ + /* check it's not out of range. NBD protocol requires ENOSPC to be + * returned in this instance + */ if ( request.from+request.len > client->serve->size) { warn("write request %"PRIu64"+%"PRIu32" out of range", request.from, request.len @@ -399,7 +401,7 @@ int client_request_needs_reply( struct client * client, if ( request.type == REQUEST_WRITE ) { client_flush( client, request.len ); } - client_write_reply( client, &request, EPERM ); /* TODO: Change to ERANGE ? */ + client_write_reply( client, &request, ENOSPC ); client->disconnect = 0; return 0; } @@ -418,7 +420,12 @@ int client_request_needs_reply( struct client * client, case REQUEST_FLUSH: break; default: - fatal("Unknown request 0x%08X", request.type); + /* NBD prototcol says servers SHOULD return EINVAL to unknown + * commands */ + warn("Unknown request 0x%08X", request.type); + client_write_reply( client, &request, EINVAL ); + client->disconnect = 0; + return 0; } return 1; } diff --git a/tests/acceptance/proxy_tests.rb b/tests/acceptance/proxy_tests.rb index c2623d1..65fe38a 100644 --- a/tests/acceptance/proxy_tests.rb +++ b/tests/acceptance/proxy_tests.rb @@ -72,6 +72,20 @@ module ProxyTests end end + def test_write_request_past_end_of_disc_returns_to_client + with_proxied_client do |client| + n = 1000 + offset = n * 4096 + client.write(offset, b * 4096) + rsp = client.read_response + + assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] + assert_equal 'myhandle', rsp[:handle] + # NBD protocol say ENOSPC (28) in this situation + assert_equal 28, rsp[:error] + end + end + def make_fake_server server = FlexNBD::FakeDest.new(@env.ip, @env.port1) @server_up = true diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index 5aa8912..4f9a77e 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -112,7 +112,8 @@ class TestServeMode < Test::Unit::TestCase assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 'myhandle', rsp[:handle] - assert rsp[:error] != 0, "Server sent success reply back: #{rsp[:error]}" + # NBD protocol suggests ENOSPC (28) is returned + assert_equal 28, rsp[:error], 'Server sent incorrect response' # Ensure we're not disconnected by sending a request. We don't care about # whether the reply is good or not, here. @@ -129,7 +130,26 @@ class TestServeMode < Test::Unit::TestCase assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 'myhandle', rsp[:handle] - assert rsp[:error] != 0, "Server sent success reply back: #{rsp[:error]}" + # NBD protocol suggests ENOSPC (28) is returned + assert_equal 28, rsp[:error], 'Server sent incorrect response' + + # Ensure we're not disconnected by sending a request. We don't care about + # whether the reply is good or not, here. + client.write(0, "\x00" * @env.file1.size) + rsp = client.read_response + assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] + end + end + + def test_unknown_command_receives_error_response + connect_to_server do |client| + client.send_request(123) + rsp = client.read_response + + assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] + assert_equal 'myhandle', rsp[:handle] + # NBD protocol suggests EINVAL (22) is returned + assert_equal 22, rsp[:error], 'Server sent incorrect response' # Ensure we're not disconnected by sending a request. We don't care about # whether the reply is good or not, here. From 5e9dbbd626f3f34ba3effc25970a642b353d9974 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Thu, 8 Feb 2018 13:32:10 +0000 Subject: [PATCH 44/71] Updated changelgo --- debian/changelog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/debian/changelog b/debian/changelog index b05e74d..f25f071 100644 --- a/debian/changelog +++ b/debian/changelog @@ -10,6 +10,10 @@ flexnbd (0.2.0) UNRELEASED; urgency=medium [ Patrick J Cherry ] * Added FLUSH and FUA support (!38) + * Server returns ENOSPC in response to writes beyond the end of the + filesystem, and EINVAL to unknown commands. (#36, !40) + * Proxy passes all NBD protocol errors through to the client instead of + disconnecting and retrying (#36, !40) -- James Carter Thu, 11 Jan 2018 10:05:35 +0000 From f8fec5f57eeda78f4b35e5267a7601e97c6edb21 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Thu, 8 Feb 2018 15:46:34 +0000 Subject: [PATCH 45/71] Alter struct types to reflect reality, avoiding mixing "host" and "raw" structs --- debian/changelog | 1 + src/common/readwrite.c | 41 +++++++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/debian/changelog b/debian/changelog index f25f071..f08dc61 100644 --- a/debian/changelog +++ b/debian/changelog @@ -14,6 +14,7 @@ flexnbd (0.2.0) UNRELEASED; urgency=medium filesystem, and EINVAL to unknown commands. (#36, !40) * Proxy passes all NBD protocol errors through to the client instead of disconnecting and retrying (#36, !40) + * Fix struct types in readwrite.c (#35, !41) -- James Carter Thu, 11 Jan 2018 10:05:35 +0000 diff --git a/src/common/readwrite.c b/src/common/readwrite.c index 03bcb13..52521cc 100644 --- a/src/common/readwrite.c +++ b/src/common/readwrite.c @@ -106,14 +106,14 @@ int socket_nbd_write_hello( int fd, off64_t out_size, uint32_t out_flags ) return 1; } -void fill_request(struct nbd_request *request, uint16_t type, uint16_t flags, uint64_t from, uint32_t len) +void fill_request(struct nbd_request_raw *request_raw, uint16_t type, uint16_t flags, uint64_t from, uint32_t len) { - request->magic = htobe32(REQUEST_MAGIC); - request->type = htobe16(type); - request->flags = htobe16(flags); - request->handle.w = (((uint64_t)rand()) << 32) | ((uint64_t)rand()); - request->from = htobe64(from); - request->len = htobe32(len); + request_raw->magic = htobe32(REQUEST_MAGIC); + request_raw->type = htobe16(type); + request_raw->flags = htobe16(flags); + request_raw->handle.w = (((uint64_t)rand()) << 32) | ((uint64_t)rand()); + request_raw->from = htobe64(from); + request_raw->len = htobe32(len); } void read_reply(int fd, struct nbd_request *request, struct nbd_reply *reply) @@ -156,14 +156,17 @@ void wait_for_data( int fd, int timeout_secs ) void socket_nbd_read(int fd, uint64_t from, uint32_t len, int out_fd, void* out_buf, int timeout_secs) { - struct nbd_request request; - struct nbd_reply reply; + struct nbd_request_raw request_raw; + struct nbd_request request; + struct nbd_reply reply; - fill_request(&request, REQUEST_READ, 0, from, len); - FATAL_IF_NEGATIVE(writeloop(fd, &request, sizeof(request)), + fill_request(&request_raw, REQUEST_READ, 0, from, len); + FATAL_IF_NEGATIVE(writeloop(fd, &request_raw, sizeof(request)), "Couldn't write request"); + wait_for_data( fd, timeout_secs ); + nbd_r2h_request( &request_raw, &request ); read_reply(fd, &request, &reply); if (out_buf) { @@ -180,11 +183,12 @@ void socket_nbd_read(int fd, uint64_t from, uint32_t len, int out_fd, void* out_ void socket_nbd_write(int fd, uint64_t from, uint32_t len, int in_fd, void* in_buf, int timeout_secs) { - struct nbd_request request; - struct nbd_reply reply; + struct nbd_request_raw request_raw; + struct nbd_request request; + struct nbd_reply reply; - fill_request(&request, REQUEST_WRITE, 0, from, len); - ERROR_IF_NEGATIVE(writeloop(fd, &request, sizeof(request)), + fill_request(&request_raw, REQUEST_WRITE, 0, from, len); + ERROR_IF_NEGATIVE(writeloop(fd, &request_raw, sizeof(request_raw)), "Couldn't write request"); if (in_buf) { @@ -199,6 +203,7 @@ void socket_nbd_write(int fd, uint64_t from, uint32_t len, int in_fd, void* in_b } wait_for_data( fd, timeout_secs ); + nbd_r2h_request( &request_raw, &request ); read_reply(fd, &request, &reply); } @@ -206,13 +211,13 @@ void socket_nbd_write(int fd, uint64_t from, uint32_t len, int in_fd, void* in_b int socket_nbd_disconnect( int fd ) { int success = 1; - struct nbd_request request; + struct nbd_request_raw request_raw; - fill_request( &request, REQUEST_DISCONNECT, 0, 0, 0 ); + fill_request( &request_raw, REQUEST_DISCONNECT, 0, 0, 0 ); /* FIXME: This shouldn't be a FATAL error. We should just drop * the mirror without affecting the main server. */ - FATAL_IF_NEGATIVE( writeloop( fd, &request, sizeof( request ) ), + FATAL_IF_NEGATIVE( writeloop( fd, &request_raw, sizeof( request_raw ) ), "Failed to write the disconnect request." ); return success; } From 347b7978e44f7f6ac4618b260e367192cd9a7f49 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Thu, 8 Feb 2018 16:31:28 +0000 Subject: [PATCH 46/71] Discs must be sized in multiples of 512 bytes or odd things happen In #36 some of the odd errors were due to seeks beyond the end of the disc. This was because the disc was "specially crafted" to be 25GB + 1 byte, which doesn't fit into the normal 512 byte sectors expected of a disc. This lead to reads going beyond the end of the disc etc. If a similarly evil disc is used with `losetup`, it just ignores the last bytes of the disc that don't fit into 512 chunks. This is what that patch does, logging an error at the same time. --- src/common/ioutil.c | 9 +++++++++ src/server/serve.c | 9 +++++++++ tests/acceptance/test_serve_mode.rb | 14 ++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/common/ioutil.c b/src/common/ioutil.c index 4c1a4bd..1926e86 100644 --- a/src/common/ioutil.c +++ b/src/common/ioutil.c @@ -97,6 +97,15 @@ int open_and_mmap(const char* filename, int* out_fd, uint64_t *out_size, void ** warn("lseek64() failed"); return size; } + + /* If discs are not in multiples of 512, then odd things happen, + * resulting in reads/writes past the ends of files. + */ + if ( size != (size & (~0x1ff))) { + warn("file does not fit into 512-byte sectors; the end of the file will be ignored."); + size = size & (~0x1ff); + } + if (out_size) { *out_size = size; } diff --git a/src/server/serve.c b/src/server/serve.c index d88e9f4..3a86c3a 100644 --- a/src/server/serve.c +++ b/src/server/serve.c @@ -710,6 +710,15 @@ void serve_init_allocation_map(struct server* params) FATAL_IF_NEGATIVE(fd, "Couldn't open %s", params->filename ); size = lseek64( fd, 0, SEEK_END ); + + /* If discs are not in multiples of 512, then odd things happen, + * resulting in reads/writes past the ends of files. + */ + if ( size != (size & ~0x1ff)) { + warn("file does not fit into 512-byte sectors; the end of the file will be ignored."); + size &= ~0x1ff; + } + params->size = size; FATAL_IF_NEGATIVE( size, "Couldn't find size of %s", params->filename ); diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index 4f9a77e..2299584 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -195,4 +195,18 @@ class TestServeMode < Test::Unit::TestCase assert_equal 6, op.first[3], 'msync called with incorrect flags' end + def test_odd_size_discs_are_truncated_to_nearest_512 + # This should get rounded down to 1024 + @env.blocksize = 1024 + 511 + @env.writefile1('0') + @env.serve1 + client = FlexNBD::FakeSource.new(@env.ip, @env.port1, 'Connecting to server failed') + begin + result = client.read_hello + assert_equal 'NBDMAGIC', result[:passwd] + assert_equal 0x00420281861253, result[:magic] + assert_equal 1024, result[:size] + client.close + end + end end From 23d9ff587e9765dd19a1059ba9c14f1d2088ca0d Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Thu, 8 Feb 2018 16:36:20 +0000 Subject: [PATCH 47/71] Updated changelog --- debian/changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/changelog b/debian/changelog index f25f071..c29ecde 100644 --- a/debian/changelog +++ b/debian/changelog @@ -14,6 +14,7 @@ flexnbd (0.2.0) UNRELEASED; urgency=medium filesystem, and EINVAL to unknown commands. (#36, !40) * Proxy passes all NBD protocol errors through to the client instead of disconnecting and retrying (#36, !40) + * Ignore ends of discs that stray outside of 512-byte sector sizes (!42). -- James Carter Thu, 11 Jan 2018 10:05:35 +0000 From a19267b377d2fe435d2e34b2a08bd7c9e390f830 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Thu, 8 Feb 2018 16:37:36 +0000 Subject: [PATCH 48/71] Adjust block-rounding line to match in serve.c --- src/common/ioutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/ioutil.c b/src/common/ioutil.c index 1926e86..dfa47df 100644 --- a/src/common/ioutil.c +++ b/src/common/ioutil.c @@ -103,7 +103,7 @@ int open_and_mmap(const char* filename, int* out_fd, uint64_t *out_size, void ** */ if ( size != (size & (~0x1ff))) { warn("file does not fit into 512-byte sectors; the end of the file will be ignored."); - size = size & (~0x1ff); + size &= ~0x1ff; } if (out_size) { From ebacf738bc6e74990a98d73a0c7cab5dd3306fde Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Thu, 8 Feb 2018 22:28:34 +0000 Subject: [PATCH 49/71] Tidy up ld preload hacks --- tests/acceptance/ld_preload.rb | 36 +++++++ .../{msync_catcher.c => msync_logger.c} | 2 +- tests/acceptance/test_serve_mode.rb | 93 ++++++++----------- 3 files changed, 74 insertions(+), 57 deletions(-) create mode 100644 tests/acceptance/ld_preload.rb rename tests/acceptance/ld_preloads/{msync_catcher.c => msync_logger.c} (94%) diff --git a/tests/acceptance/ld_preload.rb b/tests/acceptance/ld_preload.rb new file mode 100644 index 0000000..9cc5a14 --- /dev/null +++ b/tests/acceptance/ld_preload.rb @@ -0,0 +1,36 @@ +require 'tempfile' + +# LdPreload is a little wrapper for using LD_PRELOAD when testing flexnbd +module LdPreload + # This takes an object name, sets up a temporary log file, whose name is + # recorded in the environment as OUTPUT_obj_name, where obj_name is the + # name of the preload module to build and load. + def with_ld_preload(obj_name) + @ld_preload_logs ||= {} + flunk 'Can only load a preload module once!' if @ld_preload_logs[obj_name] + + system("make -C ld_preloads/ #{obj_name}.o > /dev/null") || + flunk("Failed to build object #{obj_name}") + orig_env = ENV['LD_PRELOAD'] + ENV['LD_PRELOAD'] = [orig_env, File.expand_path("./ld_preloads/#{obj_name}.o")].compact.join(' ') + + # Open the log, and stick it in a hash + @ld_preload_logs[obj_name] = Tempfile.new(obj_name) + ENV['OUTPUT_' + obj_name] = @ld_preload_logs[obj_name].path + + yield + ensure + if @ld_preload_logs[obj_name] + @ld_preload_logs[obj_name].close + @ld_preload_logs.delete(obj_name) + end + ENV['LD_PRELOAD'] = orig_env + end + + def read_ld_preload_log(obj_name) + lines = [] + lines << @ld_preload_logs[obj_name].readline.chomp until + @ld_preload_logs[obj_name].eof? + lines + end +end diff --git a/tests/acceptance/ld_preloads/msync_catcher.c b/tests/acceptance/ld_preloads/msync_logger.c similarity index 94% rename from tests/acceptance/ld_preloads/msync_catcher.c rename to tests/acceptance/ld_preloads/msync_logger.c index 18ef284..73543cd 100644 --- a/tests/acceptance/ld_preloads/msync_catcher.c +++ b/tests/acceptance/ld_preloads/msync_logger.c @@ -22,7 +22,7 @@ int msync(void *addr, size_t length, int flags) { retval = real_msync(addr, length, flags); - fn = getenv("MSYNC_CATCHER_OUTPUT"); + fn = getenv("OUTPUT_msync_logger"); if ( fn != NULL ) { fd = fopen(fn,"a"); fprintf(fd,"msync:%d:%i:%i:%i\n", addr, length, flags, retval); diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index 2299584..8a451ce 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -1,9 +1,11 @@ require 'test/unit' require 'environment' require 'flexnbd/fake_source' -require 'tempfile' +require 'ld_preload' class TestServeMode < Test::Unit::TestCase + include LdPreload + def setup super @b = "\xFF".b @@ -12,7 +14,6 @@ class TestServeMode < Test::Unit::TestCase def teardown @env.cleanup - teardown_msync_catcher super end @@ -39,33 +40,10 @@ class TestServeMode < Test::Unit::TestCase end end - def setup_msync_catcher - `make -C ld_preloads/ msync_catcher.o` - omit 'LD_PRELOAD library not found' unless - File.exist?('ld_preloads/msync_catcher.o') - - @msync_catcher = Tempfile.new('msync') - ENV['MSYNC_CATCHER_OUTPUT'] = @msync_catcher.path - - @ld_preload_orig = ENV['LD_PRELOAD'] - ENV['LD_PRELOAD'] = 'ld_preloads/msync_catcher.o' - end - - def parse_msync_output - op = [] - until @msync_catcher.eof? - op << @msync_catcher.readline.chomp.split(':').map do |e| - e =~ /^\d+$/ ? e.to_i : e - end + def parse_msync_logs + read_ld_preload_log('msync_logger').map do |l| + l.split(':').map { |i| i =~ /^\d+$/ ? i.to_i : i } end - op - end - - def teardown_msync_catcher - @msync_catcher.close if @msync_catcher - - ENV.delete 'MSYNC_CATCHER_OUTPUT' - ENV['LD_PRELOAD'] = @ld_preload_orig end def test_bad_request_magic_receives_error_response @@ -160,39 +138,42 @@ class TestServeMode < Test::Unit::TestCase end def test_flush_is_accepted - setup_msync_catcher - connect_to_server do |client| - client.flush - rsp = client.read_response - assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] - assert_equal 0, rsp[:error] + with_ld_preload('msync_logger') do + connect_to_server do |client| + client.flush + rsp = client.read_response + assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] + assert_equal 0, rsp[:error] + end + op = parse_msync_logs + assert_equal 1, op.count, 'Only one msync expected' + assert_equal @env.blocksize, op.first[2], 'msync length wrong' + assert_equal 6, op.first[3], 'msync called with incorrect flags' end - op = parse_msync_output - assert_equal 1, op.count, 'Only one msync expected' - assert_equal @env.blocksize, op.first[2], 'msync length wrong' - assert_equal 6, op.first[3], 'msync called with incorrect flags' end def test_write_with_fua_is_accepted - setup_msync_catcher - page_size = Integer(`getconf PAGESIZE`) - @env.blocksize = page_size * 10 - connect_to_server do |client| - # Write somewhere in the third page - pos = page_size * 3 + 100 - client.write_with_fua(pos, "\x00" * 33) - rsp = client.read_response - assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] - assert_equal 0, rsp[:error] + with_ld_preload('msync_logger') do + page_size = Integer(`getconf PAGESIZE`) + + @env.blocksize = page_size * 10 + connect_to_server do |client| + # Write somewhere in the third page + pos = page_size * 3 + 100 + client.write_with_fua(pos, "\x00" * 33) + rsp = client.read_response + assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] + assert_equal 0, rsp[:error] + end + op = parse_msync_logs + + assert_equal 1, op.count, 'Only one msync expected' + + # Should be 100 + 33, as we've started writing 100 bytes into a page, for + # 33 bytes + assert_equal 133, op.first[2], 'msync length wrong' + assert_equal 6, op.first[3], 'msync called with incorrect flags' end - - op = parse_msync_output - assert_equal 1, op.count, 'Only one msync expected' - - # Should be 100 + 33, as we've started writing 100 bytes into a page, for - # 33 bytes - assert_equal 133, op.first[2], 'msync length wrong' - assert_equal 6, op.first[3], 'msync called with incorrect flags' end def test_odd_size_discs_are_truncated_to_nearest_512 From c053a54faacff6c5cd9aa1ead0e3a17e9a8e93eb Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Thu, 8 Feb 2018 23:07:17 +0000 Subject: [PATCH 50/71] Added test to cover setsockopt for tcpkeepalive --- tests/acceptance/ld_preload.rb | 6 ++++ .../ld_preloads/setsockopt_logger.c | 34 +++++++++++++++++++ tests/acceptance/test_serve_mode.rb | 21 +++++++----- 3 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 tests/acceptance/ld_preloads/setsockopt_logger.c diff --git a/tests/acceptance/ld_preload.rb b/tests/acceptance/ld_preload.rb index 9cc5a14..6ebf3cc 100644 --- a/tests/acceptance/ld_preload.rb +++ b/tests/acceptance/ld_preload.rb @@ -33,4 +33,10 @@ module LdPreload @ld_preload_logs[obj_name].eof? lines end + + def parse_ld_preload_logs(obj_name) + read_ld_preload_log(obj_name).map do |l| + l.split(':').map { |i| i =~ /^\d+$/ ? i.to_i : i } + end + end end diff --git a/tests/acceptance/ld_preloads/setsockopt_logger.c b/tests/acceptance/ld_preloads/setsockopt_logger.c new file mode 100644 index 0000000..08f3142 --- /dev/null +++ b/tests/acceptance/ld_preloads/setsockopt_logger.c @@ -0,0 +1,34 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include + +typedef int (*real_setsockopt_t)(int sockfd, int level, int optname, const void *optval, socklen_t optlen); + +int real_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) +{ + return ((real_setsockopt_t)dlsym(RTLD_NEXT, "setsockopt"))(sockfd, level, optname, optval, optlen); +} + +/* + * Noddy LD_PRELOAD wrapper to catch setsockopt calls, and log them to a file. + */ + +int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) +{ + FILE *fd; + char *fn; + int retval; + + retval = real_setsockopt(sockfd, level, optname, optval, optlen); + fn = getenv("OUTPUT_setsockopt_logger"); + if ( fn != NULL && optval != NULL && optlen == 4) { + fd = fopen(fn,"a"); + fprintf(fd,"setsockopt:%d:%d:%i:%d\n", level, optname, *(int *)optval, retval); + fclose(fd); + } + + return retval; +} diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index 8a451ce..cc392d6 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -40,12 +40,6 @@ class TestServeMode < Test::Unit::TestCase end end - def parse_msync_logs - read_ld_preload_log('msync_logger').map do |l| - l.split(':').map { |i| i =~ /^\d+$/ ? i.to_i : i } - end - end - def test_bad_request_magic_receives_error_response connect_to_server do |client| # replace REQUEST_MAGIC with all 0s to make it look bad @@ -145,7 +139,7 @@ class TestServeMode < Test::Unit::TestCase assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 0, rsp[:error] end - op = parse_msync_logs + op = parse_ld_preload_logs('msync_logger') assert_equal 1, op.count, 'Only one msync expected' assert_equal @env.blocksize, op.first[2], 'msync length wrong' assert_equal 6, op.first[3], 'msync called with incorrect flags' @@ -165,7 +159,7 @@ class TestServeMode < Test::Unit::TestCase assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 0, rsp[:error] end - op = parse_msync_logs + op = parse_ld_preload_logs('msync_logger') assert_equal 1, op.count, 'Only one msync expected' @@ -190,4 +184,15 @@ class TestServeMode < Test::Unit::TestCase client.close end end + + def test_server_sets_tcpkeepalive + with_ld_preload('setsockopt_logger') do + connect_to_server(&:close) + op = parse_ld_preload_logs('setsockopt_logger') + assert(op.any? { |e| e == ['setsockopt', Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1, 0] }, 'TCP Keepalive not successfully set') + assert(op.any? { |e| e == ['setsockopt', Socket::SOL_TCP, Socket::TCP_KEEPIDLE, 30, 0] }, 'TCP Keepalive idle timeout not set to 30s') + assert(op.any? { |e| e == ['setsockopt', Socket::SOL_TCP, Socket::TCP_KEEPINTVL, 10, 0] }, 'TCP keepalive retry time not set to 10s') + assert(op.any? { |e| e == ['setsockopt', Socket::SOL_TCP, Socket::TCP_KEEPCNT, 3, 0] }, 'TCP keepalive count not set to 3') + end + end end From 8e671809991e0c78b3bc8dabd12fca6c64ec9108 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 9 Feb 2018 10:26:08 +0000 Subject: [PATCH 51/71] Check that TCP_NODELAY is set on upstream sockets on reconnection Also rationalize the test to see if a function has been called. Still not great, but getting there :) --- tests/acceptance/ld_preload.rb | 5 ++ .../ld_preloads/setsockopt_logger.c | 2 +- tests/acceptance/proxy_tests.rb | 75 +++++++++++-------- tests/acceptance/test_proxy_mode.rb | 3 + tests/acceptance/test_serve_mode.rb | 22 ++++-- 5 files changed, 70 insertions(+), 37 deletions(-) diff --git a/tests/acceptance/ld_preload.rb b/tests/acceptance/ld_preload.rb index 6ebf3cc..8ce0a8f 100644 --- a/tests/acceptance/ld_preload.rb +++ b/tests/acceptance/ld_preload.rb @@ -39,4 +39,9 @@ module LdPreload l.split(':').map { |i| i =~ /^\d+$/ ? i.to_i : i } end end + + def assert_func_call(loglines, args, msg) + re = Regexp.new('^' + args.join(':')) + assert(loglines.any? { |l| l.match(re) }, msg) + end end diff --git a/tests/acceptance/ld_preloads/setsockopt_logger.c b/tests/acceptance/ld_preloads/setsockopt_logger.c index 08f3142..9a7bf60 100644 --- a/tests/acceptance/ld_preloads/setsockopt_logger.c +++ b/tests/acceptance/ld_preloads/setsockopt_logger.c @@ -26,7 +26,7 @@ int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t fn = getenv("OUTPUT_setsockopt_logger"); if ( fn != NULL && optval != NULL && optlen == 4) { fd = fopen(fn,"a"); - fprintf(fd,"setsockopt:%d:%d:%i:%d\n", level, optname, *(int *)optval, retval); + fprintf(fd,"setsockopt:%d:%d:%d:%i:%d\n", sockfd, level, optname, *(int *)optval, retval); fclose(fd); } diff --git a/tests/acceptance/proxy_tests.rb b/tests/acceptance/proxy_tests.rb index 65fe38a..ab68f44 100644 --- a/tests/acceptance/proxy_tests.rb +++ b/tests/acceptance/proxy_tests.rb @@ -147,45 +147,58 @@ module ProxyTests def test_write_request_retried_when_upstream_dies_partway maker = make_fake_server - with_proxied_client(4096) do |client| - server, sc1 = maker.value + with_ld_preload('setsockopt_logger') do + with_proxied_client(4096) do |client| + server, sc1 = maker.value - # Send the read request to the proxy - client.write(0, (b * 4096)) + # Send the read request to the proxy + client.write(0, (b * 4096)) - # ensure we're given the read request - req1 = sc1.read_request - assert_equal ::FlexNBD::REQUEST_MAGIC, req1[:magic] - assert_equal ::FlexNBD::REQUEST_WRITE, req1[:type] - assert_equal 0, req1[:from] - assert_equal 4096, req1[:len] - data1 = sc1.read_data(4096) - assert_equal((b * 4096), data1, 'Data not proxied successfully') + # ensure we're given the read request + req1 = sc1.read_request + assert_equal ::FlexNBD::REQUEST_MAGIC, req1[:magic] + assert_equal ::FlexNBD::REQUEST_WRITE, req1[:type] + assert_equal 0, req1[:from] + assert_equal 4096, req1[:len] + data1 = sc1.read_data(4096) + assert_equal((b * 4096), data1, 'Data not proxied successfully') - # Kill the server again, now we're sure the read request has been sent once - sc1.close + # Read the setsockopt logs, so we can check that TCP_NODELAY is re-set + # later + read_ld_preload_log('setsockopt_logger') - # We expect the proxy to reconnect without our client doing anything. - sc2 = server.accept - sc2.write_hello + # Kill the server again, now we're sure the read request has been sent once + sc1.close - # And once reconnected, it should resend an identical request. - req2 = sc2.read_request - assert_equal req1, req2 - data2 = sc2.read_data(4096) - assert_equal data1, data2 + # We expect the proxy to reconnect without our client doing anything. + sc2 = server.accept + sc2.write_hello - # The reply should be proxied back to the client. - sc2.write_reply(req2[:handle]) + # And once reconnected, it should resend an identical request. + req2 = sc2.read_request + assert_equal req1, req2 + data2 = sc2.read_data(4096) + assert_equal data1, data2 - # Check it to make sure it's correct - rsp = Timeout.timeout(15) { client.read_response } - assert_equal ::FlexNBD::REPLY_MAGIC, rsp[:magic] - assert_equal 0, rsp[:error] - assert_equal req1[:handle], rsp[:handle] + # The reply should be proxied back to the client. + sc2.write_reply(req2[:handle]) - sc2.close - server.close + # Check it to make sure it's correct + rsp = Timeout.timeout(15) { client.read_response } + assert_equal ::FlexNBD::REPLY_MAGIC, rsp[:magic] + assert_equal 0, rsp[:error] + assert_equal req1[:handle], rsp[:handle] + + sc2.close + server.close + + # Check TCP_NODELAY was set on the upstream socket + log = read_ld_preload_log('setsockopt_logger') + assert_func_call(log, + ['setsockopt', 3, + Socket::SOL_TCP, Socket::TCP_NODELAY, 1, 0], + 'TCP_NODELAY not set on upstream fd 3') + end end end diff --git a/tests/acceptance/test_proxy_mode.rb b/tests/acceptance/test_proxy_mode.rb index 87d10e2..d2e98c1 100644 --- a/tests/acceptance/test_proxy_mode.rb +++ b/tests/acceptance/test_proxy_mode.rb @@ -1,8 +1,11 @@ require 'test/unit' require 'environment' +require 'ld_preload' require 'proxy_tests' class TestProxyMode < Test::Unit::TestCase + + include LdPreload include ProxyTests def setup diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index cc392d6..6c3e3f6 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -188,11 +188,23 @@ class TestServeMode < Test::Unit::TestCase def test_server_sets_tcpkeepalive with_ld_preload('setsockopt_logger') do connect_to_server(&:close) - op = parse_ld_preload_logs('setsockopt_logger') - assert(op.any? { |e| e == ['setsockopt', Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1, 0] }, 'TCP Keepalive not successfully set') - assert(op.any? { |e| e == ['setsockopt', Socket::SOL_TCP, Socket::TCP_KEEPIDLE, 30, 0] }, 'TCP Keepalive idle timeout not set to 30s') - assert(op.any? { |e| e == ['setsockopt', Socket::SOL_TCP, Socket::TCP_KEEPINTVL, 10, 0] }, 'TCP keepalive retry time not set to 10s') - assert(op.any? { |e| e == ['setsockopt', Socket::SOL_TCP, Socket::TCP_KEEPCNT, 3, 0] }, 'TCP keepalive count not set to 3') + op = read_ld_preload_log('setsockopt_logger') + assert_func_call(op, + ['setsockopt', '\d+', + Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1, 0], + 'TCP Keepalive not successfully set') + assert_func_call(op, + ['setsockopt', '\d+', + Socket::SOL_TCP, Socket::TCP_KEEPIDLE, 30, 0], + 'TCP Keepalive idle timeout not set to 30s') + assert_func_call(op, + ['setsockopt', '\d+', + Socket::SOL_TCP, Socket::TCP_KEEPINTVL, 10, 0], + 'TCP keepalive retry time not set to 10s') + assert_func_call(op, + ['setsockopt', '\d+', + Socket::SOL_TCP, Socket::TCP_KEEPCNT, 3, 0], + 'TCP keepalive count not set to 3') end end end From b75a6529d0ca0cd2d5f2bfcbcf7a4238b25e6075 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 9 Feb 2018 10:41:24 +0000 Subject: [PATCH 52/71] Move LdPreload include to correct place --- tests/acceptance/proxy_tests.rb | 4 ++++ tests/acceptance/test_proxy_mode.rb | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/acceptance/proxy_tests.rb b/tests/acceptance/proxy_tests.rb index ab68f44..92648b5 100644 --- a/tests/acceptance/proxy_tests.rb +++ b/tests/acceptance/proxy_tests.rb @@ -1,8 +1,12 @@ require 'flexnbd/fake_source' require 'flexnbd/fake_dest' +require 'ld_preload' module ProxyTests + + include LdPreload + def b "\xFF".b end diff --git a/tests/acceptance/test_proxy_mode.rb b/tests/acceptance/test_proxy_mode.rb index d2e98c1..da0db90 100644 --- a/tests/acceptance/test_proxy_mode.rb +++ b/tests/acceptance/test_proxy_mode.rb @@ -1,11 +1,9 @@ require 'test/unit' require 'environment' -require 'ld_preload' require 'proxy_tests' class TestProxyMode < Test::Unit::TestCase - include LdPreload include ProxyTests def setup From 195de41d86bbdd2564c3db31436486912f06fb40 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 9 Feb 2018 11:32:26 +0000 Subject: [PATCH 53/71] Remove extra line --- tests/acceptance/test_proxy_mode.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/acceptance/test_proxy_mode.rb b/tests/acceptance/test_proxy_mode.rb index da0db90..87d10e2 100644 --- a/tests/acceptance/test_proxy_mode.rb +++ b/tests/acceptance/test_proxy_mode.rb @@ -3,7 +3,6 @@ require 'environment' require 'proxy_tests' class TestProxyMode < Test::Unit::TestCase - include ProxyTests def setup From 9817fd7b0ac2fdd744bd39fdcabcbca94376b8e0 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 9 Feb 2018 11:42:25 +0000 Subject: [PATCH 54/71] Final tidies, comments etc. --- tests/acceptance/ld_preload.rb | 10 +++++++++- tests/acceptance/ld_preloads/setsockopt_logger.c | 14 +++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/tests/acceptance/ld_preload.rb b/tests/acceptance/ld_preload.rb index 8ce0a8f..405660e 100644 --- a/tests/acceptance/ld_preload.rb +++ b/tests/acceptance/ld_preload.rb @@ -1,7 +1,11 @@ require 'tempfile' -# LdPreload is a little wrapper for using LD_PRELOAD when testing flexnbd +# +# LdPreload is a little wrapper for using LD_PRELOAD loggers to pick up system +# calls when testing flexnbd. +# module LdPreload + # # This takes an object name, sets up a temporary log file, whose name is # recorded in the environment as OUTPUT_obj_name, where obj_name is the # name of the preload module to build and load. @@ -34,6 +38,10 @@ module LdPreload lines end + # + # The next to methods assume the log file has one entry per line, and that + # each entry is a series of values separated by colons. + # def parse_ld_preload_logs(obj_name) read_ld_preload_log(obj_name).map do |l| l.split(':').map { |i| i =~ /^\d+$/ ? i.to_i : i } diff --git a/tests/acceptance/ld_preloads/setsockopt_logger.c b/tests/acceptance/ld_preloads/setsockopt_logger.c index 9a7bf60..d2cc021 100644 --- a/tests/acceptance/ld_preloads/setsockopt_logger.c +++ b/tests/acceptance/ld_preloads/setsockopt_logger.c @@ -5,6 +5,10 @@ #include #include +/* + * Noddy LD_PRELOAD wrapper to catch setsockopt calls, and log them to a file. + */ + typedef int (*real_setsockopt_t)(int sockfd, int level, int optname, const void *optval, socklen_t optlen); int real_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) @@ -12,10 +16,6 @@ int real_setsockopt(int sockfd, int level, int optname, const void *optval, sock return ((real_setsockopt_t)dlsym(RTLD_NEXT, "setsockopt"))(sockfd, level, optname, optval, optlen); } -/* - * Noddy LD_PRELOAD wrapper to catch setsockopt calls, and log them to a file. - */ - int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) { FILE *fd; @@ -24,9 +24,13 @@ int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t retval = real_setsockopt(sockfd, level, optname, optval, optlen); fn = getenv("OUTPUT_setsockopt_logger"); + + /* + * Only interested in catching non-null 4-byte (integer) values + */ if ( fn != NULL && optval != NULL && optlen == 4) { fd = fopen(fn,"a"); - fprintf(fd,"setsockopt:%d:%d:%d:%i:%d\n", sockfd, level, optname, *(int *)optval, retval); + fprintf(fd,"setsockopt:%i:%i:%i:%i:%i\n", sockfd, level, optname, *(int *)optval, retval); fclose(fd); } From 21f384e3437405b55b2c573fc10d1073996670e8 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 9 Feb 2018 11:44:28 +0000 Subject: [PATCH 55/71] Updated changelog --- debian/changelog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/changelog b/debian/changelog index c29ecde..9d64851 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,6 +15,8 @@ flexnbd (0.2.0) UNRELEASED; urgency=medium * Proxy passes all NBD protocol errors through to the client instead of disconnecting and retrying (#36, !40) * Ignore ends of discs that stray outside of 512-byte sector sizes (!42). + * Added tests for setting TCP_NODELAY on upstream-reconnections in the + proxy, and refactored the other LD_PRELOAD tests (!43) -- James Carter Thu, 11 Jan 2018 10:05:35 +0000 From 169d40f575076b3fda0b6e016fe2dc5c8d144bdd Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 9 Feb 2018 11:57:07 +0000 Subject: [PATCH 56/71] Increase log level for readloop failures, which might help with diagnosis --- debian/changelog | 1 + src/server/client.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index c29ecde..df929fd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,6 +15,7 @@ flexnbd (0.2.0) UNRELEASED; urgency=medium * Proxy passes all NBD protocol errors through to the client instead of disconnecting and retrying (#36, !40) * Ignore ends of discs that stray outside of 512-byte sector sizes (!42). + * Tweak logging for readloop failures (!44) -- James Carter Thu, 11 Jan 2018 10:05:35 +0000 diff --git a/src/server/client.c b/src/server/client.c index 8ca4d2a..fe8a0a5 100644 --- a/src/server/client.c +++ b/src/server/client.c @@ -228,14 +228,14 @@ int client_read_request( struct client * client , struct nbd_request *out_reques *disconnected = 1; switch( errno ){ case 0: - debug( "EOF while reading request" ); + warn( "EOF while reading request" ); return 0; case ECONNRESET: - debug( "Connection reset while" + warn( "Connection reset while" " reading request" ); return 0; case ETIMEDOUT: - debug( "Connection timed out while" + warn( "Connection timed out while" " reading request" ); return 0; default: From cdcd5275444d8ace0375946589bf9abeaea5d18d Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 9 Feb 2018 12:18:34 +0000 Subject: [PATCH 57/71] Refactored read_reply to compare the network-byte-ordered handle --- src/common/readwrite.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/common/readwrite.c b/src/common/readwrite.c index 52521cc..414c169 100644 --- a/src/common/readwrite.c +++ b/src/common/readwrite.c @@ -116,7 +116,7 @@ void fill_request(struct nbd_request_raw *request_raw, uint16_t type, uint16_t f request_raw->len = htobe32(len); } -void read_reply(int fd, struct nbd_request *request, struct nbd_reply *reply) +void read_reply(int fd, uint64_t request_raw_handle, struct nbd_reply *reply) { struct nbd_reply_raw reply_raw; @@ -131,7 +131,7 @@ void read_reply(int fd, struct nbd_request *request, struct nbd_reply *reply) if (reply->error != 0) { error("Server replied with error %d", reply->error); } - if (request->handle.w != reply->handle.w) { + if (request_raw_handle != reply_raw.handle.w) { error("Did not reply with correct handle"); } } @@ -157,17 +157,15 @@ void wait_for_data( int fd, int timeout_secs ) void socket_nbd_read(int fd, uint64_t from, uint32_t len, int out_fd, void* out_buf, int timeout_secs) { struct nbd_request_raw request_raw; - struct nbd_request request; struct nbd_reply reply; fill_request(&request_raw, REQUEST_READ, 0, from, len); - FATAL_IF_NEGATIVE(writeloop(fd, &request_raw, sizeof(request)), + FATAL_IF_NEGATIVE(writeloop(fd, &request_raw, sizeof(request_raw)), "Couldn't write request"); wait_for_data( fd, timeout_secs ); - nbd_r2h_request( &request_raw, &request ); - read_reply(fd, &request, &reply); + read_reply(fd, request_raw.handle.w, &reply); if (out_buf) { FATAL_IF_NEGATIVE(readloop(fd, out_buf, len), @@ -184,7 +182,6 @@ void socket_nbd_read(int fd, uint64_t from, uint32_t len, int out_fd, void* out_ void socket_nbd_write(int fd, uint64_t from, uint32_t len, int in_fd, void* in_buf, int timeout_secs) { struct nbd_request_raw request_raw; - struct nbd_request request; struct nbd_reply reply; fill_request(&request_raw, REQUEST_WRITE, 0, from, len); @@ -203,8 +200,7 @@ void socket_nbd_write(int fd, uint64_t from, uint32_t len, int in_fd, void* in_b } wait_for_data( fd, timeout_secs ); - nbd_r2h_request( &request_raw, &request ); - read_reply(fd, &request, &reply); + read_reply(fd, request_raw.handle.w, &reply); } From 1c66b56af1b4961a4a7c765e546f438745ed2a66 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Mon, 12 Feb 2018 19:04:29 +0000 Subject: [PATCH 58/71] Update proxy malloc to add the struct size onto the request/response buffer This alters the meaning of NBD_MAX_SIZE to be the actual max request size we'll accept over nbd. Previously it was *nearly* the max size we'd accept depending on the size of the struct. --- src/proxy/proxy.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/proxy/proxy.c b/src/proxy/proxy.c index b323c68..951542c 100644 --- a/src/proxy/proxy.c +++ b/src/proxy/proxy.c @@ -76,8 +76,12 @@ struct proxier* proxy_create( } out->init.buf = xmalloc( sizeof( struct nbd_init_raw ) ); - out->req.buf = xmalloc( NBD_MAX_SIZE ); - out->rsp.buf = xmalloc( NBD_MAX_SIZE ); + + /* Add on the request / response size to our malloc to accommodate both + * the struct and the data + */ + out->req.buf = xmalloc( NBD_MAX_SIZE + NBD_REQUEST_SIZE ); + out->rsp.buf = xmalloc( NBD_MAX_SIZE + NBD_RESPONSE_SIZE ); log_context = xmalloc( strlen(s_upstream_address) + strlen(s_upstream_port) + 2 ); sprintf(log_context, "%s:%s", s_upstream_address, s_upstream_port); @@ -452,15 +456,18 @@ int proxy_read_from_downstream( struct proxier *proxy, int state ) return EXIT; } - /* Simple validations */ + /* Simple validations -- the request / reply size have already + * been taken into account in the xmalloc, so no need to worry + * about them here + */ if ( request->type == REQUEST_READ ) { - if (request->len > ( NBD_MAX_SIZE - NBD_REPLY_SIZE ) ) { + if ( request->len > NBD_MAX_SIZE ) { warn( "NBD read request size %"PRIu32" too large", request->len ); return EXIT; } } if ( request->type == REQUEST_WRITE ) { - if (request->len > ( NBD_MAX_SIZE - NBD_REQUEST_SIZE ) ) { + if ( request->len > NBD_MAX_SIZE ) { warn( "NBD write request size %"PRIu32" too large", request->len ); return EXIT; } From 158379ba7a3f09a7855399a0e653a8a5c5f770a6 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Mon, 12 Feb 2018 19:11:24 +0000 Subject: [PATCH 59/71] Use correct constant name. --- src/proxy/proxy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/proxy/proxy.c b/src/proxy/proxy.c index 951542c..291acd6 100644 --- a/src/proxy/proxy.c +++ b/src/proxy/proxy.c @@ -77,11 +77,11 @@ struct proxier* proxy_create( out->init.buf = xmalloc( sizeof( struct nbd_init_raw ) ); - /* Add on the request / response size to our malloc to accommodate both + /* Add on the request / reply size to our malloc to accommodate both * the struct and the data */ out->req.buf = xmalloc( NBD_MAX_SIZE + NBD_REQUEST_SIZE ); - out->rsp.buf = xmalloc( NBD_MAX_SIZE + NBD_RESPONSE_SIZE ); + out->rsp.buf = xmalloc( NBD_MAX_SIZE + NBD_REPLY_SIZE ); log_context = xmalloc( strlen(s_upstream_address) + strlen(s_upstream_port) + 2 ); sprintf(log_context, "%s:%s", s_upstream_address, s_upstream_port); From bb1f6ecdf5eea5e59725f4e96d4635da03fbe5da Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 13 Feb 2018 15:51:09 +0000 Subject: [PATCH 60/71] Updated changelog --- debian/changelog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/changelog b/debian/changelog index c29ecde..5ef9dbb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,6 +15,8 @@ flexnbd (0.2.0) UNRELEASED; urgency=medium * Proxy passes all NBD protocol errors through to the client instead of disconnecting and retrying (#36, !40) * Ignore ends of discs that stray outside of 512-byte sector sizes (!42). + * Alter semantics of NBD_MAX_BLOCK_SIZE to remove struct size overheads when + calculating if a request exceeds the max block size (!45) -- James Carter Thu, 11 Jan 2018 10:05:35 +0000 From 2e17e8955fef0ecb4f2c23dcf02ba8ee27788088 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 13 Feb 2018 17:04:51 +0000 Subject: [PATCH 61/71] Added tests for NBD_MAX_SIZE This constant is only used in the proxy, so the tests only cover proxy mode. --- tests/acceptance/proxy_tests.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/acceptance/proxy_tests.rb b/tests/acceptance/proxy_tests.rb index 65fe38a..897c487 100644 --- a/tests/acceptance/proxy_tests.rb +++ b/tests/acceptance/proxy_tests.rb @@ -207,4 +207,17 @@ module ProxyTests end end end + + def test_maximum_write_request_size + # Defined in src/common/nbdtypes.h + nbd_max_block_size = 32 * 1024 * 1024 + @env.writefile1('0' * 40 * 1024) + with_proxied_client do |client| + # This will crash with EPIPE if the proxy dies. + client.write(0, b * nbd_max_block_size) + rsp = client.read_response + assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] + assert_equal 0, rsp[:error] + end + end end From d0439dab88545fd6a8646cdb0a51a9fa6432ff32 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 16 Feb 2018 12:58:03 +0000 Subject: [PATCH 62/71] Call the thread cleanup code when requesting `status` This ensures the correct number of connected clients is returned when the status command is issued. Previously the thread pool would only be cleaned up on a new connection. --- src/server/serve.c | 2 ++ tests/acceptance/test_serve_mode.rb | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/server/serve.c b/src/server/serve.c index 3a86c3a..b7b8e44 100644 --- a/src/server/serve.c +++ b/src/server/serve.c @@ -332,6 +332,8 @@ int server_count_clients( struct server *params ) { NULLCHECK( params ); int i, count = 0; + + cleanup_client_threads( params->nbd_client, params->max_nbd_clients ); for ( i = 0 ; i < params->max_nbd_clients ; i++ ) { if ( params->nbd_client[i].thread != 0 ) { diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index 6c3e3f6..5bc3eb5 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -207,4 +207,14 @@ class TestServeMode < Test::Unit::TestCase 'TCP keepalive count not set to 3') end end + + def test_status_returns_correct_client_count + require 'pp' + connect_to_server do |client| + status = @env.status1 + assert_equal('1', status['num_clients']) + end + status = @env.status1 + assert_equal('0', status['num_clients']) + end end From 1407407ff493287fb9fef8dbbf97dfe47cca0fce Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 16 Feb 2018 13:00:31 +0000 Subject: [PATCH 63/71] Updated changelog --- debian/changelog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/changelog b/debian/changelog index 8d6029f..63afd7c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -20,6 +20,8 @@ flexnbd (0.2.0) UNRELEASED; urgency=medium calculating if a request exceeds the max block size (!45) * Added tests for setting TCP_NODELAY on upstream-reconnections in the proxy, and refactored the other LD_PRELOAD tests (!43) + * Clean up dead threads before calculating the number of connected clients + on the status command (!46) -- James Carter Thu, 11 Jan 2018 10:05:35 +0000 From 27a94a807e16876de7be8efc049af2c922e2af34 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Fri, 16 Feb 2018 13:46:31 +0000 Subject: [PATCH 64/71] Remove the test_gets_num_clients test from the C unit tests This test was causing problems by using dummy pointers to simulate connections. When calling the cleanup code, these pointers were thought to be real, and the code attemtped to clean up threads referenced by those pointers, causing a segfault. I've reimplemented the test in the ruby acceptance suite. --- tests/acceptance/test_serve_mode.rb | 17 ++++++++++------- tests/unit/check_status.c | 19 ------------------- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index 5bc3eb5..ddeb836 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -209,12 +209,15 @@ class TestServeMode < Test::Unit::TestCase end def test_status_returns_correct_client_count - require 'pp' - connect_to_server do |client| - status = @env.status1 - assert_equal('1', status['num_clients']) - end - status = @env.status1 - assert_equal('0', status['num_clients']) + @env.writefile1('0') + @env.serve1 + assert_equal('0', @env.status1['num_clients']) + client = FlexNBD::FakeSource.new(@env.ip, @env.port1, 'Connecting to server failed') + assert_equal('1', @env.status1['num_clients']) + client2 = FlexNBD::FakeSource.new(@env.ip, @env.port1, 'Connecting to server failed') + assert_equal('2', @env.status1['num_clients']) + client2.close + client.close + assert_equal('0', @env.status1['num_clients']) end end diff --git a/tests/unit/check_status.c b/tests/unit/check_status.c index 1daf556..1a7962b 100644 --- a/tests/unit/check_status.c +++ b/tests/unit/check_status.c @@ -105,25 +105,6 @@ START_TEST( test_gets_clients_allowed ) } END_TEST -START_TEST( test_gets_num_clients ) -{ - struct server * server = mock_server(); - struct status * status = status_create( server ); - - fail_if( status->num_clients != 0, "num_clients was wrong" ); - status_destroy( status ); - - server->nbd_client[0].thread = 1; - server->nbd_client[1].thread = 1; - status = status_create( server ); - - fail_unless( status->num_clients == 2, "num_clients was wrong" ); - status_destroy( status ); - destroy_mock_server( server ); - -} -END_TEST - START_TEST( test_gets_pid ) { struct server * server = mock_server(); From 623007bfffa00aa5bf068834c550806ae9ee317f Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Mon, 19 Feb 2018 10:22:01 +0000 Subject: [PATCH 65/71] Remove last reference to removed test_gets_num_clients --- tests/unit/check_status.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/check_status.c b/tests/unit/check_status.c index 1a7962b..ea89d3b 100644 --- a/tests/unit/check_status.c +++ b/tests/unit/check_status.c @@ -338,7 +338,6 @@ Suite *status_suite(void) tcase_add_test(tc_create, test_gets_has_control); tcase_add_test(tc_create, test_gets_is_mirroring); tcase_add_test(tc_create, test_gets_clients_allowed); - tcase_add_test(tc_create, test_gets_num_clients); tcase_add_test(tc_create, test_gets_pid); tcase_add_test(tc_create, test_gets_size); tcase_add_test(tc_create, test_gets_migration_statistics); From f47f56d4c4d94a21abef8d17997c954671cb9a07 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 20 Feb 2018 10:05:35 +0000 Subject: [PATCH 66/71] Formatted all code using `indent` --- CONTRIBUTING.md | 3 + src/common/ioutil.c | 514 +++++------ src/common/ioutil.h | 27 +- src/common/mode.h | 9 +- src/common/nbdtypes.c | 65 +- src/common/nbdtypes.h | 81 +- src/common/parse.c | 158 ++-- src/common/parse.h | 21 +- src/common/readwrite.c | 340 +++---- src/common/readwrite.h | 19 +- src/common/remote.c | 80 +- src/common/self_pipe.c | 113 +-- src/common/self_pipe.h | 16 +- src/common/sockutil.c | 422 ++++----- src/common/sockutil.h | 18 +- src/common/util.c | 75 +- src/common/util.h | 22 +- src/main.c | 19 +- src/proxy-main.c | 260 +++--- src/proxy/prefetch.c | 96 +- src/proxy/prefetch.h | 37 +- src/proxy/proxy.c | 1548 ++++++++++++++++---------------- src/proxy/proxy.h | 103 ++- src/server/acl.c | 149 ++-- src/server/acl.h | 14 +- src/server/bitset.h | 461 +++++----- src/server/client.c | 1009 +++++++++++---------- src/server/client.h | 51 +- src/server/control.c | 812 +++++++++-------- src/server/control.h | 63 +- src/server/flexnbd.c | 281 +++--- src/server/flexnbd.h | 77 +- src/server/flexthread.c | 86 +- src/server/flexthread.h | 14 +- src/server/mbox.c | 88 +- src/server/mbox.h | 22 +- src/server/mirror.c | 1579 ++++++++++++++++----------------- src/server/mirror.h | 96 +- src/server/mode.c | 1481 ++++++++++++++++--------------- src/server/serve.c | 1210 ++++++++++++------------- src/server/serve.h | 201 +++-- src/server/status.c | 98 +- src/server/status.h | 29 +- tests/unit/check_acl.c | 279 +++--- tests/unit/check_bitset.c | 655 +++++++------- tests/unit/check_client.c | 128 ++- tests/unit/check_control.c | 41 +- tests/unit/check_flexnbd.c | 50 +- tests/unit/check_flexthread.c | 70 +- tests/unit/check_ioutil.c | 166 ++-- tests/unit/check_mbox.c | 120 ++- tests/unit/check_nbdtypes.c | 351 ++++---- tests/unit/check_parse.c | 46 +- tests/unit/check_readwrite.c | 216 +++-- tests/unit/check_self_pipe.c | 300 +++---- tests/unit/check_serve.c | 334 +++---- tests/unit/check_sockutil.c | 140 +-- tests/unit/check_status.c | 441 +++++---- tests/unit/check_util.c | 189 ++-- 59 files changed, 7631 insertions(+), 7762 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f53854e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# Contribution guide + +The code is formatted using the K&R style of "indent". diff --git a/src/common/ioutil.c b/src/common/ioutil.c index dfa47df..761b6e9 100644 --- a/src/common/ioutil.c +++ b/src/common/ioutil.c @@ -13,228 +13,236 @@ #include "ioutil.h" -int build_allocation_map(struct bitset * allocation_map, int fd) +int build_allocation_map(struct bitset *allocation_map, int fd) { - /* break blocking ioctls down */ - const unsigned long max_length = 100*1024*1024; - const unsigned int max_extents = 1000; + /* break blocking ioctls down */ + const unsigned long max_length = 100 * 1024 * 1024; + const unsigned int max_extents = 1000; - unsigned long offset = 0; + unsigned long offset = 0; - struct { - struct fiemap fiemap; - struct fiemap_extent extents[max_extents]; - } fiemap_static; - struct fiemap* fiemap = (struct fiemap*) &fiemap_static; + struct { + struct fiemap fiemap; + struct fiemap_extent extents[max_extents]; + } fiemap_static; + struct fiemap *fiemap = (struct fiemap *) &fiemap_static; - memset(&fiemap_static, 0, sizeof(fiemap_static)); + memset(&fiemap_static, 0, sizeof(fiemap_static)); - for (offset = 0; offset < allocation_map->size; ) { + for (offset = 0; offset < allocation_map->size;) { - fiemap->fm_start = offset; + fiemap->fm_start = offset; - fiemap->fm_length = max_length; - if ( offset + max_length > allocation_map->size ) { - fiemap->fm_length = allocation_map->size-offset; - } - - fiemap->fm_flags = FIEMAP_FLAG_SYNC; - fiemap->fm_extent_count = max_extents; - fiemap->fm_mapped_extents = 0; - - if ( ioctl( fd, FS_IOC_FIEMAP, fiemap ) < 0 ) { - debug( "Couldn't get fiemap, returning no allocation_map" ); - return 0; /* it's up to the caller to free the map */ - } - else { - for ( unsigned int i = 0; i < fiemap->fm_mapped_extents; i++ ) { - bitset_set_range( allocation_map, - fiemap->fm_extents[i].fe_logical, - fiemap->fm_extents[i].fe_length ); - } - - - /* must move the offset on, but careful not to jump max_length - * if we've actually hit max_offsets. - */ - if (fiemap->fm_mapped_extents > 0) { - struct fiemap_extent *last = &fiemap->fm_extents[ - fiemap->fm_mapped_extents-1 - ]; - offset = last->fe_logical + last->fe_length; - } - else { - offset += fiemap->fm_length; - } - } + fiemap->fm_length = max_length; + if (offset + max_length > allocation_map->size) { + fiemap->fm_length = allocation_map->size - offset; } - info("Successfully built allocation map"); - return 1; + fiemap->fm_flags = FIEMAP_FLAG_SYNC; + fiemap->fm_extent_count = max_extents; + fiemap->fm_mapped_extents = 0; + + if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) { + debug("Couldn't get fiemap, returning no allocation_map"); + return 0; /* it's up to the caller to free the map */ + } else { + for (unsigned int i = 0; i < fiemap->fm_mapped_extents; i++) { + bitset_set_range(allocation_map, + fiemap->fm_extents[i].fe_logical, + fiemap->fm_extents[i].fe_length); + } + + + /* must move the offset on, but careful not to jump max_length + * if we've actually hit max_offsets. + */ + if (fiemap->fm_mapped_extents > 0) { + struct fiemap_extent *last = + &fiemap->fm_extents[fiemap->fm_mapped_extents - 1]; + offset = last->fe_logical + last->fe_length; + } else { + offset += fiemap->fm_length; + } + } + } + + info("Successfully built allocation map"); + return 1; } -int open_and_mmap(const char* filename, int* out_fd, uint64_t *out_size, void **out_map) +int open_and_mmap(const char *filename, int *out_fd, uint64_t * out_size, + void **out_map) { - /* - * size and out_size are intentionally of different types. - * lseek64() uses off64_t to signal errors in the sign bit. - * Since we check for these errors before trying to assign to - * *out_size, we know *out_size can never go negative. - */ - off64_t size; + /* + * size and out_size are intentionally of different types. + * lseek64() uses off64_t to signal errors in the sign bit. + * Since we check for these errors before trying to assign to + * *out_size, we know *out_size can never go negative. + */ + off64_t size; - /* O_DIRECT should not be used with mmap() */ - *out_fd = open(filename, O_RDWR | O_NOATIME ); + /* O_DIRECT should not be used with mmap() */ + *out_fd = open(filename, O_RDWR | O_NOATIME); - if (*out_fd < 1) { - warn("open(%s) failed: does it exist?", filename); - return *out_fd; + if (*out_fd < 1) { + warn("open(%s) failed: does it exist?", filename); + return *out_fd; + } + + size = lseek64(*out_fd, 0, SEEK_END); + if (size < 0) { + warn("lseek64() failed"); + return size; + } + + /* If discs are not in multiples of 512, then odd things happen, + * resulting in reads/writes past the ends of files. + */ + if (size != (size & (~0x1ff))) { + warn("file does not fit into 512-byte sectors; the end of the file will be ignored."); + size &= ~0x1ff; + } + + if (out_size) { + *out_size = size; + } + + if (out_map) { + *out_map = mmap64(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, + *out_fd, 0); + if (((long) *out_map) == -1) { + warn("mmap64() failed"); + return -1; } + debug("opened %s size %ld on fd %d @ %p", filename, size, *out_fd, + *out_map); + } else { + debug("opened %s size %ld on fd %d", filename, size, *out_fd); + } - size = lseek64(*out_fd, 0, SEEK_END); - if (size < 0) { - warn("lseek64() failed"); - return size; - } - - /* If discs are not in multiples of 512, then odd things happen, - * resulting in reads/writes past the ends of files. - */ - if ( size != (size & (~0x1ff))) { - warn("file does not fit into 512-byte sectors; the end of the file will be ignored."); - size &= ~0x1ff; - } - - if (out_size) { - *out_size = size; - } - - if (out_map) { - *out_map = mmap64(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, - *out_fd, 0); - if (((long) *out_map) == -1) { - warn("mmap64() failed"); - return -1; - } - debug("opened %s size %ld on fd %d @ %p", filename, size, *out_fd, *out_map); - } - else { - debug("opened %s size %ld on fd %d", filename, size, *out_fd); - } - - return 0; + return 0; } int writeloop(int filedes, const void *buffer, size_t size) { - size_t written=0; - while (written < size) { - ssize_t result = write(filedes, buffer+written, size-written); - if (result == -1) { - if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) { - continue; // busy-wait - } - return -1; // failure - } - written += result; + size_t written = 0; + while (written < size) { + ssize_t result = write(filedes, buffer + written, size - written); + if (result == -1) { + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + continue; // busy-wait + } + return -1; // failure } - return 0; + written += result; + } + return 0; } int readloop(int filedes, void *buffer, size_t size) { - size_t readden=0; - while (readden < size) { - ssize_t result = read(filedes, buffer+readden, size-readden); + size_t readden = 0; + while (readden < size) { + ssize_t result = read(filedes, buffer + readden, size - readden); - if ( result == 0 /* EOF */ ) { - warn( "end-of-file detected while reading after %i bytes", readden ); - return -1; - } - - if ( result == -1 ) { - if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) { - continue; // busy-wait - } - return -1; // failure - } - readden += result; + if (result == 0 /* EOF */ ) { + warn("end-of-file detected while reading after %i bytes", + readden); + return -1; } - return 0; + + if (result == -1) { + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + continue; // busy-wait + } + return -1; // failure + } + readden += result; + } + return 0; } -int sendfileloop(int out_fd, int in_fd, off64_t *offset, size_t count) +int sendfileloop(int out_fd, int in_fd, off64_t * offset, size_t count) { - size_t sent=0; - while (sent < count) { - ssize_t result = sendfile64(out_fd, in_fd, offset, count-sent); - debug("sendfile64(out_fd=%d, in_fd=%d, offset=%p, count-sent=%ld) = %ld", out_fd, in_fd, offset, count-sent, result); + size_t sent = 0; + while (sent < count) { + ssize_t result = sendfile64(out_fd, in_fd, offset, count - sent); + debug + ("sendfile64(out_fd=%d, in_fd=%d, offset=%p, count-sent=%ld) = %ld", + out_fd, in_fd, offset, count - sent, result); - if (result == -1) { - debug( "%s (%i) calling sendfile64()", strerror(errno), errno ); - return -1; - } - sent += result; - debug("sent=%ld, count=%ld", sent, count); + if (result == -1) { + debug("%s (%i) calling sendfile64()", strerror(errno), errno); + return -1; } - debug("exiting sendfileloop"); - return 0; + sent += result; + debug("sent=%ld, count=%ld", sent, count); + } + debug("exiting sendfileloop"); + return 0; } #include -ssize_t spliceloop(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags2) +ssize_t spliceloop(int fd_in, loff_t * off_in, int fd_out, + loff_t * off_out, size_t len, unsigned int flags2) { - const unsigned int flags = SPLICE_F_MORE|SPLICE_F_MOVE|flags2; - size_t spliced=0; + const unsigned int flags = SPLICE_F_MORE | SPLICE_F_MOVE | flags2; + size_t spliced = 0; - //debug("spliceloop(%d, %ld, %d, %ld, %ld)", fd_in, off_in ? *off_in : 0, fd_out, off_out ? *off_out : 0, len); + //debug("spliceloop(%d, %ld, %d, %ld, %ld)", fd_in, off_in ? *off_in : 0, fd_out, off_out ? *off_out : 0, len); - while (spliced < len) { - ssize_t result = splice(fd_in, off_in, fd_out, off_out, len, flags); - if (result < 0) { - //debug("result=%ld (%s), spliced=%ld, len=%ld", result, strerror(errno), spliced, len); - if (errno == EAGAIN && (flags & SPLICE_F_NONBLOCK) ) { - return spliced; - } - else { - return -1; - } - } else { - spliced += result; - //debug("result=%ld (%s), spliced=%ld, len=%ld", result, strerror(errno), spliced, len); - } + while (spliced < len) { + ssize_t result = + splice(fd_in, off_in, fd_out, off_out, len, flags); + if (result < 0) { + //debug("result=%ld (%s), spliced=%ld, len=%ld", result, strerror(errno), spliced, len); + if (errno == EAGAIN && (flags & SPLICE_F_NONBLOCK)) { + return spliced; + } else { + return -1; + } + } else { + spliced += result; + //debug("result=%ld (%s), spliced=%ld, len=%ld", result, strerror(errno), spliced, len); } + } - return spliced; + return spliced; } int splice_via_pipe_loop(int fd_in, int fd_out, size_t len) { - int pipefd[2]; /* read end, write end */ - size_t spliced=0; + int pipefd[2]; /* read end, write end */ + size_t spliced = 0; - if (pipe(pipefd) == -1) { - return -1; + if (pipe(pipefd) == -1) { + return -1; + } + + while (spliced < len) { + ssize_t run = len - spliced; + ssize_t s2, s1 = + spliceloop(fd_in, NULL, pipefd[1], NULL, run, + SPLICE_F_NONBLOCK); + /*if (run > 65535) + run = 65535; */ + if (s1 < 0) { + break; } - while (spliced < len) { - ssize_t run = len-spliced; - ssize_t s2, s1 = spliceloop(fd_in, NULL, pipefd[1], NULL, run, SPLICE_F_NONBLOCK); - /*if (run > 65535) - run = 65535;*/ - if (s1 < 0) { break; } - - s2 = spliceloop(pipefd[0], NULL, fd_out, NULL, s1, 0); - if (s2 < 0) { break; } - spliced += s2; + s2 = spliceloop(pipefd[0], NULL, fd_out, NULL, s1, 0); + if (s2 < 0) { + break; } - close(pipefd[0]); - close(pipefd[1]); + spliced += s2; + } + close(pipefd[0]); + close(pipefd[1]); - return spliced < len ? -1 : 0; + return spliced < len ? -1 : 0; } /* Reads single bytes from fd until either an EOF or a newline appears. @@ -244,117 +252,123 @@ int splice_via_pipe_loop(int fd_in, int fd_out, size_t len) * Returns the number of read bytes: the length of the line without the * newline, plus the trailing null. */ -int read_until_newline(int fd, char* buf, int bufsize) +int read_until_newline(int fd, char *buf, int bufsize) { - int cur; + int cur; - for (cur=0; cur < bufsize; cur++) { - int result = read(fd, buf+cur, 1); - if (result <= 0) { return -1; } - if (buf[cur] == 10) { - buf[cur] = '\0'; - break; - } + for (cur = 0; cur < bufsize; cur++) { + int result = read(fd, buf + cur, 1); + if (result <= 0) { + return -1; } + if (buf[cur] == 10) { + buf[cur] = '\0'; + break; + } + } - return cur+1; + return cur + 1; } int read_lines_until_blankline(int fd, int max_line_length, char ***lines) { - int lines_count = 0; - char line[max_line_length+1]; - *lines = NULL; + int lines_count = 0; + char line[max_line_length + 1]; + *lines = NULL; - memset(line, 0, max_line_length+1); + memset(line, 0, max_line_length + 1); - while (1) { - int readden = read_until_newline(fd, line, max_line_length); - /* readden will be: - * 1 for an empty line - * -1 for an eof - * -1 for a read error - */ - if (readden <= 1) { return lines_count; } - *lines = xrealloc(*lines, (lines_count+1) * sizeof(char*)); - (*lines)[lines_count] = strdup(line); - if ((*lines)[lines_count][0] == 0) { - return lines_count; - } - lines_count++; + while (1) { + int readden = read_until_newline(fd, line, max_line_length); + /* readden will be: + * 1 for an empty line + * -1 for an eof + * -1 for a read error + */ + if (readden <= 1) { + return lines_count; } + *lines = xrealloc(*lines, (lines_count + 1) * sizeof(char *)); + (*lines)[lines_count] = strdup(line); + if ((*lines)[lines_count][0] == 0) { + return lines_count; + } + lines_count++; + } } -int fd_is_closed( int fd_in ) +int fd_is_closed(int fd_in) { - int errno_old = errno; - int result = fcntl( fd_in, F_GETFL ) < 0; - errno = errno_old; - return result; + int errno_old = errno; + int result = fcntl(fd_in, F_GETFL) < 0; + errno = errno_old; + return result; } static inline int io_errno_permanent(void) { - return ( errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR ); + return (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR); } /* Returns -1 if the operation failed, or the number of bytes read if all is * well. Note that 0 bytes may be returned. Unlike read(), this is not an EOF! */ -ssize_t iobuf_read(int fd, struct iobuf *iobuf, size_t default_size ) +ssize_t iobuf_read(int fd, struct iobuf * iobuf, size_t default_size) { - size_t left; - ssize_t count; + size_t left; + ssize_t count; - if ( iobuf->needle == 0 ) { - iobuf->size = default_size; - } + if (iobuf->needle == 0) { + iobuf->size = default_size; + } - left = iobuf->size - iobuf->needle; - debug( "Reading %"PRIu32" of %"PRIu32" bytes from fd %i", left, iobuf->size, fd ); + left = iobuf->size - iobuf->needle; + debug("Reading %" PRIu32 " of %" PRIu32 " bytes from fd %i", left, + iobuf->size, fd); - count = read( fd, iobuf->buf + iobuf->needle, left ); + count = read(fd, iobuf->buf + iobuf->needle, left); - if ( count > 0 ) { - iobuf->needle += count; - debug( "read() returned %"PRIu32" bytes", count ); - } else if ( count == 0 ) { - warn( "read() returned EOF on fd %i", fd ); - errno = 0; - return -1; - } else if ( count == -1 ) { - if ( io_errno_permanent() ) { - warn( SHOW_ERRNO( "read() failed on fd %i", fd ) ); - } else { - debug( SHOW_ERRNO( "read() returned 0 bytes" ) ); - count = 0; - } - } - - return count; -} - -ssize_t iobuf_write( int fd, struct iobuf *iobuf ) -{ - size_t left = iobuf->size - iobuf->needle; - ssize_t count; - - debug( "Writing %"PRIu32" of %"PRIu32" bytes to fd %i", left, iobuf->size, fd ); - count = write( fd, iobuf->buf + iobuf->needle, left ); - - if ( count >= 0 ) { - iobuf->needle += count; - debug( "write() returned %"PRIu32" bytes", count ); + if (count > 0) { + iobuf->needle += count; + debug("read() returned %" PRIu32 " bytes", count); + } else if (count == 0) { + warn("read() returned EOF on fd %i", fd); + errno = 0; + return -1; + } else if (count == -1) { + if (io_errno_permanent()) { + warn(SHOW_ERRNO("read() failed on fd %i", fd)); } else { - if ( io_errno_permanent() ) { - warn( SHOW_ERRNO( "write() failed on fd %i", fd ) ); - } else { - debug( SHOW_ERRNO( "write() returned 0 bytes" ) ); - count = 0; - } + debug(SHOW_ERRNO("read() returned 0 bytes")); + count = 0; } + } - return count; + return count; +} + +ssize_t iobuf_write(int fd, struct iobuf * iobuf) +{ + size_t left = iobuf->size - iobuf->needle; + ssize_t count; + + debug("Writing %" PRIu32 " of %" PRIu32 " bytes to fd %i", left, + iobuf->size, fd); + count = write(fd, iobuf->buf + iobuf->needle, left); + + if (count >= 0) { + iobuf->needle += count; + debug("write() returned %" PRIu32 " bytes", count); + } else { + if (io_errno_permanent()) { + warn(SHOW_ERRNO("write() failed on fd %i", fd)); + } else { + debug(SHOW_ERRNO("write() returned 0 bytes")); + count = 0; + } + } + + return count; } diff --git a/src/common/ioutil.h b/src/common/ioutil.h index da69452..e018ec7 100644 --- a/src/common/ioutil.h +++ b/src/common/ioutil.h @@ -3,16 +3,16 @@ #include struct iobuf { - unsigned char *buf; - size_t size; - size_t needle; + unsigned char *buf; + size_t size; + size_t needle; }; -ssize_t iobuf_read( int fd, struct iobuf* iobuf, size_t default_size ); -ssize_t iobuf_write( int fd, struct iobuf* iobuf ); +ssize_t iobuf_read(int fd, struct iobuf *iobuf, size_t default_size); +ssize_t iobuf_write(int fd, struct iobuf *iobuf); #include "serve.h" -struct bitset; /* don't need whole of bitset.h here */ +struct bitset; /* don't need whole of bitset.h here */ /** Scan the file opened in ''fd'', set bits in ''allocation_map'' that * correspond to which blocks are physically allocated on disc (or part- @@ -20,7 +20,7 @@ struct bitset; /* don't need whole of bitset.h here */ * than you've asked for, any block or part block will count as "allocated" * with the corresponding bit set. Returns 1 if successful, 0 otherwise. */ -int build_allocation_map(struct bitset * allocation_map, int fd); +int build_allocation_map(struct bitset *allocation_map, int fd); /** Repeat a write() operation that succeeds partially until ''size'' bytes * are written, or an error is returned, when it returns -1 as usual. @@ -35,10 +35,11 @@ int readloop(int filedes, void *buffer, size_t size); /** Repeat a sendfile() operation that succeeds partially until ''size'' bytes * are written, or an error is returned, when it returns -1 as usual. */ -int sendfileloop(int out_fd, int in_fd, off64_t *offset, size_t count); +int sendfileloop(int out_fd, int in_fd, off64_t * offset, size_t count); /** Repeat a splice() operation until we have 'len' bytes. */ -ssize_t spliceloop(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags2); +ssize_t spliceloop(int fd_in, loff_t * off_in, int fd_out, + loff_t * off_out, size_t len, unsigned int flags2); /** Copy ''len'' bytes from ''fd_in'' to ''fd_out'' by creating a temporary * pipe and using the Linux splice call repeatedly until it has transferred @@ -50,7 +51,7 @@ int splice_via_pipe_loop(int fd_in, int fd_out, size_t len); * until an LF character is received, which is written to the buffer at a zero * byte. Returns -1 on error, or the number of bytes written to the buffer. */ -int read_until_newline(int fd, char* buf, int bufsize); +int read_until_newline(int fd, char *buf, int bufsize); /** Read a number of lines using read_until_newline, until an empty line is * received (i.e. the sequence LF LF). The data is read from ''fd'' and @@ -65,12 +66,12 @@ int read_lines_until_blankline(int fd, int max_line_length, char ***lines); * ''out_size'' and the address of the mmap in ''out_map''. If anything goes * wrong, returns -1 setting errno, otherwise 0. */ -int open_and_mmap( const char* filename, int* out_fd, uint64_t* out_size, void **out_map); +int open_and_mmap(const char *filename, int *out_fd, uint64_t * out_size, + void **out_map); /** Check to see whether the given file descriptor is closed. */ -int fd_is_closed( int fd_in ); +int fd_is_closed(int fd_in); #endif - diff --git a/src/common/mode.h b/src/common/mode.h index f117e95..29313fe 100644 --- a/src/common/mode.h +++ b/src/common/mode.h @@ -2,7 +2,7 @@ #define MODE_H -void mode(char* mode, int argc, char **argv); +void mode(char *mode, int argc, char **argv); #include @@ -68,9 +68,9 @@ void mode(char* mode, int argc, char **argv); "\t--" OPT_VERBOSE ",-" SOPT_VERBOSE "\t\tOutput debug information.\n" #ifdef DEBUG -# define VERBOSE_LOG_LEVEL 0 +#define VERBOSE_LOG_LEVEL 0 #else -# define VERBOSE_LOG_LEVEL 1 +#define VERBOSE_LOG_LEVEL 1 #endif #define QUIET_LOG_LEVEL 4 @@ -91,7 +91,6 @@ void mode(char* mode, int argc, char **argv); #define MAX_SPEED_LINE \ "\t--" OPT_MAX_SPEED ",-m \tMaximum speed of the migration, in bytes/sec.\n" -char * help_help_text; +char *help_help_text; #endif - diff --git a/src/common/nbdtypes.c b/src/common/nbdtypes.c index 20020b4..59e58e9 100644 --- a/src/common/nbdtypes.c +++ b/src/common/nbdtypes.c @@ -8,55 +8,54 @@ * We intentionally ignore the reserved 128 bytes at the end of the * request, since there's nothing we can do with them. */ -void nbd_r2h_init( struct nbd_init_raw * from, struct nbd_init * to ) +void nbd_r2h_init(struct nbd_init_raw *from, struct nbd_init *to) { - memcpy( to->passwd, from->passwd, 8 ); - to->magic = be64toh( from->magic ); - to->size = be64toh( from->size ); - to->flags = be32toh( from->flags ); + memcpy(to->passwd, from->passwd, 8); + to->magic = be64toh(from->magic); + to->size = be64toh(from->size); + to->flags = be32toh(from->flags); } -void nbd_h2r_init( struct nbd_init * from, struct nbd_init_raw * to) +void nbd_h2r_init(struct nbd_init *from, struct nbd_init_raw *to) { - memcpy( to->passwd, from->passwd, 8 ); - to->magic = htobe64( from->magic ); - to->size = htobe64( from->size ); - to->flags = htobe32( from->flags ); + memcpy(to->passwd, from->passwd, 8); + to->magic = htobe64(from->magic); + to->size = htobe64(from->size); + to->flags = htobe32(from->flags); } -void nbd_r2h_request( struct nbd_request_raw *from, struct nbd_request * to ) +void nbd_r2h_request(struct nbd_request_raw *from, struct nbd_request *to) { - to->magic = be32toh( from->magic ); - to->flags = be16toh( from->flags ); - to->type = be16toh( from->type ); - to->handle.w = from->handle.w; - to->from = be64toh( from->from ); - to->len = be32toh( from->len ); + to->magic = be32toh(from->magic); + to->flags = be16toh(from->flags); + to->type = be16toh(from->type); + to->handle.w = from->handle.w; + to->from = be64toh(from->from); + to->len = be32toh(from->len); } -void nbd_h2r_request( struct nbd_request * from, struct nbd_request_raw * to ) +void nbd_h2r_request(struct nbd_request *from, struct nbd_request_raw *to) { - to->magic = htobe32( from->magic ); - to->flags = htobe16( from->flags ); - to->type = htobe16( from->type ); - to->handle.w = from->handle.w; - to->from = htobe64( from->from ); - to->len = htobe32( from->len ); + to->magic = htobe32(from->magic); + to->flags = htobe16(from->flags); + to->type = htobe16(from->type); + to->handle.w = from->handle.w; + to->from = htobe64(from->from); + to->len = htobe32(from->len); } -void nbd_r2h_reply( struct nbd_reply_raw * from, struct nbd_reply * to ) +void nbd_r2h_reply(struct nbd_reply_raw *from, struct nbd_reply *to) { - to->magic = be32toh( from->magic ); - to->error = be32toh( from->error ); - to->handle.w = from->handle.w; + to->magic = be32toh(from->magic); + to->error = be32toh(from->error); + to->handle.w = from->handle.w; } -void nbd_h2r_reply( struct nbd_reply * from, struct nbd_reply_raw * to ) +void nbd_h2r_reply(struct nbd_reply *from, struct nbd_reply_raw *to) { - to->magic = htobe32( from->magic ); - to->error = htobe32( from->error ); - to->handle.w = from->handle.w; + to->magic = htobe32(from->magic); + to->error = htobe32(from->error); + to->handle.w = from->handle.w; } - diff --git a/src/common/nbdtypes.h b/src/common/nbdtypes.h index 5d5b614..5504268 100644 --- a/src/common/nbdtypes.h +++ b/src/common/nbdtypes.h @@ -29,8 +29,8 @@ #define FLAG_READ_ONLY (1 << 1) /* Device is read-only */ #define FLAG_ROTATIONAL (1 << 4) /* Use elevator algorithm - rotational media */ #define FLAG_SEND_TRIM (1 << 5) /* Send TRIM (discard) */ -#define FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send NBD_CMD_WRITE_ZEROES */ -#define FLAG_CAN_MULTI_CONN (1 << 8) /* multiple connections are okay */ +#define FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send NBD_CMD_WRITE_ZEROES */ +#define FLAG_CAN_MULTI_CONN (1 << 8) /* multiple connections are okay */ #define CMD_FLAG_NO_HOLE (1 << 1) #endif @@ -48,8 +48,8 @@ #include typedef union nbd_handle_t { - uint8_t b[8]; - uint64_t w; + uint8_t b[8]; + uint64_t w; } nbd_handle_t; /* The _raw types are the types as they appear on the wire. Non-_raw @@ -58,58 +58,57 @@ typedef union nbd_handle_t { * for converting host to raw. */ struct nbd_init_raw { - char passwd[8]; - __be64 magic; - __be64 size; - __be32 flags; - char reserved[124]; + char passwd[8]; + __be64 magic; + __be64 size; + __be32 flags; + char reserved[124]; }; struct nbd_request_raw { - __be32 magic; - __be16 flags; - __be16 type; /* == READ || == WRITE || == FLUSH */ - nbd_handle_t handle; - __be64 from; - __be32 len; -} __attribute__((packed)); + __be32 magic; + __be16 flags; + __be16 type; /* == READ || == WRITE || == FLUSH */ + nbd_handle_t handle; + __be64 from; + __be32 len; +} __attribute__ ((packed)); struct nbd_reply_raw { - __be32 magic; - __be32 error; /* 0 = ok, else error */ - nbd_handle_t handle; /* handle you got from request */ + __be32 magic; + __be32 error; /* 0 = ok, else error */ + nbd_handle_t handle; /* handle you got from request */ }; struct nbd_init { - char passwd[8]; - uint64_t magic; - uint64_t size; - uint32_t flags; - char reserved[124]; + char passwd[8]; + uint64_t magic; + uint64_t size; + uint32_t flags; + char reserved[124]; }; struct nbd_request { - uint32_t magic; - uint16_t flags; - uint16_t type; /* == READ || == WRITE || == DISCONNECT || == FLUSH */ - nbd_handle_t handle; - uint64_t from; - uint32_t len; -} __attribute__((packed)); + uint32_t magic; + uint16_t flags; + uint16_t type; /* == READ || == WRITE || == DISCONNECT || == FLUSH */ + nbd_handle_t handle; + uint64_t from; + uint32_t len; +} __attribute__ ((packed)); struct nbd_reply { - uint32_t magic; - uint32_t error; /* 0 = ok, else error */ - nbd_handle_t handle; /* handle you got from request */ + uint32_t magic; + uint32_t error; /* 0 = ok, else error */ + nbd_handle_t handle; /* handle you got from request */ }; -void nbd_r2h_init( struct nbd_init_raw * from, struct nbd_init * to ); -void nbd_r2h_request( struct nbd_request_raw *from, struct nbd_request * to ); -void nbd_r2h_reply( struct nbd_reply_raw * from, struct nbd_reply * to ); +void nbd_r2h_init(struct nbd_init_raw *from, struct nbd_init *to); +void nbd_r2h_request(struct nbd_request_raw *from, struct nbd_request *to); +void nbd_r2h_reply(struct nbd_reply_raw *from, struct nbd_reply *to); -void nbd_h2r_init( struct nbd_init * from, struct nbd_init_raw * to); -void nbd_h2r_request( struct nbd_request * from, struct nbd_request_raw * to ); -void nbd_h2r_reply( struct nbd_reply * from, struct nbd_reply_raw * to ); +void nbd_h2r_init(struct nbd_init *from, struct nbd_init_raw *to); +void nbd_h2r_request(struct nbd_request *from, struct nbd_request_raw *to); +void nbd_h2r_reply(struct nbd_reply *from, struct nbd_reply_raw *to); #endif - diff --git a/src/common/parse.c b/src/common/parse.c index 5f8c006..f2ff52f 100644 --- a/src/common/parse.c +++ b/src/common/parse.c @@ -10,118 +10,116 @@ int atoi(const char *nptr); ) /* FIXME: should change this to return negative on error like everything else */ -int parse_ip_to_sockaddr(struct sockaddr* out, char* src) +int parse_ip_to_sockaddr(struct sockaddr *out, char *src) { - NULLCHECK( out ); - NULLCHECK( src ); + NULLCHECK(out); + NULLCHECK(src); - char temp[64]; - struct sockaddr_in *v4 = (struct sockaddr_in *) out; - struct sockaddr_in6 *v6 = (struct sockaddr_in6 *) out; + char temp[64]; + struct sockaddr_in *v4 = (struct sockaddr_in *) out; + struct sockaddr_in6 *v6 = (struct sockaddr_in6 *) out; - /* allow user to start with [ and end with any other invalid char */ - { - int i=0, j=0; - if (src[i] == '[') { i++; } - for (; i<64 && IS_IP_VALID_CHAR(src[i]); i++) { - temp[j++] = src[i]; - } - temp[j] = 0; + /* allow user to start with [ and end with any other invalid char */ + { + int i = 0, j = 0; + if (src[i] == '[') { + i++; } - - if (temp[0] == '0' && temp[1] == '\0') { - v4->sin_family = AF_INET; - v4->sin_addr.s_addr = INADDR_ANY; - return 1; + for (; i < 64 && IS_IP_VALID_CHAR(src[i]); i++) { + temp[j++] = src[i]; } + temp[j] = 0; + } - if (inet_pton(AF_INET, temp, &v4->sin_addr) == 1) { - out->sa_family = AF_INET; - return 1; - } + if (temp[0] == '0' && temp[1] == '\0') { + v4->sin_family = AF_INET; + v4->sin_addr.s_addr = INADDR_ANY; + return 1; + } - if (inet_pton(AF_INET6, temp, &v6->sin6_addr) == 1) { - out->sa_family = AF_INET6; - return 1; - } + if (inet_pton(AF_INET, temp, &v4->sin_addr) == 1) { + out->sa_family = AF_INET; + return 1; + } - return 0; + if (inet_pton(AF_INET6, temp, &v6->sin6_addr) == 1) { + out->sa_family = AF_INET6; + return 1; + } + + return 0; } -int parse_to_sockaddr(struct sockaddr* out, char* address) +int parse_to_sockaddr(struct sockaddr *out, char *address) { - struct sockaddr_un* un = (struct sockaddr_un*) out; + struct sockaddr_un *un = (struct sockaddr_un *) out; - NULLCHECK( address ); + NULLCHECK(address); - if ( address[0] == '/' ) { - un->sun_family = AF_UNIX; - strncpy( un->sun_path, address, 108 ); /* FIXME: linux only */ - return 1; - } + if (address[0] == '/') { + un->sun_family = AF_UNIX; + strncpy(un->sun_path, address, 108); /* FIXME: linux only */ + return 1; + } - return parse_ip_to_sockaddr( out, address ); + return parse_ip_to_sockaddr(out, address); } int parse_acl(struct ip_and_mask (**out)[], int max, char **entries) { - struct ip_and_mask* list; - int i; + struct ip_and_mask *list; + int i; - if (max == 0) { - *out = NULL; - return 0; - } - else { - list = xmalloc(max * sizeof(struct ip_and_mask)); - *out = (struct ip_and_mask (*)[])list; - debug("acl alloc: %p", *out); - } + if (max == 0) { + *out = NULL; + return 0; + } else { + list = xmalloc(max * sizeof(struct ip_and_mask)); + *out = (struct ip_and_mask(*)[]) list; + debug("acl alloc: %p", *out); + } - for (i = 0; i < max; i++) { - int j; - struct ip_and_mask* outentry = &list[i]; + for (i = 0; i < max; i++) { + int j; + struct ip_and_mask *outentry = &list[i]; # define MAX_MASK_BITS (outentry->ip.family == AF_INET ? 32 : 128) - if (parse_ip_to_sockaddr(&outentry->ip.generic, entries[i]) == 0) { - return i; - } + if (parse_ip_to_sockaddr(&outentry->ip.generic, entries[i]) == 0) { + return i; + } - for (j=0; entries[i][j] && entries[i][j] != '/'; j++) - ; // increment j! + for (j = 0; entries[i][j] && entries[i][j] != '/'; j++); // increment j! - if (entries[i][j] == '/') { - outentry->mask = atoi(entries[i]+j+1); - if (outentry->mask < 1 || outentry->mask > MAX_MASK_BITS) { - return i; - } - } - else { - outentry->mask = MAX_MASK_BITS; - } + if (entries[i][j] == '/') { + outentry->mask = atoi(entries[i] + j + 1); + if (outentry->mask < 1 || outentry->mask > MAX_MASK_BITS) { + return i; + } + } else { + outentry->mask = MAX_MASK_BITS; + } # undef MAX_MASK_BITS - debug("acl ptr[%d]: %p %d",i, outentry, outentry->mask); - } + debug("acl ptr[%d]: %p %d", i, outentry, outentry->mask); + } - for (i=0; i < max; i++) { - debug("acl entry %d @ %p has mask %d", i, list[i], list[i].mask); - } + for (i = 0; i < max; i++) { + debug("acl entry %d @ %p has mask %d", i, list[i], list[i].mask); + } - return max; + return max; } -void parse_port( char *s_port, struct sockaddr_in *out ) +void parse_port(char *s_port, struct sockaddr_in *out) { - NULLCHECK( s_port ); + NULLCHECK(s_port); - int raw_port; + int raw_port; - raw_port = atoi( s_port ); - if ( raw_port < 0 || raw_port > 65535 ) { - fatal( "Port number must be >= 0 and <= 65535" ); - } - out->sin_port = htobe16( raw_port ); + raw_port = atoi(s_port); + if (raw_port < 0 || raw_port > 65535) { + fatal("Port number must be >= 0 and <= 65535"); + } + out->sin_port = htobe16(raw_port); } - diff --git a/src/common/parse.h b/src/common/parse.h index afe08ea..686830c 100644 --- a/src/common/parse.h +++ b/src/common/parse.h @@ -8,22 +8,21 @@ #include union mysockaddr { - unsigned short family; - struct sockaddr generic; - struct sockaddr_in v4; - struct sockaddr_in6 v6; - struct sockaddr_un un; + unsigned short family; + struct sockaddr generic; + struct sockaddr_in v4; + struct sockaddr_in6 v6; + struct sockaddr_un un; }; struct ip_and_mask { - union mysockaddr ip; - int mask; + union mysockaddr ip; + int mask; }; -int parse_ip_to_sockaddr(struct sockaddr* out, char* src); -int parse_to_sockaddr(struct sockaddr* out, char* src); +int parse_ip_to_sockaddr(struct sockaddr *out, char *src); +int parse_to_sockaddr(struct sockaddr *out, char *src); int parse_acl(struct ip_and_mask (**out)[], int max, char **entries); -void parse_port( char *s_port, struct sockaddr_in *out ); +void parse_port(char *s_port, struct sockaddr_in *out); #endif - diff --git a/src/common/readwrite.c b/src/common/readwrite.c index 414c169..3734588 100644 --- a/src/common/readwrite.c +++ b/src/common/readwrite.c @@ -8,214 +8,217 @@ #include #include -int socket_connect(struct sockaddr* to, struct sockaddr* from) +int socket_connect(struct sockaddr *to, struct sockaddr *from) { - int fd = socket(to->sa_family == AF_INET ? PF_INET : PF_INET6, SOCK_STREAM, 0); - if( fd < 0 ){ - warn( "Couldn't create client socket"); - return -1; - } + int fd = + socket(to->sa_family == AF_INET ? PF_INET : PF_INET6, SOCK_STREAM, + 0); + if (fd < 0) { + warn("Couldn't create client socket"); + return -1; + } - if (NULL != from) { - if ( 0 > bind( fd, from, sizeof(struct sockaddr_in6 ) ) ){ - warn( SHOW_ERRNO( "bind() to source address failed" ) ); - if ( 0 > close( fd ) ) { /* Non-fatal leak */ - warn( SHOW_ERRNO( "Failed to close fd %i", fd ) ); - } - return -1; - } + if (NULL != from) { + if (0 > bind(fd, from, sizeof(struct sockaddr_in6))) { + warn(SHOW_ERRNO("bind() to source address failed")); + if (0 > close(fd)) { /* Non-fatal leak */ + warn(SHOW_ERRNO("Failed to close fd %i", fd)); + } + return -1; } + } - if ( 0 > sock_try_connect( fd, to, sizeof( struct sockaddr_in6 ), 15 ) ) { - warn( SHOW_ERRNO( "connect failed" ) ); - if ( 0 > close( fd ) ) { /* Non-fatal leak */ - warn( SHOW_ERRNO( "Failed to close fd %i", fd ) ); - } - return -1; + if (0 > sock_try_connect(fd, to, sizeof(struct sockaddr_in6), 15)) { + warn(SHOW_ERRNO("connect failed")); + if (0 > close(fd)) { /* Non-fatal leak */ + warn(SHOW_ERRNO("Failed to close fd %i", fd)); } + return -1; + } - if ( sock_set_tcp_nodelay( fd, 1 ) == -1 ) { - warn( SHOW_ERRNO( "Failed to set TCP_NODELAY" ) ); - } + if (sock_set_tcp_nodelay(fd, 1) == -1) { + warn(SHOW_ERRNO("Failed to set TCP_NODELAY")); + } - return fd; + return fd; } -int nbd_check_hello( struct nbd_init_raw* init_raw, uint64_t* out_size, uint32_t* out_flags ) +int nbd_check_hello(struct nbd_init_raw *init_raw, uint64_t * out_size, + uint32_t * out_flags) { - if ( strncmp( init_raw->passwd, INIT_PASSWD, 8 ) != 0 ) { - warn( "wrong passwd" ); - goto fail; - } - if ( be64toh( init_raw->magic ) != INIT_MAGIC ) { - warn( "wrong magic (%x)", be64toh( init_raw->magic ) ); - goto fail; - } + if (strncmp(init_raw->passwd, INIT_PASSWD, 8) != 0) { + warn("wrong passwd"); + goto fail; + } + if (be64toh(init_raw->magic) != INIT_MAGIC) { + warn("wrong magic (%x)", be64toh(init_raw->magic)); + goto fail; + } - if ( NULL != out_size ) { - *out_size = be64toh( init_raw->size ); - } + if (NULL != out_size) { + *out_size = be64toh(init_raw->size); + } - if ( NULL != out_flags ) { - *out_flags = be32toh( init_raw->flags ); - } + if (NULL != out_flags) { + *out_flags = be32toh(init_raw->flags); + } - return 1; -fail: + return 1; + fail: + return 0; + +} + +int socket_nbd_read_hello(int fd, uint64_t * out_size, + uint32_t * out_flags) +{ + struct nbd_init_raw init_raw; + + + if (0 > readloop(fd, &init_raw, sizeof(init_raw))) { + warn("Couldn't read init"); return 0; + } + return nbd_check_hello(&init_raw, out_size, out_flags); } -int socket_nbd_read_hello( int fd, uint64_t* out_size, uint32_t* out_flags ) +void nbd_hello_to_buf(struct nbd_init_raw *buf, off64_t out_size, + uint32_t out_flags) { - struct nbd_init_raw init_raw; + struct nbd_init init; + memcpy(&init.passwd, INIT_PASSWD, 8); + init.magic = INIT_MAGIC; + init.size = out_size; + init.flags = out_flags; - if ( 0 > readloop( fd, &init_raw, sizeof(init_raw) ) ) { - warn( "Couldn't read init" ); - return 0; - } + memset(buf, 0, sizeof(struct nbd_init_raw)); // ensure reserved is 0s + nbd_h2r_init(&init, buf); - return nbd_check_hello( &init_raw, out_size, out_flags ); + return; } -void nbd_hello_to_buf( struct nbd_init_raw *buf, off64_t out_size, uint32_t out_flags ) +int socket_nbd_write_hello(int fd, off64_t out_size, uint32_t out_flags) { - struct nbd_init init; + struct nbd_init_raw init_raw; + nbd_hello_to_buf(&init_raw, out_size, out_flags); - memcpy( &init.passwd, INIT_PASSWD, 8 ); - init.magic = INIT_MAGIC; - init.size = out_size; - init.flags = out_flags; - - memset( buf, 0, sizeof( struct nbd_init_raw ) ); // ensure reserved is 0s - nbd_h2r_init( &init, buf ); - - return; + if (0 > writeloop(fd, &init_raw, sizeof(init_raw))) { + warn(SHOW_ERRNO("failed to write hello to socket")); + return 0; + } + return 1; } -int socket_nbd_write_hello( int fd, off64_t out_size, uint32_t out_flags ) +void fill_request(struct nbd_request_raw *request_raw, uint16_t type, + uint16_t flags, uint64_t from, uint32_t len) { - struct nbd_init_raw init_raw; - nbd_hello_to_buf( &init_raw, out_size, out_flags ); - - if ( 0 > writeloop( fd, &init_raw, sizeof( init_raw ) ) ) { - warn( SHOW_ERRNO( "failed to write hello to socket" ) ); - return 0; - } - return 1; + request_raw->magic = htobe32(REQUEST_MAGIC); + request_raw->type = htobe16(type); + request_raw->flags = htobe16(flags); + request_raw->handle.w = + (((uint64_t) rand()) << 32) | ((uint64_t) rand()); + request_raw->from = htobe64(from); + request_raw->len = htobe32(len); } -void fill_request(struct nbd_request_raw *request_raw, uint16_t type, uint16_t flags, uint64_t from, uint32_t len) +void read_reply(int fd, uint64_t request_raw_handle, + struct nbd_reply *reply) { - request_raw->magic = htobe32(REQUEST_MAGIC); - request_raw->type = htobe16(type); - request_raw->flags = htobe16(flags); - request_raw->handle.w = (((uint64_t)rand()) << 32) | ((uint64_t)rand()); - request_raw->from = htobe64(from); - request_raw->len = htobe32(len); + struct nbd_reply_raw reply_raw; + + ERROR_IF_NEGATIVE(readloop + (fd, &reply_raw, sizeof(struct nbd_reply_raw)), + "Couldn't read reply"); + + nbd_r2h_reply(&reply_raw, reply); + + if (reply->magic != REPLY_MAGIC) { + error("Reply magic incorrect (%x)", reply->magic); + } + if (reply->error != 0) { + error("Server replied with error %d", reply->error); + } + if (request_raw_handle != reply_raw.handle.w) { + error("Did not reply with correct handle"); + } } -void read_reply(int fd, uint64_t request_raw_handle, struct nbd_reply *reply) +void wait_for_data(int fd, int timeout_secs) { - struct nbd_reply_raw reply_raw; + fd_set fds; + struct timeval tv = { timeout_secs, 0 }; + int selected; - ERROR_IF_NEGATIVE(readloop(fd, &reply_raw, sizeof(struct nbd_reply_raw)), - "Couldn't read reply"); + FD_ZERO(&fds); + FD_SET(fd, &fds); - nbd_r2h_reply( &reply_raw, reply ); + selected = + sock_try_select(FD_SETSIZE, &fds, NULL, NULL, + timeout_secs >= 0 ? &tv : NULL); - if (reply->magic != REPLY_MAGIC) { - error("Reply magic incorrect (%x)", reply->magic); - } - if (reply->error != 0) { - error("Server replied with error %d", reply->error); - } - if (request_raw_handle != reply_raw.handle.w) { - error("Did not reply with correct handle"); - } -} - -void wait_for_data( int fd, int timeout_secs ) -{ - fd_set fds; - struct timeval tv = { timeout_secs, 0 }; - int selected; - - FD_ZERO( &fds ); - FD_SET( fd, &fds ); - - selected = sock_try_select( - FD_SETSIZE, &fds, NULL, NULL, timeout_secs >=0 ? &tv : NULL - ); - - FATAL_IF( -1 == selected, "Select failed" ); - ERROR_IF( 0 == selected, "Timed out waiting for reply" ); + FATAL_IF(-1 == selected, "Select failed"); + ERROR_IF(0 == selected, "Timed out waiting for reply"); } -void socket_nbd_read(int fd, uint64_t from, uint32_t len, int out_fd, void* out_buf, int timeout_secs) +void socket_nbd_read(int fd, uint64_t from, uint32_t len, int out_fd, + void *out_buf, int timeout_secs) { - struct nbd_request_raw request_raw; - struct nbd_reply reply; + struct nbd_request_raw request_raw; + struct nbd_reply reply; - fill_request(&request_raw, REQUEST_READ, 0, from, len); - FATAL_IF_NEGATIVE(writeloop(fd, &request_raw, sizeof(request_raw)), - "Couldn't write request"); + fill_request(&request_raw, REQUEST_READ, 0, from, len); + FATAL_IF_NEGATIVE(writeloop(fd, &request_raw, sizeof(request_raw)), + "Couldn't write request"); - wait_for_data( fd, timeout_secs ); - read_reply(fd, request_raw.handle.w, &reply); + wait_for_data(fd, timeout_secs); + read_reply(fd, request_raw.handle.w, &reply); - if (out_buf) { - FATAL_IF_NEGATIVE(readloop(fd, out_buf, len), - "Read failed"); - } - else { - FATAL_IF_NEGATIVE( - splice_via_pipe_loop(fd, out_fd, len), - "Splice failed" - ); - } + if (out_buf) { + FATAL_IF_NEGATIVE(readloop(fd, out_buf, len), "Read failed"); + } else { + FATAL_IF_NEGATIVE(splice_via_pipe_loop(fd, out_fd, len), + "Splice failed"); + } } -void socket_nbd_write(int fd, uint64_t from, uint32_t len, int in_fd, void* in_buf, int timeout_secs) +void socket_nbd_write(int fd, uint64_t from, uint32_t len, int in_fd, + void *in_buf, int timeout_secs) { - struct nbd_request_raw request_raw; - struct nbd_reply reply; + struct nbd_request_raw request_raw; + struct nbd_reply reply; - fill_request(&request_raw, REQUEST_WRITE, 0, from, len); - ERROR_IF_NEGATIVE(writeloop(fd, &request_raw, sizeof(request_raw)), - "Couldn't write request"); + fill_request(&request_raw, REQUEST_WRITE, 0, from, len); + ERROR_IF_NEGATIVE(writeloop(fd, &request_raw, sizeof(request_raw)), + "Couldn't write request"); - if (in_buf) { - ERROR_IF_NEGATIVE(writeloop(fd, in_buf, len), - "Write failed"); - } - else { - ERROR_IF_NEGATIVE( - splice_via_pipe_loop(in_fd, fd, len), - "Splice failed" - ); - } + if (in_buf) { + ERROR_IF_NEGATIVE(writeloop(fd, in_buf, len), "Write failed"); + } else { + ERROR_IF_NEGATIVE(splice_via_pipe_loop(in_fd, fd, len), + "Splice failed"); + } - wait_for_data( fd, timeout_secs ); - read_reply(fd, request_raw.handle.w, &reply); + wait_for_data(fd, timeout_secs); + read_reply(fd, request_raw.handle.w, &reply); } -int socket_nbd_disconnect( int fd ) +int socket_nbd_disconnect(int fd) { - int success = 1; - struct nbd_request_raw request_raw; + int success = 1; + struct nbd_request_raw request_raw; - fill_request( &request_raw, REQUEST_DISCONNECT, 0, 0, 0 ); - /* FIXME: This shouldn't be a FATAL error. We should just drop - * the mirror without affecting the main server. - */ - FATAL_IF_NEGATIVE( writeloop( fd, &request_raw, sizeof( request_raw ) ), - "Failed to write the disconnect request." ); - return success; + fill_request(&request_raw, REQUEST_DISCONNECT, 0, 0, 0); + /* FIXME: This shouldn't be a FATAL error. We should just drop + * the mirror without affecting the main server. + */ + FATAL_IF_NEGATIVE(writeloop(fd, &request_raw, sizeof(request_raw)), + "Failed to write the disconnect request."); + return success; } #define CHECK_RANGE(error_type) { \ @@ -237,23 +240,26 @@ int socket_nbd_disconnect( int fd ) }\ } -void do_read(struct mode_readwrite_params* params) +void do_read(struct mode_readwrite_params *params) { - params->client = socket_connect(¶ms->connect_to.generic, ¶ms->connect_from.generic); - FATAL_IF_NEGATIVE( params->client, "Couldn't connect." ); - CHECK_RANGE("read"); - socket_nbd_read(params->client, params->from, params->len, - params->data_fd, NULL, 10); - close(params->client); + params->client = + socket_connect(¶ms->connect_to.generic, + ¶ms->connect_from.generic); + FATAL_IF_NEGATIVE(params->client, "Couldn't connect."); + CHECK_RANGE("read"); + socket_nbd_read(params->client, params->from, params->len, + params->data_fd, NULL, 10); + close(params->client); } -void do_write(struct mode_readwrite_params* params) +void do_write(struct mode_readwrite_params *params) { - params->client = socket_connect(¶ms->connect_to.generic, ¶ms->connect_from.generic); - FATAL_IF_NEGATIVE( params->client, "Couldn't connect." ); - CHECK_RANGE("write"); - socket_nbd_write(params->client, params->from, params->len, - params->data_fd, NULL, 10); - close(params->client); + params->client = + socket_connect(¶ms->connect_to.generic, + ¶ms->connect_from.generic); + FATAL_IF_NEGATIVE(params->client, "Couldn't connect."); + CHECK_RANGE("write"); + socket_nbd_write(params->client, params->from, params->len, + params->data_fd, NULL, 10); + close(params->client); } - diff --git a/src/common/readwrite.h b/src/common/readwrite.h index 8b7371b..a358646 100644 --- a/src/common/readwrite.h +++ b/src/common/readwrite.h @@ -6,18 +6,21 @@ #include #include "nbdtypes.h" -int socket_connect(struct sockaddr* to, struct sockaddr* from); -int socket_nbd_read_hello(int fd, uint64_t* size, uint32_t* flags); +int socket_connect(struct sockaddr *to, struct sockaddr *from); +int socket_nbd_read_hello(int fd, uint64_t * size, uint32_t * flags); int socket_nbd_write_hello(int fd, uint64_t size, uint32_t flags); -void socket_nbd_read(int fd, uint64_t from, uint32_t len, int out_fd, void* out_buf, int timeout_secs); -void socket_nbd_write(int fd, uint64_t from, uint32_t len, int out_fd, void* out_buf, int timeout_secs); -int socket_nbd_disconnect( int fd ); +void socket_nbd_read(int fd, uint64_t from, uint32_t len, int out_fd, + void *out_buf, int timeout_secs); +void socket_nbd_write(int fd, uint64_t from, uint32_t len, int out_fd, + void *out_buf, int timeout_secs); +int socket_nbd_disconnect(int fd); /* as you can see, we're slowly accumulating code that should really be in an * NBD library */ -void nbd_hello_to_buf( struct nbd_init_raw* buf, uint64_t out_size, uint32_t out_flags ); -int nbd_check_hello( struct nbd_init_raw* init_raw, uint64_t* out_size, uint32_t* out_flags ); +void nbd_hello_to_buf(struct nbd_init_raw *buf, uint64_t out_size, + uint32_t out_flags); +int nbd_check_hello(struct nbd_init_raw *init_raw, uint64_t * out_size, + uint32_t * out_flags); #endif - diff --git a/src/common/remote.c b/src/common/remote.c index 43830a5..f379940 100644 --- a/src/common/remote.c +++ b/src/common/remote.c @@ -4,64 +4,62 @@ #include #include -static const int max_response=1024; +static const int max_response = 1024; -void print_response( const char * response ) +void print_response(const char *response) { - char * response_text; - FILE * out; - int exit_status; + char *response_text; + FILE *out; + int exit_status; - NULLCHECK( response ); + NULLCHECK(response); - exit_status = atoi(response); - response_text = strchr( response, ':' ); + exit_status = atoi(response); + response_text = strchr(response, ':'); - FATAL_IF_NULL( response_text, - "Error parsing server response: '%s'", response ); + FATAL_IF_NULL(response_text, + "Error parsing server response: '%s'", response); - out = exit_status > 0 ? stderr : stdout; - fprintf(out, "%s\n", response_text + 2); + out = exit_status > 0 ? stderr : stdout; + fprintf(out, "%s\n", response_text + 2); } -void do_remote_command(char* command, char* socket_name, int argc, char** argv) +void do_remote_command(char *command, char *socket_name, int argc, + char **argv) { - char newline=10; - int i; - debug( "connecting to run remote command %s", command ); - int remote = socket(AF_UNIX, SOCK_STREAM, 0); - struct sockaddr_un address; - char response[max_response]; + char newline = 10; + int i; + debug("connecting to run remote command %s", command); + int remote = socket(AF_UNIX, SOCK_STREAM, 0); + struct sockaddr_un address; + char response[max_response]; - memset(&address, 0, sizeof(address)); + memset(&address, 0, sizeof(address)); - FATAL_IF_NEGATIVE(remote, "Couldn't create client socket"); + FATAL_IF_NEGATIVE(remote, "Couldn't create client socket"); - address.sun_family = AF_UNIX; - strncpy(address.sun_path, socket_name, sizeof(address.sun_path)); + address.sun_family = AF_UNIX; + strncpy(address.sun_path, socket_name, sizeof(address.sun_path)); - FATAL_IF_NEGATIVE( - connect(remote, (struct sockaddr*) &address, sizeof(address)), - "Couldn't connect to %s", socket_name - ); + FATAL_IF_NEGATIVE(connect + (remote, (struct sockaddr *) &address, + sizeof(address)), "Couldn't connect to %s", + socket_name); - write(remote, command, strlen(command)); - write(remote, &newline, 1); - for (i=0; iread_fd = fds[0]; - sig->write_fd = fds[1]; + return NULL; + } - return sig; + sig->read_fd = fds[0]; + sig->write_fd = fds[1]; + + return sig; } @@ -83,19 +86,19 @@ struct self_pipe * self_pipe_create(void) * Returns 1 on success. Can fail if weirdness happened to the write fd * of the pipe in the self_pipe struct. */ -int self_pipe_signal( struct self_pipe * sig ) +int self_pipe_signal(struct self_pipe *sig) { - NULLCHECK( sig ); - FATAL_IF( 1 == sig->write_fd, "Shouldn't be writing to stdout" ); - FATAL_IF( 2 == sig->write_fd, "Shouldn't be writing to stderr" ); + NULLCHECK(sig); + FATAL_IF(1 == sig->write_fd, "Shouldn't be writing to stdout"); + FATAL_IF(2 == sig->write_fd, "Shouldn't be writing to stderr"); - int written = write( sig->write_fd, "X", 1 ); - if ( written != 1 ) { - self_pipe_server_error( errno, ERR_MSG_WRITE ); - return 0; - } + int written = write(sig->write_fd, "X", 1); + if (written != 1) { + self_pipe_server_error(errno, ERR_MSG_WRITE); + return 0; + } - return 1; + return 1; } @@ -106,11 +109,11 @@ int self_pipe_signal( struct self_pipe * sig ) * Returns the number of bytes read, which will be 1 on success and 0 if * there was no signal. */ -int self_pipe_signal_clear( struct self_pipe *sig ) +int self_pipe_signal_clear(struct self_pipe *sig) { - char buf[1]; + char buf[1]; - return 1 == read( sig->read_fd, buf, 1 ); + return 1 == read(sig->read_fd, buf, 1); } @@ -118,30 +121,30 @@ int self_pipe_signal_clear( struct self_pipe *sig ) * Close the pipe and free the self_pipe. Do not try to use the * self_pipe struct after calling this, the innards are mush. */ -int self_pipe_destroy( struct self_pipe * sig ) +int self_pipe_destroy(struct self_pipe *sig) { - NULLCHECK(sig); + NULLCHECK(sig); - while( close( sig->read_fd ) == -1 && errno == EINTR ); - while( close( sig->write_fd ) == -1 && errno == EINTR ); + while (close(sig->read_fd) == -1 && errno == EINTR); + while (close(sig->write_fd) == -1 && errno == EINTR); - /* Just in case anyone *does* try to use this after free, - * we should set the memory locations to an error value - */ - sig->read_fd = -1; - sig->write_fd = -1; + /* Just in case anyone *does* try to use this after free, + * we should set the memory locations to an error value + */ + sig->read_fd = -1; + sig->write_fd = -1; - free( sig ); - return 1; + free(sig); + return 1; } -int self_pipe_fd_set( struct self_pipe * sig, fd_set * fds) +int self_pipe_fd_set(struct self_pipe *sig, fd_set * fds) { - FD_SET( sig->read_fd, fds ); - return 1; + FD_SET(sig->read_fd, fds); + return 1; } -int self_pipe_fd_isset( struct self_pipe * sig, fd_set * fds) +int self_pipe_fd_isset(struct self_pipe *sig, fd_set * fds) { - return FD_ISSET( sig->read_fd, fds ); + return FD_ISSET(sig->read_fd, fds); } diff --git a/src/common/self_pipe.h b/src/common/self_pipe.h index 76576df..561519f 100644 --- a/src/common/self_pipe.h +++ b/src/common/self_pipe.h @@ -4,16 +4,16 @@ #include struct self_pipe { - int read_fd; - int write_fd; + int read_fd; + int write_fd; }; -struct self_pipe * self_pipe_create(void); -int self_pipe_signal( struct self_pipe * sig ); -int self_pipe_signal_clear( struct self_pipe *sig ); -int self_pipe_destroy( struct self_pipe * sig ); -int self_pipe_fd_set( struct self_pipe * sig, fd_set * fds ); -int self_pipe_fd_isset( struct self_pipe *sig, fd_set *fds ); +struct self_pipe *self_pipe_create(void); +int self_pipe_signal(struct self_pipe *sig); +int self_pipe_signal_clear(struct self_pipe *sig); +int self_pipe_destroy(struct self_pipe *sig); +int self_pipe_fd_set(struct self_pipe *sig, fd_set * fds); +int self_pipe_fd_isset(struct self_pipe *sig, fd_set * fds); #endif diff --git a/src/common/sockutil.c b/src/common/sockutil.c index 56d728f..6dfe3ae 100644 --- a/src/common/sockutil.c +++ b/src/common/sockutil.c @@ -9,279 +9,287 @@ #include "sockutil.h" #include "util.h" -size_t sockaddr_size( const struct sockaddr* sa ) +size_t sockaddr_size(const struct sockaddr * sa) { - struct sockaddr_un* un = (struct sockaddr_un*) sa; - size_t ret = 0; + struct sockaddr_un *un = (struct sockaddr_un *) sa; + size_t ret = 0; - switch( sa->sa_family ) { - case AF_INET: - ret = sizeof( struct sockaddr_in ); - break; - case AF_INET6: - ret = sizeof( struct sockaddr_in6 ); - break; - case AF_UNIX: - ret = sizeof( un->sun_family ) + SUN_LEN( un ); - break; - } + switch (sa->sa_family) { + case AF_INET: + ret = sizeof(struct sockaddr_in); + break; + case AF_INET6: + ret = sizeof(struct sockaddr_in6); + break; + case AF_UNIX: + ret = sizeof(un->sun_family) + SUN_LEN(un); + break; + } - return ret; + return ret; } -const char* sockaddr_address_string( const struct sockaddr* sa, char* dest, size_t len ) +const char *sockaddr_address_string(const struct sockaddr *sa, char *dest, + size_t len) { - NULLCHECK( sa ); - NULLCHECK( dest ); + NULLCHECK(sa); + NULLCHECK(dest); - struct sockaddr_in* in = ( struct sockaddr_in* ) sa; - struct sockaddr_in6* in6 = ( struct sockaddr_in6* ) sa; - struct sockaddr_un* un = ( struct sockaddr_un* ) sa; + struct sockaddr_in *in = (struct sockaddr_in *) sa; + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) sa; + struct sockaddr_un *un = (struct sockaddr_un *) sa; - unsigned short real_port = ntohs( in->sin_port ); // common to in and in6 - const char* ret = NULL; + unsigned short real_port = ntohs(in->sin_port); // common to in and in6 + const char *ret = NULL; - memset( dest, 0, len ); + memset(dest, 0, len); - if ( sa->sa_family == AF_INET ) { - ret = inet_ntop( AF_INET, &in->sin_addr, dest, len ); - } else if ( sa->sa_family == AF_INET6 ) { - ret = inet_ntop( AF_INET6, &in6->sin6_addr, dest, len ); - } else if ( sa->sa_family == AF_UNIX ) { - ret = strncpy( dest, un->sun_path, SUN_LEN( un ) ); - } + if (sa->sa_family == AF_INET) { + ret = inet_ntop(AF_INET, &in->sin_addr, dest, len); + } else if (sa->sa_family == AF_INET6) { + ret = inet_ntop(AF_INET6, &in6->sin6_addr, dest, len); + } else if (sa->sa_family == AF_UNIX) { + ret = strncpy(dest, un->sun_path, SUN_LEN(un)); + } - if ( ret == NULL ) { - strncpy( dest, "???", len ); - } + if (ret == NULL) { + strncpy(dest, "???", len); + } - if ( NULL != ret && real_port > 0 && sa->sa_family != AF_UNIX ) { - size_t size = strlen( dest ); - snprintf( dest + size, len - size, " port %d", real_port ); - } + if (NULL != ret && real_port > 0 && sa->sa_family != AF_UNIX) { + size_t size = strlen(dest); + snprintf(dest + size, len - size, " port %d", real_port); + } - return ret; + return ret; } -int sock_set_reuseaddr( int fd, int optval ) +int sock_set_reuseaddr(int fd, int optval) { - return setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval) ); + return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, + sizeof(optval)); } -int sock_set_keepalive_params( int fd, int time, int intvl, int probes) +int sock_set_keepalive_params(int fd, int time, int intvl, int probes) { - if (sock_set_keepalive(fd, 1) || - sock_set_tcp_keepidle(fd, time) || - sock_set_tcp_keepintvl(fd, intvl) || - sock_set_tcp_keepcnt(fd, probes)) { - return -1; - } - return 0; + if (sock_set_keepalive(fd, 1) || + sock_set_tcp_keepidle(fd, time) || + sock_set_tcp_keepintvl(fd, intvl) || + sock_set_tcp_keepcnt(fd, probes)) { + return -1; + } + return 0; } -int sock_set_keepalive( int fd, int optval ) +int sock_set_keepalive(int fd, int optval) { - return setsockopt( fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval) ); + return setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, + sizeof(optval)); } -int sock_set_tcp_keepidle( int fd, int optval ) +int sock_set_tcp_keepidle(int fd, int optval) { - return setsockopt( fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, sizeof(optval) ); + return setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, + sizeof(optval)); } -int sock_set_tcp_keepintvl( int fd, int optval ) +int sock_set_tcp_keepintvl(int fd, int optval) { - return setsockopt( fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, sizeof(optval) ); + return setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, + sizeof(optval)); } -int sock_set_tcp_keepcnt( int fd, int optval ) +int sock_set_tcp_keepcnt(int fd, int optval) { - return setsockopt( fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(optval) ); + return setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, + sizeof(optval)); } /* Set the tcp_nodelay option */ -int sock_set_tcp_nodelay( int fd, int optval ) +int sock_set_tcp_nodelay(int fd, int optval) { - return setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval) ); + return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, + sizeof(optval)); } -int sock_set_tcp_cork( int fd, int optval ) +int sock_set_tcp_cork(int fd, int optval) { - return setsockopt( fd, IPPROTO_TCP, TCP_CORK, &optval, sizeof(optval) ); + return setsockopt(fd, IPPROTO_TCP, TCP_CORK, &optval, sizeof(optval)); } -int sock_set_nonblock( int fd, int optval ) +int sock_set_nonblock(int fd, int optval) { - int flags = fcntl( fd, F_GETFL ); + int flags = fcntl(fd, F_GETFL); - if ( flags == -1 ) { - return -1; - } + if (flags == -1) { + return -1; + } - if ( optval ) { - flags = flags | O_NONBLOCK; + if (optval) { + flags = flags | O_NONBLOCK; + } else { + flags = flags & (~O_NONBLOCK); + } + + return fcntl(fd, F_SETFL, flags); +} + +int sock_try_bind(int fd, const struct sockaddr *sa) +{ + int bind_result; + char s_address[256]; + int retry = 10; + + sockaddr_address_string(sa, &s_address[0], 256); + + do { + bind_result = bind(fd, sa, sockaddr_size(sa)); + if (0 == bind_result) { + info("Bound to %s", s_address); + break; } else { - flags = flags & (~O_NONBLOCK); + warn(SHOW_ERRNO("Couldn't bind to %s", s_address)); + + switch (errno) { + /* bind() can give us EACCES, EADDRINUSE, EADDRNOTAVAIL, EBADF, + * EINVAL, ENOTSOCK, EFAULT, ELOOP, ENAMETOOLONG, ENOENT, + * ENOMEM, ENOTDIR, EROFS + * + * Any of these other than EADDRINUSE & EADDRNOTAVAIL signify + * that there's a logic error somewhere. + * + * EADDRINUSE is fatal: if there's something already where we + * want to be listening, we have no guarantees that any clients + * will cope with it. + */ + case EADDRNOTAVAIL: + retry--; + if (retry) { + debug("retrying"); + sleep(1); + } + continue; + case EADDRINUSE: + warn("%s in use, giving up.", s_address); + retry = 0; + break; + default: + warn("giving up"); + retry = 0; + } + } + } while (retry); + + return bind_result; +} + +int sock_try_select(int nfds, fd_set * readfds, fd_set * writefds, + fd_set * exceptfds, struct timeval *timeout) +{ + int result; + + do { + result = select(nfds, readfds, writefds, exceptfds, timeout); + if (errno != EINTR) { + break; } - return fcntl( fd, F_SETFL, flags ); + } while (result == -1); + + return result; } -int sock_try_bind( int fd, const struct sockaddr* sa ) +int sock_try_connect(int fd, struct sockaddr *to, socklen_t addrlen, + int wait) { - int bind_result; - char s_address[256]; - int retry = 10; + fd_set fds; + struct timeval tv = { wait, 0 }; + int result = 0; - sockaddr_address_string( sa, &s_address[0], 256 ); + if (sock_set_nonblock(fd, 1) == -1) { + warn(SHOW_ERRNO + ("Failed to set socket non-blocking for connect()")); + return connect(fd, to, addrlen); + } - do { - bind_result = bind( fd, sa, sockaddr_size( sa ) ); - if ( 0 == bind_result ) { - info( "Bound to %s", s_address ); - break; - } - else { - warn( SHOW_ERRNO( "Couldn't bind to %s", s_address ) ); + FD_ZERO(&fds); + FD_SET(fd, &fds); - switch ( errno ) { - /* bind() can give us EACCES, EADDRINUSE, EADDRNOTAVAIL, EBADF, - * EINVAL, ENOTSOCK, EFAULT, ELOOP, ENAMETOOLONG, ENOENT, - * ENOMEM, ENOTDIR, EROFS - * - * Any of these other than EADDRINUSE & EADDRNOTAVAIL signify - * that there's a logic error somewhere. - * - * EADDRINUSE is fatal: if there's something already where we - * want to be listening, we have no guarantees that any clients - * will cope with it. - */ - case EADDRNOTAVAIL: - retry--; - if (retry) { - debug( "retrying" ); - sleep( 1 ); - } - continue; - case EADDRINUSE: - warn( "%s in use, giving up.", s_address ); - retry = 0; - break; - default: - warn( "giving up" ); - retry = 0; - } - } - } while ( retry ); + do { + result = connect(fd, to, addrlen); - return bind_result; -} - -int sock_try_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -{ - int result; - - do { - result = select(nfds, readfds, writefds, exceptfds, timeout); - if ( errno != EINTR ) { - break; - } - - } while ( result == -1 ); - - return result; -} - -int sock_try_connect( int fd, struct sockaddr* to, socklen_t addrlen, int wait ) -{ - fd_set fds; - struct timeval tv = { wait, 0 }; - int result = 0; - - if ( sock_set_nonblock( fd, 1 ) == -1 ) { - warn( SHOW_ERRNO( "Failed to set socket non-blocking for connect()" ) ); - return connect( fd, to, addrlen ); - } - - FD_ZERO( &fds ); - FD_SET( fd, &fds ); - - do { - result = connect( fd, to, addrlen ); - - if ( result == -1 ) { - switch( errno ) { - case EINPROGRESS: - result = 0; - break; /* success */ - case EAGAIN: - case EINTR: - /* Try connect() again. This only breaks out of the switch, - * not the do...while loop. since result == -1, we go again. - */ - break; - default: - warn( SHOW_ERRNO( "Failed to connect()" ) ); - goto out; - } - } - } while ( result == -1 ); - - if ( -1 == sock_try_select( FD_SETSIZE, NULL, &fds, NULL, &tv) ) { - warn( SHOW_ERRNO( "failed to select() on non-blocking connect" ) ); - result = -1; + if (result == -1) { + switch (errno) { + case EINPROGRESS: + result = 0; + break; /* success */ + case EAGAIN: + case EINTR: + /* Try connect() again. This only breaks out of the switch, + * not the do...while loop. since result == -1, we go again. + */ + break; + default: + warn(SHOW_ERRNO("Failed to connect()")); goto out; + } } + } while (result == -1); - if ( !FD_ISSET( fd, &fds ) ) { - result = -1; - errno = ETIMEDOUT; - goto out; - } + if (-1 == sock_try_select(FD_SETSIZE, NULL, &fds, NULL, &tv)) { + warn(SHOW_ERRNO("failed to select() on non-blocking connect")); + result = -1; + goto out; + } - int scratch; - socklen_t s_size = sizeof( scratch ); - if ( getsockopt( fd, SOL_SOCKET, SO_ERROR, &scratch, &s_size ) == -1 ) { - result = -1; - warn( SHOW_ERRNO( "getsockopt() failed" ) ); - goto out; - } + if (!FD_ISSET(fd, &fds)) { + result = -1; + errno = ETIMEDOUT; + goto out; + } - if ( scratch == EINPROGRESS ) { - scratch = ETIMEDOUT; - } + int scratch; + socklen_t s_size = sizeof(scratch); + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &scratch, &s_size) == -1) { + result = -1; + warn(SHOW_ERRNO("getsockopt() failed")); + goto out; + } - result = scratch ? -1 : 0; - errno = scratch; + if (scratch == EINPROGRESS) { + scratch = ETIMEDOUT; + } -out: - if ( sock_set_nonblock( fd, 0 ) == -1 ) { - warn( SHOW_ERRNO( "Failed to make socket blocking after connect()" ) ); - return -1; - } + result = scratch ? -1 : 0; + errno = scratch; - debug( "sock_try_connect: %i", result ); - return result; + out: + if (sock_set_nonblock(fd, 0) == -1) { + warn(SHOW_ERRNO("Failed to make socket blocking after connect()")); + return -1; + } + + debug("sock_try_connect: %i", result); + return result; } -int sock_try_close( int fd ) +int sock_try_close(int fd) { - int result; + int result; - do { - result = close( fd ); + do { + result = close(fd); - if ( result == -1 ) { - if ( EINTR == errno ) { - continue; /* retry EINTR */ - } else { - warn( SHOW_ERRNO( "Failed to close() fd %i", fd ) ); - break; /* Other errors get reported */ - } - } + if (result == -1) { + if (EINTR == errno) { + continue; /* retry EINTR */ + } else { + warn(SHOW_ERRNO("Failed to close() fd %i", fd)); + break; /* Other errors get reported */ + } + } - } while( 0 ); + } while (0); - return result; + return result; } - diff --git a/src/common/sockutil.h b/src/common/sockutil.h index 94dbf85..a68ae5c 100644 --- a/src/common/sockutil.h +++ b/src/common/sockutil.h @@ -7,15 +7,16 @@ #include /* Returns the size of the sockaddr, or 0 on error */ -size_t sockaddr_size(const struct sockaddr* sa); +size_t sockaddr_size(const struct sockaddr *sa); /* Convert a sockaddr into an address. Like inet_ntop, it returns dest if * successful, NULL otherwise. In the latter case, dest will contain "???" */ -const char* sockaddr_address_string(const struct sockaddr* sa, char* dest, size_t len); +const char *sockaddr_address_string(const struct sockaddr *sa, char *dest, + size_t len); /* Configure TCP keepalive on a socket */ -int sock_set_keepalive_params( int fd, int time, int intvl, int probes); +int sock_set_keepalive_params(int fd, int time, int intvl, int probes); /* Set the SOL_KEEPALIVE otion */ int sock_set_keepalive(int fd, int optval); @@ -41,16 +42,17 @@ int sock_set_tcp_cork(int fd, int optval); int sock_set_nonblock(int fd, int optval); /* Attempt to bind the fd to the sockaddr, retrying common transient failures */ -int sock_try_bind(int fd, const struct sockaddr* sa); +int sock_try_bind(int fd, const struct sockaddr *sa); /* Try to call select(), retrying EINTR */ -int sock_try_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); +int sock_try_select(int nfds, fd_set * readfds, fd_set * writefds, + fd_set * exceptfds, struct timeval *timeout); /* Try to call connect(), timing out after wait seconds */ -int sock_try_connect( int fd, struct sockaddr* to, socklen_t addrlen, int wait ); +int sock_try_connect(int fd, struct sockaddr *to, socklen_t addrlen, + int wait); /* Try to call close(), retrying EINTR */ -int sock_try_close( int fd ); +int sock_try_close(int fd); #endif - diff --git a/src/common/util.c b/src/common/util.c index b6a279b..6cf66d6 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -17,72 +17,75 @@ char *log_context = ""; void error_init(void) { - pthread_key_create(&cleanup_handler_key, free); + pthread_key_create(&cleanup_handler_key, free); } void error_handler(int fatal) { - DECLARE_ERROR_CONTEXT(context); + DECLARE_ERROR_CONTEXT(context); - if (context) { - longjmp(context->jmp, fatal ? 1 : 2 ); - } - else { - if ( fatal ) { abort(); } - else { pthread_exit((void*) 1); } + if (context) { + longjmp(context->jmp, fatal ? 1 : 2); + } else { + if (fatal) { + abort(); + } else { + pthread_exit((void *) 1); } + } } -void exit_err( const char *msg ) +void exit_err(const char *msg) { - fprintf( stderr, "%s\n", msg ); - exit( 1 ); + fprintf(stderr, "%s\n", msg); + exit(1); } -void mylog(int line_level, const char* format, ...) +void mylog(int line_level, const char *format, ...) { - if (line_level < log_level) { return; } + if (line_level < log_level) { + return; + } - va_list argptr; + va_list argptr; - va_start(argptr, format); - vfprintf(stderr, format, argptr); - va_end(argptr); + va_start(argptr, format); + vfprintf(stderr, format, argptr); + va_end(argptr); } uint64_t monotonic_time_ms() { - struct timespec ts; - uint64_t seconds_ms, nanoseconds_ms; + struct timespec ts; + uint64_t seconds_ms, nanoseconds_ms; - FATAL_IF_NEGATIVE( - clock_gettime(CLOCK_MONOTONIC, &ts), - SHOW_ERRNO( "clock_gettime failed" ) + FATAL_IF_NEGATIVE(clock_gettime(CLOCK_MONOTONIC, &ts), + SHOW_ERRNO("clock_gettime failed") ); - seconds_ms = ts.tv_sec; - seconds_ms = seconds_ms * 1000; + seconds_ms = ts.tv_sec; + seconds_ms = seconds_ms * 1000; - nanoseconds_ms = ts.tv_nsec; - nanoseconds_ms = nanoseconds_ms / 1000000; + nanoseconds_ms = ts.tv_nsec; + nanoseconds_ms = nanoseconds_ms / 1000000; - return seconds_ms + nanoseconds_ms; + return seconds_ms + nanoseconds_ms; } -void* xrealloc(void* ptr, size_t size) +void *xrealloc(void *ptr, size_t size) { - void* p = realloc(ptr, size); - FATAL_IF_NULL(p, "couldn't xrealloc %d bytes", ptr ? "realloc" : "malloc", size); - return p; + void *p = realloc(ptr, size); + FATAL_IF_NULL(p, "couldn't xrealloc %d bytes", + ptr ? "realloc" : "malloc", size); + return p; } -void* xmalloc(size_t size) +void *xmalloc(size_t size) { - void* p = xrealloc(NULL, size); - memset(p, 0, size); - return p; + void *p = xrealloc(NULL, size); + memset(p, 0, size); + return p; } - diff --git a/src/common/util.h b/src/common/util.h index 3f05e78..c984e5f 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -10,10 +10,11 @@ #include #include -void* xrealloc(void* ptr, size_t size); -void* xmalloc(size_t size); +void *xrealloc(void *ptr, size_t size); +void *xmalloc(size_t size); -typedef void (cleanup_handler)(void* /* context */, int /* is fatal? */); +typedef void (cleanup_handler) (void * /* context */ , + int /* is fatal? */ ); /* set from 0 - 5 depending on what level of verbosity you want */ extern int log_level; @@ -25,15 +26,15 @@ void error_init(void); extern char *log_context; -void exit_err( const char * ); +void exit_err(const char *); /* error_set_handler must be a macro not a function due to setjmp stack rules */ #include struct error_handler_context { - jmp_buf jmp; - cleanup_handler* handler; - void* data; + jmp_buf jmp; + cleanup_handler *handler; + void *data; }; #define DECLARE_ERROR_CONTEXT(name) \ @@ -87,7 +88,7 @@ extern pthread_key_t cleanup_handler_key; void error_handler(int fatal); /* mylog a line at the given level (0 being most verbose) */ -void mylog(int line_level, const char* format, ...); +void mylog(int line_level, const char *format, ...); /* Returns the current time, in milliseconds, from CLOCK_MONOTONIC */ uint64_t monotonic_time_ms(void); @@ -98,9 +99,9 @@ uint64_t monotonic_time_ms(void); #define myloglev(level, msg, ...) mylog( level, "%"PRIu64":%c:%d %p %s %s:%d: "msg"\n", monotonic_time_ms(), levstr(level), getpid(),pthread_self(), log_context, __FILE__, __LINE__, ##__VA_ARGS__ ) #ifdef DEBUG -# define debug(msg, ...) myloglev(0, msg, ##__VA_ARGS__) +#define debug(msg, ...) myloglev(0, msg, ##__VA_ARGS__) #else -# define debug(msg, ...) /* no-op */ +#define debug(msg, ...) /* no-op */ #endif /* informational message, not expected to be compiled out */ @@ -162,4 +163,3 @@ uint64_t monotonic_time_ms(void); #define WARN_IF_NEGATIVE( value, msg, ... ) if ( value < 0 ) { warn( msg, ##__VA_ARGS__ ); } #endif - diff --git a/src/main.c b/src/main.c index aaf37dd..463057f 100644 --- a/src/main.c +++ b/src/main.c @@ -5,18 +5,17 @@ #include #include -int main(int argc, char** argv) +int main(int argc, char **argv) { - signal(SIGPIPE, SIG_IGN); /* calls to splice() unhelpfully throw this */ - error_init(); + signal(SIGPIPE, SIG_IGN); /* calls to splice() unhelpfully throw this */ + error_init(); - srand(time(NULL)); + srand(time(NULL)); - if (argc < 2) { - exit_err( help_help_text ); - } - mode(argv[1], argc-1, argv+1); /* never returns */ + if (argc < 2) { + exit_err(help_help_text); + } + mode(argv[1], argc - 1, argv + 1); /* never returns */ - return 0; + return 0; } - diff --git a/src/proxy-main.c b/src/proxy-main.c index fae4d07..7e382b8 100644 --- a/src/proxy-main.c +++ b/src/proxy-main.c @@ -8,164 +8,158 @@ static struct option proxy_options[] = { - GETOPT_HELP, - GETOPT_ADDR, - GETOPT_PORT, - GETOPT_CONNECT_ADDR, - GETOPT_CONNECT_PORT, - GETOPT_BIND, - GETOPT_CACHE, - GETOPT_QUIET, - GETOPT_VERBOSE, - {0} + GETOPT_HELP, + GETOPT_ADDR, + GETOPT_PORT, + GETOPT_CONNECT_ADDR, + GETOPT_CONNECT_PORT, + GETOPT_BIND, + GETOPT_CACHE, + GETOPT_QUIET, + GETOPT_VERBOSE, + {0} }; + static char proxy_short_options[] = "hl:p:C:P:b:" SOPT_QUIET SOPT_VERBOSE; static char proxy_help_text[] = - "Usage: flexnbd-proxy \n\n" - "Resiliently proxy an NBD connection between client and server\n" - "We can listen on TCP or UNIX socket, but only connect to TCP servers.\n\n" - HELP_LINE - "\t--" OPT_ADDR ",-l \tThe address we will bind to as a proxy.\n" - "\t--" OPT_PORT ",-p \tThe port we will bind to as a proxy, if required.\n" - "\t--" OPT_CONNECT_ADDR ",-C \tAddress of the proxied server.\n" - "\t--" OPT_CONNECT_PORT ",-P \tPort of the proxied server.\n" - "\t--" OPT_BIND ",-b \tThe address we connect from, as a proxy.\n" - "\t--" OPT_CACHE ",-c[=]\tUse a RAM read cache of the given size.\n" - QUIET_LINE - VERBOSE_LINE; + "Usage: flexnbd-proxy \n\n" + "Resiliently proxy an NBD connection between client and server\n" + "We can listen on TCP or UNIX socket, but only connect to TCP servers.\n\n" + HELP_LINE + "\t--" OPT_ADDR ",-l \tThe address we will bind to as a proxy.\n" + "\t--" OPT_PORT + ",-p \tThe port we will bind to as a proxy, if required.\n" + "\t--" OPT_CONNECT_ADDR ",-C \tAddress of the proxied server.\n" + "\t--" OPT_CONNECT_PORT ",-P \tPort of the proxied server.\n" + "\t--" OPT_BIND + ",-b \tThe address we connect from, as a proxy.\n" "\t--" + OPT_CACHE + ",-c[=]\tUse a RAM read cache of the given size.\n" + QUIET_LINE VERBOSE_LINE; static char proxy_default_cache_size[] = "4096"; -void read_proxy_param( - int c, - char **downstream_addr, - char **downstream_port, - char **upstream_addr, - char **upstream_port, - char **bind_addr, - char **cache_bytes) +void read_proxy_param(int c, + char **downstream_addr, + char **downstream_port, + char **upstream_addr, + char **upstream_port, + char **bind_addr, char **cache_bytes) { - switch( c ) { - case 'h' : - fprintf( stdout, "%s\n", proxy_help_text ); - exit( 0 ); - case 'l': - *downstream_addr = optarg; - break; - case 'p': - *downstream_port = optarg; - break; - case 'C': - *upstream_addr = optarg; - break; - case 'P': - *upstream_port = optarg; - break; - case 'b': - *bind_addr = optarg; - break; - case 'c': - *cache_bytes = optarg ? optarg : proxy_default_cache_size; - break; - case 'q': - log_level = QUIET_LOG_LEVEL; - break; - case 'v': - log_level = VERBOSE_LOG_LEVEL; - break; - default: - exit_err( proxy_help_text ); - break; - } + switch (c) { + case 'h': + fprintf(stdout, "%s\n", proxy_help_text); + exit(0); + case 'l': + *downstream_addr = optarg; + break; + case 'p': + *downstream_port = optarg; + break; + case 'C': + *upstream_addr = optarg; + break; + case 'P': + *upstream_port = optarg; + break; + case 'b': + *bind_addr = optarg; + break; + case 'c': + *cache_bytes = optarg ? optarg : proxy_default_cache_size; + break; + case 'q': + log_level = QUIET_LOG_LEVEL; + break; + case 'v': + log_level = VERBOSE_LOG_LEVEL; + break; + default: + exit_err(proxy_help_text); + break; + } } -struct proxier * proxy = NULL; +struct proxier *proxy = NULL; void my_exit(int signum) { - info( "Exit signalled (%i)", signum ); - if ( NULL != proxy ) { - proxy_cleanup( proxy ); - }; - exit( 0 ); + info("Exit signalled (%i)", signum); + if (NULL != proxy) { + proxy_cleanup(proxy); + }; + exit(0); } -int main( int argc, char *argv[] ) +int main(int argc, char *argv[]) { - int c; - char *downstream_addr = NULL; - char *downstream_port = NULL; - char *upstream_addr = NULL; - char *upstream_port = NULL; - char *bind_addr = NULL; - char *cache_bytes = NULL; - int success; + int c; + char *downstream_addr = NULL; + char *downstream_port = NULL; + char *upstream_addr = NULL; + char *upstream_port = NULL; + char *bind_addr = NULL; + char *cache_bytes = NULL; + int success; - sigset_t mask; - struct sigaction exit_action; + sigset_t mask; + struct sigaction exit_action; - sigemptyset( &mask ); - sigaddset( &mask, SIGTERM ); - sigaddset( &mask, SIGQUIT ); - sigaddset( &mask, SIGINT ); + sigemptyset(&mask); + sigaddset(&mask, SIGTERM); + sigaddset(&mask, SIGQUIT); + sigaddset(&mask, SIGINT); - exit_action.sa_handler = my_exit; - exit_action.sa_mask = mask; - exit_action.sa_flags = 0; + exit_action.sa_handler = my_exit; + exit_action.sa_mask = mask; + exit_action.sa_flags = 0; - srand(time(NULL)); + srand(time(NULL)); - while (1) { - c = getopt_long( argc, argv, proxy_short_options, proxy_options, NULL ); - if ( -1 == c ) { break; } - read_proxy_param( c, - &downstream_addr, - &downstream_port, - &upstream_addr, - &upstream_port, - &bind_addr, - &cache_bytes - ); + while (1) { + c = getopt_long(argc, argv, proxy_short_options, proxy_options, + NULL); + if (-1 == c) { + break; } + read_proxy_param(c, + &downstream_addr, + &downstream_port, + &upstream_addr, + &upstream_port, &bind_addr, &cache_bytes); + } - if ( NULL == downstream_addr ){ - fprintf( stderr, "--addr is required.\n" ); - exit_err( proxy_help_text ); - } else if ( NULL == upstream_addr || NULL == upstream_port ){ - fprintf( stderr, "both --conn-addr and --conn-port are required.\n" ); - exit_err( proxy_help_text ); - } + if (NULL == downstream_addr) { + fprintf(stderr, "--addr is required.\n"); + exit_err(proxy_help_text); + } else if (NULL == upstream_addr || NULL == upstream_port) { + fprintf(stderr, + "both --conn-addr and --conn-port are required.\n"); + exit_err(proxy_help_text); + } - proxy = proxy_create( - downstream_addr, - downstream_port, - upstream_addr, - upstream_port, - bind_addr, - cache_bytes - ); + proxy = proxy_create(downstream_addr, + downstream_port, + upstream_addr, + upstream_port, bind_addr, cache_bytes); - /* Set these *after* proxy has been assigned to */ - sigaction(SIGTERM, &exit_action, NULL); - sigaction(SIGQUIT, &exit_action, NULL); - sigaction(SIGINT, &exit_action, NULL); - signal(SIGPIPE, SIG_IGN); /* calls to splice() unhelpfully throw this */ + /* Set these *after* proxy has been assigned to */ + sigaction(SIGTERM, &exit_action, NULL); + sigaction(SIGQUIT, &exit_action, NULL); + sigaction(SIGINT, &exit_action, NULL); + signal(SIGPIPE, SIG_IGN); /* calls to splice() unhelpfully throw this */ - if ( NULL != downstream_port ) { - info( - "Proxying between %s %s (downstream) and %s %s (upstream)", - downstream_addr, downstream_port, upstream_addr, upstream_port - ); - } else { - info( - "Proxying between %s (downstream) and %s %s (upstream)", - downstream_addr, upstream_addr, upstream_port - ); - } + if (NULL != downstream_port) { + info("Proxying between %s %s (downstream) and %s %s (upstream)", + downstream_addr, downstream_port, upstream_addr, + upstream_port); + } else { + info("Proxying between %s (downstream) and %s %s (upstream)", + downstream_addr, upstream_addr, upstream_port); + } - success = do_proxy( proxy ); - proxy_destroy( proxy ); + success = do_proxy(proxy); + proxy_destroy(proxy); - return success ? 0 : 1; + return success ? 0 : 1; } - diff --git a/src/proxy/prefetch.c b/src/proxy/prefetch.c index 4fa77b2..2ae435f 100644 --- a/src/proxy/prefetch.c +++ b/src/proxy/prefetch.c @@ -2,67 +2,77 @@ #include "util.h" -struct prefetch* prefetch_create( size_t size_bytes ){ +struct prefetch *prefetch_create(size_t size_bytes) +{ - struct prefetch* out = xmalloc( sizeof( struct prefetch ) ); - NULLCHECK( out ); - - out->buffer = xmalloc( size_bytes ); - NULLCHECK( out->buffer ); + struct prefetch *out = xmalloc(sizeof(struct prefetch)); + NULLCHECK(out); - out->size = size_bytes; - out->is_full = 0; - out->from = 0; - out->len = 0; + out->buffer = xmalloc(size_bytes); + NULLCHECK(out->buffer); - return out; + out->size = size_bytes; + out->is_full = 0; + out->from = 0; + out->len = 0; + + return out; } -void prefetch_destroy( struct prefetch *prefetch ) { - if( prefetch ) { - free( prefetch->buffer ); - free( prefetch ); - } +void prefetch_destroy(struct prefetch *prefetch) +{ + if (prefetch) { + free(prefetch->buffer); + free(prefetch); + } } -size_t prefetch_size( struct prefetch *prefetch){ - if ( prefetch ) { - return prefetch->size; - } else { - return 0; - } +size_t prefetch_size(struct prefetch *prefetch) +{ + if (prefetch) { + return prefetch->size; + } else { + return 0; + } } -void prefetch_set_is_empty( struct prefetch *prefetch ){ - prefetch_set_full( prefetch, 0 ); +void prefetch_set_is_empty(struct prefetch *prefetch) +{ + prefetch_set_full(prefetch, 0); } -void prefetch_set_is_full( struct prefetch *prefetch ){ - prefetch_set_full( prefetch, 1 ); +void prefetch_set_is_full(struct prefetch *prefetch) +{ + prefetch_set_full(prefetch, 1); } -void prefetch_set_full( struct prefetch *prefetch, int val ){ - if( prefetch ) { - prefetch->is_full = val; - } +void prefetch_set_full(struct prefetch *prefetch, int val) +{ + if (prefetch) { + prefetch->is_full = val; + } } -int prefetch_is_full( struct prefetch *prefetch ){ - if( prefetch ) { - return prefetch->is_full; - } else { - return 0; - } +int prefetch_is_full(struct prefetch *prefetch) +{ + if (prefetch) { + return prefetch->is_full; + } else { + return 0; + } } -int prefetch_contains( struct prefetch *prefetch, uint64_t from, uint32_t len ){ - NULLCHECK( prefetch ); - return from >= prefetch->from && - from + len <= prefetch->from + prefetch->len; +int prefetch_contains(struct prefetch *prefetch, uint64_t from, + uint32_t len) +{ + NULLCHECK(prefetch); + return from >= prefetch->from && + from + len <= prefetch->from + prefetch->len; } -char *prefetch_offset( struct prefetch *prefetch, uint64_t from ){ - NULLCHECK( prefetch ); - return prefetch->buffer + (from - prefetch->from); +char *prefetch_offset(struct prefetch *prefetch, uint64_t from) +{ + NULLCHECK(prefetch); + return prefetch->buffer + (from - prefetch->from); } diff --git a/src/proxy/prefetch.h b/src/proxy/prefetch.h index 7c71885..6fde1ca 100644 --- a/src/proxy/prefetch.h +++ b/src/proxy/prefetch.h @@ -7,27 +7,28 @@ #define PREFETCH_BUFSIZE 4096 struct prefetch { - /* True if there is data in the buffer. */ - int is_full; - /* The start point of the current content of buffer */ - uint64_t from; - /* The length of the current content of buffer */ - uint32_t len; + /* True if there is data in the buffer. */ + int is_full; + /* The start point of the current content of buffer */ + uint64_t from; + /* The length of the current content of buffer */ + uint32_t len; - /* The total size of the buffer, in bytes. */ - size_t size; + /* The total size of the buffer, in bytes. */ + size_t size; - char *buffer; + char *buffer; }; -struct prefetch* prefetch_create( size_t size_bytes ); -void prefetch_destroy( struct prefetch *prefetch ); -size_t prefetch_size( struct prefetch *); -void prefetch_set_is_empty( struct prefetch *prefetch ); -void prefetch_set_is_full( struct prefetch *prefetch ); -void prefetch_set_full( struct prefetch *prefetch, int val ); -int prefetch_is_full( struct prefetch *prefetch ); -int prefetch_contains( struct prefetch *prefetch, uint64_t from, uint32_t len ); -char *prefetch_offset( struct prefetch *prefetch, uint64_t from ); +struct prefetch *prefetch_create(size_t size_bytes); +void prefetch_destroy(struct prefetch *prefetch); +size_t prefetch_size(struct prefetch *); +void prefetch_set_is_empty(struct prefetch *prefetch); +void prefetch_set_is_full(struct prefetch *prefetch); +void prefetch_set_full(struct prefetch *prefetch, int val); +int prefetch_is_full(struct prefetch *prefetch); +int prefetch_contains(struct prefetch *prefetch, uint64_t from, + uint32_t len); +char *prefetch_offset(struct prefetch *prefetch, uint64_t from); #endif diff --git a/src/proxy/proxy.c b/src/proxy/proxy.c index 291acd6..8781308 100644 --- a/src/proxy/proxy.c +++ b/src/proxy/proxy.c @@ -13,674 +13,671 @@ #include #include -struct proxier* proxy_create( - char* s_downstream_address, - char* s_downstream_port, - char* s_upstream_address, - char* s_upstream_port, - char* s_upstream_bind, - char* s_cache_bytes ) +struct proxier *proxy_create(char *s_downstream_address, + char *s_downstream_port, + char *s_upstream_address, + char *s_upstream_port, + char *s_upstream_bind, char *s_cache_bytes) { - struct proxier* out; - out = xmalloc( sizeof( struct proxier ) ); + struct proxier *out; + out = xmalloc(sizeof(struct proxier)); - FATAL_IF_NULL(s_downstream_address, "Listen address not specified"); - NULLCHECK( s_downstream_address ); + FATAL_IF_NULL(s_downstream_address, "Listen address not specified"); + NULLCHECK(s_downstream_address); - FATAL_UNLESS( - parse_to_sockaddr( &out->listen_on.generic, s_downstream_address ), - "Couldn't parse downstream address %s" - ); + FATAL_UNLESS(parse_to_sockaddr + (&out->listen_on.generic, s_downstream_address), + "Couldn't parse downstream address %s"); - if ( out->listen_on.family != AF_UNIX ) { - FATAL_IF_NULL( s_downstream_port, "Downstream port not specified" ); - NULLCHECK( s_downstream_port ); - parse_port( s_downstream_port, &out->listen_on.v4 ); - } + if (out->listen_on.family != AF_UNIX) { + FATAL_IF_NULL(s_downstream_port, "Downstream port not specified"); + NULLCHECK(s_downstream_port); + parse_port(s_downstream_port, &out->listen_on.v4); + } - FATAL_IF_NULL(s_upstream_address, "Upstream address not specified"); - NULLCHECK( s_upstream_address ); + FATAL_IF_NULL(s_upstream_address, "Upstream address not specified"); + NULLCHECK(s_upstream_address); - FATAL_UNLESS( - parse_ip_to_sockaddr( &out->connect_to.generic, s_upstream_address ), - "Couldn't parse upstream address '%s'", - s_upstream_address - ); + FATAL_UNLESS(parse_ip_to_sockaddr + (&out->connect_to.generic, s_upstream_address), + "Couldn't parse upstream address '%s'", + s_upstream_address); - FATAL_IF_NULL( s_upstream_port, "Upstream port not specified" ); - NULLCHECK( s_upstream_port ); - parse_port( s_upstream_port, &out->connect_to.v4 ); + FATAL_IF_NULL(s_upstream_port, "Upstream port not specified"); + NULLCHECK(s_upstream_port); + parse_port(s_upstream_port, &out->connect_to.v4); - if ( s_upstream_bind ) { - FATAL_IF_ZERO( - parse_ip_to_sockaddr( &out->connect_from.generic, s_upstream_bind ), - "Couldn't parse bind address '%s'", - s_upstream_bind - ); - out->bind = 1; - } + if (s_upstream_bind) { + FATAL_IF_ZERO(parse_ip_to_sockaddr + (&out->connect_from.generic, s_upstream_bind), + "Couldn't parse bind address '%s'", s_upstream_bind); + out->bind = 1; + } - out->listen_fd = -1; - out->downstream_fd = -1; - out->upstream_fd = -1; + out->listen_fd = -1; + out->downstream_fd = -1; + out->upstream_fd = -1; - out->prefetch = NULL; - if ( s_cache_bytes ){ - int cache_bytes = atoi( s_cache_bytes ); - /* leaving this off or setting a cache size of zero or - * less results in no cache. - */ - if ( cache_bytes >= 0 ) { - out->prefetch = prefetch_create( cache_bytes ); - } - } - - out->init.buf = xmalloc( sizeof( struct nbd_init_raw ) ); - - /* Add on the request / reply size to our malloc to accommodate both - * the struct and the data + out->prefetch = NULL; + if (s_cache_bytes) { + int cache_bytes = atoi(s_cache_bytes); + /* leaving this off or setting a cache size of zero or + * less results in no cache. */ - out->req.buf = xmalloc( NBD_MAX_SIZE + NBD_REQUEST_SIZE ); - out->rsp.buf = xmalloc( NBD_MAX_SIZE + NBD_REPLY_SIZE ); + if (cache_bytes >= 0) { + out->prefetch = prefetch_create(cache_bytes); + } + } - log_context = xmalloc( strlen(s_upstream_address) + strlen(s_upstream_port) + 2 ); - sprintf(log_context, "%s:%s", s_upstream_address, s_upstream_port); + out->init.buf = xmalloc(sizeof(struct nbd_init_raw)); - return out; + /* Add on the request / reply size to our malloc to accommodate both + * the struct and the data + */ + out->req.buf = xmalloc(NBD_MAX_SIZE + NBD_REQUEST_SIZE); + out->rsp.buf = xmalloc(NBD_MAX_SIZE + NBD_REPLY_SIZE); + + log_context = + xmalloc(strlen(s_upstream_address) + strlen(s_upstream_port) + 2); + sprintf(log_context, "%s:%s", s_upstream_address, s_upstream_port); + + return out; } -int proxy_prefetches( struct proxier* proxy ) { - NULLCHECK( proxy ); - return proxy->prefetch != NULL; -} - -int proxy_prefetch_bufsize( struct proxier* proxy ){ - NULLCHECK( proxy ); - return prefetch_size( proxy->prefetch ); -} - -void proxy_destroy( struct proxier* proxy ) +int proxy_prefetches(struct proxier *proxy) { - free( proxy->init.buf ); - free( proxy->req.buf ); - free( proxy->rsp.buf ); - prefetch_destroy( proxy->prefetch ); + NULLCHECK(proxy); + return proxy->prefetch != NULL; +} - free( proxy ); +int proxy_prefetch_bufsize(struct proxier *proxy) +{ + NULLCHECK(proxy); + return prefetch_size(proxy->prefetch); +} + +void proxy_destroy(struct proxier *proxy) +{ + free(proxy->init.buf); + free(proxy->req.buf); + free(proxy->rsp.buf); + prefetch_destroy(proxy->prefetch); + + free(proxy); } /* Shared between our two different connect_to_upstream paths */ -void proxy_finish_connect_to_upstream( struct proxier *proxy, uint64_t size, uint32_t flags ); +void proxy_finish_connect_to_upstream(struct proxier *proxy, uint64_t size, + uint32_t flags); /* Try to establish a connection to our upstream server. Return 1 on success, * 0 on failure. this is a blocking call that returns a non-blocking socket. */ -int proxy_connect_to_upstream( struct proxier* proxy ) +int proxy_connect_to_upstream(struct proxier *proxy) { - struct sockaddr* connect_from = NULL; - if ( proxy->bind ) { - connect_from = &proxy->connect_from.generic; - } + struct sockaddr *connect_from = NULL; + if (proxy->bind) { + connect_from = &proxy->connect_from.generic; + } - int fd = socket_connect( &proxy->connect_to.generic, connect_from ); - uint64_t size = 0; - uint32_t flags = 0; + int fd = socket_connect(&proxy->connect_to.generic, connect_from); + uint64_t size = 0; + uint32_t flags = 0; - if ( -1 == fd ) { - return 0; - } + if (-1 == fd) { + return 0; + } - if( !socket_nbd_read_hello( fd, &size, &flags ) ) { - WARN_IF_NEGATIVE( - sock_try_close( fd ), - "Couldn't close() after failed read of NBD hello on fd %i", fd - ); - return 0; - } + if (!socket_nbd_read_hello(fd, &size, &flags)) { + WARN_IF_NEGATIVE(sock_try_close(fd), + "Couldn't close() after failed read of NBD hello on fd %i", + fd); + return 0; + } - proxy->upstream_fd = fd; - sock_set_nonblock( fd, 1 ); - proxy_finish_connect_to_upstream( proxy, size, flags ); + proxy->upstream_fd = fd; + sock_set_nonblock(fd, 1); + proxy_finish_connect_to_upstream(proxy, size, flags); - return 1; + return 1; } /* First half of non-blocking connection to upstream. Gets as far as calling * connect() on a non-blocking socket. */ -void proxy_start_connect_to_upstream( struct proxier* proxy ) +void proxy_start_connect_to_upstream(struct proxier *proxy) { - int fd, result; - struct sockaddr* from = NULL; - struct sockaddr* to = &proxy->connect_to.generic; + int fd, result; + struct sockaddr *from = NULL; + struct sockaddr *to = &proxy->connect_to.generic; - if ( proxy->bind ) { - from = &proxy->connect_from.generic; - } + if (proxy->bind) { + from = &proxy->connect_from.generic; + } - fd = socket( to->sa_family , SOCK_STREAM, 0 ); + fd = socket(to->sa_family, SOCK_STREAM, 0); - if( fd < 0 ) { - warn( SHOW_ERRNO( "Couldn't create socket to reconnect to upstream" ) ); - return; - } - - info( "Beginning non-blocking connection to upstream on fd %i", fd ); - - if ( NULL != from ) { - if ( 0 > bind( fd, from, sockaddr_size( from ) ) ) { - warn( SHOW_ERRNO( "bind() to source address failed" ) ); - } - } - - result = sock_set_nonblock( fd, 1 ); - if ( result == -1 ) { - warn( SHOW_ERRNO( "Failed to set upstream fd %i non-blocking", fd ) ); - goto error; - } - - result = connect( fd, to, sockaddr_size( to ) ); - if ( result == -1 && errno != EINPROGRESS ) { - warn( SHOW_ERRNO( "Failed to start connect()ing to upstream!" ) ); - goto error; - } - - proxy->upstream_fd = fd; + if (fd < 0) { + warn(SHOW_ERRNO + ("Couldn't create socket to reconnect to upstream")); return; + } -error: - if ( sock_try_close( fd ) == -1 ) { - /* Non-fatal leak, although still nasty */ - warn( SHOW_ERRNO( "Failed to close fd for upstream %i", fd ) ); + info("Beginning non-blocking connection to upstream on fd %i", fd); + + if (NULL != from) { + if (0 > bind(fd, from, sockaddr_size(from))) { + warn(SHOW_ERRNO("bind() to source address failed")); } - return; + } + + result = sock_set_nonblock(fd, 1); + if (result == -1) { + warn(SHOW_ERRNO("Failed to set upstream fd %i non-blocking", fd)); + goto error; + } + + result = connect(fd, to, sockaddr_size(to)); + if (result == -1 && errno != EINPROGRESS) { + warn(SHOW_ERRNO("Failed to start connect()ing to upstream!")); + goto error; + } + + proxy->upstream_fd = fd; + return; + + error: + if (sock_try_close(fd) == -1) { + /* Non-fatal leak, although still nasty */ + warn(SHOW_ERRNO("Failed to close fd for upstream %i", fd)); + } + return; } -void proxy_finish_connect_to_upstream( struct proxier *proxy, uint64_t size, uint32_t flags ) { +void proxy_finish_connect_to_upstream(struct proxier *proxy, uint64_t size, + uint32_t flags) +{ - if ( proxy->upstream_size == 0 ) { - info( "Size of upstream image is %"PRIu64" bytes", size ); - } else if ( proxy->upstream_size != size ) { - warn( - "Size changed from %"PRIu64" to %"PRIu64" bytes", - proxy->upstream_size, size - ); + if (proxy->upstream_size == 0) { + info("Size of upstream image is %" PRIu64 " bytes", size); + } else if (proxy->upstream_size != size) { + warn("Size changed from %" PRIu64 " to %" PRIu64 " bytes", + proxy->upstream_size, size); + } + + proxy->upstream_size = size; + + if (proxy->upstream_flags == 0) { + info("Upstream transmission flags set to %" PRIu32 "", flags); + } else if (proxy->upstream_flags != flags) { + warn("Upstream transmission flags changed from %" PRIu32 " to %" + PRIu32 "", proxy->upstream_flags, flags); + } + + proxy->upstream_flags = flags; + + if (AF_UNIX != proxy->connect_to.family) { + if (sock_set_tcp_nodelay(proxy->upstream_fd, 1) == -1) { + warn(SHOW_ERRNO("Failed to set TCP_NODELAY")); } + } - proxy->upstream_size = size; + info("Connected to upstream on fd %i", proxy->upstream_fd); - if ( proxy->upstream_flags == 0 ) { - info( "Upstream transmission flags set to %"PRIu32"", flags ); - } else if ( proxy->upstream_flags != flags ) { - warn( - "Upstream transmission flags changed from %"PRIu32" to %"PRIu32"", - proxy->upstream_flags, flags - ); - } - - proxy->upstream_flags = flags; - - if ( AF_UNIX != proxy->connect_to.family ) { - if ( sock_set_tcp_nodelay( proxy->upstream_fd, 1 ) == -1 ) { - warn( SHOW_ERRNO( "Failed to set TCP_NODELAY" ) ); - } - } - - info( "Connected to upstream on fd %i", proxy->upstream_fd ); - - return; + return; } -void proxy_disconnect_from_upstream( struct proxier* proxy ) +void proxy_disconnect_from_upstream(struct proxier *proxy) { - if ( -1 != proxy->upstream_fd ) { - info("Closing upstream connection on fd %i", proxy->upstream_fd ); + if (-1 != proxy->upstream_fd) { + info("Closing upstream connection on fd %i", proxy->upstream_fd); - /* TODO: An NBD disconnect would be pleasant here */ - WARN_IF_NEGATIVE( - sock_try_close( proxy->upstream_fd ), - "Failed to close() fd %i when disconnecting from upstream", - proxy->upstream_fd - ); - proxy->upstream_fd = -1; - } + /* TODO: An NBD disconnect would be pleasant here */ + WARN_IF_NEGATIVE(sock_try_close(proxy->upstream_fd), + "Failed to close() fd %i when disconnecting from upstream", + proxy->upstream_fd); + proxy->upstream_fd = -1; + } } /** Prepares a listening socket for the NBD server, binding etc. */ -void proxy_open_listen_socket(struct proxier* params) +void proxy_open_listen_socket(struct proxier *params) { - NULLCHECK( params ); + NULLCHECK(params); - params->listen_fd = socket(params->listen_on.family, SOCK_STREAM, 0); - FATAL_IF_NEGATIVE( - params->listen_fd, SHOW_ERRNO( "Couldn't create listen socket" ) + params->listen_fd = socket(params->listen_on.family, SOCK_STREAM, 0); + FATAL_IF_NEGATIVE(params->listen_fd, + SHOW_ERRNO("Couldn't create listen socket") ); - /* Allow us to restart quickly */ - FATAL_IF_NEGATIVE( - sock_set_reuseaddr(params->listen_fd, 1), - SHOW_ERRNO( "Couldn't set SO_REUSEADDR" ) + /* Allow us to restart quickly */ + FATAL_IF_NEGATIVE(sock_set_reuseaddr(params->listen_fd, 1), + SHOW_ERRNO("Couldn't set SO_REUSEADDR") ); - if( AF_UNIX != params->listen_on.family ) { - FATAL_IF_NEGATIVE( - sock_set_tcp_nodelay(params->listen_fd, 1), - SHOW_ERRNO( "Couldn't set TCP_NODELAY" ) - ); - } + if (AF_UNIX != params->listen_on.family) { + FATAL_IF_NEGATIVE(sock_set_tcp_nodelay(params->listen_fd, 1), + SHOW_ERRNO("Couldn't set TCP_NODELAY") + ); + } - FATAL_UNLESS_ZERO( - sock_try_bind( params->listen_fd, ¶ms->listen_on.generic ), - SHOW_ERRNO( "Failed to bind to listening socket" ) + FATAL_UNLESS_ZERO(sock_try_bind + (params->listen_fd, ¶ms->listen_on.generic), + SHOW_ERRNO("Failed to bind to listening socket") ); - /* We're only serving one client at a time, hence backlog of 1 */ - FATAL_IF_NEGATIVE( - listen(params->listen_fd, 1), - SHOW_ERRNO( "Failed to listen on listening socket" ) + /* We're only serving one client at a time, hence backlog of 1 */ + FATAL_IF_NEGATIVE(listen(params->listen_fd, 1), + SHOW_ERRNO("Failed to listen on listening socket") ); - info( "Now listening for incoming connections" ); + info("Now listening for incoming connections"); - return; + return; } typedef enum { - EXIT, - WRITE_TO_DOWNSTREAM, - READ_FROM_DOWNSTREAM, - CONNECT_TO_UPSTREAM, - READ_INIT_FROM_UPSTREAM, - WRITE_TO_UPSTREAM, - READ_FROM_UPSTREAM + EXIT, + WRITE_TO_DOWNSTREAM, + READ_FROM_DOWNSTREAM, + CONNECT_TO_UPSTREAM, + READ_INIT_FROM_UPSTREAM, + WRITE_TO_UPSTREAM, + READ_FROM_UPSTREAM } proxy_session_states; -static char* proxy_session_state_names[] = { - "EXIT", - "WRITE_TO_DOWNSTREAM", - "READ_FROM_DOWNSTREAM", - "CONNECT_TO_UPSTREAM", - "READ_INIT_FROM_UPSTREAM", - "WRITE_TO_UPSTREAM", - "READ_FROM_UPSTREAM" +static char *proxy_session_state_names[] = { + "EXIT", + "WRITE_TO_DOWNSTREAM", + "READ_FROM_DOWNSTREAM", + "CONNECT_TO_UPSTREAM", + "READ_INIT_FROM_UPSTREAM", + "WRITE_TO_UPSTREAM", + "READ_FROM_UPSTREAM" }; -static inline int proxy_state_upstream( int state ) +static inline int proxy_state_upstream(int state) { - return state == CONNECT_TO_UPSTREAM || state == READ_INIT_FROM_UPSTREAM || - state == WRITE_TO_UPSTREAM || state == READ_FROM_UPSTREAM; + return state == CONNECT_TO_UPSTREAM || state == READ_INIT_FROM_UPSTREAM + || state == WRITE_TO_UPSTREAM || state == READ_FROM_UPSTREAM; } -int proxy_prefetch_for_request( struct proxier* proxy, int state ) +int proxy_prefetch_for_request(struct proxier *proxy, int state) { - NULLCHECK( proxy ); - struct nbd_request* req = &proxy->req_hdr; - struct nbd_reply* rsp = &proxy->rsp_hdr; + NULLCHECK(proxy); + struct nbd_request *req = &proxy->req_hdr; + struct nbd_reply *rsp = &proxy->rsp_hdr; - struct nbd_request_raw* req_raw = (struct nbd_request_raw*) proxy->req.buf; - struct nbd_reply_raw *rsp_raw = (struct nbd_reply_raw*) proxy->rsp.buf; + struct nbd_request_raw *req_raw = + (struct nbd_request_raw *) proxy->req.buf; + struct nbd_reply_raw *rsp_raw = + (struct nbd_reply_raw *) proxy->rsp.buf; - int is_read = req->type == REQUEST_READ; + int is_read = req->type == REQUEST_READ; - if ( is_read ) { - /* See if we can respond with what's in our prefetch - * cache */ - if ( prefetch_is_full( proxy->prefetch ) && - prefetch_contains( proxy->prefetch, req->from, req->len ) ) { - /* HUZZAH! A match! */ - debug( "Prefetch hit!" ); + if (is_read) { + /* See if we can respond with what's in our prefetch + * cache */ + if (prefetch_is_full(proxy->prefetch) && + prefetch_contains(proxy->prefetch, req->from, req->len)) { + /* HUZZAH! A match! */ + debug("Prefetch hit!"); - /* First build a reply header */ - rsp->magic = REPLY_MAGIC; - rsp->error = 0; - memcpy( &rsp->handle, &req->handle, 8 ); + /* First build a reply header */ + rsp->magic = REPLY_MAGIC; + rsp->error = 0; + memcpy(&rsp->handle, &req->handle, 8); - /* now copy it into the response */ - nbd_h2r_reply( rsp, rsp_raw ); + /* now copy it into the response */ + nbd_h2r_reply(rsp, rsp_raw); - /* and the data */ - memcpy( - proxy->rsp.buf + NBD_REPLY_SIZE, - prefetch_offset( proxy->prefetch, req->from ), - req->len - ); + /* and the data */ + memcpy(proxy->rsp.buf + NBD_REPLY_SIZE, + prefetch_offset(proxy->prefetch, req->from), req->len); - proxy->rsp.size = NBD_REPLY_SIZE + req->len; - proxy->rsp.needle = 0; + proxy->rsp.size = NBD_REPLY_SIZE + req->len; + proxy->rsp.needle = 0; - /* return early, our work here is done */ - return WRITE_TO_DOWNSTREAM; - } + /* return early, our work here is done */ + return WRITE_TO_DOWNSTREAM; } - else { - /* Safety catch. If we're sending a write request, we - * blow away the cache. This is very pessimistic, but - * it's simpler (and therefore safer) than working out - * whether we can keep it or not. - */ - debug( "Blowing away prefetch cache on type %d request.", req->type ); - prefetch_set_is_empty( proxy->prefetch ); - } - - debug( "Prefetch cache MISS!"); - - uint64_t prefetch_start = req->from; - /* We prefetch what we expect to be the next request. */ - uint64_t prefetch_end = req->from + ( req->len * 2 ); - - /* We only want to consider prefetching if we know we're not - * getting too much data back, if it's a read request, and if - * the prefetch won't try to read past the end of the file. + } else { + /* Safety catch. If we're sending a write request, we + * blow away the cache. This is very pessimistic, but + * it's simpler (and therefore safer) than working out + * whether we can keep it or not. */ - int prefetching = - req->len <= prefetch_size( proxy->prefetch ) && - is_read && - prefetch_start < prefetch_end && - prefetch_end <= proxy->upstream_size; + debug("Blowing away prefetch cache on type %d request.", + req->type); + prefetch_set_is_empty(proxy->prefetch); + } - /* We pull the request out of the proxy struct, rewrite the - * request size, and write it back. + debug("Prefetch cache MISS!"); + + uint64_t prefetch_start = req->from; + /* We prefetch what we expect to be the next request. */ + uint64_t prefetch_end = req->from + (req->len * 2); + + /* We only want to consider prefetching if we know we're not + * getting too much data back, if it's a read request, and if + * the prefetch won't try to read past the end of the file. + */ + int prefetching = + req->len <= prefetch_size(proxy->prefetch) && + is_read && + prefetch_start < prefetch_end && + prefetch_end <= proxy->upstream_size; + + /* We pull the request out of the proxy struct, rewrite the + * request size, and write it back. + */ + if (prefetching) { + proxy->is_prefetch_req = 1; + proxy->prefetch_req_orig_len = req->len; + + req->len *= 2; + + debug("Prefetching additional %" PRIu32 " bytes", + req->len - proxy->prefetch_req_orig_len); + nbd_h2r_request(req, req_raw); + } + + return state; +} + +int proxy_prefetch_for_reply(struct proxier *proxy, int state) +{ + size_t prefetched_bytes; + + if (!proxy->is_prefetch_req) { + return state; + } + + prefetched_bytes = proxy->req_hdr.len - proxy->prefetch_req_orig_len; + + debug("Prefetched additional %d bytes", prefetched_bytes); + memcpy(proxy->prefetch->buffer, + proxy->rsp.buf + proxy->prefetch_req_orig_len + NBD_REPLY_SIZE, + prefetched_bytes); + + proxy->prefetch->from = + proxy->req_hdr.from + proxy->prefetch_req_orig_len; + proxy->prefetch->len = prefetched_bytes; + + /* We've finished with proxy->req by now, so don't need to alter it to make + * it look like the request was before prefetch */ + + /* Truncate the bytes we'll write downstream */ + proxy->req_hdr.len = proxy->prefetch_req_orig_len; + proxy->rsp.size -= prefetched_bytes; + + /* And we need to reset these */ + prefetch_set_is_full(proxy->prefetch); + proxy->is_prefetch_req = 0; + + return state; +} + + + +int proxy_read_from_downstream(struct proxier *proxy, int state) +{ + ssize_t count; + + struct nbd_request_raw *request_raw = + (struct nbd_request_raw *) proxy->req.buf; + struct nbd_request *request = &(proxy->req_hdr); + +// assert( state == READ_FROM_DOWNSTREAM ); + + count = + iobuf_read(proxy->downstream_fd, &proxy->req, NBD_REQUEST_SIZE); + + if (count == -1) { + warn(SHOW_ERRNO("Couldn't read request from downstream")); + return EXIT; + } + + if (proxy->req.needle == NBD_REQUEST_SIZE) { + nbd_r2h_request(request_raw, request); + + if (request->type == REQUEST_DISCONNECT) { + info("Received disconnect request from client"); + return EXIT; + } + + /* Simple validations -- the request / reply size have already + * been taken into account in the xmalloc, so no need to worry + * about them here */ - if ( prefetching ) { - proxy->is_prefetch_req = 1; - proxy->prefetch_req_orig_len = req->len; - - req->len *= 2; - - debug( "Prefetching additional %"PRIu32" bytes", - req->len - proxy->prefetch_req_orig_len ); - nbd_h2r_request( req, req_raw ); - } - - return state; -} - -int proxy_prefetch_for_reply( struct proxier* proxy, int state ) -{ - size_t prefetched_bytes; - - if ( !proxy->is_prefetch_req ) { - return state; - } - - prefetched_bytes = proxy->req_hdr.len - proxy->prefetch_req_orig_len; - - debug( "Prefetched additional %d bytes", prefetched_bytes ); - memcpy( - proxy->prefetch->buffer, - proxy->rsp.buf + proxy->prefetch_req_orig_len + NBD_REPLY_SIZE, - prefetched_bytes - ); - - proxy->prefetch->from = proxy->req_hdr.from + proxy->prefetch_req_orig_len; - proxy->prefetch->len = prefetched_bytes; - - /* We've finished with proxy->req by now, so don't need to alter it to make - * it look like the request was before prefetch */ - - /* Truncate the bytes we'll write downstream */ - proxy->req_hdr.len = proxy->prefetch_req_orig_len; - proxy->rsp.size -= prefetched_bytes; - - /* And we need to reset these */ - prefetch_set_is_full( proxy->prefetch ); - proxy->is_prefetch_req = 0; - - return state; -} - - - -int proxy_read_from_downstream( struct proxier *proxy, int state ) -{ - ssize_t count; - - struct nbd_request_raw* request_raw = (struct nbd_request_raw*) proxy->req.buf; - struct nbd_request* request = &(proxy->req_hdr); - -// assert( state == READ_FROM_DOWNSTREAM ); - - count = iobuf_read( proxy->downstream_fd, &proxy->req, NBD_REQUEST_SIZE ); - - if ( count == -1 ) { - warn( SHOW_ERRNO( "Couldn't read request from downstream" ) ); + if (request->type == REQUEST_READ) { + if (request->len > NBD_MAX_SIZE) { + warn("NBD read request size %" PRIu32 " too large", + request->len); return EXIT; + } } + if (request->type == REQUEST_WRITE) { + if (request->len > NBD_MAX_SIZE) { + warn("NBD write request size %" PRIu32 " too large", + request->len); + return EXIT; + } - if ( proxy->req.needle == NBD_REQUEST_SIZE ) { - nbd_r2h_request( request_raw, request ); - - if ( request->type == REQUEST_DISCONNECT ) { - info( "Received disconnect request from client" ); - return EXIT; - } - - /* Simple validations -- the request / reply size have already - * been taken into account in the xmalloc, so no need to worry - * about them here - */ - if ( request->type == REQUEST_READ ) { - if ( request->len > NBD_MAX_SIZE ) { - warn( "NBD read request size %"PRIu32" too large", request->len ); - return EXIT; - } - } - if ( request->type == REQUEST_WRITE ) { - if ( request->len > NBD_MAX_SIZE ) { - warn( "NBD write request size %"PRIu32" too large", request->len ); - return EXIT; - } - - proxy->req.size += request->len; - } + proxy->req.size += request->len; } + } - if ( proxy->req.needle == proxy->req.size ) { - debug( - "Received NBD request from downstream. type=%"PRIu16" flags=%"PRIu16" from=%"PRIu64" len=%"PRIu32, - request->type, request->flags, request->from, request->len - ); + if (proxy->req.needle == proxy->req.size) { + debug("Received NBD request from downstream. type=%" PRIu16 + " flags=%" PRIu16 " from=%" PRIu64 " len=%" PRIu32, + request->type, request->flags, request->from, request->len); - /* Finished reading, so advance state. Leave size untouched so the next - * state knows how many bytes to write */ - proxy->req.needle = 0; - return WRITE_TO_UPSTREAM; - } + /* Finished reading, so advance state. Leave size untouched so the next + * state knows how many bytes to write */ + proxy->req.needle = 0; + return WRITE_TO_UPSTREAM; + } - return state; + return state; } -int proxy_continue_connecting_to_upstream( struct proxier* proxy, int state ) +int proxy_continue_connecting_to_upstream(struct proxier *proxy, int state) { - int error, result; - socklen_t len = sizeof( error ); + int error, result; + socklen_t len = sizeof(error); -// assert( state == CONNECT_TO_UPSTREAM ); +// assert( state == CONNECT_TO_UPSTREAM ); - result = getsockopt( - proxy->upstream_fd, SOL_SOCKET, SO_ERROR, &error, &len - ); + result = + getsockopt(proxy->upstream_fd, SOL_SOCKET, SO_ERROR, &error, &len); - if ( result == -1 ) { - warn( SHOW_ERRNO( "Failed to tell if connected to upstream" ) ); - return state; - } + if (result == -1) { + warn(SHOW_ERRNO("Failed to tell if connected to upstream")); + return state; + } - if ( error != 0 ) { - errno = error; - warn( SHOW_ERRNO( "Failed to connect to upstream" ) ); - return state; - } + if (error != 0) { + errno = error; + warn(SHOW_ERRNO("Failed to connect to upstream")); + return state; + } - /* Data may have changed while we were disconnected */ - prefetch_set_is_empty( proxy->prefetch ); + /* Data may have changed while we were disconnected */ + prefetch_set_is_empty(proxy->prefetch); - info( "Connected to upstream on fd %i", proxy->upstream_fd ); - return READ_INIT_FROM_UPSTREAM; + info("Connected to upstream on fd %i", proxy->upstream_fd); + return READ_INIT_FROM_UPSTREAM; } -int proxy_read_init_from_upstream( struct proxier* proxy, int state ) +int proxy_read_init_from_upstream(struct proxier *proxy, int state) { - ssize_t count; + ssize_t count; -// assert( state == READ_INIT_FROM_UPSTREAM ); +// assert( state == READ_INIT_FROM_UPSTREAM ); - count = iobuf_read( proxy->upstream_fd, &proxy->init, sizeof( struct nbd_init_raw ) ); + count = + iobuf_read(proxy->upstream_fd, &proxy->init, + sizeof(struct nbd_init_raw)); - if ( count == -1 ) { - warn( SHOW_ERRNO( "Failed to read init from upstream" ) ); - goto disconnect; + if (count == -1) { + warn(SHOW_ERRNO("Failed to read init from upstream")); + goto disconnect; + } + + if (proxy->init.needle == proxy->init.size) { + uint64_t upstream_size; + uint32_t upstream_flags; + if (!nbd_check_hello + ((struct nbd_init_raw *) proxy->init.buf, &upstream_size, + &upstream_flags)) { + warn("Upstream sent invalid init"); + goto disconnect; } - if ( proxy->init.needle == proxy->init.size ) { - uint64_t upstream_size; - uint32_t upstream_flags; - if ( !nbd_check_hello( (struct nbd_init_raw*) proxy->init.buf, &upstream_size, &upstream_flags ) ) { - warn( "Upstream sent invalid init" ); - goto disconnect; - } + /* record the flags, and log the reconnection, set TCP_NODELAY */ + proxy_finish_connect_to_upstream(proxy, upstream_size, + upstream_flags); - /* record the flags, and log the reconnection, set TCP_NODELAY */ - proxy_finish_connect_to_upstream( proxy, upstream_size, upstream_flags ); - - /* Currently, we only get disconnected from upstream (so needing to come - * here) when we have an outstanding request. If that becomes false, - * we'll need to choose the right state to return to here */ - proxy->init.needle = 0; - return WRITE_TO_UPSTREAM; - } - - return state; - -disconnect: + /* Currently, we only get disconnected from upstream (so needing to come + * here) when we have an outstanding request. If that becomes false, + * we'll need to choose the right state to return to here */ proxy->init.needle = 0; - proxy->init.size = 0; + return WRITE_TO_UPSTREAM; + } + + return state; + + disconnect: + proxy->init.needle = 0; + proxy->init.size = 0; + return CONNECT_TO_UPSTREAM; +} + +int proxy_write_to_upstream(struct proxier *proxy, int state) +{ + ssize_t count; + +// assert( state == WRITE_TO_UPSTREAM ); + + /* FIXME: We may set cork=1 multiple times as a result of this idiom. + * Not a serious problem, but we could do better + */ + if (proxy->req.needle == 0 && AF_UNIX != proxy->connect_to.family) { + if (sock_set_tcp_cork(proxy->upstream_fd, 1) == -1) { + warn(SHOW_ERRNO("Failed to set TCP_CORK")); + } + } + + count = iobuf_write(proxy->upstream_fd, &proxy->req); + + if (count == -1) { + warn(SHOW_ERRNO("Failed to send request to upstream")); + proxy->req.needle = 0; + // We're throwing the socket away so no need to uncork return CONNECT_TO_UPSTREAM; + } + + if (proxy->req.needle == proxy->req.size) { + /* Request sent. Advance to reading the response from upstream. We might + * still need req.size if reading the reply fails - we disconnect + * and resend the reply in that case - so keep it around for now. */ + proxy->req.needle = 0; + + if (AF_UNIX != proxy->connect_to.family) { + if (sock_set_tcp_cork(proxy->upstream_fd, 0) == -1) { + warn(SHOW_ERRNO("Failed to unset TCP_CORK")); + // TODO: should we return to CONNECT_TO_UPSTREAM in this instance? + } + } + + return READ_FROM_UPSTREAM; + } + + return state; } -int proxy_write_to_upstream( struct proxier* proxy, int state ) +int proxy_read_from_upstream(struct proxier *proxy, int state) { - ssize_t count; + ssize_t count; -// assert( state == WRITE_TO_UPSTREAM ); + struct nbd_reply *reply = &(proxy->rsp_hdr); + struct nbd_reply_raw *reply_raw = + (struct nbd_reply_raw *) proxy->rsp.buf; - /* FIXME: We may set cork=1 multiple times as a result of this idiom. - * Not a serious problem, but we could do better - */ - if ( proxy->req.needle == 0 && AF_UNIX != proxy->connect_to.family ) { - if ( sock_set_tcp_cork( proxy->upstream_fd, 1 ) == -1 ) { - warn( SHOW_ERRNO( "Failed to set TCP_CORK" ) ); - } + /* We can't assume the NBD_REPLY_SIZE + req->len is what we'll get back */ + count = iobuf_read(proxy->upstream_fd, &proxy->rsp, NBD_REPLY_SIZE); + + if (count == -1) { + warn(SHOW_ERRNO("Failed to get reply from upstream")); + goto disconnect; + } + + if (proxy->rsp.needle == NBD_REPLY_SIZE) { + nbd_r2h_reply(reply_raw, reply); + + if (reply->magic != REPLY_MAGIC) { + warn("Reply magic is incorrect"); + goto disconnect; } - count = iobuf_write( proxy->upstream_fd, &proxy->req ); - - if ( count == -1 ) { - warn( SHOW_ERRNO( "Failed to send request to upstream" ) ); - proxy->req.needle = 0; - // We're throwing the socket away so no need to uncork - return CONNECT_TO_UPSTREAM; + if (proxy->req_hdr.type == REQUEST_READ) { + /* Get the read reply data too. */ + proxy->rsp.size += proxy->req_hdr.len; } + } - if ( proxy->req.needle == proxy->req.size ) { - /* Request sent. Advance to reading the response from upstream. We might - * still need req.size if reading the reply fails - we disconnect - * and resend the reply in that case - so keep it around for now. */ - proxy->req.needle = 0; - - if ( AF_UNIX != proxy->connect_to.family ) { - if ( sock_set_tcp_cork( proxy->upstream_fd, 0 ) == -1 ) { - warn( SHOW_ERRNO( "Failed to unset TCP_CORK" ) ); - // TODO: should we return to CONNECT_TO_UPSTREAM in this instance? - } - } - - return READ_FROM_UPSTREAM; - } - - return state; -} - -int proxy_read_from_upstream( struct proxier* proxy, int state ) -{ - ssize_t count; - - struct nbd_reply* reply = &(proxy->rsp_hdr); - struct nbd_reply_raw* reply_raw = (struct nbd_reply_raw*) proxy->rsp.buf; - - /* We can't assume the NBD_REPLY_SIZE + req->len is what we'll get back */ - count = iobuf_read( proxy->upstream_fd, &proxy->rsp, NBD_REPLY_SIZE ); - - if ( count == -1 ) { - warn( SHOW_ERRNO( "Failed to get reply from upstream" ) ); - goto disconnect; - } - - if ( proxy->rsp.needle == NBD_REPLY_SIZE ) { - nbd_r2h_reply( reply_raw, reply ); - - if ( reply->magic != REPLY_MAGIC ) { - warn( "Reply magic is incorrect" ); - goto disconnect; - } - - if ( proxy->req_hdr.type == REQUEST_READ ) { - /* Get the read reply data too. */ - proxy->rsp.size += proxy->req_hdr.len; - } - } - - if ( proxy->rsp.size == proxy->rsp.needle ) { - debug( "NBD reply received from upstream." ); - proxy->rsp.needle = 0; - return WRITE_TO_DOWNSTREAM; - } - - return state; - -disconnect: + if (proxy->rsp.size == proxy->rsp.needle) { + debug("NBD reply received from upstream."); proxy->rsp.needle = 0; - proxy->rsp.size = 0; - return CONNECT_TO_UPSTREAM; + return WRITE_TO_DOWNSTREAM; + } + + return state; + + disconnect: + proxy->rsp.needle = 0; + proxy->rsp.size = 0; + return CONNECT_TO_UPSTREAM; } -int proxy_write_to_downstream( struct proxier* proxy, int state ) +int proxy_write_to_downstream(struct proxier *proxy, int state) { - ssize_t count; + ssize_t count; -// assert( state == WRITE_TO_DOWNSTREAM ); +// assert( state == WRITE_TO_DOWNSTREAM ); - if ( !proxy->hello_sent ) { - info( "Writing init to downstream" ); + if (!proxy->hello_sent) { + info("Writing init to downstream"); + } + + count = iobuf_write(proxy->downstream_fd, &proxy->rsp); + + if (count == -1) { + warn(SHOW_ERRNO("Failed to write to downstream")); + return EXIT; + } + + if (proxy->rsp.needle == proxy->rsp.size) { + if (!proxy->hello_sent) { + info("Hello message sent to client"); + proxy->hello_sent = 1; + } else { + debug("Reply sent"); + proxy->req_count++; } - count = iobuf_write( proxy->downstream_fd, &proxy->rsp ); + /* We're done with the request & response buffers now */ + proxy->req.size = 0; + proxy->req.needle = 0; + proxy->rsp.size = 0; + proxy->rsp.needle = 0; + return READ_FROM_DOWNSTREAM; + } - if ( count == -1 ) { - warn( SHOW_ERRNO( "Failed to write to downstream" ) ); - return EXIT; - } - - if ( proxy->rsp.needle == proxy->rsp.size ) { - if ( !proxy->hello_sent ) { - info( "Hello message sent to client" ); - proxy->hello_sent = 1; - } else { - debug( "Reply sent" ); - proxy->req_count++; - } - - /* We're done with the request & response buffers now */ - proxy->req.size = 0; - proxy->req.needle = 0; - proxy->rsp.size = 0; - proxy->rsp.needle = 0; - return READ_FROM_DOWNSTREAM; - } - - return state; + return state; } /* Non-blocking proxy session. Simple(ish) state machine. We read from d/s until @@ -692,305 +689,300 @@ int proxy_write_to_downstream( struct proxier* proxy, int state ) * This is the second-simplest NBD proxy I can think of. The first version was * non-blocking I/O, but it was getting impossible to manage exceptional stuff */ -void proxy_session( struct proxier* proxy ) +void proxy_session(struct proxier *proxy) { - uint64_t state_started = monotonic_time_ms(); - int old_state = EXIT; - int state; - int connect_to_upstream_cooldown = 0; + uint64_t state_started = monotonic_time_ms(); + int old_state = EXIT; + int state; + int connect_to_upstream_cooldown = 0; - /* First action: Write hello to downstream */ - nbd_hello_to_buf( (struct nbd_init_raw *) proxy->rsp.buf, proxy->upstream_size, proxy->upstream_flags ); - proxy->rsp.size = sizeof( struct nbd_init_raw ); - proxy->rsp.needle = 0; - state = WRITE_TO_DOWNSTREAM; + /* First action: Write hello to downstream */ + nbd_hello_to_buf((struct nbd_init_raw *) proxy->rsp.buf, + proxy->upstream_size, proxy->upstream_flags); + proxy->rsp.size = sizeof(struct nbd_init_raw); + proxy->rsp.needle = 0; + state = WRITE_TO_DOWNSTREAM; - info( "Beginning proxy session on fd %i", proxy->downstream_fd ); + info("Beginning proxy session on fd %i", proxy->downstream_fd); - while( state != EXIT ) { + while (state != EXIT) { - struct timeval select_timeout = { - .tv_sec = 0, - .tv_usec = 0 - }; + struct timeval select_timeout = { + .tv_sec = 0, + .tv_usec = 0 + }; - struct timeval *select_timeout_ptr = NULL; + struct timeval *select_timeout_ptr = NULL; - int result; /* used by select() */ + int result; /* used by select() */ - fd_set rfds; - fd_set wfds; + fd_set rfds; + fd_set wfds; - FD_ZERO( &rfds ); - FD_ZERO( &wfds ); + FD_ZERO(&rfds); + FD_ZERO(&wfds); - if ( state != old_state ) { - state_started = monotonic_time_ms(); + if (state != old_state) { + state_started = monotonic_time_ms(); - debug( - "State transition from %s to %s", - proxy_session_state_names[old_state], - proxy_session_state_names[state] - ); - } else { - debug( "Proxy is in state %s", proxy_session_state_names[state], state ); - } - - old_state = state; - - switch( state ) { - case READ_FROM_DOWNSTREAM: - FD_SET( proxy->downstream_fd, &rfds ); - break; - case WRITE_TO_DOWNSTREAM: - FD_SET( proxy->downstream_fd, &wfds ); - break; - case WRITE_TO_UPSTREAM: - select_timeout.tv_sec = 15; - FD_SET(proxy->upstream_fd, &wfds ); - break; - case CONNECT_TO_UPSTREAM: - /* upstream_fd is now -1 */ - proxy_disconnect_from_upstream( proxy ); - - if ( connect_to_upstream_cooldown ) { - connect_to_upstream_cooldown = 0; - select_timeout.tv_sec = 3; - } else { - proxy_start_connect_to_upstream( proxy ); - - if ( proxy->upstream_fd == -1 ) { - warn( SHOW_ERRNO( "Error acquiring socket to upstream" ) ); - continue; - } - FD_SET( proxy->upstream_fd, &wfds ); - select_timeout.tv_sec = 15; - } - break; - case READ_INIT_FROM_UPSTREAM: - case READ_FROM_UPSTREAM: - select_timeout.tv_sec = 15; - FD_SET( proxy->upstream_fd, &rfds ); - break; - }; - - if ( select_timeout.tv_sec > 0 ) { - select_timeout_ptr = &select_timeout; - } - - result = sock_try_select( FD_SETSIZE, &rfds, &wfds, NULL, select_timeout_ptr ); - - if ( result == -1 ) { - warn( SHOW_ERRNO( "select() failed: " ) ); - break; - } - - /* Happens after failed reconnect. Avoid SIGBUS on FD_ISSET() */ - if ( proxy->upstream_fd == -1 ) { - continue; - } - - switch( state ) { - case READ_FROM_DOWNSTREAM: - if ( FD_ISSET( proxy->downstream_fd, &rfds ) ) { - state = proxy_read_from_downstream( proxy, state ); - /* Check if we can fulfil the request from prefetch, or - * rewrite the request to fill the prefetch buffer if needed - */ - if ( proxy_prefetches( proxy ) && state == WRITE_TO_UPSTREAM ) { - state = proxy_prefetch_for_request( proxy, state ); - } - } - break; - case CONNECT_TO_UPSTREAM: - if ( FD_ISSET( proxy->upstream_fd, &wfds ) ) { - state = proxy_continue_connecting_to_upstream( proxy, state ); - } - /* Leaving state untouched will retry connecting to upstream - - * so introduce a bit of sleep */ - if ( state == CONNECT_TO_UPSTREAM ) { - connect_to_upstream_cooldown = 1; - } - - break; - case READ_INIT_FROM_UPSTREAM: - state = proxy_read_init_from_upstream( proxy, state ); - - if ( state == CONNECT_TO_UPSTREAM ) { - connect_to_upstream_cooldown = 1; - } - - break; - case WRITE_TO_UPSTREAM: - if ( FD_ISSET( proxy->upstream_fd, &wfds ) ) { - state = proxy_write_to_upstream( proxy, state ); - } - break; - case READ_FROM_UPSTREAM: - if ( FD_ISSET( proxy->upstream_fd, &rfds ) ) { - state = proxy_read_from_upstream( proxy, state ); - } - /* Fill the prefetch buffer and rewrite the reply, if needed */ - if ( proxy_prefetches( proxy ) && state == WRITE_TO_DOWNSTREAM ) { - state = proxy_prefetch_for_reply( proxy, state ); - } - break; - case WRITE_TO_DOWNSTREAM: - if ( FD_ISSET( proxy->downstream_fd, &wfds ) ) { - state = proxy_write_to_downstream( proxy, state ); - } - break; - } - - /* In these states, we're interested in restarting after a timeout. - */ - if ( old_state == state && proxy_state_upstream( state ) ) { - if ( ( monotonic_time_ms() ) - state_started > UPSTREAM_TIMEOUT ) { - warn( - "Timed out in state %s while communicating with upstream", - proxy_session_state_names[state] - ); - state = CONNECT_TO_UPSTREAM; - - /* Since we've timed out, we won't have gone through the timeout logic - * in the various state handlers that resets these appropriately... */ - proxy->init.size = 0; - proxy->init.needle = 0; - proxy->rsp.size = 0; - proxy->rsp.needle = 0; - } - } + debug("State transition from %s to %s", + proxy_session_state_names[old_state], + proxy_session_state_names[state] + ); + } else { + debug("Proxy is in state %s", proxy_session_state_names[state], + state); } - info( - "Finished proxy session on fd %i after %"PRIu64" successful request(s)", - proxy->downstream_fd, proxy->req_count - ); + old_state = state; - /* Reset these two for the next session */ - proxy->req_count = 0; - proxy->hello_sent = 0; + switch (state) { + case READ_FROM_DOWNSTREAM: + FD_SET(proxy->downstream_fd, &rfds); + break; + case WRITE_TO_DOWNSTREAM: + FD_SET(proxy->downstream_fd, &wfds); + break; + case WRITE_TO_UPSTREAM: + select_timeout.tv_sec = 15; + FD_SET(proxy->upstream_fd, &wfds); + break; + case CONNECT_TO_UPSTREAM: + /* upstream_fd is now -1 */ + proxy_disconnect_from_upstream(proxy); - return; + if (connect_to_upstream_cooldown) { + connect_to_upstream_cooldown = 0; + select_timeout.tv_sec = 3; + } else { + proxy_start_connect_to_upstream(proxy); + + if (proxy->upstream_fd == -1) { + warn(SHOW_ERRNO("Error acquiring socket to upstream")); + continue; + } + FD_SET(proxy->upstream_fd, &wfds); + select_timeout.tv_sec = 15; + } + break; + case READ_INIT_FROM_UPSTREAM: + case READ_FROM_UPSTREAM: + select_timeout.tv_sec = 15; + FD_SET(proxy->upstream_fd, &rfds); + break; + }; + + if (select_timeout.tv_sec > 0) { + select_timeout_ptr = &select_timeout; + } + + result = + sock_try_select(FD_SETSIZE, &rfds, &wfds, NULL, + select_timeout_ptr); + + if (result == -1) { + warn(SHOW_ERRNO("select() failed: ")); + break; + } + + /* Happens after failed reconnect. Avoid SIGBUS on FD_ISSET() */ + if (proxy->upstream_fd == -1) { + continue; + } + + switch (state) { + case READ_FROM_DOWNSTREAM: + if (FD_ISSET(proxy->downstream_fd, &rfds)) { + state = proxy_read_from_downstream(proxy, state); + /* Check if we can fulfil the request from prefetch, or + * rewrite the request to fill the prefetch buffer if needed + */ + if (proxy_prefetches(proxy) && state == WRITE_TO_UPSTREAM) { + state = proxy_prefetch_for_request(proxy, state); + } + } + break; + case CONNECT_TO_UPSTREAM: + if (FD_ISSET(proxy->upstream_fd, &wfds)) { + state = + proxy_continue_connecting_to_upstream(proxy, state); + } + /* Leaving state untouched will retry connecting to upstream - + * so introduce a bit of sleep */ + if (state == CONNECT_TO_UPSTREAM) { + connect_to_upstream_cooldown = 1; + } + + break; + case READ_INIT_FROM_UPSTREAM: + state = proxy_read_init_from_upstream(proxy, state); + + if (state == CONNECT_TO_UPSTREAM) { + connect_to_upstream_cooldown = 1; + } + + break; + case WRITE_TO_UPSTREAM: + if (FD_ISSET(proxy->upstream_fd, &wfds)) { + state = proxy_write_to_upstream(proxy, state); + } + break; + case READ_FROM_UPSTREAM: + if (FD_ISSET(proxy->upstream_fd, &rfds)) { + state = proxy_read_from_upstream(proxy, state); + } + /* Fill the prefetch buffer and rewrite the reply, if needed */ + if (proxy_prefetches(proxy) && state == WRITE_TO_DOWNSTREAM) { + state = proxy_prefetch_for_reply(proxy, state); + } + break; + case WRITE_TO_DOWNSTREAM: + if (FD_ISSET(proxy->downstream_fd, &wfds)) { + state = proxy_write_to_downstream(proxy, state); + } + break; + } + + /* In these states, we're interested in restarting after a timeout. + */ + if (old_state == state && proxy_state_upstream(state)) { + if ((monotonic_time_ms()) - state_started > UPSTREAM_TIMEOUT) { + warn("Timed out in state %s while communicating with upstream", proxy_session_state_names[state] + ); + state = CONNECT_TO_UPSTREAM; + + /* Since we've timed out, we won't have gone through the timeout logic + * in the various state handlers that resets these appropriately... */ + proxy->init.size = 0; + proxy->init.needle = 0; + proxy->rsp.size = 0; + proxy->rsp.needle = 0; + } + } + } + + info("Finished proxy session on fd %i after %" PRIu64 + " successful request(s)", proxy->downstream_fd, proxy->req_count); + + /* Reset these two for the next session */ + proxy->req_count = 0; + proxy->hello_sent = 0; + + return; } /** Accept an NBD socket connection, dispatch appropriately */ -int proxy_accept( struct proxier* params ) +int proxy_accept(struct proxier *params) { - NULLCHECK( params ); + NULLCHECK(params); - int client_fd; - fd_set fds; + int client_fd; + fd_set fds; - union mysockaddr client_address; - socklen_t socklen = sizeof( client_address ); + union mysockaddr client_address; + socklen_t socklen = sizeof(client_address); - info( "Waiting for client connection" ); + info("Waiting for client connection"); - FD_ZERO(&fds); - FD_SET(params->listen_fd, &fds); + FD_ZERO(&fds); + FD_SET(params->listen_fd, &fds); - FATAL_IF_NEGATIVE( - sock_try_select(FD_SETSIZE, &fds, NULL, NULL, NULL), - SHOW_ERRNO( "select() failed" ) + FATAL_IF_NEGATIVE(sock_try_select(FD_SETSIZE, &fds, NULL, NULL, NULL), + SHOW_ERRNO("select() failed") ); - if ( FD_ISSET( params->listen_fd, &fds ) ) { - client_fd = accept( params->listen_fd, &client_address.generic, &socklen ); + if (FD_ISSET(params->listen_fd, &fds)) { + client_fd = + accept(params->listen_fd, &client_address.generic, &socklen); - if ( client_address.family != AF_UNIX ) { - if ( sock_set_tcp_nodelay(client_fd, 1) == -1 ) { - warn( SHOW_ERRNO( "Failed to set TCP_NODELAY" ) ); - } - } - - info( "Accepted nbd client socket fd %d", client_fd ); - sock_set_nonblock( client_fd, 1 ); - params->downstream_fd = client_fd; - proxy_session( params ); - - WARN_IF_NEGATIVE( - sock_try_close( params->downstream_fd ), - "Couldn't close() downstram fd %i after proxy session", - params->downstream_fd - ); - params->downstream_fd = -1; + if (client_address.family != AF_UNIX) { + if (sock_set_tcp_nodelay(client_fd, 1) == -1) { + warn(SHOW_ERRNO("Failed to set TCP_NODELAY")); + } } - return 1; /* We actually expect to be interrupted by signal handlers */ + info("Accepted nbd client socket fd %d", client_fd); + sock_set_nonblock(client_fd, 1); + params->downstream_fd = client_fd; + proxy_session(params); + + WARN_IF_NEGATIVE(sock_try_close(params->downstream_fd), + "Couldn't close() downstram fd %i after proxy session", + params->downstream_fd); + params->downstream_fd = -1; + } + + return 1; /* We actually expect to be interrupted by signal handlers */ } -void proxy_accept_loop( struct proxier* params ) +void proxy_accept_loop(struct proxier *params) { - NULLCHECK( params ); - while( proxy_accept( params ) ); + NULLCHECK(params); + while (proxy_accept(params)); } /** Closes sockets */ -void proxy_cleanup( struct proxier* proxy ) +void proxy_cleanup(struct proxier *proxy) { - NULLCHECK( proxy ); + NULLCHECK(proxy); - info( "Cleaning up" ); + info("Cleaning up"); - if ( -1 != proxy->listen_fd ) { + if (-1 != proxy->listen_fd) { - if ( AF_UNIX == proxy->listen_on.family ) { - if ( -1 == unlink( proxy->listen_on.un.sun_path ) ) { - warn( SHOW_ERRNO( "Failed to unlink %s", proxy->listen_on.un.sun_path ) ); - } - } - - WARN_IF_NEGATIVE( - sock_try_close( proxy->listen_fd ), - SHOW_ERRNO( "Failed to close() listen fd %i", proxy->listen_fd ) - ); - proxy->listen_fd = -1; + if (AF_UNIX == proxy->listen_on.family) { + if (-1 == unlink(proxy->listen_on.un.sun_path)) { + warn(SHOW_ERRNO + ("Failed to unlink %s", + proxy->listen_on.un.sun_path)); + } } - if ( -1 != proxy->downstream_fd ) { - WARN_IF_NEGATIVE( - sock_try_close( proxy->downstream_fd ), - SHOW_ERRNO( - "Failed to close() downstream fd %i", proxy->downstream_fd - ) - ); - proxy->downstream_fd = -1; - } + WARN_IF_NEGATIVE(sock_try_close(proxy->listen_fd), + SHOW_ERRNO("Failed to close() listen fd %i", + proxy->listen_fd) + ); + proxy->listen_fd = -1; + } - if ( -1 != proxy->upstream_fd ) { - WARN_IF_NEGATIVE( - sock_try_close( proxy->upstream_fd ), - SHOW_ERRNO( - "Failed to close() upstream fd %i", proxy->upstream_fd - ) - ); - proxy->upstream_fd = -1; - } + if (-1 != proxy->downstream_fd) { + WARN_IF_NEGATIVE(sock_try_close(proxy->downstream_fd), + SHOW_ERRNO("Failed to close() downstream fd %i", + proxy->downstream_fd) + ); + proxy->downstream_fd = -1; + } - info( "Cleanup done" ); + if (-1 != proxy->upstream_fd) { + WARN_IF_NEGATIVE(sock_try_close(proxy->upstream_fd), + SHOW_ERRNO("Failed to close() upstream fd %i", + proxy->upstream_fd) + ); + proxy->upstream_fd = -1; + } + + info("Cleanup done"); } /** Full lifecycle of the proxier */ -int do_proxy( struct proxier* params ) +int do_proxy(struct proxier *params) { - NULLCHECK( params ); + NULLCHECK(params); - info( "Ensuring upstream server is open" ); + info("Ensuring upstream server is open"); - if ( !proxy_connect_to_upstream( params ) ) { - warn( "Couldn't connect to upstream server during initialization, exiting" ); - proxy_cleanup( params ); - return 1; - }; + if (!proxy_connect_to_upstream(params)) { + warn("Couldn't connect to upstream server during initialization, exiting"); + proxy_cleanup(params); + return 1; + }; - proxy_open_listen_socket( params ); - proxy_accept_loop( params ); - proxy_cleanup( params ); + proxy_open_listen_socket(params); + proxy_accept_loop(params); + proxy_cleanup(params); - return 0; + return 0; } - diff --git a/src/proxy/proxy.h b/src/proxy/proxy.h index 4be93d5..3652350 100644 --- a/src/proxy/proxy.h +++ b/src/proxy/proxy.h @@ -10,7 +10,7 @@ #include "self_pipe.h" #ifdef PREFETCH - #include "prefetch.h" +#include "prefetch.h" #endif /** UPSTREAM_TIMEOUT @@ -21,80 +21,77 @@ struct proxier { /** address/port to bind to */ - union mysockaddr listen_on; + union mysockaddr listen_on; /** address/port to connect to */ - union mysockaddr connect_to; + union mysockaddr connect_to; /** address to bind to when making outgoing connections */ - union mysockaddr connect_from; - int bind; /* Set to true if we should use it */ + union mysockaddr connect_from; + int bind; /* Set to true if we should use it */ - /* The socket we listen() on and accept() against */ - int listen_fd; + /* The socket we listen() on and accept() against */ + int listen_fd; - /* The socket returned by accept() that we receive requests from and send - * responses to - */ - int downstream_fd; + /* The socket returned by accept() that we receive requests from and send + * responses to + */ + int downstream_fd; - /* The socket returned by connect() that we send requests to and receive - * responses from - */ - int upstream_fd; + /* The socket returned by connect() that we send requests to and receive + * responses from + */ + int upstream_fd; - /* This is the size we advertise to the downstream server */ - uint64_t upstream_size; + /* This is the size we advertise to the downstream server */ + uint64_t upstream_size; - /* These are the transmission flags sent as part of the handshake */ - uint32_t upstream_flags; + /* These are the transmission flags sent as part of the handshake */ + uint32_t upstream_flags; - /* We transform the raw request header into here */ - struct nbd_request req_hdr; + /* We transform the raw request header into here */ + struct nbd_request req_hdr; - /* We transform the raw reply header into here */ - struct nbd_reply rsp_hdr; + /* We transform the raw reply header into here */ + struct nbd_reply rsp_hdr; - /* Used for our non-blocking negotiation with upstream. TODO: maybe use - * for downstream as well ( we currently overload rsp ) */ - struct iobuf init; + /* Used for our non-blocking negotiation with upstream. TODO: maybe use + * for downstream as well ( we currently overload rsp ) */ + struct iobuf init; - /* The current NBD request from downstream */ - struct iobuf req; + /* The current NBD request from downstream */ + struct iobuf req; - /* The current NBD reply from upstream */ - struct iobuf rsp; + /* The current NBD reply from upstream */ + struct iobuf rsp; - /* It's starting to feel like we need an object for a single proxy session. - * These two track how many requests we've sent so far, and whether the - * NBD_INIT code has been sent to the client yet. - */ - uint64_t req_count; - int hello_sent; + /* It's starting to feel like we need an object for a single proxy session. + * These two track how many requests we've sent so far, and whether the + * NBD_INIT code has been sent to the client yet. + */ + uint64_t req_count; + int hello_sent; /** These are only used if we pass --cache on the command line */ - /* While the in-flight request has been munged by prefetch, these two are - * set to true, and the original length of the request, respectively */ - int is_prefetch_req; - uint32_t prefetch_req_orig_len; + /* While the in-flight request has been munged by prefetch, these two are + * set to true, and the original length of the request, respectively */ + int is_prefetch_req; + uint32_t prefetch_req_orig_len; - /* And here, we actually store the prefetched data once it's returned */ - struct prefetch *prefetch; + /* And here, we actually store the prefetched data once it's returned */ + struct prefetch *prefetch; /** */ }; -struct proxier* proxy_create( - char* s_downstream_address, - char* s_downstream_port, - char* s_upstream_address, - char* s_upstream_port, - char* s_upstream_bind, - char* s_cache_bytes); -int do_proxy( struct proxier* proxy ); -void proxy_cleanup( struct proxier* proxy ); -void proxy_destroy( struct proxier* proxy ); +struct proxier *proxy_create(char *s_downstream_address, + char *s_downstream_port, + char *s_upstream_address, + char *s_upstream_port, + char *s_upstream_bind, char *s_cache_bytes); +int do_proxy(struct proxier *proxy); +void proxy_cleanup(struct proxier *proxy); +void proxy_destroy(struct proxier *proxy); #endif - diff --git a/src/server/acl.c b/src/server/acl.c index eb605a9..67f76f2 100644 --- a/src/server/acl.c +++ b/src/server/acl.c @@ -6,103 +6,104 @@ #include "acl.h" -struct acl * acl_create( int len, char ** lines, int default_deny ) +struct acl *acl_create(int len, char **lines, int default_deny) { - struct acl * acl; + struct acl *acl; - acl = (struct acl *)xmalloc( sizeof( struct acl ) ); - acl->len = parse_acl( &acl->entries, len, lines ); - acl->default_deny = default_deny; - return acl; + acl = (struct acl *) xmalloc(sizeof(struct acl)); + acl->len = parse_acl(&acl->entries, len, lines); + acl->default_deny = default_deny; + return acl; } -static int testmasks[9] = { 0,128,192,224,240,248,252,254,255 }; +static int testmasks[9] = { 0, 128, 192, 224, 240, 248, 252, 254, 255 }; /** Test whether AF_INET or AF_INET6 sockaddr is included in the given access * control list, returning 1 if it is, and 0 if not. */ -static int is_included_in_acl(int list_length, struct ip_and_mask (*list)[], union mysockaddr* test) +static int is_included_in_acl(int list_length, + struct ip_and_mask (*list)[], + union mysockaddr *test) { - NULLCHECK( test ); + NULLCHECK(test); - int i; + int i; - for (i=0; i < list_length; i++) { - struct ip_and_mask *entry = &(*list)[i]; - int testbits; - unsigned char *raw_address1 = NULL, *raw_address2 = NULL; + for (i = 0; i < list_length; i++) { + struct ip_and_mask *entry = &(*list)[i]; + int testbits; + unsigned char *raw_address1 = NULL, *raw_address2 = NULL; - debug("checking acl entry %d (%d/%d)", i, test->generic.sa_family, entry->ip.family); + debug("checking acl entry %d (%d/%d)", i, test->generic.sa_family, + entry->ip.family); - if (test->generic.sa_family != entry->ip.family) { - continue; - } - - if (test->generic.sa_family == AF_INET) { - debug("it's an AF_INET"); - raw_address1 = (unsigned char*) &test->v4.sin_addr; - raw_address2 = (unsigned char*) &entry->ip.v4.sin_addr; - } - else if (test->generic.sa_family == AF_INET6) { - debug("it's an AF_INET6"); - raw_address1 = (unsigned char*) &test->v6.sin6_addr; - raw_address2 = (unsigned char*) &entry->ip.v6.sin6_addr; - } - else { - fatal( "Can't check an ACL for this address type." ); - } - - debug("testbits=%d", entry->mask); - - for (testbits = entry->mask; testbits > 0; testbits -= 8) { - debug("testbits=%d, c1=%02x, c2=%02x", testbits, raw_address1[0], raw_address2[0]); - if (testbits >= 8) { - if (raw_address1[0] != raw_address2[0]) { goto no_match; } - } - else { - if ((raw_address1[0] & testmasks[testbits%8]) != - (raw_address2[0] & testmasks[testbits%8]) ) { - goto no_match; - } - } - - raw_address1++; - raw_address2++; - } - - return 1; - - no_match: ; - debug("no match"); + if (test->generic.sa_family != entry->ip.family) { + continue; } - return 0; -} - -int acl_includes( struct acl * acl, union mysockaddr * addr ) -{ - NULLCHECK( acl ); - - if ( 0 == acl->len ) { - return !( acl->default_deny ); + if (test->generic.sa_family == AF_INET) { + debug("it's an AF_INET"); + raw_address1 = (unsigned char *) &test->v4.sin_addr; + raw_address2 = (unsigned char *) &entry->ip.v4.sin_addr; + } else if (test->generic.sa_family == AF_INET6) { + debug("it's an AF_INET6"); + raw_address1 = (unsigned char *) &test->v6.sin6_addr; + raw_address2 = (unsigned char *) &entry->ip.v6.sin6_addr; + } else { + fatal("Can't check an ACL for this address type."); } - else { - return is_included_in_acl( acl->len, acl->entries, addr ); + + debug("testbits=%d", entry->mask); + + for (testbits = entry->mask; testbits > 0; testbits -= 8) { + debug("testbits=%d, c1=%02x, c2=%02x", testbits, + raw_address1[0], raw_address2[0]); + if (testbits >= 8) { + if (raw_address1[0] != raw_address2[0]) { + goto no_match; + } + } else { + if ((raw_address1[0] & testmasks[testbits % 8]) != + (raw_address2[0] & testmasks[testbits % 8])) { + goto no_match; + } + } + + raw_address1++; + raw_address2++; } + + return 1; + + no_match:; + debug("no match"); + } + + return 0; } -int acl_default_deny( struct acl * acl ) +int acl_includes(struct acl *acl, union mysockaddr *addr) { - NULLCHECK( acl ); - return acl->default_deny; + NULLCHECK(acl); + + if (0 == acl->len) { + return !(acl->default_deny); + } else { + return is_included_in_acl(acl->len, acl->entries, addr); + } } -void acl_destroy( struct acl * acl ) +int acl_default_deny(struct acl *acl) { - free( acl->entries ); - acl->len = 0; - acl->entries = NULL; - free( acl ); + NULLCHECK(acl); + return acl->default_deny; } +void acl_destroy(struct acl *acl) +{ + free(acl->entries); + acl->len = 0; + acl->entries = NULL; + free(acl); +} diff --git a/src/server/acl.h b/src/server/acl.h index 8c4af3c..7f40677 100644 --- a/src/server/acl.h +++ b/src/server/acl.h @@ -4,9 +4,9 @@ #include "parse.h" struct acl { - int len; - int default_deny; - struct ip_and_mask (*entries)[]; + int len; + int default_deny; + struct ip_and_mask (*entries)[]; }; /** Allocate a new acl structure, parsing the given lines to sockaddr @@ -17,21 +17,21 @@ struct acl { * default_deny controls the behaviour of an empty list: if true, all * requests will be denied. If true, all requests will be accepted. */ -struct acl * acl_create( int len, char **lines, int default_deny ); +struct acl *acl_create(int len, char **lines, int default_deny); /** Check to see whether an address is allowed by an acl. * See acl_create for how the default_deny setting affects this. */ -int acl_includes( struct acl *, union mysockaddr *); +int acl_includes(struct acl *, union mysockaddr *); /** Get the default_deny status */ -int acl_default_deny( struct acl * ); +int acl_default_deny(struct acl *); /** Free the acl structure and the internal acl entries table. */ -void acl_destroy( struct acl * ); +void acl_destroy(struct acl *); #endif diff --git a/src/server/bitset.h b/src/server/bitset.h index ed0ffd2..bb64577 100644 --- a/src/server/bitset.h +++ b/src/server/bitset.h @@ -12,8 +12,8 @@ * poking at the bits directly without using these * accessors/macros */ -typedef uint64_t bitfield_word_t; -typedef bitfield_word_t * bitfield_p; +typedef uint64_t bitfield_word_t; +typedef bitfield_word_t *bitfield_p; #define BITFIELD_WORD_SIZE sizeof(bitfield_word_t) #define BITS_PER_WORD (BITFIELD_WORD_SIZE * 8) @@ -30,65 +30,78 @@ typedef bitfield_word_t * bitfield_p; ((_bytes + (BITFIELD_WORD_SIZE-1)) / BITFIELD_WORD_SIZE) /** Return the bit value ''idx'' in array ''b'' */ -static inline int bit_get(bitfield_p b, uint64_t idx) { - return (BIT_WORD(b, idx) >> (idx & (BITS_PER_WORD-1))) & 1; +static inline int bit_get(bitfield_p b, uint64_t idx) +{ + return (BIT_WORD(b, idx) >> (idx & (BITS_PER_WORD - 1))) & 1; } /** Return 1 if the bit at ''idx'' in array ''b'' is set */ -static inline int bit_is_set(bitfield_p b, uint64_t idx) { - return bit_get(b, idx); +static inline int bit_is_set(bitfield_p b, uint64_t idx) +{ + return bit_get(b, idx); } + /** Return 1 if the bit at ''idx'' in array ''b'' is clear */ -static inline int bit_is_clear(bitfield_p b, uint64_t idx) { - return !bit_get(b, idx); +static inline int bit_is_clear(bitfield_p b, uint64_t idx) +{ + return !bit_get(b, idx); } + /** Tests whether the bit at ''idx'' in array ''b'' has value ''value'' */ -static inline int bit_has_value(bitfield_p b, uint64_t idx, int value) { - return bit_get(b, idx) == !!value; +static inline int bit_has_value(bitfield_p b, uint64_t idx, int value) +{ + return bit_get(b, idx) == ! !value; } + /** Sets the bit ''idx'' in array ''b'' */ -static inline void bit_set(bitfield_p b, uint64_t idx) { - BIT_WORD(b, idx) |= BIT_MASK(idx); +static inline void bit_set(bitfield_p b, uint64_t idx) +{ + BIT_WORD(b, idx) |= BIT_MASK(idx); } + /** Clears the bit ''idx'' in array ''b'' */ -static inline void bit_clear(bitfield_p b, uint64_t idx) { - BIT_WORD(b, idx) &= ~BIT_MASK(idx); +static inline void bit_clear(bitfield_p b, uint64_t idx) +{ + BIT_WORD(b, idx) &= ~BIT_MASK(idx); } + /** Sets ''len'' bits in array ''b'' starting at offset ''from'' */ static inline void bit_set_range(bitfield_p b, uint64_t from, uint64_t len) { - for ( ; (from % BITS_PER_WORD) != 0 && len > 0 ; len-- ) { - bit_set( b, from++ ); - } + for (; (from % BITS_PER_WORD) != 0 && len > 0; len--) { + bit_set(b, from++); + } - if (len >= BITS_PER_WORD) { - memset(&BIT_WORD(b, from), 0xff, len / 8 ); - from += len; - len = len % BITS_PER_WORD; - from -= len; - } + if (len >= BITS_PER_WORD) { + memset(&BIT_WORD(b, from), 0xff, len / 8); + from += len; + len = len % BITS_PER_WORD; + from -= len; + } - for ( ; len > 0 ; len-- ) { - bit_set( b, from++ ); - } + for (; len > 0; len--) { + bit_set(b, from++); + } } + /** Clears ''len'' bits in array ''b'' starting at offset ''from'' */ -static inline void bit_clear_range(bitfield_p b, uint64_t from, uint64_t len) +static inline void bit_clear_range(bitfield_p b, uint64_t from, + uint64_t len) { - for ( ; (from % BITS_PER_WORD) != 0 && len > 0 ; len-- ) { - bit_clear( b, from++ ); - } + for (; (from % BITS_PER_WORD) != 0 && len > 0; len--) { + bit_clear(b, from++); + } - if (len >= BITS_PER_WORD) { - memset(&BIT_WORD(b, from), 0, len / 8 ); - from += len; - len = len % BITS_PER_WORD; - from -= len; - } + if (len >= BITS_PER_WORD) { + memset(&BIT_WORD(b, from), 0, len / 8); + from += len; + len = len % BITS_PER_WORD; + from -= len; + } - for ( ; len > 0 ; len-- ) { - bit_clear( b, from++ ); - } + for (; len > 0; len--) { + bit_clear(b, from++); + } } /** Counts the number of contiguous bits in array ''b'', starting at ''from'' @@ -96,52 +109,54 @@ static inline void bit_clear_range(bitfield_p b, uint64_t from, uint64_t len) * bits that are the same as the first one specified. If ''run_is_set'' is * non-NULL, the value of that bit is placed into it. */ -static inline uint64_t bit_run_count(bitfield_p b, uint64_t from, uint64_t len, int *run_is_set) { - uint64_t count = 0; - int first_value = bit_get(b, from); - bitfield_word_t word_match = first_value ? -1 : 0; +static inline uint64_t bit_run_count(bitfield_p b, uint64_t from, + uint64_t len, int *run_is_set) +{ + uint64_t count = 0; + int first_value = bit_get(b, from); + bitfield_word_t word_match = first_value ? -1 : 0; - if ( run_is_set != NULL ) { - *run_is_set = first_value; + if (run_is_set != NULL) { + *run_is_set = first_value; + } + + for (; ((from + count) % BITS_PER_WORD) != 0 && len > 0; len--) { + if (bit_has_value(b, from + count, first_value)) { + count++; + } else { + return count; } + } - for ( ; ((from + count) % BITS_PER_WORD) != 0 && len > 0; len--) { - if (bit_has_value(b, from + count, first_value)) { - count++; - } else { - return count; - } + for (; len >= BITS_PER_WORD; len -= BITS_PER_WORD) { + if (BIT_WORD(b, from + count) == word_match) { + count += BITS_PER_WORD; + } else { + break; } + } - for ( ; len >= BITS_PER_WORD ; len -= BITS_PER_WORD ) { - if (BIT_WORD(b, from + count) == word_match) { - count += BITS_PER_WORD; - } else { - break; - } + for (; len > 0; len--) { + if (bit_has_value(b, from + count, first_value)) { + count++; } + } - for ( ; len > 0; len-- ) { - if ( bit_has_value(b, from + count, first_value) ) { - count++; - } - } - - return count; + return count; } enum bitset_stream_events { - BITSET_STREAM_UNSET = 0, - BITSET_STREAM_SET = 1, - BITSET_STREAM_ON = 2, - BITSET_STREAM_OFF = 3 + BITSET_STREAM_UNSET = 0, + BITSET_STREAM_SET = 1, + BITSET_STREAM_ON = 2, + BITSET_STREAM_OFF = 3 }; #define BITSET_STREAM_EVENTS_ENUM_SIZE 4 struct bitset_stream_entry { - enum bitset_stream_events event; - uint64_t from; - uint64_t len; + enum bitset_stream_events event; + uint64_t from; + uint64_t len; }; /** Limit the stream size to 1MB for now. @@ -152,14 +167,14 @@ struct bitset_stream_entry { #define BITSET_STREAM_SIZE ( ( 1024 * 1024 ) / sizeof( struct bitset_stream_entry ) ) struct bitset_stream { - struct bitset_stream_entry entries[BITSET_STREAM_SIZE]; - int in; - int out; - int size; - pthread_mutex_t mutex; - pthread_cond_t cond_not_full; - pthread_cond_t cond_not_empty; - uint64_t queued_bytes[BITSET_STREAM_EVENTS_ENUM_SIZE]; + struct bitset_stream_entry entries[BITSET_STREAM_SIZE]; + int in; + int out; + int size; + pthread_mutex_t mutex; + pthread_cond_t cond_not_full; + pthread_cond_t cond_not_empty; + uint64_t queued_bytes[BITSET_STREAM_EVENTS_ENUM_SIZE]; }; @@ -169,47 +184,49 @@ struct bitset_stream { * written reliably by multiple threads. */ struct bitset { - pthread_mutex_t lock; - uint64_t size; - int resolution; - struct bitset_stream *stream; - int stream_enabled; - bitfield_word_t bits[]; + pthread_mutex_t lock; + uint64_t size; + int resolution; + struct bitset_stream *stream; + int stream_enabled; + bitfield_word_t bits[]; }; /** Allocate a bitset for a file of the given size, and chunks of the * given resolution. */ -static inline struct bitset *bitset_alloc( uint64_t size, int resolution ) +static inline struct bitset *bitset_alloc(uint64_t size, int resolution) { - // calculate a size to allocate that is a multiple of the size of the - // bitfield word - size_t bitfield_size = - BIT_WORDS_FOR_SIZE((( size + resolution - 1 ) / resolution)) * sizeof( bitfield_word_t ); - struct bitset *bitset = xmalloc(sizeof( struct bitset ) + ( bitfield_size / 8 ) ); + // calculate a size to allocate that is a multiple of the size of the + // bitfield word + size_t bitfield_size = + BIT_WORDS_FOR_SIZE(((size + resolution - + 1) / resolution)) * sizeof(bitfield_word_t); + struct bitset *bitset = + xmalloc(sizeof(struct bitset) + (bitfield_size / 8)); - bitset->size = size; - bitset->resolution = resolution; - /* don't actually need to call pthread_mutex_destroy '*/ - pthread_mutex_init(&bitset->lock, NULL); - bitset->stream = xmalloc( sizeof( struct bitset_stream ) ); - pthread_mutex_init( &bitset->stream->mutex, NULL ); + bitset->size = size; + bitset->resolution = resolution; + /* don't actually need to call pthread_mutex_destroy ' */ + pthread_mutex_init(&bitset->lock, NULL); + bitset->stream = xmalloc(sizeof(struct bitset_stream)); + pthread_mutex_init(&bitset->stream->mutex, NULL); - /* Technically don't need to call pthread_cond_destroy either */ - pthread_cond_init( &bitset->stream->cond_not_full, NULL ); - pthread_cond_init( &bitset->stream->cond_not_empty, NULL ); + /* Technically don't need to call pthread_cond_destroy either */ + pthread_cond_init(&bitset->stream->cond_not_full, NULL); + pthread_cond_init(&bitset->stream->cond_not_empty, NULL); - return bitset; + return bitset; } -static inline void bitset_free( struct bitset * set ) +static inline void bitset_free(struct bitset *set) { - /* TODO: free our mutex... */ + /* TODO: free our mutex... */ - free( set->stream ); - set->stream = NULL; + free(set->stream); + set->stream = NULL; - free( set ); + free(set); } #define INT_FIRST_AND_LAST \ @@ -224,215 +241,201 @@ static inline void bitset_free( struct bitset * set ) FATAL_IF_NEGATIVE(pthread_mutex_unlock(&set->lock), "Error unlocking bitset") -static inline void bitset_stream_enqueue( - struct bitset * set, - enum bitset_stream_events event, - uint64_t from, - uint64_t len -) +static inline void bitset_stream_enqueue(struct bitset *set, + enum bitset_stream_events event, + uint64_t from, uint64_t len) { - struct bitset_stream * stream = set->stream; + struct bitset_stream *stream = set->stream; - pthread_mutex_lock( &stream->mutex ); + pthread_mutex_lock(&stream->mutex); - while ( stream->size == BITSET_STREAM_SIZE ) { - pthread_cond_wait( &stream->cond_not_full, &stream->mutex ); - } + while (stream->size == BITSET_STREAM_SIZE) { + pthread_cond_wait(&stream->cond_not_full, &stream->mutex); + } - stream->entries[stream->in].event = event; - stream->entries[stream->in].from = from; - stream->entries[stream->in].len = len; - stream->queued_bytes[event] += len; + stream->entries[stream->in].event = event; + stream->entries[stream->in].from = from; + stream->entries[stream->in].len = len; + stream->queued_bytes[event] += len; - stream->size++; - stream->in++; - stream->in %= BITSET_STREAM_SIZE; + stream->size++; + stream->in++; + stream->in %= BITSET_STREAM_SIZE; - pthread_mutex_unlock( & stream->mutex ); - pthread_cond_signal( &stream->cond_not_empty ); + pthread_mutex_unlock(&stream->mutex); + pthread_cond_signal(&stream->cond_not_empty); - return; + return; } -static inline void bitset_stream_dequeue( - struct bitset * set, - struct bitset_stream_entry * out -) +static inline void bitset_stream_dequeue(struct bitset *set, + struct bitset_stream_entry *out) { - struct bitset_stream * stream = set->stream; - struct bitset_stream_entry * dequeued; + struct bitset_stream *stream = set->stream; + struct bitset_stream_entry *dequeued; - pthread_mutex_lock( &stream->mutex ); + pthread_mutex_lock(&stream->mutex); - while ( stream->size == 0 ) { - pthread_cond_wait( &stream->cond_not_empty, &stream->mutex ); - } + while (stream->size == 0) { + pthread_cond_wait(&stream->cond_not_empty, &stream->mutex); + } - dequeued = &stream->entries[stream->out]; + dequeued = &stream->entries[stream->out]; - if ( out != NULL ) { - out->event = dequeued->event; - out->from = dequeued->from; - out->len = dequeued->len; - } + if (out != NULL) { + out->event = dequeued->event; + out->from = dequeued->from; + out->len = dequeued->len; + } - stream->queued_bytes[dequeued->event] -= dequeued->len; - stream->size--; - stream->out++; - stream->out %= BITSET_STREAM_SIZE; + stream->queued_bytes[dequeued->event] -= dequeued->len; + stream->size--; + stream->out++; + stream->out %= BITSET_STREAM_SIZE; - pthread_mutex_unlock( &stream->mutex ); - pthread_cond_signal( &stream->cond_not_full ); + pthread_mutex_unlock(&stream->mutex); + pthread_cond_signal(&stream->cond_not_full); - return; + return; } -static inline size_t bitset_stream_size( struct bitset * set ) +static inline size_t bitset_stream_size(struct bitset *set) { - size_t size; + size_t size; - pthread_mutex_lock( &set->stream->mutex ); - size = set->stream->size; - pthread_mutex_unlock( &set->stream->mutex ); + pthread_mutex_lock(&set->stream->mutex); + size = set->stream->size; + pthread_mutex_unlock(&set->stream->mutex); - return size; + return size; } -static inline uint64_t bitset_stream_queued_bytes( - struct bitset * set, - enum bitset_stream_events event -) +static inline uint64_t bitset_stream_queued_bytes(struct bitset *set, + enum bitset_stream_events + event) { - uint64_t total; + uint64_t total; - pthread_mutex_lock( &set->stream->mutex ); - total = set->stream->queued_bytes[event]; - pthread_mutex_unlock( &set->stream->mutex ); + pthread_mutex_lock(&set->stream->mutex); + total = set->stream->queued_bytes[event]; + pthread_mutex_unlock(&set->stream->mutex); - return total; + return total; } -static inline void bitset_enable_stream( struct bitset * set ) +static inline void bitset_enable_stream(struct bitset *set) { - BITSET_LOCK; - set->stream_enabled = 1; - bitset_stream_enqueue( set, BITSET_STREAM_ON, 0, set->size ); - BITSET_UNLOCK; + BITSET_LOCK; + set->stream_enabled = 1; + bitset_stream_enqueue(set, BITSET_STREAM_ON, 0, set->size); + BITSET_UNLOCK; } -static inline void bitset_disable_stream( struct bitset * set ) +static inline void bitset_disable_stream(struct bitset *set) { - BITSET_LOCK; - bitset_stream_enqueue( set, BITSET_STREAM_OFF, 0, set->size ); - set->stream_enabled = 0; - BITSET_UNLOCK; + BITSET_LOCK; + bitset_stream_enqueue(set, BITSET_STREAM_OFF, 0, set->size); + set->stream_enabled = 0; + BITSET_UNLOCK; } /** Set the bits in a bitset which correspond to the given bytes in the larger * file. */ -static inline void bitset_set_range( - struct bitset * set, - uint64_t from, - uint64_t len) +static inline void bitset_set_range(struct bitset *set, + uint64_t from, uint64_t len) { - INT_FIRST_AND_LAST; - BITSET_LOCK; - bit_set_range(set->bits, first, bitlen); + INT_FIRST_AND_LAST; + BITSET_LOCK; + bit_set_range(set->bits, first, bitlen); - if ( set->stream_enabled ) { - bitset_stream_enqueue( set, BITSET_STREAM_SET, from, len ); - } + if (set->stream_enabled) { + bitset_stream_enqueue(set, BITSET_STREAM_SET, from, len); + } - BITSET_UNLOCK; + BITSET_UNLOCK; } /** Set every bit in the bitset. */ -static inline void bitset_set( struct bitset * set ) +static inline void bitset_set(struct bitset *set) { - bitset_set_range(set, 0, set->size); + bitset_set_range(set, 0, set->size); } /** Clear the bits in a bitset which correspond to the given bytes in the * larger file. */ -static inline void bitset_clear_range( - struct bitset * set, - uint64_t from, - uint64_t len) +static inline void bitset_clear_range(struct bitset *set, + uint64_t from, uint64_t len) { - INT_FIRST_AND_LAST; - BITSET_LOCK; - bit_clear_range(set->bits, first, bitlen); + INT_FIRST_AND_LAST; + BITSET_LOCK; + bit_clear_range(set->bits, first, bitlen); - if ( set->stream_enabled ) { - bitset_stream_enqueue( set, BITSET_STREAM_UNSET, from, len ); - } + if (set->stream_enabled) { + bitset_stream_enqueue(set, BITSET_STREAM_UNSET, from, len); + } - BITSET_UNLOCK; + BITSET_UNLOCK; } /** Clear every bit in the bitset. */ -static inline void bitset_clear( struct bitset * set ) +static inline void bitset_clear(struct bitset *set) { - bitset_clear_range(set, 0, set->size); + bitset_clear_range(set, 0, set->size); } /** As per bitset_run_count but also tells you whether the run it found was set * or unset, atomically. */ -static inline uint64_t bitset_run_count_ex( - struct bitset * set, - uint64_t from, - uint64_t len, - int* run_is_set -) +static inline uint64_t bitset_run_count_ex(struct bitset *set, + uint64_t from, + uint64_t len, int *run_is_set) { - uint64_t run; + uint64_t run; - /* Clip our requests to the end of the bitset, avoiding uint underflow. */ - if ( from > set->size ) { - return 0; - } - len = ( len + from ) > set->size ? ( set->size - from ) : len; + /* Clip our requests to the end of the bitset, avoiding uint underflow. */ + if (from > set->size) { + return 0; + } + len = (len + from) > set->size ? (set->size - from) : len; - INT_FIRST_AND_LAST; + INT_FIRST_AND_LAST; - BITSET_LOCK; - run = bit_run_count(set->bits, first, bitlen, run_is_set) * set->resolution; - run -= (from % set->resolution); - BITSET_UNLOCK; + BITSET_LOCK; + run = + bit_run_count(set->bits, first, bitlen, + run_is_set) * set->resolution; + run -= (from % set->resolution); + BITSET_UNLOCK; - return run; + return run; } /** Counts the number of contiguous bytes that are represented as a run in * the bit field. */ -static inline uint64_t bitset_run_count( - struct bitset * set, - uint64_t from, - uint64_t len) +static inline uint64_t bitset_run_count(struct bitset *set, + uint64_t from, uint64_t len) { - return bitset_run_count_ex( set, from, len, NULL ); + return bitset_run_count_ex(set, from, len, NULL); } /** Tests whether the bit field is clear for the given file offset. */ -static inline int bitset_is_clear_at( struct bitset * set, uint64_t at ) +static inline int bitset_is_clear_at(struct bitset *set, uint64_t at) { - return bit_is_clear(set->bits, at/set->resolution); + return bit_is_clear(set->bits, at / set->resolution); } /** Tests whether the bit field is set for the given file offset. */ -static inline int bitset_is_set_at( struct bitset * set, uint64_t at ) +static inline int bitset_is_set_at(struct bitset *set, uint64_t at) { - return bit_is_set(set->bits, at/set->resolution); + return bit_is_set(set->bits, at / set->resolution); } #endif - diff --git a/src/server/client.c b/src/server/client.c index fe8a0a5..972cf77 100644 --- a/src/server/client.c +++ b/src/server/client.c @@ -18,72 +18,74 @@ // When this signal is invoked, we call shutdown() on the client fd, which // results in the thread being wound up -void client_killswitch_hit(int signal __attribute__ ((unused)), siginfo_t *info, void *ptr __attribute__ ((unused))) +void client_killswitch_hit(int signal + __attribute__ ((unused)), siginfo_t * info, + void *ptr __attribute__ ((unused))) { - int fd = info->si_value.sival_int; - warn( "Killswitch for fd %i activated, calling shutdown on socket", fd ); + int fd = info->si_value.sival_int; + warn("Killswitch for fd %i activated, calling shutdown on socket", fd); - FATAL_IF( - -1 == shutdown( fd, SHUT_RDWR ), - SHOW_ERRNO( "Failed to shutdown() the socket, killing the server" ) - ); + FATAL_IF(-1 == shutdown(fd, SHUT_RDWR), + SHOW_ERRNO + ("Failed to shutdown() the socket, killing the server") + ); } -struct client *client_create( struct server *serve, int socket ) +struct client *client_create(struct server *serve, int socket) { - NULLCHECK( serve ); + NULLCHECK(serve); - struct client *c; - struct sigevent evp = { - .sigev_notify = SIGEV_SIGNAL, - .sigev_signo = CLIENT_KILLSWITCH_SIGNAL - }; + struct client *c; + struct sigevent evp = { + .sigev_notify = SIGEV_SIGNAL, + .sigev_signo = CLIENT_KILLSWITCH_SIGNAL + }; - /* - * Our killswitch closes this socket, forcing read() and write() calls - * blocked on it to return with an error. The thread then close()s the - * socket itself, avoiding races. - */ - evp.sigev_value.sival_int = socket; + /* + * Our killswitch closes this socket, forcing read() and write() calls + * blocked on it to return with an error. The thread then close()s the + * socket itself, avoiding races. + */ + evp.sigev_value.sival_int = socket; - c = xmalloc( sizeof( struct client ) ); - c->stopped = 0; - c->socket = socket; - c->serve = serve; + c = xmalloc(sizeof(struct client)); + c->stopped = 0; + c->socket = socket; + c->serve = serve; - c->stop_signal = self_pipe_create(); + c->stop_signal = self_pipe_create(); - FATAL_IF_NEGATIVE( - timer_create( CLOCK_MONOTONIC, &evp, &(c->killswitch) ), - SHOW_ERRNO( "Failed to create killswitch timer" ) + FATAL_IF_NEGATIVE(timer_create + (CLOCK_MONOTONIC, &evp, &(c->killswitch)), + SHOW_ERRNO("Failed to create killswitch timer") ); - debug( "Alloced client %p with socket %d", c, socket ); - return c; + debug("Alloced client %p with socket %d", c, socket); + return c; } -void client_signal_stop( struct client *c) +void client_signal_stop(struct client *c) { - NULLCHECK( c); + NULLCHECK(c); - debug("client %p: signal stop (%d, %d)", c,c->stop_signal->read_fd, c->stop_signal->write_fd ); - self_pipe_signal( c->stop_signal ); + debug("client %p: signal stop (%d, %d)", c, c->stop_signal->read_fd, + c->stop_signal->write_fd); + self_pipe_signal(c->stop_signal); } -void client_destroy( struct client *client ) +void client_destroy(struct client *client) { - NULLCHECK( client ); + NULLCHECK(client); - FATAL_IF_NEGATIVE( - timer_delete( client->killswitch ), - SHOW_ERRNO( "Couldn't delete killswitch" ) + FATAL_IF_NEGATIVE(timer_delete(client->killswitch), + SHOW_ERRNO("Couldn't delete killswitch") ); - debug( "Destroying stop signal for client %p", client ); - self_pipe_destroy( client->stop_signal ); - debug( "Freeing client %p", client ); - free( client ); + debug("Destroying stop signal for client %p", client); + self_pipe_destroy(client->stop_signal); + debug("Freeing client %p", client); + free(client); } @@ -100,50 +102,51 @@ void client_destroy( struct client *client ) * allocated, we can proceed as normal and make one call to writeloop. * */ -void write_not_zeroes(struct client* client, uint64_t from, uint64_t len) +void write_not_zeroes(struct client *client, uint64_t from, uint64_t len) { - NULLCHECK( client ); - NULLCHECK( client->serve ); - NULLCHECK( client->serve->allocation_map ); + NULLCHECK(client); + NULLCHECK(client->serve); + NULLCHECK(client->serve->allocation_map); - struct bitset * map = client->serve->allocation_map; + struct bitset *map = client->serve->allocation_map; - while (len > 0) { - /* so we have to calculate how much of our input to consider - * next based on the bitmap of allocated blocks. This will be - * at a coarser resolution than the actual write, which may - * not fall on a block boundary at either end. So we look up - * how many blocks our write covers, then cut off the start - * and end to get the exact number of bytes. - */ + while (len > 0) { + /* so we have to calculate how much of our input to consider + * next based on the bitmap of allocated blocks. This will be + * at a coarser resolution than the actual write, which may + * not fall on a block boundary at either end. So we look up + * how many blocks our write covers, then cut off the start + * and end to get the exact number of bytes. + */ - uint64_t run = bitset_run_count(map, from, len); + uint64_t run = bitset_run_count(map, from, len); - debug("write_not_zeroes: from=%ld, len=%d, run=%d", from, len, run); + debug("write_not_zeroes: from=%ld, len=%d, run=%d", from, len, + run); - if (run > len) { - run = len; - debug("(run adjusted to %d)", run); - } + if (run > len) { + run = len; + debug("(run adjusted to %d)", run); + } - /* - // Useful but expensive - if (0) - { - uint64_t i; - fprintf(stderr, "full map resolution=%d: ", map->resolution); - for (i=0; iserve->size; i+=map->resolution) { - int here = (from >= i && from < i+map->resolution); + /* + // Useful but expensive + if (0) + { + uint64_t i; + fprintf(stderr, "full map resolution=%d: ", map->resolution); + for (i=0; iserve->size; i+=map->resolution) { + int here = (from >= i && from < i+map->resolution); - if (here) { fprintf(stderr, ">"); } - fprintf(stderr, bitset_is_set_at(map, i) ? "1" : "0"); - if (here) { fprintf(stderr, "<"); } - } - fprintf(stderr, "\n"); - } - */ + if (here) { fprintf(stderr, ">"); } + fprintf(stderr, bitset_is_set_at(map, i) ? "1" : "0"); + if (here) { fprintf(stderr, "<"); } + } + fprintf(stderr, "\n"); + } + */ - #define DO_READ(dst, len) ERROR_IF_NEGATIVE( \ +#define DO_READ(dst, len) ERROR_IF_NEGATIVE( \ readloop( \ client->socket, \ (dst), \ @@ -152,139 +155,136 @@ void write_not_zeroes(struct client* client, uint64_t from, uint64_t len) "read failed %ld+%d", from, (len) \ ) - if (bitset_is_set_at(map, from)) { - debug("writing the lot: from=%ld, run=%d", from, run); - /* already allocated, just write it all */ - DO_READ(client->mapped + from, run); - /* We know from our earlier call to bitset_run_count that the - * bitset is all-1s at this point, but we need to dirty it for the - * sake of the event stream - the actual bytes have changed, and we - * are interested in that fact. - */ - bitset_set_range( map, from, run ); - len -= run; - from += run; + if (bitset_is_set_at(map, from)) { + debug("writing the lot: from=%ld, run=%d", from, run); + /* already allocated, just write it all */ + DO_READ(client->mapped + from, run); + /* We know from our earlier call to bitset_run_count that the + * bitset is all-1s at this point, but we need to dirty it for the + * sake of the event stream - the actual bytes have changed, and we + * are interested in that fact. + */ + bitset_set_range(map, from, run); + len -= run; + from += run; + } else { + char zerobuffer[block_allocation_resolution]; + /* not allocated, read in block_allocation_resoution */ + while (run > 0) { + uint64_t blockrun = block_allocation_resolution - + (from % block_allocation_resolution); + if (blockrun > run) + blockrun = run; + + DO_READ(zerobuffer, blockrun); + + /* This reads the buffer twice in the worst case + * but we're leaning on memcmp failing early + * and memcpy being fast, rather than try to + * hand-optimized something specific. + */ + + int all_zeros = (zerobuffer[0] == 0) && + (0 == + memcmp(zerobuffer, zerobuffer + 1, blockrun - 1)); + + if (!all_zeros) { + memcpy(client->mapped + from, zerobuffer, blockrun); + bitset_set_range(map, from, blockrun); + /* at this point we could choose to + * short-cut the rest of the write for + * faster I/O but by continuing to do it + * the slow way we preserve as much + * sparseness as possible. + */ } - else { - char zerobuffer[block_allocation_resolution]; - /* not allocated, read in block_allocation_resoution */ - while (run > 0) { - uint64_t blockrun = block_allocation_resolution - - (from % block_allocation_resolution); - if (blockrun > run) - blockrun = run; + /* When the block is all_zeroes, no bytes have changed, so we + * don't need to put an event into the bitset stream. This may + * be surprising in the future. + */ - DO_READ(zerobuffer, blockrun); - - /* This reads the buffer twice in the worst case - * but we're leaning on memcmp failing early - * and memcpy being fast, rather than try to - * hand-optimized something specific. - */ - - int all_zeros = (zerobuffer[0] == 0) && - (0 == memcmp( zerobuffer, zerobuffer+1, blockrun-1 )); - - if ( !all_zeros ) { - memcpy(client->mapped+from, zerobuffer, blockrun); - bitset_set_range(map, from, blockrun); - /* at this point we could choose to - * short-cut the rest of the write for - * faster I/O but by continuing to do it - * the slow way we preserve as much - * sparseness as possible. - */ - } - /* When the block is all_zeroes, no bytes have changed, so we - * don't need to put an event into the bitset stream. This may - * be surprising in the future. - */ - - len -= blockrun; - run -= blockrun; - from += blockrun; - } - } + len -= blockrun; + run -= blockrun; + from += blockrun; + } } + } } -int fd_read_request( int fd, struct nbd_request_raw *out_request) +int fd_read_request(int fd, struct nbd_request_raw *out_request) { - return readloop(fd, out_request, sizeof(struct nbd_request_raw)); + return readloop(fd, out_request, sizeof(struct nbd_request_raw)); } /* Returns 1 if *request was filled with a valid request which we should * try to honour. 0 otherwise. */ -int client_read_request( struct client * client , struct nbd_request *out_request, int * disconnected ) +int client_read_request(struct client *client, + struct nbd_request *out_request, int *disconnected) { - NULLCHECK( client ); - NULLCHECK( out_request ); + NULLCHECK(client); + NULLCHECK(out_request); - struct nbd_request_raw request_raw; + struct nbd_request_raw request_raw; - if (fd_read_request(client->socket, &request_raw) == -1) { - *disconnected = 1; - switch( errno ){ - case 0: - warn( "EOF while reading request" ); - return 0; - case ECONNRESET: - warn( "Connection reset while" - " reading request" ); - return 0; - case ETIMEDOUT: - warn( "Connection timed out while" - " reading request" ); - return 0; - default: - /* FIXME: I've seen this happen, but I - * couldn't reproduce it so I'm leaving - * it here with a better debug output in - * the hope it'll spontaneously happen - * again. It should *probably* be an - * error() call, but I want to be sure. - * */ - fatal("Error reading request: %d, %s", - errno, - strerror( errno )); - } + if (fd_read_request(client->socket, &request_raw) == -1) { + *disconnected = 1; + switch (errno) { + case 0: + warn("EOF while reading request"); + return 0; + case ECONNRESET: + warn("Connection reset while" " reading request"); + return 0; + case ETIMEDOUT: + warn("Connection timed out while" " reading request"); + return 0; + default: + /* FIXME: I've seen this happen, but I + * couldn't reproduce it so I'm leaving + * it here with a better debug output in + * the hope it'll spontaneously happen + * again. It should *probably* be an + * error() call, but I want to be sure. + * */ + fatal("Error reading request: %d, %s", errno, strerror(errno)); } + } - nbd_r2h_request( &request_raw, out_request ); - return 1; + nbd_r2h_request(&request_raw, out_request); + return 1; } -int fd_write_reply( int fd, uint64_t handle, int error ) +int fd_write_reply(int fd, uint64_t handle, int error) { - struct nbd_reply reply; - struct nbd_reply_raw reply_raw; + struct nbd_reply reply; + struct nbd_reply_raw reply_raw; - reply.magic = REPLY_MAGIC; - reply.error = error; - reply.handle.w = handle; + reply.magic = REPLY_MAGIC; + reply.error = error; + reply.handle.w = handle; - nbd_h2r_reply( &reply, &reply_raw ); - debug( "Replying with handle=0x%08X, error=%"PRIu32, handle, error ); + nbd_h2r_reply(&reply, &reply_raw); + debug("Replying with handle=0x%08X, error=%" PRIu32, handle, error); - if( -1 == writeloop( fd, &reply_raw, sizeof( reply_raw ) ) ) { - switch( errno ) { - case ECONNRESET: - error( "Connection reset while writing reply" ); - break; - case EBADF: - fatal( "Tried to write to an invalid file descriptor" ); - break; - case EPIPE: - error( "Remote end closed" ); - break; - default: - fatal( "Unhandled error while writing: %d", errno ); - } + if (-1 == writeloop(fd, &reply_raw, sizeof(reply_raw))) { + switch (errno) { + case ECONNRESET: + error("Connection reset while writing reply"); + break; + case EBADF: + fatal("Tried to write to an invalid file descriptor"); + break; + case EPIPE: + error("Remote end closed"); + break; + default: + fatal("Unhandled error while writing: %d", errno); } + } - return 1; + return 1; } @@ -293,32 +293,32 @@ int fd_write_reply( int fd, uint64_t handle, int error ) * Returns 1; we don't check for errors on the write. * TODO: Check for errors on the write. */ -int client_write_reply( struct client * client, struct nbd_request *request, int error ) +int client_write_reply(struct client *client, struct nbd_request *request, + int error) { - return fd_write_reply( client->socket, request->handle.w, error); + return fd_write_reply(client->socket, request->handle.w, error); } -void client_write_init( struct client * client, uint64_t size ) +void client_write_init(struct client *client, uint64_t size) { - struct nbd_init init = {{0}}; - struct nbd_init_raw init_raw = {{0}}; + struct nbd_init init = { {0} }; + struct nbd_init_raw init_raw = { {0} }; - memcpy( init.passwd, INIT_PASSWD, sizeof( init.passwd ) ); - init.magic = INIT_MAGIC; - init.size = size; - /* As more features are implemented, this is the place to advertise - * them. - */ - init.flags = FLAG_HAS_FLAGS | FLAG_SEND_FLUSH | FLAG_SEND_FUA; - memset( init.reserved, 0, 124 ); + memcpy(init.passwd, INIT_PASSWD, sizeof(init.passwd)); + init.magic = INIT_MAGIC; + init.size = size; + /* As more features are implemented, this is the place to advertise + * them. + */ + init.flags = FLAG_HAS_FLAGS | FLAG_SEND_FLUSH | FLAG_SEND_FUA; + memset(init.reserved, 0, 124); - nbd_h2r_init( &init, &init_raw ); + nbd_h2r_init(&init, &init_raw); - ERROR_IF_NEGATIVE( - writeloop(client->socket, &init_raw, sizeof(init_raw)), - "Couldn't send hello" - ); + ERROR_IF_NEGATIVE(writeloop + (client->socket, &init_raw, sizeof(init_raw)), + "Couldn't send hello"); } @@ -326,43 +326,35 @@ void client_write_init( struct client * client, uint64_t size ) * client sends a write we can't honour - we need to get rid of the * bytes they've already written before we can look for another request. */ -void client_flush( struct client * client, size_t len ) +void client_flush(struct client *client, size_t len) { - int devnull = open("/dev/null", O_WRONLY); - FATAL_IF_NEGATIVE( devnull, - "Couldn't open /dev/null: %s", strerror(errno)); - int pipes[2]; - pipe( pipes ); + int devnull = open("/dev/null", O_WRONLY); + FATAL_IF_NEGATIVE(devnull, + "Couldn't open /dev/null: %s", strerror(errno)); + int pipes[2]; + pipe(pipes); - const unsigned int flags = SPLICE_F_MORE | SPLICE_F_MOVE; - size_t spliced = 0; + const unsigned int flags = SPLICE_F_MORE | SPLICE_F_MOVE; + size_t spliced = 0; - while ( spliced < len ) { - ssize_t received = splice( - client->socket, NULL, - pipes[1], NULL, - len-spliced, flags ); - FATAL_IF_NEGATIVE( received, - "splice error: %s", - strerror(errno)); - ssize_t junked = 0; - while( junked < received ) { - ssize_t junk; - junk = splice( - pipes[0], NULL, - devnull, NULL, - received, flags ); - FATAL_IF_NEGATIVE( junk, - "splice error: %s", - strerror(errno)); - junked += junk; - } - spliced += received; + while (spliced < len) { + ssize_t received = splice(client->socket, NULL, + pipes[1], NULL, + len - spliced, flags); + FATAL_IF_NEGATIVE(received, "splice error: %s", strerror(errno)); + ssize_t junked = 0; + while (junked < received) { + ssize_t junk; + junk = splice(pipes[0], NULL, devnull, NULL, received, flags); + FATAL_IF_NEGATIVE(junk, "splice error: %s", strerror(errno)); + junked += junk; } - debug("Flushed %d bytes", len); + spliced += received; + } + debug("Flushed %d bytes", len); - close( devnull ); + close(devnull); } @@ -371,369 +363,362 @@ void client_flush( struct client * client, size_t len ) * request_err is set to 0 if the client sent a bad request, in which * case we drop the connection. */ -int client_request_needs_reply( struct client * client, - struct nbd_request request ) +int client_request_needs_reply(struct client *client, + struct nbd_request request) { - /* The client is stupid, but don't take down the whole server as a result. - * We send a reply before disconnecting so that at least some indication of - * the problem is visible, and so proxies don't retry the same (bad) request - * forever. - */ - if (request.magic != REQUEST_MAGIC) { - warn("Bad magic 0x%08X from client", request.magic); - client_write_reply( client, &request, EBADMSG ); - client->disconnect = 1; // no need to flush - return 0; - } - - debug( - "request type=%"PRIu16", flags=%"PRIu16", from=%"PRIu64", len=%"PRIu32", handle=0x%08X", - request.type, request.flags, request.from, request.len, request.handle - ); - - /* check it's not out of range. NBD protocol requires ENOSPC to be - * returned in this instance - */ - if ( request.from+request.len > client->serve->size) { - warn("write request %"PRIu64"+%"PRIu32" out of range", - request.from, request.len - ); - if ( request.type == REQUEST_WRITE ) { - client_flush( client, request.len ); - } - client_write_reply( client, &request, ENOSPC ); - client->disconnect = 0; - return 0; + /* The client is stupid, but don't take down the whole server as a result. + * We send a reply before disconnecting so that at least some indication of + * the problem is visible, and so proxies don't retry the same (bad) request + * forever. + */ + if (request.magic != REQUEST_MAGIC) { + warn("Bad magic 0x%08X from client", request.magic); + client_write_reply(client, &request, EBADMSG); + client->disconnect = 1; // no need to flush + return 0; + } + + debug("request type=%" PRIu16 ", flags=%" PRIu16 ", from=%" PRIu64 + ", len=%" PRIu32 ", handle=0x%08X", request.type, request.flags, + request.from, request.len, request.handle); + + /* check it's not out of range. NBD protocol requires ENOSPC to be + * returned in this instance + */ + if (request.from + request.len > client->serve->size) { + warn("write request %" PRIu64 "+%" PRIu32 " out of range", + request.from, request.len); + if (request.type == REQUEST_WRITE) { + client_flush(client, request.len); } + client_write_reply(client, &request, ENOSPC); + client->disconnect = 0; + return 0; + } - switch (request.type) - { - case REQUEST_READ: - break; - case REQUEST_WRITE: - break; - case REQUEST_DISCONNECT: - debug("request disconnect"); - client->disconnect = 1; - return 0; - case REQUEST_FLUSH: - break; - default: - /* NBD prototcol says servers SHOULD return EINVAL to unknown - * commands */ - warn("Unknown request 0x%08X", request.type); - client_write_reply( client, &request, EINVAL ); - client->disconnect = 0; - return 0; - } - return 1; + switch (request.type) { + case REQUEST_READ: + break; + case REQUEST_WRITE: + break; + case REQUEST_DISCONNECT: + debug("request disconnect"); + client->disconnect = 1; + return 0; + case REQUEST_FLUSH: + break; + default: + /* NBD prototcol says servers SHOULD return EINVAL to unknown + * commands */ + warn("Unknown request 0x%08X", request.type); + client_write_reply(client, &request, EINVAL); + client->disconnect = 0; + return 0; + } + return 1; } -void client_reply_to_read( struct client* client, struct nbd_request request ) +void client_reply_to_read(struct client *client, + struct nbd_request request) { - off64_t offset; + off64_t offset; - debug("request read %ld+%d", request.from, request.len); - sock_set_tcp_cork( client->socket, 1 ); - client_write_reply( client, &request, 0 ); + debug("request read %ld+%d", request.from, request.len); + sock_set_tcp_cork(client->socket, 1); + client_write_reply(client, &request, 0); - offset = request.from; + offset = request.from; - /* If we get cut off partway through this sendfile, we don't - * want to kill the server. This should be an error. - */ - ERROR_IF_NEGATIVE( - sendfileloop( - client->socket, - client->fileno, - &offset, - request.len), - "sendfile failed from=%ld, len=%d", - offset, - request.len); + /* If we get cut off partway through this sendfile, we don't + * want to kill the server. This should be an error. + */ + ERROR_IF_NEGATIVE(sendfileloop(client->socket, + client->fileno, + &offset, + request.len), + "sendfile failed from=%ld, len=%d", + offset, request.len); - sock_set_tcp_cork( client->socket, 0 ); + sock_set_tcp_cork(client->socket, 0); } -void client_reply_to_write( struct client* client, struct nbd_request request ) +void client_reply_to_write(struct client *client, + struct nbd_request request) { - debug("request write from=%"PRIu64", len=%"PRIu32", handle=0x%08X", request.from, request.len, request.handle); - if (client->serve->allocation_map_built) { - write_not_zeroes( client, request.from, request.len ); - } - else { - debug("No allocation map, writing directly."); - /* If we get cut off partway through reading this data: - * */ - ERROR_IF_NEGATIVE( - readloop( client->socket, - client->mapped + request.from, - request.len), - "reading write data failed from=%ld, len=%d", - request.from, - request.len - ); + debug("request write from=%" PRIu64 ", len=%" PRIu32 ", handle=0x%08X", + request.from, request.len, request.handle); + if (client->serve->allocation_map_built) { + write_not_zeroes(client, request.from, request.len); + } else { + debug("No allocation map, writing directly."); + /* If we get cut off partway through reading this data: + * */ + ERROR_IF_NEGATIVE(readloop(client->socket, + client->mapped + request.from, + request.len), + "reading write data failed from=%ld, len=%d", + request.from, request.len); - /* the allocation_map is shared between client threads, and may be - * being built. We need to reflect the write in it, as it may be in - * a position the builder has already gone over. - */ - bitset_set_range(client->serve->allocation_map, request.from, request.len); - } + /* the allocation_map is shared between client threads, and may be + * being built. We need to reflect the write in it, as it may be in + * a position the builder has already gone over. + */ + bitset_set_range(client->serve->allocation_map, request.from, + request.len); + } - // Only flush if FUA is set - if (request.flags & CMD_FLAG_FUA) - { - /* multiple of page size */ - uint64_t from_rounded = request.from & (~(sysconf(_SC_PAGE_SIZE)-1)); - uint64_t len_rounded = request.len + (request.from - from_rounded); - debug("Calling msync from=%"PRIu64", len=%"PRIu64"",from_rounded, len_rounded); + // Only flush if FUA is set + if (request.flags & CMD_FLAG_FUA) { + /* multiple of page size */ + uint64_t from_rounded = + request.from & (~(sysconf(_SC_PAGE_SIZE) - 1)); + uint64_t len_rounded = request.len + (request.from - from_rounded); + debug("Calling msync from=%" PRIu64 ", len=%" PRIu64 "", + from_rounded, len_rounded); - FATAL_IF_NEGATIVE( - msync( client->mapped + from_rounded, + FATAL_IF_NEGATIVE(msync(client->mapped + from_rounded, len_rounded, MS_SYNC | MS_INVALIDATE), - "msync failed %ld %ld", request.from, request.len - ); - } - client_write_reply( client, &request, 0); + "msync failed %ld %ld", request.from, + request.len); + } + client_write_reply(client, &request, 0); } -void client_reply_to_flush( struct client* client, struct nbd_request request ) +void client_reply_to_flush(struct client *client, + struct nbd_request request) { - debug("request flush from=%"PRIu64", len=%"PRIu32", handle=0x%08X", request.from, request.len, request.handle); + debug("request flush from=%" PRIu64 ", len=%" PRIu32 ", handle=0x%08X", + request.from, request.len, request.handle); - ERROR_IF_NEGATIVE( - msync(client->mapped, client->mapped_size, MS_SYNC | MS_INVALIDATE), - "flush failed" - ); + ERROR_IF_NEGATIVE(msync + (client->mapped, client->mapped_size, + MS_SYNC | MS_INVALIDATE), "flush failed"); - client_write_reply( client, &request, 0); + client_write_reply(client, &request, 0); } -void client_reply( struct client* client, struct nbd_request request ) +void client_reply(struct client *client, struct nbd_request request) { - switch (request.type) { - case REQUEST_READ: - client_reply_to_read( client, request ); - break; - case REQUEST_WRITE: - client_reply_to_write( client, request ); - break; - case REQUEST_FLUSH: - client_reply_to_flush( client, request ); - break; - } + switch (request.type) { + case REQUEST_READ: + client_reply_to_read(client, request); + break; + case REQUEST_WRITE: + client_reply_to_write(client, request); + break; + case REQUEST_FLUSH: + client_reply_to_flush(client, request); + break; + } } /* Starts a timer that will kill the whole process if disarm is not called * within a timeout (see CLIENT_HANDLE_TIMEOUT). */ -void client_arm_killswitch( struct client* client ) +void client_arm_killswitch(struct client *client) { - struct itimerspec its = { - .it_value = { .tv_nsec = 0, .tv_sec = CLIENT_HANDLER_TIMEOUT }, - .it_interval = { .tv_nsec = 0, .tv_sec = 0 } - }; + struct itimerspec its = { + .it_value = {.tv_nsec = 0,.tv_sec = CLIENT_HANDLER_TIMEOUT}, + .it_interval = {.tv_nsec = 0,.tv_sec = 0} + }; - if ( !client->serve->use_killswitch ) { - return; - } + if (!client->serve->use_killswitch) { + return; + } - debug( "Arming killswitch" ); + debug("Arming killswitch"); - FATAL_IF_NEGATIVE( - timer_settime( client->killswitch, 0, &its, NULL ), - SHOW_ERRNO( "Failed to arm killswitch" ) + FATAL_IF_NEGATIVE(timer_settime(client->killswitch, 0, &its, NULL), + SHOW_ERRNO("Failed to arm killswitch") ); - return; + return; } -void client_disarm_killswitch( struct client* client ) +void client_disarm_killswitch(struct client *client) { - struct itimerspec its = { - .it_value = { .tv_nsec = 0, .tv_sec = 0 }, - .it_interval = { .tv_nsec = 0, .tv_sec = 0 } - }; + struct itimerspec its = { + .it_value = {.tv_nsec = 0,.tv_sec = 0}, + .it_interval = {.tv_nsec = 0,.tv_sec = 0} + }; - if ( !client->serve->use_killswitch ) { - return; - } + if (!client->serve->use_killswitch) { + return; + } - debug( "Disarming killswitch" ); + debug("Disarming killswitch"); - FATAL_IF_NEGATIVE( - timer_settime( client->killswitch, 0, &its, NULL ), - SHOW_ERRNO( "Failed to disarm killswitch" ) + FATAL_IF_NEGATIVE(timer_settime(client->killswitch, 0, &its, NULL), + SHOW_ERRNO("Failed to disarm killswitch") ); - return; + return; } /* Returns 0 if we should continue trying to serve requests */ -int client_serve_request(struct client* client) +int client_serve_request(struct client *client) { - struct nbd_request request = {0}; - int stop = 1; - int disconnected = 0; - fd_set rfds, efds; - int fd_count; + struct nbd_request request = { 0 }; + int stop = 1; + int disconnected = 0; + fd_set rfds, efds; + int fd_count; - /* wait until there are some bytes on the fd before committing to reads - * FIXME: this whole scheme is broken because we're using blocking reads. - * read() can block directly after a select anyway, and it's possible that, - * without the killswitch, we'd hang forever. With the killswitch, we just - * hang for "a while". The Right Thing to do is to rewrite client.c to be - * non-blocking. - */ + /* wait until there are some bytes on the fd before committing to reads + * FIXME: this whole scheme is broken because we're using blocking reads. + * read() can block directly after a select anyway, and it's possible that, + * without the killswitch, we'd hang forever. With the killswitch, we just + * hang for "a while". The Right Thing to do is to rewrite client.c to be + * non-blocking. + */ - FD_ZERO( &rfds ); - FD_SET( client->socket, &rfds ); - self_pipe_fd_set( client->stop_signal, &rfds ); + FD_ZERO(&rfds); + FD_SET(client->socket, &rfds); + self_pipe_fd_set(client->stop_signal, &rfds); - FD_ZERO( &efds ); - FD_SET( client->socket, &efds ); + FD_ZERO(&efds); + FD_SET(client->socket, &efds); - fd_count = sock_try_select( FD_SETSIZE, &rfds, NULL, &efds, NULL ); + fd_count = sock_try_select(FD_SETSIZE, &rfds, NULL, &efds, NULL); - if ( fd_count == 0 ) { - /* This "can't ever happen" */ - fatal( "No FDs selected, and no timeout!" ); - } - else if ( fd_count < 0 ) { fatal( "Select failed" ); } + if (fd_count == 0) { + /* This "can't ever happen" */ + fatal("No FDs selected, and no timeout!"); + } else if (fd_count < 0) { + fatal("Select failed"); + } - if ( self_pipe_fd_isset( client->stop_signal, &rfds ) ){ - debug("Client received stop signal."); - return 1; // Don't try to serve more requests - } + if (self_pipe_fd_isset(client->stop_signal, &rfds)) { + debug("Client received stop signal."); + return 1; // Don't try to serve more requests + } - if ( FD_ISSET( client->socket, &efds ) ) { - debug( "Client connection closed" ); - return 1; - } + if (FD_ISSET(client->socket, &efds)) { + debug("Client connection closed"); + return 1; + } - /* We arm / disarm around the whole request cycle. The reason for this is - * that the remote peer could uncleanly die at any point; if we're stuck on - * a blocking read(), then that will hang for (almost) forever. This is bad - * in general, makes the server respond only to kill -9, and breaks - * outward mirroring in a most unpleasant way. - * - * Don't forget to disarm before exiting, no matter what! - * - * The replication is simple: open a connection to the flexnbd server, write - * a single byte, and then wait. - * - */ - client_arm_killswitch( client ); + /* We arm / disarm around the whole request cycle. The reason for this is + * that the remote peer could uncleanly die at any point; if we're stuck on + * a blocking read(), then that will hang for (almost) forever. This is bad + * in general, makes the server respond only to kill -9, and breaks + * outward mirroring in a most unpleasant way. + * + * Don't forget to disarm before exiting, no matter what! + * + * The replication is simple: open a connection to the flexnbd server, write + * a single byte, and then wait. + * + */ + client_arm_killswitch(client); - if ( !client_read_request( client, &request, &disconnected ) ) { - client_disarm_killswitch( client ); - return stop; - } - if ( disconnected ) { - client_disarm_killswitch( client ); - return stop; - } - - if ( !client_request_needs_reply( client, request ) ) { - client_disarm_killswitch( client ); - return client->disconnect; - } - - { - if ( !server_is_closed( client->serve ) ) { - client_reply( client, request ); - stop = 0; - } - } - - client_disarm_killswitch( client ); + if (!client_read_request(client, &request, &disconnected)) { + client_disarm_killswitch(client); return stop; + } + if (disconnected) { + client_disarm_killswitch(client); + return stop; + } + + if (!client_request_needs_reply(client, request)) { + client_disarm_killswitch(client); + return client->disconnect; + } + + { + if (!server_is_closed(client->serve)) { + client_reply(client, request); + stop = 0; + } + } + + client_disarm_killswitch(client); + return stop; } -void client_send_hello(struct client* client) +void client_send_hello(struct client *client) { - client_write_init( client, client->serve->size ); + client_write_init(client, client->serve->size); } -void client_cleanup(struct client* client, - int fatal __attribute__ ((unused)) ) +void client_cleanup(struct client *client, + int fatal __attribute__ ((unused))) { - info("client cleanup for client %p", client); + info("client cleanup for client %p", client); - /* If the thread hits an error, we need to ensure this is off */ - client_disarm_killswitch( client ); + /* If the thread hits an error, we need to ensure this is off */ + client_disarm_killswitch(client); - if (client->socket) { - FATAL_IF_NEGATIVE( close(client->socket), - "Error closing client socket %d", - client->socket ); - debug("Closed client socket fd %d", client->socket); - client->socket = -1; - } - if (client->mapped) { - munmap(client->mapped, client->serve->size); - } - if (client->fileno) { - FATAL_IF_NEGATIVE( close(client->fileno), - "Error closing file %d", - client->fileno ); - debug("Closed client file fd %d", client->fileno ); - client->fileno = -1; - } + if (client->socket) { + FATAL_IF_NEGATIVE(close(client->socket), + "Error closing client socket %d", + client->socket); + debug("Closed client socket fd %d", client->socket); + client->socket = -1; + } + if (client->mapped) { + munmap(client->mapped, client->serve->size); + } + if (client->fileno) { + FATAL_IF_NEGATIVE(close(client->fileno), + "Error closing file %d", client->fileno); + debug("Closed client file fd %d", client->fileno); + client->fileno = -1; + } - if ( server_acl_locked( client->serve ) ) { server_unlock_acl( client->serve ); } + if (server_acl_locked(client->serve)) { + server_unlock_acl(client->serve); + } } -void* client_serve(void* client_uncast) +void *client_serve(void *client_uncast) { - struct client* client = (struct client*) client_uncast; + struct client *client = (struct client *) client_uncast; - error_set_handler((cleanup_handler*) client_cleanup, client); + error_set_handler((cleanup_handler *) client_cleanup, client); - info("client: mmaping file"); - FATAL_IF_NEGATIVE( - open_and_mmap( - client->serve->filename, - &client->fileno, - &client->mapped_size, - (void**) &client->mapped - ), - "Couldn't open/mmap file %s: %s", client->serve->filename, strerror( errno ) + info("client: mmaping file"); + FATAL_IF_NEGATIVE(open_and_mmap(client->serve->filename, + &client->fileno, + &client->mapped_size, + (void **) &client->mapped), + "Couldn't open/mmap file %s: %s", + client->serve->filename, strerror(errno) ); - FATAL_IF_NEGATIVE( - madvise( client->mapped, client->serve->size, MADV_RANDOM ), - SHOW_ERRNO( "Failed to madvise() %s", client->serve->filename ) + FATAL_IF_NEGATIVE(madvise + (client->mapped, client->serve->size, MADV_RANDOM), + SHOW_ERRNO("Failed to madvise() %s", + client->serve->filename) ); - debug( "Opened client file fd %d", client->fileno); - debug("client: sending hello"); - client_send_hello(client); + debug("Opened client file fd %d", client->fileno); + debug("client: sending hello"); + client_send_hello(client); - debug("client: serving requests"); - while (client_serve_request(client) == 0) - ; - debug("client: stopped serving requests"); - client->stopped = 1; + debug("client: serving requests"); + while (client_serve_request(client) == 0); + debug("client: stopped serving requests"); + client->stopped = 1; - if ( client->disconnect ){ - debug("client: control arrived" ); - server_control_arrived( client->serve ); - } + if (client->disconnect) { + debug("client: control arrived"); + server_control_arrived(client->serve); + } - debug("Cleaning client %p up normally in thread %p", client, pthread_self()); - client_cleanup(client, 0); - debug("Client thread done" ); + debug("Cleaning client %p up normally in thread %p", client, + pthread_self()); + client_cleanup(client, 0); + debug("Client thread done"); - return NULL; + return NULL; } - diff --git a/src/server/client.h b/src/server/client.h index a03ea44..56b1458 100644 --- a/src/server/client.h +++ b/src/server/client.h @@ -19,41 +19,40 @@ struct client { - /* When we call pthread_join, if the thread is already dead - * we can get an ESRCH. Since we have no other way to tell - * if that ESRCH is from a dead thread or a thread that never - * existed, we use a `stopped` flag to indicate a thread which - * did exist, but went away. Only check this after a - * pthread_join call. - */ - int stopped; - int socket; + /* When we call pthread_join, if the thread is already dead + * we can get an ESRCH. Since we have no other way to tell + * if that ESRCH is from a dead thread or a thread that never + * existed, we use a `stopped` flag to indicate a thread which + * did exist, but went away. Only check this after a + * pthread_join call. + */ + int stopped; + int socket; - int fileno; - char* mapped; + int fileno; + char *mapped; - uint64_t mapped_size; + uint64_t mapped_size; - struct self_pipe * stop_signal; + struct self_pipe *stop_signal; - struct server* serve; /* FIXME: remove above duplication */ + struct server *serve; /* FIXME: remove above duplication */ - /* Have we seen a REQUEST_DISCONNECT message? */ - int disconnect; + /* Have we seen a REQUEST_DISCONNECT message? */ + int disconnect; - /* kill the whole server if a request has been outstanding too long, - * assuming use_killswitch is set in serve - */ - timer_t killswitch; + /* kill the whole server if a request has been outstanding too long, + * assuming use_killswitch is set in serve + */ + timer_t killswitch; }; -void client_killswitch_hit(int signal, siginfo_t *info, void *ptr); +void client_killswitch_hit(int signal, siginfo_t * info, void *ptr); -void* client_serve(void* client_uncast); -struct client * client_create( struct server * serve, int socket ); -void client_destroy( struct client * client ); -void client_signal_stop( struct client * client ); +void *client_serve(void *client_uncast); +struct client *client_create(struct server *serve, int socket); +void client_destroy(struct client *client); +void client_signal_stop(struct client *client); #endif - diff --git a/src/server/control.c b/src/server/control.c index 63f0720..394854e 100644 --- a/src/server/control.c +++ b/src/server/control.c @@ -44,590 +44,570 @@ #include -struct control * control_create( - struct flexnbd * flexnbd, - const char * csn) +struct control *control_create(struct flexnbd *flexnbd, const char *csn) { - struct control * control = xmalloc( sizeof( struct control ) ); + struct control *control = xmalloc(sizeof(struct control)); - NULLCHECK( csn ); + NULLCHECK(csn); - control->flexnbd = flexnbd; - control->socket_name = csn; - control->open_signal = self_pipe_create(); - control->close_signal = self_pipe_create(); - control->mirror_state_mbox = mbox_create(); + control->flexnbd = flexnbd; + control->socket_name = csn; + control->open_signal = self_pipe_create(); + control->close_signal = self_pipe_create(); + control->mirror_state_mbox = mbox_create(); - return control; + return control; } -void control_signal_close( struct control * control) +void control_signal_close(struct control *control) { - NULLCHECK( control ); - self_pipe_signal( control->close_signal ); + NULLCHECK(control); + self_pipe_signal(control->close_signal); } -void control_destroy( struct control * control ) +void control_destroy(struct control *control) { - NULLCHECK( control ); + NULLCHECK(control); - mbox_destroy( control->mirror_state_mbox ); - self_pipe_destroy( control->close_signal ); - self_pipe_destroy( control->open_signal ); - free( control ); + mbox_destroy(control->mirror_state_mbox); + self_pipe_destroy(control->close_signal); + self_pipe_destroy(control->open_signal); + free(control); } -struct control_client * control_client_create( - struct flexnbd * flexnbd, - int client_fd , - struct mbox * state_mbox ) +struct control_client *control_client_create(struct flexnbd *flexnbd, + int client_fd, + struct mbox *state_mbox) { - NULLCHECK( flexnbd ); + NULLCHECK(flexnbd); - struct control_client * control_client = - xmalloc( sizeof( struct control_client ) ); + struct control_client *control_client = + xmalloc(sizeof(struct control_client)); - control_client->socket = client_fd; - control_client->flexnbd = flexnbd; - control_client->mirror_state_mbox = state_mbox; - return control_client; + control_client->socket = client_fd; + control_client->flexnbd = flexnbd; + control_client->mirror_state_mbox = state_mbox; + return control_client; } -void control_client_destroy( struct control_client * client ) +void control_client_destroy(struct control_client *client) { - NULLCHECK( client ); - free( client ); + NULLCHECK(client); + free(client); } -void control_respond(struct control_client * client); +void control_respond(struct control_client *client); -void control_handle_client( struct control * control, int client_fd ) +void control_handle_client(struct control *control, int client_fd) { - NULLCHECK( control ); - NULLCHECK( control->flexnbd ); - struct control_client * control_client = - control_client_create( - control->flexnbd, - client_fd , - control->mirror_state_mbox); + NULLCHECK(control); + NULLCHECK(control->flexnbd); + struct control_client *control_client = + control_client_create(control->flexnbd, + client_fd, + control->mirror_state_mbox); - /* We intentionally don't spawn a thread for the client here. - * This is to avoid having more than one thread potentially - * waiting on the migration commit status. - */ - control_respond( control_client ); + /* We intentionally don't spawn a thread for the client here. + * This is to avoid having more than one thread potentially + * waiting on the migration commit status. + */ + control_respond(control_client); } -void control_accept_client( struct control * control ) +void control_accept_client(struct control *control) { - int client_fd; - union mysockaddr client_address; - socklen_t addrlen = sizeof( union mysockaddr ); + int client_fd; + union mysockaddr client_address; + socklen_t addrlen = sizeof(union mysockaddr); - client_fd = accept( control->control_fd, &client_address.generic, &addrlen ); - FATAL_IF( -1 == client_fd, "control accept failed" ); + client_fd = + accept(control->control_fd, &client_address.generic, &addrlen); + FATAL_IF(-1 == client_fd, "control accept failed"); - control_handle_client( control, client_fd ); + control_handle_client(control, client_fd); } -int control_accept( struct control * control ) +int control_accept(struct control *control) { - NULLCHECK( control ); + NULLCHECK(control); - fd_set fds; + fd_set fds; - FD_ZERO( &fds ); - FD_SET( control->control_fd, &fds ); - self_pipe_fd_set( control->close_signal, &fds ); - debug("Control thread selecting"); - FATAL_UNLESS( 0 < select( FD_SETSIZE, &fds, NULL, NULL, NULL ), - "Control select failed." ); + FD_ZERO(&fds); + FD_SET(control->control_fd, &fds); + self_pipe_fd_set(control->close_signal, &fds); + debug("Control thread selecting"); + FATAL_UNLESS(0 < select(FD_SETSIZE, &fds, NULL, NULL, NULL), + "Control select failed."); - if ( self_pipe_fd_isset( control->close_signal, &fds ) ){ - return 0; - } + if (self_pipe_fd_isset(control->close_signal, &fds)) { + return 0; + } - if ( FD_ISSET( control->control_fd, &fds ) ) { - control_accept_client( control ); - } - return 1; + if (FD_ISSET(control->control_fd, &fds)) { + control_accept_client(control); + } + return 1; } -void control_accept_loop( struct control * control ) +void control_accept_loop(struct control *control) { - while( control_accept( control ) ); + while (control_accept(control)); } -int open_control_socket( const char * socket_name ) +int open_control_socket(const char *socket_name) { - struct sockaddr_un bind_address; - int control_fd; + struct sockaddr_un bind_address; + int control_fd; - if (!socket_name) { - fatal( "Tried to open a control socket without a socket name" ); - } + if (!socket_name) { + fatal("Tried to open a control socket without a socket name"); + } - control_fd = socket(AF_UNIX, SOCK_STREAM, 0); - FATAL_IF_NEGATIVE(control_fd , - "Couldn't create control socket"); + control_fd = socket(AF_UNIX, SOCK_STREAM, 0); + FATAL_IF_NEGATIVE(control_fd, "Couldn't create control socket"); - memset(&bind_address, 0, sizeof(struct sockaddr_un)); - bind_address.sun_family = AF_UNIX; - strncpy(bind_address.sun_path, socket_name, sizeof(bind_address.sun_path)-1); + memset(&bind_address, 0, sizeof(struct sockaddr_un)); + bind_address.sun_family = AF_UNIX; + strncpy(bind_address.sun_path, socket_name, + sizeof(bind_address.sun_path) - 1); - //unlink(socket_name); /* ignore failure */ + //unlink(socket_name); /* ignore failure */ - FATAL_IF_NEGATIVE( - bind(control_fd , &bind_address, sizeof(bind_address)), - "Couldn't bind control socket to %s: %s", - socket_name, strerror( errno ) + FATAL_IF_NEGATIVE(bind + (control_fd, &bind_address, sizeof(bind_address)), + "Couldn't bind control socket to %s: %s", + socket_name, strerror(errno) ); - FATAL_IF_NEGATIVE( - listen(control_fd , 5), - "Couldn't listen on control socket" - ); - return control_fd; + FATAL_IF_NEGATIVE(listen(control_fd, 5), + "Couldn't listen on control socket"); + return control_fd; } -void control_listen(struct control* control) +void control_listen(struct control *control) { - NULLCHECK( control ); - control->control_fd = open_control_socket( control->socket_name ); + NULLCHECK(control); + control->control_fd = open_control_socket(control->socket_name); } -void control_wait_for_open_signal( struct control * control ) +void control_wait_for_open_signal(struct control *control) { - fd_set fds; - FD_ZERO( &fds ); - self_pipe_fd_set( control->open_signal, &fds ); - FATAL_IF_NEGATIVE( select( FD_SETSIZE, &fds, NULL, NULL, NULL ), - "select() failed" ); + fd_set fds; + FD_ZERO(&fds); + self_pipe_fd_set(control->open_signal, &fds); + FATAL_IF_NEGATIVE(select(FD_SETSIZE, &fds, NULL, NULL, NULL), + "select() failed"); - self_pipe_signal_clear( control->open_signal ); + self_pipe_signal_clear(control->open_signal); } -void control_serve( struct control * control ) +void control_serve(struct control *control) { - NULLCHECK( control ); + NULLCHECK(control); - control_wait_for_open_signal( control ); - control_listen( control ); - while( control_accept( control ) ); + control_wait_for_open_signal(control); + control_listen(control); + while (control_accept(control)); } -void control_cleanup( - struct control * control, - int fatal __attribute__((unused)) ) +void control_cleanup(struct control *control, + int fatal __attribute__ ((unused))) { - NULLCHECK( control ); - unlink( control->socket_name ); - close( control->control_fd ); + NULLCHECK(control); + unlink(control->socket_name); + close(control->control_fd); } -void * control_runner( void * control_uncast ) +void *control_runner(void *control_uncast) { - debug("Control thread"); - NULLCHECK( control_uncast ); - struct control * control = (struct control *)control_uncast; + debug("Control thread"); + NULLCHECK(control_uncast); + struct control *control = (struct control *) control_uncast; - error_set_handler( (cleanup_handler*)control_cleanup, control ); + error_set_handler((cleanup_handler *) control_cleanup, control); - control_serve( control ); + control_serve(control); - control_cleanup( control, 0 ); - pthread_exit( NULL ); + control_cleanup(control, 0); + pthread_exit(NULL); } #define write_socket(msg) write(client_fd, (msg "\n"), strlen((msg))+1) -void control_write_mirror_response( enum mirror_state mirror_state, int client_fd ) +void control_write_mirror_response(enum mirror_state mirror_state, + int client_fd) { - switch (mirror_state) { - case MS_INIT: - case MS_UNKNOWN: - write_socket( "1: Mirror failed to initialise" ); - fatal( "Impossible mirror state: %d", mirror_state ); - case MS_FAIL_CONNECT: - write_socket( "1: Mirror failed to connect"); - break; - case MS_FAIL_REJECTED: - write_socket( "1: Mirror was rejected" ); - break; - case MS_FAIL_NO_HELLO: - write_socket( "1: Remote server failed to respond"); - break; - case MS_FAIL_SIZE_MISMATCH: - write_socket( "1: Remote size does not match local size" ); - break; - case MS_ABANDONED: - write_socket( "1: Mirroring abandoned" ); - break; - case MS_GO: - case MS_DONE: /* Yes, I know we know better, but it's simpler this way */ - write_socket( "0: Mirror started" ); - break; - default: - fatal( "Unhandled mirror state: %d", mirror_state ); - } + switch (mirror_state) { + case MS_INIT: + case MS_UNKNOWN: + write_socket("1: Mirror failed to initialise"); + fatal("Impossible mirror state: %d", mirror_state); + case MS_FAIL_CONNECT: + write_socket("1: Mirror failed to connect"); + break; + case MS_FAIL_REJECTED: + write_socket("1: Mirror was rejected"); + break; + case MS_FAIL_NO_HELLO: + write_socket("1: Remote server failed to respond"); + break; + case MS_FAIL_SIZE_MISMATCH: + write_socket("1: Remote size does not match local size"); + break; + case MS_ABANDONED: + write_socket("1: Mirroring abandoned"); + break; + case MS_GO: + case MS_DONE: /* Yes, I know we know better, but it's simpler this way */ + write_socket("0: Mirror started"); + break; + default: + fatal("Unhandled mirror state: %d", mirror_state); + } } + #undef write_socket /* Call this in the thread where you want to receive the mirror state */ -enum mirror_state control_client_mirror_wait( - struct control_client* client) +enum mirror_state control_client_mirror_wait(struct control_client *client) { - NULLCHECK( client ); - NULLCHECK( client->mirror_state_mbox ); + NULLCHECK(client); + NULLCHECK(client->mirror_state_mbox); - struct mbox * mbox = client->mirror_state_mbox; - enum mirror_state mirror_state; - enum mirror_state * contents; + struct mbox *mbox = client->mirror_state_mbox; + enum mirror_state mirror_state; + enum mirror_state *contents; - contents = (enum mirror_state*)mbox_receive( mbox ); - NULLCHECK( contents ); + contents = (enum mirror_state *) mbox_receive(mbox); + NULLCHECK(contents); - mirror_state = *contents; + mirror_state = *contents; - free( contents ); + free(contents); - return mirror_state; + return mirror_state; } #define write_socket(msg) write(client->socket, (msg "\n"), strlen((msg))+1) /** Command parser to start mirror process from socket input */ -int control_mirror(struct control_client* client, int linesc, char** lines) +int control_mirror(struct control_client *client, int linesc, char **lines) { - NULLCHECK( client ); + NULLCHECK(client); - struct flexnbd * flexnbd = client->flexnbd; - union mysockaddr *connect_to = xmalloc( sizeof( union mysockaddr ) ); - union mysockaddr *connect_from = NULL; - uint64_t max_Bps = UINT64_MAX; - int action_at_finish; - int raw_port; + struct flexnbd *flexnbd = client->flexnbd; + union mysockaddr *connect_to = xmalloc(sizeof(union mysockaddr)); + union mysockaddr *connect_from = NULL; + uint64_t max_Bps = UINT64_MAX; + int action_at_finish; + int raw_port; - if (linesc < 2) { - write_socket("1: mirror takes at least two parameters"); - return -1; + if (linesc < 2) { + write_socket("1: mirror takes at least two parameters"); + return -1; + } + + if (parse_ip_to_sockaddr(&connect_to->generic, lines[0]) == 0) { + write_socket("1: bad IP address"); + return -1; + } + + raw_port = atoi(lines[1]); + if (raw_port < 0 || raw_port > 65535) { + write_socket("1: bad IP port number"); + return -1; + } + connect_to->v4.sin_port = htobe16(raw_port); + + action_at_finish = ACTION_EXIT; + if (linesc > 2) { + if (strcmp("exit", lines[2]) == 0) { + action_at_finish = ACTION_EXIT; + } else if (strcmp("unlink", lines[2]) == 0) { + action_at_finish = ACTION_UNLINK; + } else if (strcmp("nothing", lines[2]) == 0) { + action_at_finish = ACTION_NOTHING; + } else { + write_socket("1: action must be 'exit' or 'nothing'"); + return -1; + } + } + + if (linesc > 3) { + connect_from = xmalloc(sizeof(union mysockaddr)); + if (parse_ip_to_sockaddr(&connect_from->generic, lines[3]) == 0) { + write_socket("1: bad bind address"); + return -1; + } + } + + if (linesc > 4) { + errno = 0; + max_Bps = strtoull(lines[4], NULL, 10); + if (errno == ERANGE) { + write_socket("1: max_bps out of range"); + return -1; + } else if (errno != 0) { + write_socket("1: max_bps couldn't be parsed"); + return -1; + } + } + + + if (linesc > 5) { + write_socket("1: unrecognised parameters to mirror"); + return -1; + } + + struct server *serve = flexnbd_server(flexnbd); + + server_lock_start_mirror(serve); + { + if (server_mirror_can_start(serve)) { + serve->mirror_super = mirror_super_create(serve->filename, + connect_to, + connect_from, + max_Bps, + action_at_finish, + client-> + mirror_state_mbox); + serve->mirror = serve->mirror_super->mirror; + server_prevent_mirror_start(serve); + } else { + if (serve->mirror_super) { + warn("Tried to start a second mirror run"); + write_socket("1: mirror already running"); + } else { + warn("Cannot start mirroring, shutting down"); + write_socket("1: shutting down"); + } } - if (parse_ip_to_sockaddr(&connect_to->generic, lines[0]) == 0) { - write_socket("1: bad IP address"); - return -1; - } + } + server_unlock_start_mirror(serve); - raw_port = atoi(lines[1]); - if (raw_port < 0 || raw_port > 65535) { - write_socket("1: bad IP port number"); - return -1; - } - connect_to->v4.sin_port = htobe16(raw_port); + /* Do this outside the lock to minimise the length of time the + * sighandler can block the serve thread + */ + if (serve->mirror_super) { + FATAL_IF(0 != pthread_create(&serve->mirror_super->thread, + NULL, + mirror_super_runner, + serve), + "Failed to create mirror thread"); - action_at_finish = ACTION_EXIT; - if (linesc > 2) { - if (strcmp("exit", lines[2]) == 0) { - action_at_finish = ACTION_EXIT; - } - else if (strcmp( "unlink", lines[2]) == 0 ) { - action_at_finish = ACTION_UNLINK; - } - else if (strcmp("nothing", lines[2]) == 0) { - action_at_finish = ACTION_NOTHING; - } - else { - write_socket("1: action must be 'exit' or 'nothing'"); - return -1; - } - } + debug("Control thread mirror super waiting"); + enum mirror_state state = control_client_mirror_wait(client); + debug("Control thread writing response"); + control_write_mirror_response(state, client->socket); + } - if (linesc > 3) { - connect_from = xmalloc( sizeof( union mysockaddr ) ); - if (parse_ip_to_sockaddr(&connect_from->generic, lines[3]) == 0) { - write_socket("1: bad bind address"); - return -1; - } - } + debug("Control thread going away."); - if (linesc > 4) { - errno = 0; - max_Bps = strtoull( lines[4], NULL, 10 ); - if ( errno == ERANGE ) { - write_socket( "1: max_bps out of range" ); - return -1; - } else if ( errno != 0 ) { - write_socket( "1: max_bps couldn't be parsed" ); - return -1; - } - } - - - if (linesc > 5) { - write_socket("1: unrecognised parameters to mirror"); - return -1; - } - - struct server * serve = flexnbd_server(flexnbd); - - server_lock_start_mirror( serve ); - { - if ( server_mirror_can_start( serve ) ) { - serve->mirror_super = mirror_super_create( - serve->filename, - connect_to, - connect_from, - max_Bps , - action_at_finish, - client->mirror_state_mbox ); - serve->mirror = serve->mirror_super->mirror; - server_prevent_mirror_start( serve ); - } else { - if ( serve->mirror_super ) { - warn( "Tried to start a second mirror run" ); - write_socket( "1: mirror already running" ); - } else { - warn( "Cannot start mirroring, shutting down" ); - write_socket( "1: shutting down" ); - } - } - - } - server_unlock_start_mirror( serve ); - - /* Do this outside the lock to minimise the length of time the - * sighandler can block the serve thread - */ - if ( serve->mirror_super ) { - FATAL_IF( 0 != pthread_create( - &serve->mirror_super->thread, - NULL, - mirror_super_runner, - serve - ), - "Failed to create mirror thread" - ); - - debug("Control thread mirror super waiting"); - enum mirror_state state = - control_client_mirror_wait( client ); - debug("Control thread writing response"); - control_write_mirror_response( state, client->socket ); - } - - debug( "Control thread going away." ); - - return 0; + return 0; } -int control_mirror_max_bps( struct control_client* client, int linesc, char** lines ) +int control_mirror_max_bps(struct control_client *client, int linesc, + char **lines) { - NULLCHECK( client ); - NULLCHECK( client->flexnbd ); + NULLCHECK(client); + NULLCHECK(client->flexnbd); - struct server* serve = flexnbd_server( client->flexnbd ); - uint64_t max_Bps; + struct server *serve = flexnbd_server(client->flexnbd); + uint64_t max_Bps; - if ( !serve->mirror_super ) { - write_socket( "1: Not currently mirroring" ); - return -1; - } + if (!serve->mirror_super) { + write_socket("1: Not currently mirroring"); + return -1; + } - if ( linesc != 1 ) { - write_socket( "1: Bad format" ); - return -1; - } + if (linesc != 1) { + write_socket("1: Bad format"); + return -1; + } - errno = 0; - max_Bps = strtoull( lines[0], NULL, 10 ); - if ( errno == ERANGE ) { - write_socket( "1: max_bps out of range" ); - return -1; - } else if ( errno != 0 ) { - write_socket( "1: max_bps couldn't be parsed" ); - return -1; - } + errno = 0; + max_Bps = strtoull(lines[0], NULL, 10); + if (errno == ERANGE) { + write_socket("1: max_bps out of range"); + return -1; + } else if (errno != 0) { + write_socket("1: max_bps couldn't be parsed"); + return -1; + } - serve->mirror->max_bytes_per_second = max_Bps; - write_socket( "0: updated" ); + serve->mirror->max_bytes_per_second = max_Bps; + write_socket("0: updated"); - return 0; + return 0; } #undef write_socket /** Command parser to alter access control list from socket input */ -int control_acl(struct control_client* client, int linesc, char** lines) +int control_acl(struct control_client *client, int linesc, char **lines) { - NULLCHECK( client ); - NULLCHECK( client->flexnbd ); - struct flexnbd * flexnbd = client->flexnbd; + NULLCHECK(client); + NULLCHECK(client->flexnbd); + struct flexnbd *flexnbd = client->flexnbd; - int default_deny = flexnbd_default_deny( flexnbd ); - struct acl * new_acl = acl_create( linesc, lines, default_deny ); + int default_deny = flexnbd_default_deny(flexnbd); + struct acl *new_acl = acl_create(linesc, lines, default_deny); - if (new_acl->len != linesc) { - warn("Bad ACL spec: %s", lines[new_acl->len] ); - write(client->socket, "1: bad spec: ", 13); - write(client->socket, lines[new_acl->len], - strlen(lines[new_acl->len])); - write(client->socket, "\n", 1); - acl_destroy( new_acl ); - } - else { - flexnbd_replace_acl( flexnbd, new_acl ); - info("ACL set"); - write( client->socket, "0: updated\n", 11); - } + if (new_acl->len != linesc) { + warn("Bad ACL spec: %s", lines[new_acl->len]); + write(client->socket, "1: bad spec: ", 13); + write(client->socket, lines[new_acl->len], + strlen(lines[new_acl->len])); + write(client->socket, "\n", 1); + acl_destroy(new_acl); + } else { + flexnbd_replace_acl(flexnbd, new_acl); + info("ACL set"); + write(client->socket, "0: updated\n", 11); + } - return 0; + return 0; } -int control_break( - struct control_client* client, - int linesc __attribute__ ((unused)), - char** lines __attribute__((unused)) - ) +int control_break(struct control_client *client, + int linesc __attribute__ ((unused)), + char **lines __attribute__ ((unused)) + ) { - NULLCHECK( client ); - NULLCHECK( client->flexnbd ); + NULLCHECK(client); + NULLCHECK(client->flexnbd); - int result = 0; - struct flexnbd* flexnbd = client->flexnbd; + int result = 0; + struct flexnbd *flexnbd = client->flexnbd; - struct server * serve = flexnbd_server( flexnbd ); + struct server *serve = flexnbd_server(flexnbd); - server_lock_start_mirror( serve ); - { - if ( server_is_mirroring( serve ) ) { + server_lock_start_mirror(serve); + { + if (server_is_mirroring(serve)) { - info( "Signaling to abandon mirror" ); - server_abandon_mirror( serve ); - debug( "Abandon signaled" ); + info("Signaling to abandon mirror"); + server_abandon_mirror(serve); + debug("Abandon signaled"); - if ( server_is_closed( serve ) ) { - info( "Mirror completed while canceling" ); - write( client->socket, - "1: mirror completed\n", 20 ); - } - else { - info( "Mirror successfully stopped." ); - write( client->socket, - "0: mirror stopped\n", 18 ); - result = 1; - } + if (server_is_closed(serve)) { + info("Mirror completed while canceling"); + write(client->socket, "1: mirror completed\n", 20); + } else { + info("Mirror successfully stopped."); + write(client->socket, "0: mirror stopped\n", 18); + result = 1; + } - } else { - warn( "Not mirroring." ); - write( client->socket, "1: not mirroring\n", 17 ); - } + } else { + warn("Not mirroring."); + write(client->socket, "1: not mirroring\n", 17); } - server_unlock_start_mirror( serve ); + } + server_unlock_start_mirror(serve); - return result; + return result; } /** FIXME: add some useful statistics */ -int control_status( - struct control_client* client, - int linesc __attribute__ ((unused)), - char** lines __attribute__((unused)) - ) +int control_status(struct control_client *client, + int linesc __attribute__ ((unused)), + char **lines __attribute__ ((unused)) + ) { - NULLCHECK( client ); - NULLCHECK( client->flexnbd ); - struct status * status = flexnbd_status_create( client->flexnbd ); + NULLCHECK(client); + NULLCHECK(client->flexnbd); + struct status *status = flexnbd_status_create(client->flexnbd); - write( client->socket, "0: ", 3 ); - status_write( status, client->socket ); - status_destroy( status ); + write(client->socket, "0: ", 3); + status_write(status, client->socket); + status_destroy(status); - return 0; + return 0; } -void control_client_cleanup(struct control_client* client, - int fatal __attribute__ ((unused)) ) +void control_client_cleanup(struct control_client *client, + int fatal __attribute__ ((unused))) { - if (client->socket) { close(client->socket); } + if (client->socket) { + close(client->socket); + } - /* This is wrongness */ - if ( server_acl_locked( client->flexnbd->serve ) ) { server_unlock_acl( client->flexnbd->serve ); } + /* This is wrongness */ + if (server_acl_locked(client->flexnbd->serve)) { + server_unlock_acl(client->flexnbd->serve); + } - control_client_destroy( client ); + control_client_destroy(client); } /** Master command parser for control socket connections, delegates quickly */ -void control_respond(struct control_client * client) +void control_respond(struct control_client *client) { - char **lines = NULL; + char **lines = NULL; - error_set_handler((cleanup_handler*) control_client_cleanup, client); + error_set_handler((cleanup_handler *) control_client_cleanup, client); - int i, linesc; - linesc = read_lines_until_blankline(client->socket, 256, &lines); + int i, linesc; + linesc = read_lines_until_blankline(client->socket, 256, &lines); - if (linesc < 1) - { - write(client->socket, "9: missing command\n", 19); - /* ignore failure */ + if (linesc < 1) { + write(client->socket, "9: missing command\n", 19); + /* ignore failure */ + } else if (strcmp(lines[0], "acl") == 0) { + info("acl command received"); + if (control_acl(client, linesc - 1, lines + 1) < 0) { + debug("acl command failed"); } - else if (strcmp(lines[0], "acl") == 0) { - info("acl command received" ); - if (control_acl(client, linesc-1, lines+1) < 0) { - debug("acl command failed"); - } + } else if (strcmp(lines[0], "mirror") == 0) { + info("mirror command received"); + if (control_mirror(client, linesc - 1, lines + 1) < 0) { + debug("mirror command failed"); } - else if (strcmp(lines[0], "mirror") == 0) { - info("mirror command received" ); - if (control_mirror(client, linesc-1, lines+1) < 0) { - debug("mirror command failed"); - } + } else if (strcmp(lines[0], "break") == 0) { + info("break command received"); + if (control_break(client, linesc - 1, lines + 1) < 0) { + debug("break command failed"); } - else if (strcmp(lines[0], "break") == 0) { - info( "break command received" ); - if ( control_break( client, linesc-1, lines+1) < 0) { - debug( "break command failed" ); - } + } else if (strcmp(lines[0], "status") == 0) { + info("status command received"); + if (control_status(client, linesc - 1, lines + 1) < 0) { + debug("status command failed"); } - else if (strcmp(lines[0], "status") == 0) { - info("status command received" ); - if (control_status(client, linesc-1, lines+1) < 0) { - debug("status command failed"); - } - } else if ( strcmp( lines[0], "mirror_max_bps" ) == 0 ) { - info( "mirror_max_bps command received" ); - if( control_mirror_max_bps( client, linesc-1, lines+1 ) < 0 ) { - debug( "mirror_max_bps command failed" ); - } - } - else { - write(client->socket, "10: unknown command\n", 23); + } else if (strcmp(lines[0], "mirror_max_bps") == 0) { + info("mirror_max_bps command received"); + if (control_mirror_max_bps(client, linesc - 1, lines + 1) < 0) { + debug("mirror_max_bps command failed"); } + } else { + write(client->socket, "10: unknown command\n", 23); + } - for (i=0; icontrol = - control_create( flexnbd, s_ctrl_sock ); - } - else { - flexnbd->control = NULL; - } + NULLCHECK(flexnbd); + if (s_ctrl_sock) { + flexnbd->control = control_create(flexnbd, s_ctrl_sock); + } else { + flexnbd->control = NULL; + } - flexnbd->signal_fd = flexnbd_build_signal_fd(); + flexnbd->signal_fd = flexnbd_build_signal_fd(); } -struct flexnbd * flexnbd_create_serving( - char* s_ip_address, - char* s_port, - char* s_file, - char* s_ctrl_sock, - int default_deny, - int acl_entries, - char** s_acl_entries, - int max_nbd_clients, - int use_killswitch) +struct flexnbd *flexnbd_create_serving(char *s_ip_address, + char *s_port, + char *s_file, + char *s_ctrl_sock, + int default_deny, + int acl_entries, + char **s_acl_entries, + int max_nbd_clients, + int use_killswitch) { - struct flexnbd * flexnbd = xmalloc( sizeof( struct flexnbd ) ); - flexnbd->serve = server_create( - flexnbd, - s_ip_address, - s_port, - s_file, - default_deny, - acl_entries, - s_acl_entries, - max_nbd_clients, - use_killswitch, - 1); - flexnbd_create_shared( flexnbd, s_ctrl_sock ); + struct flexnbd *flexnbd = xmalloc(sizeof(struct flexnbd)); + flexnbd->serve = server_create(flexnbd, + s_ip_address, + s_port, + s_file, + default_deny, + acl_entries, + s_acl_entries, + max_nbd_clients, use_killswitch, 1); + flexnbd_create_shared(flexnbd, s_ctrl_sock); - // Beats installing one handler per client instance - if ( use_killswitch ) { - struct sigaction act = { - .sa_sigaction = client_killswitch_hit, - .sa_flags = SA_RESTART | SA_SIGINFO - }; + // Beats installing one handler per client instance + if (use_killswitch) { + struct sigaction act = { + .sa_sigaction = client_killswitch_hit, + .sa_flags = SA_RESTART | SA_SIGINFO + }; - FATAL_UNLESS( - 0 == sigaction( CLIENT_KILLSWITCH_SIGNAL, &act, NULL ), - "Installing client killswitch signal failed" - ); - } + FATAL_UNLESS(0 == sigaction(CLIENT_KILLSWITCH_SIGNAL, &act, NULL), + "Installing client killswitch signal failed"); + } - return flexnbd; + return flexnbd; } -struct flexnbd * flexnbd_create_listening( - char* s_ip_address, - char* s_port, - char* s_file, - char* s_ctrl_sock, - int default_deny, - int acl_entries, - char** s_acl_entries ) +struct flexnbd *flexnbd_create_listening(char *s_ip_address, + char *s_port, + char *s_file, + char *s_ctrl_sock, + int default_deny, + int acl_entries, + char **s_acl_entries) { - struct flexnbd * flexnbd = xmalloc( sizeof( struct flexnbd ) ); - flexnbd->serve = server_create( - flexnbd, - s_ip_address, - s_port, - s_file, - default_deny, - acl_entries, - s_acl_entries, - 1, 0, 0); - flexnbd_create_shared( flexnbd, s_ctrl_sock ); + struct flexnbd *flexnbd = xmalloc(sizeof(struct flexnbd)); + flexnbd->serve = server_create(flexnbd, + s_ip_address, + s_port, + s_file, + default_deny, + acl_entries, s_acl_entries, 1, 0, 0); + flexnbd_create_shared(flexnbd, s_ctrl_sock); - // listen can't use killswitch, as mirror may pause on sending things - // for a very long time. + // listen can't use killswitch, as mirror may pause on sending things + // for a very long time. - return flexnbd; + return flexnbd; } -void flexnbd_spawn_control(struct flexnbd * flexnbd ) +void flexnbd_spawn_control(struct flexnbd *flexnbd) { - NULLCHECK( flexnbd ); - NULLCHECK( flexnbd->control ); + NULLCHECK(flexnbd); + NULLCHECK(flexnbd->control); - pthread_t * control_thread = &flexnbd->control->thread; + pthread_t *control_thread = &flexnbd->control->thread; - FATAL_UNLESS( 0 == pthread_create( - control_thread, - NULL, - control_runner, - flexnbd->control ), - "Couldn't create the control thread" ); + FATAL_UNLESS(0 == pthread_create(control_thread, + NULL, + control_runner, + flexnbd->control), + "Couldn't create the control thread"); } -void flexnbd_stop_control( struct flexnbd * flexnbd ) +void flexnbd_stop_control(struct flexnbd *flexnbd) { - NULLCHECK( flexnbd ); - NULLCHECK( flexnbd->control ); + NULLCHECK(flexnbd); + NULLCHECK(flexnbd->control); - control_signal_close( flexnbd->control ); - pthread_t tid = flexnbd->control->thread; - FATAL_UNLESS( 0 == pthread_join( tid, NULL ), - "Failed joining the control thread" ); - debug( "Control thread %p pthread_join returned", tid ); + control_signal_close(flexnbd->control); + pthread_t tid = flexnbd->control->thread; + FATAL_UNLESS(0 == pthread_join(tid, NULL), + "Failed joining the control thread"); + debug("Control thread %p pthread_join returned", tid); } -int flexnbd_signal_fd( struct flexnbd * flexnbd ) +int flexnbd_signal_fd(struct flexnbd *flexnbd) { - NULLCHECK( flexnbd ); - return flexnbd->signal_fd; + NULLCHECK(flexnbd); + return flexnbd->signal_fd; } -void flexnbd_destroy( struct flexnbd * flexnbd ) +void flexnbd_destroy(struct flexnbd *flexnbd) { - NULLCHECK( flexnbd ); - if ( flexnbd->control ) { - control_destroy( flexnbd->control ); - } + NULLCHECK(flexnbd); + if (flexnbd->control) { + control_destroy(flexnbd->control); + } - close( flexnbd->signal_fd ); - free( flexnbd ); + close(flexnbd->signal_fd); + free(flexnbd); } -struct server * flexnbd_server( struct flexnbd * flexnbd ) +struct server *flexnbd_server(struct flexnbd *flexnbd) { - NULLCHECK( flexnbd ); - return flexnbd->serve; + NULLCHECK(flexnbd); + return flexnbd->serve; } -void flexnbd_replace_acl( struct flexnbd * flexnbd, struct acl * acl ) +void flexnbd_replace_acl(struct flexnbd *flexnbd, struct acl *acl) { - NULLCHECK( flexnbd ); - server_replace_acl( flexnbd_server(flexnbd), acl ); + NULLCHECK(flexnbd); + server_replace_acl(flexnbd_server(flexnbd), acl); } -struct status * flexnbd_status_create( struct flexnbd * flexnbd ) +struct status *flexnbd_status_create(struct flexnbd *flexnbd) { - NULLCHECK( flexnbd ); - struct status * status; + NULLCHECK(flexnbd); + struct status *status; - status = status_create( flexnbd_server( flexnbd ) ); - return status; + status = status_create(flexnbd_server(flexnbd)); + return status; } -void flexnbd_set_server( struct flexnbd * flexnbd, struct server * serve ) +void flexnbd_set_server(struct flexnbd *flexnbd, struct server *serve) { - NULLCHECK( flexnbd ); - flexnbd->serve = serve; + NULLCHECK(flexnbd); + flexnbd->serve = serve; } /* Get the default_deny of the current server object. */ -int flexnbd_default_deny( struct flexnbd * flexnbd ) +int flexnbd_default_deny(struct flexnbd *flexnbd) { - NULLCHECK( flexnbd ); - return server_default_deny( flexnbd->serve ); + NULLCHECK(flexnbd); + return server_default_deny(flexnbd->serve); } -void make_writable( const char * filename ) +void make_writable(const char *filename) { - NULLCHECK( filename ); - FATAL_IF_NEGATIVE( chmod( filename, S_IWUSR ), - "Couldn't chmod %s: %s", - filename, - strerror( errno ) ); + NULLCHECK(filename); + FATAL_IF_NEGATIVE(chmod(filename, S_IWUSR), + "Couldn't chmod %s: %s", filename, strerror(errno)); } -int flexnbd_serve( struct flexnbd * flexnbd ) +int flexnbd_serve(struct flexnbd *flexnbd) { - NULLCHECK( flexnbd ); - int success; - struct self_pipe * open_signal = NULL; + NULLCHECK(flexnbd); + int success; + struct self_pipe *open_signal = NULL; - if ( flexnbd->control ){ - debug( "Spawning control thread" ); - flexnbd_spawn_control( flexnbd ); - open_signal = flexnbd->control->open_signal; - } + if (flexnbd->control) { + debug("Spawning control thread"); + flexnbd_spawn_control(flexnbd); + open_signal = flexnbd->control->open_signal; + } - success = do_serve( flexnbd->serve, open_signal ); - debug("do_serve success is %d", success ); + success = do_serve(flexnbd->serve, open_signal); + debug("do_serve success is %d", success); - if ( flexnbd->control ) { - debug( "Stopping control thread" ); - flexnbd_stop_control( flexnbd ); - debug("Control thread stopped"); - } + if (flexnbd->control) { + debug("Stopping control thread"); + flexnbd_stop_control(flexnbd); + debug("Control thread stopped"); + } - return success; + return success; } - diff --git a/src/server/flexnbd.h b/src/server/flexnbd.h index b5b3238..5377eb0 100644 --- a/src/server/flexnbd.h +++ b/src/server/flexnbd.h @@ -13,54 +13,51 @@ /* Carries the "globals". */ struct flexnbd { - /* Our serve pointer should never be dereferenced outside a - * flexnbd_switch_lock/unlock pair. - */ - struct server * serve; + /* Our serve pointer should never be dereferenced outside a + * flexnbd_switch_lock/unlock pair. + */ + struct server *serve; - /* We only have a control object if a control socket name was - * passed on the command line. - */ - struct control * control; + /* We only have a control object if a control socket name was + * passed on the command line. + */ + struct control *control; - /* File descriptor for a signalfd(2) signal stream. */ - int signal_fd; + /* File descriptor for a signalfd(2) signal stream. */ + int signal_fd; }; -struct flexnbd * flexnbd_create(void); -struct flexnbd * flexnbd_create_serving( - char* s_ip_address, - char* s_port, - char* s_file, - char* s_ctrl_sock, - int default_deny, - int acl_entries, - char** s_acl_entries, - int max_nbd_clients, - int use_killswitch); +struct flexnbd *flexnbd_create(void); +struct flexnbd *flexnbd_create_serving(char *s_ip_address, + char *s_port, + char *s_file, + char *s_ctrl_sock, + int default_deny, + int acl_entries, + char **s_acl_entries, + int max_nbd_clients, + int use_killswitch); -struct flexnbd * flexnbd_create_listening( - char* s_ip_address, - char* s_port, - char* s_file, - char* s_ctrl_sock, - int default_deny, - int acl_entries, - char** s_acl_entries ); +struct flexnbd *flexnbd_create_listening(char *s_ip_address, + char *s_port, + char *s_file, + char *s_ctrl_sock, + int default_deny, + int acl_entries, + char **s_acl_entries); -void flexnbd_destroy( struct flexnbd * ); +void flexnbd_destroy(struct flexnbd *); enum mirror_state; -enum mirror_state flexnbd_get_mirror_state( struct flexnbd * ); -int flexnbd_default_deny( struct flexnbd * ); -void flexnbd_set_server( struct flexnbd * flexnbd, struct server * serve ); -int flexnbd_signal_fd( struct flexnbd * flexnbd ); +enum mirror_state flexnbd_get_mirror_state(struct flexnbd *); +int flexnbd_default_deny(struct flexnbd *); +void flexnbd_set_server(struct flexnbd *flexnbd, struct server *serve); +int flexnbd_signal_fd(struct flexnbd *flexnbd); -int flexnbd_serve( struct flexnbd * flexnbd ); -int flexnbd_proxy( struct flexnbd * flexnbd ); -struct server * flexnbd_server( struct flexnbd * flexnbd ); -void flexnbd_replace_acl( struct flexnbd * flexnbd, struct acl * acl ); -struct status * flexnbd_status_create( struct flexnbd * flexnbd ); +int flexnbd_serve(struct flexnbd *flexnbd); +int flexnbd_proxy(struct flexnbd *flexnbd); +struct server *flexnbd_server(struct flexnbd *flexnbd); +void flexnbd_replace_acl(struct flexnbd *flexnbd, struct acl *acl); +struct status *flexnbd_status_create(struct flexnbd *flexnbd); #endif - diff --git a/src/server/flexthread.c b/src/server/flexthread.c index ef1d7df..4af8792 100644 --- a/src/server/flexthread.c +++ b/src/server/flexthread.c @@ -4,72 +4,70 @@ #include -struct flexthread_mutex * flexthread_mutex_create(void) +struct flexthread_mutex *flexthread_mutex_create(void) { - struct flexthread_mutex * ftm = - xmalloc( sizeof( struct flexthread_mutex ) ); + struct flexthread_mutex *ftm = + xmalloc(sizeof(struct flexthread_mutex)); - FATAL_UNLESS( 0 == pthread_mutex_init( &ftm->mutex, NULL ), - "Mutex initialisation failed" ); - return ftm; + FATAL_UNLESS(0 == pthread_mutex_init(&ftm->mutex, NULL), + "Mutex initialisation failed"); + return ftm; } -void flexthread_mutex_destroy( struct flexthread_mutex * ftm ) +void flexthread_mutex_destroy(struct flexthread_mutex *ftm) { - NULLCHECK( ftm ); + NULLCHECK(ftm); - if( flexthread_mutex_held( ftm ) ) { - flexthread_mutex_unlock( ftm ); - } - else if ( (pthread_t)NULL != ftm->holder ) { - /* This "should never happen": if we can try to destroy - * a mutex currently held by another thread, there's a - * logic bug somewhere. I know the test here is racy, - * but there's not a lot we can do about it at this - * point. - */ - fatal( "Attempted to destroy a flexthread_mutex"\ - " held by another thread!" ); - } + if (flexthread_mutex_held(ftm)) { + flexthread_mutex_unlock(ftm); + } else if ((pthread_t) NULL != ftm->holder) { + /* This "should never happen": if we can try to destroy + * a mutex currently held by another thread, there's a + * logic bug somewhere. I know the test here is racy, + * but there's not a lot we can do about it at this + * point. + */ + fatal("Attempted to destroy a flexthread_mutex" + " held by another thread!"); + } - FATAL_UNLESS( 0 == pthread_mutex_destroy( &ftm->mutex ), - "Mutex destroy failed" ); - free( ftm ); + FATAL_UNLESS(0 == pthread_mutex_destroy(&ftm->mutex), + "Mutex destroy failed"); + free(ftm); } -int flexthread_mutex_lock( struct flexthread_mutex * ftm ) +int flexthread_mutex_lock(struct flexthread_mutex *ftm) { - NULLCHECK( ftm ); + NULLCHECK(ftm); - int failure = pthread_mutex_lock( &ftm->mutex ); - if ( 0 == failure ) { - ftm->holder = pthread_self(); - } + int failure = pthread_mutex_lock(&ftm->mutex); + if (0 == failure) { + ftm->holder = pthread_self(); + } - return failure; + return failure; } -int flexthread_mutex_unlock( struct flexthread_mutex * ftm ) +int flexthread_mutex_unlock(struct flexthread_mutex *ftm) { - NULLCHECK( ftm ); + NULLCHECK(ftm); - pthread_t orig = ftm->holder; - ftm->holder = (pthread_t)NULL; - int failure = pthread_mutex_unlock( &ftm->mutex ); - if ( 0 != failure ) { - ftm->holder = orig; - } - return failure; + pthread_t orig = ftm->holder; + ftm->holder = (pthread_t) NULL; + int failure = pthread_mutex_unlock(&ftm->mutex); + if (0 != failure) { + ftm->holder = orig; + } + return failure; } -int flexthread_mutex_held( struct flexthread_mutex * ftm ) +int flexthread_mutex_held(struct flexthread_mutex *ftm) { - NULLCHECK( ftm ); - return pthread_self() == ftm->holder; + NULLCHECK(ftm); + return pthread_self() == ftm->holder; } - diff --git a/src/server/flexthread.h b/src/server/flexthread.h index 6a39097..c218766 100644 --- a/src/server/flexthread.h +++ b/src/server/flexthread.h @@ -15,15 +15,15 @@ */ struct flexthread_mutex { - pthread_mutex_t mutex; - pthread_t holder; + pthread_mutex_t mutex; + pthread_t holder; }; -struct flexthread_mutex * flexthread_mutex_create(void); -void flexthread_mutex_destroy( struct flexthread_mutex * ); +struct flexthread_mutex *flexthread_mutex_create(void); +void flexthread_mutex_destroy(struct flexthread_mutex *); -int flexthread_mutex_lock( struct flexthread_mutex * ); -int flexthread_mutex_unlock( struct flexthread_mutex * ); -int flexthread_mutex_held( struct flexthread_mutex * ); +int flexthread_mutex_lock(struct flexthread_mutex *); +int flexthread_mutex_unlock(struct flexthread_mutex *); +int flexthread_mutex_held(struct flexthread_mutex *); #endif diff --git a/src/server/mbox.c b/src/server/mbox.c index 3e96785..4c7298d 100644 --- a/src/server/mbox.c +++ b/src/server/mbox.c @@ -3,75 +3,75 @@ #include -struct mbox * mbox_create( void ) +struct mbox *mbox_create(void) { - struct mbox * mbox = xmalloc( sizeof( struct mbox ) ); - FATAL_UNLESS( 0 == pthread_cond_init( &mbox->filled_cond, NULL ), - "Failed to initialise a condition variable" ); - FATAL_UNLESS( 0 == pthread_cond_init( &mbox->emptied_cond, NULL ), - "Failed to initialise a condition variable" ); - FATAL_UNLESS( 0 == pthread_mutex_init( &mbox->mutex, NULL ), - "Failed to initialise a mutex" ); - return mbox; + struct mbox *mbox = xmalloc(sizeof(struct mbox)); + FATAL_UNLESS(0 == pthread_cond_init(&mbox->filled_cond, NULL), + "Failed to initialise a condition variable"); + FATAL_UNLESS(0 == pthread_cond_init(&mbox->emptied_cond, NULL), + "Failed to initialise a condition variable"); + FATAL_UNLESS(0 == pthread_mutex_init(&mbox->mutex, NULL), + "Failed to initialise a mutex"); + return mbox; } -void mbox_post( struct mbox * mbox, void * contents ) +void mbox_post(struct mbox *mbox, void *contents) { - pthread_mutex_lock( &mbox->mutex ); - { - if (mbox->full){ - pthread_cond_wait( &mbox->emptied_cond, &mbox->mutex ); - } - mbox->contents = contents; - mbox->full = 1; - while( 0 != pthread_cond_signal( &mbox->filled_cond ) ); + pthread_mutex_lock(&mbox->mutex); + { + if (mbox->full) { + pthread_cond_wait(&mbox->emptied_cond, &mbox->mutex); } - pthread_mutex_unlock( &mbox->mutex ); + mbox->contents = contents; + mbox->full = 1; + while (0 != pthread_cond_signal(&mbox->filled_cond)); + } + pthread_mutex_unlock(&mbox->mutex); } -void * mbox_contents( struct mbox * mbox ) +void *mbox_contents(struct mbox *mbox) { - return mbox->contents; + return mbox->contents; } -int mbox_is_full( struct mbox * mbox ) +int mbox_is_full(struct mbox *mbox) { - return mbox->full; + return mbox->full; } -void * mbox_receive( struct mbox * mbox ) +void *mbox_receive(struct mbox *mbox) { - NULLCHECK( mbox ); - void * result; + NULLCHECK(mbox); + void *result; - pthread_mutex_lock( &mbox->mutex ); - { - if ( !mbox->full ) { - pthread_cond_wait( &mbox->filled_cond, &mbox->mutex ); - } - mbox->full = 0; - result = mbox->contents; - mbox->contents = NULL; - - while( 0 != pthread_cond_signal( &mbox->emptied_cond)); + pthread_mutex_lock(&mbox->mutex); + { + if (!mbox->full) { + pthread_cond_wait(&mbox->filled_cond, &mbox->mutex); } - pthread_mutex_unlock( &mbox->mutex ); + mbox->full = 0; + result = mbox->contents; + mbox->contents = NULL; - return result; + while (0 != pthread_cond_signal(&mbox->emptied_cond)); + } + pthread_mutex_unlock(&mbox->mutex); + + return result; } -void mbox_destroy( struct mbox * mbox ) +void mbox_destroy(struct mbox *mbox) { - NULLCHECK( mbox ); + NULLCHECK(mbox); - while( 0 != pthread_cond_destroy( &mbox->emptied_cond ) ); - while( 0 != pthread_cond_destroy( &mbox->filled_cond ) ); + while (0 != pthread_cond_destroy(&mbox->emptied_cond)); + while (0 != pthread_cond_destroy(&mbox->filled_cond)); - while( 0 != pthread_mutex_destroy( &mbox->mutex ) ); + while (0 != pthread_mutex_destroy(&mbox->mutex)); - free( mbox ); + free(mbox); } diff --git a/src/server/mbox.h b/src/server/mbox.h index 3af54d8..87735f9 100644 --- a/src/server/mbox.h +++ b/src/server/mbox.h @@ -14,42 +14,42 @@ struct mbox { - void * contents; + void *contents; /** Marker to tell us if there's content in the box. * Keeping this separate allows us to use NULL for the contents. */ - int full; + int full; /** This gets signaled by mbox_post, and waited on by * mbox_receive */ - pthread_cond_t filled_cond; + pthread_cond_t filled_cond; /** This is signaled by mbox_receive, and waited on by mbox_post */ - pthread_cond_t emptied_cond; - pthread_mutex_t mutex; + pthread_cond_t emptied_cond; + pthread_mutex_t mutex; }; /* Create an mbox. */ -struct mbox * mbox_create(void); +struct mbox *mbox_create(void); /* Put something in the mbox, blocking if it's already full. * That something can be NULL if you want. */ -void mbox_post( struct mbox *, void *); +void mbox_post(struct mbox *, void *); /* See what's in the mbox. This isn't thread-safe. */ -void * mbox_contents( struct mbox *); +void *mbox_contents(struct mbox *); /* See if anything has been put into the mbox. This isn't thread-safe. * */ -int mbox_is_full( struct mbox *); +int mbox_is_full(struct mbox *); /* Get the contents from the mbox, blocking if there's nothing there. */ -void * mbox_receive( struct mbox *); +void *mbox_receive(struct mbox *); /* Free the mbox and destroy the associated pthread bits. */ -void mbox_destroy( struct mbox *); +void mbox_destroy(struct mbox *); #endif diff --git a/src/server/mirror.c b/src/server/mirror.c index bd25008..b1d917b 100644 --- a/src/server/mirror.c +++ b/src/server/mirror.c @@ -47,79 +47,78 @@ /* We use this to keep track of the socket request data we need to send */ struct xfer { - /* Store the bytes we need to send before the data, or receive back */ - union { - struct nbd_request_raw req_raw; - struct nbd_reply_raw rsp_raw; - } hdr; + /* Store the bytes we need to send before the data, or receive back */ + union { + struct nbd_request_raw req_raw; + struct nbd_reply_raw rsp_raw; + } hdr; - /* what in mirror->mapped we should write, and how much of it we've done */ - uint64_t from; - uint64_t len; - uint64_t written; + /* what in mirror->mapped we should write, and how much of it we've done */ + uint64_t from; + uint64_t len; + uint64_t written; - /* number of bytes of response read */ - uint64_t read; + /* number of bytes of response read */ + uint64_t read; }; struct mirror_ctrl { - struct server *serve; - struct mirror *mirror; + struct server *serve; + struct mirror *mirror; - /* libev stuff */ - struct ev_loop *ev_loop; - ev_timer begin_watcher; - ev_io read_watcher; - ev_io write_watcher; - ev_timer timeout_watcher; - ev_timer limit_watcher; - ev_io abandon_watcher; + /* libev stuff */ + struct ev_loop *ev_loop; + ev_timer begin_watcher; + ev_io read_watcher; + ev_io write_watcher; + ev_timer timeout_watcher; + ev_timer limit_watcher; + ev_io abandon_watcher; - /* We set this if the bitset stream is getting uncomfortably full, and unset - * once it's emptier */ - int clear_events; + /* We set this if the bitset stream is getting uncomfortably full, and unset + * once it's emptier */ + int clear_events; - /* This is set once all clients have been closed, to let the mirror know - * it's safe to finish once the queue is empty */ - int clients_closed; + /* This is set once all clients have been closed, to let the mirror know + * it's safe to finish once the queue is empty */ + int clients_closed; - /* Use this to keep track of what we're copying at any moment */ - struct xfer xfer; + /* Use this to keep track of what we're copying at any moment */ + struct xfer xfer; }; -struct mirror * mirror_alloc( - union mysockaddr * connect_to, - union mysockaddr * connect_from, - uint64_t max_Bps, - enum mirror_finish_action action_at_finish, - struct mbox * commit_signal) +struct mirror *mirror_alloc(union mysockaddr *connect_to, + union mysockaddr *connect_from, + uint64_t max_Bps, + enum mirror_finish_action action_at_finish, + struct mbox *commit_signal) { - struct mirror * mirror; + struct mirror *mirror; - mirror = xmalloc(sizeof(struct mirror)); - mirror->connect_to = connect_to; - mirror->connect_from = connect_from; - mirror->max_bytes_per_second = max_Bps; - mirror->action_at_finish = action_at_finish; - mirror->commit_signal = commit_signal; - mirror->commit_state = MS_UNKNOWN; - mirror->abandon_signal = self_pipe_create(); + mirror = xmalloc(sizeof(struct mirror)); + mirror->connect_to = connect_to; + mirror->connect_from = connect_from; + mirror->max_bytes_per_second = max_Bps; + mirror->action_at_finish = action_at_finish; + mirror->commit_signal = commit_signal; + mirror->commit_state = MS_UNKNOWN; + mirror->abandon_signal = self_pipe_create(); - if ( mirror->abandon_signal == NULL ) { - warn( "Couldn't create mirror abandon signal" ); - return NULL; - } + if (mirror->abandon_signal == NULL) { + warn("Couldn't create mirror abandon signal"); + return NULL; + } - return mirror; + return mirror; } -void mirror_set_state_f( struct mirror * mirror, enum mirror_state state ) +void mirror_set_state_f(struct mirror *mirror, enum mirror_state state) { - NULLCHECK( mirror ); - mirror->commit_state = state; + NULLCHECK(mirror); + mirror->commit_state = state; } #define mirror_set_state( mirror, state ) do{\ @@ -127,92 +126,83 @@ void mirror_set_state_f( struct mirror * mirror, enum mirror_state state ) mirror_set_state_f( mirror, state );\ } while(0) -enum mirror_state mirror_get_state( struct mirror * mirror ) +enum mirror_state mirror_get_state(struct mirror *mirror) { - NULLCHECK( mirror ); - return mirror->commit_state; + NULLCHECK(mirror); + return mirror->commit_state; } #define mirror_state_is( mirror, state ) mirror_get_state( mirror ) == state -void mirror_init( struct mirror * mirror, const char * filename ) +void mirror_init(struct mirror *mirror, const char *filename) { - int map_fd; - uint64_t size; + int map_fd; + uint64_t size; - NULLCHECK( mirror ); - NULLCHECK( filename ); + NULLCHECK(mirror); + NULLCHECK(filename); - FATAL_IF_NEGATIVE( - open_and_mmap( - filename, - &map_fd, - &size, - (void**) &mirror->mapped - ), - "Failed to open and mmap %s", - filename - ); + FATAL_IF_NEGATIVE(open_and_mmap(filename, + &map_fd, + &size, + (void **) &mirror->mapped), + "Failed to open and mmap %s", filename); - FATAL_IF_NEGATIVE( - madvise( mirror->mapped, size, MADV_SEQUENTIAL ), - SHOW_ERRNO( "Failed to madvise() %s", filename ) + FATAL_IF_NEGATIVE(madvise(mirror->mapped, size, MADV_SEQUENTIAL), + SHOW_ERRNO("Failed to madvise() %s", filename) ); } /* Call this before a mirror attempt. */ -void mirror_reset( struct mirror * mirror ) +void mirror_reset(struct mirror *mirror) { - NULLCHECK( mirror ); - mirror_set_state( mirror, MS_INIT ); + NULLCHECK(mirror); + mirror_set_state(mirror, MS_INIT); - mirror->all_dirty = 0; - mirror->migration_started = 0; - mirror->offset = 0; + mirror->all_dirty = 0; + mirror->migration_started = 0; + mirror->offset = 0; - return; + return; } -struct mirror * mirror_create( - const char * filename, - union mysockaddr * connect_to, - union mysockaddr * connect_from, - uint64_t max_Bps, - int action_at_finish, - struct mbox * commit_signal) +struct mirror *mirror_create(const char *filename, + union mysockaddr *connect_to, + union mysockaddr *connect_from, + uint64_t max_Bps, + int action_at_finish, + struct mbox *commit_signal) { - /* FIXME: shouldn't map_fd get closed? */ - struct mirror * mirror; + /* FIXME: shouldn't map_fd get closed? */ + struct mirror *mirror; - mirror = mirror_alloc( connect_to, - connect_from, - max_Bps, - action_at_finish, - commit_signal); + mirror = mirror_alloc(connect_to, + connect_from, + max_Bps, action_at_finish, commit_signal); - mirror_init( mirror, filename ); - mirror_reset( mirror ); + mirror_init(mirror, filename); + mirror_reset(mirror); - return mirror; + return mirror; } -void mirror_destroy( struct mirror *mirror ) +void mirror_destroy(struct mirror *mirror) { - NULLCHECK( mirror ); - self_pipe_destroy( mirror->abandon_signal ); - free(mirror->connect_to); - free(mirror->connect_from); - free(mirror); + NULLCHECK(mirror); + self_pipe_destroy(mirror->abandon_signal); + free(mirror->connect_to); + free(mirror->connect_from); + free(mirror); } /** The mirror code will split NBD writes, making them this long as a maximum */ -static const int mirror_longest_write = 8<<20; +static const int mirror_longest_write = 8 << 20; /* This must not be called if there's any chance of further I/O. Methods to * ensure this include: @@ -220,134 +210,134 @@ static const int mirror_longest_write = 8<<20; * - call server_forbid_new_clients() followed by a successful * server_close_clients() ; server_join_clients() */ -void mirror_on_exit( struct server * serve ) +void mirror_on_exit(struct server *serve) { - /* If we're still here, we can shut the server down. - * - * - */ - debug("serve_signal_close"); - serve_signal_close( serve ); + /* If we're still here, we can shut the server down. + * + * + */ + debug("serve_signal_close"); + serve_signal_close(serve); - /* We have to wait until the server is closed before unlocking - * IO. This is because the client threads check to see if the - * server is still open before reading or writing inside their - * own locks. If we don't wait for the close, there's no way to - * guarantee the server thread will win the race and we risk the - * clients seeing a "successful" write to a dead disc image. - */ - debug("serve_wait_for_close"); - serve_wait_for_close( serve ); + /* We have to wait until the server is closed before unlocking + * IO. This is because the client threads check to see if the + * server is still open before reading or writing inside their + * own locks. If we don't wait for the close, there's no way to + * guarantee the server thread will win the race and we risk the + * clients seeing a "successful" write to a dead disc image. + */ + debug("serve_wait_for_close"); + serve_wait_for_close(serve); - if ( ACTION_UNLINK == serve->mirror->action_at_finish ) { - debug("Unlinking %s", serve->filename ); - server_unlink( serve ); - } + if (ACTION_UNLINK == serve->mirror->action_at_finish) { + debug("Unlinking %s", serve->filename); + server_unlink(serve); + } - debug("Sending disconnect"); - socket_nbd_disconnect( serve->mirror->client ); - info("Mirror sent."); + debug("Sending disconnect"); + socket_nbd_disconnect(serve->mirror->client); + info("Mirror sent."); } -void mirror_cleanup( struct server * serve, - int fatal __attribute__((unused))) +void mirror_cleanup(struct server *serve, + int fatal __attribute__ ((unused))) { - NULLCHECK( serve ); - struct mirror * mirror = serve->mirror; - NULLCHECK( mirror ); - info( "Cleaning up mirror thread"); + NULLCHECK(serve); + struct mirror *mirror = serve->mirror; + NULLCHECK(mirror); + info("Cleaning up mirror thread"); - if ( mirror->mapped ) { - munmap( mirror->mapped, serve->size ); - } - mirror->mapped = NULL; + if (mirror->mapped) { + munmap(mirror->mapped, serve->size); + } + mirror->mapped = NULL; - if( mirror->client && mirror->client > 0 ){ - close( mirror->client ); - } - mirror->client = -1; + if (mirror->client && mirror->client > 0) { + close(mirror->client); + } + mirror->client = -1; } -int mirror_connect( struct mirror * mirror, uint64_t local_size ) +int mirror_connect(struct mirror *mirror, uint64_t local_size) { - struct sockaddr * connect_from = NULL; - int connected = 0; + struct sockaddr *connect_from = NULL; + int connected = 0; - if ( mirror->connect_from ) { - connect_from = &mirror->connect_from->generic; - } + if (mirror->connect_from) { + connect_from = &mirror->connect_from->generic; + } - NULLCHECK( mirror->connect_to ); + NULLCHECK(mirror->connect_to); - mirror->client = socket_connect(&mirror->connect_to->generic, connect_from); - if ( 0 < mirror->client ) { - fd_set fds; - struct timeval tv = { MS_HELLO_TIME_SECS, 0}; - FD_ZERO( &fds ); - FD_SET( mirror->client, &fds ); + mirror->client = + socket_connect(&mirror->connect_to->generic, connect_from); + if (0 < mirror->client) { + fd_set fds; + struct timeval tv = { MS_HELLO_TIME_SECS, 0 }; + FD_ZERO(&fds); + FD_SET(mirror->client, &fds); - FATAL_UNLESS( 0 <= select( FD_SETSIZE, &fds, NULL, NULL, &tv ), - "Select failed." ); + FATAL_UNLESS(0 <= select(FD_SETSIZE, &fds, NULL, NULL, &tv), + "Select failed."); - if( FD_ISSET( mirror->client, &fds ) ){ - uint64_t remote_size; - uint32_t remote_flags; - if ( socket_nbd_read_hello( mirror->client, &remote_size, &remote_flags ) ) { - if( remote_size == local_size ){ - connected = 1; - mirror_set_state( mirror, MS_GO ); - } - else { - warn("Remote size (%d) doesn't match local (%d)", - remote_size, local_size ); - mirror_set_state( mirror, MS_FAIL_SIZE_MISMATCH ); - } - } - else { - warn( "Mirror attempt rejected." ); - mirror_set_state( mirror, MS_FAIL_REJECTED ); - } + if (FD_ISSET(mirror->client, &fds)) { + uint64_t remote_size; + uint32_t remote_flags; + if (socket_nbd_read_hello + (mirror->client, &remote_size, &remote_flags)) { + if (remote_size == local_size) { + connected = 1; + mirror_set_state(mirror, MS_GO); + } else { + warn("Remote size (%d) doesn't match local (%d)", + remote_size, local_size); + mirror_set_state(mirror, MS_FAIL_SIZE_MISMATCH); } - else { - warn( "No NBD Hello received." ); - mirror_set_state( mirror, MS_FAIL_NO_HELLO ); - } - - if ( !connected ) { close( mirror->client ); } - } - else { - warn( "Mirror failed to connect."); - mirror_set_state( mirror, MS_FAIL_CONNECT ); + } else { + warn("Mirror attempt rejected."); + mirror_set_state(mirror, MS_FAIL_REJECTED); + } + } else { + warn("No NBD Hello received."); + mirror_set_state(mirror, MS_FAIL_NO_HELLO); } - return connected; + if (!connected) { + close(mirror->client); + } + } else { + warn("Mirror failed to connect."); + mirror_set_state(mirror, MS_FAIL_CONNECT); + } + + return connected; } -int mirror_should_quit( struct mirror * mirror ) +int mirror_should_quit(struct mirror *mirror) { - switch( mirror->action_at_finish ) { - case ACTION_EXIT: - case ACTION_UNLINK: - return 1; - default: - return 0; - } + switch (mirror->action_at_finish) { + case ACTION_EXIT: + case ACTION_UNLINK: + return 1; + default: + return 0; + } } /* Bandwidth limiting - we hang around if bps is too high, unless we need to * empty out the bitset stream a bit */ -int mirror_should_wait( struct mirror_ctrl *ctrl ) +int mirror_should_wait(struct mirror_ctrl *ctrl) { - int bps_over = server_mirror_bps( ctrl->serve ) > - ctrl->serve->mirror->max_bytes_per_second; + int bps_over = server_mirror_bps(ctrl->serve) > + ctrl->serve->mirror->max_bytes_per_second; - int stream_full = bitset_stream_size( ctrl->serve->allocation_map ) > - ( BITSET_STREAM_SIZE / 2 ); + int stream_full = bitset_stream_size(ctrl->serve->allocation_map) > + (BITSET_STREAM_SIZE / 2); - return bps_over && !stream_full; + return bps_over && !stream_full; } /* @@ -358,515 +348,530 @@ int mirror_should_wait( struct mirror_ctrl *ctrl ) * * iterates through the bitmap, finding a dirty run to form the basis of the * next transfer, then puts it together. */ -int mirror_setup_next_xfer( struct mirror_ctrl *ctrl ) +int mirror_setup_next_xfer(struct mirror_ctrl *ctrl) { - struct mirror* mirror = ctrl->mirror; - struct server* serve = ctrl->serve; - struct bitset_stream_entry e = { .event = BITSET_STREAM_UNSET }; - uint64_t current = mirror->offset, run = 0, size = serve->size; + struct mirror *mirror = ctrl->mirror; + struct server *serve = ctrl->serve; + struct bitset_stream_entry e = {.event = BITSET_STREAM_UNSET }; + uint64_t current = mirror->offset, run = 0, size = serve->size; - /* Technically, we'd be interested in UNSET events too, but they are never - * generated. TODO if that changes. - * - * We use ctrl->clear_events to start emptying the stream when it's half - * full, and stop when it's a quarter full. This stops a busy client from - * stalling a migration forever. FIXME: made-up numbers. - */ - if ( mirror->offset < serve->size && bitset_stream_size( serve->allocation_map ) > BITSET_STREAM_SIZE / 2 ) { - ctrl->clear_events = 1; + /* Technically, we'd be interested in UNSET events too, but they are never + * generated. TODO if that changes. + * + * We use ctrl->clear_events to start emptying the stream when it's half + * full, and stop when it's a quarter full. This stops a busy client from + * stalling a migration forever. FIXME: made-up numbers. + */ + if (mirror->offset < serve->size + && bitset_stream_size(serve->allocation_map) > + BITSET_STREAM_SIZE / 2) { + ctrl->clear_events = 1; + } + + + while ((mirror->offset == serve->size || ctrl->clear_events) + && e.event != BITSET_STREAM_SET) { + uint64_t events = bitset_stream_size(serve->allocation_map); + + if (events == 0) { + break; } + debug("Dequeueing event"); + bitset_stream_dequeue(ctrl->serve->allocation_map, &e); + debug("Dequeued event %i, %zu, %zu", e.event, e.from, e.len); - while ( ( mirror->offset == serve->size || ctrl->clear_events ) && e.event != BITSET_STREAM_SET ) { - uint64_t events = bitset_stream_size( serve->allocation_map ); - - if ( events == 0 ) { - break; - } - - debug("Dequeueing event"); - bitset_stream_dequeue( ctrl->serve->allocation_map, &e ); - debug("Dequeued event %i, %zu, %zu", e.event, e.from, e.len); - - if ( events < ( BITSET_STREAM_SIZE / 4 ) ) { - ctrl->clear_events = 0; - } + if (events < (BITSET_STREAM_SIZE / 4)) { + ctrl->clear_events = 0; } + } - if ( e.event == BITSET_STREAM_SET ) { - current = e.from; - run = e.len; - } else if ( current < serve->size ) { - current = mirror->offset; - run = mirror_longest_write; + if (e.event == BITSET_STREAM_SET) { + current = e.from; + run = e.len; + } else if (current < serve->size) { + current = mirror->offset; + run = mirror_longest_write; - /* Adjust final block if necessary */ - if ( current + run > serve->size ) { - run = size - current; - } - mirror->offset += run; - } else { - return 0; + /* Adjust final block if necessary */ + if (current + run > serve->size) { + run = size - current; } + mirror->offset += run; + } else { + return 0; + } - debug( "Next transfer: current=%"PRIu64", run=%"PRIu64, current, run ); - struct nbd_request req = { - .magic = REQUEST_MAGIC, - .type = REQUEST_WRITE, - .handle.b = ".MIRROR.", - .from = current, - .len = run - }; - nbd_h2r_request( &req, &ctrl->xfer.hdr.req_raw ); + debug("Next transfer: current=%" PRIu64 ", run=%" PRIu64, current, + run); + struct nbd_request req = { + .magic = REQUEST_MAGIC, + .type = REQUEST_WRITE, + .handle.b = ".MIRROR.", + .from = current, + .len = run + }; + nbd_h2r_request(&req, &ctrl->xfer.hdr.req_raw); - ctrl->xfer.from = current; - ctrl->xfer.len = run; + ctrl->xfer.from = current; + ctrl->xfer.len = run; - ctrl->xfer.written = 0; - ctrl->xfer.read = 0; + ctrl->xfer.written = 0; + ctrl->xfer.read = 0; - return 1; + return 1; } // ONLY CALL THIS AFTER CLOSING CLIENTS -void mirror_complete( struct server *serve ) +void mirror_complete(struct server *serve) { - /* FIXME: Pretty sure this is broken, if action != !QUIT. Just moving code - * around for now, can fix it later. Action is always quit in production */ - if ( mirror_should_quit( serve->mirror ) ) { - debug("exit!"); - /* FIXME: This depends on blocking I/O right now, so make sure we are */ - sock_set_nonblock( serve->mirror->client, 0 ); - mirror_on_exit( serve ); - info("Server closed, quitting after successful migration"); - } + /* FIXME: Pretty sure this is broken, if action != !QUIT. Just moving code + * around for now, can fix it later. Action is always quit in production */ + if (mirror_should_quit(serve->mirror)) { + debug("exit!"); + /* FIXME: This depends on blocking I/O right now, so make sure we are */ + sock_set_nonblock(serve->mirror->client, 0); + mirror_on_exit(serve); + info("Server closed, quitting after successful migration"); + } - mirror_set_state( serve->mirror, MS_DONE ); - return; + mirror_set_state(serve->mirror, MS_DONE); + return; } -static void mirror_write_cb( struct ev_loop *loop, ev_io *w, int revents ) +static void mirror_write_cb(struct ev_loop *loop, ev_io * w, int revents) { - struct mirror_ctrl* ctrl = (struct mirror_ctrl*) w->data; - NULLCHECK( ctrl ); + struct mirror_ctrl *ctrl = (struct mirror_ctrl *) w->data; + NULLCHECK(ctrl); - struct xfer *xfer = &ctrl->xfer; + struct xfer *xfer = &ctrl->xfer; - size_t to_write, hdr_size = sizeof( struct nbd_request_raw ); - char *data_loc; - ssize_t count; - - if ( !( revents & EV_WRITE ) ) { - warn( "No write event signalled in mirror write callback" ); - return; - } - - debug( "Mirror write callback invoked with events %d. fd: %i", revents, ctrl->mirror->client ); - - /* FIXME: We can end up corking multiple times in unusual circumstances; this - * is annoying, but harmless */ - if ( xfer->written == 0 ) { - sock_set_tcp_cork( ctrl->mirror->client, 1 ); - } - - if ( xfer->written < hdr_size ) { - data_loc = ( (char*) &xfer->hdr.req_raw ) + ctrl->xfer.written; - to_write = hdr_size - xfer->written; - } else { - data_loc = ctrl->mirror->mapped + xfer->from + ( xfer->written - hdr_size ); - to_write = xfer->len - ( ctrl->xfer.written - hdr_size ); - } - - // Actually write some bytes - if ( ( count = write( ctrl->mirror->client, data_loc, to_write ) ) < 0 ) { - if ( errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR ) { - warn( SHOW_ERRNO( "Couldn't write to listener" ) ); - ev_break( loop, EVBREAK_ONE ); - } - return; - } - debug( "Wrote %"PRIu64" bytes", count ); - debug( "to_write was %"PRIu64", xfer->written was %"PRIu64, to_write, xfer->written ); - - // We wrote some bytes, so reset the timer and keep track for the next pass - if ( count > 0 ) { - ctrl->xfer.written += count; - ev_timer_again( ctrl->ev_loop, &ctrl->timeout_watcher ); - } - - // All bytes written, so now we need to read the NBD reply back. - if ( ctrl->xfer.written == ctrl->xfer.len + hdr_size ) { - sock_set_tcp_cork( ctrl->mirror->client, 0 ) ; - ev_io_start( loop, &ctrl->read_watcher ); - ev_io_stop( loop, &ctrl->write_watcher ); - } + size_t to_write, hdr_size = sizeof(struct nbd_request_raw); + char *data_loc; + ssize_t count; + if (!(revents & EV_WRITE)) { + warn("No write event signalled in mirror write callback"); return; + } + + debug("Mirror write callback invoked with events %d. fd: %i", revents, + ctrl->mirror->client); + + /* FIXME: We can end up corking multiple times in unusual circumstances; this + * is annoying, but harmless */ + if (xfer->written == 0) { + sock_set_tcp_cork(ctrl->mirror->client, 1); + } + + if (xfer->written < hdr_size) { + data_loc = ((char *) &xfer->hdr.req_raw) + ctrl->xfer.written; + to_write = hdr_size - xfer->written; + } else { + data_loc = + ctrl->mirror->mapped + xfer->from + (xfer->written - hdr_size); + to_write = xfer->len - (ctrl->xfer.written - hdr_size); + } + + // Actually write some bytes + if ((count = write(ctrl->mirror->client, data_loc, to_write)) < 0) { + if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { + warn(SHOW_ERRNO("Couldn't write to listener")); + ev_break(loop, EVBREAK_ONE); + } + return; + } + debug("Wrote %" PRIu64 " bytes", count); + debug("to_write was %" PRIu64 ", xfer->written was %" PRIu64, to_write, + xfer->written); + + // We wrote some bytes, so reset the timer and keep track for the next pass + if (count > 0) { + ctrl->xfer.written += count; + ev_timer_again(ctrl->ev_loop, &ctrl->timeout_watcher); + } + // All bytes written, so now we need to read the NBD reply back. + if (ctrl->xfer.written == ctrl->xfer.len + hdr_size) { + sock_set_tcp_cork(ctrl->mirror->client, 0); + ev_io_start(loop, &ctrl->read_watcher); + ev_io_stop(loop, &ctrl->write_watcher); + } + + return; } -static void mirror_read_cb( struct ev_loop *loop, ev_io *w, int revents ) +static void mirror_read_cb(struct ev_loop *loop, ev_io * w, int revents) { - struct mirror_ctrl* ctrl = (struct mirror_ctrl*) w->data; - NULLCHECK( ctrl ); + struct mirror_ctrl *ctrl = (struct mirror_ctrl *) w->data; + NULLCHECK(ctrl); - struct mirror *m = ctrl->mirror; - NULLCHECK( m ); + struct mirror *m = ctrl->mirror; + NULLCHECK(m); - struct xfer *xfer = &ctrl->xfer; - NULLCHECK( xfer ); - - if ( !( revents & EV_READ ) ) { - warn( "No read event signalled in mirror read callback" ); - return; - } - - struct nbd_reply rsp; - ssize_t count; - uint64_t left = sizeof( struct nbd_reply_raw ) - xfer->read; - - debug( "Mirror read callback invoked with events %d. fd:%i", revents, m->client ); - - /* Start / continue reading the NBD response from the mirror. */ - if ( ( count = read( m->client, ((void*) &xfer->hdr.rsp_raw) + xfer->read, left ) ) < 0 ) { - if ( errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR ) { - warn( SHOW_ERRNO( "Couldn't read from listener" ) ); - ev_break( loop, EVBREAK_ONE ); - } - debug( SHOW_ERRNO( "Couldn't read from listener (non-scary)" ) ); - return; - } - - if ( count == 0 ) { - warn( "EOF reading response from server!" ); - ev_break( loop, EVBREAK_ONE ); - return; - } - - // We read some bytes, so reset the timer - ev_timer_again( ctrl->ev_loop, &ctrl->timeout_watcher ); - - debug( "Read %i bytes", count ); - debug( "left was %"PRIu64", xfer->read was %"PRIu64, left, xfer->read ); - xfer->read += count; - - if ( xfer->read < sizeof( struct nbd_reply_raw ) ) { - // Haven't read the whole response yet - return; - } - - nbd_r2h_reply( &xfer->hdr.rsp_raw, &rsp ); - - // validate reply, break event loop if bad - if ( rsp.magic != REPLY_MAGIC ) { - warn( "Bad reply magic from listener" ); - ev_break( loop, EVBREAK_ONE ); - return; - } - - if ( rsp.error != 0 ) { - warn( "Error returned from listener: %i", rsp.error ); - ev_break( loop, EVBREAK_ONE ); - return; - } - - if ( memcmp( ".MIRROR.", rsp.handle.b, 8 ) != 0 ) { - warn( "Bad handle returned from listener" ); - ev_break( loop, EVBREAK_ONE ); - return; - } - - /* transfer was completed, so now we need to either set up the next - * transfer of this pass, set up the first transfer of the next pass, or - * complete the migration */ - xfer->read = 0; - xfer->written = 0; - - /* We don't account for bytes written in this mode, to stop high-throughput - * discs getting stuck in "drain the event queue!" mode forever - */ - if ( !ctrl->clear_events ) { - m->all_dirty += xfer->len; - } - - - /* This next bit could take a little while, which is fine */ - ev_timer_stop( ctrl->ev_loop, &ctrl->timeout_watcher ); - - /* Set up the next transfer, which may be offset + mirror_longest_write - * or an event from the bitset stream. When offset hits serve->size, - * xfers will be constructed solely from the event stream. Once our estimate - * of time left reaches a sensible number (or the event stream empties), - * we stop new clients from connecting, disconnect existing ones, then - * continue emptying the bitstream. Once it's empty again, we're finished. - */ - int next_xfer = mirror_setup_next_xfer( ctrl ); - debug( "next_xfer: %d", next_xfer ); - - /* Regardless of time estimates, if there's no waiting transfer, we can start closing clients down. */ - if ( !ctrl->clients_closed && ( !next_xfer || server_mirror_eta( ctrl->serve ) < MS_CONVERGE_TIME_SECS ) ) { - info( "Closing clients to allow mirroring to converge" ); - server_forbid_new_clients( ctrl->serve ); - server_close_clients( ctrl->serve ); - server_join_clients( ctrl->serve ); - ctrl->clients_closed = 1; - - /* One more try - a new event may have been pushed since our last check */ - if ( !next_xfer ) { - next_xfer = mirror_setup_next_xfer( ctrl ); - } - } - - if ( ctrl->clients_closed && !next_xfer ) { - mirror_complete( ctrl->serve ); - ev_break( loop, EVBREAK_ONE ); - return; - } - - /* This is a guard Just In Case */ - ERROR_IF( !next_xfer, "Unknown problem - no next transfer to do!" ); - - ev_io_stop( loop, &ctrl->read_watcher ); - - /* FIXME: Should we ignore the bwlimit after server_close_clients has been called? */ - - if ( mirror_should_wait( ctrl ) ) { - /* We're over the bandwidth limit, so don't move onto the next transfer - * yet. Our limit_watcher will move us on once we're OK. timeout_watcher - * was disabled further up, so don't need to stop it here too */ - debug( "max_bps exceeded, waiting" ); - ev_timer_again( loop, &ctrl->limit_watcher ); - } else { - /* We're waiting for the socket to become writable again, so re-enable */ - ev_timer_again( loop, &ctrl->timeout_watcher ); - ev_io_start( loop, &ctrl->write_watcher ); - } + struct xfer *xfer = &ctrl->xfer; + NULLCHECK(xfer); + if (!(revents & EV_READ)) { + warn("No read event signalled in mirror read callback"); return; + } + + struct nbd_reply rsp; + ssize_t count; + uint64_t left = sizeof(struct nbd_reply_raw) - xfer->read; + + debug("Mirror read callback invoked with events %d. fd:%i", revents, + m->client); + + /* Start / continue reading the NBD response from the mirror. */ + if ((count = + read(m->client, ((void *) &xfer->hdr.rsp_raw) + xfer->read, + left)) < 0) { + if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { + warn(SHOW_ERRNO("Couldn't read from listener")); + ev_break(loop, EVBREAK_ONE); + } + debug(SHOW_ERRNO("Couldn't read from listener (non-scary)")); + return; + } + + if (count == 0) { + warn("EOF reading response from server!"); + ev_break(loop, EVBREAK_ONE); + return; + } + // We read some bytes, so reset the timer + ev_timer_again(ctrl->ev_loop, &ctrl->timeout_watcher); + + debug("Read %i bytes", count); + debug("left was %" PRIu64 ", xfer->read was %" PRIu64, left, + xfer->read); + xfer->read += count; + + if (xfer->read < sizeof(struct nbd_reply_raw)) { + // Haven't read the whole response yet + return; + } + + nbd_r2h_reply(&xfer->hdr.rsp_raw, &rsp); + + // validate reply, break event loop if bad + if (rsp.magic != REPLY_MAGIC) { + warn("Bad reply magic from listener"); + ev_break(loop, EVBREAK_ONE); + return; + } + + if (rsp.error != 0) { + warn("Error returned from listener: %i", rsp.error); + ev_break(loop, EVBREAK_ONE); + return; + } + + if (memcmp(".MIRROR.", rsp.handle.b, 8) != 0) { + warn("Bad handle returned from listener"); + ev_break(loop, EVBREAK_ONE); + return; + } + + /* transfer was completed, so now we need to either set up the next + * transfer of this pass, set up the first transfer of the next pass, or + * complete the migration */ + xfer->read = 0; + xfer->written = 0; + + /* We don't account for bytes written in this mode, to stop high-throughput + * discs getting stuck in "drain the event queue!" mode forever + */ + if (!ctrl->clear_events) { + m->all_dirty += xfer->len; + } + + + /* This next bit could take a little while, which is fine */ + ev_timer_stop(ctrl->ev_loop, &ctrl->timeout_watcher); + + /* Set up the next transfer, which may be offset + mirror_longest_write + * or an event from the bitset stream. When offset hits serve->size, + * xfers will be constructed solely from the event stream. Once our estimate + * of time left reaches a sensible number (or the event stream empties), + * we stop new clients from connecting, disconnect existing ones, then + * continue emptying the bitstream. Once it's empty again, we're finished. + */ + int next_xfer = mirror_setup_next_xfer(ctrl); + debug("next_xfer: %d", next_xfer); + + /* Regardless of time estimates, if there's no waiting transfer, we can start closing clients down. */ + if (!ctrl->clients_closed + && (!next_xfer + || server_mirror_eta(ctrl->serve) < MS_CONVERGE_TIME_SECS)) { + info("Closing clients to allow mirroring to converge"); + server_forbid_new_clients(ctrl->serve); + server_close_clients(ctrl->serve); + server_join_clients(ctrl->serve); + ctrl->clients_closed = 1; + + /* One more try - a new event may have been pushed since our last check */ + if (!next_xfer) { + next_xfer = mirror_setup_next_xfer(ctrl); + } + } + + if (ctrl->clients_closed && !next_xfer) { + mirror_complete(ctrl->serve); + ev_break(loop, EVBREAK_ONE); + return; + } + + /* This is a guard Just In Case */ + ERROR_IF(!next_xfer, "Unknown problem - no next transfer to do!"); + + ev_io_stop(loop, &ctrl->read_watcher); + + /* FIXME: Should we ignore the bwlimit after server_close_clients has been called? */ + + if (mirror_should_wait(ctrl)) { + /* We're over the bandwidth limit, so don't move onto the next transfer + * yet. Our limit_watcher will move us on once we're OK. timeout_watcher + * was disabled further up, so don't need to stop it here too */ + debug("max_bps exceeded, waiting"); + ev_timer_again(loop, &ctrl->limit_watcher); + } else { + /* We're waiting for the socket to become writable again, so re-enable */ + ev_timer_again(loop, &ctrl->timeout_watcher); + ev_io_start(loop, &ctrl->write_watcher); + } + + return; } -static void mirror_timeout_cb( struct ev_loop *loop, ev_timer *w __attribute__((unused)), int revents ) +static void mirror_timeout_cb(struct ev_loop *loop, ev_timer * w + __attribute__ ((unused)), int revents) { - if ( !(revents & EV_TIMER ) ) { - warn( "Mirror timeout called but no timer event signalled" ); - return; - } - - info( "Mirror timeout signalled" ); - ev_break( loop, EVBREAK_ONE ); + if (!(revents & EV_TIMER)) { + warn("Mirror timeout called but no timer event signalled"); return; + } + + info("Mirror timeout signalled"); + ev_break(loop, EVBREAK_ONE); + return; } -static void mirror_abandon_cb( struct ev_loop *loop, ev_io *w, int revents ) +static void mirror_abandon_cb(struct ev_loop *loop, ev_io * w, int revents) { - struct mirror_ctrl* ctrl = (struct mirror_ctrl*) w->data; - NULLCHECK( ctrl ); + struct mirror_ctrl *ctrl = (struct mirror_ctrl *) w->data; + NULLCHECK(ctrl); - if ( !(revents & EV_READ ) ) { - warn( "Mirror abandon called but no abandon event signalled" ); - return; - } - - debug( "Abandon message received" ); - mirror_set_state( ctrl->mirror, MS_ABANDONED ); - self_pipe_signal_clear( ctrl->mirror->abandon_signal ); - ev_break( loop, EVBREAK_ONE ); + if (!(revents & EV_READ)) { + warn("Mirror abandon called but no abandon event signalled"); return; + } + + debug("Abandon message received"); + mirror_set_state(ctrl->mirror, MS_ABANDONED); + self_pipe_signal_clear(ctrl->mirror->abandon_signal); + ev_break(loop, EVBREAK_ONE); + return; } -static void mirror_limit_cb( struct ev_loop *loop, ev_timer *w, int revents ) +static void mirror_limit_cb(struct ev_loop *loop, ev_timer * w, + int revents) { - struct mirror_ctrl* ctrl = (struct mirror_ctrl*) w->data; - NULLCHECK( ctrl ); - - if ( !(revents & EV_TIMER ) ) { - warn( "Mirror limit callback executed but no timer event signalled" ); - return; - } - - if ( mirror_should_wait( ctrl ) ) { - debug( "max_bps exceeded, waiting", ctrl->mirror->max_bytes_per_second ); - ev_timer_again( loop, w ); - } else { - /* We're below the limit, so do the next request */ - debug("max_bps not exceeded, performing next transfer" ); - ev_io_start( loop, &ctrl->write_watcher ); - ev_timer_stop( loop, &ctrl->limit_watcher ); - ev_timer_again( loop, &ctrl->timeout_watcher ); - } + struct mirror_ctrl *ctrl = (struct mirror_ctrl *) w->data; + NULLCHECK(ctrl); + if (!(revents & EV_TIMER)) { + warn("Mirror limit callback executed but no timer event signalled"); return; + } + + if (mirror_should_wait(ctrl)) { + debug("max_bps exceeded, waiting", + ctrl->mirror->max_bytes_per_second); + ev_timer_again(loop, w); + } else { + /* We're below the limit, so do the next request */ + debug("max_bps not exceeded, performing next transfer"); + ev_io_start(loop, &ctrl->write_watcher); + ev_timer_stop(loop, &ctrl->limit_watcher); + ev_timer_again(loop, &ctrl->timeout_watcher); + } + + return; } /* We use this to periodically check whether the allocation map has built, and * if it has, start migrating. If it's not finished, then enabling the bitset * stream does not go well for us. */ -static void mirror_begin_cb( struct ev_loop *loop, ev_timer *w, int revents ) +static void mirror_begin_cb(struct ev_loop *loop, ev_timer * w, + int revents) { - struct mirror_ctrl* ctrl = (struct mirror_ctrl*) w->data; - NULLCHECK( ctrl ); - - if ( !(revents & EV_TIMER ) ) { - warn( "Mirror limit callback executed but no timer event signalled" ); - return; - } - - if ( ctrl->serve->allocation_map_built || ctrl->serve->allocation_map_not_built ) { - info( "allocation map builder is finished, beginning migration" ); - ev_timer_stop( loop, w ); - /* Start by writing xfer 0 to the listener */ - ev_io_start( loop, &ctrl->write_watcher ); - /* We want to timeout during the first write as well as subsequent ones */ - ev_timer_again( loop, &ctrl->timeout_watcher ); - /* We're now interested in events */ - bitset_enable_stream( ctrl->serve->allocation_map ); - } else { - /* not done yet, so wait another second */ - ev_timer_again( loop, w ); - } + struct mirror_ctrl *ctrl = (struct mirror_ctrl *) w->data; + NULLCHECK(ctrl); + if (!(revents & EV_TIMER)) { + warn("Mirror limit callback executed but no timer event signalled"); return; + } + + if (ctrl->serve->allocation_map_built + || ctrl->serve->allocation_map_not_built) { + info("allocation map builder is finished, beginning migration"); + ev_timer_stop(loop, w); + /* Start by writing xfer 0 to the listener */ + ev_io_start(loop, &ctrl->write_watcher); + /* We want to timeout during the first write as well as subsequent ones */ + ev_timer_again(loop, &ctrl->timeout_watcher); + /* We're now interested in events */ + bitset_enable_stream(ctrl->serve->allocation_map); + } else { + /* not done yet, so wait another second */ + ev_timer_again(loop, w); + } + + return; } -void mirror_run( struct server *serve ) +void mirror_run(struct server *serve) { - NULLCHECK( serve ); - NULLCHECK( serve->mirror ); + NULLCHECK(serve); + NULLCHECK(serve->mirror); - struct mirror *m = serve->mirror; + struct mirror *m = serve->mirror; - m->migration_started = monotonic_time_ms(); - info("Starting mirror" ); - - /* mirror_setup_next_xfer won't be able to cope with this, so special-case - * it here. There can't be any writes going on, so don't bother locking - * anything. - * - */ - if ( serve->size == 0 ) { - info( "0-byte image special case" ); - mirror_complete( serve ); - return; - } - - struct mirror_ctrl ctrl; - memset( &ctrl, 0, sizeof( struct mirror_ctrl ) ); - - ctrl.serve = serve; - ctrl.mirror = m; - - ctrl.ev_loop = EV_DEFAULT; - - /* gcc warns with -Wstrict-aliasing on -O2. clang doesn't - * implement this warning. Seems to be the fault of ev.h */ - ev_init( &ctrl.begin_watcher, mirror_begin_cb ); - ctrl.begin_watcher.repeat = 1.0; // We check bps every second. seems sane. - ctrl.begin_watcher.data = (void*) &ctrl; - - ev_io_init( &ctrl.read_watcher, mirror_read_cb, m->client, EV_READ ); - ctrl.read_watcher.data = (void*) &ctrl; - - ev_io_init( &ctrl.write_watcher, mirror_write_cb, m->client, EV_WRITE ); - ctrl.write_watcher.data = (void*) &ctrl; - - ev_init( &ctrl.timeout_watcher, mirror_timeout_cb ); - - char * env_request_limit = getenv( "FLEXNBD_MS_REQUEST_LIMIT_SECS" ); - double timeout_limit = MS_REQUEST_LIMIT_SECS_F; - - if ( NULL != env_request_limit ) { - char *endptr = NULL; - errno = 0; - double limit = strtod( env_request_limit, &endptr ); - warn( SHOW_ERRNO( "Got %f from strtod", limit ) ); - - if ( errno == 0 ) { - timeout_limit = limit; - } - } - - ctrl.timeout_watcher.repeat = timeout_limit; - - ev_init( &ctrl.limit_watcher, mirror_limit_cb ); - ctrl.limit_watcher.repeat = 1.0; // We check bps every second. seems sane. - ctrl.limit_watcher.data = (void*) &ctrl; - - ev_init( &ctrl.abandon_watcher, mirror_abandon_cb ); - ev_io_set( &ctrl.abandon_watcher, m->abandon_signal->read_fd, EV_READ ); - ctrl.abandon_watcher.data = (void*) &ctrl; - ev_io_start( ctrl.ev_loop, &ctrl.abandon_watcher ); - - ERROR_UNLESS( - mirror_setup_next_xfer( &ctrl ), - "Couldn't find first transfer for mirror!" - ); - - - if ( serve->allocation_map_built ) { - /* Start by writing xfer 0 to the listener */ - ev_io_start( ctrl.ev_loop, &ctrl.write_watcher ); - /* We want to timeout during the first write as well as subsequent ones */ - ev_timer_again( ctrl.ev_loop, &ctrl.timeout_watcher ); - bitset_enable_stream( serve->allocation_map ); - } else { - debug( "Waiting for allocation map to be built" ); - ev_timer_again( ctrl.ev_loop, &ctrl.begin_watcher ); - } - - /* Everything up to here is blocking. We switch to non-blocking so we - * can handle rate-limiting and weird error conditions better. TODO: We - * should expand the event loop upwards so we can do the same there too */ - sock_set_nonblock( m->client, 1 ); - - info( "Entering event loop" ); - ev_run( ctrl.ev_loop, 0 ); - info( "Exited event loop" ); - - /* Parent code might expect a non-blocking socket */ - sock_set_nonblock( m->client, 0 ); - - - /* Errors in the event loop don't track I/O lock state or try to restore - * it to something sane - they just terminate the event loop with state != - * MS_DONE. We re-allow new clients here if necessary. - */ - if ( m->action_at_finish == ACTION_NOTHING || m->commit_state != MS_DONE ) { - server_allow_new_clients( serve ); - } - - /* Returning here says "mirroring complete" to the runner. The error - * call retries the migration from scratch. */ - - if ( m->commit_state != MS_DONE ) { - /* mirror_reset will be called before a retry, so keeping hold of events - * between now and our next mirroring attempt is not useful - */ - bitset_disable_stream( serve->allocation_map ); - error( "Event loop exited, but mirroring is not complete" ); - } + m->migration_started = monotonic_time_ms(); + info("Starting mirror"); + /* mirror_setup_next_xfer won't be able to cope with this, so special-case + * it here. There can't be any writes going on, so don't bother locking + * anything. + * + */ + if (serve->size == 0) { + info("0-byte image special case"); + mirror_complete(serve); return; + } + + struct mirror_ctrl ctrl; + memset(&ctrl, 0, sizeof(struct mirror_ctrl)); + + ctrl.serve = serve; + ctrl.mirror = m; + + ctrl.ev_loop = EV_DEFAULT; + + /* gcc warns with -Wstrict-aliasing on -O2. clang doesn't + * implement this warning. Seems to be the fault of ev.h */ + ev_init(&ctrl.begin_watcher, mirror_begin_cb); + ctrl.begin_watcher.repeat = 1.0; // We check bps every second. seems sane. + ctrl.begin_watcher.data = (void *) &ctrl; + + ev_io_init(&ctrl.read_watcher, mirror_read_cb, m->client, EV_READ); + ctrl.read_watcher.data = (void *) &ctrl; + + ev_io_init(&ctrl.write_watcher, mirror_write_cb, m->client, EV_WRITE); + ctrl.write_watcher.data = (void *) &ctrl; + + ev_init(&ctrl.timeout_watcher, mirror_timeout_cb); + + char *env_request_limit = getenv("FLEXNBD_MS_REQUEST_LIMIT_SECS"); + double timeout_limit = MS_REQUEST_LIMIT_SECS_F; + + if (NULL != env_request_limit) { + char *endptr = NULL; + errno = 0; + double limit = strtod(env_request_limit, &endptr); + warn(SHOW_ERRNO("Got %f from strtod", limit)); + + if (errno == 0) { + timeout_limit = limit; + } + } + + ctrl.timeout_watcher.repeat = timeout_limit; + + ev_init(&ctrl.limit_watcher, mirror_limit_cb); + ctrl.limit_watcher.repeat = 1.0; // We check bps every second. seems sane. + ctrl.limit_watcher.data = (void *) &ctrl; + + ev_init(&ctrl.abandon_watcher, mirror_abandon_cb); + ev_io_set(&ctrl.abandon_watcher, m->abandon_signal->read_fd, EV_READ); + ctrl.abandon_watcher.data = (void *) &ctrl; + ev_io_start(ctrl.ev_loop, &ctrl.abandon_watcher); + + ERROR_UNLESS(mirror_setup_next_xfer(&ctrl), + "Couldn't find first transfer for mirror!"); + + + if (serve->allocation_map_built) { + /* Start by writing xfer 0 to the listener */ + ev_io_start(ctrl.ev_loop, &ctrl.write_watcher); + /* We want to timeout during the first write as well as subsequent ones */ + ev_timer_again(ctrl.ev_loop, &ctrl.timeout_watcher); + bitset_enable_stream(serve->allocation_map); + } else { + debug("Waiting for allocation map to be built"); + ev_timer_again(ctrl.ev_loop, &ctrl.begin_watcher); + } + + /* Everything up to here is blocking. We switch to non-blocking so we + * can handle rate-limiting and weird error conditions better. TODO: We + * should expand the event loop upwards so we can do the same there too */ + sock_set_nonblock(m->client, 1); + + info("Entering event loop"); + ev_run(ctrl.ev_loop, 0); + info("Exited event loop"); + + /* Parent code might expect a non-blocking socket */ + sock_set_nonblock(m->client, 0); + + + /* Errors in the event loop don't track I/O lock state or try to restore + * it to something sane - they just terminate the event loop with state != + * MS_DONE. We re-allow new clients here if necessary. + */ + if (m->action_at_finish == ACTION_NOTHING + || m->commit_state != MS_DONE) { + server_allow_new_clients(serve); + } + + /* Returning here says "mirroring complete" to the runner. The error + * call retries the migration from scratch. */ + + if (m->commit_state != MS_DONE) { + /* mirror_reset will be called before a retry, so keeping hold of events + * between now and our next mirroring attempt is not useful + */ + bitset_disable_stream(serve->allocation_map); + error("Event loop exited, but mirroring is not complete"); + } + + return; } -void mbox_post_mirror_state( struct mbox * mbox, enum mirror_state st ) +void mbox_post_mirror_state(struct mbox *mbox, enum mirror_state st) { - NULLCHECK( mbox ); - enum mirror_state * contents = xmalloc( sizeof( enum mirror_state ) ); + NULLCHECK(mbox); + enum mirror_state *contents = xmalloc(sizeof(enum mirror_state)); - *contents = st; + *contents = st; - mbox_post( mbox, contents ); + mbox_post(mbox, contents); } -void mirror_signal_commit( struct mirror * mirror ) +void mirror_signal_commit(struct mirror *mirror) { - NULLCHECK( mirror ); + NULLCHECK(mirror); - mbox_post_mirror_state( mirror->commit_signal, - mirror_get_state( mirror ) ); + mbox_post_mirror_state(mirror->commit_signal, + mirror_get_state(mirror)); } /** Thread launched to drive mirror process @@ -876,105 +881,102 @@ void mirror_signal_commit( struct mirror * mirror ) * retries can be cleanly handled without a bespoke error handling * mechanism. * */ -void* mirror_runner(void* serve_params_uncast) +void *mirror_runner(void *serve_params_uncast) { - /* The supervisor thread relies on there not being any ERROR - * calls until after the mirror_signal_commit() call in this - * function. - * However, *after* that, we should call ERROR_* instead of - * FATAL_* wherever possible. + /* The supervisor thread relies on there not being any ERROR + * calls until after the mirror_signal_commit() call in this + * function. + * However, *after* that, we should call ERROR_* instead of + * FATAL_* wherever possible. + */ + struct server *serve = (struct server *) serve_params_uncast; + + NULLCHECK(serve); + NULLCHECK(serve->mirror); + struct mirror *mirror = serve->mirror; + + error_set_handler((cleanup_handler *) mirror_cleanup, serve); + + info("Connecting to mirror"); + + time_t start_time = time(NULL); + int connected = mirror_connect(mirror, serve->size); + mirror_signal_commit(mirror); + if (!connected) { + goto abandon_mirror; + } + + /* After this point, if we see a failure we need to disconnect + * and retry everything from mirror_set_state(_, MS_INIT), but + * *without* signaling the commit or abandoning the mirror. + * */ + + if ((time(NULL) - start_time) > MS_CONNECT_TIME_SECS) { + /* If we get here, then we managed to connect but the + * control thread feeding status back to the user will + * have gone away, leaving the user without meaningful + * feedback. In this instance, they have to assume a + * failure, so we can't afford to let the mirror happen. + * We have to set the state to avoid a race. */ - struct server *serve = (struct server*) serve_params_uncast; + mirror_set_state(mirror, MS_FAIL_CONNECT); + warn("Mirror connected, but too slowly"); + goto abandon_mirror; + } - NULLCHECK( serve ); - NULLCHECK( serve->mirror ); - struct mirror * mirror = serve->mirror; + mirror_run(serve); - error_set_handler( (cleanup_handler *) mirror_cleanup, serve ); + /* On success, this is unnecessary, and harmless ( mirror_cleanup does it + * for us ). But if we've failed and are going to retry on the next run, we + * must close this socket here to have any chance of it succeeding. + */ + if (!(mirror->client < 0)) { + sock_try_close(mirror->client); + mirror->client = -1; + } - info( "Connecting to mirror" ); - - time_t start_time = time(NULL); - int connected = mirror_connect( mirror, serve->size ); - mirror_signal_commit( mirror ); - if ( !connected ) { goto abandon_mirror; } - - /* After this point, if we see a failure we need to disconnect - * and retry everything from mirror_set_state(_, MS_INIT), but - * *without* signaling the commit or abandoning the mirror. - * */ - - if ( (time(NULL) - start_time) > MS_CONNECT_TIME_SECS ){ - /* If we get here, then we managed to connect but the - * control thread feeding status back to the user will - * have gone away, leaving the user without meaningful - * feedback. In this instance, they have to assume a - * failure, so we can't afford to let the mirror happen. - * We have to set the state to avoid a race. - */ - mirror_set_state( mirror, MS_FAIL_CONNECT ); - warn( "Mirror connected, but too slowly" ); - goto abandon_mirror; - } - - mirror_run( serve ); - - /* On success, this is unnecessary, and harmless ( mirror_cleanup does it - * for us ). But if we've failed and are going to retry on the next run, we - * must close this socket here to have any chance of it succeeding. - */ - if ( !(mirror->client < 0) ) { - sock_try_close( mirror->client ); - mirror->client = -1; - } - -abandon_mirror: - return NULL; + abandon_mirror: + return NULL; } -struct mirror_super * mirror_super_create( - const char * filename, - union mysockaddr * connect_to, - union mysockaddr * connect_from, - uint64_t max_Bps, - enum mirror_finish_action action_at_finish, - struct mbox * state_mbox) +struct mirror_super *mirror_super_create(const char *filename, + union mysockaddr *connect_to, + union mysockaddr *connect_from, + uint64_t max_Bps, + enum mirror_finish_action + action_at_finish, + struct mbox *state_mbox) { - struct mirror_super * super = xmalloc( sizeof( struct mirror_super) ); - super->mirror = mirror_create( - filename, - connect_to, - connect_from, - max_Bps, - action_at_finish, - mbox_create() ) ; - super->state_mbox = state_mbox; - return super; + struct mirror_super *super = xmalloc(sizeof(struct mirror_super)); + super->mirror = mirror_create(filename, + connect_to, + connect_from, + max_Bps, + action_at_finish, mbox_create()); + super->state_mbox = state_mbox; + return super; } /* Post the current state of the mirror into super->state_mbox.*/ -void mirror_super_signal_committed( - struct mirror_super * super , - enum mirror_state commit_state ) +void mirror_super_signal_committed(struct mirror_super *super, + enum mirror_state commit_state) { - NULLCHECK( super ); - NULLCHECK( super->state_mbox ); + NULLCHECK(super); + NULLCHECK(super->state_mbox); - mbox_post_mirror_state( - super->state_mbox, - commit_state ); + mbox_post_mirror_state(super->state_mbox, commit_state); } -void mirror_super_destroy( struct mirror_super * super ) +void mirror_super_destroy(struct mirror_super *super) { - NULLCHECK( super ); + NULLCHECK(super); - mbox_destroy( super->mirror->commit_signal ); - mirror_destroy( super->mirror ); - free( super ); + mbox_destroy(super->mirror->commit_signal); + mirror_destroy(super->mirror); + free(super); } @@ -983,90 +985,87 @@ void mirror_super_destroy( struct mirror_super * super ) * The mirror and mirror_super objects are never freed, and the * mirror_super_runner thread is never joined. */ -void * mirror_super_runner( void * serve_uncast ) +void *mirror_super_runner(void *serve_uncast) { - struct server * serve = (struct server *) serve_uncast; - NULLCHECK( serve ); - NULLCHECK( serve->mirror ); - NULLCHECK( serve->mirror_super ); + struct server *serve = (struct server *) serve_uncast; + NULLCHECK(serve); + NULLCHECK(serve->mirror); + NULLCHECK(serve->mirror_super); - int first_pass = 1; - int should_retry = 0; - int success = 0, abandoned = 0; + int first_pass = 1; + int should_retry = 0; + int success = 0, abandoned = 0; - struct mirror * mirror = serve->mirror; - struct mirror_super * super = serve->mirror_super; + struct mirror *mirror = serve->mirror; + struct mirror_super *super = serve->mirror_super; - do { - FATAL_IF( 0 != pthread_create( - &mirror->thread, - NULL, - mirror_runner, - serve), - "Failed to create mirror thread"); + do { + FATAL_IF(0 != pthread_create(&mirror->thread, + NULL, + mirror_runner, + serve), + "Failed to create mirror thread"); - debug("Supervisor waiting for commit signal"); - enum mirror_state * commit_state = - mbox_receive( mirror->commit_signal ); + debug("Supervisor waiting for commit signal"); + enum mirror_state *commit_state = + mbox_receive(mirror->commit_signal); - debug( "Supervisor got commit signal" ); - if ( first_pass ) { - /* Only retry if the connection attempt was successful. Otherwise - * the user will see an error reported while we're still trying to - * retry behind the scenes. This may race with migration completing - * but since we "shouldn't retry" in that case either, that's fine - */ - should_retry = *commit_state == MS_GO; - - /* Only send this signal the first time */ - mirror_super_signal_committed( - super, - *commit_state); - debug("Mirror supervisor committed"); - } - /* We only care about the value of the commit signal on - * the first pass, so this is ok - */ - free( commit_state ); - - debug("Supervisor waiting for mirror thread" ); - pthread_join( mirror->thread, NULL ); - - /* If we can't connect to the remote end, the watcher for the abandon - * signal never gets installed at the moment, which is why we also check - * it here. */ - abandoned = - mirror_get_state( mirror ) == MS_ABANDONED || - self_pipe_signal_clear( mirror->abandon_signal ); - - success = MS_DONE == mirror_get_state( mirror ); - - - if( success ){ - info( "Mirror supervisor success, exiting" ); - } else if ( abandoned ) { - info( "Mirror abandoned" ); - should_retry = 0; - } else if ( should_retry ) { - info( "Mirror failed, retrying" ); - } else { - info( "Mirror failed before commit, giving up" ); - } - - first_pass = 0; - - if ( should_retry ) { - /* We don't want to hammer the destination too - * hard, so if this is a retry, insert a delay. */ - sleep( MS_RETRY_DELAY_SECS ); - - /* We also have to reset the bitmap to be sure - * we transfer everything */ - mirror_reset( mirror ); - } + debug("Supervisor got commit signal"); + if (first_pass) { + /* Only retry if the connection attempt was successful. Otherwise + * the user will see an error reported while we're still trying to + * retry behind the scenes. This may race with migration completing + * but since we "shouldn't retry" in that case either, that's fine + */ + should_retry = *commit_state == MS_GO; + /* Only send this signal the first time */ + mirror_super_signal_committed(super, *commit_state); + debug("Mirror supervisor committed"); } - while ( should_retry && !success ); + /* We only care about the value of the commit signal on + * the first pass, so this is ok + */ + free(commit_state); - return NULL; + debug("Supervisor waiting for mirror thread"); + pthread_join(mirror->thread, NULL); + + /* If we can't connect to the remote end, the watcher for the abandon + * signal never gets installed at the moment, which is why we also check + * it here. */ + abandoned = + mirror_get_state(mirror) == MS_ABANDONED || + self_pipe_signal_clear(mirror->abandon_signal); + + success = MS_DONE == mirror_get_state(mirror); + + + if (success) { + info("Mirror supervisor success, exiting"); + } else if (abandoned) { + info("Mirror abandoned"); + should_retry = 0; + } else if (should_retry) { + info("Mirror failed, retrying"); + } else { + info("Mirror failed before commit, giving up"); + } + + first_pass = 0; + + if (should_retry) { + /* We don't want to hammer the destination too + * hard, so if this is a retry, insert a delay. */ + sleep(MS_RETRY_DELAY_SECS); + + /* We also have to reset the bitmap to be sure + * we transfer everything */ + mirror_reset(mirror); + } + + } + while (should_retry && !success); + + return NULL; } diff --git a/src/server/mirror.h b/src/server/mirror.h index d390fdf..7601bee 100644 --- a/src/server/mirror.h +++ b/src/server/mirror.h @@ -58,65 +58,65 @@ enum mirror_state; #define MS_REQUEST_LIMIT_SECS_F 60.0 enum mirror_finish_action { - ACTION_EXIT, - ACTION_UNLINK, - ACTION_NOTHING + ACTION_EXIT, + ACTION_UNLINK, + ACTION_NOTHING }; enum mirror_state { - MS_UNKNOWN, - MS_INIT, - MS_GO, - MS_ABANDONED, - MS_DONE, - MS_FAIL_CONNECT, - MS_FAIL_REJECTED, - MS_FAIL_NO_HELLO, - MS_FAIL_SIZE_MISMATCH + MS_UNKNOWN, + MS_INIT, + MS_GO, + MS_ABANDONED, + MS_DONE, + MS_FAIL_CONNECT, + MS_FAIL_REJECTED, + MS_FAIL_NO_HELLO, + MS_FAIL_SIZE_MISMATCH }; struct mirror { - pthread_t thread; + pthread_t thread; - /* Signal to this then join the thread if you want to abandon mirroring */ - struct self_pipe * abandon_signal; + /* Signal to this then join the thread if you want to abandon mirroring */ + struct self_pipe *abandon_signal; - union mysockaddr * connect_to; - union mysockaddr * connect_from; - int client; - const char * filename; + union mysockaddr *connect_to; + union mysockaddr *connect_from; + int client; + const char *filename; - /* Limiter, used to restrict migration speed Only dirty bytes (those going - * over the network) are considered */ - uint64_t max_bytes_per_second; + /* Limiter, used to restrict migration speed Only dirty bytes (those going + * over the network) are considered */ + uint64_t max_bytes_per_second; - enum mirror_finish_action action_at_finish; + enum mirror_finish_action action_at_finish; - char *mapped; + char *mapped; - /* We need to send every byte at least once; we do so by */ - uint64_t offset; + /* We need to send every byte at least once; we do so by */ + uint64_t offset; - enum mirror_state commit_state; + enum mirror_state commit_state; - /* commit_signal is sent immediately after attempting to connect - * and checking the remote size, whether successful or not. - */ - struct mbox * commit_signal; + /* commit_signal is sent immediately after attempting to connect + * and checking the remote size, whether successful or not. + */ + struct mbox *commit_signal; - /* The time (from monotonic_time_ms()) the migration was started. Can be - * used to calculate bps, etc. */ - uint64_t migration_started; + /* The time (from monotonic_time_ms()) the migration was started. Can be + * used to calculate bps, etc. */ + uint64_t migration_started; - /* Running count of all bytes we've transferred */ - uint64_t all_dirty; + /* Running count of all bytes we've transferred */ + uint64_t all_dirty; }; struct mirror_super { - struct mirror * mirror; - pthread_t thread; - struct mbox * state_mbox; + struct mirror *mirror; + pthread_t thread; + struct mbox *state_mbox; }; @@ -127,15 +127,13 @@ struct mirror_super { struct server; struct flexnbd; -struct mirror_super * mirror_super_create( - const char * filename, - union mysockaddr * connect_to, - union mysockaddr * connect_from, - uint64_t max_Bps, - enum mirror_finish_action action_at_finish, - struct mbox * state_mbox - ); -void * mirror_super_runner( void * serve_uncast ); +struct mirror_super *mirror_super_create(const char *filename, + union mysockaddr *connect_to, + union mysockaddr *connect_from, + uint64_t max_Bps, + enum mirror_finish_action + action_at_finish, + struct mbox *state_mbox); +void *mirror_super_runner(void *serve_uncast); #endif - diff --git a/src/server/mode.c b/src/server/mode.c index 47dbffc..6082e04 100644 --- a/src/server/mode.c +++ b/src/server/mode.c @@ -8,526 +8,517 @@ static struct option serve_options[] = { - GETOPT_HELP, - GETOPT_ADDR, - GETOPT_PORT, - GETOPT_FILE, - GETOPT_SOCK, - GETOPT_DENY, - GETOPT_QUIET, - GETOPT_KILLSWITCH, - GETOPT_VERBOSE, - {0} + GETOPT_HELP, + GETOPT_ADDR, + GETOPT_PORT, + GETOPT_FILE, + GETOPT_SOCK, + GETOPT_DENY, + GETOPT_QUIET, + GETOPT_KILLSWITCH, + GETOPT_VERBOSE, + {0} }; + static char serve_short_options[] = "hl:p:f:s:dk" SOPT_QUIET SOPT_VERBOSE; static char serve_help_text[] = - "Usage: flexnbd " CMD_SERVE " [*]\n\n" - "Serve FILE from ADDR:PORT, with an optional control socket at SOCK.\n\n" - HELP_LINE - "\t--" OPT_ADDR ",-l \tThe address to serve on.\n" - "\t--" OPT_PORT ",-p \tThe port to serve on.\n" - "\t--" OPT_FILE ",-f \tThe file to serve.\n" - "\t--" OPT_DENY ",-d\tDeny connections by default unless in ACL.\n" - "\t--" OPT_KILLSWITCH",-k \tKill the server if a request takes 120 seconds.\n" - SOCK_LINE - VERBOSE_LINE - QUIET_LINE; + "Usage: flexnbd " CMD_SERVE " [*]\n\n" + "Serve FILE from ADDR:PORT, with an optional control socket at SOCK.\n\n" + HELP_LINE + "\t--" OPT_ADDR ",-l \tThe address to serve on.\n" + "\t--" OPT_PORT ",-p \tThe port to serve on.\n" + "\t--" OPT_FILE ",-f \tThe file to serve.\n" + "\t--" OPT_DENY ",-d\tDeny connections by default unless in ACL.\n" + "\t--" OPT_KILLSWITCH + ",-k \tKill the server if a request takes 120 seconds.\n" SOCK_LINE + VERBOSE_LINE QUIET_LINE; static struct option listen_options[] = { - GETOPT_HELP, - GETOPT_ADDR, - GETOPT_PORT, - GETOPT_FILE, - GETOPT_SOCK, - GETOPT_DENY, - GETOPT_QUIET, - GETOPT_VERBOSE, - {0} + GETOPT_HELP, + GETOPT_ADDR, + GETOPT_PORT, + GETOPT_FILE, + GETOPT_SOCK, + GETOPT_DENY, + GETOPT_QUIET, + GETOPT_VERBOSE, + {0} }; + static char listen_short_options[] = "hl:p:f:s:d" SOPT_QUIET SOPT_VERBOSE; static char listen_help_text[] = - "Usage: flexnbd " CMD_LISTEN " [*]\n\n" - "Listen for an incoming migration on ADDR:PORT." - HELP_LINE - "\t--" OPT_ADDR ",-l \tThe address to listen on.\n" - "\t--" OPT_PORT ",-p \tThe port to listen on.\n" - "\t--" OPT_FILE ",-f \tThe file to serve.\n" - "\t--" OPT_DENY ",-d\tDeny connections by default unless in ACL.\n" - SOCK_LINE - VERBOSE_LINE - QUIET_LINE; + "Usage: flexnbd " CMD_LISTEN " [*]\n\n" + "Listen for an incoming migration on ADDR:PORT." + HELP_LINE + "\t--" OPT_ADDR ",-l \tThe address to listen on.\n" + "\t--" OPT_PORT ",-p \tThe port to listen on.\n" + "\t--" OPT_FILE ",-f \tThe file to serve.\n" + "\t--" OPT_DENY ",-d\tDeny connections by default unless in ACL.\n" + SOCK_LINE VERBOSE_LINE QUIET_LINE; static struct option read_options[] = { - GETOPT_HELP, - GETOPT_ADDR, - GETOPT_PORT, - GETOPT_FROM, - GETOPT_SIZE, - GETOPT_BIND, - GETOPT_QUIET, - GETOPT_VERBOSE, - {0} + GETOPT_HELP, + GETOPT_ADDR, + GETOPT_PORT, + GETOPT_FROM, + GETOPT_SIZE, + GETOPT_BIND, + GETOPT_QUIET, + GETOPT_VERBOSE, + {0} }; + static char read_short_options[] = "hl:p:F:S:b:" SOPT_QUIET SOPT_VERBOSE; static char read_help_text[] = - "Usage: flexnbd " CMD_READ " \n\n" - "Read SIZE bytes from a server at ADDR:PORT to stdout, starting at OFFSET.\n\n" - HELP_LINE - "\t--" OPT_ADDR ",-l \tThe address to read from.\n" - "\t--" OPT_PORT ",-p \tThe port to read from.\n" - "\t--" OPT_FROM ",-F \tByte offset to read from.\n" - "\t--" OPT_SIZE ",-S \tBytes to read.\n" - BIND_LINE - VERBOSE_LINE - QUIET_LINE; + "Usage: flexnbd " CMD_READ " \n\n" + "Read SIZE bytes from a server at ADDR:PORT to stdout, starting at OFFSET.\n\n" + HELP_LINE + "\t--" OPT_ADDR ",-l \tThe address to read from.\n" + "\t--" OPT_PORT ",-p \tThe port to read from.\n" + "\t--" OPT_FROM ",-F \tByte offset to read from.\n" + "\t--" OPT_SIZE ",-S \tBytes to read.\n" + BIND_LINE VERBOSE_LINE QUIET_LINE; static struct option *write_options = read_options; static char *write_short_options = read_short_options; static char write_help_text[] = - "Usage: flexnbd " CMD_WRITE" \n\n" - "Write SIZE bytes from stdin to a server at ADDR:PORT, starting at OFFSET.\n\n" - HELP_LINE - "\t--" OPT_ADDR ",-l \tThe address to write to.\n" - "\t--" OPT_PORT ",-p \tThe port to write to.\n" - "\t--" OPT_FROM ",-F \tByte offset to write from.\n" - "\t--" OPT_SIZE ",-S \tBytes to write.\n" - BIND_LINE - VERBOSE_LINE - QUIET_LINE; + "Usage: flexnbd " CMD_WRITE " \n\n" + "Write SIZE bytes from stdin to a server at ADDR:PORT, starting at OFFSET.\n\n" + HELP_LINE + "\t--" OPT_ADDR ",-l \tThe address to write to.\n" + "\t--" OPT_PORT ",-p \tThe port to write to.\n" + "\t--" OPT_FROM ",-F \tByte offset to write from.\n" + "\t--" OPT_SIZE ",-S \tBytes to write.\n" + BIND_LINE VERBOSE_LINE QUIET_LINE; static struct option acl_options[] = { - GETOPT_HELP, - GETOPT_SOCK, - GETOPT_QUIET, - GETOPT_VERBOSE, - {0} + GETOPT_HELP, + GETOPT_SOCK, + GETOPT_QUIET, + GETOPT_VERBOSE, + {0} }; + static char acl_short_options[] = "hs:" SOPT_QUIET SOPT_VERBOSE; static char acl_help_text[] = - "Usage: flexnbd " CMD_ACL " [+]\n\n" - "Set the access control list for a server with control socket SOCK.\n\n" - HELP_LINE - SOCK_LINE - VERBOSE_LINE - QUIET_LINE; + "Usage: flexnbd " CMD_ACL " [+]\n\n" + "Set the access control list for a server with control socket SOCK.\n\n" + HELP_LINE SOCK_LINE VERBOSE_LINE QUIET_LINE; static struct option mirror_speed_options[] = { - GETOPT_HELP, - GETOPT_SOCK, - GETOPT_MAX_SPEED, - GETOPT_QUIET, - GETOPT_VERBOSE, - {0} + GETOPT_HELP, + GETOPT_SOCK, + GETOPT_MAX_SPEED, + GETOPT_QUIET, + GETOPT_VERBOSE, + {0} }; + static char mirror_speed_short_options[] = "hs:m:" SOPT_QUIET SOPT_VERBOSE; static char mirror_speed_help_text[] = - "Usage: flexnbd " CMD_MIRROR_SPEED " \n\n" - "Set the maximum speed of a migration from a mirring server listening on SOCK.\n\n" - HELP_LINE - SOCK_LINE - MAX_SPEED_LINE - VERBOSE_LINE - QUIET_LINE; + "Usage: flexnbd " CMD_MIRROR_SPEED " \n\n" + "Set the maximum speed of a migration from a mirring server listening on SOCK.\n\n" + HELP_LINE SOCK_LINE MAX_SPEED_LINE VERBOSE_LINE QUIET_LINE; static struct option mirror_options[] = { - GETOPT_HELP, - GETOPT_SOCK, - GETOPT_ADDR, - GETOPT_PORT, - GETOPT_UNLINK, - GETOPT_BIND, - GETOPT_QUIET, - GETOPT_VERBOSE, - {0} + GETOPT_HELP, + GETOPT_SOCK, + GETOPT_ADDR, + GETOPT_PORT, + GETOPT_UNLINK, + GETOPT_BIND, + GETOPT_QUIET, + GETOPT_VERBOSE, + {0} }; + static char mirror_short_options[] = "hs:l:p:ub:" SOPT_QUIET SOPT_VERBOSE; static char mirror_help_text[] = - "Usage: flexnbd " CMD_MIRROR " \n\n" - "Start mirroring from the server with control socket SOCK to one at ADDR:PORT.\n\n" - HELP_LINE - "\t--" OPT_ADDR ",-l \tThe address to mirror to.\n" - "\t--" OPT_PORT ",-p \tThe port to mirror to.\n" - SOCK_LINE - "\t--" OPT_UNLINK ",-u\tUnlink the local file when done.\n" - BIND_LINE - VERBOSE_LINE - QUIET_LINE; + "Usage: flexnbd " CMD_MIRROR " \n\n" + "Start mirroring from the server with control socket SOCK to one at ADDR:PORT.\n\n" + HELP_LINE + "\t--" OPT_ADDR ",-l \tThe address to mirror to.\n" + "\t--" OPT_PORT ",-p \tThe port to mirror to.\n" + SOCK_LINE + "\t--" OPT_UNLINK ",-u\tUnlink the local file when done.\n" + BIND_LINE VERBOSE_LINE QUIET_LINE; static struct option break_options[] = { - GETOPT_HELP, - GETOPT_SOCK, - GETOPT_QUIET, - GETOPT_VERBOSE, - {0} + GETOPT_HELP, + GETOPT_SOCK, + GETOPT_QUIET, + GETOPT_VERBOSE, + {0} }; + static char break_short_options[] = "hs:" SOPT_QUIET SOPT_VERBOSE; static char break_help_text[] = - "Usage: flexnbd " CMD_BREAK " \n\n" - "Stop mirroring from the server with control socket SOCK.\n\n" - HELP_LINE - SOCK_LINE - VERBOSE_LINE - QUIET_LINE; + "Usage: flexnbd " CMD_BREAK " \n\n" + "Stop mirroring from the server with control socket SOCK.\n\n" + HELP_LINE SOCK_LINE VERBOSE_LINE QUIET_LINE; static struct option status_options[] = { - GETOPT_HELP, - GETOPT_SOCK, - GETOPT_QUIET, - GETOPT_VERBOSE, - {0} + GETOPT_HELP, + GETOPT_SOCK, + GETOPT_QUIET, + GETOPT_VERBOSE, + {0} }; + static char status_short_options[] = "hs:" SOPT_QUIET SOPT_VERBOSE; static char status_help_text[] = - "Usage: flexnbd " CMD_STATUS " \n\n" - "Get the status for a server with control socket SOCK.\n\n" - HELP_LINE - SOCK_LINE - VERBOSE_LINE - QUIET_LINE; + "Usage: flexnbd " CMD_STATUS " \n\n" + "Get the status for a server with control socket SOCK.\n\n" + HELP_LINE SOCK_LINE VERBOSE_LINE QUIET_LINE; char help_help_text_arr[] = - "Usage: flexnbd [cmd options]\n\n" - "Commands:\n" - "\tflexnbd serve\n" - "\tflexnbd listen\n" - "\tflexnbd read\n" - "\tflexnbd write\n" - "\tflexnbd acl\n" - "\tflexnbd mirror\n" - "\tflexnbd mirror-speed\n" - "\tflexnbd break\n" - "\tflexnbd status\n" - "\tflexnbd help\n\n" - "See flexnbd help for further info\n"; + "Usage: flexnbd [cmd options]\n\n" + "Commands:\n" + "\tflexnbd serve\n" + "\tflexnbd listen\n" + "\tflexnbd read\n" + "\tflexnbd write\n" + "\tflexnbd acl\n" + "\tflexnbd mirror\n" + "\tflexnbd mirror-speed\n" + "\tflexnbd break\n" + "\tflexnbd status\n" + "\tflexnbd help\n\n" "See flexnbd help for further info\n"; /* Slightly odd array/pointer pair to stop the compiler from complaining * about symbol sizes */ -char * help_help_text = help_help_text_arr; +char *help_help_text = help_help_text_arr; -void do_read(struct mode_readwrite_params* params); -void do_write(struct mode_readwrite_params* params); -void do_remote_command(char* command, char* mode, int argc, char** argv); +void do_read(struct mode_readwrite_params *params); +void do_write(struct mode_readwrite_params *params); +void do_remote_command(char *command, char *mode, int argc, char **argv); -void read_serve_param( int c, char **ip_addr, char **ip_port, char **file, char **sock, int *default_deny, int *use_killswitch ) +void read_serve_param(int c, char **ip_addr, char **ip_port, char **file, + char **sock, int *default_deny, int *use_killswitch) { - switch(c){ - case 'h': - fprintf(stdout, "%s\n", serve_help_text ); - exit( 0 ); - case 'l': - *ip_addr = optarg; - break; - case 'p': - *ip_port = optarg; - break; - case 'f': - *file = optarg; - break; - case 's': - *sock = optarg; - break; - case 'd': - *default_deny = 1; - break; - case 'q': - log_level = QUIET_LOG_LEVEL; - break; - case 'v': - log_level = VERBOSE_LOG_LEVEL; - break; - case 'k': - *use_killswitch = 1; - break; - default: - exit_err( serve_help_text ); - break; - } + switch (c) { + case 'h': + fprintf(stdout, "%s\n", serve_help_text); + exit(0); + case 'l': + *ip_addr = optarg; + break; + case 'p': + *ip_port = optarg; + break; + case 'f': + *file = optarg; + break; + case 's': + *sock = optarg; + break; + case 'd': + *default_deny = 1; + break; + case 'q': + log_level = QUIET_LOG_LEVEL; + break; + case 'v': + log_level = VERBOSE_LOG_LEVEL; + break; + case 'k': + *use_killswitch = 1; + break; + default: + exit_err(serve_help_text); + break; + } } -void read_listen_param( int c, - char **ip_addr, - char **ip_port, - char **file, - char **sock, - int *default_deny ) +void read_listen_param(int c, + char **ip_addr, + char **ip_port, + char **file, char **sock, int *default_deny) { - switch(c){ - case 'h': - fprintf(stdout, "%s\n", listen_help_text ); - exit(0); - case 'l': - *ip_addr = optarg; - break; - case 'p': - *ip_port = optarg; - break; - case 'f': - *file = optarg; - break; - case 's': - *sock = optarg; - break; - case 'd': - *default_deny = 1; - break; - case 'q': - log_level = QUIET_LOG_LEVEL; - break; - case 'v': - log_level = VERBOSE_LOG_LEVEL; - break; - default: - exit_err( listen_help_text ); - break; - } + switch (c) { + case 'h': + fprintf(stdout, "%s\n", listen_help_text); + exit(0); + case 'l': + *ip_addr = optarg; + break; + case 'p': + *ip_port = optarg; + break; + case 'f': + *file = optarg; + break; + case 's': + *sock = optarg; + break; + case 'd': + *default_deny = 1; + break; + case 'q': + log_level = QUIET_LOG_LEVEL; + break; + case 'v': + log_level = VERBOSE_LOG_LEVEL; + break; + default: + exit_err(listen_help_text); + break; + } } -void read_readwrite_param( int c, char **ip_addr, char **ip_port, char **bind_addr, char **from, char **size, char *err_text ) +void read_readwrite_param(int c, char **ip_addr, char **ip_port, + char **bind_addr, char **from, char **size, + char *err_text) { - switch(c){ - case 'h': - fprintf(stdout, "%s\n", err_text ); - exit( 0 ); - case 'l': - *ip_addr = optarg; - break; - case 'p': - *ip_port = optarg; - break; - case 'F': - *from = optarg; - break; - case 'S': - *size = optarg; - break; - case 'b': - *bind_addr = optarg; - break; - case 'q': - log_level = QUIET_LOG_LEVEL; - break; - case 'v': - log_level = VERBOSE_LOG_LEVEL; - break; - default: - exit_err( err_text ); - break; - } + switch (c) { + case 'h': + fprintf(stdout, "%s\n", err_text); + exit(0); + case 'l': + *ip_addr = optarg; + break; + case 'p': + *ip_port = optarg; + break; + case 'F': + *from = optarg; + break; + case 'S': + *size = optarg; + break; + case 'b': + *bind_addr = optarg; + break; + case 'q': + log_level = QUIET_LOG_LEVEL; + break; + case 'v': + log_level = VERBOSE_LOG_LEVEL; + break; + default: + exit_err(err_text); + break; + } } -void read_sock_param( int c, char **sock, char *help_text ) +void read_sock_param(int c, char **sock, char *help_text) { - switch(c){ - case 'h': - fprintf( stdout, "%s\n", help_text ); - exit( 0 ); - case 's': - *sock = optarg; - break; - case 'q': - log_level = QUIET_LOG_LEVEL; - break; - case 'v': - log_level = VERBOSE_LOG_LEVEL; - break; - default: - exit_err( help_text ); - break; - } + switch (c) { + case 'h': + fprintf(stdout, "%s\n", help_text); + exit(0); + case 's': + *sock = optarg; + break; + case 'q': + log_level = QUIET_LOG_LEVEL; + break; + case 'v': + log_level = VERBOSE_LOG_LEVEL; + break; + default: + exit_err(help_text); + break; + } } -void read_acl_param( int c, char **sock ) +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_speed_param( - int c, - char **sock, - char **max_speed -) +void read_mirror_speed_param(int c, char **sock, char **max_speed) { - switch( c ) { - case 'h': - fprintf( stdout, "%s\n", mirror_speed_help_text ); - exit( 0 ); - case 's': - *sock = optarg; - break; - case 'm': - *max_speed = optarg; - break; - case 'q': - log_level = QUIET_LOG_LEVEL; - break; - case 'v': - log_level = VERBOSE_LOG_LEVEL; - break; - default: - exit_err( mirror_speed_help_text ); - break; + switch (c) { + case 'h': + fprintf(stdout, "%s\n", mirror_speed_help_text); + exit(0); + case 's': + *sock = optarg; + break; + case 'm': + *max_speed = optarg; + break; + case 'q': + log_level = QUIET_LOG_LEVEL; + break; + case 'v': + log_level = VERBOSE_LOG_LEVEL; + break; + default: + exit_err(mirror_speed_help_text); + break; - } + } } -void read_mirror_param( - int c, - char **sock, - char **ip_addr, - char **ip_port, - int *unlink, - char **bind_addr ) +void read_mirror_param(int c, + char **sock, + char **ip_addr, + char **ip_port, int *unlink, char **bind_addr) { - switch( c ){ - case 'h': - fprintf( stdout, "%s\n", mirror_help_text ); - exit( 0 ); - case 's': - *sock = optarg; - break; - case 'l': - *ip_addr = optarg; - break; - case 'p': - *ip_port = optarg; - break; - case 'u': - *unlink = 1; - break; - case 'b': - *bind_addr = optarg; - break; - case 'q': - log_level = QUIET_LOG_LEVEL; - break; - case 'v': - log_level = VERBOSE_LOG_LEVEL; - break; - default: - exit_err( mirror_help_text ); - break; - } + switch (c) { + case 'h': + fprintf(stdout, "%s\n", mirror_help_text); + exit(0); + case 's': + *sock = optarg; + break; + case 'l': + *ip_addr = optarg; + break; + case 'p': + *ip_port = optarg; + break; + case 'u': + *unlink = 1; + break; + case 'b': + *bind_addr = optarg; + break; + case 'q': + log_level = QUIET_LOG_LEVEL; + break; + case 'v': + log_level = VERBOSE_LOG_LEVEL; + break; + default: + exit_err(mirror_help_text); + break; + } } -void read_break_param( int c, char **sock ) +void read_break_param(int c, char **sock) { - switch( c ) { - case 'h': - fprintf( stdout, "%s\n", break_help_text ); - exit( 0 ); - case 's': - *sock = optarg; - break; - case 'q': - log_level = QUIET_LOG_LEVEL; - break; - case 'v': - log_level = VERBOSE_LOG_LEVEL; - break; - default: - exit_err( break_help_text ); - break; - } + switch (c) { + case 'h': + fprintf(stdout, "%s\n", break_help_text); + exit(0); + case 's': + *sock = optarg; + break; + case 'q': + log_level = QUIET_LOG_LEVEL; + break; + case 'v': + log_level = VERBOSE_LOG_LEVEL; + break; + default: + exit_err(break_help_text); + break; + } } -void read_status_param( int c, char **sock ) +void read_status_param(int c, char **sock) { - read_sock_param( c, sock, status_help_text ); + read_sock_param(c, sock, status_help_text); } -int mode_serve( int argc, char *argv[] ) +int mode_serve(int argc, char *argv[]) { - int c; - char *ip_addr = NULL; - char *ip_port = NULL; - char *file = NULL; - char *sock = NULL; - int default_deny = 0; // not on by default - int use_killswitch = 0; - int err = 0; + int c; + char *ip_addr = NULL; + char *ip_port = NULL; + char *file = NULL; + char *sock = NULL; + int default_deny = 0; // not on by default + int use_killswitch = 0; + int err = 0; - int success; + int success; - struct flexnbd * flexnbd; + struct flexnbd *flexnbd; - while (1) { - c = getopt_long(argc, argv, serve_short_options, serve_options, NULL); - if ( c == -1 ) { break; } - - read_serve_param( c, &ip_addr, &ip_port, &file, &sock, &default_deny, &use_killswitch ); + while (1) { + c = getopt_long(argc, argv, serve_short_options, serve_options, + NULL); + if (c == -1) { + break; } - if ( NULL == ip_addr || NULL == ip_port ) { - err = 1; - fprintf( stderr, "both --addr and --port are required.\n" ); - } - if ( NULL == file ) { - err = 1; - fprintf( stderr, "--file is required\n" ); - } - if ( err ) { exit_err( serve_help_text ); } + read_serve_param(c, &ip_addr, &ip_port, &file, &sock, + &default_deny, &use_killswitch); + } - flexnbd = flexnbd_create_serving( ip_addr, ip_port, file, sock, default_deny, argc - optind, argv + optind, MAX_NBD_CLIENTS, use_killswitch ); - info( "Serving file %s", file ); - success = flexnbd_serve( flexnbd ); - flexnbd_destroy( flexnbd ); + if (NULL == ip_addr || NULL == ip_port) { + err = 1; + fprintf(stderr, "both --addr and --port are required.\n"); + } + if (NULL == file) { + err = 1; + fprintf(stderr, "--file is required\n"); + } + if (err) { + exit_err(serve_help_text); + } - return success ? 0 : 1; + flexnbd = + flexnbd_create_serving(ip_addr, ip_port, file, sock, default_deny, + argc - optind, argv + optind, + MAX_NBD_CLIENTS, use_killswitch); + info("Serving file %s", file); + success = flexnbd_serve(flexnbd); + flexnbd_destroy(flexnbd); + + return success ? 0 : 1; } -int mode_listen( int argc, char *argv[] ) +int mode_listen(int argc, char *argv[]) { - int c; - char *ip_addr = NULL; - char *ip_port = NULL; - char *file = NULL; - char *sock = NULL; - int default_deny = 0; // not on by default - int err = 0; + int c; + char *ip_addr = NULL; + char *ip_port = NULL; + char *file = NULL; + char *sock = NULL; + int default_deny = 0; // not on by default + int err = 0; - int success; + int success; - struct flexnbd * flexnbd; + struct flexnbd *flexnbd; - while (1) { - c = getopt_long(argc, argv, listen_short_options, listen_options, NULL); - if ( c == -1 ) { break; } - - read_listen_param( c, &ip_addr, &ip_port, - &file, &sock, &default_deny ); + while (1) { + c = getopt_long(argc, argv, listen_short_options, listen_options, + NULL); + if (c == -1) { + break; } - if ( NULL == ip_addr || NULL == ip_port ) { - err = 1; - fprintf( stderr, "both --addr and --port are required.\n" ); - } - if ( NULL == file ) { - err = 1; - fprintf( stderr, "--file is required\n" ); - } - if ( err ) { exit_err( listen_help_text ); } + read_listen_param(c, &ip_addr, &ip_port, + &file, &sock, &default_deny); + } - flexnbd = flexnbd_create_listening( - ip_addr, - ip_port, - file, - sock, - default_deny, - argc - optind, - argv + optind); - success = flexnbd_serve( flexnbd ); - flexnbd_destroy( flexnbd ); + if (NULL == ip_addr || NULL == ip_port) { + err = 1; + fprintf(stderr, "both --addr and --port are required.\n"); + } + if (NULL == file) { + err = 1; + fprintf(stderr, "--file is required\n"); + } + if (err) { + exit_err(listen_help_text); + } - return success ? 0 : 1; + flexnbd = flexnbd_create_listening(ip_addr, + ip_port, + file, + sock, + default_deny, + argc - optind, argv + optind); + success = flexnbd_serve(flexnbd); + flexnbd_destroy(flexnbd); + + return success ? 0 : 1; } @@ -545,340 +536,354 @@ int mode_listen( int argc, char *argv[] ) * char *s_length, * char *s_filename ) */ -void params_readwrite( - int write_not_read, - struct mode_readwrite_params* out, - char* s_ip_address, - char* s_port, - char* s_bind_address, - char* s_from, - char* s_length_or_filename -) +void params_readwrite(int write_not_read, + struct mode_readwrite_params *out, + char *s_ip_address, + char *s_port, + char *s_bind_address, + char *s_from, char *s_length_or_filename) { - FATAL_IF_NULL(s_ip_address, "No IP address supplied"); - FATAL_IF_NULL(s_port, "No port number supplied"); - FATAL_IF_NULL(s_from, "No from supplied"); - FATAL_IF_NULL(s_length_or_filename, "No length supplied"); + FATAL_IF_NULL(s_ip_address, "No IP address supplied"); + FATAL_IF_NULL(s_port, "No port number supplied"); + FATAL_IF_NULL(s_from, "No from supplied"); + FATAL_IF_NULL(s_length_or_filename, "No length supplied"); - FATAL_IF_ZERO( - parse_ip_to_sockaddr(&out->connect_to.generic, s_ip_address), - "Couldn't parse connection address '%s'", - s_ip_address - ); + FATAL_IF_ZERO(parse_ip_to_sockaddr + (&out->connect_to.generic, s_ip_address), + "Couldn't parse connection address '%s'", s_ip_address); - if (s_bind_address != NULL && - parse_ip_to_sockaddr(&out->connect_from.generic, s_bind_address) == 0) { - fatal("Couldn't parse bind address '%s'", s_bind_address); - } + if (s_bind_address != NULL && + parse_ip_to_sockaddr(&out->connect_from.generic, + s_bind_address) == 0) { + fatal("Couldn't parse bind address '%s'", s_bind_address); + } - parse_port( s_port, &out->connect_to.v4 ); + parse_port(s_port, &out->connect_to.v4); - long signed_from = atol(s_from); - FATAL_IF_NEGATIVE( signed_from, - "Can't read from a negative offset %d.", signed_from); - out->from = signed_from; + long signed_from = atol(s_from); + FATAL_IF_NEGATIVE(signed_from, + "Can't read from a negative offset %d.", + signed_from); + out->from = signed_from; - if (write_not_read) { - if (s_length_or_filename[0]-48 < 10) { - out->len = atol(s_length_or_filename); - out->data_fd = 0; - } - else { - out->data_fd = open( - s_length_or_filename, O_RDONLY); - FATAL_IF_NEGATIVE(out->data_fd, - "Couldn't open %s", s_length_or_filename); - off64_t signed_len = lseek64(out->data_fd, 0, SEEK_END); - FATAL_IF_NEGATIVE(signed_len, - "Couldn't find length of %s", s_length_or_filename); - out->len = signed_len; - FATAL_IF_NEGATIVE( - lseek64(out->data_fd, 0, SEEK_SET), - "Couldn't rewind %s", s_length_or_filename - ); - } - } - else { - out->len = atol(s_length_or_filename); - out->data_fd = 1; - } -} - - -int mode_read( int argc, char *argv[] ) -{ - int c; - char *ip_addr = NULL; - char *ip_port = NULL; - char *bind_addr = NULL; - char *from = NULL; - char *size = NULL; - int err = 0; - - struct mode_readwrite_params readwrite; - - while (1){ - c = getopt_long(argc, argv, read_short_options, read_options, NULL); - - if ( c == -1 ) { break; } - - read_readwrite_param( c, &ip_addr, &ip_port, &bind_addr, &from, &size, read_help_text ); - } - - if ( NULL == ip_addr || NULL == ip_port ) { - err = 1; - fprintf( stderr, "both --addr and --port are required.\n" ); - } - if ( NULL == from || NULL == size ) { - err = 1; - fprintf( stderr, "both --from and --size are required.\n" ); - } - if ( err ) { exit_err( read_help_text ); } - - memset( &readwrite, 0, sizeof( readwrite ) ); - params_readwrite( 0, &readwrite, ip_addr, ip_port, bind_addr, from, size ); - do_read( &readwrite ); - return 0; -} - -int mode_write( int argc, char *argv[] ) -{ - int c; - char *ip_addr = NULL; - char *ip_port = NULL; - char *bind_addr = NULL; - char *from = NULL; - char *size = NULL; - int err = 0; - - struct mode_readwrite_params readwrite; - - while (1){ - c = getopt_long(argc, argv, write_short_options, write_options, NULL); - if ( c == -1 ) { break; } - - read_readwrite_param( c, &ip_addr, &ip_port, &bind_addr, &from, &size, write_help_text ); - } - - if ( NULL == ip_addr || NULL == ip_port ) { - err = 1; - fprintf( stderr, "both --addr and --port are required.\n" ); - } - if ( NULL == from || NULL == size ) { - err = 1; - fprintf( stderr, "both --from and --size are required.\n" ); - } - if ( err ) { exit_err( write_help_text ); } - - memset( &readwrite, 0, sizeof( readwrite ) ); - params_readwrite( 1, &readwrite, ip_addr, ip_port, bind_addr, from, size ); - do_write( &readwrite ); - return 0; -} - -int mode_acl( int argc, char *argv[] ) -{ - int c; - char *sock = NULL; - - while (1) { - c = getopt_long( argc, argv, acl_short_options, acl_options, NULL ); - if ( c == -1 ) { break; } - read_acl_param( c, &sock ); - } - - if ( NULL == sock ){ - fprintf( stderr, "--sock is required.\n" ); - exit_err( acl_help_text ); - } - - /* Don't use the CMD_ACL macro here, "acl" is the remote command - * name, not the cli option - */ - do_remote_command( "acl", sock, argc - optind, argv + optind ); - - return 0; -} - - -int mode_mirror_speed( int argc, char *argv[] ) -{ - int c; - char *sock = NULL; - char *speed = NULL; - - while( 1 ) { - c = getopt_long( argc, argv, mirror_speed_short_options, mirror_speed_options, NULL ); - if ( -1 == c ) { break; } - read_mirror_speed_param( c, &sock, &speed ); - } - - if ( NULL == sock ) { - fprintf( stderr, "--sock is required.\n" ); - exit_err( mirror_speed_help_text ); - } - - if ( NULL == speed ) { - fprintf( stderr, "--max-speed is required.\n"); - exit_err( mirror_speed_help_text ); - } - - do_remote_command( "mirror_max_bps", sock, 1, &speed ); - return 0; -} - - -int mode_mirror( int argc, char *argv[] ) -{ - int c; - char *sock = NULL; - char *remote_argv[4] = {0}; - int err = 0; - int unlink = 0; - - remote_argv[2] = "exit"; - - while (1) { - c = getopt_long( argc, argv, mirror_short_options, mirror_options, NULL); - if ( -1 == c ) { break; } - read_mirror_param( c, - &sock, - &remote_argv[0], - &remote_argv[1], - &unlink, - &remote_argv[3] ); - } - - if ( NULL == sock ){ - fprintf( stderr, "--sock is required.\n" ); - err = 1; - } - if ( NULL == remote_argv[0] || NULL == remote_argv[1] ) { - fprintf( stderr, "both --addr and --port are required.\n"); - err = 1; - } - if ( err ) { exit_err( mirror_help_text ); } - if ( unlink ) { remote_argv[2] = "unlink"; } - - if (remote_argv[3] == NULL) { - do_remote_command( "mirror", sock, 3, remote_argv ); - } - else { - do_remote_command( "mirror", sock, 4, remote_argv ); - } - - return 0; -} - - -int mode_break( int argc, char *argv[] ) -{ - int c; - char *sock = NULL; - - while (1) { - c = getopt_long( argc, argv, break_short_options, break_options, NULL ); - if ( -1 == c ) { break; } - read_break_param( c, &sock ); - } - - if ( NULL == sock ){ - fprintf( stderr, "--sock is required.\n" ); - exit_err( break_help_text ); - } - - do_remote_command( "break", sock, argc - optind, argv + optind ); - - return 0; -} - -int mode_status( int argc, char *argv[] ) -{ - int c; - char *sock = NULL; - - while (1) { - c = getopt_long( argc, argv, status_short_options, status_options, NULL ); - if ( -1 == c ) { break; } - read_status_param( c, &sock ); - } - - if ( NULL == sock ){ - fprintf( stderr, "--sock is required.\n" ); - exit_err( status_help_text ); - } - - do_remote_command( "status", sock, argc - optind, argv + optind ); - - return 0; -} - -int mode_help( int argc, char *argv[] ) -{ - char *cmd; - char *help_text = NULL; - - if ( argc < 1 ){ - help_text = help_help_text; + if (write_not_read) { + if (s_length_or_filename[0] - 48 < 10) { + out->len = atol(s_length_or_filename); + out->data_fd = 0; } else { - cmd = argv[0]; - if (IS_CMD( CMD_SERVE, cmd ) ) { - help_text = serve_help_text; - } else if ( IS_CMD( CMD_LISTEN, cmd ) ) { - help_text = listen_help_text; - } else if ( IS_CMD( CMD_READ, cmd ) ) { - help_text = read_help_text; - } else if ( IS_CMD( CMD_WRITE, cmd ) ) { - help_text = write_help_text; - } else if ( IS_CMD( CMD_ACL, cmd ) ) { - help_text = acl_help_text; - } else if ( IS_CMD( CMD_MIRROR, cmd ) ) { - help_text = mirror_help_text; - } else if ( IS_CMD( CMD_STATUS, cmd ) ) { - help_text = status_help_text; - } else { exit_err( help_help_text ); } + out->data_fd = open(s_length_or_filename, O_RDONLY); + FATAL_IF_NEGATIVE(out->data_fd, + "Couldn't open %s", s_length_or_filename); + off64_t signed_len = lseek64(out->data_fd, 0, SEEK_END); + FATAL_IF_NEGATIVE(signed_len, + "Couldn't find length of %s", + s_length_or_filename); + out->len = signed_len; + FATAL_IF_NEGATIVE(lseek64(out->data_fd, 0, SEEK_SET), + "Couldn't rewind %s", s_length_or_filename); } - - fprintf( stdout, "%s\n", help_text ); - return 0; + } else { + out->len = atol(s_length_or_filename); + out->data_fd = 1; + } } -void mode(char* mode, int argc, char **argv) +int mode_read(int argc, char *argv[]) { - if ( IS_CMD( CMD_SERVE, mode ) ) { - exit( mode_serve( argc, argv ) ); + int c; + char *ip_addr = NULL; + char *ip_port = NULL; + char *bind_addr = NULL; + char *from = NULL; + char *size = NULL; + int err = 0; + + struct mode_readwrite_params readwrite; + + while (1) { + c = getopt_long(argc, argv, read_short_options, read_options, + NULL); + + if (c == -1) { + break; } - else if ( IS_CMD( CMD_LISTEN, mode ) ) { - exit( mode_listen( argc, argv ) ); - } - else if ( IS_CMD( CMD_READ, mode ) ) { - mode_read( argc, argv ); - } - else if ( IS_CMD( CMD_WRITE, mode ) ) { - mode_write( argc, argv ); - } - else if ( IS_CMD( CMD_ACL, mode ) ) { - mode_acl( argc, argv ); - } else if ( IS_CMD ( CMD_MIRROR_SPEED, mode ) ) { - mode_mirror_speed( argc, argv ); - } - else if ( IS_CMD( CMD_MIRROR, mode ) ) { - mode_mirror( argc, argv ); - } - else if ( IS_CMD( CMD_BREAK, mode ) ) { - mode_break( argc, argv ); - } - else if ( IS_CMD( CMD_STATUS, mode ) ) { - mode_status( argc, argv ); - } - else if ( IS_CMD( CMD_HELP, mode ) ) { - mode_help( argc-1, argv+1 ); - } - else { - mode_help( argc-1, argv+1 ); - exit( 1 ); - } - exit(0); + + read_readwrite_param(c, &ip_addr, &ip_port, &bind_addr, &from, + &size, read_help_text); + } + + if (NULL == ip_addr || NULL == ip_port) { + err = 1; + fprintf(stderr, "both --addr and --port are required.\n"); + } + if (NULL == from || NULL == size) { + err = 1; + fprintf(stderr, "both --from and --size are required.\n"); + } + if (err) { + exit_err(read_help_text); + } + + memset(&readwrite, 0, sizeof(readwrite)); + params_readwrite(0, &readwrite, ip_addr, ip_port, bind_addr, from, + size); + do_read(&readwrite); + return 0; } +int mode_write(int argc, char *argv[]) +{ + int c; + char *ip_addr = NULL; + char *ip_port = NULL; + char *bind_addr = NULL; + char *from = NULL; + char *size = NULL; + int err = 0; + + struct mode_readwrite_params readwrite; + + while (1) { + c = getopt_long(argc, argv, write_short_options, write_options, + NULL); + if (c == -1) { + break; + } + + read_readwrite_param(c, &ip_addr, &ip_port, &bind_addr, &from, + &size, write_help_text); + } + + if (NULL == ip_addr || NULL == ip_port) { + err = 1; + fprintf(stderr, "both --addr and --port are required.\n"); + } + if (NULL == from || NULL == size) { + err = 1; + fprintf(stderr, "both --from and --size are required.\n"); + } + if (err) { + exit_err(write_help_text); + } + + memset(&readwrite, 0, sizeof(readwrite)); + params_readwrite(1, &readwrite, ip_addr, ip_port, bind_addr, from, + size); + do_write(&readwrite); + return 0; +} + +int mode_acl(int argc, char *argv[]) +{ + int c; + char *sock = NULL; + + while (1) { + c = getopt_long(argc, argv, acl_short_options, acl_options, NULL); + if (c == -1) { + break; + } + read_acl_param(c, &sock); + } + + if (NULL == sock) { + fprintf(stderr, "--sock is required.\n"); + exit_err(acl_help_text); + } + + /* Don't use the CMD_ACL macro here, "acl" is the remote command + * name, not the cli option + */ + do_remote_command("acl", sock, argc - optind, argv + optind); + + return 0; +} + + +int mode_mirror_speed(int argc, char *argv[]) +{ + int c; + char *sock = NULL; + char *speed = NULL; + + while (1) { + c = getopt_long(argc, argv, mirror_speed_short_options, + mirror_speed_options, NULL); + if (-1 == c) { + break; + } + read_mirror_speed_param(c, &sock, &speed); + } + + if (NULL == sock) { + fprintf(stderr, "--sock is required.\n"); + exit_err(mirror_speed_help_text); + } + + if (NULL == speed) { + fprintf(stderr, "--max-speed is required.\n"); + exit_err(mirror_speed_help_text); + } + + do_remote_command("mirror_max_bps", sock, 1, &speed); + return 0; +} + + +int mode_mirror(int argc, char *argv[]) +{ + int c; + char *sock = NULL; + char *remote_argv[4] = { 0 }; + int err = 0; + int unlink = 0; + + remote_argv[2] = "exit"; + + while (1) { + c = getopt_long(argc, argv, mirror_short_options, mirror_options, + NULL); + if (-1 == c) { + break; + } + read_mirror_param(c, + &sock, + &remote_argv[0], + &remote_argv[1], &unlink, &remote_argv[3]); + } + + if (NULL == sock) { + fprintf(stderr, "--sock is required.\n"); + err = 1; + } + if (NULL == remote_argv[0] || NULL == remote_argv[1]) { + fprintf(stderr, "both --addr and --port are required.\n"); + err = 1; + } + if (err) { + exit_err(mirror_help_text); + } + if (unlink) { + remote_argv[2] = "unlink"; + } + + if (remote_argv[3] == NULL) { + do_remote_command("mirror", sock, 3, remote_argv); + } else { + do_remote_command("mirror", sock, 4, remote_argv); + } + + return 0; +} + + +int mode_break(int argc, char *argv[]) +{ + int c; + char *sock = NULL; + + while (1) { + c = getopt_long(argc, argv, break_short_options, break_options, + NULL); + if (-1 == c) { + break; + } + read_break_param(c, &sock); + } + + if (NULL == sock) { + fprintf(stderr, "--sock is required.\n"); + exit_err(break_help_text); + } + + do_remote_command("break", sock, argc - optind, argv + optind); + + return 0; +} + +int mode_status(int argc, char *argv[]) +{ + int c; + char *sock = NULL; + + while (1) { + c = getopt_long(argc, argv, status_short_options, status_options, + NULL); + if (-1 == c) { + break; + } + read_status_param(c, &sock); + } + + if (NULL == sock) { + fprintf(stderr, "--sock is required.\n"); + exit_err(status_help_text); + } + + do_remote_command("status", sock, argc - optind, argv + optind); + + return 0; +} + +int mode_help(int argc, char *argv[]) +{ + char *cmd; + char *help_text = NULL; + + if (argc < 1) { + help_text = help_help_text; + } else { + cmd = argv[0]; + if (IS_CMD(CMD_SERVE, cmd)) { + help_text = serve_help_text; + } else if (IS_CMD(CMD_LISTEN, cmd)) { + help_text = listen_help_text; + } else if (IS_CMD(CMD_READ, cmd)) { + help_text = read_help_text; + } else if (IS_CMD(CMD_WRITE, cmd)) { + help_text = write_help_text; + } else if (IS_CMD(CMD_ACL, cmd)) { + help_text = acl_help_text; + } else if (IS_CMD(CMD_MIRROR, cmd)) { + help_text = mirror_help_text; + } else if (IS_CMD(CMD_STATUS, cmd)) { + help_text = status_help_text; + } else { + exit_err(help_help_text); + } + } + + fprintf(stdout, "%s\n", help_text); + return 0; +} + + +void mode(char *mode, int argc, char **argv) +{ + if (IS_CMD(CMD_SERVE, mode)) { + exit(mode_serve(argc, argv)); + } else if (IS_CMD(CMD_LISTEN, mode)) { + exit(mode_listen(argc, argv)); + } else if (IS_CMD(CMD_READ, mode)) { + mode_read(argc, argv); + } else if (IS_CMD(CMD_WRITE, mode)) { + mode_write(argc, argv); + } else if (IS_CMD(CMD_ACL, mode)) { + mode_acl(argc, argv); + } else if (IS_CMD(CMD_MIRROR_SPEED, mode)) { + mode_mirror_speed(argc, argv); + } else if (IS_CMD(CMD_MIRROR, mode)) { + mode_mirror(argc, argv); + } else if (IS_CMD(CMD_BREAK, mode)) { + mode_break(argc, argv); + } else if (IS_CMD(CMD_STATUS, mode)) { + mode_status(argc, argv); + } else if (IS_CMD(CMD_HELP, mode)) { + mode_help(argc - 1, argv + 1); + } else { + mode_help(argc - 1, argv + 1); + exit(1); + } + exit(0); +} diff --git a/src/server/serve.c b/src/server/serve.c index b7b8e44..e5cc588 100644 --- a/src/server/serve.c +++ b/src/server/serve.c @@ -21,97 +21,93 @@ #include #include -struct server * server_create ( - struct flexnbd * flexnbd, - char* s_ip_address, - char* s_port, - char* s_file, - int default_deny, - int acl_entries, - char** s_acl_entries, - int max_nbd_clients, - int use_killswitch, - int success) +struct server *server_create(struct flexnbd *flexnbd, + char *s_ip_address, + char *s_port, + char *s_file, + int default_deny, + int acl_entries, + char **s_acl_entries, + int max_nbd_clients, + int use_killswitch, int success) { - NULLCHECK( flexnbd ); - struct server * out; - out = xmalloc( sizeof( struct server ) ); - out->flexnbd = flexnbd; - out->success = success; - out->max_nbd_clients = max_nbd_clients; - out->use_killswitch = use_killswitch; + NULLCHECK(flexnbd); + struct server *out; + out = xmalloc(sizeof(struct server)); + out->flexnbd = flexnbd; + out->success = success; + out->max_nbd_clients = max_nbd_clients; + out->use_killswitch = use_killswitch; - server_allow_new_clients( out ); + server_allow_new_clients(out); - out->nbd_client = xmalloc( max_nbd_clients * sizeof( struct client_tbl_entry ) ); - out->tcp_backlog = 10; /* does this need to be settable? */ + out->nbd_client = + xmalloc(max_nbd_clients * sizeof(struct client_tbl_entry)); + out->tcp_backlog = 10; /* does this need to be settable? */ - FATAL_IF_NULL(s_ip_address, "No IP address supplied"); - FATAL_IF_NULL(s_port, "No port number supplied"); - FATAL_IF_NULL(s_file, "No filename supplied"); - NULLCHECK( s_ip_address ); - FATAL_IF_ZERO( - parse_ip_to_sockaddr(&out->bind_to.generic, s_ip_address), - "Couldn't parse server address '%s' (use 0 if " - "you want to bind to all IPs)", - s_ip_address - ); + FATAL_IF_NULL(s_ip_address, "No IP address supplied"); + FATAL_IF_NULL(s_port, "No port number supplied"); + FATAL_IF_NULL(s_file, "No filename supplied"); + NULLCHECK(s_ip_address); + FATAL_IF_ZERO(parse_ip_to_sockaddr + (&out->bind_to.generic, s_ip_address), + "Couldn't parse server address '%s' (use 0 if " + "you want to bind to all IPs)", s_ip_address); - out->acl = acl_create( acl_entries, s_acl_entries, default_deny ); - if (out->acl && out->acl->len != acl_entries) { - fatal("Bad ACL entry '%s'", s_acl_entries[out->acl->len]); - } + out->acl = acl_create(acl_entries, s_acl_entries, default_deny); + if (out->acl && out->acl->len != acl_entries) { + fatal("Bad ACL entry '%s'", s_acl_entries[out->acl->len]); + } - parse_port( s_port, &out->bind_to.v4 ); + parse_port(s_port, &out->bind_to.v4); - out->filename = s_file; + out->filename = s_file; - out->l_acl = flexthread_mutex_create(); - out->l_start_mirror = flexthread_mutex_create(); + out->l_acl = flexthread_mutex_create(); + out->l_start_mirror = flexthread_mutex_create(); - out->mirror_can_start = 1; + out->mirror_can_start = 1; - out->close_signal = self_pipe_create(); - out->acl_updated_signal = self_pipe_create(); + out->close_signal = self_pipe_create(); + out->acl_updated_signal = self_pipe_create(); - NULLCHECK( out->close_signal ); - NULLCHECK( out->acl_updated_signal ); + NULLCHECK(out->close_signal); + NULLCHECK(out->acl_updated_signal); - log_context = s_file; + log_context = s_file; - return out; + return out; } -void server_destroy( struct server * serve ) +void server_destroy(struct server *serve) { - self_pipe_destroy( serve->acl_updated_signal ); - serve->acl_updated_signal = NULL; - self_pipe_destroy( serve->close_signal ); - serve->close_signal = NULL; + self_pipe_destroy(serve->acl_updated_signal); + serve->acl_updated_signal = NULL; + self_pipe_destroy(serve->close_signal); + serve->close_signal = NULL; - flexthread_mutex_destroy( serve->l_start_mirror ); - flexthread_mutex_destroy( serve->l_acl ); + flexthread_mutex_destroy(serve->l_start_mirror); + flexthread_mutex_destroy(serve->l_acl); - if ( serve->acl ) { - acl_destroy( serve->acl ); - serve->acl = NULL; - } + if (serve->acl) { + acl_destroy(serve->acl); + serve->acl = NULL; + } - free( serve->nbd_client ); - free( serve ); + free(serve->nbd_client); + free(serve); } -void server_unlink( struct server * serve ) +void server_unlink(struct server *serve) { - NULLCHECK( serve ); - NULLCHECK( serve->filename ); + NULLCHECK(serve); + NULLCHECK(serve->filename); - FATAL_IF_NEGATIVE( unlink( serve->filename ), - "Failed to unlink %s: %s", - serve->filename, - strerror( errno ) ); + FATAL_IF_NEGATIVE(unlink(serve->filename), + "Failed to unlink %s: %s", + serve->filename, strerror(errno)); } @@ -122,150 +118,149 @@ void server_unlink( struct server * serve ) do { NULLCHECK( s ); \ FATAL_IF( 0 != flexthread_mutex_unlock( s->f ), msg ); } while (0) -void server_lock_acl( struct server *serve ) +void server_lock_acl(struct server *serve) { - debug("ACL locking"); + debug("ACL locking"); - SERVER_LOCK( serve, l_acl, "Problem with ACL lock" ); + SERVER_LOCK(serve, l_acl, "Problem with ACL lock"); } -void server_unlock_acl( struct server *serve ) +void server_unlock_acl(struct server *serve) { - debug( "ACL unlocking" ); + debug("ACL unlocking"); - SERVER_UNLOCK( serve, l_acl, "Problem with ACL unlock" ); + SERVER_UNLOCK(serve, l_acl, "Problem with ACL unlock"); } -int server_acl_locked( struct server * serve ) +int server_acl_locked(struct server *serve) { - NULLCHECK( serve ); - return flexthread_mutex_held( serve->l_acl ); + NULLCHECK(serve); + return flexthread_mutex_held(serve->l_acl); } -void server_lock_start_mirror( struct server *serve ) +void server_lock_start_mirror(struct server *serve) { - debug("Mirror start locking"); + debug("Mirror start locking"); - SERVER_LOCK( serve, l_start_mirror, "Problem with start mirror lock" ); + SERVER_LOCK(serve, l_start_mirror, "Problem with start mirror lock"); } -void server_unlock_start_mirror( struct server *serve ) +void server_unlock_start_mirror(struct server *serve) { - debug("Mirror start unlocking"); + debug("Mirror start unlocking"); - SERVER_UNLOCK( serve, l_start_mirror, "Problem with start mirror unlock" ); + SERVER_UNLOCK(serve, l_start_mirror, + "Problem with start mirror unlock"); } -int server_start_mirror_locked( struct server * serve ) +int server_start_mirror_locked(struct server *serve) { - NULLCHECK( serve ); - return flexthread_mutex_held( serve->l_start_mirror ); + NULLCHECK(serve); + return flexthread_mutex_held(serve->l_start_mirror); } /** Return the actual port the server bound to. This is used because we * are allowed to pass "0" on the command-line. */ -int server_port( struct server * server ) +int server_port(struct server *server) { - NULLCHECK( server ); - union mysockaddr addr; - socklen_t len = sizeof( addr.v4 ); + NULLCHECK(server); + union mysockaddr addr; + socklen_t len = sizeof(addr.v4); - if ( getsockname( server->server_fd, &addr.v4, &len ) < 0 ) { - fatal( "Failed to get the port number." ); - } + if (getsockname(server->server_fd, &addr.v4, &len) < 0) { + fatal("Failed to get the port number."); + } - return be16toh( addr.v4.sin_port ); + return be16toh(addr.v4.sin_port); } /** Prepares a listening socket for the NBD server, binding etc. */ -void serve_open_server_socket(struct server* params) +void serve_open_server_socket(struct server *params) { - NULLCHECK( params ); + NULLCHECK(params); - params->server_fd = socket(params->bind_to.generic.sa_family == AF_INET ? - PF_INET : PF_INET6, SOCK_STREAM, 0); + params->server_fd = + socket(params->bind_to.generic.sa_family == + AF_INET ? PF_INET : PF_INET6, SOCK_STREAM, 0); - FATAL_IF_NEGATIVE( params->server_fd, "Couldn't create server socket" ); + FATAL_IF_NEGATIVE(params->server_fd, "Couldn't create server socket"); - /* We need SO_REUSEADDR so that when we switch from listening to - * serving we don't have to change address if we don't want to. - * - * If this fails, it's not necessarily bad in principle, but at - * this point in the code we can't tell if it's going to be a - * problem. It's also indicative of something odd going on, so - * we barf. - */ - FATAL_IF_NEGATIVE( - sock_set_reuseaddr( params->server_fd, 1 ), "Couldn't set SO_REUSEADDR" + /* We need SO_REUSEADDR so that when we switch from listening to + * serving we don't have to change address if we don't want to. + * + * If this fails, it's not necessarily bad in principle, but at + * this point in the code we can't tell if it's going to be a + * problem. It's also indicative of something odd going on, so + * we barf. + */ + FATAL_IF_NEGATIVE(sock_set_reuseaddr(params->server_fd, 1), + "Couldn't set SO_REUSEADDR"); + + /* TCP_NODELAY makes everything not be slow. If we can't set + * this, again, there's something odd going on which we don't + * understand. + */ + FATAL_IF_NEGATIVE(sock_set_tcp_nodelay(params->server_fd, 1), + "Couldn't set TCP_NODELAY"); + + /* If we can't bind, presumably that's because someone else is + * squatting on our ip/port combo, or the ip isn't yet + * configured. Ideally we want to retry this. */ + FATAL_UNLESS_ZERO(sock_try_bind + (params->server_fd, ¶ms->bind_to.generic), + SHOW_ERRNO("Failed to bind() socket") ); - /* TCP_NODELAY makes everything not be slow. If we can't set - * this, again, there's something odd going on which we don't - * understand. - */ - FATAL_IF_NEGATIVE( - sock_set_tcp_nodelay( params->server_fd, 1 ), "Couldn't set TCP_NODELAY" - ); - - /* If we can't bind, presumably that's because someone else is - * squatting on our ip/port combo, or the ip isn't yet - * configured. Ideally we want to retry this. */ - FATAL_UNLESS_ZERO( - sock_try_bind( params->server_fd, ¶ms->bind_to.generic ), - SHOW_ERRNO( "Failed to bind() socket" ) - ); - - FATAL_IF_NEGATIVE( - listen(params->server_fd, params->tcp_backlog), - "Couldn't listen on server socket" - ); + FATAL_IF_NEGATIVE(listen(params->server_fd, params->tcp_backlog), + "Couldn't listen on server socket"); } -int tryjoin_client_thread( struct client_tbl_entry *entry, int (*joinfunc)(pthread_t, void **) ) +int tryjoin_client_thread(struct client_tbl_entry *entry, + int (*joinfunc) (pthread_t, void **)) { - NULLCHECK( entry ); - NULLCHECK( joinfunc ); + NULLCHECK(entry); + NULLCHECK(joinfunc); - int was_closed = 0; - void * status=NULL; + int was_closed = 0; + void *status = NULL; - if (entry->thread != 0) { - char s_client_address[128]; + if (entry->thread != 0) { + char s_client_address[128]; - sockaddr_address_string( &entry->address.generic, &s_client_address[0], 128 ); + sockaddr_address_string(&entry->address.generic, + &s_client_address[0], 128); - debug( "%s(%p,...)", joinfunc == pthread_join ? "joining" : "tryjoining", entry->thread ); - int join_errno = joinfunc(entry->thread, &status); + debug("%s(%p,...)", + joinfunc == pthread_join ? "joining" : "tryjoining", + entry->thread); + int join_errno = joinfunc(entry->thread, &status); - /* join_errno can legitimately be ESRCH if the thread is - * already dead, but the client still needs tidying up. */ - if (join_errno != 0 && !entry->client->stopped ) { - debug( "join_errno was %s, stopped was %d", strerror( join_errno ), entry->client->stopped ); - FATAL_UNLESS( join_errno == EBUSY, - "Problem with joining thread %p: %s", - entry->thread, - strerror(join_errno) ); - } - else if ( join_errno == 0 ) { - debug("nbd thread %016x exited (%s) with status %ld", - entry->thread, - s_client_address, - (uintptr_t)status); - client_destroy( entry->client ); - entry->client = NULL; - entry->thread = 0; - was_closed = 1; - } + /* join_errno can legitimately be ESRCH if the thread is + * already dead, but the client still needs tidying up. */ + if (join_errno != 0 && !entry->client->stopped) { + debug("join_errno was %s, stopped was %d", + strerror(join_errno), entry->client->stopped); + FATAL_UNLESS(join_errno == EBUSY, + "Problem with joining thread %p: %s", + entry->thread, strerror(join_errno)); + } else if (join_errno == 0) { + debug("nbd thread %016x exited (%s) with status %ld", + entry->thread, s_client_address, (uintptr_t) status); + client_destroy(entry->client); + entry->client = NULL; + entry->thread = 0; + was_closed = 1; } + } - return was_closed; + return was_closed; } @@ -282,17 +277,18 @@ int tryjoin_client_thread( struct client_tbl_entry *entry, int (*joinfunc)(pthre * including their signal pipes, won't be cleaned up until the next new * client connection attempt. */ -int cleanup_client_thread( struct client_tbl_entry * entry ) +int cleanup_client_thread(struct client_tbl_entry *entry) { - return tryjoin_client_thread( entry, pthread_tryjoin_np ); + return tryjoin_client_thread(entry, pthread_tryjoin_np); } -void cleanup_client_threads( struct client_tbl_entry * entries, size_t entries_len ) +void cleanup_client_threads(struct client_tbl_entry *entries, + size_t entries_len) { - size_t i; - for( i = 0; i < entries_len; i++ ) { - cleanup_client_thread( &entries[i] ); - } + size_t i; + for (i = 0; i < entries_len; i++) { + cleanup_client_thread(&entries[i]); + } } @@ -301,47 +297,47 @@ void cleanup_client_threads( struct client_tbl_entry * entries, size_t entries_l * This function will not return until pthread_join has returned, so * ensures that the client thread is dead. */ -int join_client_thread( struct client_tbl_entry *entry ) +int join_client_thread(struct client_tbl_entry *entry) { - return tryjoin_client_thread( entry, pthread_join ); + return tryjoin_client_thread(entry, pthread_join); } /** We can only accommodate MAX_NBD_CLIENTS connections at once. This function * goes through the current list, waits for any threads that have finished * and returns the next slot free (or -1 if there are none). */ -int cleanup_and_find_client_slot(struct server* params) +int cleanup_and_find_client_slot(struct server *params) { - NULLCHECK( params ); + NULLCHECK(params); - int slot=-1, i; + int slot = -1, i; - cleanup_client_threads( params->nbd_client, params->max_nbd_clients ); + cleanup_client_threads(params->nbd_client, params->max_nbd_clients); - for ( i = 0; i < params->max_nbd_clients; i++ ) { - if( params->nbd_client[i].thread == 0 && slot == -1 ){ - slot = i; - break; - } + for (i = 0; i < params->max_nbd_clients; i++) { + if (params->nbd_client[i].thread == 0 && slot == -1) { + slot = i; + break; } + } - return slot; + return slot; } -int server_count_clients( struct server *params ) +int server_count_clients(struct server *params) { - NULLCHECK( params ); - int i, count = 0; - - cleanup_client_threads( params->nbd_client, params->max_nbd_clients ); + NULLCHECK(params); + int i, count = 0; - for ( i = 0 ; i < params->max_nbd_clients ; i++ ) { - if ( params->nbd_client[i].thread != 0 ) { - count++; - } + cleanup_client_threads(params->nbd_client, params->max_nbd_clients); + + for (i = 0; i < params->max_nbd_clients; i++) { + if (params->nbd_client[i].thread != 0) { + count++; } + } - return count; + return count; } @@ -349,64 +345,65 @@ int server_count_clients( struct server *params ) * to the current acl. If params->acl is NULL, the result will be 1, * otherwise it will be the result of acl_includes(). */ -int server_acl_accepts( struct server *params, union mysockaddr * client_address ) +int server_acl_accepts(struct server *params, + union mysockaddr *client_address) { - NULLCHECK( params ); - NULLCHECK( client_address ); + NULLCHECK(params); + NULLCHECK(client_address); - struct acl * acl; - int accepted; + struct acl *acl; + int accepted; - server_lock_acl( params ); - { - acl = params->acl; - accepted = acl ? acl_includes( acl, client_address ) : 1; - } - server_unlock_acl( params ); + server_lock_acl(params); + { + acl = params->acl; + accepted = acl ? acl_includes(acl, client_address) : 1; + } + server_unlock_acl(params); - return accepted; + return accepted; } -int server_should_accept_client( - struct server * params, - union mysockaddr * client_address, - char *s_client_address, - size_t s_client_address_len ) +int server_should_accept_client(struct server *params, + union mysockaddr *client_address, + char *s_client_address, + size_t s_client_address_len) { - NULLCHECK( params ); - NULLCHECK( client_address ); - NULLCHECK( s_client_address ); + NULLCHECK(params); + NULLCHECK(client_address); + NULLCHECK(s_client_address); - const char* result = sockaddr_address_string( - &client_address->generic, s_client_address, s_client_address_len - ); + const char *result = + sockaddr_address_string(&client_address->generic, s_client_address, + s_client_address_len); - if ( NULL == result ) { - warn( "Rejecting client %s: Bad client_address", s_client_address ); - return 0; - } + if (NULL == result) { + warn("Rejecting client %s: Bad client_address", s_client_address); + return 0; + } - if ( !server_acl_accepts( params, client_address ) ) { - warn( "Rejecting client %s: Access control error", s_client_address ); - debug( "We %s have an acl, and default_deny is %s", - (params->acl ? "do" : "do not"), - (params->acl->default_deny ? "true" : "false") ); - return 0; - } + if (!server_acl_accepts(params, client_address)) { + warn("Rejecting client %s: Access control error", + s_client_address); + debug("We %s have an acl, and default_deny is %s", + (params->acl ? "do" : "do not"), + (params->acl->default_deny ? "true" : "false")); + return 0; + } - return 1; + return 1; } -int spawn_client_thread( - struct client * client_params, - pthread_t *out_thread) +int spawn_client_thread(struct client *client_params, + pthread_t * out_thread) { - int result = pthread_create(out_thread, NULL, client_serve, client_params); + int result = + pthread_create(out_thread, NULL, client_serve, client_params); - return result; + return result; } @@ -414,167 +411,176 @@ int spawn_client_thread( * to handle it. Rejects the connection if there is an ACL, and the far end's * address doesn't match, or if there are too many clients already connected. */ -void accept_nbd_client( - struct server* params, - int client_fd, - union mysockaddr* client_address) +void accept_nbd_client(struct server *params, + int client_fd, union mysockaddr *client_address) { - NULLCHECK(params); - NULLCHECK(client_address); + NULLCHECK(params); + NULLCHECK(client_address); - struct client* client_params; - int slot; - char s_client_address[64] = {0}; + struct client *client_params; + int slot; + char s_client_address[64] = { 0 }; - FATAL_IF_NEGATIVE( sock_set_keepalive_params( client_fd, CLIENT_KEEPALIVE_TIME, CLIENT_KEEPALIVE_INTVL, CLIENT_KEEPALIVE_PROBES), - "Error setting keepalive parameters on client socket fd %d", client_fd ); + FATAL_IF_NEGATIVE(sock_set_keepalive_params + (client_fd, CLIENT_KEEPALIVE_TIME, + CLIENT_KEEPALIVE_INTVL, CLIENT_KEEPALIVE_PROBES), + "Error setting keepalive parameters on client socket fd %d", + client_fd); - if ( !server_should_accept_client( params, client_address, s_client_address, 64 ) ) { - FATAL_IF_NEGATIVE( close( client_fd ), - "Error closing client socket fd %d", client_fd ); - debug("Closed client socket fd %d", client_fd); - return; - } + if (!server_should_accept_client + (params, client_address, s_client_address, 64)) { + FATAL_IF_NEGATIVE(close(client_fd), + "Error closing client socket fd %d", client_fd); + debug("Closed client socket fd %d", client_fd); + return; + } - slot = cleanup_and_find_client_slot(params); - if (slot < 0) { - warn("too many clients to accept connection"); - FATAL_IF_NEGATIVE( close( client_fd ), - "Error closing client socket fd %d", client_fd ); - debug("Closed client socket fd %d", client_fd); - return; - } + slot = cleanup_and_find_client_slot(params); + if (slot < 0) { + warn("too many clients to accept connection"); + FATAL_IF_NEGATIVE(close(client_fd), + "Error closing client socket fd %d", client_fd); + debug("Closed client socket fd %d", client_fd); + return; + } - info( "Client %s accepted on fd %d.", s_client_address, client_fd ); - client_params = client_create( params, client_fd ); + info("Client %s accepted on fd %d.", s_client_address, client_fd); + client_params = client_create(params, client_fd); - params->nbd_client[slot].client = client_params; - memcpy(¶ms->nbd_client[slot].address, client_address, - sizeof(union mysockaddr)); + params->nbd_client[slot].client = client_params; + memcpy(¶ms->nbd_client[slot].address, client_address, + sizeof(union mysockaddr)); - pthread_t * thread = ¶ms->nbd_client[slot].thread; + pthread_t *thread = ¶ms->nbd_client[slot].thread; - if ( 0 != spawn_client_thread( client_params, thread ) ) { - debug( "Thread creation problem." ); - client_destroy( client_params ); - FATAL_IF_NEGATIVE( close(client_fd), - "Error closing client socket fd %d", client_fd ); - debug("Closed client socket fd %d", client_fd); - return; - } + if (0 != spawn_client_thread(client_params, thread)) { + debug("Thread creation problem."); + client_destroy(client_params); + FATAL_IF_NEGATIVE(close(client_fd), + "Error closing client socket fd %d", client_fd); + debug("Closed client socket fd %d", client_fd); + return; + } - debug("nbd thread %p started (%s)", params->nbd_client[slot].thread, s_client_address); + debug("nbd thread %p started (%s)", params->nbd_client[slot].thread, + s_client_address); } -void server_audit_clients( struct server * serve) +void server_audit_clients(struct server *serve) { - NULLCHECK( serve ); + NULLCHECK(serve); - int i; - struct client_tbl_entry * entry; + int i; + struct client_tbl_entry *entry; - /* There's an apparent race here. If the acl updates while - * we're traversing the nbd_clients array, the earlier entries - * won't have been audited against the later acl. This isn't a - * problem though, because in order to update the acl - * server_replace_acl must have been called, so the - * server_accept loop will see a second acl_updated signal as - * soon as it hits select, and a second audit will be run. - */ - for( i = 0; i < serve->max_nbd_clients; i++ ) { - entry = &serve->nbd_client[i]; - if ( 0 == entry->thread ) { continue; } - if ( server_acl_accepts( serve, &entry->address ) ) { continue; } - client_signal_stop( entry->client ); + /* There's an apparent race here. If the acl updates while + * we're traversing the nbd_clients array, the earlier entries + * won't have been audited against the later acl. This isn't a + * problem though, because in order to update the acl + * server_replace_acl must have been called, so the + * server_accept loop will see a second acl_updated signal as + * soon as it hits select, and a second audit will be run. + */ + for (i = 0; i < serve->max_nbd_clients; i++) { + entry = &serve->nbd_client[i]; + if (0 == entry->thread) { + continue; } + if (server_acl_accepts(serve, &entry->address)) { + continue; + } + client_signal_stop(entry->client); + } } -int server_is_closed(struct server* serve) +int server_is_closed(struct server *serve) { - NULLCHECK( serve ); - return fd_is_closed( serve->server_fd ); + NULLCHECK(serve); + return fd_is_closed(serve->server_fd); } -void server_close_clients( struct server *params ) +void server_close_clients(struct server *params) { - NULLCHECK(params); + NULLCHECK(params); - info("closing all clients"); + info("closing all clients"); - int i; /* , j; */ - struct client_tbl_entry *entry; + int i; /* , j; */ + struct client_tbl_entry *entry; - for( i = 0; i < params->max_nbd_clients; i++ ) { - entry = ¶ms->nbd_client[i]; + for (i = 0; i < params->max_nbd_clients; i++) { + entry = ¶ms->nbd_client[i]; - if ( entry->thread != 0 ) { - debug( "Stop signaling client %p", entry->client ); - client_signal_stop( entry->client ); - } + if (entry->thread != 0) { + debug("Stop signaling client %p", entry->client); + client_signal_stop(entry->client); } - /* We don't join the clients here. When we enter the final - * mirror pass, we get the IO lock, then wait for the server_fd - * to close before sending the data, to be sure that no new - * clients can be accepted which might think they've written - * to the disc. However, an existing client thread can be - * waiting for the IO lock already, so if we try to join it - * here, we deadlock. - * - * The client threads will be joined in serve_cleanup. - * - */ + } + /* We don't join the clients here. When we enter the final + * mirror pass, we get the IO lock, then wait for the server_fd + * to close before sending the data, to be sure that no new + * clients can be accepted which might think they've written + * to the disc. However, an existing client thread can be + * waiting for the IO lock already, so if we try to join it + * here, we deadlock. + * + * The client threads will be joined in serve_cleanup. + * + */ } /** Replace the current acl with a new one. The old one will be thrown * away. */ -void server_replace_acl( struct server *serve, struct acl * new_acl ) +void server_replace_acl(struct server *serve, struct acl *new_acl) { - NULLCHECK(serve); - NULLCHECK(new_acl); + NULLCHECK(serve); + NULLCHECK(new_acl); - /* We need to lock around updates to the acl in case we try to - * destroy the old acl while checking against it. - */ - server_lock_acl( serve ); - { - struct acl * old_acl = serve->acl; - serve->acl = new_acl; - /* We should always have an old_acl, but just in case... */ - if ( old_acl ) { acl_destroy( old_acl ); } + /* We need to lock around updates to the acl in case we try to + * destroy the old acl while checking against it. + */ + server_lock_acl(serve); + { + struct acl *old_acl = serve->acl; + serve->acl = new_acl; + /* We should always have an old_acl, but just in case... */ + if (old_acl) { + acl_destroy(old_acl); } - server_unlock_acl( serve ); + } + server_unlock_acl(serve); - self_pipe_signal( serve->acl_updated_signal ); + self_pipe_signal(serve->acl_updated_signal); } -void server_prevent_mirror_start( struct server *serve ) +void server_prevent_mirror_start(struct server *serve) { - NULLCHECK( serve ); + NULLCHECK(serve); - serve->mirror_can_start = 0; + serve->mirror_can_start = 0; } -void server_allow_mirror_start( struct server *serve ) +void server_allow_mirror_start(struct server *serve) { - NULLCHECK( serve ); + NULLCHECK(serve); - serve->mirror_can_start = 1; + serve->mirror_can_start = 1; } /* Only call this with the mirror start lock held */ -int server_mirror_can_start( struct server *serve ) +int server_mirror_can_start(struct server *serve) { - NULLCHECK( serve ); + NULLCHECK(serve); - return serve->mirror_can_start; + return serve->mirror_can_start; } @@ -582,306 +588,318 @@ int server_mirror_can_start( struct server *serve ) * 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 serve_shutdown_is_graceful(struct server *params) { - int is_mirroring = 0; - server_lock_start_mirror( params ); - { - if ( server_is_mirroring( params ) ) { - is_mirroring = 1; - warn( "Stop signal received while mirroring." ); - server_prevent_mirror_start( params ); - } + int is_mirroring = 0; + server_lock_start_mirror(params); + { + if (server_is_mirroring(params)) { + is_mirroring = 1; + warn("Stop signal received while mirroring."); + server_prevent_mirror_start(params); } - server_unlock_start_mirror( params ); + } + server_unlock_start_mirror(params); - return !is_mirroring; + return !is_mirroring; } /** Accept either an NBD or control socket connection, dispatch appropriately */ -int server_accept( struct server * params ) +int server_accept(struct server *params) { - NULLCHECK( params ); - debug("accept loop starting"); - union mysockaddr client_address; - fd_set fds; - socklen_t socklen=sizeof(client_address); - /* We select on this fd to receive OS signals (only a few of - * which we're interested in, see flexnbd.c */ - int signal_fd = flexnbd_signal_fd( params->flexnbd ); - int should_continue = 1; + NULLCHECK(params); + debug("accept loop starting"); + union mysockaddr client_address; + fd_set fds; + socklen_t socklen = sizeof(client_address); + /* We select on this fd to receive OS signals (only a few of + * which we're interested in, see flexnbd.c */ + int signal_fd = flexnbd_signal_fd(params->flexnbd); + int should_continue = 1; - FD_ZERO(&fds); - FD_SET(params->server_fd, &fds); - if( 0 < signal_fd ) { FD_SET(signal_fd, &fds); } - self_pipe_fd_set( params->close_signal, &fds ); - self_pipe_fd_set( params->acl_updated_signal, &fds ); + FD_ZERO(&fds); + FD_SET(params->server_fd, &fds); + if (0 < signal_fd) { + FD_SET(signal_fd, &fds); + } + self_pipe_fd_set(params->close_signal, &fds); + self_pipe_fd_set(params->acl_updated_signal, &fds); - FATAL_IF_NEGATIVE( - sock_try_select(FD_SETSIZE, &fds, NULL, NULL, NULL), - SHOW_ERRNO( "select() failed" ) + FATAL_IF_NEGATIVE(sock_try_select(FD_SETSIZE, &fds, NULL, NULL, NULL), + SHOW_ERRNO("select() failed") ); - if ( self_pipe_fd_isset( params->close_signal, &fds ) ){ - server_close_clients( params ); - should_continue = 0; + if (self_pipe_fd_isset(params->close_signal, &fds)) { + server_close_clients(params); + should_continue = 0; + } + + + if (0 < signal_fd && FD_ISSET(signal_fd, &fds)) { + debug("Stop signal received."); + server_close_clients(params); + params->success = params->success + && serve_shutdown_is_graceful(params); + should_continue = 0; + } + + + if (self_pipe_fd_isset(params->acl_updated_signal, &fds)) { + self_pipe_signal_clear(params->acl_updated_signal); + server_audit_clients(params); + } + + if (FD_ISSET(params->server_fd, &fds)) { + int client_fd = + accept(params->server_fd, &client_address.generic, &socklen); + + if (params->allow_new_clients) { + debug("Accepted nbd client socket fd %d", client_fd); + accept_nbd_client(params, client_fd, &client_address); + } else { + debug("New NBD client socket %d not allowed", client_fd); + sock_try_close(client_fd); } + } - - if ( 0 < signal_fd && FD_ISSET( signal_fd, &fds ) ){ - debug( "Stop signal received." ); - server_close_clients( params ); - params->success = params->success && serve_shutdown_is_graceful( params ); - should_continue = 0; - } - - - if ( self_pipe_fd_isset( params->acl_updated_signal, &fds ) ) { - self_pipe_signal_clear( params->acl_updated_signal ); - server_audit_clients( params ); - } - - if ( FD_ISSET( params->server_fd, &fds ) ){ - int client_fd = accept( params->server_fd, &client_address.generic, &socklen ); - - if ( params->allow_new_clients ) { - debug("Accepted nbd client socket fd %d", client_fd); - accept_nbd_client(params, client_fd, &client_address); - } else { - debug( "New NBD client socket %d not allowed", client_fd ); - sock_try_close( client_fd ); - } - } - - return should_continue; + return should_continue; } -void serve_accept_loop(struct server* params) +void serve_accept_loop(struct server *params) { - NULLCHECK( params ); - while( server_accept( params ) ); + NULLCHECK(params); + while (server_accept(params)); } -void* build_allocation_map_thread(void* serve_uncast) +void *build_allocation_map_thread(void *serve_uncast) { - NULLCHECK( serve_uncast ); + NULLCHECK(serve_uncast); - struct server* serve = (struct server*) serve_uncast; + struct server *serve = (struct server *) serve_uncast; - NULLCHECK( serve->filename ); - NULLCHECK( serve->allocation_map ); + NULLCHECK(serve->filename); + NULLCHECK(serve->allocation_map); - int fd = open( serve->filename, O_RDONLY ); - FATAL_IF_NEGATIVE( fd, "Couldn't open %s", serve->filename ); + int fd = open(serve->filename, O_RDONLY); + FATAL_IF_NEGATIVE(fd, "Couldn't open %s", serve->filename); - if ( build_allocation_map( serve->allocation_map, fd ) ) { - serve->allocation_map_built = 1; - } - else { - /* We can operate without it, but we can't free it without a race. - * All that happens if we leave it is that it gradually builds up an - * *incomplete* record of writes. Nobody will use it, as - * allocation_map_built == 0 for the lifetime of the process. - * - * The stream functionality can still be relied on. We don't need to - * worry about mirroring waiting for the allocation map to finish, - * because we already copy every byte at least once. If that changes in - * the future, we'll need to wait for the allocation map to finish or - * fail before we can complete the migration. - */ - serve->allocation_map_not_built = 1; - warn( "Didn't build allocation map for %s", serve->filename ); - } + if (build_allocation_map(serve->allocation_map, fd)) { + serve->allocation_map_built = 1; + } else { + /* We can operate without it, but we can't free it without a race. + * All that happens if we leave it is that it gradually builds up an + * *incomplete* record of writes. Nobody will use it, as + * allocation_map_built == 0 for the lifetime of the process. + * + * The stream functionality can still be relied on. We don't need to + * worry about mirroring waiting for the allocation map to finish, + * because we already copy every byte at least once. If that changes in + * the future, we'll need to wait for the allocation map to finish or + * fail before we can complete the migration. + */ + serve->allocation_map_not_built = 1; + warn("Didn't build allocation map for %s", serve->filename); + } - close( fd ); - return NULL; + close(fd); + return NULL; } /** Initialisation function that sets up the initial allocation map, i.e. so * we know which blocks of the file are allocated. */ -void serve_init_allocation_map(struct server* params) +void serve_init_allocation_map(struct server *params) { - NULLCHECK( params ); - NULLCHECK( params->filename ); + NULLCHECK(params); + NULLCHECK(params->filename); - int fd = open( params->filename, O_RDONLY ); - off64_t size; + int fd = open(params->filename, O_RDONLY); + off64_t size; - FATAL_IF_NEGATIVE(fd, "Couldn't open %s", params->filename ); - size = lseek64( fd, 0, SEEK_END ); + FATAL_IF_NEGATIVE(fd, "Couldn't open %s", params->filename); + size = lseek64(fd, 0, SEEK_END); - /* If discs are not in multiples of 512, then odd things happen, - * resulting in reads/writes past the ends of files. - */ - if ( size != (size & ~0x1ff)) { - warn("file does not fit into 512-byte sectors; the end of the file will be ignored."); - size &= ~0x1ff; + /* If discs are not in multiples of 512, then odd things happen, + * resulting in reads/writes past the ends of files. + */ + if (size != (size & ~0x1ff)) { + warn("file does not fit into 512-byte sectors; the end of the file will be ignored."); + size &= ~0x1ff; + } + + params->size = size; + FATAL_IF_NEGATIVE(size, "Couldn't find size of %s", params->filename); + + params->allocation_map = + bitset_alloc(params->size, block_allocation_resolution); + + int ok = pthread_create(¶ms->allocation_map_builder_thread, + NULL, + build_allocation_map_thread, + params); + + FATAL_IF_NEGATIVE(ok, "Couldn't create thread"); +} + + +void server_forbid_new_clients(struct server *serve) +{ + serve->allow_new_clients = 0; + return; +} + +void server_allow_new_clients(struct server *serve) +{ + serve->allow_new_clients = 1; + return; +} + +void server_join_clients(struct server *serve) +{ + int i; + void *status; + + for (i = 0; i < serve->max_nbd_clients; i++) { + pthread_t thread_id = serve->nbd_client[i].thread; + + if (thread_id != 0) { + debug("joining thread %p", thread_id); + int err = pthread_join(thread_id, &status); + if (0 == err) { + serve->nbd_client[i].thread = 0; + } else { + warn("Error %s (%i) joining thread %p", strerror(err), err, + thread_id); + } } + } - params->size = size; - FATAL_IF_NEGATIVE( size, "Couldn't find size of %s", - params->filename ); - - params->allocation_map = - bitset_alloc( params->size, block_allocation_resolution ); - - int ok = pthread_create( ¶ms->allocation_map_builder_thread, - NULL, - build_allocation_map_thread, - params ); - - FATAL_IF_NEGATIVE( ok, "Couldn't create thread" ); -} - - -void server_forbid_new_clients( struct server * serve ) -{ - serve->allow_new_clients = 0; - return; -} - -void server_allow_new_clients( struct server * serve ) -{ - serve->allow_new_clients = 1; - return; -} - -void server_join_clients( struct server * serve ) { - int i; - void* status; - - for (i=0; i < serve->max_nbd_clients; i++) { - pthread_t thread_id = serve->nbd_client[i].thread; - - if (thread_id != 0) { - debug( "joining thread %p", thread_id ); - int err = pthread_join( thread_id, &status ); - if ( 0 == err ) { - serve->nbd_client[i].thread = 0; - } else { - warn( "Error %s (%i) joining thread %p", strerror( err ), err, thread_id ); - } - } - } - - return; + return; } /* Tell the server to close all the things. */ -void serve_signal_close( struct server * serve ) +void serve_signal_close(struct server *serve) { - NULLCHECK( serve ); - info("signalling close"); - self_pipe_signal( serve->close_signal ); + NULLCHECK(serve); + info("signalling close"); + self_pipe_signal(serve->close_signal); } /* Block until the server closes the server_fd. */ -void serve_wait_for_close( struct server * serve ) +void serve_wait_for_close(struct server *serve) { - while( !fd_is_closed( serve->server_fd ) ){ - usleep(10000); - } + while (!fd_is_closed(serve->server_fd)) { + usleep(10000); + } } /* We've just had an DISCONNECT pair, so we need to shut down * and signal our listener that we can safely take over. */ -void server_control_arrived( struct server *serve ) +void server_control_arrived(struct server *serve) { - debug( "server_control_arrived" ); - NULLCHECK( serve ); + debug("server_control_arrived"); + NULLCHECK(serve); - if ( !serve->success ) { - serve->success = 1; - serve_signal_close( serve ); - } + if (!serve->success) { + serve->success = 1; + serve_signal_close(serve); + } } -void flexnbd_stop_control( struct flexnbd * flexnbd ); +void flexnbd_stop_control(struct flexnbd *flexnbd); /** Closes sockets, frees memory and waits for all client threads to finish */ -void serve_cleanup(struct server* params, - int fatal __attribute__ ((unused)) ) +void serve_cleanup(struct server *params, + int fatal __attribute__ ((unused))) { - NULLCHECK( params ); - void* status; + NULLCHECK(params); + void *status; - info("cleaning up"); + info("cleaning up"); - if (params->server_fd){ close(params->server_fd); } + if (params->server_fd) { + close(params->server_fd); + } - /* need to stop background build if we're killed very early on */ - pthread_cancel(params->allocation_map_builder_thread); - pthread_join(params->allocation_map_builder_thread, &status); + /* need to stop background build if we're killed very early on */ + pthread_cancel(params->allocation_map_builder_thread); + pthread_join(params->allocation_map_builder_thread, &status); - int need_mirror_lock; - need_mirror_lock = !server_start_mirror_locked( params ); + int need_mirror_lock; + need_mirror_lock = !server_start_mirror_locked(params); - if ( need_mirror_lock ) { server_lock_start_mirror( params ); } - { - if ( server_is_mirroring( params ) ) { - server_abandon_mirror( params ); - } - server_prevent_mirror_start( params ); + if (need_mirror_lock) { + server_lock_start_mirror(params); + } + { + if (server_is_mirroring(params)) { + server_abandon_mirror(params); } - if ( need_mirror_lock ) { server_unlock_start_mirror( params ); } + server_prevent_mirror_start(params); + } + if (need_mirror_lock) { + server_unlock_start_mirror(params); + } - server_join_clients( params ); + server_join_clients(params); - if (params->allocation_map) { - bitset_free( params->allocation_map ); - } + if (params->allocation_map) { + bitset_free(params->allocation_map); + } - if ( server_start_mirror_locked( params ) ) { - server_unlock_start_mirror( params ); - } + if (server_start_mirror_locked(params)) { + server_unlock_start_mirror(params); + } - if ( server_acl_locked( params ) ) { - server_unlock_acl( params ); - } + if (server_acl_locked(params)) { + server_unlock_acl(params); + } - /* if( params->flexnbd ) { */ - /* if ( params->flexnbd->control ) { */ - /* flexnbd_stop_control( params->flexnbd ); */ - /* } */ - /* flexnbd_destroy( params->flexnbd ); */ - /* } */ + /* if( params->flexnbd ) { */ + /* if ( params->flexnbd->control ) { */ + /* flexnbd_stop_control( params->flexnbd ); */ + /* } */ + /* flexnbd_destroy( params->flexnbd ); */ + /* } */ - /* server_destroy( params ); */ + /* server_destroy( params ); */ - debug( "Cleanup done"); + debug("Cleanup done"); } -int server_is_in_control( struct server *serve ) +int server_is_in_control(struct server *serve) { - NULLCHECK( serve ); - return serve->success; + NULLCHECK(serve); + return serve->success; } -int server_is_mirroring( struct server * serve ) +int server_is_mirroring(struct server *serve) { - NULLCHECK( serve ); - return !!serve->mirror_super; + NULLCHECK(serve); + return ! !serve->mirror_super; } -uint64_t server_mirror_bytes_remaining( struct server * serve ) +uint64_t server_mirror_bytes_remaining(struct server * serve) { - if ( server_is_mirroring( serve ) ) { - uint64_t bytes_to_xfer = - bitset_stream_queued_bytes( serve->allocation_map, BITSET_STREAM_SET ) + - ( serve->size - serve->mirror->offset ); + if (server_is_mirroring(serve)) { + uint64_t bytes_to_xfer = + bitset_stream_queued_bytes(serve->allocation_map, + BITSET_STREAM_SET) + (serve->size - + serve-> + mirror-> + offset); - return bytes_to_xfer; - } + return bytes_to_xfer; + } - return 0; + return 0; } /* Given historic bps measurements and number of bytes left to transfer, give @@ -889,82 +907,82 @@ uint64_t server_mirror_bytes_remaining( struct server * serve ) * complete, assuming no new bytes are written. */ -uint64_t server_mirror_eta( struct server * serve ) +uint64_t server_mirror_eta(struct server * serve) { - if ( server_is_mirroring( serve ) ) { - uint64_t bytes_to_xfer = server_mirror_bytes_remaining( serve ); - return bytes_to_xfer / ( server_mirror_bps( serve ) + 1 ); - } + if (server_is_mirroring(serve)) { + uint64_t bytes_to_xfer = server_mirror_bytes_remaining(serve); + return bytes_to_xfer / (server_mirror_bps(serve) + 1); + } - return 0; + return 0; } -uint64_t server_mirror_bps( struct server * serve ) +uint64_t server_mirror_bps(struct server * serve) { - if ( server_is_mirroring( serve ) ) { - uint64_t duration_ms = - monotonic_time_ms() - serve->mirror->migration_started; + if (server_is_mirroring(serve)) { + uint64_t duration_ms = + monotonic_time_ms() - serve->mirror->migration_started; - return serve->mirror->all_dirty / ( ( duration_ms / 1000 ) + 1 ); - } + return serve->mirror->all_dirty / ((duration_ms / 1000) + 1); + } - return 0; + return 0; } -void mirror_super_destroy( struct mirror_super * super ); +void mirror_super_destroy(struct mirror_super *super); /* This must only be called with the start_mirror lock held */ -void server_abandon_mirror( struct server * serve ) +void server_abandon_mirror(struct server *serve) { - NULLCHECK( serve ); - if ( serve->mirror_super ) { - /* FIXME: AWOOGA! RACE! - * We can set abandon_signal after mirror_super has checked it, but - * before the reset. However, mirror_reset doesn't clear abandon_signal - * so it'll just terminate early on the next pass. */ - ERROR_UNLESS( - self_pipe_signal( serve->mirror->abandon_signal ), - "Failed to signal abandon to mirror" - ); + NULLCHECK(serve); + if (serve->mirror_super) { + /* FIXME: AWOOGA! RACE! + * We can set abandon_signal after mirror_super has checked it, but + * before the reset. However, mirror_reset doesn't clear abandon_signal + * so it'll just terminate early on the next pass. */ + ERROR_UNLESS(self_pipe_signal(serve->mirror->abandon_signal), + "Failed to signal abandon to mirror"); - pthread_t tid = serve->mirror_super->thread; - pthread_join( tid, NULL ); - debug( "Mirror thread %p pthread_join returned", tid ); + pthread_t tid = serve->mirror_super->thread; + pthread_join(tid, NULL); + debug("Mirror thread %p pthread_join returned", tid); - server_allow_mirror_start( serve ); - mirror_super_destroy( serve->mirror_super ); + server_allow_mirror_start(serve); + mirror_super_destroy(serve->mirror_super); - serve->mirror = NULL; - serve->mirror_super = NULL; + serve->mirror = NULL; + serve->mirror_super = NULL; - debug( "Mirror supervisor done." ); - } + debug("Mirror supervisor done."); + } } -int server_default_deny( struct server * serve ) +int server_default_deny(struct server *serve) { - NULLCHECK( serve ); - return acl_default_deny( serve->acl ); + NULLCHECK(serve); + return acl_default_deny(serve->acl); } /** Full lifecycle of the server */ -int do_serve( struct server* params, struct self_pipe * open_signal ) +int do_serve(struct server *params, struct self_pipe *open_signal) { - NULLCHECK( params ); + NULLCHECK(params); - int success; + int success; - error_set_handler((cleanup_handler*) serve_cleanup, params); - serve_open_server_socket(params); + error_set_handler((cleanup_handler *) serve_cleanup, params); + serve_open_server_socket(params); - /* Only signal that we are open for business once the server - socket is open */ - if ( NULL != open_signal ) { self_pipe_signal( open_signal ); } + /* Only signal that we are open for business once the server + socket is open */ + if (NULL != open_signal) { + self_pipe_signal(open_signal); + } - serve_init_allocation_map(params); - serve_accept_loop(params); - success = params->success; - serve_cleanup(params, 0); + serve_init_allocation_map(params); + serve_accept_loop(params); + success = params->success; + serve_cleanup(params, 0); - return success; + return success; } diff --git a/src/server/serve.h b/src/server/serve.h index 1b697f2..f94e34f 100644 --- a/src/server/serve.h +++ b/src/server/serve.h @@ -3,20 +3,20 @@ #include #include -#include /* for sig_atomic_t */ +#include /* for sig_atomic_t */ #include "flexnbd.h" #include "parse.h" #include "acl.h" -static const int block_allocation_resolution = 4096;//128<<10; +static const int block_allocation_resolution = 4096; //128<<10; struct client_tbl_entry { - pthread_t thread; - union mysockaddr address; - struct client * client; + pthread_t thread; + union mysockaddr address; + struct client *client; }; @@ -25,146 +25,143 @@ struct client_tbl_entry { #define CLIENT_KEEPALIVE_INTVL 10 #define CLIENT_KEEPALIVE_PROBES 3 struct server { - /* The flexnbd wrapper this server is attached to */ - struct flexnbd * flexnbd; + /* The flexnbd wrapper this server is attached to */ + struct flexnbd *flexnbd; /** address/port to bind to */ - union mysockaddr bind_to; + union mysockaddr bind_to; /** (static) file name to serve */ - char* filename; + char *filename; /** TCP backlog for listen() */ - int tcp_backlog; + int tcp_backlog; /** (static) file name of UNIX control socket (or NULL if none) */ - char* control_socket_name; + char *control_socket_name; /** size of file */ - uint64_t size; + uint64_t size; /** to interrupt accept loop and clients, write() to close_signal[1] */ - struct self_pipe * close_signal; + struct self_pipe *close_signal; /** access control list */ - struct acl * acl; + struct acl *acl; /** acl_updated_signal will be signalled after the acl struct * has been replaced */ - struct self_pipe * acl_updated_signal; + struct self_pipe *acl_updated_signal; - /* Claimed around any updates to the ACL. */ - struct flexthread_mutex * l_acl; + /* Claimed around any updates to the ACL. */ + struct flexthread_mutex *l_acl; - /* Claimed around starting a mirror so that it doesn't race with - * shutting down on a SIGTERM. */ - struct flexthread_mutex * l_start_mirror; + /* Claimed around starting a mirror so that it doesn't race with + * shutting down on a SIGTERM. */ + struct flexthread_mutex *l_start_mirror; - struct mirror* mirror; - struct mirror_super * mirror_super; - /* This is used to stop the mirror from starting after we - * receive a SIGTERM */ - int mirror_can_start; + struct mirror *mirror; + struct mirror_super *mirror_super; + /* This is used to stop the mirror from starting after we + * receive a SIGTERM */ + int mirror_can_start; - int server_fd; - int control_fd; + int server_fd; + int control_fd; - /* the allocation_map keeps track of which blocks in the backing file - * have been allocated, or part-allocated on disc, with unallocated - * blocks presumed to contain zeroes (i.e. represented as sparse files - * by the filesystem). We can use this information when receiving - * incoming writes, and avoid writing zeroes to unallocated sections - * of the file which would needlessly increase disc usage. This - * 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 - * blocks can never become unallocated again, as is the case with ext3 - * at least). - */ - struct bitset * allocation_map; - /* when starting up, this thread builds the allocation_map */ - pthread_t allocation_map_builder_thread; + /* the allocation_map keeps track of which blocks in the backing file + * have been allocated, or part-allocated on disc, with unallocated + * blocks presumed to contain zeroes (i.e. represented as sparse files + * by the filesystem). We can use this information when receiving + * incoming writes, and avoid writing zeroes to unallocated sections + * of the file which would needlessly increase disc usage. This + * 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 + * blocks can never become unallocated again, as is the case with ext3 + * at least). + */ + struct bitset *allocation_map; + /* when starting up, this thread builds the allocation_map */ + pthread_t allocation_map_builder_thread; - /* when the thread has finished, it sets this to 1 */ - volatile sig_atomic_t allocation_map_built; - volatile sig_atomic_t allocation_map_not_built; + /* when the thread has finished, it sets this to 1 */ + volatile sig_atomic_t allocation_map_built; + volatile sig_atomic_t allocation_map_not_built; - int max_nbd_clients; - struct client_tbl_entry *nbd_client; + int max_nbd_clients; + struct client_tbl_entry *nbd_client; /** Should clients use the killswitch? */ - int use_killswitch; + int use_killswitch; /** If this isn't set, newly accepted clients will be closed immediately */ - int allow_new_clients; + int allow_new_clients; - /* Marker for whether this server has control over the data in - * the file, or if we're waiting to receive it from an inbound - * migration which hasn't yet finished. - * - * It's the value which controls the exit status of a serve or - * listen process. - */ - int success; + /* Marker for whether this server has control over the data in + * the file, or if we're waiting to receive it from an inbound + * migration which hasn't yet finished. + * + * It's the value which controls the exit status of a serve or + * listen process. + */ + int success; }; -struct server * server_create( - struct flexnbd * flexnbd, - char* s_ip_address, - char* s_port, - char* s_file, - int default_deny, - int acl_entries, - char** s_acl_entries, - int max_nbd_clients, - int use_killswitch, - int success ); -void server_destroy( struct server * ); -int server_is_closed(struct server* serve); -void serve_signal_close( struct server *serve ); -void serve_wait_for_close( struct server * serve ); -void server_replace_acl( struct server *serve, struct acl * acl); -void server_control_arrived( struct server *serve ); -int server_is_in_control( struct server *serve ); -int server_default_deny( struct server * serve ); -int server_acl_locked( struct server * serve ); -void server_lock_acl( struct server *serve ); -void server_unlock_acl( struct server *serve ); -void server_lock_start_mirror( struct server *serve ); -void server_unlock_start_mirror( struct server *serve ); -int server_is_mirroring( struct server * serve ); +struct server *server_create(struct flexnbd *flexnbd, + char *s_ip_address, + char *s_port, + char *s_file, + int default_deny, + int acl_entries, + char **s_acl_entries, + int max_nbd_clients, + int use_killswitch, int success); +void server_destroy(struct server *); +int server_is_closed(struct server *serve); +void serve_signal_close(struct server *serve); +void serve_wait_for_close(struct server *serve); +void server_replace_acl(struct server *serve, struct acl *acl); +void server_control_arrived(struct server *serve); +int server_is_in_control(struct server *serve); +int server_default_deny(struct server *serve); +int server_acl_locked(struct server *serve); +void server_lock_acl(struct server *serve); +void server_unlock_acl(struct server *serve); +void server_lock_start_mirror(struct server *serve); +void server_unlock_start_mirror(struct server *serve); +int server_is_mirroring(struct server *serve); -uint64_t server_mirror_bytes_remaining( struct server * serve ); -uint64_t server_mirror_eta( struct server * serve ); -uint64_t server_mirror_bps( struct server * serve ); +uint64_t server_mirror_bytes_remaining(struct server *serve); +uint64_t server_mirror_eta(struct server *serve); +uint64_t server_mirror_bps(struct server *serve); -void server_abandon_mirror( struct server * serve ); -void server_prevent_mirror_start( struct server *serve ); -void server_allow_mirror_start( struct server *serve ); -int server_mirror_can_start( struct server *serve ); +void server_abandon_mirror(struct server *serve); +void server_prevent_mirror_start(struct server *serve); +void server_allow_mirror_start(struct server *serve); +int server_mirror_can_start(struct server *serve); /* These three functions are used by mirror around the final pass, to close * existing clients and prevent new ones from being around */ -void server_forbid_new_clients( struct server *serve ); -void server_close_clients( struct server *serve ); -void server_join_clients( struct server *serve ); -void server_allow_new_clients( struct server *serve ); +void server_forbid_new_clients(struct server *serve); +void server_close_clients(struct server *serve); +void server_join_clients(struct server *serve); +void server_allow_new_clients(struct server *serve); /* Returns a count (ish) of the number of currently-running client threads */ -int server_count_clients( struct server *params ); +int server_count_clients(struct server *params); -void server_unlink( struct server * serve ); +void server_unlink(struct server *serve); -int do_serve( struct server *, struct self_pipe * ); +int do_serve(struct server *, struct self_pipe *); struct mode_readwrite_params { - union mysockaddr connect_to; - union mysockaddr connect_from; + union mysockaddr connect_to; + union mysockaddr connect_from; - uint64_t from; - uint32_t len; + uint64_t from; + uint32_t len; - int data_fd; - int client; + int data_fd; + int client; }; #endif - diff --git a/src/server/status.c b/src/server/status.c index 530bd7b..937e9fb 100644 --- a/src/server/status.c +++ b/src/server/status.c @@ -2,41 +2,44 @@ #include "serve.h" #include "util.h" -struct status * status_create( struct server * serve ) +struct status *status_create(struct server *serve) { - NULLCHECK( serve ); - struct status * status; + NULLCHECK(serve); + struct status *status; - status = xmalloc( sizeof( struct status ) ); - status->pid = getpid(); - status->size = serve->size; - status->has_control = serve->success; + status = xmalloc(sizeof(struct status)); + status->pid = getpid(); + status->size = serve->size; + status->has_control = serve->success; - status->clients_allowed = serve->allow_new_clients; - status->num_clients = server_count_clients( serve ); + status->clients_allowed = serve->allow_new_clients; + status->num_clients = server_count_clients(serve); - server_lock_start_mirror( serve ); + server_lock_start_mirror(serve); - status->is_mirroring = NULL != serve->mirror; - if ( status->is_mirroring ) { - status->migration_duration = monotonic_time_ms(); + status->is_mirroring = NULL != serve->mirror; + if (status->is_mirroring) { + status->migration_duration = monotonic_time_ms(); - if ( ( serve->mirror->migration_started ) < status->migration_duration ) { - status->migration_duration -= serve->mirror->migration_started; - } else { - status->migration_duration = 0; - } - status->migration_duration /= 1000; - status->migration_speed = server_mirror_bps( serve ); - status->migration_speed_limit = serve->mirror->max_bytes_per_second; - - status->migration_seconds_left = server_mirror_eta( serve ); - status->migration_bytes_left = server_mirror_bytes_remaining( serve ); + if ((serve->mirror->migration_started) < + status->migration_duration) { + status->migration_duration -= serve->mirror->migration_started; + } else { + status->migration_duration = 0; } + status->migration_duration /= 1000; + status->migration_speed = server_mirror_bps(serve); + status->migration_speed_limit = + serve->mirror->max_bytes_per_second; - server_unlock_start_mirror( serve ); + status->migration_seconds_left = server_mirror_eta(serve); + status->migration_bytes_left = + server_mirror_bytes_remaining(serve); + } - return status; + server_unlock_start_mirror(serve); + + return status; } @@ -48,33 +51,32 @@ struct status * status_create( struct server * serve ) #define PRINT_UINT64( var ) \ do{dprintf( fd, #var "=%"PRIu64" ", status->var );}while(0) -int status_write( struct status * status, int fd ) +int status_write(struct status *status, int fd) { - PRINT_INT( pid ); - PRINT_UINT64( size ); - PRINT_BOOL( is_mirroring ); - PRINT_BOOL( clients_allowed ); - PRINT_INT( num_clients ); - PRINT_BOOL( has_control ); + PRINT_INT(pid); + PRINT_UINT64(size); + PRINT_BOOL(is_mirroring); + PRINT_BOOL(clients_allowed); + PRINT_INT(num_clients); + PRINT_BOOL(has_control); - if ( status->is_mirroring ) { - PRINT_UINT64( migration_speed ); - PRINT_UINT64( migration_duration ); - PRINT_UINT64( migration_seconds_left ); - PRINT_UINT64( migration_bytes_left ); - if ( status->migration_speed_limit < UINT64_MAX ) { - PRINT_UINT64( migration_speed_limit ); - }; - } + if (status->is_mirroring) { + PRINT_UINT64(migration_speed); + PRINT_UINT64(migration_duration); + PRINT_UINT64(migration_seconds_left); + PRINT_UINT64(migration_bytes_left); + if (status->migration_speed_limit < UINT64_MAX) { + PRINT_UINT64(migration_speed_limit); + }; + } - dprintf(fd, "\n"); - return 1; + dprintf(fd, "\n"); + return 1; } -void status_destroy( struct status * status ) +void status_destroy(struct status *status) { - NULLCHECK( status ); - free( status ); + NULLCHECK(status); + free(status); } - diff --git a/src/server/status.h b/src/server/status.h index 068571b..642e71b 100644 --- a/src/server/status.h +++ b/src/server/status.h @@ -75,30 +75,29 @@ #include struct status { - pid_t pid; - uint64_t size; - int has_control; - int clients_allowed; - int num_clients; - int is_mirroring; + pid_t pid; + uint64_t size; + int has_control; + int clients_allowed; + int num_clients; + int is_mirroring; - uint64_t migration_duration; - uint64_t migration_speed; - uint64_t migration_speed_limit; - uint64_t migration_seconds_left; - uint64_t migration_bytes_left; + uint64_t migration_duration; + uint64_t migration_speed; + uint64_t migration_speed_limit; + uint64_t migration_seconds_left; + uint64_t migration_bytes_left; }; /** Create a status object for the given server. */ -struct status * status_create( struct server * ); +struct status *status_create(struct server *); /** Output the given status object to the given file descriptot */ -int status_write( struct status *, int fd ); +int status_write(struct status *, int fd); /** Free the status object */ -void status_destroy( struct status * ); +void status_destroy(struct status *); #endif - diff --git a/tests/unit/check_acl.c b/tests/unit/check_acl.c index bb12f81..6aac7ea 100644 --- a/tests/unit/check_acl.c +++ b/tests/unit/check_acl.c @@ -4,226 +4,221 @@ #include "acl.h" #include "util.h" -START_TEST( test_null_acl ) +START_TEST(test_null_acl) { - struct acl *acl = acl_create( 0,NULL, 0 ); + struct acl *acl = acl_create(0, NULL, 0); - fail_if( NULL == acl, "No acl alloced." ); - fail_unless( 0 == acl->len, "Incorrect length" ); + fail_if(NULL == acl, "No acl alloced."); + fail_unless(0 == acl->len, "Incorrect length"); } -END_TEST - -START_TEST( test_parses_single_line ) +END_TEST START_TEST(test_parses_single_line) { - char *lines[] = {"127.0.0.1"}; - struct acl * acl = acl_create( 1, lines, 0 ); + char *lines[] = { "127.0.0.1" }; + struct acl *acl = acl_create(1, lines, 0); - fail_unless( 1 == acl->len, "Incorrect length." ); - fail_if( NULL == acl->entries, "No entries present." ); + fail_unless(1 == acl->len, "Incorrect length."); + fail_if(NULL == acl->entries, "No entries present."); } -END_TEST -START_TEST( test_parses_multiple_lines ) +END_TEST START_TEST(test_parses_multiple_lines) { - char *lines[] = {"127.0.0.1", "::1"}; - struct acl * acl = acl_create( 2, lines, 0 ); - union mysockaddr e0, e1; + char *lines[] = { "127.0.0.1", "::1" }; + struct acl *acl = acl_create(2, lines, 0); + union mysockaddr e0, e1; - parse_ip_to_sockaddr( &e0.generic, lines[0] ); - parse_ip_to_sockaddr( &e1.generic, lines[1] ); + parse_ip_to_sockaddr(&e0.generic, lines[0]); + parse_ip_to_sockaddr(&e1.generic, lines[1]); - fail_unless( acl->len == 2, "Multiple lines not parsed" ); + fail_unless(acl->len == 2, "Multiple lines not parsed"); - struct ip_and_mask *entry; - entry = &(*acl->entries)[0]; - fail_unless(entry->ip.family == e0.family, "entry 0 has wrong family!"); - entry = &(*acl->entries)[1]; - fail_unless(entry->ip.family == e1.family, "entry 1 has wrong family!"); + struct ip_and_mask *entry; + entry = &(*acl->entries)[0]; + fail_unless(entry->ip.family == e0.family, + "entry 0 has wrong family!"); + entry = &(*acl->entries)[1]; + fail_unless(entry->ip.family == e1.family, + "entry 1 has wrong family!"); } -END_TEST -START_TEST( test_destroy_doesnt_crash ) +END_TEST START_TEST(test_destroy_doesnt_crash) { - char *lines[] = {"127.0.0.1"}; - struct acl * acl = acl_create( 1, lines, 0 ); + char *lines[] = { "127.0.0.1" }; + struct acl *acl = acl_create(1, lines, 0); - acl_destroy( acl ); + acl_destroy(acl); } -END_TEST - -START_TEST( test_includes_single_address ) +END_TEST START_TEST(test_includes_single_address) { - char *lines[] = {"127.0.0.1"}; - struct acl * acl = acl_create( 1, lines, 0 ); - union mysockaddr x; + char *lines[] = { "127.0.0.1" }; + struct acl *acl = acl_create(1, lines, 0); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "127.0.0.1" ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.1"); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); } + END_TEST - -START_TEST( test_includes_single_address_when_netmask_specified_ipv4 ) +START_TEST(test_includes_single_address_when_netmask_specified_ipv4) { - char *lines[] = {"127.0.0.1/24"}; - struct acl * acl = acl_create( 1, lines, 0 ); - union mysockaddr x; + char *lines[] = { "127.0.0.1/24" }; + struct acl *acl = acl_create(1, lines, 0); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "127.0.0.0" ); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.0"); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); - parse_ip_to_sockaddr( &x.generic, "127.0.0.1" ); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.1"); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); - parse_ip_to_sockaddr( &x.generic, "127.0.0.255" ); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.255"); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); } + END_TEST - -START_TEST( test_includes_single_address_when_netmask_specified_ipv6 ) +START_TEST(test_includes_single_address_when_netmask_specified_ipv6) { - char *lines[] = {"fe80::/10"}; - struct acl * acl = acl_create( 1, lines, 0 ); - union mysockaddr x; + char *lines[] = { "fe80::/10" }; + struct acl *acl = acl_create(1, lines, 0); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "fe80::1" ); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + parse_ip_to_sockaddr(&x.generic, "fe80::1"); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); - parse_ip_to_sockaddr( &x.generic, "fe80::2" ); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + parse_ip_to_sockaddr(&x.generic, "fe80::2"); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); - parse_ip_to_sockaddr( &x.generic, "fe80:ffff:ffff::ffff" ); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + parse_ip_to_sockaddr(&x.generic, "fe80:ffff:ffff::ffff"); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); } + END_TEST - -START_TEST( test_includes_single_address_when_multiple_entries_exist ) +START_TEST(test_includes_single_address_when_multiple_entries_exist) { - char *lines[] = {"127.0.0.1", "::1"}; - struct acl * acl = acl_create( 2, lines, 0 ); - union mysockaddr e0; - union mysockaddr e1; + char *lines[] = { "127.0.0.1", "::1" }; + struct acl *acl = acl_create(2, lines, 0); + union mysockaddr e0; + union mysockaddr e1; - parse_ip_to_sockaddr( &e0.generic, "127.0.0.1" ); - parse_ip_to_sockaddr( &e1.generic, "::1" ); + parse_ip_to_sockaddr(&e0.generic, "127.0.0.1"); + parse_ip_to_sockaddr(&e1.generic, "::1"); - fail_unless( acl_includes( acl, &e0 ), "Included address 0 wasn't covered" ); - fail_unless( acl_includes( acl, &e1 ), "Included address 1 wasn't covered" ); + fail_unless(acl_includes(acl, &e0), + "Included address 0 wasn't covered"); + fail_unless(acl_includes(acl, &e1), + "Included address 1 wasn't covered"); } -END_TEST - -START_TEST( test_doesnt_include_other_address ) +END_TEST START_TEST(test_doesnt_include_other_address) { - char *lines[] = {"127.0.0.1"}; - struct acl * acl = acl_create( 1, lines, 0 ); - union mysockaddr x; + char *lines[] = { "127.0.0.1" }; + struct acl *acl = acl_create(1, lines, 0); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "127.0.0.2" ); - fail_if( acl_includes( acl, &x ), "Excluded address was covered." ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.2"); + fail_if(acl_includes(acl, &x), "Excluded address was covered."); } + END_TEST - -START_TEST( test_doesnt_include_other_address_when_netmask_specified ) +START_TEST(test_doesnt_include_other_address_when_netmask_specified) { - char *lines[] = {"127.0.0.1/32"}; - struct acl * acl = acl_create( 1, lines, 0 ); - union mysockaddr x; + char *lines[] = { "127.0.0.1/32" }; + struct acl *acl = acl_create(1, lines, 0); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "127.0.0.2" ); - fail_if( acl_includes( acl, &x ), "Excluded address was covered." ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.2"); + fail_if(acl_includes(acl, &x), "Excluded address was covered."); } + END_TEST - -START_TEST( test_doesnt_include_other_address_when_multiple_entries_exist ) +START_TEST(test_doesnt_include_other_address_when_multiple_entries_exist) { - char *lines[] = {"127.0.0.1", "::1"}; - struct acl * acl = acl_create( 2, lines, 0 ); - union mysockaddr e0; - union mysockaddr e1; + char *lines[] = { "127.0.0.1", "::1" }; + struct acl *acl = acl_create(2, lines, 0); + union mysockaddr e0; + union mysockaddr e1; - parse_ip_to_sockaddr( &e0.generic, "127.0.0.2" ); - parse_ip_to_sockaddr( &e1.generic, "::2" ); + parse_ip_to_sockaddr(&e0.generic, "127.0.0.2"); + parse_ip_to_sockaddr(&e1.generic, "::2"); - fail_if( acl_includes( acl, &e0 ), "Excluded address 0 was covered." ); - fail_if( acl_includes( acl, &e1 ), "Excluded address 1 was covered." ); + fail_if(acl_includes(acl, &e0), "Excluded address 0 was covered."); + fail_if(acl_includes(acl, &e1), "Excluded address 1 was covered."); } -END_TEST -START_TEST( test_default_deny_rejects ) +END_TEST START_TEST(test_default_deny_rejects) { - struct acl * acl = acl_create( 0, NULL, 1 ); - union mysockaddr x; + struct acl *acl = acl_create(0, NULL, 1); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "127.0.0.1" ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.1"); - fail_if( acl_includes( acl, &x ), "Default deny accepted." ); + fail_if(acl_includes(acl, &x), "Default deny accepted."); } -END_TEST - -START_TEST( test_default_accept_rejects ) +END_TEST START_TEST(test_default_accept_rejects) { - struct acl * acl = acl_create( 0, NULL, 0 ); - union mysockaddr x; + struct acl *acl = acl_create(0, NULL, 0); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "127.0.0.1" ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.1"); - fail_unless( acl_includes( acl, &x ), "Default accept rejected." ); + fail_unless(acl_includes(acl, &x), "Default accept rejected."); } -END_TEST - -Suite* acl_suite(void) +END_TEST Suite * acl_suite(void) { - Suite *s = suite_create("acl"); - TCase *tc_create = tcase_create("create"); - TCase *tc_includes = tcase_create("includes"); - TCase *tc_destroy = tcase_create("destroy"); + Suite *s = suite_create("acl"); + TCase *tc_create = tcase_create("create"); + TCase *tc_includes = tcase_create("includes"); + TCase *tc_destroy = tcase_create("destroy"); - tcase_add_test(tc_create, test_null_acl); - tcase_add_test(tc_create, test_parses_single_line); - tcase_add_test(tc_includes, test_parses_multiple_lines); + tcase_add_test(tc_create, test_null_acl); + tcase_add_test(tc_create, test_parses_single_line); + tcase_add_test(tc_includes, test_parses_multiple_lines); - tcase_add_test(tc_includes, test_includes_single_address); - tcase_add_test(tc_includes, test_includes_single_address_when_netmask_specified_ipv4); - tcase_add_test(tc_includes, test_includes_single_address_when_netmask_specified_ipv6); + tcase_add_test(tc_includes, test_includes_single_address); + tcase_add_test(tc_includes, + test_includes_single_address_when_netmask_specified_ipv4); + tcase_add_test(tc_includes, + test_includes_single_address_when_netmask_specified_ipv6); - tcase_add_test(tc_includes, test_includes_single_address_when_multiple_entries_exist); + tcase_add_test(tc_includes, + test_includes_single_address_when_multiple_entries_exist); - tcase_add_test(tc_includes, test_doesnt_include_other_address); - tcase_add_test(tc_includes, test_doesnt_include_other_address_when_netmask_specified); - tcase_add_test(tc_includes, test_doesnt_include_other_address_when_multiple_entries_exist); + tcase_add_test(tc_includes, test_doesnt_include_other_address); + tcase_add_test(tc_includes, + test_doesnt_include_other_address_when_netmask_specified); + tcase_add_test(tc_includes, + test_doesnt_include_other_address_when_multiple_entries_exist); - tcase_add_test(tc_includes, test_default_deny_rejects); - tcase_add_test(tc_includes, test_default_accept_rejects); + tcase_add_test(tc_includes, test_default_deny_rejects); + tcase_add_test(tc_includes, test_default_accept_rejects); - tcase_add_test(tc_destroy, test_destroy_doesnt_crash); + tcase_add_test(tc_destroy, test_destroy_doesnt_crash); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_includes); - suite_add_tcase(s, tc_destroy); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_includes); + suite_add_tcase(s, tc_destroy); - return s; + return s; } int main(void) { #ifdef DEBUG - log_level = 0; + log_level = 0; #else - log_level = 2; + log_level = 2; #endif - int number_failed; - Suite *s = acl_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - log_level = 0; - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? 0 : 1; + int number_failed; + Suite *s = acl_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + log_level = 0; + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; } - diff --git a/tests/unit/check_bitset.c b/tests/unit/check_bitset.c index 36b4e55..100e96b 100644 --- a/tests/unit/check_bitset.c +++ b/tests/unit/check_bitset.c @@ -9,492 +9,473 @@ START_TEST(test_bit_set) { - uint64_t num = 0; - bitfield_p bits = (bitfield_p) # + uint64_t num = 0; + bitfield_p bits = (bitfield_p) & num; #define TEST_BIT_SET(bit, newvalue) \ bit_set(bits, (bit)); \ fail_unless(num == (newvalue), "num was %x instead of %x", num, (newvalue)); - TEST_BIT_SET(0, 1); - TEST_BIT_SET(1, 3); - TEST_BIT_SET(2, 7); - TEST_BIT_SET(7, 0x87); - TEST_BIT_SET(63, 0x8000000000000087); + TEST_BIT_SET(0, 1); + TEST_BIT_SET(1, 3); + TEST_BIT_SET(2, 7); + TEST_BIT_SET(7, 0x87); + TEST_BIT_SET(63, 0x8000000000000087); } -END_TEST -START_TEST(test_bit_clear) +END_TEST START_TEST(test_bit_clear) { - uint64_t num = 0xffffffffffffffff; - bitfield_p bits = (bitfield_p) # + uint64_t num = 0xffffffffffffffff; + bitfield_p bits = (bitfield_p) & num; #define TEST_BIT_CLEAR(bit, newvalue) \ bit_clear(bits, (bit)); \ fail_unless(num == (newvalue), "num was %x instead of %x", num, (newvalue)); - TEST_BIT_CLEAR(0, 0xfffffffffffffffe); - TEST_BIT_CLEAR(1, 0xfffffffffffffffc); - TEST_BIT_CLEAR(2, 0xfffffffffffffff8); - TEST_BIT_CLEAR(7, 0xffffffffffffff78); - TEST_BIT_CLEAR(63,0x7fffffffffffff78); + TEST_BIT_CLEAR(0, 0xfffffffffffffffe); + TEST_BIT_CLEAR(1, 0xfffffffffffffffc); + TEST_BIT_CLEAR(2, 0xfffffffffffffff8); + TEST_BIT_CLEAR(7, 0xffffffffffffff78); + TEST_BIT_CLEAR(63, 0x7fffffffffffff78); } -END_TEST -START_TEST(test_bit_tests) +END_TEST START_TEST(test_bit_tests) { - uint64_t num = 0x5555555555555555; - bitfield_p bits = (bitfield_p) # + uint64_t num = 0x5555555555555555; + bitfield_p bits = (bitfield_p) & num; - fail_unless(bit_has_value(bits, 0, 1), "bit_has_value malfunction"); - fail_unless(bit_has_value(bits, 1, 0), "bit_has_value malfunction"); - fail_unless(bit_has_value(bits, 63, 0), "bit_has_value malfunction"); - fail_unless(bit_is_set(bits, 0), "bit_is_set malfunction"); - fail_unless(bit_is_clear(bits, 1), "bit_is_clear malfunction"); - fail_unless(bit_is_set(bits, 62), "bit_is_set malfunction"); - fail_unless(bit_is_clear(bits, 63), "bit_is_clear malfunction"); + fail_unless(bit_has_value(bits, 0, 1), "bit_has_value malfunction"); + fail_unless(bit_has_value(bits, 1, 0), "bit_has_value malfunction"); + fail_unless(bit_has_value(bits, 63, 0), "bit_has_value malfunction"); + fail_unless(bit_is_set(bits, 0), "bit_is_set malfunction"); + fail_unless(bit_is_clear(bits, 1), "bit_is_clear malfunction"); + fail_unless(bit_is_set(bits, 62), "bit_is_set malfunction"); + fail_unless(bit_is_clear(bits, 63), "bit_is_clear malfunction"); } -END_TEST -START_TEST(test_bit_ranges) +END_TEST START_TEST(test_bit_ranges) { - bitfield_word_t buffer[BIT_WORDS_FOR_SIZE(4160)]; - uint64_t *longs = (uint64_t *) buffer; - uint64_t i; + bitfield_word_t buffer[BIT_WORDS_FOR_SIZE(4160)]; + uint64_t *longs = (uint64_t *) buffer; + uint64_t i; - memset(buffer, 0, 4160); + memset(buffer, 0, 4160); - for (i=0; i<64; i++) { - bit_set_range(buffer, i*64, i); - fail_unless( - longs[i] == (1ULL<bits; + map = bitset_alloc(6400, 100); + num = (uint64_t *) map->bits; - bitset_set_range(map,0,50); - ck_assert_int_eq(1, *num); - bitset_set_range(map,99,1); - ck_assert_int_eq(1, *num); - bitset_set_range(map,100,1); - ck_assert_int_eq(3, *num); - bitset_set_range(map,0,800); - ck_assert_int_eq(255, *num); - bitset_set_range(map,1499,2); - ck_assert_int_eq(0xc0ff, *num); - bitset_clear_range(map,1499,2); - ck_assert_int_eq(255, *num); + bitset_set_range(map, 0, 50); + ck_assert_int_eq(1, *num); + bitset_set_range(map, 99, 1); + ck_assert_int_eq(1, *num); + bitset_set_range(map, 100, 1); + ck_assert_int_eq(3, *num); + bitset_set_range(map, 0, 800); + ck_assert_int_eq(255, *num); + bitset_set_range(map, 1499, 2); + ck_assert_int_eq(0xc0ff, *num); + bitset_clear_range(map, 1499, 2); + ck_assert_int_eq(255, *num); - *num = 0; - bitset_set_range(map, 1499, 2); - bitset_clear_range(map, 1300, 200); - ck_assert_int_eq(0x8000, *num); + *num = 0; + bitset_set_range(map, 1499, 2); + bitset_clear_range(map, 1300, 200); + ck_assert_int_eq(0x8000, *num); - *num = 0; - bitset_set_range(map, 0, 6400); - ck_assert_int_eq(0xffffffffffffffff, *num); - bitset_clear_range(map, 3200, 400); - ck_assert_int_eq(0xfffffff0ffffffff, *num); + *num = 0; + bitset_set_range(map, 0, 6400); + ck_assert_int_eq(0xffffffffffffffff, *num); + bitset_clear_range(map, 3200, 400); + ck_assert_int_eq(0xfffffff0ffffffff, *num); } -END_TEST - -START_TEST( test_bitset_set ) +END_TEST START_TEST(test_bitset_set) { - struct bitset * map; - uint64_t run; + struct bitset *map; + uint64_t run; - map = bitset_alloc(64, 1); + map = bitset_alloc(64, 1); - assert_bitset_is( map, 0x0000000000000000 ); - bitset_set( map ); - assert_bitset_is( map, 0xffffffffffffffff ); - bitset_free( map ); + assert_bitset_is(map, 0x0000000000000000); + bitset_set(map); + assert_bitset_is(map, 0xffffffffffffffff); + bitset_free(map); - map = bitset_alloc( 6400, 100 ); - assert_bitset_is( map, 0x0000000000000000 ); - bitset_set( map ); - assert_bitset_is( map, 0xffffffffffffffff ); - bitset_free( map ); + map = bitset_alloc(6400, 100); + assert_bitset_is(map, 0x0000000000000000); + bitset_set(map); + assert_bitset_is(map, 0xffffffffffffffff); + bitset_free(map); - // Now do something large and representative - map = bitset_alloc( 53687091200, 4096 ); - bitset_set( map ); + // Now do something large and representative + map = bitset_alloc(53687091200, 4096); + bitset_set(map); - run = bitset_run_count( map, 0, 53687091200 ); - ck_assert_int_eq( run, 53687091200 ); - bitset_free( map ); + run = bitset_run_count(map, 0, 53687091200); + ck_assert_int_eq(run, 53687091200); + bitset_free(map); } -END_TEST - -START_TEST( test_bitset_clear ) +END_TEST START_TEST(test_bitset_clear) { - struct bitset * map; - uint64_t *num; - uint64_t run; + struct bitset *map; + uint64_t *num; + uint64_t run; - map = bitset_alloc(64, 1); - num = (uint64_t*) map->bits; + map = bitset_alloc(64, 1); + num = (uint64_t *) map->bits; - ck_assert_int_eq( 0x0000000000000000, *num ); - bitset_set( map ); - bitset_clear( map ); - ck_assert_int_eq( 0x0000000000000000, *num ); + ck_assert_int_eq(0x0000000000000000, *num); + bitset_set(map); + bitset_clear(map); + ck_assert_int_eq(0x0000000000000000, *num); - bitset_free( map ); + bitset_free(map); - // Now do something large and representative - map = bitset_alloc( 53687091200, 4096 ); - bitset_set( map ); - bitset_clear( map ); - run = bitset_run_count( map, 0, 53687091200 ); - ck_assert_int_eq( run, 53687091200 ); - bitset_free( map ); + // Now do something large and representative + map = bitset_alloc(53687091200, 4096); + bitset_set(map); + bitset_clear(map); + run = bitset_run_count(map, 0, 53687091200); + ck_assert_int_eq(run, 53687091200); + bitset_free(map); } -END_TEST -START_TEST( test_bitset_set_range ) +END_TEST START_TEST(test_bitset_set_range) { - struct bitset* map = bitset_alloc( 64, 1 ); - assert_bitset_is( map, 0x0000000000000000 ); + struct bitset *map = bitset_alloc(64, 1); + assert_bitset_is(map, 0x0000000000000000); - bitset_set_range( map, 8, 8 ); - assert_bitset_is( map, 0x000000000000ff00 ); + bitset_set_range(map, 8, 8); + assert_bitset_is(map, 0x000000000000ff00); - bitset_clear( map ); - assert_bitset_is( map, 0x0000000000000000 ); - bitset_set_range( map, 0, 0 ); - assert_bitset_is( map, 0x0000000000000000 ); + bitset_clear(map); + assert_bitset_is(map, 0x0000000000000000); + bitset_set_range(map, 0, 0); + assert_bitset_is(map, 0x0000000000000000); - bitset_free( map ); + bitset_free(map); } -END_TEST -START_TEST( test_bitset_clear_range ) +END_TEST START_TEST(test_bitset_clear_range) { - struct bitset* map = bitset_alloc( 64, 1 ); - bitset_set( map ); - assert_bitset_is( map, 0xffffffffffffffff ); + struct bitset *map = bitset_alloc(64, 1); + bitset_set(map); + assert_bitset_is(map, 0xffffffffffffffff); - bitset_clear_range( map, 8, 8 ); - assert_bitset_is( map, 0xffffffffffff00ff ); + bitset_clear_range(map, 8, 8); + assert_bitset_is(map, 0xffffffffffff00ff); - bitset_set( map ); - assert_bitset_is( map, 0xffffffffffffffff ); - bitset_clear_range( map, 0, 0 ); - assert_bitset_is( map, 0xffffffffffffffff ); + bitset_set(map); + assert_bitset_is(map, 0xffffffffffffffff); + bitset_clear_range(map, 0, 0); + assert_bitset_is(map, 0xffffffffffffffff); - bitset_free( map ); + bitset_free(map); } -END_TEST -START_TEST( test_bitset_run_count ) +END_TEST START_TEST(test_bitset_run_count) { - struct bitset* map = bitset_alloc( 64, 1 ); - uint64_t run; + struct bitset *map = bitset_alloc(64, 1); + uint64_t run; - assert_bitset_is( map, 0x0000000000000000 ); + assert_bitset_is(map, 0x0000000000000000); - run = bitset_run_count( map, 0, 64 ); - ck_assert_int_eq( 64, run ); + run = bitset_run_count(map, 0, 64); + ck_assert_int_eq(64, run); - bitset_set_range( map, 0, 32 ); - assert_bitset_is( map, 0x00000000ffffffff ); + bitset_set_range(map, 0, 32); + assert_bitset_is(map, 0x00000000ffffffff); - run = bitset_run_count( map, 0, 64 ); - ck_assert_int_eq( 32, run ); + run = bitset_run_count(map, 0, 64); + ck_assert_int_eq(32, run); - run = bitset_run_count( map, 0, 16 ); - ck_assert_int_eq( 16, run ); + run = bitset_run_count(map, 0, 16); + ck_assert_int_eq(16, run); - run = bitset_run_count( map, 16, 64 ); - ck_assert_int_eq( 16, run ); + run = bitset_run_count(map, 16, 64); + ck_assert_int_eq(16, run); - run = bitset_run_count( map, 31, 64 ); - ck_assert_int_eq( 1, run ); + run = bitset_run_count(map, 31, 64); + ck_assert_int_eq(1, run); - run = bitset_run_count( map, 32, 64 ); - ck_assert_int_eq( 32, run ); + run = bitset_run_count(map, 32, 64); + ck_assert_int_eq(32, run); - run = bitset_run_count( map, 32, 32 ); - ck_assert_int_eq( 32, run ); + run = bitset_run_count(map, 32, 32); + ck_assert_int_eq(32, run); - run = bitset_run_count( map, 32, 16 ); - ck_assert_int_eq( 16, run ); + run = bitset_run_count(map, 32, 16); + ck_assert_int_eq(16, run); - bitset_free( map ); + bitset_free(map); - map = bitset_alloc( 6400, 100 ); - assert_bitset_is( map, 0x0000000000000000 ); + map = bitset_alloc(6400, 100); + assert_bitset_is(map, 0x0000000000000000); - run = bitset_run_count( map, 0, 6400 ); - ck_assert_int_eq( 6400, run ); + run = bitset_run_count(map, 0, 6400); + ck_assert_int_eq(6400, run); - bitset_set_range( map, 0, 3200 ); + bitset_set_range(map, 0, 3200); - run = bitset_run_count( map, 0, 6400 ); - ck_assert_int_eq( 3200, run ); + run = bitset_run_count(map, 0, 6400); + ck_assert_int_eq(3200, run); - run = bitset_run_count( map, 1, 6400 ); - ck_assert_int_eq( 3199, run ); + run = bitset_run_count(map, 1, 6400); + ck_assert_int_eq(3199, run); - run = bitset_run_count( map, 3200, 6400 ); - ck_assert_int_eq( 3200, run ); + run = bitset_run_count(map, 3200, 6400); + ck_assert_int_eq(3200, run); - run = bitset_run_count( map, 6500, 6400 ); - ck_assert_int_eq( 0, run ); - bitset_free( map ); + run = bitset_run_count(map, 6500, 6400); + ck_assert_int_eq(0, run); + bitset_free(map); - // Now do something large and representative - map = bitset_alloc( 53687091200, 4096 ); - bitset_set( map ); - run = bitset_run_count( map, 0, 53687091200 ); - ck_assert_int_eq( run, 53687091200 ); + // Now do something large and representative + map = bitset_alloc(53687091200, 4096); + bitset_set(map); + run = bitset_run_count(map, 0, 53687091200); + ck_assert_int_eq(run, 53687091200); - bitset_free( map ); + bitset_free(map); } -END_TEST -START_TEST( test_bitset_set_range_doesnt_push_to_stream ) +END_TEST START_TEST(test_bitset_set_range_doesnt_push_to_stream) { - struct bitset *map = bitset_alloc( 64, 1 ); - bitset_set_range( map, 0, 64 ); - ck_assert_int_eq( 0, bitset_stream_size( map ) ); - bitset_free( map ); + struct bitset *map = bitset_alloc(64, 1); + bitset_set_range(map, 0, 64); + ck_assert_int_eq(0, bitset_stream_size(map)); + bitset_free(map); } -END_TEST -START_TEST( test_bitset_clear_range_doesnt_push_to_stream ) +END_TEST START_TEST(test_bitset_clear_range_doesnt_push_to_stream) { - struct bitset *map = bitset_alloc( 64, 1 ); - bitset_clear_range( map, 0, 64 ); - ck_assert_int_eq( 0, bitset_stream_size( map ) ); - bitset_free( map ); + struct bitset *map = bitset_alloc(64, 1); + bitset_clear_range(map, 0, 64); + ck_assert_int_eq(0, bitset_stream_size(map)); + bitset_free(map); } -END_TEST -START_TEST(test_bitset_enable_stream) +END_TEST START_TEST(test_bitset_enable_stream) { - struct bitset *map = bitset_alloc( 64, 1 ); - struct bitset_stream_entry result; - memset( &result, 0, sizeof( result ) ); + struct bitset *map = bitset_alloc(64, 1); + struct bitset_stream_entry result; + memset(&result, 0, sizeof(result)); - bitset_enable_stream( map ); + bitset_enable_stream(map); - ck_assert_int_eq( 1, map->stream_enabled ); + ck_assert_int_eq(1, map->stream_enabled); - bitset_stream_dequeue( map, &result ); + bitset_stream_dequeue(map, &result); - ck_assert_int_eq( BITSET_STREAM_ON, result.event ); - ck_assert_int_eq( 0, result.from ); - ck_assert_int_eq( 64, result.len ); + ck_assert_int_eq(BITSET_STREAM_ON, result.event); + ck_assert_int_eq(0, result.from); + ck_assert_int_eq(64, result.len); - bitset_free( map ); + bitset_free(map); } -END_TEST -START_TEST(test_bitset_disable_stream) +END_TEST START_TEST(test_bitset_disable_stream) { - struct bitset *map = bitset_alloc( 64, 1 ); - struct bitset_stream_entry result; - memset( &result, 0, sizeof( result ) ); + struct bitset *map = bitset_alloc(64, 1); + struct bitset_stream_entry result; + memset(&result, 0, sizeof(result)); - bitset_enable_stream( map ); - bitset_disable_stream( map ); + bitset_enable_stream(map); + bitset_disable_stream(map); - ck_assert_int_eq( 0, map->stream_enabled ); - ck_assert_int_eq( 2, bitset_stream_size( map ) ); + ck_assert_int_eq(0, map->stream_enabled); + ck_assert_int_eq(2, bitset_stream_size(map)); - bitset_stream_dequeue( map, NULL ); // ON - bitset_stream_dequeue( map, &result ); // OFF + bitset_stream_dequeue(map, NULL); // ON + bitset_stream_dequeue(map, &result); // OFF - ck_assert_int_eq( BITSET_STREAM_OFF, result.event ); - ck_assert_int_eq( 0, result.from ); - ck_assert_int_eq( 64, result.len ); + ck_assert_int_eq(BITSET_STREAM_OFF, result.event); + ck_assert_int_eq(0, result.from); + ck_assert_int_eq(64, result.len); - bitset_free( map ); + bitset_free(map); } -END_TEST -START_TEST(test_bitset_stream_with_set_range) +END_TEST START_TEST(test_bitset_stream_with_set_range) { - struct bitset *map = bitset_alloc( 64, 1 ); - struct bitset_stream_entry result; - memset( &result, 0, sizeof( result ) ); + struct bitset *map = bitset_alloc(64, 1); + struct bitset_stream_entry result; + memset(&result, 0, sizeof(result)); - bitset_enable_stream( map ); - bitset_set_range( map, 0, 32 ); + bitset_enable_stream(map); + bitset_set_range(map, 0, 32); - ck_assert_int_eq( 2, bitset_stream_size( map ) ); + ck_assert_int_eq(2, bitset_stream_size(map)); - bitset_stream_dequeue( map, NULL ); // ON - bitset_stream_dequeue( map, &result ); // SET + bitset_stream_dequeue(map, NULL); // ON + bitset_stream_dequeue(map, &result); // SET - ck_assert_int_eq( BITSET_STREAM_SET, result.event ); - ck_assert_int_eq( 0, result.from ); - ck_assert_int_eq( 32, result.len ); + ck_assert_int_eq(BITSET_STREAM_SET, result.event); + ck_assert_int_eq(0, result.from); + ck_assert_int_eq(32, result.len); - bitset_free( map ); + bitset_free(map); } -END_TEST -START_TEST(test_bitset_stream_with_clear_range) +END_TEST START_TEST(test_bitset_stream_with_clear_range) { - struct bitset *map = bitset_alloc( 64, 1 ); - struct bitset_stream_entry result; - memset( &result, 0, sizeof( result ) ); + struct bitset *map = bitset_alloc(64, 1); + struct bitset_stream_entry result; + memset(&result, 0, sizeof(result)); - bitset_enable_stream( map ); - bitset_clear_range( map, 0, 32 ); - ck_assert_int_eq( 2, bitset_stream_size( map ) ); + bitset_enable_stream(map); + bitset_clear_range(map, 0, 32); + ck_assert_int_eq(2, bitset_stream_size(map)); - bitset_stream_dequeue( map, NULL ); // ON - bitset_stream_dequeue( map, &result ); // UNSET + bitset_stream_dequeue(map, NULL); // ON + bitset_stream_dequeue(map, &result); // UNSET - ck_assert_int_eq( BITSET_STREAM_UNSET, result.event ); - ck_assert_int_eq( 0, result.from ); - ck_assert_int_eq( 32, result.len ); + ck_assert_int_eq(BITSET_STREAM_UNSET, result.event); + ck_assert_int_eq(0, result.from); + ck_assert_int_eq(32, result.len); - bitset_free( map ); + bitset_free(map); } -END_TEST -START_TEST(test_bitset_stream_size) +END_TEST START_TEST(test_bitset_stream_size) { - struct bitset *map = bitset_alloc( 64, 1 ); - bitset_enable_stream( map ); - bitset_set_range( map, 0, 32 ); - bitset_set_range( map, 16, 32 ); - bitset_set_range( map, 7, 16 ); + struct bitset *map = bitset_alloc(64, 1); + bitset_enable_stream(map); + bitset_set_range(map, 0, 32); + bitset_set_range(map, 16, 32); + bitset_set_range(map, 7, 16); - bitset_clear_range( map, 0, 32 ); - bitset_clear_range( map, 16, 32 ); - bitset_clear_range( map, 48, 16 ); - bitset_disable_stream( map ); + bitset_clear_range(map, 0, 32); + bitset_clear_range(map, 16, 32); + bitset_clear_range(map, 48, 16); + bitset_disable_stream(map); - ck_assert_int_eq( 8, bitset_stream_size( map ) ); + ck_assert_int_eq(8, bitset_stream_size(map)); - bitset_free( map ); + bitset_free(map); } -END_TEST -START_TEST(test_bitset_stream_queued_bytes) +END_TEST START_TEST(test_bitset_stream_queued_bytes) { - struct bitset *map = bitset_alloc( 64, 1 ); - bitset_enable_stream( map ); - bitset_set_range( map, 0, 32 ); - bitset_set_range( map, 16, 32 ); - bitset_set_range( map, 7, 16 ); + struct bitset *map = bitset_alloc(64, 1); + bitset_enable_stream(map); + bitset_set_range(map, 0, 32); + bitset_set_range(map, 16, 32); + bitset_set_range(map, 7, 16); - bitset_clear_range( map, 0, 32 ); - bitset_clear_range( map, 16, 32 ); - bitset_clear_range( map, 48, 16 ); - bitset_clear_range( map, 0, 2 ); - bitset_disable_stream( map ); + bitset_clear_range(map, 0, 32); + bitset_clear_range(map, 16, 32); + bitset_clear_range(map, 48, 16); + bitset_clear_range(map, 0, 2); + bitset_disable_stream(map); - ck_assert_int_eq( 64, bitset_stream_queued_bytes( map, BITSET_STREAM_ON ) ); - ck_assert_int_eq( 80, bitset_stream_queued_bytes( map, BITSET_STREAM_SET ) ); - ck_assert_int_eq( 82, bitset_stream_queued_bytes( map, BITSET_STREAM_UNSET ) ); - ck_assert_int_eq( 64, bitset_stream_queued_bytes( map, BITSET_STREAM_OFF ) ); - bitset_free( map ); + ck_assert_int_eq(64, + bitset_stream_queued_bytes(map, BITSET_STREAM_ON)); + ck_assert_int_eq(80, + bitset_stream_queued_bytes(map, BITSET_STREAM_SET)); + ck_assert_int_eq(82, + bitset_stream_queued_bytes(map, BITSET_STREAM_UNSET)); + ck_assert_int_eq(64, + bitset_stream_queued_bytes(map, BITSET_STREAM_OFF)); + bitset_free(map); } -END_TEST -Suite* bitset_suite(void) +END_TEST Suite * bitset_suite(void) { - Suite *s = suite_create("bitset"); + Suite *s = suite_create("bitset"); - TCase *tc_bit = tcase_create("bit"); - tcase_add_test(tc_bit, test_bit_set); - tcase_add_test(tc_bit, test_bit_clear); - tcase_add_test(tc_bit, test_bit_tests); - tcase_add_test(tc_bit, test_bit_ranges); - tcase_add_test(tc_bit, test_bit_runs); - suite_add_tcase(s, tc_bit); + TCase *tc_bit = tcase_create("bit"); + tcase_add_test(tc_bit, test_bit_set); + tcase_add_test(tc_bit, test_bit_clear); + tcase_add_test(tc_bit, test_bit_tests); + tcase_add_test(tc_bit, test_bit_ranges); + tcase_add_test(tc_bit, test_bit_runs); + suite_add_tcase(s, tc_bit); - TCase *tc_bitset = tcase_create("bitset"); - tcase_add_test(tc_bitset, test_bitset); - tcase_add_test(tc_bitset, test_bitset_set); - tcase_add_test(tc_bitset, test_bitset_clear); - tcase_add_test(tc_bitset, test_bitset_run_count); - tcase_add_test(tc_bitset, test_bitset_set_range); - tcase_add_test(tc_bitset, test_bitset_clear_range); - tcase_add_test(tc_bitset, test_bitset_set_range_doesnt_push_to_stream); - tcase_add_test(tc_bitset, test_bitset_clear_range_doesnt_push_to_stream); - suite_add_tcase(s, tc_bitset); + TCase *tc_bitset = tcase_create("bitset"); + tcase_add_test(tc_bitset, test_bitset); + tcase_add_test(tc_bitset, test_bitset_set); + tcase_add_test(tc_bitset, test_bitset_clear); + tcase_add_test(tc_bitset, test_bitset_run_count); + tcase_add_test(tc_bitset, test_bitset_set_range); + tcase_add_test(tc_bitset, test_bitset_clear_range); + tcase_add_test(tc_bitset, test_bitset_set_range_doesnt_push_to_stream); + tcase_add_test(tc_bitset, + test_bitset_clear_range_doesnt_push_to_stream); + suite_add_tcase(s, tc_bitset); - TCase *tc_bitset_stream = tcase_create("bitset_stream"); - tcase_add_test(tc_bitset_stream, test_bitset_enable_stream); - tcase_add_test(tc_bitset_stream, test_bitset_disable_stream); - tcase_add_test(tc_bitset_stream, test_bitset_stream_with_set_range); - tcase_add_test(tc_bitset_stream, test_bitset_stream_with_clear_range); - tcase_add_test(tc_bitset_stream, test_bitset_stream_size); - tcase_add_test(tc_bitset_stream, test_bitset_stream_queued_bytes); - suite_add_tcase(s, tc_bitset_stream); + TCase *tc_bitset_stream = tcase_create("bitset_stream"); + tcase_add_test(tc_bitset_stream, test_bitset_enable_stream); + tcase_add_test(tc_bitset_stream, test_bitset_disable_stream); + tcase_add_test(tc_bitset_stream, test_bitset_stream_with_set_range); + tcase_add_test(tc_bitset_stream, test_bitset_stream_with_clear_range); + tcase_add_test(tc_bitset_stream, test_bitset_stream_size); + tcase_add_test(tc_bitset_stream, test_bitset_stream_queued_bytes); + suite_add_tcase(s, tc_bitset_stream); - return s; + return s; } int main(void) { - int number_failed; - Suite *s = bitset_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; + int number_failed; + Suite *s = bitset_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; } - diff --git a/tests/unit/check_client.c b/tests/unit/check_client.c index 188db10..3df7a13 100644 --- a/tests/unit/check_client.c +++ b/tests/unit/check_client.c @@ -9,114 +9,104 @@ #include -struct server fake_server = {0}; +struct server fake_server = { 0 }; + #define FAKE_SERVER &fake_server #define FAKE_SOCKET (42) -START_TEST( test_assigns_socket ) +START_TEST(test_assigns_socket) { - struct client * c; + struct client *c; - c = client_create( FAKE_SERVER, FAKE_SOCKET ); + c = client_create(FAKE_SERVER, FAKE_SOCKET); - fail_unless( 42 == c->socket, "Socket wasn't assigned." ); + fail_unless(42 == c->socket, "Socket wasn't assigned."); } -END_TEST - -START_TEST( test_assigns_server ) +END_TEST START_TEST(test_assigns_server) { - struct client * c; - /* can't predict the storage size so we can't allocate one on - * the stack - */ - c = client_create( FAKE_SERVER, FAKE_SOCKET ); + struct client *c; + /* can't predict the storage size so we can't allocate one on + * the stack + */ + c = client_create(FAKE_SERVER, FAKE_SOCKET); - fail_unless( FAKE_SERVER == c->serve, "Serve wasn't assigned." ); + fail_unless(FAKE_SERVER == c->serve, "Serve wasn't assigned."); } -END_TEST - -START_TEST( test_opens_stop_signal ) +END_TEST START_TEST(test_opens_stop_signal) { - struct client *c = client_create( FAKE_SERVER, FAKE_SOCKET ); + struct client *c = client_create(FAKE_SERVER, FAKE_SOCKET); - client_signal_stop( c ); + client_signal_stop(c); - fail_unless( 1 == self_pipe_signal_clear( c->stop_signal ), - "No signal was sent." ); + fail_unless(1 == self_pipe_signal_clear(c->stop_signal), + "No signal was sent."); } -END_TEST +END_TEST int fd_is_closed(int); -int fd_is_closed(int); - -START_TEST( test_closes_stop_signal ) +START_TEST(test_closes_stop_signal) { - struct client *c = client_create( FAKE_SERVER, FAKE_SOCKET ); - int read_fd = c->stop_signal->read_fd; - int write_fd = c->stop_signal->write_fd; + struct client *c = client_create(FAKE_SERVER, FAKE_SOCKET); + int read_fd = c->stop_signal->read_fd; + int write_fd = c->stop_signal->write_fd; - client_destroy( c ); + client_destroy(c); - fail_unless( fd_is_closed( read_fd ), "Stop signal wasn't destroyed." ); - fail_unless( fd_is_closed( write_fd ), "Stop signal wasn't destroyed." ); + fail_unless(fd_is_closed(read_fd), "Stop signal wasn't destroyed."); + fail_unless(fd_is_closed(write_fd), "Stop signal wasn't destroyed."); } -END_TEST - -START_TEST( test_read_request_quits_on_stop_signal ) +END_TEST START_TEST(test_read_request_quits_on_stop_signal) { - int fds[2]; - struct nbd_request nbdr; - pipe( fds ); - struct client *c = client_create( FAKE_SERVER, fds[0] ); - - client_signal_stop( c ); + int fds[2]; + struct nbd_request nbdr; + pipe(fds); + struct client *c = client_create(FAKE_SERVER, fds[0]); - int client_serve_request( struct client *); - fail_unless( 1 == client_serve_request( c ), "Didn't quit on stop." ); + client_signal_stop(c); - close( fds[0] ); - close( fds[1] ); + int client_serve_request(struct client *); + fail_unless(1 == client_serve_request(c), "Didn't quit on stop."); + + close(fds[0]); + close(fds[1]); } -END_TEST - -Suite *client_suite(void) +END_TEST Suite * client_suite(void) { - Suite *s = suite_create("client"); + Suite *s = suite_create("client"); - TCase *tc_create = tcase_create("create"); - TCase *tc_signal = tcase_create("signal"); - TCase *tc_destroy = tcase_create("destroy"); + TCase *tc_create = tcase_create("create"); + TCase *tc_signal = tcase_create("signal"); + TCase *tc_destroy = tcase_create("destroy"); - tcase_add_test(tc_create, test_assigns_socket); - tcase_add_test(tc_create, test_assigns_server); + tcase_add_test(tc_create, test_assigns_socket); + tcase_add_test(tc_create, test_assigns_server); - tcase_add_test(tc_signal, test_opens_stop_signal); - tcase_add_test(tc_signal, test_read_request_quits_on_stop_signal); + tcase_add_test(tc_signal, test_opens_stop_signal); + tcase_add_test(tc_signal, test_read_request_quits_on_stop_signal); - tcase_add_test( tc_destroy, test_closes_stop_signal ); + tcase_add_test(tc_destroy, test_closes_stop_signal); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_signal); - suite_add_tcase(s, tc_destroy); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_signal); + suite_add_tcase(s, tc_destroy); - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = client_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; -} + int number_failed; + Suite *s = client_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; +} diff --git a/tests/unit/check_control.c b/tests/unit/check_control.c index fbb2ec9..2afd6dc 100644 --- a/tests/unit/check_control.c +++ b/tests/unit/check_control.c @@ -4,39 +4,36 @@ #include -START_TEST( test_assigns_sock_name ) +START_TEST(test_assigns_sock_name) { - struct flexnbd flexnbd = {0}; - char csn[] = "foobar"; + struct flexnbd flexnbd = { 0 }; + char csn[] = "foobar"; - struct control * control = control_create(&flexnbd, csn ); + struct control *control = control_create(&flexnbd, csn); - fail_unless( csn == control->socket_name, "Socket name not assigned" ); + fail_unless(csn == control->socket_name, "Socket name not assigned"); } -END_TEST - -Suite *control_suite(void) +END_TEST Suite * control_suite(void) { - Suite *s = suite_create("control"); + Suite *s = suite_create("control"); - TCase *tc_create = tcase_create("create"); + TCase *tc_create = tcase_create("create"); - tcase_add_test(tc_create, test_assigns_sock_name); - suite_add_tcase( s, tc_create ); + tcase_add_test(tc_create, test_assigns_sock_name); + suite_add_tcase(s, tc_create); - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = control_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; -} + int number_failed; + Suite *s = control_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; +} diff --git a/tests/unit/check_flexnbd.c b/tests/unit/check_flexnbd.c index bff82e4..6c45814 100644 --- a/tests/unit/check_flexnbd.c +++ b/tests/unit/check_flexnbd.c @@ -3,42 +3,38 @@ #include -START_TEST( test_listening_assigns_sock ) +START_TEST(test_listening_assigns_sock) { - struct flexnbd * flexnbd = flexnbd_create_listening( - "127.0.0.1", - "4777", - "fakefile", - "fakesock", - 0, - 0, - NULL ); - fail_if( NULL == flexnbd->control->socket_name, "No socket was copied" ); + struct flexnbd *flexnbd = flexnbd_create_listening("127.0.0.1", + "4777", + "fakefile", + "fakesock", + 0, + 0, + NULL); + fail_if(NULL == flexnbd->control->socket_name, "No socket was copied"); } -END_TEST - -Suite *flexnbd_suite(void) +END_TEST Suite * flexnbd_suite(void) { - Suite *s = suite_create("flexnbd"); + Suite *s = suite_create("flexnbd"); - TCase *tc_create = tcase_create("create"); + TCase *tc_create = tcase_create("create"); - tcase_add_test(tc_create, test_listening_assigns_sock); - suite_add_tcase( s, tc_create ); + tcase_add_test(tc_create, test_listening_assigns_sock); + suite_add_tcase(s, tc_create); - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = flexnbd_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; -} + int number_failed; + Suite *s = flexnbd_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; +} diff --git a/tests/unit/check_flexthread.c b/tests/unit/check_flexthread.c index 092ab5b..d6535a9 100644 --- a/tests/unit/check_flexthread.c +++ b/tests/unit/check_flexthread.c @@ -4,59 +4,57 @@ #include -START_TEST( test_mutex_create ) +START_TEST(test_mutex_create) { - struct flexthread_mutex * ftm = flexthread_mutex_create(); - NULLCHECK( ftm ); - flexthread_mutex_destroy( ftm ); + struct flexthread_mutex *ftm = flexthread_mutex_create(); + NULLCHECK(ftm); + flexthread_mutex_destroy(ftm); } -END_TEST - -START_TEST( test_mutex_lock ) +END_TEST START_TEST(test_mutex_lock) { - struct flexthread_mutex * ftm = flexthread_mutex_create(); + struct flexthread_mutex *ftm = flexthread_mutex_create(); - fail_if( flexthread_mutex_held( ftm ), "Flexthread_mutex is held before lock" ); - flexthread_mutex_lock( ftm ); - fail_unless( flexthread_mutex_held( ftm ), "Flexthread_mutex is not held inside lock" ); - flexthread_mutex_unlock( ftm ); - fail_if( flexthread_mutex_held( ftm ), "Flexthread_mutex is held after unlock" ); + fail_if(flexthread_mutex_held(ftm), + "Flexthread_mutex is held before lock"); + flexthread_mutex_lock(ftm); + fail_unless(flexthread_mutex_held(ftm), + "Flexthread_mutex is not held inside lock"); + flexthread_mutex_unlock(ftm); + fail_if(flexthread_mutex_held(ftm), + "Flexthread_mutex is held after unlock"); - flexthread_mutex_destroy( ftm ); + flexthread_mutex_destroy(ftm); } -END_TEST - -Suite* flexthread_suite(void) +END_TEST Suite * flexthread_suite(void) { - Suite *s = suite_create("flexthread"); - TCase *tc_create = tcase_create("create"); - TCase *tc_destroy = tcase_create("destroy"); + Suite *s = suite_create("flexthread"); + TCase *tc_create = tcase_create("create"); + TCase *tc_destroy = tcase_create("destroy"); - tcase_add_test( tc_create, test_mutex_create ); - tcase_add_test( tc_create, test_mutex_lock ); + tcase_add_test(tc_create, test_mutex_create); + tcase_add_test(tc_create, test_mutex_lock); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_destroy); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_destroy); - return s; + return s; } int main(void) { #ifdef DEBUG - log_level = 0; + log_level = 0; #else - log_level = 2; + log_level = 2; #endif - int number_failed; - Suite *s = flexthread_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - log_level = 0; - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? 0 : 1; + int number_failed; + Suite *s = flexthread_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + log_level = 0; + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; } - diff --git a/tests/unit/check_ioutil.c b/tests/unit/check_ioutil.c index b1f26a5..dbe75ab 100644 --- a/tests/unit/check_ioutil.c +++ b/tests/unit/check_ioutil.c @@ -2,133 +2,125 @@ #include -START_TEST( test_read_until_newline_returns_line_length_plus_null ) +START_TEST(test_read_until_newline_returns_line_length_plus_null) { - int fds[2]; - int nread; - char buf[5] = {0}; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = { 0 }; + pipe(fds); - write( fds[1], "1234\n", 5 ); - - nread = read_until_newline( fds[0], buf, 5 ); + write(fds[1], "1234\n", 5); - ck_assert_int_eq( 5, nread ); + nread = read_until_newline(fds[0], buf, 5); + + ck_assert_int_eq(5, nread); } -END_TEST - -START_TEST( test_read_until_newline_inserts_null ) +END_TEST START_TEST(test_read_until_newline_inserts_null) { - int fds[2]; - int nread; - char buf[5] = {0}; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = { 0 }; + pipe(fds); - write( fds[1], "1234\n", 5 ); - - nread = read_until_newline( fds[0], buf, 5 ); + write(fds[1], "1234\n", 5); - ck_assert_int_eq( '\0', buf[4] ); + nread = read_until_newline(fds[0], buf, 5); + + ck_assert_int_eq('\0', buf[4]); } -END_TEST - -START_TEST( test_read_empty_line_inserts_null ) +END_TEST START_TEST(test_read_empty_line_inserts_null) { - int fds[2]; - int nread; - char buf[5] = {0}; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = { 0 }; + pipe(fds); - write( fds[1], "\n", 1 ); - nread = read_until_newline( fds[0], buf, 1 ); + write(fds[1], "\n", 1); + nread = read_until_newline(fds[0], buf, 1); - ck_assert_int_eq( '\0', buf[0] ); - ck_assert_int_eq( 1, nread ); + ck_assert_int_eq('\0', buf[0]); + ck_assert_int_eq(1, nread); } -END_TEST - -START_TEST( test_read_eof_returns_err ) +END_TEST START_TEST(test_read_eof_returns_err) { - int fds[2]; - int nread; - char buf[5] = {0}; - pipe( fds ); + int fds[2]; + int nread; + char buf[5] = { 0 }; + pipe(fds); - close( fds[1] ); - nread = read_until_newline( fds[0], buf, 5 ); + close(fds[1]); + nread = read_until_newline(fds[0], buf, 5); - ck_assert_int_eq( -1, nread ); + ck_assert_int_eq(-1, nread); } -END_TEST - -START_TEST( test_read_eof_fills_line ) +END_TEST START_TEST(test_read_eof_fills_line) { - int fds[2]; - int nread; - char buf[5] = {0}; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = { 0 }; + pipe(fds); - write( fds[1], "1234", 4 ); - close( fds[1] ); - nread = read_until_newline( fds[0], buf, 5 ); + write(fds[1], "1234", 4); + close(fds[1]); + nread = read_until_newline(fds[0], buf, 5); - ck_assert_int_eq( -1, nread ); - ck_assert_int_eq( '4', buf[3] ); + ck_assert_int_eq(-1, nread); + ck_assert_int_eq('4', buf[3]); } -END_TEST - -START_TEST( test_read_lines_until_blankline ) +END_TEST START_TEST(test_read_lines_until_blankline) { - char **lines = NULL; - int fds[2]; - int nlines; - pipe( fds ); + char **lines = NULL; + int fds[2]; + int nlines; + pipe(fds); - write( fds[1], "a\nb\nc\n\n", 7 ); + write(fds[1], "a\nb\nc\n\n", 7); - nlines = read_lines_until_blankline( fds[0], 256, &lines ); + nlines = read_lines_until_blankline(fds[0], 256, &lines); - ck_assert_int_eq( 3, nlines ); + ck_assert_int_eq(3, nlines); } -END_TEST - -Suite *ioutil_suite(void) +END_TEST Suite * ioutil_suite(void) { - Suite *s = suite_create("ioutil"); + Suite *s = suite_create("ioutil"); - TCase *tc_read_until_newline = tcase_create("read_until_newline"); - TCase *tc_read_lines_until_blankline = tcase_create("read_lines_until_blankline"); + TCase *tc_read_until_newline = tcase_create("read_until_newline"); + TCase *tc_read_lines_until_blankline = + tcase_create("read_lines_until_blankline"); - tcase_add_test(tc_read_until_newline, test_read_until_newline_returns_line_length_plus_null); - tcase_add_test(tc_read_until_newline, test_read_until_newline_inserts_null); - tcase_add_test(tc_read_until_newline, test_read_empty_line_inserts_null); - tcase_add_test(tc_read_until_newline, test_read_eof_returns_err); - tcase_add_test(tc_read_until_newline, test_read_eof_fills_line ); + tcase_add_test(tc_read_until_newline, + test_read_until_newline_returns_line_length_plus_null); + tcase_add_test(tc_read_until_newline, + test_read_until_newline_inserts_null); + tcase_add_test(tc_read_until_newline, + test_read_empty_line_inserts_null); + tcase_add_test(tc_read_until_newline, test_read_eof_returns_err); + tcase_add_test(tc_read_until_newline, test_read_eof_fills_line); - tcase_add_test(tc_read_lines_until_blankline, test_read_lines_until_blankline ); + tcase_add_test(tc_read_lines_until_blankline, + test_read_lines_until_blankline); - suite_add_tcase(s, tc_read_until_newline); - suite_add_tcase(s, tc_read_lines_until_blankline); + suite_add_tcase(s, tc_read_until_newline); + suite_add_tcase(s, tc_read_lines_until_blankline); - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = ioutil_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; -} + int number_failed; + Suite *s = ioutil_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; +} diff --git a/tests/unit/check_mbox.c b/tests/unit/check_mbox.c index 5399531..0d6c3d3 100644 --- a/tests/unit/check_mbox.c +++ b/tests/unit/check_mbox.c @@ -4,83 +4,76 @@ #include #include -START_TEST( test_allocs_cvar ) +START_TEST(test_allocs_cvar) { - struct mbox * mbox = mbox_create(); - fail_if( NULL == mbox, "Nothing allocated" ); + struct mbox *mbox = mbox_create(); + fail_if(NULL == mbox, "Nothing allocated"); - pthread_cond_t cond_zero; - /* A freshly inited pthread_cond_t is set to {0} */ - memset( &cond_zero, 'X', sizeof( cond_zero ) ); - fail_if( memcmp( &cond_zero, &mbox->filled_cond, sizeof( cond_zero ) ) == 0 , - "Condition variable not allocated" ); - fail_if( memcmp( &cond_zero, &mbox->emptied_cond, sizeof( cond_zero ) ) == 0 , - "Condition variable not allocated" ); + pthread_cond_t cond_zero; + /* A freshly inited pthread_cond_t is set to {0} */ + memset(&cond_zero, 'X', sizeof(cond_zero)); + fail_if(memcmp(&cond_zero, &mbox->filled_cond, sizeof(cond_zero)) == 0, + "Condition variable not allocated"); + fail_if(memcmp(&cond_zero, &mbox->emptied_cond, sizeof(cond_zero)) == + 0, "Condition variable not allocated"); } -END_TEST - -START_TEST( test_post_stores_value ) +END_TEST START_TEST(test_post_stores_value) { - struct mbox * mbox = mbox_create(); - - void * deadbeef = (void *)0xDEADBEEF; - mbox_post( mbox, deadbeef ); + struct mbox *mbox = mbox_create(); - fail_unless( deadbeef == mbox_contents( mbox ), - "Contents were not posted" ); + void *deadbeef = (void *) 0xDEADBEEF; + mbox_post(mbox, deadbeef); + + fail_unless(deadbeef == mbox_contents(mbox), + "Contents were not posted"); } -END_TEST - -void * mbox_receive_runner( void * mbox_uncast ) +END_TEST void *mbox_receive_runner(void *mbox_uncast) { - struct mbox * mbox = (struct mbox *)mbox_uncast; - void * contents = NULL; + struct mbox *mbox = (struct mbox *) mbox_uncast; + void *contents = NULL; - contents = mbox_receive( mbox ); - return contents; + contents = mbox_receive(mbox); + return contents; } -START_TEST( test_receive_blocks_until_post ) +START_TEST(test_receive_blocks_until_post) { - struct mbox * mbox = mbox_create(); - pthread_t receiver; - pthread_create( &receiver, NULL, mbox_receive_runner, mbox ); - - void * deadbeef = (void *)0xDEADBEEF; - void * retval =NULL; - usleep(10000); - fail_unless( EBUSY == pthread_tryjoin_np( receiver, &retval ), - "Receiver thread wasn't blocked"); + struct mbox *mbox = mbox_create(); + pthread_t receiver; + pthread_create(&receiver, NULL, mbox_receive_runner, mbox); - mbox_post( mbox, deadbeef ); - fail_unless( 0 == pthread_join( receiver, &retval ), - "Failed to join the receiver thread" ); - fail_unless( retval == deadbeef, - "Return value was wrong" ); + void *deadbeef = (void *) 0xDEADBEEF; + void *retval = NULL; + usleep(10000); + fail_unless(EBUSY == pthread_tryjoin_np(receiver, &retval), + "Receiver thread wasn't blocked"); + + mbox_post(mbox, deadbeef); + fail_unless(0 == pthread_join(receiver, &retval), + "Failed to join the receiver thread"); + fail_unless(retval == deadbeef, "Return value was wrong"); } -END_TEST - -Suite* mbox_suite(void) +END_TEST Suite * mbox_suite(void) { - Suite *s = suite_create("mbox"); - TCase *tc_create = tcase_create("create"); - TCase *tc_post = tcase_create("post"); + Suite *s = suite_create("mbox"); + TCase *tc_create = tcase_create("create"); + TCase *tc_post = tcase_create("post"); - tcase_add_test(tc_create, test_allocs_cvar); + tcase_add_test(tc_create, test_allocs_cvar); - tcase_add_test( tc_post, test_post_stores_value ); - tcase_add_test( tc_post, test_receive_blocks_until_post); + tcase_add_test(tc_post, test_post_stores_value); + tcase_add_test(tc_post, test_receive_blocks_until_post); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_post); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_post); - return s; + return s; } @@ -88,17 +81,16 @@ Suite* mbox_suite(void) int main(void) { #ifdef DEBUG - log_level = 0; + log_level = 0; #else - log_level = 2; + log_level = 2; #endif - int number_failed; - Suite *s = mbox_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - log_level = 0; - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? 0 : 1; + int number_failed; + Suite *s = mbox_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + log_level = 0; + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; } - diff --git a/tests/unit/check_nbdtypes.c b/tests/unit/check_nbdtypes.c index 9124063..b1ee034 100644 --- a/tests/unit/check_nbdtypes.c +++ b/tests/unit/check_nbdtypes.c @@ -4,257 +4,246 @@ START_TEST(test_init_passwd) { - struct nbd_init_raw init_raw; - struct nbd_init init; + struct nbd_init_raw init_raw; + struct nbd_init init; - memcpy( init_raw.passwd, INIT_PASSWD, 8 ); - - nbd_r2h_init( &init_raw, &init ); - memset( init_raw.passwd, 0, 8 ); - nbd_h2r_init( &init, &init_raw ); - - fail_unless( memcmp( init.passwd, INIT_PASSWD, 8 ) == 0, "The password was not copied." ); - fail_unless( memcmp( init_raw.passwd, INIT_PASSWD, 8 ) == 0, "The password was not copied back." ); + memcpy(init_raw.passwd, INIT_PASSWD, 8); + + nbd_r2h_init(&init_raw, &init); + memset(init_raw.passwd, 0, 8); + nbd_h2r_init(&init, &init_raw); + + fail_unless(memcmp(init.passwd, INIT_PASSWD, 8) == 0, + "The password was not copied."); + fail_unless(memcmp(init_raw.passwd, INIT_PASSWD, 8) == 0, + "The password was not copied back."); } -END_TEST - -START_TEST(test_init_magic) +END_TEST START_TEST(test_init_magic) { - struct nbd_init_raw init_raw; - struct nbd_init init; + struct nbd_init_raw init_raw; + struct nbd_init init; - init_raw.magic = 12345; - nbd_r2h_init( &init_raw, &init ); - fail_unless( be64toh( 12345 ) == init.magic, "Magic was not converted." ); + init_raw.magic = 12345; + nbd_r2h_init(&init_raw, &init); + fail_unless(be64toh(12345) == init.magic, "Magic was not converted."); - init.magic = 67890; - nbd_h2r_init( &init, &init_raw ); - fail_unless( htobe64( 67890 ) == init_raw.magic, "Magic was not converted back." ); + init.magic = 67890; + nbd_h2r_init(&init, &init_raw); + fail_unless(htobe64(67890) == init_raw.magic, + "Magic was not converted back."); } -END_TEST - -START_TEST(test_init_size) +END_TEST START_TEST(test_init_size) { - struct nbd_init_raw init_raw; - struct nbd_init init; + struct nbd_init_raw init_raw; + struct nbd_init init; - init_raw.size = 12345; - nbd_r2h_init( &init_raw, &init ); - fail_unless( be64toh( 12345 ) == init.size, "Size was not converted." ); + init_raw.size = 12345; + nbd_r2h_init(&init_raw, &init); + fail_unless(be64toh(12345) == init.size, "Size was not converted."); - init.size = 67890; - nbd_h2r_init( &init, &init_raw ); - fail_unless( htobe64( 67890 ) == init_raw.size, "Size was not converted back." ); + init.size = 67890; + nbd_h2r_init(&init, &init_raw); + fail_unless(htobe64(67890) == init_raw.size, + "Size was not converted back."); } -END_TEST - -START_TEST(test_request_magic ) +END_TEST START_TEST(test_request_magic) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.magic = 12345; - nbd_r2h_request( &request_raw, &request ); - fail_unless( be32toh( 12345 ) == request.magic, "Magic was not converted." ); + request_raw.magic = 12345; + nbd_r2h_request(&request_raw, &request); + fail_unless(be32toh(12345) == request.magic, + "Magic was not converted."); - request.magic = 67890; - nbd_h2r_request( &request, &request_raw ); - fail_unless( htobe32( 67890 ) == request_raw.magic, "Magic was not converted back." ); + request.magic = 67890; + nbd_h2r_request(&request, &request_raw); + fail_unless(htobe32(67890) == request_raw.magic, + "Magic was not converted back."); } -END_TEST -START_TEST(test_request_type) +END_TEST START_TEST(test_request_type) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.type = 123; - nbd_r2h_request( &request_raw, &request ); - fail_unless( be16toh( 123 ) == request.type, "Type was not converted." ); + request_raw.type = 123; + nbd_r2h_request(&request_raw, &request); + fail_unless(be16toh(123) == request.type, "Type was not converted."); - request.type = 234; - nbd_h2r_request( &request, &request_raw ); - fail_unless( htobe16( 234 ) == request_raw.type, "Type was not converted back." ); + request.type = 234; + nbd_h2r_request(&request, &request_raw); + fail_unless(htobe16(234) == request_raw.type, + "Type was not converted back."); } -END_TEST - - -START_TEST(test_request_flags) +END_TEST START_TEST(test_request_flags) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.flags = 123; - nbd_r2h_request( &request_raw, &request ); - fail_unless( be16toh( 123 ) == request.flags, "Flags were not converted." ); + request_raw.flags = 123; + nbd_r2h_request(&request_raw, &request); + fail_unless(be16toh(123) == request.flags, + "Flags were not converted."); - request.flags = 234; - nbd_h2r_request( &request, &request_raw ); - fail_unless( htobe16( 234 ) == request_raw.flags, "Flags were not converted back." ); + request.flags = 234; + nbd_h2r_request(&request, &request_raw); + fail_unless(htobe16(234) == request_raw.flags, + "Flags were not converted back."); } -END_TEST - - -START_TEST(test_request_handle) +END_TEST START_TEST(test_request_handle) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - memcpy( request_raw.handle.b, "MYHANDLE", 8 ); - - nbd_r2h_request( &request_raw, &request ); - request_raw.handle.w = 0; - nbd_h2r_request( &request, &request_raw ); - - fail_unless( memcmp( request.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied." ); - fail_unless( memcmp( request_raw.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied back." ); + memcpy(request_raw.handle.b, "MYHANDLE", 8); + + nbd_r2h_request(&request_raw, &request); + request_raw.handle.w = 0; + nbd_h2r_request(&request, &request_raw); + + fail_unless(memcmp(request.handle.b, "MYHANDLE", 8) == 0, + "The handle was not copied."); + fail_unless(memcmp(request_raw.handle.b, "MYHANDLE", 8) == 0, + "The handle was not copied back."); } -END_TEST - - -START_TEST(test_request_from ) +END_TEST START_TEST(test_request_from) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.from = 12345; - nbd_r2h_request( &request_raw, &request ); - fail_unless( be64toh( 12345 ) == request.from, "From was not converted." ); + request_raw.from = 12345; + nbd_r2h_request(&request_raw, &request); + fail_unless(be64toh(12345) == request.from, "From was not converted."); - request.from = 67890; - nbd_h2r_request( &request, &request_raw ); - fail_unless( htobe64( 67890 ) == request_raw.from, "From was not converted back." ); + request.from = 67890; + nbd_h2r_request(&request, &request_raw); + fail_unless(htobe64(67890) == request_raw.from, + "From was not converted back."); } -END_TEST - - -START_TEST(test_request_len ) +END_TEST START_TEST(test_request_len) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.len = 12345; - nbd_r2h_request( &request_raw, &request ); - fail_unless( be32toh( 12345 ) == request.len, "Type was not converted." ); + request_raw.len = 12345; + nbd_r2h_request(&request_raw, &request); + fail_unless(be32toh(12345) == request.len, "Type was not converted."); - request.len = 67890; - nbd_h2r_request( &request, &request_raw ); - fail_unless( htobe32( 67890 ) == request_raw.len, "Type was not converted back." ); + request.len = 67890; + nbd_h2r_request(&request, &request_raw); + fail_unless(htobe32(67890) == request_raw.len, + "Type was not converted back."); } -END_TEST - -START_TEST(test_reply_magic ) +END_TEST START_TEST(test_reply_magic) { - struct nbd_reply_raw reply_raw; - struct nbd_reply reply; + struct nbd_reply_raw reply_raw; + struct nbd_reply reply; - reply_raw.magic = 12345; - nbd_r2h_reply( &reply_raw, &reply ); - fail_unless( be32toh( 12345 ) == reply.magic, "Magic was not converted." ); + reply_raw.magic = 12345; + nbd_r2h_reply(&reply_raw, &reply); + fail_unless(be32toh(12345) == reply.magic, "Magic was not converted."); - reply.magic = 67890; - nbd_h2r_reply( &reply, &reply_raw ); - fail_unless( htobe32( 67890 ) == reply_raw.magic, "Magic was not converted back." ); + reply.magic = 67890; + nbd_h2r_reply(&reply, &reply_raw); + fail_unless(htobe32(67890) == reply_raw.magic, + "Magic was not converted back."); } -END_TEST - -START_TEST(test_reply_error ) +END_TEST START_TEST(test_reply_error) { - struct nbd_reply_raw reply_raw; - struct nbd_reply reply; + struct nbd_reply_raw reply_raw; + struct nbd_reply reply; - reply_raw.error = 12345; - nbd_r2h_reply( &reply_raw, &reply ); - fail_unless( be32toh( 12345 ) == reply.error, "Error was not converted." ); + reply_raw.error = 12345; + nbd_r2h_reply(&reply_raw, &reply); + fail_unless(be32toh(12345) == reply.error, "Error was not converted."); - reply.error = 67890; - nbd_h2r_reply( &reply, &reply_raw ); - fail_unless( htobe32( 67890 ) == reply_raw.error, "Error was not converted back." ); + reply.error = 67890; + nbd_h2r_reply(&reply, &reply_raw); + fail_unless(htobe32(67890) == reply_raw.error, + "Error was not converted back."); } -END_TEST -START_TEST(test_reply_handle) +END_TEST START_TEST(test_reply_handle) { - struct nbd_reply_raw reply_raw; - struct nbd_reply reply; + struct nbd_reply_raw reply_raw; + struct nbd_reply reply; - memcpy( reply_raw.handle.b, "MYHANDLE", 8 ); - - nbd_r2h_reply( &reply_raw, &reply ); - reply_raw.handle.w = 0; - nbd_h2r_reply( &reply, &reply_raw ); - - fail_unless( memcmp( reply.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied." ); - fail_unless( memcmp( reply_raw.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied back." ); + memcpy(reply_raw.handle.b, "MYHANDLE", 8); + + nbd_r2h_reply(&reply_raw, &reply); + reply_raw.handle.w = 0; + nbd_h2r_reply(&reply, &reply_raw); + + fail_unless(memcmp(reply.handle.b, "MYHANDLE", 8) == 0, + "The handle was not copied."); + fail_unless(memcmp(reply_raw.handle.b, "MYHANDLE", 8) == 0, + "The handle was not copied back."); } -END_TEST - -START_TEST( test_convert_from ) +END_TEST START_TEST(test_convert_from) { - /* Check that we can correctly pull numbers out of an - * nbd_request_raw */ - struct nbd_request_raw request_raw; - struct nbd_request request; + /* Check that we can correctly pull numbers out of an + * nbd_request_raw */ + struct nbd_request_raw request_raw; + struct nbd_request request; - uint64_t target = 0x8000000000000000; + uint64_t target = 0x8000000000000000; - /* this is stored big-endian */ - request_raw.from = htobe64(target); + /* this is stored big-endian */ + request_raw.from = htobe64(target); - /* We expect this to convert big-endian to the host format */ - nbd_r2h_request( &request_raw, &request ); + /* We expect this to convert big-endian to the host format */ + nbd_r2h_request(&request_raw, &request); - fail_unless( target == request.from, "from was wrong" ); -} -END_TEST + fail_unless(target == request.from, "from was wrong"); +} -Suite *nbdtypes_suite(void) +END_TEST Suite * nbdtypes_suite(void) { - Suite *s = suite_create( "nbdtypes" ); - TCase *tc_init = tcase_create( "nbd_init" ); - TCase *tc_request = tcase_create( "nbd_request" ); - TCase *tc_reply = tcase_create( "nbd_reply" ); + Suite *s = suite_create("nbdtypes"); + TCase *tc_init = tcase_create("nbd_init"); + TCase *tc_request = tcase_create("nbd_request"); + TCase *tc_reply = tcase_create("nbd_reply"); - tcase_add_test( tc_init, test_init_passwd ); - tcase_add_test( tc_init, test_init_magic ); - tcase_add_test( tc_init, test_init_size ); - tcase_add_test( tc_request, test_request_magic ); - tcase_add_test( tc_request, test_request_type ); - tcase_add_test( tc_request, test_request_handle ); - tcase_add_test( tc_request, test_request_from ); - tcase_add_test( tc_request, test_request_len ); - tcase_add_test( tc_request, test_convert_from ); - tcase_add_test( tc_reply, test_reply_magic ); - tcase_add_test( tc_reply, test_reply_error ); - tcase_add_test( tc_reply, test_reply_handle ); + tcase_add_test(tc_init, test_init_passwd); + tcase_add_test(tc_init, test_init_magic); + tcase_add_test(tc_init, test_init_size); + tcase_add_test(tc_request, test_request_magic); + tcase_add_test(tc_request, test_request_type); + tcase_add_test(tc_request, test_request_handle); + tcase_add_test(tc_request, test_request_from); + tcase_add_test(tc_request, test_request_len); + tcase_add_test(tc_request, test_convert_from); + tcase_add_test(tc_reply, test_reply_magic); + tcase_add_test(tc_reply, test_reply_error); + tcase_add_test(tc_reply, test_reply_handle); - suite_add_tcase( s, tc_init ); - suite_add_tcase( s, tc_request ); - suite_add_tcase( s, tc_reply ); + suite_add_tcase(s, tc_init); + suite_add_tcase(s, tc_request); + suite_add_tcase(s, tc_reply); - return s; + return s; } int main(void) { - int number_failed; - Suite *s = nbdtypes_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; + int number_failed; + Suite *s = nbdtypes_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; } - diff --git a/tests/unit/check_parse.c b/tests/unit/check_parse.c index b30ee6d..3d9130a 100644 --- a/tests/unit/check_parse.c +++ b/tests/unit/check_parse.c @@ -3,45 +3,41 @@ #include -START_TEST( test_can_parse_ip_address_twice ) +START_TEST(test_can_parse_ip_address_twice) { - char ip_address[] = "127.0.0.1"; - struct sockaddr saddr; + char ip_address[] = "127.0.0.1"; + struct sockaddr saddr; - parse_ip_to_sockaddr( &saddr, ip_address ); - parse_ip_to_sockaddr( &saddr, ip_address ); + parse_ip_to_sockaddr(&saddr, ip_address); + parse_ip_to_sockaddr(&saddr, ip_address); } -END_TEST - - -Suite* parse_suite(void) +END_TEST Suite * parse_suite(void) { - Suite *s = suite_create("parse"); - TCase *tc_create = tcase_create("ip_to_sockaddr"); + Suite *s = suite_create("parse"); + TCase *tc_create = tcase_create("ip_to_sockaddr"); - tcase_add_test(tc_create, test_can_parse_ip_address_twice); + tcase_add_test(tc_create, test_can_parse_ip_address_twice); - suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_create); - return s; + return s; } #ifdef DEBUG -# define LOG_LEVEL 0 +#define LOG_LEVEL 0 #else -# define LOG_LEVEL 2 +#define LOG_LEVEL 2 #endif int main(void) { - log_level = LOG_LEVEL; - int number_failed; - Suite *s = parse_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; + log_level = LOG_LEVEL; + int number_failed; + Suite *s = parse_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; } - diff --git a/tests/unit/check_readwrite.c b/tests/unit/check_readwrite.c index c158d7b..9f20bf9 100644 --- a/tests/unit/check_readwrite.c +++ b/tests/unit/check_readwrite.c @@ -21,173 +21,169 @@ -int fd_read_request( int, struct nbd_request_raw *); -int fd_write_reply( int, uint64_t, int ); +int fd_read_request(int, struct nbd_request_raw *); +int fd_write_reply(int, uint64_t, int); int marker; -void error_marker(void * unused __attribute__((unused)), - int fatal __attribute__((unused))) +void error_marker(void *unused __attribute__ ((unused)), + int fatal __attribute__ ((unused))) { - marker = 1; - return; + marker = 1; + return; } struct respond { - int sock_fds[2]; // server end - int do_fail; - pthread_t thread_id; - pthread_attr_t thread_attr; - struct nbd_request received; + int sock_fds[2]; // server end + int do_fail; + pthread_t thread_id; + pthread_attr_t thread_attr; + struct nbd_request received; }; -void * responder( void *respond_uncast ) +void *responder(void *respond_uncast) { - struct respond * resp = (struct respond *) respond_uncast; - int sock_fd = resp->sock_fds[1]; - struct nbd_request_raw request_raw; - uint64_t wrong_handle = 0x80; + struct respond *resp = (struct respond *) respond_uncast; + int sock_fd = resp->sock_fds[1]; + struct nbd_request_raw request_raw; + uint64_t wrong_handle = 0x80; - if( fd_read_request( sock_fd, &request_raw ) == -1){ - fprintf(stderr, "Problem with fd_read_request\n"); + if (fd_read_request(sock_fd, &request_raw) == -1) { + fprintf(stderr, "Problem with fd_read_request\n"); + } else { + nbd_r2h_request(&request_raw, &resp->received); + if (resp->do_fail) { + fd_write_reply(sock_fd, wrong_handle, 0); } else { - nbd_r2h_request( &request_raw, &resp->received); - if (resp->do_fail){ - fd_write_reply( sock_fd, wrong_handle, 0 ); - } - else { - fd_write_reply( sock_fd, resp->received.handle.w, 0 ); - } - write( sock_fd, "12345678", 8 ); + fd_write_reply(sock_fd, resp->received.handle.w, 0); } - return NULL; + write(sock_fd, "12345678", 8); + } + return NULL; } -struct respond * respond_create( int do_fail ) +struct respond *respond_create(int do_fail) { - struct respond * respond = (struct respond *)calloc( 1, sizeof( struct respond ) ); - socketpair( PF_UNIX, SOCK_STREAM, 0, respond->sock_fds ); - respond->do_fail = do_fail; + struct respond *respond = + (struct respond *) calloc(1, sizeof(struct respond)); + socketpair(PF_UNIX, SOCK_STREAM, 0, respond->sock_fds); + respond->do_fail = do_fail; - pthread_attr_init( &respond->thread_attr ); - pthread_create( &respond->thread_id, &respond->thread_attr, responder, respond ); + pthread_attr_init(&respond->thread_attr); + pthread_create(&respond->thread_id, &respond->thread_attr, responder, + respond); - return respond; + return respond; } -void respond_destroy( struct respond * respond ){ - NULLCHECK( respond ); - - pthread_join( respond->thread_id, NULL ); - pthread_attr_destroy( &respond->thread_attr ); - - close( respond->sock_fds[0] ); - close( respond->sock_fds[1] ); - free( respond ); -} - - -void * reader( void * nothing __attribute__((unused))) +void respond_destroy(struct respond *respond) { - DECLARE_ERROR_CONTEXT( error_context ); - error_set_handler( (cleanup_handler *)error_marker, error_context ); + NULLCHECK(respond); - struct respond * respond = respond_create( 1 ); - int devnull = open("/dev/null", O_WRONLY); - char outbuf[8] = {0}; + pthread_join(respond->thread_id, NULL); + pthread_attr_destroy(&respond->thread_attr); - socket_nbd_read( respond->sock_fds[0], 0, 8, devnull, outbuf, 1 ); - - return NULL; + close(respond->sock_fds[0]); + close(respond->sock_fds[1]); + free(respond); } -START_TEST( test_rejects_mismatched_handle ) + +void *reader(void *nothing __attribute__ ((unused))) +{ + DECLARE_ERROR_CONTEXT(error_context); + error_set_handler((cleanup_handler *) error_marker, error_context); + + struct respond *respond = respond_create(1); + int devnull = open("/dev/null", O_WRONLY); + char outbuf[8] = { 0 }; + + socket_nbd_read(respond->sock_fds[0], 0, 8, devnull, outbuf, 1); + + return NULL; +} + +START_TEST(test_rejects_mismatched_handle) { - error_init(); - pthread_t reader_thread; + error_init(); + pthread_t reader_thread; - log_level=5; - - marker = 0; - pthread_create( &reader_thread, NULL, reader, NULL ); - FATAL_UNLESS( 0 == pthread_join( reader_thread, NULL ), - "pthread_join failed"); - - log_level=2; + log_level = 5; - fail_unless( marker == 1, "Error handler wasn't called" ); + marker = 0; + pthread_create(&reader_thread, NULL, reader, NULL); + FATAL_UNLESS(0 == pthread_join(reader_thread, NULL), + "pthread_join failed"); + + log_level = 2; + + fail_unless(marker == 1, "Error handler wasn't called"); } -END_TEST - -START_TEST( test_accepts_matched_handle ) +END_TEST START_TEST(test_accepts_matched_handle) { - struct respond * respond = respond_create( 0 ); + struct respond *respond = respond_create(0); - int devnull = open("/dev/null", O_WRONLY); - char outbuf[8] = {0}; + int devnull = open("/dev/null", O_WRONLY); + char outbuf[8] = { 0 }; - socket_nbd_read( respond->sock_fds[0], 0, 8, devnull, outbuf, 1 ); + socket_nbd_read(respond->sock_fds[0], 0, 8, devnull, outbuf, 1); - respond_destroy( respond ); + respond_destroy(respond); } -END_TEST - -START_TEST( test_disconnect_doesnt_read_reply ) +END_TEST START_TEST(test_disconnect_doesnt_read_reply) { - struct respond * respond = respond_create( 1 ); + struct respond *respond = respond_create(1); - socket_nbd_disconnect( respond->sock_fds[0] ); + socket_nbd_disconnect(respond->sock_fds[0]); - respond_destroy( respond ); + respond_destroy(respond); } -END_TEST - -Suite* readwrite_suite(void) +END_TEST Suite * readwrite_suite(void) { - Suite *s = suite_create("readwrite"); - TCase *tc_transfer = tcase_create("entrust"); - TCase *tc_disconnect = tcase_create("disconnect"); + Suite *s = suite_create("readwrite"); + TCase *tc_transfer = tcase_create("entrust"); + TCase *tc_disconnect = tcase_create("disconnect"); - tcase_add_test(tc_transfer, test_rejects_mismatched_handle); - tcase_add_exit_test(tc_transfer, test_accepts_matched_handle, 0); + tcase_add_test(tc_transfer, test_rejects_mismatched_handle); + tcase_add_exit_test(tc_transfer, test_accepts_matched_handle, 0); - /* This test is a little funny. We respond with a dodgy handle - * and check that this *doesn't* cause a message rejection, - * because we want to know that the sender won't even try to - * read the response. - */ - tcase_add_exit_test( tc_disconnect, test_disconnect_doesnt_read_reply,0 ); + /* This test is a little funny. We respond with a dodgy handle + * and check that this *doesn't* cause a message rejection, + * because we want to know that the sender won't even try to + * read the response. + */ + tcase_add_exit_test(tc_disconnect, test_disconnect_doesnt_read_reply, + 0); - suite_add_tcase(s, tc_transfer); - suite_add_tcase(s, tc_disconnect); + suite_add_tcase(s, tc_transfer); + suite_add_tcase(s, tc_disconnect); - return s; + return s; } #ifdef DEBUG -# define LOG_LEVEL 0 +#define LOG_LEVEL 0 #else -# define LOG_LEVEL 2 +#define LOG_LEVEL 2 #endif int main(void) { - log_level = LOG_LEVEL; - int number_failed; - Suite *s = readwrite_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - log_level = 0; - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? 0 : 1; + log_level = LOG_LEVEL; + int number_failed; + Suite *s = readwrite_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + log_level = 0; + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; } - diff --git a/tests/unit/check_self_pipe.c b/tests/unit/check_self_pipe.c index c3026c9..fcc783f 100644 --- a/tests/unit/check_self_pipe.c +++ b/tests/unit/check_self_pipe.c @@ -9,190 +9,180 @@ #include "self_pipe.h" -START_TEST( test_opens_pipe ) +START_TEST(test_opens_pipe) { - struct self_pipe* sig; - char buf[] = " "; + struct self_pipe *sig; + char buf[] = " "; - sig = self_pipe_create(); + sig = self_pipe_create(); - write( sig->write_fd, "1", 1 ); - read( sig->read_fd, buf, 1 ); + write(sig->write_fd, "1", 1); + read(sig->read_fd, buf, 1); - fail_unless( buf[0] == '1', "Pipe does not seem to be open;" ); - self_pipe_destroy( sig ); -} -END_TEST - - -void * signal_thread( void * thing ) -{ - struct self_pipe *sig = (struct self_pipe *)thing; - usleep( 100000 ); - self_pipe_signal( sig ); - return NULL; + fail_unless(buf[0] == '1', "Pipe does not seem to be open;"); + self_pipe_destroy(sig); } -pthread_t start_signal_thread( struct self_pipe *sig ) +END_TEST void *signal_thread(void *thing) { - pthread_attr_t attr; - pthread_t thread_id; + struct self_pipe *sig = (struct self_pipe *) thing; + usleep(100000); + self_pipe_signal(sig); + return NULL; +} - pthread_attr_init( &attr ); - pthread_create( &thread_id, &attr, signal_thread, sig ); - pthread_attr_destroy( &attr ); +pthread_t start_signal_thread(struct self_pipe * sig) +{ + pthread_attr_t attr; + pthread_t thread_id; - return thread_id; + pthread_attr_init(&attr); + pthread_create(&thread_id, &attr, signal_thread, sig); + pthread_attr_destroy(&attr); + + return thread_id; } -START_TEST( test_signals ) +START_TEST(test_signals) { - struct self_pipe* sig; - fd_set fds; - pthread_t signal_thread_id; + struct self_pipe *sig; + fd_set fds; + pthread_t signal_thread_id; - sig = self_pipe_create(); + sig = self_pipe_create(); - FD_ZERO( &fds ); - self_pipe_fd_set( sig, &fds ); + FD_ZERO(&fds); + self_pipe_fd_set(sig, &fds); - signal_thread_id = start_signal_thread( sig ); - if ( select( FD_SETSIZE, &fds, NULL, NULL, NULL ) == -1 ) { - fail( strerror(errno) ); + signal_thread_id = start_signal_thread(sig); + if (select(FD_SETSIZE, &fds, NULL, NULL, NULL) == -1) { + fail(strerror(errno)); + } + self_pipe_signal_clear(sig); + + fail_unless(self_pipe_fd_isset(sig, &fds), + "Signalled pipe was not FD_ISSET."); + pthread_join(signal_thread_id, NULL); + + self_pipe_destroy(sig); +} + +END_TEST START_TEST(test_clear_returns_immediately) +{ + struct self_pipe *sig; + sig = self_pipe_create(); + fail_unless(0 == self_pipe_signal_clear(sig), "Wrong clear result."); +} + +END_TEST START_TEST(test_destroy_closes_read_pipe) +{ + struct self_pipe *sig; + ssize_t read_len; + int orig_read_fd; + + sig = self_pipe_create(); + orig_read_fd = sig->read_fd; + self_pipe_destroy(sig); + + while ((read_len = read(orig_read_fd, "", 0)) == -1 && errno == EINTR); + + switch (read_len) { + case 0: + fail("The read fd wasn't closed."); + break; + case -1: + switch (errno) { + case EBADF: + /* This is what we want */ + break; + case EAGAIN: + fail("The read fd wasn't closed."); + break; + default: + fail(strerror(errno)); + break; } - self_pipe_signal_clear( sig ); - - fail_unless( self_pipe_fd_isset( sig, &fds ), "Signalled pipe was not FD_ISSET." ); - pthread_join( signal_thread_id, NULL ); - - self_pipe_destroy( sig ); + break; + default: + fail("The read fd wasn't closed, and had data in it."); + break; + } } -END_TEST - -START_TEST( test_clear_returns_immediately ) +END_TEST START_TEST(test_destroy_closes_write_pipe) { - struct self_pipe *sig; - sig = self_pipe_create(); - fail_unless( 0 == self_pipe_signal_clear( sig ), "Wrong clear result." ); -} -END_TEST + struct self_pipe *sig; + ssize_t write_len; + int orig_write_fd; + sig = self_pipe_create(); + orig_write_fd = sig->write_fd; + self_pipe_destroy(sig); -START_TEST( test_destroy_closes_read_pipe ) -{ - struct self_pipe* sig; - ssize_t read_len; - int orig_read_fd; + while ((write_len = write(orig_write_fd, "", 0)) == -1 + && errno == EINTR); - sig = self_pipe_create(); - orig_read_fd = sig->read_fd; - self_pipe_destroy( sig ); - - while( (read_len = read( orig_read_fd, "", 0 )) == -1 && errno == EINTR ); - - switch( read_len ) { - case 0: - fail("The read fd wasn't closed." ); - break; - case -1: - switch(errno) { - case EBADF: - /* This is what we want */ - break; - case EAGAIN: - fail( "The read fd wasn't closed." ); - break; - default: - fail( strerror( errno ) ); - break; - } - break; - default: - fail( "The read fd wasn't closed, and had data in it." ); - break; + switch (write_len) { + case 0: + fail("The write fd wasn't closed."); + break; + case -1: + switch (errno) { + case EPIPE: + case EBADF: + /* This is what we want */ + break; + case EAGAIN: + fail("The write fd wasn't closed."); + break; + default: + fail(strerror(errno)); + break; } -} -END_TEST - - -START_TEST( test_destroy_closes_write_pipe ) -{ - struct self_pipe * sig; - ssize_t write_len; - int orig_write_fd; - - sig = self_pipe_create(); - orig_write_fd = sig->write_fd; - self_pipe_destroy( sig ); - - while ( ( write_len = write( orig_write_fd, "", 0 ) ) == -1 && errno == EINTR ); - - switch( write_len ) { - case 0: - fail( "The write fd wasn't closed." ); - break; - case -1: - switch( errno ) { - case EPIPE: - case EBADF: - /* This is what we want */ - break; - case EAGAIN: - fail("The write fd wasn't closed." ); - break; - default: - fail( strerror( errno ) ); - break; - } - break; - default: - /* To get here, the write(_,_,0) would have to - * write some bytes. - */ - fail( "The write fd wasn't closed, and something REALLY WEIRD is going on." ); - break; - } - -} -END_TEST - - - -Suite *self_pipe_suite(void) -{ - Suite *s = suite_create("self_pipe"); - - TCase *tc_create = tcase_create("create"); - TCase *tc_signal = tcase_create("signal"); - TCase *tc_destroy = tcase_create("destroy"); - - tcase_add_test(tc_create, test_opens_pipe); - tcase_add_test(tc_signal, test_signals ); - tcase_add_test(tc_signal, test_clear_returns_immediately ); - tcase_add_test(tc_destroy, test_destroy_closes_read_pipe ); - tcase_add_test(tc_destroy, test_destroy_closes_write_pipe ); - /* We don't test that destroy free()'s the self_pipe pointer because - * that'll be caught by valgrind. + break; + default: + /* To get here, the write(_,_,0) would have to + * write some bytes. */ + fail("The write fd wasn't closed, and something REALLY WEIRD is going on."); + break; + } - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_signal); - suite_add_tcase(s, tc_destroy); +} - return s; +END_TEST Suite * self_pipe_suite(void) +{ + Suite *s = suite_create("self_pipe"); + + TCase *tc_create = tcase_create("create"); + TCase *tc_signal = tcase_create("signal"); + TCase *tc_destroy = tcase_create("destroy"); + + tcase_add_test(tc_create, test_opens_pipe); + tcase_add_test(tc_signal, test_signals); + tcase_add_test(tc_signal, test_clear_returns_immediately); + tcase_add_test(tc_destroy, test_destroy_closes_read_pipe); + tcase_add_test(tc_destroy, test_destroy_closes_write_pipe); + /* We don't test that destroy free()'s the self_pipe pointer because + * that'll be caught by valgrind. + */ + + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_signal); + suite_add_tcase(s, tc_destroy); + + return s; } int main(void) { - int number_failed; - - Suite *s = self_pipe_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; -} + int number_failed; + Suite *s = self_pipe_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; +} diff --git a/tests/unit/check_serve.c b/tests/unit/check_serve.c index b00bb1a..e0a2a67 100644 --- a/tests/unit/check_serve.c +++ b/tests/unit/check_serve.c @@ -15,9 +15,9 @@ #include #ifdef DEBUG -# define LOG_LEVEL 0 +#define LOG_LEVEL 0 #else -# define LOG_LEVEL 2 +#define LOG_LEVEL 2 #endif @@ -28,237 +28,245 @@ #define myfail_if( tst, msg ) do { if( tst ) { myfail( msg ); } } while (0) #define myfail_unless( tst, msg ) myfail_if( !(tst), msg ) -char * dummy_file; +char *dummy_file; char *make_tmpfile(void) { - FILE *fp; - char *fn_buf; - char leader[] = "/tmp/check_serve"; + FILE *fp; + char *fn_buf; + char leader[] = "/tmp/check_serve"; - fn_buf = (char *)malloc( 1024 ); - strncpy( fn_buf, leader, sizeof( leader ) - 1); - snprintf( &fn_buf[sizeof( leader ) - 1], 10, "%d", getpid() ); - fp = fopen( fn_buf, "w" ); - fwrite( fn_buf, 1024, 1, fp ); - fclose( fp ); + fn_buf = (char *) malloc(1024); + strncpy(fn_buf, leader, sizeof(leader) - 1); + snprintf(&fn_buf[sizeof(leader) - 1], 10, "%d", getpid()); + fp = fopen(fn_buf, "w"); + fwrite(fn_buf, 1024, 1, fp); + fclose(fp); - return fn_buf; + return fn_buf; } -void setup( void ) +void setup(void) { - dummy_file = make_tmpfile(); + dummy_file = make_tmpfile(); } -void teardown( void ) +void teardown(void) { - if( dummy_file ){ unlink( dummy_file ); } - free( dummy_file ); - dummy_file = NULL; + if (dummy_file) { + unlink(dummy_file); + } + free(dummy_file); + dummy_file = NULL; } -START_TEST( test_replaces_acl ) +START_TEST(test_replaces_acl) { - struct flexnbd flexnbd; - flexnbd.signal_fd = -1; - struct server * s = server_create( &flexnbd, "127.0.0.1", "0", dummy_file, 0, 0, NULL, 1, 0, 1 ); - struct acl * new_acl = acl_create( 0, NULL, 0 ); + struct flexnbd flexnbd; + flexnbd.signal_fd = -1; + struct server *s = + server_create(&flexnbd, "127.0.0.1", "0", dummy_file, 0, 0, NULL, + 1, 0, 1); + struct acl *new_acl = acl_create(0, NULL, 0); - server_replace_acl( s, new_acl ); + server_replace_acl(s, new_acl); - myfail_unless( s->acl == new_acl, "ACL wasn't replaced." ); - server_destroy( s ); + myfail_unless(s->acl == new_acl, "ACL wasn't replaced."); + server_destroy(s); } -END_TEST - -START_TEST( test_signals_acl_updated ) +END_TEST START_TEST(test_signals_acl_updated) { - struct flexnbd flexnbd; - flexnbd.signal_fd = -1; - struct server * s = server_create( &flexnbd, "127.0.0.1", "0", dummy_file, 0, 0, NULL, 1, 0, 1 ); - struct acl * new_acl = acl_create( 0, NULL, 0 ); + struct flexnbd flexnbd; + flexnbd.signal_fd = -1; + struct server *s = + server_create(&flexnbd, "127.0.0.1", "0", dummy_file, 0, 0, NULL, + 1, 0, 1); + struct acl *new_acl = acl_create(0, NULL, 0); - server_replace_acl( s, new_acl ); + server_replace_acl(s, new_acl); - myfail_unless( 1 == self_pipe_signal_clear( s->acl_updated_signal ), - "No signal sent." ); - server_destroy( s ); + myfail_unless(1 == self_pipe_signal_clear(s->acl_updated_signal), + "No signal sent."); + server_destroy(s); } -END_TEST - -int connect_client( char *addr, int actual_port, char *source_addr ) +END_TEST int connect_client(char *addr, int actual_port, char *source_addr) { - int client_fd = -1; + int client_fd = -1; - struct addrinfo hint; - struct addrinfo *ailist, *aip; + struct addrinfo hint; + struct addrinfo *ailist, *aip; - memset( &hint, '\0', sizeof( struct addrinfo ) ); - hint.ai_socktype = SOCK_STREAM; + memset(&hint, '\0', sizeof(struct addrinfo)); + hint.ai_socktype = SOCK_STREAM; - myfail_if( getaddrinfo( addr, NULL, &hint, &ailist ) != 0, "getaddrinfo failed." ); + myfail_if(getaddrinfo(addr, NULL, &hint, &ailist) != 0, + "getaddrinfo failed."); - int connected = 0; - for( aip = ailist; aip; aip = aip->ai_next ) { - ((struct sockaddr_in *)aip->ai_addr)->sin_port = htons( actual_port ); - client_fd = socket( aip->ai_family, aip->ai_socktype, aip->ai_protocol ); + int connected = 0; + for (aip = ailist; aip; aip = aip->ai_next) { + ((struct sockaddr_in *) aip->ai_addr)->sin_port = + htons(actual_port); + client_fd = + socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol); - if (source_addr) { - struct sockaddr src; - if( !parse_ip_to_sockaddr(&src, source_addr)) { - close(client_fd); - continue; - } - bind(client_fd, &src, sizeof(struct sockaddr_in6)); - } - - if( client_fd == -1) { continue; } - if( connect( client_fd, aip->ai_addr, aip->ai_addrlen) == 0 ) { - connected = 1; - break; - } - close( client_fd ); + if (source_addr) { + struct sockaddr src; + if (!parse_ip_to_sockaddr(&src, source_addr)) { + close(client_fd); + continue; + } + bind(client_fd, &src, sizeof(struct sockaddr_in6)); } - myfail_unless( connected, "Didn't connect." ); - return client_fd; + if (client_fd == -1) { + continue; + } + if (connect(client_fd, aip->ai_addr, aip->ai_addrlen) == 0) { + connected = 1; + break; + } + close(client_fd); + } + + myfail_unless(connected, "Didn't connect."); + return client_fd; } /* These are "internal" functions we need for the following test. We * shouldn't need them but there's no other way at the moment. */ -void serve_open_server_socket( struct server * ); -int server_port( struct server * ); -void server_accept( struct server * ); -int fd_is_closed( int ); -void server_close_clients( struct server * ); +void serve_open_server_socket(struct server *); +int server_port(struct server *); +void server_accept(struct server *); +int fd_is_closed(int); +void server_close_clients(struct server *); -START_TEST( test_acl_update_closes_bad_client ) +START_TEST(test_acl_update_closes_bad_client) { - /* This is the wrong way round. Rather than pulling the thread - * and socket out of the server structure, we should be testing - * a client socket. - */ - struct flexnbd flexnbd; - flexnbd.signal_fd = -1; - struct server * s = server_create( &flexnbd, "127.0.0.7", "0", dummy_file, 0, 0, NULL, 1, 0, 1 ); - struct acl * new_acl = acl_create( 0, NULL, 1 ); - struct client * c; - struct client_tbl_entry * entry; + /* This is the wrong way round. Rather than pulling the thread + * and socket out of the server structure, we should be testing + * a client socket. + */ + struct flexnbd flexnbd; + flexnbd.signal_fd = -1; + struct server *s = + server_create(&flexnbd, "127.0.0.7", "0", dummy_file, 0, 0, NULL, + 1, 0, 1); + struct acl *new_acl = acl_create(0, NULL, 1); + struct client *c; + struct client_tbl_entry *entry; - int actual_port; - int client_fd; - int server_fd; + int actual_port; + int client_fd; + int server_fd; - serve_open_server_socket( s ); - actual_port = server_port( s ); + serve_open_server_socket(s); + actual_port = server_port(s); - client_fd = connect_client( "127.0.0.7", actual_port, "127.0.0.1" ); - server_accept( s ); - entry = &s->nbd_client[0]; - c = entry->client; - /* At this point there should be an entry in the nbd_clients - * table and a background thread to run the client loop - */ - myfail_if( entry->thread == 0, "No client thread was started." ); - server_fd = c->socket; - myfail_if( fd_is_closed(server_fd), - "Sanity check failed - client socket wasn't open." ); + client_fd = connect_client("127.0.0.7", actual_port, "127.0.0.1"); + server_accept(s); + entry = &s->nbd_client[0]; + c = entry->client; + /* At this point there should be an entry in the nbd_clients + * table and a background thread to run the client loop + */ + myfail_if(entry->thread == 0, "No client thread was started."); + server_fd = c->socket; + myfail_if(fd_is_closed(server_fd), + "Sanity check failed - client socket wasn't open."); - server_replace_acl( s, new_acl ); + server_replace_acl(s, new_acl); - /* accept again, so that we can react to the acl replacement signal */ - server_accept( s ); + /* accept again, so that we can react to the acl replacement signal */ + server_accept(s); - /* Fail if we time out here */ - while( !fd_is_closed( server_fd ) ); + /* Fail if we time out here */ + while (!fd_is_closed(server_fd)); - close( client_fd ); - server_close_clients( s ); - server_destroy( s ); + close(client_fd); + server_close_clients(s); + server_destroy(s); } -END_TEST - -START_TEST( test_acl_update_leaves_good_client ) +END_TEST START_TEST(test_acl_update_leaves_good_client) { - struct flexnbd flexnbd; - flexnbd.signal_fd = -1; + struct flexnbd flexnbd; + flexnbd.signal_fd = -1; - struct server * s = server_create( &flexnbd, "127.0.0.7", "0", dummy_file, 0, 0, NULL, 1, 0, 1 ); + struct server *s = + server_create(&flexnbd, "127.0.0.7", "0", dummy_file, 0, 0, NULL, + 1, 0, 1); - char *lines[] = {"127.0.0.1"}; - struct acl * new_acl = acl_create( 1, lines, 1 ); - struct client * c; - struct client_tbl_entry * entry; + char *lines[] = { "127.0.0.1" }; + struct acl *new_acl = acl_create(1, lines, 1); + struct client *c; + struct client_tbl_entry *entry; - int actual_port; - int client_fd; - int server_fd; + int actual_port; + int client_fd; + int server_fd; - serve_open_server_socket( s ); - actual_port = server_port( s ); - client_fd = connect_client( "127.0.0.7", actual_port, "127.0.0.1" ); - server_accept( s ); - entry = &s->nbd_client[0]; - c = entry->client; - /* At this point there should be an entry in the nbd_clients - * table and a background thread to run the client loop - */ - myfail_if( entry->thread == 0, "No client thread was started." ); - server_fd = c->socket; - myfail_if( fd_is_closed(server_fd), - "Sanity check failed - client socket wasn't open." ); + serve_open_server_socket(s); + actual_port = server_port(s); + client_fd = connect_client("127.0.0.7", actual_port, "127.0.0.1"); + server_accept(s); + entry = &s->nbd_client[0]; + c = entry->client; + /* At this point there should be an entry in the nbd_clients + * table and a background thread to run the client loop + */ + myfail_if(entry->thread == 0, "No client thread was started."); + server_fd = c->socket; + myfail_if(fd_is_closed(server_fd), + "Sanity check failed - client socket wasn't open."); - server_replace_acl( s, new_acl ); - server_accept( s ); + server_replace_acl(s, new_acl); + server_accept(s); - myfail_if( self_pipe_signal_clear( c->stop_signal ), - "Client was told to stop." ); + myfail_if(self_pipe_signal_clear(c->stop_signal), + "Client was told to stop."); - close( client_fd ); - server_close_clients( s ); - server_destroy( s ); + close(client_fd); + server_close_clients(s); + server_destroy(s); } -END_TEST - -Suite* serve_suite(void) +END_TEST Suite * serve_suite(void) { - Suite *s = suite_create("serve"); - TCase *tc_acl_update = tcase_create("acl_update"); + Suite *s = suite_create("serve"); + TCase *tc_acl_update = tcase_create("acl_update"); - tcase_add_checked_fixture( tc_acl_update, setup, NULL ); + tcase_add_checked_fixture(tc_acl_update, setup, NULL); - tcase_add_test(tc_acl_update, test_replaces_acl); - tcase_add_test(tc_acl_update, test_signals_acl_updated); + tcase_add_test(tc_acl_update, test_replaces_acl); + tcase_add_test(tc_acl_update, test_signals_acl_updated); - tcase_add_exit_test(tc_acl_update, test_acl_update_closes_bad_client, 0); - tcase_add_exit_test(tc_acl_update, test_acl_update_leaves_good_client, 0); + tcase_add_exit_test(tc_acl_update, test_acl_update_closes_bad_client, + 0); + tcase_add_exit_test(tc_acl_update, test_acl_update_leaves_good_client, + 0); - suite_add_tcase(s, tc_acl_update); + suite_add_tcase(s, tc_acl_update); - return s; + return s; } int main(void) { - log_level = LOG_LEVEL; - error_init(); - 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; + log_level = LOG_LEVEL; + error_init(); + 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; } - diff --git a/tests/unit/check_sockutil.c b/tests/unit/check_sockutil.c index 57626bb..dc7295f 100644 --- a/tests/unit/check_sockutil.c +++ b/tests/unit/check_sockutil.c @@ -6,110 +6,112 @@ #include -START_TEST( test_sockaddr_address_string_af_inet_converts_to_string ) +START_TEST(test_sockaddr_address_string_af_inet_converts_to_string) { - struct sockaddr sa; - struct sockaddr_in* v4 = (struct sockaddr_in*) &sa; - char testbuf[128]; - const char* result; + struct sockaddr sa; + struct sockaddr_in *v4 = (struct sockaddr_in *) &sa; + char testbuf[128]; + const char *result; - v4->sin_family = AF_INET; - v4->sin_port = htons( 4777 ); - ck_assert_int_eq( 1, inet_pton( AF_INET, "192.168.0.1", &v4->sin_addr )); + v4->sin_family = AF_INET; + v4->sin_port = htons(4777); + ck_assert_int_eq(1, inet_pton(AF_INET, "192.168.0.1", &v4->sin_addr)); - result = sockaddr_address_string( &sa, &testbuf[0], 128 ); - ck_assert( result != NULL ); + result = sockaddr_address_string(&sa, &testbuf[0], 128); + ck_assert(result != NULL); - ck_assert_str_eq( "192.168.0.1 port 4777", testbuf ); + ck_assert_str_eq("192.168.0.1 port 4777", testbuf); } + END_TEST - - -START_TEST( test_sockaddr_address_string_af_inet6_converts_to_string ) +START_TEST(test_sockaddr_address_string_af_inet6_converts_to_string) { - struct sockaddr_in6 v6_raw; - struct sockaddr_in6* v6 = &v6_raw; - struct sockaddr* sa = (struct sockaddr*) &v6_raw; + struct sockaddr_in6 v6_raw; + struct sockaddr_in6 *v6 = &v6_raw; + struct sockaddr *sa = (struct sockaddr *) &v6_raw; - char testbuf[128]; - const char* result; + char testbuf[128]; + const char *result; - v6->sin6_family = AF_INET6; - v6->sin6_port = htons( 4777 ); - ck_assert_int_eq( 1, inet_pton( AF_INET6, "fe80::1", &v6->sin6_addr )); + v6->sin6_family = AF_INET6; + v6->sin6_port = htons(4777); + ck_assert_int_eq(1, inet_pton(AF_INET6, "fe80::1", &v6->sin6_addr)); - result = sockaddr_address_string( sa, &testbuf[0], 128 ); - ck_assert( result != NULL ); + result = sockaddr_address_string(sa, &testbuf[0], 128); + ck_assert(result != NULL); - ck_assert_str_eq( "fe80::1 port 4777", testbuf ); + ck_assert_str_eq("fe80::1 port 4777", testbuf); } -END_TEST +END_TEST /* We don't know what it is, so we just call it "???" and return NULL */ -START_TEST( test_sockaddr_address_string_af_unspec_is_failure ) +START_TEST(test_sockaddr_address_string_af_unspec_is_failure) { - struct sockaddr sa; - struct sockaddr_in* v4 = (struct sockaddr_in*) &sa; - char testbuf[128]; - const char* result; + struct sockaddr sa; + struct sockaddr_in *v4 = (struct sockaddr_in *) &sa; + char testbuf[128]; + const char *result; - v4->sin_family = AF_UNSPEC; - v4->sin_port = htons( 4777 ); - ck_assert_int_eq( 1, inet_pton( AF_INET, "192.168.0.1", &v4->sin_addr )); + v4->sin_family = AF_UNSPEC; + v4->sin_port = htons(4777); + ck_assert_int_eq(1, inet_pton(AF_INET, "192.168.0.1", &v4->sin_addr)); - result = sockaddr_address_string( &sa, &testbuf[0], 128 ); - ck_assert( result == NULL ); + result = sockaddr_address_string(&sa, &testbuf[0], 128); + ck_assert(result == NULL); - ck_assert_str_eq( "???", testbuf ); + ck_assert_str_eq("???", testbuf); } -END_TEST +END_TEST /* This is a complete failure to parse, rather than a partial failure */ -START_TEST( test_sockaddr_address_string_doesnt_overflow_short_buffer ) +START_TEST(test_sockaddr_address_string_doesnt_overflow_short_buffer) { - struct sockaddr sa; - struct sockaddr_in* v4 = (struct sockaddr_in*) &sa; - char testbuf[128]; - const char* result; + struct sockaddr sa; + struct sockaddr_in *v4 = (struct sockaddr_in *) &sa; + char testbuf[128]; + const char *result; - memset( testbuf, 0, 128 ); - v4->sin_family = AF_INET; - v4->sin_port = htons( 4777 ); - ck_assert_int_eq( 1, inet_pton( AF_INET, "192.168.0.1", &v4->sin_addr )); - memset( &testbuf, 0, 128 ); + memset(testbuf, 0, 128); + v4->sin_family = AF_INET; + v4->sin_port = htons(4777); + ck_assert_int_eq(1, inet_pton(AF_INET, "192.168.0.1", &v4->sin_addr)); + memset(&testbuf, 0, 128); - result = sockaddr_address_string( &sa, &testbuf[0], 2 ); - ck_assert( result == NULL ); + result = sockaddr_address_string(&sa, &testbuf[0], 2); + ck_assert(result == NULL); - ck_assert_str_eq( "??", testbuf ); + ck_assert_str_eq("??", testbuf); } -END_TEST -Suite *sockutil_suite(void) +END_TEST Suite * sockutil_suite(void) { - Suite *s = suite_create("sockutil"); + Suite *s = suite_create("sockutil"); - TCase *tc_sockaddr_address_string = tcase_create("sockaddr_address_string"); + TCase *tc_sockaddr_address_string = + tcase_create("sockaddr_address_string"); - tcase_add_test(tc_sockaddr_address_string, test_sockaddr_address_string_af_inet_converts_to_string); - tcase_add_test(tc_sockaddr_address_string, test_sockaddr_address_string_af_inet6_converts_to_string); - tcase_add_test(tc_sockaddr_address_string, test_sockaddr_address_string_af_unspec_is_failure); - tcase_add_test(tc_sockaddr_address_string, test_sockaddr_address_string_doesnt_overflow_short_buffer); - suite_add_tcase(s, tc_sockaddr_address_string); + tcase_add_test(tc_sockaddr_address_string, + test_sockaddr_address_string_af_inet_converts_to_string); + tcase_add_test(tc_sockaddr_address_string, + test_sockaddr_address_string_af_inet6_converts_to_string); + tcase_add_test(tc_sockaddr_address_string, + test_sockaddr_address_string_af_unspec_is_failure); + tcase_add_test(tc_sockaddr_address_string, + test_sockaddr_address_string_doesnt_overflow_short_buffer); + suite_add_tcase(s, tc_sockaddr_address_string); - return s; + return s; } int main(void) { - int number_failed; + int number_failed; - Suite *s = sockutil_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; + Suite *s = sockutil_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; } - diff --git a/tests/unit/check_status.c b/tests/unit/check_status.c index ea89d3b..8c37563 100644 --- a/tests/unit/check_status.c +++ b/tests/unit/check_status.c @@ -6,366 +6,331 @@ #include -struct server* mock_server(void) +struct server *mock_server(void) { - struct server* out = xmalloc( sizeof( struct server ) ); - out->l_start_mirror = flexthread_mutex_create(); - out->nbd_client = xmalloc( sizeof( struct client_tbl_entry ) * 4 ); - out->max_nbd_clients = 4; - out->size = 65536; + struct server *out = xmalloc(sizeof(struct server)); + out->l_start_mirror = flexthread_mutex_create(); + out->nbd_client = xmalloc(sizeof(struct client_tbl_entry) * 4); + out->max_nbd_clients = 4; + out->size = 65536; - out->allocation_map = bitset_alloc( 65536, 4096 ); + out->allocation_map = bitset_alloc(65536, 4096); - return out; + return out; } -struct server* mock_mirroring_server(void) +struct server *mock_mirroring_server(void) { - struct server *out = mock_server(); - out->mirror = xmalloc( sizeof( struct mirror ) ); - out->mirror_super = xmalloc( sizeof( struct mirror_super ) ); - return out; + struct server *out = mock_server(); + out->mirror = xmalloc(sizeof(struct mirror)); + out->mirror_super = xmalloc(sizeof(struct mirror_super)); + return out; } -void destroy_mock_server( struct server* serve ) +void destroy_mock_server(struct server *serve) { - if ( NULL != serve->mirror ) { - free( serve->mirror ); - } + if (NULL != serve->mirror) { + free(serve->mirror); + } - if ( NULL != serve->mirror_super ) { - free( serve->mirror_super ); - } + if (NULL != serve->mirror_super) { + free(serve->mirror_super); + } - flexthread_mutex_destroy( serve->l_start_mirror ); + flexthread_mutex_destroy(serve->l_start_mirror); - bitset_free( serve->allocation_map ); - free( serve->nbd_client ); - free( serve ); + bitset_free(serve->allocation_map); + free(serve->nbd_client); + free(serve); } -START_TEST( test_status_create ) +START_TEST(test_status_create) { - struct server * server = mock_server(); - struct status * status = status_create( server ); + struct server *server = mock_server(); + struct status *status = status_create(server); - fail_if( NULL == status, "Status wasn't allocated" ); - status_destroy( status ); - destroy_mock_server( server ); + fail_if(NULL == status, "Status wasn't allocated"); + status_destroy(status); + destroy_mock_server(server); } -END_TEST -START_TEST( test_gets_has_control ) +END_TEST START_TEST(test_gets_has_control) { - struct server * server = mock_server(); - server->success = 1; + struct server *server = mock_server(); + server->success = 1; - struct status * status = status_create( server ); + struct status *status = status_create(server); - fail_unless( status->has_control == 1, "has_control wasn't copied" ); - status_destroy( status ); - destroy_mock_server( server ); + fail_unless(status->has_control == 1, "has_control wasn't copied"); + status_destroy(status); + destroy_mock_server(server); } -END_TEST - -START_TEST( test_gets_is_mirroring ) +END_TEST START_TEST(test_gets_is_mirroring) { - struct server * server = mock_server(); - struct status * status = status_create( server ); + struct server *server = mock_server(); + struct status *status = status_create(server); - fail_if( status->is_mirroring, "is_mirroring was set" ); - status_destroy( status ); - destroy_mock_server( server ); + fail_if(status->is_mirroring, "is_mirroring was set"); + status_destroy(status); + destroy_mock_server(server); - server = mock_mirroring_server(); - status = status_create( server ); + server = mock_mirroring_server(); + status = status_create(server); - fail_unless( status->is_mirroring, "is_mirroring wasn't set" ); - status_destroy( status ); - destroy_mock_server( server ); + fail_unless(status->is_mirroring, "is_mirroring wasn't set"); + status_destroy(status); + destroy_mock_server(server); } -END_TEST -START_TEST( test_gets_clients_allowed ) +END_TEST START_TEST(test_gets_clients_allowed) { - struct server * server = mock_server(); - struct status * status = status_create( server ); + struct server *server = mock_server(); + struct status *status = status_create(server); - fail_if( status->clients_allowed, "clients_allowed was set" ); - status_destroy( status ); + fail_if(status->clients_allowed, "clients_allowed was set"); + status_destroy(status); - server->allow_new_clients = 1; - status = status_create( server ); + server->allow_new_clients = 1; + status = status_create(server); - fail_unless( status->clients_allowed, "clients_allowed was not set" ); - status_destroy( status ); - destroy_mock_server( server ); + fail_unless(status->clients_allowed, "clients_allowed was not set"); + status_destroy(status); + destroy_mock_server(server); } -END_TEST -START_TEST( test_gets_pid ) +END_TEST START_TEST(test_gets_pid) { - struct server * server = mock_server(); - struct status * status = status_create( server ); + struct server *server = mock_server(); + struct status *status = status_create(server); - fail_unless( getpid() == status->pid, "Pid wasn't gathered" ); + fail_unless(getpid() == status->pid, "Pid wasn't gathered"); - status_destroy( status ); - destroy_mock_server( server ); + status_destroy(status); + destroy_mock_server(server); } -END_TEST -START_TEST( test_gets_size ) +END_TEST START_TEST(test_gets_size) { - struct server * server = mock_server(); - server->size = 1024; + struct server *server = mock_server(); + server->size = 1024; - struct status * status = status_create( server ); + struct status *status = status_create(server); - fail_unless( 1024 == status->size, "Size wasn't gathered" ); + fail_unless(1024 == status->size, "Size wasn't gathered"); - status_destroy( status ); - destroy_mock_server( server ); + status_destroy(status); + destroy_mock_server(server); } -END_TEST -START_TEST( test_gets_migration_statistics ) +END_TEST START_TEST(test_gets_migration_statistics) { - struct server * server = mock_mirroring_server(); - server->mirror->all_dirty = 16384; - server->mirror->max_bytes_per_second = 32768; - server->mirror->offset = 0; + struct server *server = mock_mirroring_server(); + server->mirror->all_dirty = 16384; + server->mirror->max_bytes_per_second = 32768; + server->mirror->offset = 0; - /* we have a bit of a time dependency here */ - server->mirror->migration_started = monotonic_time_ms(); + /* we have a bit of a time dependency here */ + server->mirror->migration_started = monotonic_time_ms(); - struct status * status = status_create( server ); + struct status *status = status_create(server); - fail_unless ( - 0 == status->migration_duration || + fail_unless(0 == status->migration_duration || 1 == status->migration_duration || 2 == status->migration_duration, - "migration_duration is unreasonable!" - ); + "migration_duration is unreasonable!"); - fail_unless( - 16384 / ( status->migration_duration + 1 ) == status->migration_speed, - "migration_speed not calculated correctly" - ); + fail_unless(16384 / (status->migration_duration + 1) == + status->migration_speed, + "migration_speed not calculated correctly"); - fail_unless( 32768 == status->migration_speed_limit, "migration_speed_limit not read" ); + fail_unless(32768 == status->migration_speed_limit, + "migration_speed_limit not read"); - // ( size / current_bps ) + 1 happens to be 3 for this test - fail_unless( 3 == status->migration_seconds_left, "migration_seconds_left not gathered" ); + // ( size / current_bps ) + 1 happens to be 3 for this test + fail_unless(3 == status->migration_seconds_left, + "migration_seconds_left not gathered"); - status_destroy( status ); - destroy_mock_server( server ); + status_destroy(status); + destroy_mock_server(server); } + END_TEST - - #define RENDER_TEST_SETUP \ struct status status; \ int fds[2]; \ pipe( fds ); - -void fail_unless_rendered( int fd, char *fragment ) +void fail_unless_rendered(int fd, char *fragment) { - char buf[1024] = {0}; - char emsg[1024] = {0}; - char *found = NULL; + char buf[1024] = { 0 }; + char emsg[1024] = { 0 }; + char *found = NULL; - sprintf(emsg, "Fragment: %s not found", fragment ); + sprintf(emsg, "Fragment: %s not found", fragment); - fail_unless( read_until_newline( fd, buf, 1024 ) > 0, "Couldn't read" ); - found = strstr( buf, fragment ); - fail_if( NULL == found, emsg ); + fail_unless(read_until_newline(fd, buf, 1024) > 0, "Couldn't read"); + found = strstr(buf, fragment); + fail_if(NULL == found, emsg); - return; + return; } -void fail_if_rendered( int fd, char *fragment ) +void fail_if_rendered(int fd, char *fragment) { - char buf[1024] = {0}; - char emsg[1024] = {0}; - char *found = NULL; + char buf[1024] = { 0 }; + char emsg[1024] = { 0 }; + char *found = NULL; - sprintf(emsg, "Fragment: %s found", fragment ); + sprintf(emsg, "Fragment: %s found", fragment); - fail_unless( read_until_newline( fd, buf, 1024 ) > 0, "Couldn't read" ); - found = strstr( buf, fragment ); - fail_unless( NULL == found, emsg ); + fail_unless(read_until_newline(fd, buf, 1024) > 0, "Couldn't read"); + found = strstr(buf, fragment); + fail_unless(NULL == found, emsg); - return; + return; } -START_TEST( test_renders_has_control ) +START_TEST(test_renders_has_control) { - RENDER_TEST_SETUP + RENDER_TEST_SETUP status.has_control = 1; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "has_control=true"); - status.has_control = 1; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "has_control=true" ); - - status.has_control = 0; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "has_control=false" ); + status.has_control = 0; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "has_control=false"); } -END_TEST - -START_TEST( test_renders_is_mirroring ) +END_TEST START_TEST(test_renders_is_mirroring) { - RENDER_TEST_SETUP + RENDER_TEST_SETUP status.is_mirroring = 1; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "is_mirroring=true"); - status.is_mirroring = 1; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "is_mirroring=true" ); - - status.is_mirroring = 0; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "is_mirroring=false" ); + status.is_mirroring = 0; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "is_mirroring=false"); } -END_TEST -START_TEST( test_renders_clients_allowed ) +END_TEST START_TEST(test_renders_clients_allowed) { - RENDER_TEST_SETUP + RENDER_TEST_SETUP status.clients_allowed = 1; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "clients_allowed=true"); - status.clients_allowed = 1; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "clients_allowed=true" ); - - status.clients_allowed = 0; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "clients_allowed=false" ); + status.clients_allowed = 0; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "clients_allowed=false"); } -END_TEST -START_TEST( test_renders_num_clients ) +END_TEST START_TEST(test_renders_num_clients) { - RENDER_TEST_SETUP + RENDER_TEST_SETUP status.num_clients = 0; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "num_clients=0"); - status.num_clients = 0; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "num_clients=0" ); - - status.num_clients = 4000; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "num_clients=4000" ); + status.num_clients = 4000; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "num_clients=4000"); } -END_TEST - -START_TEST( test_renders_pid ) +END_TEST START_TEST(test_renders_pid) { - RENDER_TEST_SETUP - - status.pid = 42; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "pid=42" ); + RENDER_TEST_SETUP status.pid = 42; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "pid=42"); } -END_TEST -START_TEST( test_renders_size ) +END_TEST START_TEST(test_renders_size) { - RENDER_TEST_SETUP - - status.size = ( (uint64_t)1 << 33 ); - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "size=8589934592" ); + RENDER_TEST_SETUP status.size = ((uint64_t) 1 << 33); + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "size=8589934592"); } -END_TEST -START_TEST( test_renders_migration_statistics ) +END_TEST START_TEST(test_renders_migration_statistics) { - RENDER_TEST_SETUP + RENDER_TEST_SETUP status.is_mirroring = 0; + status.migration_duration = 8; + status.migration_speed = 40000000; + status.migration_speed_limit = 40000001; + status.migration_seconds_left = 1; + status.migration_bytes_left = 5000; - status.is_mirroring = 0; - status.migration_duration = 8; - status.migration_speed = 40000000; - status.migration_speed_limit = 40000001; - status.migration_seconds_left = 1; - status.migration_bytes_left = 5000; + status_write(&status, fds[1]); + fail_if_rendered(fds[0], "migration_duration"); - status_write( &status, fds[1] ); - fail_if_rendered( fds[0], "migration_duration" ); + status_write(&status, fds[1]); + fail_if_rendered(fds[0], "migration_speed"); - status_write( &status, fds[1] ); - fail_if_rendered( fds[0], "migration_speed" ); + status_write(&status, fds[1]); + fail_if_rendered(fds[0], "migration_speed_limit"); - status_write( &status, fds[1] ); - fail_if_rendered( fds[0], "migration_speed_limit" ); + status_write(&status, fds[1]); + fail_if_rendered(fds[0], "migration_seconds_left"); - status_write( &status, fds[1] ); - fail_if_rendered( fds[0], "migration_seconds_left" ); + status.is_mirroring = 1; - status.is_mirroring = 1; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "migration_duration=8"); - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "migration_duration=8" ); + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "migration_speed=40000000"); - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "migration_speed=40000000" ); + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "migration_speed_limit=40000001"); - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "migration_speed_limit=40000001" ); + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "migration_seconds_left=1"); - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "migration_seconds_left=1" ); + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "migration_bytes_left=5000"); - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "migration_bytes_left=5000" ); + status.migration_speed_limit = UINT64_MAX; - status.migration_speed_limit = UINT64_MAX; - - status_write( &status, fds[1] ); - fail_if_rendered( fds[0], "migration_speed_limit" ); + status_write(&status, fds[1]); + fail_if_rendered(fds[0], "migration_speed_limit"); } -END_TEST - -Suite *status_suite(void) +END_TEST Suite * status_suite(void) { - Suite *s = suite_create("status"); - TCase *tc_create = tcase_create("create"); - TCase *tc_render = tcase_create("render"); + Suite *s = suite_create("status"); + TCase *tc_create = tcase_create("create"); + TCase *tc_render = tcase_create("render"); - tcase_add_test(tc_create, test_status_create); - tcase_add_test(tc_create, test_gets_has_control); - tcase_add_test(tc_create, test_gets_is_mirroring); - tcase_add_test(tc_create, test_gets_clients_allowed); - tcase_add_test(tc_create, test_gets_pid); - tcase_add_test(tc_create, test_gets_size); - tcase_add_test(tc_create, test_gets_migration_statistics); + tcase_add_test(tc_create, test_status_create); + tcase_add_test(tc_create, test_gets_has_control); + tcase_add_test(tc_create, test_gets_is_mirroring); + tcase_add_test(tc_create, test_gets_clients_allowed); + tcase_add_test(tc_create, test_gets_pid); + tcase_add_test(tc_create, test_gets_size); + tcase_add_test(tc_create, test_gets_migration_statistics); - tcase_add_test(tc_render, test_renders_has_control); - tcase_add_test(tc_render, test_renders_is_mirroring); - tcase_add_test(tc_render, test_renders_clients_allowed); - tcase_add_test(tc_render, test_renders_num_clients); - tcase_add_test(tc_render, test_renders_pid); - tcase_add_test(tc_render, test_renders_size); - tcase_add_test(tc_render, test_renders_migration_statistics); + tcase_add_test(tc_render, test_renders_has_control); + tcase_add_test(tc_render, test_renders_is_mirroring); + tcase_add_test(tc_render, test_renders_clients_allowed); + tcase_add_test(tc_render, test_renders_num_clients); + tcase_add_test(tc_render, test_renders_pid); + tcase_add_test(tc_render, test_renders_size); + tcase_add_test(tc_render, test_renders_migration_statistics); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_render); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_render); - return s; + return s; } int main(void) { - int number_failed; + int number_failed; - Suite *s = status_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; + Suite *s = status_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; } - diff --git a/tests/unit/check_util.c b/tests/unit/check_util.c index 63e2ade..5fdd588 100644 --- a/tests/unit/check_util.c +++ b/tests/unit/check_util.c @@ -9,165 +9,156 @@ struct cleanup_bucket { - struct self_pipe *called_signal; + struct self_pipe *called_signal; }; struct cleanup_bucket bkt; -void bucket_init(void){ - if ( bkt.called_signal ) { - self_pipe_destroy( bkt.called_signal ); - } - bkt.called_signal = self_pipe_create(); +void bucket_init(void) +{ + if (bkt.called_signal) { + self_pipe_destroy(bkt.called_signal); + } + bkt.called_signal = self_pipe_create(); } void setup(void) { - bkt.called_signal = NULL; + bkt.called_signal = NULL; } int handler_called(void) { - return self_pipe_signal_clear( bkt.called_signal ); + return self_pipe_signal_clear(bkt.called_signal); } -void dummy_cleanup( struct cleanup_bucket * foo, int fatal __attribute__((unused)) ) +void dummy_cleanup(struct cleanup_bucket *foo, int fatal + __attribute__ ((unused))) { - if (NULL != foo){ - self_pipe_signal( foo->called_signal ); - } + if (NULL != foo) { + self_pipe_signal(foo->called_signal); + } } void trigger_fatal(void) -{ - error_init(); - error_set_handler( (cleanup_handler*) dummy_cleanup, &bkt ); +{ + error_init(); + error_set_handler((cleanup_handler *) dummy_cleanup, &bkt); - log_level = 5; + log_level = 5; - fatal("Expected fatal error"); + fatal("Expected fatal error"); } -void trigger_error( void ) +void trigger_error(void) { - error_init(); - error_set_handler( (cleanup_handler *) dummy_cleanup, &bkt); - log_level = 4; - error("Expected error"); + error_init(); + error_set_handler((cleanup_handler *) dummy_cleanup, &bkt); + log_level = 4; + error("Expected error"); } -START_TEST( test_fatal_kills_process ) +START_TEST(test_fatal_kills_process) { - pid_t pid; + pid_t pid; - pid = fork(); + pid = fork(); - if ( pid == 0 ) { - trigger_fatal(); - /* If we get here, just block so the test timeout fails - * us */ - sleep(10); - } - else { - int kidret, kidstatus, result; - result = waitpid( pid, &kidret, 0 ); - fail_if( result < 0, "Wait failed." ); - fail_unless( WIFSIGNALED( kidret ), "Process didn't exit via signal" ); - kidstatus = WTERMSIG( kidret ); - ck_assert_int_eq( kidstatus, SIGABRT ); - } + if (pid == 0) { + trigger_fatal(); + /* If we get here, just block so the test timeout fails + * us */ + sleep(10); + } else { + int kidret, kidstatus, result; + result = waitpid(pid, &kidret, 0); + fail_if(result < 0, "Wait failed."); + fail_unless(WIFSIGNALED(kidret), "Process didn't exit via signal"); + kidstatus = WTERMSIG(kidret); + ck_assert_int_eq(kidstatus, SIGABRT); + } } -END_TEST - -void * error_thread( void *nothing __attribute__((unused)) ) +END_TEST void *error_thread(void *nothing __attribute__ ((unused))) { - trigger_error(); - return NULL; + trigger_error(); + return NULL; } -START_TEST( test_error_doesnt_kill_process ) +START_TEST(test_error_doesnt_kill_process) { - bucket_init(); - pthread_attr_t attr; - pthread_t tid; + bucket_init(); + pthread_attr_t attr; + pthread_t tid; - pthread_attr_init( &attr ); + pthread_attr_init(&attr); - pthread_create( &tid, &attr, error_thread, NULL ); - pthread_join( tid, NULL ); + pthread_create(&tid, &attr, error_thread, NULL); + pthread_join(tid, NULL); } -END_TEST - -START_TEST( test_error_calls_handler ) +END_TEST START_TEST(test_error_calls_handler) { - bucket_init(); + bucket_init(); - pthread_attr_t attr; - pthread_t tid; + pthread_attr_t attr; + pthread_t tid; - pthread_attr_init( &attr ); + pthread_attr_init(&attr); - pthread_create( &tid, &attr, error_thread, NULL ); - pthread_join( tid, NULL ); - fail_unless( handler_called(), "Handler wasn't called." ); + pthread_create(&tid, &attr, error_thread, NULL); + pthread_join(tid, NULL); + fail_unless(handler_called(), "Handler wasn't called."); } -END_TEST - -START_TEST( test_fatal_doesnt_call_handler ) +END_TEST START_TEST(test_fatal_doesnt_call_handler) { - bucket_init(); + bucket_init(); - pid_t kidpid; + pid_t kidpid; - kidpid = fork(); - if ( kidpid == 0 ) { - trigger_fatal(); - } - else { - int kidstatus; - int result = waitpid( kidpid, &kidstatus, 0 ); - fail_if( result < 0, "Wait failed" ); - fail_if( handler_called(), "Handler was called."); - } + kidpid = fork(); + if (kidpid == 0) { + trigger_fatal(); + } else { + int kidstatus; + int result = waitpid(kidpid, &kidstatus, 0); + fail_if(result < 0, "Wait failed"); + fail_if(handler_called(), "Handler was called."); + } } -END_TEST - -Suite* util_suite(void) +END_TEST Suite * util_suite(void) { - Suite *s = suite_create("util"); - TCase *tc_process = tcase_create("process"); - TCase *tc_handler = tcase_create("handler"); + Suite *s = suite_create("util"); + TCase *tc_process = tcase_create("process"); + TCase *tc_handler = tcase_create("handler"); - tcase_add_checked_fixture( tc_process, setup, NULL ); + tcase_add_checked_fixture(tc_process, setup, NULL); - tcase_add_test(tc_process, test_fatal_kills_process); - tcase_add_test(tc_process, test_error_doesnt_kill_process); - tcase_add_test(tc_handler, test_error_calls_handler ); - tcase_add_test(tc_handler, test_fatal_doesnt_call_handler); + tcase_add_test(tc_process, test_fatal_kills_process); + tcase_add_test(tc_process, test_error_doesnt_kill_process); + tcase_add_test(tc_handler, test_error_calls_handler); + tcase_add_test(tc_handler, test_fatal_doesnt_call_handler); - suite_add_tcase(s, tc_process); - suite_add_tcase(s, tc_handler); - - return s; + suite_add_tcase(s, tc_process); + suite_add_tcase(s, tc_handler); + + return s; } int main(void) { - int number_failed; - Suite *s = util_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; + int number_failed; + Suite *s = util_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; } - From 7bee1aadfeb5fde65279932ae663d23658ca7606 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 20 Feb 2018 10:11:38 +0000 Subject: [PATCH 67/71] Enable request flags test Missed this out when I wrote the test! --- tests/unit/check_nbdtypes.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/check_nbdtypes.c b/tests/unit/check_nbdtypes.c index 9124063..8665818 100644 --- a/tests/unit/check_nbdtypes.c +++ b/tests/unit/check_nbdtypes.c @@ -230,6 +230,7 @@ Suite *nbdtypes_suite(void) tcase_add_test( tc_init, test_init_size ); tcase_add_test( tc_request, test_request_magic ); tcase_add_test( tc_request, test_request_type ); + tcase_add_test( tc_request, test_request_flags ); tcase_add_test( tc_request, test_request_handle ); tcase_add_test( tc_request, test_request_from ); tcase_add_test( tc_request, test_request_len ); From 103bd7ad5b1894b05df21d1671bd4aea43d18b28 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 20 Feb 2018 10:13:42 +0000 Subject: [PATCH 68/71] Undo formatting on test suite -- it wasn't right --- tests/unit/check_acl.c | 331 ++++++++--------- tests/unit/check_bitset.c | 655 +++++++++++++++++----------------- tests/unit/check_client.c | 128 ++++--- tests/unit/check_control.c | 41 ++- tests/unit/check_flexnbd.c | 50 +-- tests/unit/check_flexthread.c | 70 ++-- tests/unit/check_ioutil.c | 166 +++++---- tests/unit/check_mbox.c | 120 ++++--- tests/unit/check_nbdtypes.c | 351 +++++++++--------- tests/unit/check_parse.c | 46 +-- tests/unit/check_readwrite.c | 204 +++++------ tests/unit/check_self_pipe.c | 300 ++++++++-------- tests/unit/check_serve.c | 334 +++++++++-------- tests/unit/check_sockutil.c | 140 ++++---- tests/unit/check_status.c | 441 ++++++++++++----------- tests/unit/check_util.c | 189 +++++----- 16 files changed, 1844 insertions(+), 1722 deletions(-) diff --git a/tests/unit/check_acl.c b/tests/unit/check_acl.c index 6aac7ea..bb12f81 100644 --- a/tests/unit/check_acl.c +++ b/tests/unit/check_acl.c @@ -4,221 +4,226 @@ #include "acl.h" #include "util.h" -START_TEST(test_null_acl) +START_TEST( test_null_acl ) { - struct acl *acl = acl_create(0, NULL, 0); + struct acl *acl = acl_create( 0,NULL, 0 ); - fail_if(NULL == acl, "No acl alloced."); - fail_unless(0 == acl->len, "Incorrect length"); + fail_if( NULL == acl, "No acl alloced." ); + fail_unless( 0 == acl->len, "Incorrect length" ); } - -END_TEST START_TEST(test_parses_single_line) -{ - char *lines[] = { "127.0.0.1" }; - struct acl *acl = acl_create(1, lines, 0); - - fail_unless(1 == acl->len, "Incorrect length."); - fail_if(NULL == acl->entries, "No entries present."); -} - -END_TEST START_TEST(test_parses_multiple_lines) -{ - char *lines[] = { "127.0.0.1", "::1" }; - struct acl *acl = acl_create(2, lines, 0); - union mysockaddr e0, e1; - - parse_ip_to_sockaddr(&e0.generic, lines[0]); - parse_ip_to_sockaddr(&e1.generic, lines[1]); - - fail_unless(acl->len == 2, "Multiple lines not parsed"); - - struct ip_and_mask *entry; - entry = &(*acl->entries)[0]; - fail_unless(entry->ip.family == e0.family, - "entry 0 has wrong family!"); - entry = &(*acl->entries)[1]; - fail_unless(entry->ip.family == e1.family, - "entry 1 has wrong family!"); -} - -END_TEST START_TEST(test_destroy_doesnt_crash) -{ - char *lines[] = { "127.0.0.1" }; - struct acl *acl = acl_create(1, lines, 0); - - acl_destroy(acl); -} - -END_TEST START_TEST(test_includes_single_address) -{ - char *lines[] = { "127.0.0.1" }; - struct acl *acl = acl_create(1, lines, 0); - union mysockaddr x; - - parse_ip_to_sockaddr(&x.generic, "127.0.0.1"); - - fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); -} - END_TEST -START_TEST(test_includes_single_address_when_netmask_specified_ipv4) + + +START_TEST( test_parses_single_line ) { - char *lines[] = { "127.0.0.1/24" }; - struct acl *acl = acl_create(1, lines, 0); - union mysockaddr x; + char *lines[] = {"127.0.0.1"}; + struct acl * acl = acl_create( 1, lines, 0 ); - parse_ip_to_sockaddr(&x.generic, "127.0.0.0"); - fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); - - parse_ip_to_sockaddr(&x.generic, "127.0.0.1"); - fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); - - parse_ip_to_sockaddr(&x.generic, "127.0.0.255"); - fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); + fail_unless( 1 == acl->len, "Incorrect length." ); + fail_if( NULL == acl->entries, "No entries present." ); } - END_TEST -START_TEST(test_includes_single_address_when_netmask_specified_ipv6) + +START_TEST( test_parses_multiple_lines ) { - char *lines[] = { "fe80::/10" }; - struct acl *acl = acl_create(1, lines, 0); - union mysockaddr x; + char *lines[] = {"127.0.0.1", "::1"}; + struct acl * acl = acl_create( 2, lines, 0 ); + union mysockaddr e0, e1; - parse_ip_to_sockaddr(&x.generic, "fe80::1"); - fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); + parse_ip_to_sockaddr( &e0.generic, lines[0] ); + parse_ip_to_sockaddr( &e1.generic, lines[1] ); - parse_ip_to_sockaddr(&x.generic, "fe80::2"); - fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); + fail_unless( acl->len == 2, "Multiple lines not parsed" ); - parse_ip_to_sockaddr(&x.generic, "fe80:ffff:ffff::ffff"); - fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); + struct ip_and_mask *entry; + entry = &(*acl->entries)[0]; + fail_unless(entry->ip.family == e0.family, "entry 0 has wrong family!"); + entry = &(*acl->entries)[1]; + fail_unless(entry->ip.family == e1.family, "entry 1 has wrong family!"); } - END_TEST -START_TEST(test_includes_single_address_when_multiple_entries_exist) + +START_TEST( test_destroy_doesnt_crash ) { - char *lines[] = { "127.0.0.1", "::1" }; - struct acl *acl = acl_create(2, lines, 0); - union mysockaddr e0; - union mysockaddr e1; + char *lines[] = {"127.0.0.1"}; + struct acl * acl = acl_create( 1, lines, 0 ); - parse_ip_to_sockaddr(&e0.generic, "127.0.0.1"); - parse_ip_to_sockaddr(&e1.generic, "::1"); - - fail_unless(acl_includes(acl, &e0), - "Included address 0 wasn't covered"); - fail_unless(acl_includes(acl, &e1), - "Included address 1 wasn't covered"); + acl_destroy( acl ); } - -END_TEST START_TEST(test_doesnt_include_other_address) -{ - char *lines[] = { "127.0.0.1" }; - struct acl *acl = acl_create(1, lines, 0); - union mysockaddr x; - - parse_ip_to_sockaddr(&x.generic, "127.0.0.2"); - fail_if(acl_includes(acl, &x), "Excluded address was covered."); -} - END_TEST -START_TEST(test_doesnt_include_other_address_when_netmask_specified) + + +START_TEST( test_includes_single_address ) { - char *lines[] = { "127.0.0.1/32" }; - struct acl *acl = acl_create(1, lines, 0); - union mysockaddr x; + char *lines[] = {"127.0.0.1"}; + struct acl * acl = acl_create( 1, lines, 0 ); + union mysockaddr x; - parse_ip_to_sockaddr(&x.generic, "127.0.0.2"); - fail_if(acl_includes(acl, &x), "Excluded address was covered."); + parse_ip_to_sockaddr( &x.generic, "127.0.0.1" ); + + fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); } - END_TEST -START_TEST(test_doesnt_include_other_address_when_multiple_entries_exist) + +START_TEST( test_includes_single_address_when_netmask_specified_ipv4 ) { - char *lines[] = { "127.0.0.1", "::1" }; - struct acl *acl = acl_create(2, lines, 0); - union mysockaddr e0; - union mysockaddr e1; + char *lines[] = {"127.0.0.1/24"}; + struct acl * acl = acl_create( 1, lines, 0 ); + union mysockaddr x; - parse_ip_to_sockaddr(&e0.generic, "127.0.0.2"); - parse_ip_to_sockaddr(&e1.generic, "::2"); + parse_ip_to_sockaddr( &x.generic, "127.0.0.0" ); + fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); - fail_if(acl_includes(acl, &e0), "Excluded address 0 was covered."); - fail_if(acl_includes(acl, &e1), "Excluded address 1 was covered."); + parse_ip_to_sockaddr( &x.generic, "127.0.0.1" ); + fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + + parse_ip_to_sockaddr( &x.generic, "127.0.0.255" ); + fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); } +END_TEST -END_TEST START_TEST(test_default_deny_rejects) +START_TEST( test_includes_single_address_when_netmask_specified_ipv6 ) { - struct acl *acl = acl_create(0, NULL, 1); - union mysockaddr x; + char *lines[] = {"fe80::/10"}; + struct acl * acl = acl_create( 1, lines, 0 ); + union mysockaddr x; - parse_ip_to_sockaddr(&x.generic, "127.0.0.1"); + parse_ip_to_sockaddr( &x.generic, "fe80::1" ); + fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); - fail_if(acl_includes(acl, &x), "Default deny accepted."); + parse_ip_to_sockaddr( &x.generic, "fe80::2" ); + fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + + parse_ip_to_sockaddr( &x.generic, "fe80:ffff:ffff::ffff" ); + fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); } +END_TEST -END_TEST START_TEST(test_default_accept_rejects) +START_TEST( test_includes_single_address_when_multiple_entries_exist ) { - struct acl *acl = acl_create(0, NULL, 0); - union mysockaddr x; + char *lines[] = {"127.0.0.1", "::1"}; + struct acl * acl = acl_create( 2, lines, 0 ); + union mysockaddr e0; + union mysockaddr e1; - parse_ip_to_sockaddr(&x.generic, "127.0.0.1"); + parse_ip_to_sockaddr( &e0.generic, "127.0.0.1" ); + parse_ip_to_sockaddr( &e1.generic, "::1" ); - fail_unless(acl_includes(acl, &x), "Default accept rejected."); + fail_unless( acl_includes( acl, &e0 ), "Included address 0 wasn't covered" ); + fail_unless( acl_includes( acl, &e1 ), "Included address 1 wasn't covered" ); } +END_TEST -END_TEST Suite * acl_suite(void) + +START_TEST( test_doesnt_include_other_address ) { - Suite *s = suite_create("acl"); - TCase *tc_create = tcase_create("create"); - TCase *tc_includes = tcase_create("includes"); - TCase *tc_destroy = tcase_create("destroy"); + char *lines[] = {"127.0.0.1"}; + struct acl * acl = acl_create( 1, lines, 0 ); + union mysockaddr x; + + parse_ip_to_sockaddr( &x.generic, "127.0.0.2" ); + fail_if( acl_includes( acl, &x ), "Excluded address was covered." ); +} +END_TEST + +START_TEST( test_doesnt_include_other_address_when_netmask_specified ) +{ + char *lines[] = {"127.0.0.1/32"}; + struct acl * acl = acl_create( 1, lines, 0 ); + union mysockaddr x; + + parse_ip_to_sockaddr( &x.generic, "127.0.0.2" ); + fail_if( acl_includes( acl, &x ), "Excluded address was covered." ); +} +END_TEST + +START_TEST( test_doesnt_include_other_address_when_multiple_entries_exist ) +{ + char *lines[] = {"127.0.0.1", "::1"}; + struct acl * acl = acl_create( 2, lines, 0 ); + union mysockaddr e0; + union mysockaddr e1; + + parse_ip_to_sockaddr( &e0.generic, "127.0.0.2" ); + parse_ip_to_sockaddr( &e1.generic, "::2" ); + + fail_if( acl_includes( acl, &e0 ), "Excluded address 0 was covered." ); + fail_if( acl_includes( acl, &e1 ), "Excluded address 1 was covered." ); +} +END_TEST + +START_TEST( test_default_deny_rejects ) +{ + struct acl * acl = acl_create( 0, NULL, 1 ); + union mysockaddr x; + + parse_ip_to_sockaddr( &x.generic, "127.0.0.1" ); + + fail_if( acl_includes( acl, &x ), "Default deny accepted." ); +} +END_TEST - tcase_add_test(tc_create, test_null_acl); - tcase_add_test(tc_create, test_parses_single_line); - tcase_add_test(tc_includes, test_parses_multiple_lines); +START_TEST( test_default_accept_rejects ) +{ + struct acl * acl = acl_create( 0, NULL, 0 ); + union mysockaddr x; - tcase_add_test(tc_includes, test_includes_single_address); - tcase_add_test(tc_includes, - test_includes_single_address_when_netmask_specified_ipv4); - tcase_add_test(tc_includes, - test_includes_single_address_when_netmask_specified_ipv6); + parse_ip_to_sockaddr( &x.generic, "127.0.0.1" ); - tcase_add_test(tc_includes, - test_includes_single_address_when_multiple_entries_exist); + fail_unless( acl_includes( acl, &x ), "Default accept rejected." ); +} +END_TEST - tcase_add_test(tc_includes, test_doesnt_include_other_address); - tcase_add_test(tc_includes, - test_doesnt_include_other_address_when_netmask_specified); - tcase_add_test(tc_includes, - test_doesnt_include_other_address_when_multiple_entries_exist); - tcase_add_test(tc_includes, test_default_deny_rejects); - tcase_add_test(tc_includes, test_default_accept_rejects); +Suite* acl_suite(void) +{ + Suite *s = suite_create("acl"); + TCase *tc_create = tcase_create("create"); + TCase *tc_includes = tcase_create("includes"); + TCase *tc_destroy = tcase_create("destroy"); - tcase_add_test(tc_destroy, test_destroy_doesnt_crash); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_includes); - suite_add_tcase(s, tc_destroy); + tcase_add_test(tc_create, test_null_acl); + tcase_add_test(tc_create, test_parses_single_line); + tcase_add_test(tc_includes, test_parses_multiple_lines); - return s; + tcase_add_test(tc_includes, test_includes_single_address); + tcase_add_test(tc_includes, test_includes_single_address_when_netmask_specified_ipv4); + tcase_add_test(tc_includes, test_includes_single_address_when_netmask_specified_ipv6); + + tcase_add_test(tc_includes, test_includes_single_address_when_multiple_entries_exist); + + tcase_add_test(tc_includes, test_doesnt_include_other_address); + tcase_add_test(tc_includes, test_doesnt_include_other_address_when_netmask_specified); + tcase_add_test(tc_includes, test_doesnt_include_other_address_when_multiple_entries_exist); + + tcase_add_test(tc_includes, test_default_deny_rejects); + tcase_add_test(tc_includes, test_default_accept_rejects); + + tcase_add_test(tc_destroy, test_destroy_doesnt_crash); + + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_includes); + suite_add_tcase(s, tc_destroy); + + return s; } int main(void) { #ifdef DEBUG - log_level = 0; + log_level = 0; #else - log_level = 2; + log_level = 2; #endif - int number_failed; - Suite *s = acl_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - log_level = 0; - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? 0 : 1; + int number_failed; + Suite *s = acl_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + log_level = 0; + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; } + diff --git a/tests/unit/check_bitset.c b/tests/unit/check_bitset.c index 100e96b..36b4e55 100644 --- a/tests/unit/check_bitset.c +++ b/tests/unit/check_bitset.c @@ -9,473 +9,492 @@ START_TEST(test_bit_set) { - uint64_t num = 0; - bitfield_p bits = (bitfield_p) & num; + uint64_t num = 0; + bitfield_p bits = (bitfield_p) # #define TEST_BIT_SET(bit, newvalue) \ bit_set(bits, (bit)); \ fail_unless(num == (newvalue), "num was %x instead of %x", num, (newvalue)); - TEST_BIT_SET(0, 1); - TEST_BIT_SET(1, 3); - TEST_BIT_SET(2, 7); - TEST_BIT_SET(7, 0x87); - TEST_BIT_SET(63, 0x8000000000000087); + TEST_BIT_SET(0, 1); + TEST_BIT_SET(1, 3); + TEST_BIT_SET(2, 7); + TEST_BIT_SET(7, 0x87); + TEST_BIT_SET(63, 0x8000000000000087); } +END_TEST -END_TEST START_TEST(test_bit_clear) +START_TEST(test_bit_clear) { - uint64_t num = 0xffffffffffffffff; - bitfield_p bits = (bitfield_p) & num; + uint64_t num = 0xffffffffffffffff; + bitfield_p bits = (bitfield_p) # #define TEST_BIT_CLEAR(bit, newvalue) \ bit_clear(bits, (bit)); \ fail_unless(num == (newvalue), "num was %x instead of %x", num, (newvalue)); - TEST_BIT_CLEAR(0, 0xfffffffffffffffe); - TEST_BIT_CLEAR(1, 0xfffffffffffffffc); - TEST_BIT_CLEAR(2, 0xfffffffffffffff8); - TEST_BIT_CLEAR(7, 0xffffffffffffff78); - TEST_BIT_CLEAR(63, 0x7fffffffffffff78); + TEST_BIT_CLEAR(0, 0xfffffffffffffffe); + TEST_BIT_CLEAR(1, 0xfffffffffffffffc); + TEST_BIT_CLEAR(2, 0xfffffffffffffff8); + TEST_BIT_CLEAR(7, 0xffffffffffffff78); + TEST_BIT_CLEAR(63,0x7fffffffffffff78); } +END_TEST -END_TEST START_TEST(test_bit_tests) +START_TEST(test_bit_tests) { - uint64_t num = 0x5555555555555555; - bitfield_p bits = (bitfield_p) & num; + uint64_t num = 0x5555555555555555; + bitfield_p bits = (bitfield_p) # - fail_unless(bit_has_value(bits, 0, 1), "bit_has_value malfunction"); - fail_unless(bit_has_value(bits, 1, 0), "bit_has_value malfunction"); - fail_unless(bit_has_value(bits, 63, 0), "bit_has_value malfunction"); - fail_unless(bit_is_set(bits, 0), "bit_is_set malfunction"); - fail_unless(bit_is_clear(bits, 1), "bit_is_clear malfunction"); - fail_unless(bit_is_set(bits, 62), "bit_is_set malfunction"); - fail_unless(bit_is_clear(bits, 63), "bit_is_clear malfunction"); + fail_unless(bit_has_value(bits, 0, 1), "bit_has_value malfunction"); + fail_unless(bit_has_value(bits, 1, 0), "bit_has_value malfunction"); + fail_unless(bit_has_value(bits, 63, 0), "bit_has_value malfunction"); + fail_unless(bit_is_set(bits, 0), "bit_is_set malfunction"); + fail_unless(bit_is_clear(bits, 1), "bit_is_clear malfunction"); + fail_unless(bit_is_set(bits, 62), "bit_is_set malfunction"); + fail_unless(bit_is_clear(bits, 63), "bit_is_clear malfunction"); } +END_TEST -END_TEST START_TEST(test_bit_ranges) +START_TEST(test_bit_ranges) { - bitfield_word_t buffer[BIT_WORDS_FOR_SIZE(4160)]; - uint64_t *longs = (uint64_t *) buffer; - uint64_t i; + bitfield_word_t buffer[BIT_WORDS_FOR_SIZE(4160)]; + uint64_t *longs = (uint64_t *) buffer; + uint64_t i; - memset(buffer, 0, 4160); + memset(buffer, 0, 4160); - for (i = 0; i < 64; i++) { - bit_set_range(buffer, i * 64, i); - fail_unless(longs[i] == (1ULL << i) - 1, - "longs[%ld] = %lx SHOULD BE %lx", - i, longs[i], (1ULL << i) - 1); + for (i=0; i<64; i++) { + bit_set_range(buffer, i*64, i); + fail_unless( + longs[i] == (1ULL<bits; + map = bitset_alloc(6400, 100); + num = (uint64_t*) map->bits; - bitset_set_range(map, 0, 50); - ck_assert_int_eq(1, *num); - bitset_set_range(map, 99, 1); - ck_assert_int_eq(1, *num); - bitset_set_range(map, 100, 1); - ck_assert_int_eq(3, *num); - bitset_set_range(map, 0, 800); - ck_assert_int_eq(255, *num); - bitset_set_range(map, 1499, 2); - ck_assert_int_eq(0xc0ff, *num); - bitset_clear_range(map, 1499, 2); - ck_assert_int_eq(255, *num); + bitset_set_range(map,0,50); + ck_assert_int_eq(1, *num); + bitset_set_range(map,99,1); + ck_assert_int_eq(1, *num); + bitset_set_range(map,100,1); + ck_assert_int_eq(3, *num); + bitset_set_range(map,0,800); + ck_assert_int_eq(255, *num); + bitset_set_range(map,1499,2); + ck_assert_int_eq(0xc0ff, *num); + bitset_clear_range(map,1499,2); + ck_assert_int_eq(255, *num); - *num = 0; - bitset_set_range(map, 1499, 2); - bitset_clear_range(map, 1300, 200); - ck_assert_int_eq(0x8000, *num); + *num = 0; + bitset_set_range(map, 1499, 2); + bitset_clear_range(map, 1300, 200); + ck_assert_int_eq(0x8000, *num); - *num = 0; - bitset_set_range(map, 0, 6400); - ck_assert_int_eq(0xffffffffffffffff, *num); - bitset_clear_range(map, 3200, 400); - ck_assert_int_eq(0xfffffff0ffffffff, *num); + *num = 0; + bitset_set_range(map, 0, 6400); + ck_assert_int_eq(0xffffffffffffffff, *num); + bitset_clear_range(map, 3200, 400); + ck_assert_int_eq(0xfffffff0ffffffff, *num); } +END_TEST -END_TEST START_TEST(test_bitset_set) + +START_TEST( test_bitset_set ) { - struct bitset *map; - uint64_t run; + struct bitset * map; + uint64_t run; - map = bitset_alloc(64, 1); + map = bitset_alloc(64, 1); - assert_bitset_is(map, 0x0000000000000000); - bitset_set(map); - assert_bitset_is(map, 0xffffffffffffffff); - bitset_free(map); + assert_bitset_is( map, 0x0000000000000000 ); + bitset_set( map ); + assert_bitset_is( map, 0xffffffffffffffff ); + bitset_free( map ); - map = bitset_alloc(6400, 100); - assert_bitset_is(map, 0x0000000000000000); - bitset_set(map); - assert_bitset_is(map, 0xffffffffffffffff); - bitset_free(map); + map = bitset_alloc( 6400, 100 ); + assert_bitset_is( map, 0x0000000000000000 ); + bitset_set( map ); + assert_bitset_is( map, 0xffffffffffffffff ); + bitset_free( map ); - // Now do something large and representative - map = bitset_alloc(53687091200, 4096); - bitset_set(map); + // Now do something large and representative + map = bitset_alloc( 53687091200, 4096 ); + bitset_set( map ); - run = bitset_run_count(map, 0, 53687091200); - ck_assert_int_eq(run, 53687091200); - bitset_free(map); + run = bitset_run_count( map, 0, 53687091200 ); + ck_assert_int_eq( run, 53687091200 ); + bitset_free( map ); } +END_TEST -END_TEST START_TEST(test_bitset_clear) + +START_TEST( test_bitset_clear ) { - struct bitset *map; - uint64_t *num; - uint64_t run; + struct bitset * map; + uint64_t *num; + uint64_t run; - map = bitset_alloc(64, 1); - num = (uint64_t *) map->bits; + map = bitset_alloc(64, 1); + num = (uint64_t*) map->bits; - ck_assert_int_eq(0x0000000000000000, *num); - bitset_set(map); - bitset_clear(map); - ck_assert_int_eq(0x0000000000000000, *num); + ck_assert_int_eq( 0x0000000000000000, *num ); + bitset_set( map ); + bitset_clear( map ); + ck_assert_int_eq( 0x0000000000000000, *num ); - bitset_free(map); + bitset_free( map ); - // Now do something large and representative - map = bitset_alloc(53687091200, 4096); - bitset_set(map); - bitset_clear(map); - run = bitset_run_count(map, 0, 53687091200); - ck_assert_int_eq(run, 53687091200); - bitset_free(map); + // Now do something large and representative + map = bitset_alloc( 53687091200, 4096 ); + bitset_set( map ); + bitset_clear( map ); + run = bitset_run_count( map, 0, 53687091200 ); + ck_assert_int_eq( run, 53687091200 ); + bitset_free( map ); } +END_TEST -END_TEST START_TEST(test_bitset_set_range) +START_TEST( test_bitset_set_range ) { - struct bitset *map = bitset_alloc(64, 1); - assert_bitset_is(map, 0x0000000000000000); + struct bitset* map = bitset_alloc( 64, 1 ); + assert_bitset_is( map, 0x0000000000000000 ); - bitset_set_range(map, 8, 8); - assert_bitset_is(map, 0x000000000000ff00); + bitset_set_range( map, 8, 8 ); + assert_bitset_is( map, 0x000000000000ff00 ); - bitset_clear(map); - assert_bitset_is(map, 0x0000000000000000); - bitset_set_range(map, 0, 0); - assert_bitset_is(map, 0x0000000000000000); + bitset_clear( map ); + assert_bitset_is( map, 0x0000000000000000 ); + bitset_set_range( map, 0, 0 ); + assert_bitset_is( map, 0x0000000000000000 ); - bitset_free(map); + bitset_free( map ); } +END_TEST -END_TEST START_TEST(test_bitset_clear_range) +START_TEST( test_bitset_clear_range ) { - struct bitset *map = bitset_alloc(64, 1); - bitset_set(map); - assert_bitset_is(map, 0xffffffffffffffff); + struct bitset* map = bitset_alloc( 64, 1 ); + bitset_set( map ); + assert_bitset_is( map, 0xffffffffffffffff ); - bitset_clear_range(map, 8, 8); - assert_bitset_is(map, 0xffffffffffff00ff); + bitset_clear_range( map, 8, 8 ); + assert_bitset_is( map, 0xffffffffffff00ff ); - bitset_set(map); - assert_bitset_is(map, 0xffffffffffffffff); - bitset_clear_range(map, 0, 0); - assert_bitset_is(map, 0xffffffffffffffff); + bitset_set( map ); + assert_bitset_is( map, 0xffffffffffffffff ); + bitset_clear_range( map, 0, 0 ); + assert_bitset_is( map, 0xffffffffffffffff ); - bitset_free(map); + bitset_free( map ); } +END_TEST -END_TEST START_TEST(test_bitset_run_count) +START_TEST( test_bitset_run_count ) { - struct bitset *map = bitset_alloc(64, 1); - uint64_t run; + struct bitset* map = bitset_alloc( 64, 1 ); + uint64_t run; - assert_bitset_is(map, 0x0000000000000000); + assert_bitset_is( map, 0x0000000000000000 ); - run = bitset_run_count(map, 0, 64); - ck_assert_int_eq(64, run); + run = bitset_run_count( map, 0, 64 ); + ck_assert_int_eq( 64, run ); - bitset_set_range(map, 0, 32); - assert_bitset_is(map, 0x00000000ffffffff); + bitset_set_range( map, 0, 32 ); + assert_bitset_is( map, 0x00000000ffffffff ); - run = bitset_run_count(map, 0, 64); - ck_assert_int_eq(32, run); + run = bitset_run_count( map, 0, 64 ); + ck_assert_int_eq( 32, run ); - run = bitset_run_count(map, 0, 16); - ck_assert_int_eq(16, run); + run = bitset_run_count( map, 0, 16 ); + ck_assert_int_eq( 16, run ); - run = bitset_run_count(map, 16, 64); - ck_assert_int_eq(16, run); + run = bitset_run_count( map, 16, 64 ); + ck_assert_int_eq( 16, run ); - run = bitset_run_count(map, 31, 64); - ck_assert_int_eq(1, run); + run = bitset_run_count( map, 31, 64 ); + ck_assert_int_eq( 1, run ); - run = bitset_run_count(map, 32, 64); - ck_assert_int_eq(32, run); + run = bitset_run_count( map, 32, 64 ); + ck_assert_int_eq( 32, run ); - run = bitset_run_count(map, 32, 32); - ck_assert_int_eq(32, run); + run = bitset_run_count( map, 32, 32 ); + ck_assert_int_eq( 32, run ); - run = bitset_run_count(map, 32, 16); - ck_assert_int_eq(16, run); + run = bitset_run_count( map, 32, 16 ); + ck_assert_int_eq( 16, run ); - bitset_free(map); + bitset_free( map ); - map = bitset_alloc(6400, 100); - assert_bitset_is(map, 0x0000000000000000); + map = bitset_alloc( 6400, 100 ); + assert_bitset_is( map, 0x0000000000000000 ); - run = bitset_run_count(map, 0, 6400); - ck_assert_int_eq(6400, run); + run = bitset_run_count( map, 0, 6400 ); + ck_assert_int_eq( 6400, run ); - bitset_set_range(map, 0, 3200); + bitset_set_range( map, 0, 3200 ); - run = bitset_run_count(map, 0, 6400); - ck_assert_int_eq(3200, run); + run = bitset_run_count( map, 0, 6400 ); + ck_assert_int_eq( 3200, run ); - run = bitset_run_count(map, 1, 6400); - ck_assert_int_eq(3199, run); + run = bitset_run_count( map, 1, 6400 ); + ck_assert_int_eq( 3199, run ); - run = bitset_run_count(map, 3200, 6400); - ck_assert_int_eq(3200, run); + run = bitset_run_count( map, 3200, 6400 ); + ck_assert_int_eq( 3200, run ); - run = bitset_run_count(map, 6500, 6400); - ck_assert_int_eq(0, run); - bitset_free(map); + run = bitset_run_count( map, 6500, 6400 ); + ck_assert_int_eq( 0, run ); + bitset_free( map ); - // Now do something large and representative - map = bitset_alloc(53687091200, 4096); - bitset_set(map); - run = bitset_run_count(map, 0, 53687091200); - ck_assert_int_eq(run, 53687091200); + // Now do something large and representative + map = bitset_alloc( 53687091200, 4096 ); + bitset_set( map ); + run = bitset_run_count( map, 0, 53687091200 ); + ck_assert_int_eq( run, 53687091200 ); - bitset_free(map); + bitset_free( map ); } +END_TEST -END_TEST START_TEST(test_bitset_set_range_doesnt_push_to_stream) +START_TEST( test_bitset_set_range_doesnt_push_to_stream ) { - struct bitset *map = bitset_alloc(64, 1); - bitset_set_range(map, 0, 64); - ck_assert_int_eq(0, bitset_stream_size(map)); - bitset_free(map); + struct bitset *map = bitset_alloc( 64, 1 ); + bitset_set_range( map, 0, 64 ); + ck_assert_int_eq( 0, bitset_stream_size( map ) ); + bitset_free( map ); } +END_TEST -END_TEST START_TEST(test_bitset_clear_range_doesnt_push_to_stream) +START_TEST( test_bitset_clear_range_doesnt_push_to_stream ) { - struct bitset *map = bitset_alloc(64, 1); - bitset_clear_range(map, 0, 64); - ck_assert_int_eq(0, bitset_stream_size(map)); - bitset_free(map); + struct bitset *map = bitset_alloc( 64, 1 ); + bitset_clear_range( map, 0, 64 ); + ck_assert_int_eq( 0, bitset_stream_size( map ) ); + bitset_free( map ); } +END_TEST -END_TEST START_TEST(test_bitset_enable_stream) +START_TEST(test_bitset_enable_stream) { - struct bitset *map = bitset_alloc(64, 1); - struct bitset_stream_entry result; - memset(&result, 0, sizeof(result)); + struct bitset *map = bitset_alloc( 64, 1 ); + struct bitset_stream_entry result; + memset( &result, 0, sizeof( result ) ); - bitset_enable_stream(map); + bitset_enable_stream( map ); - ck_assert_int_eq(1, map->stream_enabled); + ck_assert_int_eq( 1, map->stream_enabled ); - bitset_stream_dequeue(map, &result); + bitset_stream_dequeue( map, &result ); - ck_assert_int_eq(BITSET_STREAM_ON, result.event); - ck_assert_int_eq(0, result.from); - ck_assert_int_eq(64, result.len); + ck_assert_int_eq( BITSET_STREAM_ON, result.event ); + ck_assert_int_eq( 0, result.from ); + ck_assert_int_eq( 64, result.len ); - bitset_free(map); + bitset_free( map ); } +END_TEST -END_TEST START_TEST(test_bitset_disable_stream) +START_TEST(test_bitset_disable_stream) { - struct bitset *map = bitset_alloc(64, 1); - struct bitset_stream_entry result; - memset(&result, 0, sizeof(result)); + struct bitset *map = bitset_alloc( 64, 1 ); + struct bitset_stream_entry result; + memset( &result, 0, sizeof( result ) ); - bitset_enable_stream(map); - bitset_disable_stream(map); + bitset_enable_stream( map ); + bitset_disable_stream( map ); - ck_assert_int_eq(0, map->stream_enabled); - ck_assert_int_eq(2, bitset_stream_size(map)); + ck_assert_int_eq( 0, map->stream_enabled ); + ck_assert_int_eq( 2, bitset_stream_size( map ) ); - bitset_stream_dequeue(map, NULL); // ON - bitset_stream_dequeue(map, &result); // OFF + bitset_stream_dequeue( map, NULL ); // ON + bitset_stream_dequeue( map, &result ); // OFF - ck_assert_int_eq(BITSET_STREAM_OFF, result.event); - ck_assert_int_eq(0, result.from); - ck_assert_int_eq(64, result.len); + ck_assert_int_eq( BITSET_STREAM_OFF, result.event ); + ck_assert_int_eq( 0, result.from ); + ck_assert_int_eq( 64, result.len ); - bitset_free(map); + bitset_free( map ); } +END_TEST -END_TEST START_TEST(test_bitset_stream_with_set_range) +START_TEST(test_bitset_stream_with_set_range) { - struct bitset *map = bitset_alloc(64, 1); - struct bitset_stream_entry result; - memset(&result, 0, sizeof(result)); + struct bitset *map = bitset_alloc( 64, 1 ); + struct bitset_stream_entry result; + memset( &result, 0, sizeof( result ) ); - bitset_enable_stream(map); - bitset_set_range(map, 0, 32); + bitset_enable_stream( map ); + bitset_set_range( map, 0, 32 ); - ck_assert_int_eq(2, bitset_stream_size(map)); + ck_assert_int_eq( 2, bitset_stream_size( map ) ); - bitset_stream_dequeue(map, NULL); // ON - bitset_stream_dequeue(map, &result); // SET + bitset_stream_dequeue( map, NULL ); // ON + bitset_stream_dequeue( map, &result ); // SET - ck_assert_int_eq(BITSET_STREAM_SET, result.event); - ck_assert_int_eq(0, result.from); - ck_assert_int_eq(32, result.len); + ck_assert_int_eq( BITSET_STREAM_SET, result.event ); + ck_assert_int_eq( 0, result.from ); + ck_assert_int_eq( 32, result.len ); - bitset_free(map); + bitset_free( map ); } +END_TEST -END_TEST START_TEST(test_bitset_stream_with_clear_range) +START_TEST(test_bitset_stream_with_clear_range) { - struct bitset *map = bitset_alloc(64, 1); - struct bitset_stream_entry result; - memset(&result, 0, sizeof(result)); + struct bitset *map = bitset_alloc( 64, 1 ); + struct bitset_stream_entry result; + memset( &result, 0, sizeof( result ) ); - bitset_enable_stream(map); - bitset_clear_range(map, 0, 32); - ck_assert_int_eq(2, bitset_stream_size(map)); + bitset_enable_stream( map ); + bitset_clear_range( map, 0, 32 ); + ck_assert_int_eq( 2, bitset_stream_size( map ) ); - bitset_stream_dequeue(map, NULL); // ON - bitset_stream_dequeue(map, &result); // UNSET + bitset_stream_dequeue( map, NULL ); // ON + bitset_stream_dequeue( map, &result ); // UNSET - ck_assert_int_eq(BITSET_STREAM_UNSET, result.event); - ck_assert_int_eq(0, result.from); - ck_assert_int_eq(32, result.len); + ck_assert_int_eq( BITSET_STREAM_UNSET, result.event ); + ck_assert_int_eq( 0, result.from ); + ck_assert_int_eq( 32, result.len ); - bitset_free(map); + bitset_free( map ); } +END_TEST -END_TEST START_TEST(test_bitset_stream_size) +START_TEST(test_bitset_stream_size) { - struct bitset *map = bitset_alloc(64, 1); - bitset_enable_stream(map); - bitset_set_range(map, 0, 32); - bitset_set_range(map, 16, 32); - bitset_set_range(map, 7, 16); + struct bitset *map = bitset_alloc( 64, 1 ); + bitset_enable_stream( map ); + bitset_set_range( map, 0, 32 ); + bitset_set_range( map, 16, 32 ); + bitset_set_range( map, 7, 16 ); - bitset_clear_range(map, 0, 32); - bitset_clear_range(map, 16, 32); - bitset_clear_range(map, 48, 16); - bitset_disable_stream(map); + bitset_clear_range( map, 0, 32 ); + bitset_clear_range( map, 16, 32 ); + bitset_clear_range( map, 48, 16 ); + bitset_disable_stream( map ); - ck_assert_int_eq(8, bitset_stream_size(map)); + ck_assert_int_eq( 8, bitset_stream_size( map ) ); - bitset_free(map); + bitset_free( map ); } +END_TEST -END_TEST START_TEST(test_bitset_stream_queued_bytes) +START_TEST(test_bitset_stream_queued_bytes) { - struct bitset *map = bitset_alloc(64, 1); - bitset_enable_stream(map); - bitset_set_range(map, 0, 32); - bitset_set_range(map, 16, 32); - bitset_set_range(map, 7, 16); + struct bitset *map = bitset_alloc( 64, 1 ); + bitset_enable_stream( map ); + bitset_set_range( map, 0, 32 ); + bitset_set_range( map, 16, 32 ); + bitset_set_range( map, 7, 16 ); - bitset_clear_range(map, 0, 32); - bitset_clear_range(map, 16, 32); - bitset_clear_range(map, 48, 16); - bitset_clear_range(map, 0, 2); - bitset_disable_stream(map); + bitset_clear_range( map, 0, 32 ); + bitset_clear_range( map, 16, 32 ); + bitset_clear_range( map, 48, 16 ); + bitset_clear_range( map, 0, 2 ); + bitset_disable_stream( map ); - ck_assert_int_eq(64, - bitset_stream_queued_bytes(map, BITSET_STREAM_ON)); - ck_assert_int_eq(80, - bitset_stream_queued_bytes(map, BITSET_STREAM_SET)); - ck_assert_int_eq(82, - bitset_stream_queued_bytes(map, BITSET_STREAM_UNSET)); - ck_assert_int_eq(64, - bitset_stream_queued_bytes(map, BITSET_STREAM_OFF)); - bitset_free(map); + ck_assert_int_eq( 64, bitset_stream_queued_bytes( map, BITSET_STREAM_ON ) ); + ck_assert_int_eq( 80, bitset_stream_queued_bytes( map, BITSET_STREAM_SET ) ); + ck_assert_int_eq( 82, bitset_stream_queued_bytes( map, BITSET_STREAM_UNSET ) ); + ck_assert_int_eq( 64, bitset_stream_queued_bytes( map, BITSET_STREAM_OFF ) ); + bitset_free( map ); } +END_TEST -END_TEST Suite * bitset_suite(void) +Suite* bitset_suite(void) { - Suite *s = suite_create("bitset"); + Suite *s = suite_create("bitset"); - TCase *tc_bit = tcase_create("bit"); - tcase_add_test(tc_bit, test_bit_set); - tcase_add_test(tc_bit, test_bit_clear); - tcase_add_test(tc_bit, test_bit_tests); - tcase_add_test(tc_bit, test_bit_ranges); - tcase_add_test(tc_bit, test_bit_runs); - suite_add_tcase(s, tc_bit); + TCase *tc_bit = tcase_create("bit"); + tcase_add_test(tc_bit, test_bit_set); + tcase_add_test(tc_bit, test_bit_clear); + tcase_add_test(tc_bit, test_bit_tests); + tcase_add_test(tc_bit, test_bit_ranges); + tcase_add_test(tc_bit, test_bit_runs); + suite_add_tcase(s, tc_bit); - TCase *tc_bitset = tcase_create("bitset"); - tcase_add_test(tc_bitset, test_bitset); - tcase_add_test(tc_bitset, test_bitset_set); - tcase_add_test(tc_bitset, test_bitset_clear); - tcase_add_test(tc_bitset, test_bitset_run_count); - tcase_add_test(tc_bitset, test_bitset_set_range); - tcase_add_test(tc_bitset, test_bitset_clear_range); - tcase_add_test(tc_bitset, test_bitset_set_range_doesnt_push_to_stream); - tcase_add_test(tc_bitset, - test_bitset_clear_range_doesnt_push_to_stream); - suite_add_tcase(s, tc_bitset); + TCase *tc_bitset = tcase_create("bitset"); + tcase_add_test(tc_bitset, test_bitset); + tcase_add_test(tc_bitset, test_bitset_set); + tcase_add_test(tc_bitset, test_bitset_clear); + tcase_add_test(tc_bitset, test_bitset_run_count); + tcase_add_test(tc_bitset, test_bitset_set_range); + tcase_add_test(tc_bitset, test_bitset_clear_range); + tcase_add_test(tc_bitset, test_bitset_set_range_doesnt_push_to_stream); + tcase_add_test(tc_bitset, test_bitset_clear_range_doesnt_push_to_stream); + suite_add_tcase(s, tc_bitset); - TCase *tc_bitset_stream = tcase_create("bitset_stream"); - tcase_add_test(tc_bitset_stream, test_bitset_enable_stream); - tcase_add_test(tc_bitset_stream, test_bitset_disable_stream); - tcase_add_test(tc_bitset_stream, test_bitset_stream_with_set_range); - tcase_add_test(tc_bitset_stream, test_bitset_stream_with_clear_range); - tcase_add_test(tc_bitset_stream, test_bitset_stream_size); - tcase_add_test(tc_bitset_stream, test_bitset_stream_queued_bytes); - suite_add_tcase(s, tc_bitset_stream); + TCase *tc_bitset_stream = tcase_create("bitset_stream"); + tcase_add_test(tc_bitset_stream, test_bitset_enable_stream); + tcase_add_test(tc_bitset_stream, test_bitset_disable_stream); + tcase_add_test(tc_bitset_stream, test_bitset_stream_with_set_range); + tcase_add_test(tc_bitset_stream, test_bitset_stream_with_clear_range); + tcase_add_test(tc_bitset_stream, test_bitset_stream_size); + tcase_add_test(tc_bitset_stream, test_bitset_stream_queued_bytes); + suite_add_tcase(s, tc_bitset_stream); - return s; + return s; } int main(void) { - int number_failed; - Suite *s = bitset_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; + int number_failed; + Suite *s = bitset_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; } + diff --git a/tests/unit/check_client.c b/tests/unit/check_client.c index 3df7a13..188db10 100644 --- a/tests/unit/check_client.c +++ b/tests/unit/check_client.c @@ -9,104 +9,114 @@ #include -struct server fake_server = { 0 }; - +struct server fake_server = {0}; #define FAKE_SERVER &fake_server #define FAKE_SOCKET (42) -START_TEST(test_assigns_socket) +START_TEST( test_assigns_socket ) { - struct client *c; + struct client * c; - c = client_create(FAKE_SERVER, FAKE_SOCKET); + c = client_create( FAKE_SERVER, FAKE_SOCKET ); - fail_unless(42 == c->socket, "Socket wasn't assigned."); + fail_unless( 42 == c->socket, "Socket wasn't assigned." ); } +END_TEST -END_TEST START_TEST(test_assigns_server) + +START_TEST( test_assigns_server ) { - struct client *c; - /* can't predict the storage size so we can't allocate one on - * the stack - */ - c = client_create(FAKE_SERVER, FAKE_SOCKET); + struct client * c; + /* can't predict the storage size so we can't allocate one on + * the stack + */ + c = client_create( FAKE_SERVER, FAKE_SOCKET ); - fail_unless(FAKE_SERVER == c->serve, "Serve wasn't assigned."); + fail_unless( FAKE_SERVER == c->serve, "Serve wasn't assigned." ); } +END_TEST -END_TEST START_TEST(test_opens_stop_signal) + +START_TEST( test_opens_stop_signal ) { - struct client *c = client_create(FAKE_SERVER, FAKE_SOCKET); + struct client *c = client_create( FAKE_SERVER, FAKE_SOCKET ); - client_signal_stop(c); + client_signal_stop( c ); - fail_unless(1 == self_pipe_signal_clear(c->stop_signal), - "No signal was sent."); + fail_unless( 1 == self_pipe_signal_clear( c->stop_signal ), + "No signal was sent." ); } +END_TEST -END_TEST int fd_is_closed(int); -START_TEST(test_closes_stop_signal) +int fd_is_closed(int); + +START_TEST( test_closes_stop_signal ) { - struct client *c = client_create(FAKE_SERVER, FAKE_SOCKET); - int read_fd = c->stop_signal->read_fd; - int write_fd = c->stop_signal->write_fd; + struct client *c = client_create( FAKE_SERVER, FAKE_SOCKET ); + int read_fd = c->stop_signal->read_fd; + int write_fd = c->stop_signal->write_fd; - client_destroy(c); + client_destroy( c ); - fail_unless(fd_is_closed(read_fd), "Stop signal wasn't destroyed."); - fail_unless(fd_is_closed(write_fd), "Stop signal wasn't destroyed."); + fail_unless( fd_is_closed( read_fd ), "Stop signal wasn't destroyed." ); + fail_unless( fd_is_closed( write_fd ), "Stop signal wasn't destroyed." ); } +END_TEST -END_TEST START_TEST(test_read_request_quits_on_stop_signal) + +START_TEST( test_read_request_quits_on_stop_signal ) { - int fds[2]; - struct nbd_request nbdr; - pipe(fds); - struct client *c = client_create(FAKE_SERVER, fds[0]); + int fds[2]; + struct nbd_request nbdr; + pipe( fds ); + struct client *c = client_create( FAKE_SERVER, fds[0] ); + + client_signal_stop( c ); - client_signal_stop(c); + int client_serve_request( struct client *); + fail_unless( 1 == client_serve_request( c ), "Didn't quit on stop." ); - int client_serve_request(struct client *); - fail_unless(1 == client_serve_request(c), "Didn't quit on stop."); - - close(fds[0]); - close(fds[1]); + close( fds[0] ); + close( fds[1] ); } +END_TEST -END_TEST Suite * client_suite(void) + +Suite *client_suite(void) { - Suite *s = suite_create("client"); + Suite *s = suite_create("client"); - TCase *tc_create = tcase_create("create"); - TCase *tc_signal = tcase_create("signal"); - TCase *tc_destroy = tcase_create("destroy"); + TCase *tc_create = tcase_create("create"); + TCase *tc_signal = tcase_create("signal"); + TCase *tc_destroy = tcase_create("destroy"); - tcase_add_test(tc_create, test_assigns_socket); - tcase_add_test(tc_create, test_assigns_server); + tcase_add_test(tc_create, test_assigns_socket); + tcase_add_test(tc_create, test_assigns_server); - tcase_add_test(tc_signal, test_opens_stop_signal); - tcase_add_test(tc_signal, test_read_request_quits_on_stop_signal); + tcase_add_test(tc_signal, test_opens_stop_signal); + tcase_add_test(tc_signal, test_read_request_quits_on_stop_signal); - tcase_add_test(tc_destroy, test_closes_stop_signal); + tcase_add_test( tc_destroy, test_closes_stop_signal ); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_signal); - suite_add_tcase(s, tc_destroy); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_signal); + suite_add_tcase(s, tc_destroy); - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = client_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; + int number_failed; + + Suite *s = client_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; } + diff --git a/tests/unit/check_control.c b/tests/unit/check_control.c index 2afd6dc..fbb2ec9 100644 --- a/tests/unit/check_control.c +++ b/tests/unit/check_control.c @@ -4,36 +4,39 @@ #include -START_TEST(test_assigns_sock_name) +START_TEST( test_assigns_sock_name ) { - struct flexnbd flexnbd = { 0 }; - char csn[] = "foobar"; + struct flexnbd flexnbd = {0}; + char csn[] = "foobar"; - struct control *control = control_create(&flexnbd, csn); + struct control * control = control_create(&flexnbd, csn ); - fail_unless(csn == control->socket_name, "Socket name not assigned"); + fail_unless( csn == control->socket_name, "Socket name not assigned" ); } +END_TEST -END_TEST Suite * control_suite(void) + +Suite *control_suite(void) { - Suite *s = suite_create("control"); + Suite *s = suite_create("control"); - TCase *tc_create = tcase_create("create"); + TCase *tc_create = tcase_create("create"); - tcase_add_test(tc_create, test_assigns_sock_name); - suite_add_tcase(s, tc_create); + tcase_add_test(tc_create, test_assigns_sock_name); + suite_add_tcase( s, tc_create ); - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = control_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; + int number_failed; + + Suite *s = control_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; } + diff --git a/tests/unit/check_flexnbd.c b/tests/unit/check_flexnbd.c index 6c45814..bff82e4 100644 --- a/tests/unit/check_flexnbd.c +++ b/tests/unit/check_flexnbd.c @@ -3,38 +3,42 @@ #include -START_TEST(test_listening_assigns_sock) +START_TEST( test_listening_assigns_sock ) { - struct flexnbd *flexnbd = flexnbd_create_listening("127.0.0.1", - "4777", - "fakefile", - "fakesock", - 0, - 0, - NULL); - fail_if(NULL == flexnbd->control->socket_name, "No socket was copied"); + struct flexnbd * flexnbd = flexnbd_create_listening( + "127.0.0.1", + "4777", + "fakefile", + "fakesock", + 0, + 0, + NULL ); + fail_if( NULL == flexnbd->control->socket_name, "No socket was copied" ); } +END_TEST -END_TEST Suite * flexnbd_suite(void) + +Suite *flexnbd_suite(void) { - Suite *s = suite_create("flexnbd"); + Suite *s = suite_create("flexnbd"); - TCase *tc_create = tcase_create("create"); + TCase *tc_create = tcase_create("create"); - tcase_add_test(tc_create, test_listening_assigns_sock); - suite_add_tcase(s, tc_create); + tcase_add_test(tc_create, test_listening_assigns_sock); + suite_add_tcase( s, tc_create ); - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = flexnbd_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; + int number_failed; + + Suite *s = flexnbd_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; } + diff --git a/tests/unit/check_flexthread.c b/tests/unit/check_flexthread.c index d6535a9..092ab5b 100644 --- a/tests/unit/check_flexthread.c +++ b/tests/unit/check_flexthread.c @@ -4,57 +4,59 @@ #include -START_TEST(test_mutex_create) +START_TEST( test_mutex_create ) { - struct flexthread_mutex *ftm = flexthread_mutex_create(); - NULLCHECK(ftm); - flexthread_mutex_destroy(ftm); + struct flexthread_mutex * ftm = flexthread_mutex_create(); + NULLCHECK( ftm ); + flexthread_mutex_destroy( ftm ); } +END_TEST -END_TEST START_TEST(test_mutex_lock) + +START_TEST( test_mutex_lock ) { - struct flexthread_mutex *ftm = flexthread_mutex_create(); + struct flexthread_mutex * ftm = flexthread_mutex_create(); - fail_if(flexthread_mutex_held(ftm), - "Flexthread_mutex is held before lock"); - flexthread_mutex_lock(ftm); - fail_unless(flexthread_mutex_held(ftm), - "Flexthread_mutex is not held inside lock"); - flexthread_mutex_unlock(ftm); - fail_if(flexthread_mutex_held(ftm), - "Flexthread_mutex is held after unlock"); + fail_if( flexthread_mutex_held( ftm ), "Flexthread_mutex is held before lock" ); + flexthread_mutex_lock( ftm ); + fail_unless( flexthread_mutex_held( ftm ), "Flexthread_mutex is not held inside lock" ); + flexthread_mutex_unlock( ftm ); + fail_if( flexthread_mutex_held( ftm ), "Flexthread_mutex is held after unlock" ); - flexthread_mutex_destroy(ftm); + flexthread_mutex_destroy( ftm ); } +END_TEST -END_TEST Suite * flexthread_suite(void) + +Suite* flexthread_suite(void) { - Suite *s = suite_create("flexthread"); - TCase *tc_create = tcase_create("create"); - TCase *tc_destroy = tcase_create("destroy"); + Suite *s = suite_create("flexthread"); + TCase *tc_create = tcase_create("create"); + TCase *tc_destroy = tcase_create("destroy"); - tcase_add_test(tc_create, test_mutex_create); - tcase_add_test(tc_create, test_mutex_lock); + tcase_add_test( tc_create, test_mutex_create ); + tcase_add_test( tc_create, test_mutex_lock ); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_destroy); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_destroy); - return s; + return s; } int main(void) { #ifdef DEBUG - log_level = 0; + log_level = 0; #else - log_level = 2; + log_level = 2; #endif - int number_failed; - Suite *s = flexthread_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - log_level = 0; - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? 0 : 1; + int number_failed; + Suite *s = flexthread_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + log_level = 0; + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; } + diff --git a/tests/unit/check_ioutil.c b/tests/unit/check_ioutil.c index dbe75ab..b1f26a5 100644 --- a/tests/unit/check_ioutil.c +++ b/tests/unit/check_ioutil.c @@ -2,125 +2,133 @@ #include -START_TEST(test_read_until_newline_returns_line_length_plus_null) +START_TEST( test_read_until_newline_returns_line_length_plus_null ) { - int fds[2]; - int nread; - char buf[5] = { 0 }; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = {0}; + pipe(fds); - write(fds[1], "1234\n", 5); + write( fds[1], "1234\n", 5 ); + + nread = read_until_newline( fds[0], buf, 5 ); - nread = read_until_newline(fds[0], buf, 5); - - ck_assert_int_eq(5, nread); + ck_assert_int_eq( 5, nread ); } +END_TEST -END_TEST START_TEST(test_read_until_newline_inserts_null) + +START_TEST( test_read_until_newline_inserts_null ) { - int fds[2]; - int nread; - char buf[5] = { 0 }; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = {0}; + pipe(fds); - write(fds[1], "1234\n", 5); + write( fds[1], "1234\n", 5 ); + + nread = read_until_newline( fds[0], buf, 5 ); - nread = read_until_newline(fds[0], buf, 5); - - ck_assert_int_eq('\0', buf[4]); + ck_assert_int_eq( '\0', buf[4] ); } +END_TEST -END_TEST START_TEST(test_read_empty_line_inserts_null) + +START_TEST( test_read_empty_line_inserts_null ) { - int fds[2]; - int nread; - char buf[5] = { 0 }; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = {0}; + pipe(fds); - write(fds[1], "\n", 1); - nread = read_until_newline(fds[0], buf, 1); + write( fds[1], "\n", 1 ); + nread = read_until_newline( fds[0], buf, 1 ); - ck_assert_int_eq('\0', buf[0]); - ck_assert_int_eq(1, nread); + ck_assert_int_eq( '\0', buf[0] ); + ck_assert_int_eq( 1, nread ); } +END_TEST -END_TEST START_TEST(test_read_eof_returns_err) + +START_TEST( test_read_eof_returns_err ) { - int fds[2]; - int nread; - char buf[5] = { 0 }; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = {0}; + pipe( fds ); - close(fds[1]); - nread = read_until_newline(fds[0], buf, 5); + close( fds[1] ); + nread = read_until_newline( fds[0], buf, 5 ); - ck_assert_int_eq(-1, nread); + ck_assert_int_eq( -1, nread ); } +END_TEST -END_TEST START_TEST(test_read_eof_fills_line) + +START_TEST( test_read_eof_fills_line ) { - int fds[2]; - int nread; - char buf[5] = { 0 }; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = {0}; + pipe(fds); - write(fds[1], "1234", 4); - close(fds[1]); - nread = read_until_newline(fds[0], buf, 5); + write( fds[1], "1234", 4 ); + close( fds[1] ); + nread = read_until_newline( fds[0], buf, 5 ); - ck_assert_int_eq(-1, nread); - ck_assert_int_eq('4', buf[3]); + ck_assert_int_eq( -1, nread ); + ck_assert_int_eq( '4', buf[3] ); } +END_TEST -END_TEST START_TEST(test_read_lines_until_blankline) + +START_TEST( test_read_lines_until_blankline ) { - char **lines = NULL; - int fds[2]; - int nlines; - pipe(fds); + char **lines = NULL; + int fds[2]; + int nlines; + pipe( fds ); - write(fds[1], "a\nb\nc\n\n", 7); + write( fds[1], "a\nb\nc\n\n", 7 ); - nlines = read_lines_until_blankline(fds[0], 256, &lines); + nlines = read_lines_until_blankline( fds[0], 256, &lines ); - ck_assert_int_eq(3, nlines); + ck_assert_int_eq( 3, nlines ); } +END_TEST -END_TEST Suite * ioutil_suite(void) + +Suite *ioutil_suite(void) { - Suite *s = suite_create("ioutil"); + Suite *s = suite_create("ioutil"); - TCase *tc_read_until_newline = tcase_create("read_until_newline"); - TCase *tc_read_lines_until_blankline = - tcase_create("read_lines_until_blankline"); + TCase *tc_read_until_newline = tcase_create("read_until_newline"); + TCase *tc_read_lines_until_blankline = tcase_create("read_lines_until_blankline"); - tcase_add_test(tc_read_until_newline, - test_read_until_newline_returns_line_length_plus_null); - tcase_add_test(tc_read_until_newline, - test_read_until_newline_inserts_null); - tcase_add_test(tc_read_until_newline, - test_read_empty_line_inserts_null); - tcase_add_test(tc_read_until_newline, test_read_eof_returns_err); - tcase_add_test(tc_read_until_newline, test_read_eof_fills_line); + tcase_add_test(tc_read_until_newline, test_read_until_newline_returns_line_length_plus_null); + tcase_add_test(tc_read_until_newline, test_read_until_newline_inserts_null); + tcase_add_test(tc_read_until_newline, test_read_empty_line_inserts_null); + tcase_add_test(tc_read_until_newline, test_read_eof_returns_err); + tcase_add_test(tc_read_until_newline, test_read_eof_fills_line ); - tcase_add_test(tc_read_lines_until_blankline, - test_read_lines_until_blankline); + tcase_add_test(tc_read_lines_until_blankline, test_read_lines_until_blankline ); - suite_add_tcase(s, tc_read_until_newline); - suite_add_tcase(s, tc_read_lines_until_blankline); + suite_add_tcase(s, tc_read_until_newline); + suite_add_tcase(s, tc_read_lines_until_blankline); - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = ioutil_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; + int number_failed; + + Suite *s = ioutil_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; } + diff --git a/tests/unit/check_mbox.c b/tests/unit/check_mbox.c index 0d6c3d3..5399531 100644 --- a/tests/unit/check_mbox.c +++ b/tests/unit/check_mbox.c @@ -4,76 +4,83 @@ #include #include -START_TEST(test_allocs_cvar) +START_TEST( test_allocs_cvar ) { - struct mbox *mbox = mbox_create(); - fail_if(NULL == mbox, "Nothing allocated"); + struct mbox * mbox = mbox_create(); + fail_if( NULL == mbox, "Nothing allocated" ); - pthread_cond_t cond_zero; - /* A freshly inited pthread_cond_t is set to {0} */ - memset(&cond_zero, 'X', sizeof(cond_zero)); - fail_if(memcmp(&cond_zero, &mbox->filled_cond, sizeof(cond_zero)) == 0, - "Condition variable not allocated"); - fail_if(memcmp(&cond_zero, &mbox->emptied_cond, sizeof(cond_zero)) == - 0, "Condition variable not allocated"); + pthread_cond_t cond_zero; + /* A freshly inited pthread_cond_t is set to {0} */ + memset( &cond_zero, 'X', sizeof( cond_zero ) ); + fail_if( memcmp( &cond_zero, &mbox->filled_cond, sizeof( cond_zero ) ) == 0 , + "Condition variable not allocated" ); + fail_if( memcmp( &cond_zero, &mbox->emptied_cond, sizeof( cond_zero ) ) == 0 , + "Condition variable not allocated" ); } +END_TEST -END_TEST START_TEST(test_post_stores_value) + +START_TEST( test_post_stores_value ) { - struct mbox *mbox = mbox_create(); + struct mbox * mbox = mbox_create(); + + void * deadbeef = (void *)0xDEADBEEF; + mbox_post( mbox, deadbeef ); - void *deadbeef = (void *) 0xDEADBEEF; - mbox_post(mbox, deadbeef); - - fail_unless(deadbeef == mbox_contents(mbox), - "Contents were not posted"); + fail_unless( deadbeef == mbox_contents( mbox ), + "Contents were not posted" ); } +END_TEST -END_TEST void *mbox_receive_runner(void *mbox_uncast) + +void * mbox_receive_runner( void * mbox_uncast ) { - struct mbox *mbox = (struct mbox *) mbox_uncast; - void *contents = NULL; + struct mbox * mbox = (struct mbox *)mbox_uncast; + void * contents = NULL; - contents = mbox_receive(mbox); - return contents; + contents = mbox_receive( mbox ); + return contents; } -START_TEST(test_receive_blocks_until_post) +START_TEST( test_receive_blocks_until_post ) { - struct mbox *mbox = mbox_create(); - pthread_t receiver; - pthread_create(&receiver, NULL, mbox_receive_runner, mbox); + struct mbox * mbox = mbox_create(); + pthread_t receiver; + pthread_create( &receiver, NULL, mbox_receive_runner, mbox ); + + void * deadbeef = (void *)0xDEADBEEF; + void * retval =NULL; + usleep(10000); + fail_unless( EBUSY == pthread_tryjoin_np( receiver, &retval ), + "Receiver thread wasn't blocked"); - void *deadbeef = (void *) 0xDEADBEEF; - void *retval = NULL; - usleep(10000); - fail_unless(EBUSY == pthread_tryjoin_np(receiver, &retval), - "Receiver thread wasn't blocked"); - - mbox_post(mbox, deadbeef); - fail_unless(0 == pthread_join(receiver, &retval), - "Failed to join the receiver thread"); - fail_unless(retval == deadbeef, "Return value was wrong"); + mbox_post( mbox, deadbeef ); + fail_unless( 0 == pthread_join( receiver, &retval ), + "Failed to join the receiver thread" ); + fail_unless( retval == deadbeef, + "Return value was wrong" ); } +END_TEST -END_TEST Suite * mbox_suite(void) + +Suite* mbox_suite(void) { - Suite *s = suite_create("mbox"); - TCase *tc_create = tcase_create("create"); - TCase *tc_post = tcase_create("post"); + Suite *s = suite_create("mbox"); + TCase *tc_create = tcase_create("create"); + TCase *tc_post = tcase_create("post"); - tcase_add_test(tc_create, test_allocs_cvar); + tcase_add_test(tc_create, test_allocs_cvar); - tcase_add_test(tc_post, test_post_stores_value); - tcase_add_test(tc_post, test_receive_blocks_until_post); + tcase_add_test( tc_post, test_post_stores_value ); + tcase_add_test( tc_post, test_receive_blocks_until_post); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_post); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_post); - return s; + return s; } @@ -81,16 +88,17 @@ END_TEST Suite * mbox_suite(void) int main(void) { #ifdef DEBUG - log_level = 0; + log_level = 0; #else - log_level = 2; + log_level = 2; #endif - int number_failed; - Suite *s = mbox_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - log_level = 0; - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? 0 : 1; + int number_failed; + Suite *s = mbox_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + log_level = 0; + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; } + diff --git a/tests/unit/check_nbdtypes.c b/tests/unit/check_nbdtypes.c index b1ee034..9124063 100644 --- a/tests/unit/check_nbdtypes.c +++ b/tests/unit/check_nbdtypes.c @@ -4,246 +4,257 @@ START_TEST(test_init_passwd) { - struct nbd_init_raw init_raw; - struct nbd_init init; + struct nbd_init_raw init_raw; + struct nbd_init init; - memcpy(init_raw.passwd, INIT_PASSWD, 8); - - nbd_r2h_init(&init_raw, &init); - memset(init_raw.passwd, 0, 8); - nbd_h2r_init(&init, &init_raw); - - fail_unless(memcmp(init.passwd, INIT_PASSWD, 8) == 0, - "The password was not copied."); - fail_unless(memcmp(init_raw.passwd, INIT_PASSWD, 8) == 0, - "The password was not copied back."); + memcpy( init_raw.passwd, INIT_PASSWD, 8 ); + + nbd_r2h_init( &init_raw, &init ); + memset( init_raw.passwd, 0, 8 ); + nbd_h2r_init( &init, &init_raw ); + + fail_unless( memcmp( init.passwd, INIT_PASSWD, 8 ) == 0, "The password was not copied." ); + fail_unless( memcmp( init_raw.passwd, INIT_PASSWD, 8 ) == 0, "The password was not copied back." ); } +END_TEST -END_TEST START_TEST(test_init_magic) + +START_TEST(test_init_magic) { - struct nbd_init_raw init_raw; - struct nbd_init init; + struct nbd_init_raw init_raw; + struct nbd_init init; - init_raw.magic = 12345; - nbd_r2h_init(&init_raw, &init); - fail_unless(be64toh(12345) == init.magic, "Magic was not converted."); + init_raw.magic = 12345; + nbd_r2h_init( &init_raw, &init ); + fail_unless( be64toh( 12345 ) == init.magic, "Magic was not converted." ); - init.magic = 67890; - nbd_h2r_init(&init, &init_raw); - fail_unless(htobe64(67890) == init_raw.magic, - "Magic was not converted back."); + init.magic = 67890; + nbd_h2r_init( &init, &init_raw ); + fail_unless( htobe64( 67890 ) == init_raw.magic, "Magic was not converted back." ); } +END_TEST -END_TEST START_TEST(test_init_size) + +START_TEST(test_init_size) { - struct nbd_init_raw init_raw; - struct nbd_init init; + struct nbd_init_raw init_raw; + struct nbd_init init; - init_raw.size = 12345; - nbd_r2h_init(&init_raw, &init); - fail_unless(be64toh(12345) == init.size, "Size was not converted."); + init_raw.size = 12345; + nbd_r2h_init( &init_raw, &init ); + fail_unless( be64toh( 12345 ) == init.size, "Size was not converted." ); - init.size = 67890; - nbd_h2r_init(&init, &init_raw); - fail_unless(htobe64(67890) == init_raw.size, - "Size was not converted back."); + init.size = 67890; + nbd_h2r_init( &init, &init_raw ); + fail_unless( htobe64( 67890 ) == init_raw.size, "Size was not converted back." ); } +END_TEST -END_TEST START_TEST(test_request_magic) + +START_TEST(test_request_magic ) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.magic = 12345; - nbd_r2h_request(&request_raw, &request); - fail_unless(be32toh(12345) == request.magic, - "Magic was not converted."); + request_raw.magic = 12345; + nbd_r2h_request( &request_raw, &request ); + fail_unless( be32toh( 12345 ) == request.magic, "Magic was not converted." ); - request.magic = 67890; - nbd_h2r_request(&request, &request_raw); - fail_unless(htobe32(67890) == request_raw.magic, - "Magic was not converted back."); + request.magic = 67890; + nbd_h2r_request( &request, &request_raw ); + fail_unless( htobe32( 67890 ) == request_raw.magic, "Magic was not converted back." ); } +END_TEST -END_TEST START_TEST(test_request_type) +START_TEST(test_request_type) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.type = 123; - nbd_r2h_request(&request_raw, &request); - fail_unless(be16toh(123) == request.type, "Type was not converted."); + request_raw.type = 123; + nbd_r2h_request( &request_raw, &request ); + fail_unless( be16toh( 123 ) == request.type, "Type was not converted." ); - request.type = 234; - nbd_h2r_request(&request, &request_raw); - fail_unless(htobe16(234) == request_raw.type, - "Type was not converted back."); + request.type = 234; + nbd_h2r_request( &request, &request_raw ); + fail_unless( htobe16( 234 ) == request_raw.type, "Type was not converted back." ); } +END_TEST -END_TEST START_TEST(test_request_flags) + + +START_TEST(test_request_flags) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.flags = 123; - nbd_r2h_request(&request_raw, &request); - fail_unless(be16toh(123) == request.flags, - "Flags were not converted."); + request_raw.flags = 123; + nbd_r2h_request( &request_raw, &request ); + fail_unless( be16toh( 123 ) == request.flags, "Flags were not converted." ); - request.flags = 234; - nbd_h2r_request(&request, &request_raw); - fail_unless(htobe16(234) == request_raw.flags, - "Flags were not converted back."); + request.flags = 234; + nbd_h2r_request( &request, &request_raw ); + fail_unless( htobe16( 234 ) == request_raw.flags, "Flags were not converted back." ); } +END_TEST -END_TEST START_TEST(test_request_handle) + + +START_TEST(test_request_handle) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - memcpy(request_raw.handle.b, "MYHANDLE", 8); - - nbd_r2h_request(&request_raw, &request); - request_raw.handle.w = 0; - nbd_h2r_request(&request, &request_raw); - - fail_unless(memcmp(request.handle.b, "MYHANDLE", 8) == 0, - "The handle was not copied."); - fail_unless(memcmp(request_raw.handle.b, "MYHANDLE", 8) == 0, - "The handle was not copied back."); + memcpy( request_raw.handle.b, "MYHANDLE", 8 ); + + nbd_r2h_request( &request_raw, &request ); + request_raw.handle.w = 0; + nbd_h2r_request( &request, &request_raw ); + + fail_unless( memcmp( request.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied." ); + fail_unless( memcmp( request_raw.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied back." ); } +END_TEST -END_TEST START_TEST(test_request_from) + + +START_TEST(test_request_from ) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.from = 12345; - nbd_r2h_request(&request_raw, &request); - fail_unless(be64toh(12345) == request.from, "From was not converted."); + request_raw.from = 12345; + nbd_r2h_request( &request_raw, &request ); + fail_unless( be64toh( 12345 ) == request.from, "From was not converted." ); - request.from = 67890; - nbd_h2r_request(&request, &request_raw); - fail_unless(htobe64(67890) == request_raw.from, - "From was not converted back."); + request.from = 67890; + nbd_h2r_request( &request, &request_raw ); + fail_unless( htobe64( 67890 ) == request_raw.from, "From was not converted back." ); } +END_TEST -END_TEST START_TEST(test_request_len) + + +START_TEST(test_request_len ) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.len = 12345; - nbd_r2h_request(&request_raw, &request); - fail_unless(be32toh(12345) == request.len, "Type was not converted."); + request_raw.len = 12345; + nbd_r2h_request( &request_raw, &request ); + fail_unless( be32toh( 12345 ) == request.len, "Type was not converted." ); - request.len = 67890; - nbd_h2r_request(&request, &request_raw); - fail_unless(htobe32(67890) == request_raw.len, - "Type was not converted back."); + request.len = 67890; + nbd_h2r_request( &request, &request_raw ); + fail_unless( htobe32( 67890 ) == request_raw.len, "Type was not converted back." ); } +END_TEST -END_TEST START_TEST(test_reply_magic) + +START_TEST(test_reply_magic ) { - struct nbd_reply_raw reply_raw; - struct nbd_reply reply; + struct nbd_reply_raw reply_raw; + struct nbd_reply reply; - reply_raw.magic = 12345; - nbd_r2h_reply(&reply_raw, &reply); - fail_unless(be32toh(12345) == reply.magic, "Magic was not converted."); + reply_raw.magic = 12345; + nbd_r2h_reply( &reply_raw, &reply ); + fail_unless( be32toh( 12345 ) == reply.magic, "Magic was not converted." ); - reply.magic = 67890; - nbd_h2r_reply(&reply, &reply_raw); - fail_unless(htobe32(67890) == reply_raw.magic, - "Magic was not converted back."); + reply.magic = 67890; + nbd_h2r_reply( &reply, &reply_raw ); + fail_unless( htobe32( 67890 ) == reply_raw.magic, "Magic was not converted back." ); } +END_TEST -END_TEST START_TEST(test_reply_error) + +START_TEST(test_reply_error ) { - struct nbd_reply_raw reply_raw; - struct nbd_reply reply; + struct nbd_reply_raw reply_raw; + struct nbd_reply reply; - reply_raw.error = 12345; - nbd_r2h_reply(&reply_raw, &reply); - fail_unless(be32toh(12345) == reply.error, "Error was not converted."); + reply_raw.error = 12345; + nbd_r2h_reply( &reply_raw, &reply ); + fail_unless( be32toh( 12345 ) == reply.error, "Error was not converted." ); - reply.error = 67890; - nbd_h2r_reply(&reply, &reply_raw); - fail_unless(htobe32(67890) == reply_raw.error, - "Error was not converted back."); + reply.error = 67890; + nbd_h2r_reply( &reply, &reply_raw ); + fail_unless( htobe32( 67890 ) == reply_raw.error, "Error was not converted back." ); } +END_TEST -END_TEST START_TEST(test_reply_handle) +START_TEST(test_reply_handle) { - struct nbd_reply_raw reply_raw; - struct nbd_reply reply; + struct nbd_reply_raw reply_raw; + struct nbd_reply reply; - memcpy(reply_raw.handle.b, "MYHANDLE", 8); - - nbd_r2h_reply(&reply_raw, &reply); - reply_raw.handle.w = 0; - nbd_h2r_reply(&reply, &reply_raw); - - fail_unless(memcmp(reply.handle.b, "MYHANDLE", 8) == 0, - "The handle was not copied."); - fail_unless(memcmp(reply_raw.handle.b, "MYHANDLE", 8) == 0, - "The handle was not copied back."); + memcpy( reply_raw.handle.b, "MYHANDLE", 8 ); + + nbd_r2h_reply( &reply_raw, &reply ); + reply_raw.handle.w = 0; + nbd_h2r_reply( &reply, &reply_raw ); + + fail_unless( memcmp( reply.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied." ); + fail_unless( memcmp( reply_raw.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied back." ); } +END_TEST -END_TEST START_TEST(test_convert_from) + +START_TEST( test_convert_from ) { - /* Check that we can correctly pull numbers out of an - * nbd_request_raw */ - struct nbd_request_raw request_raw; - struct nbd_request request; + /* Check that we can correctly pull numbers out of an + * nbd_request_raw */ + struct nbd_request_raw request_raw; + struct nbd_request request; - uint64_t target = 0x8000000000000000; + uint64_t target = 0x8000000000000000; - /* this is stored big-endian */ - request_raw.from = htobe64(target); + /* this is stored big-endian */ + request_raw.from = htobe64(target); - /* We expect this to convert big-endian to the host format */ - nbd_r2h_request(&request_raw, &request); + /* We expect this to convert big-endian to the host format */ + nbd_r2h_request( &request_raw, &request ); - fail_unless(target == request.from, "from was wrong"); -} + fail_unless( target == request.from, "from was wrong" ); +} +END_TEST -END_TEST Suite * nbdtypes_suite(void) +Suite *nbdtypes_suite(void) { - Suite *s = suite_create("nbdtypes"); - TCase *tc_init = tcase_create("nbd_init"); - TCase *tc_request = tcase_create("nbd_request"); - TCase *tc_reply = tcase_create("nbd_reply"); + Suite *s = suite_create( "nbdtypes" ); + TCase *tc_init = tcase_create( "nbd_init" ); + TCase *tc_request = tcase_create( "nbd_request" ); + TCase *tc_reply = tcase_create( "nbd_reply" ); - tcase_add_test(tc_init, test_init_passwd); - tcase_add_test(tc_init, test_init_magic); - tcase_add_test(tc_init, test_init_size); - tcase_add_test(tc_request, test_request_magic); - tcase_add_test(tc_request, test_request_type); - tcase_add_test(tc_request, test_request_handle); - tcase_add_test(tc_request, test_request_from); - tcase_add_test(tc_request, test_request_len); - tcase_add_test(tc_request, test_convert_from); - tcase_add_test(tc_reply, test_reply_magic); - tcase_add_test(tc_reply, test_reply_error); - tcase_add_test(tc_reply, test_reply_handle); + tcase_add_test( tc_init, test_init_passwd ); + tcase_add_test( tc_init, test_init_magic ); + tcase_add_test( tc_init, test_init_size ); + tcase_add_test( tc_request, test_request_magic ); + tcase_add_test( tc_request, test_request_type ); + tcase_add_test( tc_request, test_request_handle ); + tcase_add_test( tc_request, test_request_from ); + tcase_add_test( tc_request, test_request_len ); + tcase_add_test( tc_request, test_convert_from ); + tcase_add_test( tc_reply, test_reply_magic ); + tcase_add_test( tc_reply, test_reply_error ); + tcase_add_test( tc_reply, test_reply_handle ); - suite_add_tcase(s, tc_init); - suite_add_tcase(s, tc_request); - suite_add_tcase(s, tc_reply); + suite_add_tcase( s, tc_init ); + suite_add_tcase( s, tc_request ); + suite_add_tcase( s, tc_reply ); - return s; + return s; } int main(void) { - int number_failed; - Suite *s = nbdtypes_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; + int number_failed; + Suite *s = nbdtypes_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; } + diff --git a/tests/unit/check_parse.c b/tests/unit/check_parse.c index 3d9130a..b30ee6d 100644 --- a/tests/unit/check_parse.c +++ b/tests/unit/check_parse.c @@ -3,41 +3,45 @@ #include -START_TEST(test_can_parse_ip_address_twice) +START_TEST( test_can_parse_ip_address_twice ) { - char ip_address[] = "127.0.0.1"; - struct sockaddr saddr; + char ip_address[] = "127.0.0.1"; + struct sockaddr saddr; - parse_ip_to_sockaddr(&saddr, ip_address); - parse_ip_to_sockaddr(&saddr, ip_address); + parse_ip_to_sockaddr( &saddr, ip_address ); + parse_ip_to_sockaddr( &saddr, ip_address ); } +END_TEST -END_TEST Suite * parse_suite(void) + + +Suite* parse_suite(void) { - Suite *s = suite_create("parse"); - TCase *tc_create = tcase_create("ip_to_sockaddr"); + Suite *s = suite_create("parse"); + TCase *tc_create = tcase_create("ip_to_sockaddr"); - tcase_add_test(tc_create, test_can_parse_ip_address_twice); + tcase_add_test(tc_create, test_can_parse_ip_address_twice); - suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_create); - return s; + return s; } #ifdef DEBUG -#define LOG_LEVEL 0 +# define LOG_LEVEL 0 #else -#define LOG_LEVEL 2 +# define LOG_LEVEL 2 #endif int main(void) { - log_level = LOG_LEVEL; - int number_failed; - Suite *s = parse_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; + log_level = LOG_LEVEL; + int number_failed; + Suite *s = parse_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; } + diff --git a/tests/unit/check_readwrite.c b/tests/unit/check_readwrite.c index 9f20bf9..c158d7b 100644 --- a/tests/unit/check_readwrite.c +++ b/tests/unit/check_readwrite.c @@ -21,169 +21,173 @@ -int fd_read_request(int, struct nbd_request_raw *); -int fd_write_reply(int, uint64_t, int); +int fd_read_request( int, struct nbd_request_raw *); +int fd_write_reply( int, uint64_t, int ); int marker; -void error_marker(void *unused __attribute__ ((unused)), - int fatal __attribute__ ((unused))) +void error_marker(void * unused __attribute__((unused)), + int fatal __attribute__((unused))) { - marker = 1; - return; + marker = 1; + return; } struct respond { - int sock_fds[2]; // server end - int do_fail; - pthread_t thread_id; - pthread_attr_t thread_attr; - struct nbd_request received; + int sock_fds[2]; // server end + int do_fail; + pthread_t thread_id; + pthread_attr_t thread_attr; + struct nbd_request received; }; -void *responder(void *respond_uncast) +void * responder( void *respond_uncast ) { - struct respond *resp = (struct respond *) respond_uncast; - int sock_fd = resp->sock_fds[1]; - struct nbd_request_raw request_raw; - uint64_t wrong_handle = 0x80; + struct respond * resp = (struct respond *) respond_uncast; + int sock_fd = resp->sock_fds[1]; + struct nbd_request_raw request_raw; + uint64_t wrong_handle = 0x80; - if (fd_read_request(sock_fd, &request_raw) == -1) { - fprintf(stderr, "Problem with fd_read_request\n"); - } else { - nbd_r2h_request(&request_raw, &resp->received); - if (resp->do_fail) { - fd_write_reply(sock_fd, wrong_handle, 0); + if( fd_read_request( sock_fd, &request_raw ) == -1){ + fprintf(stderr, "Problem with fd_read_request\n"); } else { - fd_write_reply(sock_fd, resp->received.handle.w, 0); + nbd_r2h_request( &request_raw, &resp->received); + if (resp->do_fail){ + fd_write_reply( sock_fd, wrong_handle, 0 ); + } + else { + fd_write_reply( sock_fd, resp->received.handle.w, 0 ); + } + write( sock_fd, "12345678", 8 ); } - write(sock_fd, "12345678", 8); - } - return NULL; + return NULL; } -struct respond *respond_create(int do_fail) +struct respond * respond_create( int do_fail ) { - struct respond *respond = - (struct respond *) calloc(1, sizeof(struct respond)); - socketpair(PF_UNIX, SOCK_STREAM, 0, respond->sock_fds); - respond->do_fail = do_fail; + struct respond * respond = (struct respond *)calloc( 1, sizeof( struct respond ) ); + socketpair( PF_UNIX, SOCK_STREAM, 0, respond->sock_fds ); + respond->do_fail = do_fail; - pthread_attr_init(&respond->thread_attr); - pthread_create(&respond->thread_id, &respond->thread_attr, responder, - respond); + pthread_attr_init( &respond->thread_attr ); + pthread_create( &respond->thread_id, &respond->thread_attr, responder, respond ); - return respond; + return respond; } -void respond_destroy(struct respond *respond) -{ - NULLCHECK(respond); +void respond_destroy( struct respond * respond ){ + NULLCHECK( respond ); - pthread_join(respond->thread_id, NULL); - pthread_attr_destroy(&respond->thread_attr); + pthread_join( respond->thread_id, NULL ); + pthread_attr_destroy( &respond->thread_attr ); - close(respond->sock_fds[0]); - close(respond->sock_fds[1]); - free(respond); + close( respond->sock_fds[0] ); + close( respond->sock_fds[1] ); + free( respond ); } -void *reader(void *nothing __attribute__ ((unused))) +void * reader( void * nothing __attribute__((unused))) { - DECLARE_ERROR_CONTEXT(error_context); - error_set_handler((cleanup_handler *) error_marker, error_context); + DECLARE_ERROR_CONTEXT( error_context ); + error_set_handler( (cleanup_handler *)error_marker, error_context ); - struct respond *respond = respond_create(1); - int devnull = open("/dev/null", O_WRONLY); - char outbuf[8] = { 0 }; + struct respond * respond = respond_create( 1 ); + int devnull = open("/dev/null", O_WRONLY); + char outbuf[8] = {0}; - socket_nbd_read(respond->sock_fds[0], 0, 8, devnull, outbuf, 1); + socket_nbd_read( respond->sock_fds[0], 0, 8, devnull, outbuf, 1 ); - return NULL; + return NULL; } -START_TEST(test_rejects_mismatched_handle) +START_TEST( test_rejects_mismatched_handle ) { - error_init(); - pthread_t reader_thread; + error_init(); + pthread_t reader_thread; - log_level = 5; + log_level=5; + + marker = 0; + pthread_create( &reader_thread, NULL, reader, NULL ); + FATAL_UNLESS( 0 == pthread_join( reader_thread, NULL ), + "pthread_join failed"); + + log_level=2; - marker = 0; - pthread_create(&reader_thread, NULL, reader, NULL); - FATAL_UNLESS(0 == pthread_join(reader_thread, NULL), - "pthread_join failed"); - - log_level = 2; - - fail_unless(marker == 1, "Error handler wasn't called"); + fail_unless( marker == 1, "Error handler wasn't called" ); } +END_TEST -END_TEST START_TEST(test_accepts_matched_handle) + +START_TEST( test_accepts_matched_handle ) { - struct respond *respond = respond_create(0); + struct respond * respond = respond_create( 0 ); - int devnull = open("/dev/null", O_WRONLY); - char outbuf[8] = { 0 }; + int devnull = open("/dev/null", O_WRONLY); + char outbuf[8] = {0}; - socket_nbd_read(respond->sock_fds[0], 0, 8, devnull, outbuf, 1); + socket_nbd_read( respond->sock_fds[0], 0, 8, devnull, outbuf, 1 ); - respond_destroy(respond); + respond_destroy( respond ); } +END_TEST -END_TEST START_TEST(test_disconnect_doesnt_read_reply) + +START_TEST( test_disconnect_doesnt_read_reply ) { - struct respond *respond = respond_create(1); + struct respond * respond = respond_create( 1 ); - socket_nbd_disconnect(respond->sock_fds[0]); + socket_nbd_disconnect( respond->sock_fds[0] ); - respond_destroy(respond); + respond_destroy( respond ); } +END_TEST -END_TEST Suite * readwrite_suite(void) + +Suite* readwrite_suite(void) { - Suite *s = suite_create("readwrite"); - TCase *tc_transfer = tcase_create("entrust"); - TCase *tc_disconnect = tcase_create("disconnect"); + Suite *s = suite_create("readwrite"); + TCase *tc_transfer = tcase_create("entrust"); + TCase *tc_disconnect = tcase_create("disconnect"); - tcase_add_test(tc_transfer, test_rejects_mismatched_handle); - tcase_add_exit_test(tc_transfer, test_accepts_matched_handle, 0); + tcase_add_test(tc_transfer, test_rejects_mismatched_handle); + tcase_add_exit_test(tc_transfer, test_accepts_matched_handle, 0); - /* This test is a little funny. We respond with a dodgy handle - * and check that this *doesn't* cause a message rejection, - * because we want to know that the sender won't even try to - * read the response. - */ - tcase_add_exit_test(tc_disconnect, test_disconnect_doesnt_read_reply, - 0); + /* This test is a little funny. We respond with a dodgy handle + * and check that this *doesn't* cause a message rejection, + * because we want to know that the sender won't even try to + * read the response. + */ + tcase_add_exit_test( tc_disconnect, test_disconnect_doesnt_read_reply,0 ); - suite_add_tcase(s, tc_transfer); - suite_add_tcase(s, tc_disconnect); + suite_add_tcase(s, tc_transfer); + suite_add_tcase(s, tc_disconnect); - return s; + return s; } #ifdef DEBUG -#define LOG_LEVEL 0 +# define LOG_LEVEL 0 #else -#define LOG_LEVEL 2 +# define LOG_LEVEL 2 #endif int main(void) { - log_level = LOG_LEVEL; - int number_failed; - Suite *s = readwrite_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - log_level = 0; - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? 0 : 1; + log_level = LOG_LEVEL; + int number_failed; + Suite *s = readwrite_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + log_level = 0; + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; } + diff --git a/tests/unit/check_self_pipe.c b/tests/unit/check_self_pipe.c index fcc783f..c3026c9 100644 --- a/tests/unit/check_self_pipe.c +++ b/tests/unit/check_self_pipe.c @@ -9,180 +9,190 @@ #include "self_pipe.h" -START_TEST(test_opens_pipe) +START_TEST( test_opens_pipe ) { - struct self_pipe *sig; - char buf[] = " "; + struct self_pipe* sig; + char buf[] = " "; - sig = self_pipe_create(); + sig = self_pipe_create(); - write(sig->write_fd, "1", 1); - read(sig->read_fd, buf, 1); + write( sig->write_fd, "1", 1 ); + read( sig->read_fd, buf, 1 ); - fail_unless(buf[0] == '1', "Pipe does not seem to be open;"); - self_pipe_destroy(sig); + fail_unless( buf[0] == '1', "Pipe does not seem to be open;" ); + self_pipe_destroy( sig ); +} +END_TEST + + +void * signal_thread( void * thing ) +{ + struct self_pipe *sig = (struct self_pipe *)thing; + usleep( 100000 ); + self_pipe_signal( sig ); + return NULL; } -END_TEST void *signal_thread(void *thing) +pthread_t start_signal_thread( struct self_pipe *sig ) { - struct self_pipe *sig = (struct self_pipe *) thing; - usleep(100000); - self_pipe_signal(sig); - return NULL; -} + pthread_attr_t attr; + pthread_t thread_id; -pthread_t start_signal_thread(struct self_pipe * sig) -{ - pthread_attr_t attr; - pthread_t thread_id; + pthread_attr_init( &attr ); + pthread_create( &thread_id, &attr, signal_thread, sig ); + pthread_attr_destroy( &attr ); - pthread_attr_init(&attr); - pthread_create(&thread_id, &attr, signal_thread, sig); - pthread_attr_destroy(&attr); - - return thread_id; + return thread_id; } -START_TEST(test_signals) +START_TEST( test_signals ) { - struct self_pipe *sig; - fd_set fds; - pthread_t signal_thread_id; + struct self_pipe* sig; + fd_set fds; + pthread_t signal_thread_id; - sig = self_pipe_create(); + sig = self_pipe_create(); - FD_ZERO(&fds); - self_pipe_fd_set(sig, &fds); + FD_ZERO( &fds ); + self_pipe_fd_set( sig, &fds ); - signal_thread_id = start_signal_thread(sig); - if (select(FD_SETSIZE, &fds, NULL, NULL, NULL) == -1) { - fail(strerror(errno)); - } - self_pipe_signal_clear(sig); - - fail_unless(self_pipe_fd_isset(sig, &fds), - "Signalled pipe was not FD_ISSET."); - pthread_join(signal_thread_id, NULL); - - self_pipe_destroy(sig); -} - -END_TEST START_TEST(test_clear_returns_immediately) -{ - struct self_pipe *sig; - sig = self_pipe_create(); - fail_unless(0 == self_pipe_signal_clear(sig), "Wrong clear result."); -} - -END_TEST START_TEST(test_destroy_closes_read_pipe) -{ - struct self_pipe *sig; - ssize_t read_len; - int orig_read_fd; - - sig = self_pipe_create(); - orig_read_fd = sig->read_fd; - self_pipe_destroy(sig); - - while ((read_len = read(orig_read_fd, "", 0)) == -1 && errno == EINTR); - - switch (read_len) { - case 0: - fail("The read fd wasn't closed."); - break; - case -1: - switch (errno) { - case EBADF: - /* This is what we want */ - break; - case EAGAIN: - fail("The read fd wasn't closed."); - break; - default: - fail(strerror(errno)); - break; + signal_thread_id = start_signal_thread( sig ); + if ( select( FD_SETSIZE, &fds, NULL, NULL, NULL ) == -1 ) { + fail( strerror(errno) ); } - break; - default: - fail("The read fd wasn't closed, and had data in it."); - break; - } + self_pipe_signal_clear( sig ); + + fail_unless( self_pipe_fd_isset( sig, &fds ), "Signalled pipe was not FD_ISSET." ); + pthread_join( signal_thread_id, NULL ); + + self_pipe_destroy( sig ); } +END_TEST -END_TEST START_TEST(test_destroy_closes_write_pipe) + +START_TEST( test_clear_returns_immediately ) { - struct self_pipe *sig; - ssize_t write_len; - int orig_write_fd; + struct self_pipe *sig; + sig = self_pipe_create(); + fail_unless( 0 == self_pipe_signal_clear( sig ), "Wrong clear result." ); +} +END_TEST - sig = self_pipe_create(); - orig_write_fd = sig->write_fd; - self_pipe_destroy(sig); - while ((write_len = write(orig_write_fd, "", 0)) == -1 - && errno == EINTR); +START_TEST( test_destroy_closes_read_pipe ) +{ + struct self_pipe* sig; + ssize_t read_len; + int orig_read_fd; - switch (write_len) { - case 0: - fail("The write fd wasn't closed."); - break; - case -1: - switch (errno) { - case EPIPE: - case EBADF: - /* This is what we want */ - break; - case EAGAIN: - fail("The write fd wasn't closed."); - break; - default: - fail(strerror(errno)); - break; + sig = self_pipe_create(); + orig_read_fd = sig->read_fd; + self_pipe_destroy( sig ); + + while( (read_len = read( orig_read_fd, "", 0 )) == -1 && errno == EINTR ); + + switch( read_len ) { + case 0: + fail("The read fd wasn't closed." ); + break; + case -1: + switch(errno) { + case EBADF: + /* This is what we want */ + break; + case EAGAIN: + fail( "The read fd wasn't closed." ); + break; + default: + fail( strerror( errno ) ); + break; + } + break; + default: + fail( "The read fd wasn't closed, and had data in it." ); + break; } - break; - default: - /* To get here, the write(_,_,0) would have to - * write some bytes. +} +END_TEST + + +START_TEST( test_destroy_closes_write_pipe ) +{ + struct self_pipe * sig; + ssize_t write_len; + int orig_write_fd; + + sig = self_pipe_create(); + orig_write_fd = sig->write_fd; + self_pipe_destroy( sig ); + + while ( ( write_len = write( orig_write_fd, "", 0 ) ) == -1 && errno == EINTR ); + + switch( write_len ) { + case 0: + fail( "The write fd wasn't closed." ); + break; + case -1: + switch( errno ) { + case EPIPE: + case EBADF: + /* This is what we want */ + break; + case EAGAIN: + fail("The write fd wasn't closed." ); + break; + default: + fail( strerror( errno ) ); + break; + } + break; + default: + /* To get here, the write(_,_,0) would have to + * write some bytes. + */ + fail( "The write fd wasn't closed, and something REALLY WEIRD is going on." ); + break; + } + +} +END_TEST + + + +Suite *self_pipe_suite(void) +{ + Suite *s = suite_create("self_pipe"); + + TCase *tc_create = tcase_create("create"); + TCase *tc_signal = tcase_create("signal"); + TCase *tc_destroy = tcase_create("destroy"); + + tcase_add_test(tc_create, test_opens_pipe); + tcase_add_test(tc_signal, test_signals ); + tcase_add_test(tc_signal, test_clear_returns_immediately ); + tcase_add_test(tc_destroy, test_destroy_closes_read_pipe ); + tcase_add_test(tc_destroy, test_destroy_closes_write_pipe ); + /* We don't test that destroy free()'s the self_pipe pointer because + * that'll be caught by valgrind. */ - fail("The write fd wasn't closed, and something REALLY WEIRD is going on."); - break; - } -} + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_signal); + suite_add_tcase(s, tc_destroy); -END_TEST Suite * self_pipe_suite(void) -{ - Suite *s = suite_create("self_pipe"); - - TCase *tc_create = tcase_create("create"); - TCase *tc_signal = tcase_create("signal"); - TCase *tc_destroy = tcase_create("destroy"); - - tcase_add_test(tc_create, test_opens_pipe); - tcase_add_test(tc_signal, test_signals); - tcase_add_test(tc_signal, test_clear_returns_immediately); - tcase_add_test(tc_destroy, test_destroy_closes_read_pipe); - tcase_add_test(tc_destroy, test_destroy_closes_write_pipe); - /* We don't test that destroy free()'s the self_pipe pointer because - * that'll be caught by valgrind. - */ - - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_signal); - suite_add_tcase(s, tc_destroy); - - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = self_pipe_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; + int number_failed; + + Suite *s = self_pipe_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; } + diff --git a/tests/unit/check_serve.c b/tests/unit/check_serve.c index e0a2a67..b00bb1a 100644 --- a/tests/unit/check_serve.c +++ b/tests/unit/check_serve.c @@ -15,9 +15,9 @@ #include #ifdef DEBUG -#define LOG_LEVEL 0 +# define LOG_LEVEL 0 #else -#define LOG_LEVEL 2 +# define LOG_LEVEL 2 #endif @@ -28,245 +28,237 @@ #define myfail_if( tst, msg ) do { if( tst ) { myfail( msg ); } } while (0) #define myfail_unless( tst, msg ) myfail_if( !(tst), msg ) -char *dummy_file; +char * dummy_file; char *make_tmpfile(void) { - FILE *fp; - char *fn_buf; - char leader[] = "/tmp/check_serve"; + FILE *fp; + char *fn_buf; + char leader[] = "/tmp/check_serve"; - fn_buf = (char *) malloc(1024); - strncpy(fn_buf, leader, sizeof(leader) - 1); - snprintf(&fn_buf[sizeof(leader) - 1], 10, "%d", getpid()); - fp = fopen(fn_buf, "w"); - fwrite(fn_buf, 1024, 1, fp); - fclose(fp); + fn_buf = (char *)malloc( 1024 ); + strncpy( fn_buf, leader, sizeof( leader ) - 1); + snprintf( &fn_buf[sizeof( leader ) - 1], 10, "%d", getpid() ); + fp = fopen( fn_buf, "w" ); + fwrite( fn_buf, 1024, 1, fp ); + fclose( fp ); - return fn_buf; + return fn_buf; } -void setup(void) +void setup( void ) { - dummy_file = make_tmpfile(); + dummy_file = make_tmpfile(); } -void teardown(void) +void teardown( void ) { - if (dummy_file) { - unlink(dummy_file); - } - free(dummy_file); - dummy_file = NULL; + if( dummy_file ){ unlink( dummy_file ); } + free( dummy_file ); + dummy_file = NULL; } -START_TEST(test_replaces_acl) +START_TEST( test_replaces_acl ) { - struct flexnbd flexnbd; - flexnbd.signal_fd = -1; - struct server *s = - server_create(&flexnbd, "127.0.0.1", "0", dummy_file, 0, 0, NULL, - 1, 0, 1); - struct acl *new_acl = acl_create(0, NULL, 0); + struct flexnbd flexnbd; + flexnbd.signal_fd = -1; + struct server * s = server_create( &flexnbd, "127.0.0.1", "0", dummy_file, 0, 0, NULL, 1, 0, 1 ); + struct acl * new_acl = acl_create( 0, NULL, 0 ); - server_replace_acl(s, new_acl); + server_replace_acl( s, new_acl ); - myfail_unless(s->acl == new_acl, "ACL wasn't replaced."); - server_destroy(s); + myfail_unless( s->acl == new_acl, "ACL wasn't replaced." ); + server_destroy( s ); } +END_TEST -END_TEST START_TEST(test_signals_acl_updated) + +START_TEST( test_signals_acl_updated ) { - struct flexnbd flexnbd; - flexnbd.signal_fd = -1; - struct server *s = - server_create(&flexnbd, "127.0.0.1", "0", dummy_file, 0, 0, NULL, - 1, 0, 1); - struct acl *new_acl = acl_create(0, NULL, 0); + struct flexnbd flexnbd; + flexnbd.signal_fd = -1; + struct server * s = server_create( &flexnbd, "127.0.0.1", "0", dummy_file, 0, 0, NULL, 1, 0, 1 ); + struct acl * new_acl = acl_create( 0, NULL, 0 ); - server_replace_acl(s, new_acl); + server_replace_acl( s, new_acl ); - myfail_unless(1 == self_pipe_signal_clear(s->acl_updated_signal), - "No signal sent."); - server_destroy(s); + myfail_unless( 1 == self_pipe_signal_clear( s->acl_updated_signal ), + "No signal sent." ); + server_destroy( s ); } +END_TEST -END_TEST int connect_client(char *addr, int actual_port, char *source_addr) + +int connect_client( char *addr, int actual_port, char *source_addr ) { - int client_fd = -1; + int client_fd = -1; - struct addrinfo hint; - struct addrinfo *ailist, *aip; + struct addrinfo hint; + struct addrinfo *ailist, *aip; - memset(&hint, '\0', sizeof(struct addrinfo)); - hint.ai_socktype = SOCK_STREAM; + memset( &hint, '\0', sizeof( struct addrinfo ) ); + hint.ai_socktype = SOCK_STREAM; - myfail_if(getaddrinfo(addr, NULL, &hint, &ailist) != 0, - "getaddrinfo failed."); + myfail_if( getaddrinfo( addr, NULL, &hint, &ailist ) != 0, "getaddrinfo failed." ); - int connected = 0; - for (aip = ailist; aip; aip = aip->ai_next) { - ((struct sockaddr_in *) aip->ai_addr)->sin_port = - htons(actual_port); - client_fd = - socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol); + int connected = 0; + for( aip = ailist; aip; aip = aip->ai_next ) { + ((struct sockaddr_in *)aip->ai_addr)->sin_port = htons( actual_port ); + client_fd = socket( aip->ai_family, aip->ai_socktype, aip->ai_protocol ); - if (source_addr) { - struct sockaddr src; - if (!parse_ip_to_sockaddr(&src, source_addr)) { - close(client_fd); - continue; - } - bind(client_fd, &src, sizeof(struct sockaddr_in6)); + if (source_addr) { + struct sockaddr src; + if( !parse_ip_to_sockaddr(&src, source_addr)) { + close(client_fd); + continue; + } + bind(client_fd, &src, sizeof(struct sockaddr_in6)); + } + + if( client_fd == -1) { continue; } + if( connect( client_fd, aip->ai_addr, aip->ai_addrlen) == 0 ) { + connected = 1; + break; + } + close( client_fd ); } - if (client_fd == -1) { - continue; - } - if (connect(client_fd, aip->ai_addr, aip->ai_addrlen) == 0) { - connected = 1; - break; - } - close(client_fd); - } - - myfail_unless(connected, "Didn't connect."); - return client_fd; + myfail_unless( connected, "Didn't connect." ); + return client_fd; } /* These are "internal" functions we need for the following test. We * shouldn't need them but there's no other way at the moment. */ -void serve_open_server_socket(struct server *); -int server_port(struct server *); -void server_accept(struct server *); -int fd_is_closed(int); -void server_close_clients(struct server *); +void serve_open_server_socket( struct server * ); +int server_port( struct server * ); +void server_accept( struct server * ); +int fd_is_closed( int ); +void server_close_clients( struct server * ); -START_TEST(test_acl_update_closes_bad_client) +START_TEST( test_acl_update_closes_bad_client ) { - /* This is the wrong way round. Rather than pulling the thread - * and socket out of the server structure, we should be testing - * a client socket. - */ - struct flexnbd flexnbd; - flexnbd.signal_fd = -1; - struct server *s = - server_create(&flexnbd, "127.0.0.7", "0", dummy_file, 0, 0, NULL, - 1, 0, 1); - struct acl *new_acl = acl_create(0, NULL, 1); - struct client *c; - struct client_tbl_entry *entry; + /* This is the wrong way round. Rather than pulling the thread + * and socket out of the server structure, we should be testing + * a client socket. + */ + struct flexnbd flexnbd; + flexnbd.signal_fd = -1; + struct server * s = server_create( &flexnbd, "127.0.0.7", "0", dummy_file, 0, 0, NULL, 1, 0, 1 ); + struct acl * new_acl = acl_create( 0, NULL, 1 ); + struct client * c; + struct client_tbl_entry * entry; - int actual_port; - int client_fd; - int server_fd; + int actual_port; + int client_fd; + int server_fd; - serve_open_server_socket(s); - actual_port = server_port(s); + serve_open_server_socket( s ); + actual_port = server_port( s ); - client_fd = connect_client("127.0.0.7", actual_port, "127.0.0.1"); - server_accept(s); - entry = &s->nbd_client[0]; - c = entry->client; - /* At this point there should be an entry in the nbd_clients - * table and a background thread to run the client loop - */ - myfail_if(entry->thread == 0, "No client thread was started."); - server_fd = c->socket; - myfail_if(fd_is_closed(server_fd), - "Sanity check failed - client socket wasn't open."); + client_fd = connect_client( "127.0.0.7", actual_port, "127.0.0.1" ); + server_accept( s ); + entry = &s->nbd_client[0]; + c = entry->client; + /* At this point there should be an entry in the nbd_clients + * table and a background thread to run the client loop + */ + myfail_if( entry->thread == 0, "No client thread was started." ); + server_fd = c->socket; + myfail_if( fd_is_closed(server_fd), + "Sanity check failed - client socket wasn't open." ); - server_replace_acl(s, new_acl); + server_replace_acl( s, new_acl ); - /* accept again, so that we can react to the acl replacement signal */ - server_accept(s); + /* accept again, so that we can react to the acl replacement signal */ + server_accept( s ); - /* Fail if we time out here */ - while (!fd_is_closed(server_fd)); + /* Fail if we time out here */ + while( !fd_is_closed( server_fd ) ); - close(client_fd); - server_close_clients(s); - server_destroy(s); + close( client_fd ); + server_close_clients( s ); + server_destroy( s ); } +END_TEST -END_TEST START_TEST(test_acl_update_leaves_good_client) + +START_TEST( test_acl_update_leaves_good_client ) { - struct flexnbd flexnbd; - flexnbd.signal_fd = -1; + struct flexnbd flexnbd; + flexnbd.signal_fd = -1; - struct server *s = - server_create(&flexnbd, "127.0.0.7", "0", dummy_file, 0, 0, NULL, - 1, 0, 1); + struct server * s = server_create( &flexnbd, "127.0.0.7", "0", dummy_file, 0, 0, NULL, 1, 0, 1 ); - char *lines[] = { "127.0.0.1" }; - struct acl *new_acl = acl_create(1, lines, 1); - struct client *c; - struct client_tbl_entry *entry; + char *lines[] = {"127.0.0.1"}; + struct acl * new_acl = acl_create( 1, lines, 1 ); + struct client * c; + struct client_tbl_entry * entry; - int actual_port; - int client_fd; - int server_fd; + int actual_port; + int client_fd; + int server_fd; - serve_open_server_socket(s); - actual_port = server_port(s); - client_fd = connect_client("127.0.0.7", actual_port, "127.0.0.1"); - server_accept(s); - entry = &s->nbd_client[0]; - c = entry->client; - /* At this point there should be an entry in the nbd_clients - * table and a background thread to run the client loop - */ - myfail_if(entry->thread == 0, "No client thread was started."); - server_fd = c->socket; - myfail_if(fd_is_closed(server_fd), - "Sanity check failed - client socket wasn't open."); + serve_open_server_socket( s ); + actual_port = server_port( s ); + client_fd = connect_client( "127.0.0.7", actual_port, "127.0.0.1" ); + server_accept( s ); + entry = &s->nbd_client[0]; + c = entry->client; + /* At this point there should be an entry in the nbd_clients + * table and a background thread to run the client loop + */ + myfail_if( entry->thread == 0, "No client thread was started." ); + server_fd = c->socket; + myfail_if( fd_is_closed(server_fd), + "Sanity check failed - client socket wasn't open." ); - server_replace_acl(s, new_acl); - server_accept(s); + server_replace_acl( s, new_acl ); + server_accept( s ); - myfail_if(self_pipe_signal_clear(c->stop_signal), - "Client was told to stop."); + myfail_if( self_pipe_signal_clear( c->stop_signal ), + "Client was told to stop." ); - close(client_fd); - server_close_clients(s); - server_destroy(s); + close( client_fd ); + server_close_clients( s ); + server_destroy( s ); } +END_TEST -END_TEST Suite * serve_suite(void) + +Suite* serve_suite(void) { - Suite *s = suite_create("serve"); - TCase *tc_acl_update = tcase_create("acl_update"); + Suite *s = suite_create("serve"); + TCase *tc_acl_update = tcase_create("acl_update"); - tcase_add_checked_fixture(tc_acl_update, setup, NULL); + tcase_add_checked_fixture( tc_acl_update, setup, NULL ); - tcase_add_test(tc_acl_update, test_replaces_acl); - tcase_add_test(tc_acl_update, test_signals_acl_updated); + tcase_add_test(tc_acl_update, test_replaces_acl); + tcase_add_test(tc_acl_update, test_signals_acl_updated); - tcase_add_exit_test(tc_acl_update, test_acl_update_closes_bad_client, - 0); - tcase_add_exit_test(tc_acl_update, test_acl_update_leaves_good_client, - 0); + tcase_add_exit_test(tc_acl_update, test_acl_update_closes_bad_client, 0); + tcase_add_exit_test(tc_acl_update, test_acl_update_leaves_good_client, 0); - suite_add_tcase(s, tc_acl_update); + suite_add_tcase(s, tc_acl_update); - return s; + return s; } int main(void) { - log_level = LOG_LEVEL; - error_init(); - 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; + log_level = LOG_LEVEL; + error_init(); + 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; } + diff --git a/tests/unit/check_sockutil.c b/tests/unit/check_sockutil.c index dc7295f..57626bb 100644 --- a/tests/unit/check_sockutil.c +++ b/tests/unit/check_sockutil.c @@ -6,112 +6,110 @@ #include -START_TEST(test_sockaddr_address_string_af_inet_converts_to_string) +START_TEST( test_sockaddr_address_string_af_inet_converts_to_string ) { - struct sockaddr sa; - struct sockaddr_in *v4 = (struct sockaddr_in *) &sa; - char testbuf[128]; - const char *result; + struct sockaddr sa; + struct sockaddr_in* v4 = (struct sockaddr_in*) &sa; + char testbuf[128]; + const char* result; - v4->sin_family = AF_INET; - v4->sin_port = htons(4777); - ck_assert_int_eq(1, inet_pton(AF_INET, "192.168.0.1", &v4->sin_addr)); + v4->sin_family = AF_INET; + v4->sin_port = htons( 4777 ); + ck_assert_int_eq( 1, inet_pton( AF_INET, "192.168.0.1", &v4->sin_addr )); - result = sockaddr_address_string(&sa, &testbuf[0], 128); - ck_assert(result != NULL); + result = sockaddr_address_string( &sa, &testbuf[0], 128 ); + ck_assert( result != NULL ); - ck_assert_str_eq("192.168.0.1 port 4777", testbuf); + ck_assert_str_eq( "192.168.0.1 port 4777", testbuf ); } - END_TEST -START_TEST(test_sockaddr_address_string_af_inet6_converts_to_string) + + +START_TEST( test_sockaddr_address_string_af_inet6_converts_to_string ) { - struct sockaddr_in6 v6_raw; - struct sockaddr_in6 *v6 = &v6_raw; - struct sockaddr *sa = (struct sockaddr *) &v6_raw; + struct sockaddr_in6 v6_raw; + struct sockaddr_in6* v6 = &v6_raw; + struct sockaddr* sa = (struct sockaddr*) &v6_raw; - char testbuf[128]; - const char *result; + char testbuf[128]; + const char* result; - v6->sin6_family = AF_INET6; - v6->sin6_port = htons(4777); - ck_assert_int_eq(1, inet_pton(AF_INET6, "fe80::1", &v6->sin6_addr)); + v6->sin6_family = AF_INET6; + v6->sin6_port = htons( 4777 ); + ck_assert_int_eq( 1, inet_pton( AF_INET6, "fe80::1", &v6->sin6_addr )); - result = sockaddr_address_string(sa, &testbuf[0], 128); - ck_assert(result != NULL); + result = sockaddr_address_string( sa, &testbuf[0], 128 ); + ck_assert( result != NULL ); - ck_assert_str_eq("fe80::1 port 4777", testbuf); + ck_assert_str_eq( "fe80::1 port 4777", testbuf ); } - END_TEST + /* We don't know what it is, so we just call it "???" and return NULL */ -START_TEST(test_sockaddr_address_string_af_unspec_is_failure) +START_TEST( test_sockaddr_address_string_af_unspec_is_failure ) { - struct sockaddr sa; - struct sockaddr_in *v4 = (struct sockaddr_in *) &sa; - char testbuf[128]; - const char *result; + struct sockaddr sa; + struct sockaddr_in* v4 = (struct sockaddr_in*) &sa; + char testbuf[128]; + const char* result; - v4->sin_family = AF_UNSPEC; - v4->sin_port = htons(4777); - ck_assert_int_eq(1, inet_pton(AF_INET, "192.168.0.1", &v4->sin_addr)); + v4->sin_family = AF_UNSPEC; + v4->sin_port = htons( 4777 ); + ck_assert_int_eq( 1, inet_pton( AF_INET, "192.168.0.1", &v4->sin_addr )); - result = sockaddr_address_string(&sa, &testbuf[0], 128); - ck_assert(result == NULL); + result = sockaddr_address_string( &sa, &testbuf[0], 128 ); + ck_assert( result == NULL ); - ck_assert_str_eq("???", testbuf); + ck_assert_str_eq( "???", testbuf ); } - END_TEST + /* This is a complete failure to parse, rather than a partial failure */ -START_TEST(test_sockaddr_address_string_doesnt_overflow_short_buffer) +START_TEST( test_sockaddr_address_string_doesnt_overflow_short_buffer ) { - struct sockaddr sa; - struct sockaddr_in *v4 = (struct sockaddr_in *) &sa; - char testbuf[128]; - const char *result; + struct sockaddr sa; + struct sockaddr_in* v4 = (struct sockaddr_in*) &sa; + char testbuf[128]; + const char* result; - memset(testbuf, 0, 128); - v4->sin_family = AF_INET; - v4->sin_port = htons(4777); - ck_assert_int_eq(1, inet_pton(AF_INET, "192.168.0.1", &v4->sin_addr)); - memset(&testbuf, 0, 128); + memset( testbuf, 0, 128 ); + v4->sin_family = AF_INET; + v4->sin_port = htons( 4777 ); + ck_assert_int_eq( 1, inet_pton( AF_INET, "192.168.0.1", &v4->sin_addr )); + memset( &testbuf, 0, 128 ); - result = sockaddr_address_string(&sa, &testbuf[0], 2); - ck_assert(result == NULL); + result = sockaddr_address_string( &sa, &testbuf[0], 2 ); + ck_assert( result == NULL ); - ck_assert_str_eq("??", testbuf); + ck_assert_str_eq( "??", testbuf ); } +END_TEST -END_TEST Suite * sockutil_suite(void) +Suite *sockutil_suite(void) { - Suite *s = suite_create("sockutil"); + Suite *s = suite_create("sockutil"); - TCase *tc_sockaddr_address_string = - tcase_create("sockaddr_address_string"); + TCase *tc_sockaddr_address_string = tcase_create("sockaddr_address_string"); - tcase_add_test(tc_sockaddr_address_string, - test_sockaddr_address_string_af_inet_converts_to_string); - tcase_add_test(tc_sockaddr_address_string, - test_sockaddr_address_string_af_inet6_converts_to_string); - tcase_add_test(tc_sockaddr_address_string, - test_sockaddr_address_string_af_unspec_is_failure); - tcase_add_test(tc_sockaddr_address_string, - test_sockaddr_address_string_doesnt_overflow_short_buffer); - suite_add_tcase(s, tc_sockaddr_address_string); + tcase_add_test(tc_sockaddr_address_string, test_sockaddr_address_string_af_inet_converts_to_string); + tcase_add_test(tc_sockaddr_address_string, test_sockaddr_address_string_af_inet6_converts_to_string); + tcase_add_test(tc_sockaddr_address_string, test_sockaddr_address_string_af_unspec_is_failure); + tcase_add_test(tc_sockaddr_address_string, test_sockaddr_address_string_doesnt_overflow_short_buffer); + suite_add_tcase(s, tc_sockaddr_address_string); - return s; + return s; } int main(void) { - int number_failed; + int number_failed; - Suite *s = sockutil_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; + Suite *s = sockutil_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; } + diff --git a/tests/unit/check_status.c b/tests/unit/check_status.c index 8c37563..ea89d3b 100644 --- a/tests/unit/check_status.c +++ b/tests/unit/check_status.c @@ -6,331 +6,366 @@ #include -struct server *mock_server(void) +struct server* mock_server(void) { - struct server *out = xmalloc(sizeof(struct server)); - out->l_start_mirror = flexthread_mutex_create(); - out->nbd_client = xmalloc(sizeof(struct client_tbl_entry) * 4); - out->max_nbd_clients = 4; - out->size = 65536; + struct server* out = xmalloc( sizeof( struct server ) ); + out->l_start_mirror = flexthread_mutex_create(); + out->nbd_client = xmalloc( sizeof( struct client_tbl_entry ) * 4 ); + out->max_nbd_clients = 4; + out->size = 65536; - out->allocation_map = bitset_alloc(65536, 4096); + out->allocation_map = bitset_alloc( 65536, 4096 ); - return out; + return out; } -struct server *mock_mirroring_server(void) +struct server* mock_mirroring_server(void) { - struct server *out = mock_server(); - out->mirror = xmalloc(sizeof(struct mirror)); - out->mirror_super = xmalloc(sizeof(struct mirror_super)); - return out; + struct server *out = mock_server(); + out->mirror = xmalloc( sizeof( struct mirror ) ); + out->mirror_super = xmalloc( sizeof( struct mirror_super ) ); + return out; } -void destroy_mock_server(struct server *serve) +void destroy_mock_server( struct server* serve ) { - if (NULL != serve->mirror) { - free(serve->mirror); - } + if ( NULL != serve->mirror ) { + free( serve->mirror ); + } - if (NULL != serve->mirror_super) { - free(serve->mirror_super); - } + if ( NULL != serve->mirror_super ) { + free( serve->mirror_super ); + } - flexthread_mutex_destroy(serve->l_start_mirror); + flexthread_mutex_destroy( serve->l_start_mirror ); - bitset_free(serve->allocation_map); - free(serve->nbd_client); - free(serve); + bitset_free( serve->allocation_map ); + free( serve->nbd_client ); + free( serve ); } -START_TEST(test_status_create) +START_TEST( test_status_create ) { - struct server *server = mock_server(); - struct status *status = status_create(server); + struct server * server = mock_server(); + struct status * status = status_create( server ); - fail_if(NULL == status, "Status wasn't allocated"); - status_destroy(status); - destroy_mock_server(server); + fail_if( NULL == status, "Status wasn't allocated" ); + status_destroy( status ); + destroy_mock_server( server ); } +END_TEST -END_TEST START_TEST(test_gets_has_control) +START_TEST( test_gets_has_control ) { - struct server *server = mock_server(); - server->success = 1; + struct server * server = mock_server(); + server->success = 1; - struct status *status = status_create(server); + struct status * status = status_create( server ); - fail_unless(status->has_control == 1, "has_control wasn't copied"); - status_destroy(status); - destroy_mock_server(server); + fail_unless( status->has_control == 1, "has_control wasn't copied" ); + status_destroy( status ); + destroy_mock_server( server ); } +END_TEST -END_TEST START_TEST(test_gets_is_mirroring) + +START_TEST( test_gets_is_mirroring ) { - struct server *server = mock_server(); - struct status *status = status_create(server); + struct server * server = mock_server(); + struct status * status = status_create( server ); - fail_if(status->is_mirroring, "is_mirroring was set"); - status_destroy(status); - destroy_mock_server(server); + fail_if( status->is_mirroring, "is_mirroring was set" ); + status_destroy( status ); + destroy_mock_server( server ); - server = mock_mirroring_server(); - status = status_create(server); + server = mock_mirroring_server(); + status = status_create( server ); - fail_unless(status->is_mirroring, "is_mirroring wasn't set"); - status_destroy(status); - destroy_mock_server(server); + fail_unless( status->is_mirroring, "is_mirroring wasn't set" ); + status_destroy( status ); + destroy_mock_server( server ); } +END_TEST -END_TEST START_TEST(test_gets_clients_allowed) +START_TEST( test_gets_clients_allowed ) { - struct server *server = mock_server(); - struct status *status = status_create(server); + struct server * server = mock_server(); + struct status * status = status_create( server ); - fail_if(status->clients_allowed, "clients_allowed was set"); - status_destroy(status); + fail_if( status->clients_allowed, "clients_allowed was set" ); + status_destroy( status ); - server->allow_new_clients = 1; - status = status_create(server); + server->allow_new_clients = 1; + status = status_create( server ); - fail_unless(status->clients_allowed, "clients_allowed was not set"); - status_destroy(status); - destroy_mock_server(server); + fail_unless( status->clients_allowed, "clients_allowed was not set" ); + status_destroy( status ); + destroy_mock_server( server ); } +END_TEST -END_TEST START_TEST(test_gets_pid) +START_TEST( test_gets_pid ) { - struct server *server = mock_server(); - struct status *status = status_create(server); + struct server * server = mock_server(); + struct status * status = status_create( server ); - fail_unless(getpid() == status->pid, "Pid wasn't gathered"); + fail_unless( getpid() == status->pid, "Pid wasn't gathered" ); - status_destroy(status); - destroy_mock_server(server); + status_destroy( status ); + destroy_mock_server( server ); } +END_TEST -END_TEST START_TEST(test_gets_size) +START_TEST( test_gets_size ) { - struct server *server = mock_server(); - server->size = 1024; + struct server * server = mock_server(); + server->size = 1024; - struct status *status = status_create(server); + struct status * status = status_create( server ); - fail_unless(1024 == status->size, "Size wasn't gathered"); + fail_unless( 1024 == status->size, "Size wasn't gathered" ); - status_destroy(status); - destroy_mock_server(server); + status_destroy( status ); + destroy_mock_server( server ); } +END_TEST -END_TEST START_TEST(test_gets_migration_statistics) +START_TEST( test_gets_migration_statistics ) { - struct server *server = mock_mirroring_server(); - server->mirror->all_dirty = 16384; - server->mirror->max_bytes_per_second = 32768; - server->mirror->offset = 0; + struct server * server = mock_mirroring_server(); + server->mirror->all_dirty = 16384; + server->mirror->max_bytes_per_second = 32768; + server->mirror->offset = 0; - /* we have a bit of a time dependency here */ - server->mirror->migration_started = monotonic_time_ms(); + /* we have a bit of a time dependency here */ + server->mirror->migration_started = monotonic_time_ms(); - struct status *status = status_create(server); + struct status * status = status_create( server ); - fail_unless(0 == status->migration_duration || + fail_unless ( + 0 == status->migration_duration || 1 == status->migration_duration || 2 == status->migration_duration, - "migration_duration is unreasonable!"); + "migration_duration is unreasonable!" + ); - fail_unless(16384 / (status->migration_duration + 1) == - status->migration_speed, - "migration_speed not calculated correctly"); + fail_unless( + 16384 / ( status->migration_duration + 1 ) == status->migration_speed, + "migration_speed not calculated correctly" + ); - fail_unless(32768 == status->migration_speed_limit, - "migration_speed_limit not read"); + fail_unless( 32768 == status->migration_speed_limit, "migration_speed_limit not read" ); - // ( size / current_bps ) + 1 happens to be 3 for this test - fail_unless(3 == status->migration_seconds_left, - "migration_seconds_left not gathered"); + // ( size / current_bps ) + 1 happens to be 3 for this test + fail_unless( 3 == status->migration_seconds_left, "migration_seconds_left not gathered" ); - status_destroy(status); - destroy_mock_server(server); + status_destroy( status ); + destroy_mock_server( server ); } - END_TEST + + #define RENDER_TEST_SETUP \ struct status status; \ int fds[2]; \ pipe( fds ); -void fail_unless_rendered(int fd, char *fragment) + +void fail_unless_rendered( int fd, char *fragment ) { - char buf[1024] = { 0 }; - char emsg[1024] = { 0 }; - char *found = NULL; + char buf[1024] = {0}; + char emsg[1024] = {0}; + char *found = NULL; - sprintf(emsg, "Fragment: %s not found", fragment); + sprintf(emsg, "Fragment: %s not found", fragment ); - fail_unless(read_until_newline(fd, buf, 1024) > 0, "Couldn't read"); - found = strstr(buf, fragment); - fail_if(NULL == found, emsg); + fail_unless( read_until_newline( fd, buf, 1024 ) > 0, "Couldn't read" ); + found = strstr( buf, fragment ); + fail_if( NULL == found, emsg ); - return; + return; } -void fail_if_rendered(int fd, char *fragment) +void fail_if_rendered( int fd, char *fragment ) { - char buf[1024] = { 0 }; - char emsg[1024] = { 0 }; - char *found = NULL; + char buf[1024] = {0}; + char emsg[1024] = {0}; + char *found = NULL; - sprintf(emsg, "Fragment: %s found", fragment); + sprintf(emsg, "Fragment: %s found", fragment ); - fail_unless(read_until_newline(fd, buf, 1024) > 0, "Couldn't read"); - found = strstr(buf, fragment); - fail_unless(NULL == found, emsg); + fail_unless( read_until_newline( fd, buf, 1024 ) > 0, "Couldn't read" ); + found = strstr( buf, fragment ); + fail_unless( NULL == found, emsg ); - return; + return; } -START_TEST(test_renders_has_control) +START_TEST( test_renders_has_control ) { - RENDER_TEST_SETUP status.has_control = 1; - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "has_control=true"); + RENDER_TEST_SETUP - status.has_control = 0; - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "has_control=false"); + status.has_control = 1; + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "has_control=true" ); + + status.has_control = 0; + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "has_control=false" ); } +END_TEST -END_TEST START_TEST(test_renders_is_mirroring) + +START_TEST( test_renders_is_mirroring ) { - RENDER_TEST_SETUP status.is_mirroring = 1; - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "is_mirroring=true"); + RENDER_TEST_SETUP - status.is_mirroring = 0; - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "is_mirroring=false"); + status.is_mirroring = 1; + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "is_mirroring=true" ); + + status.is_mirroring = 0; + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "is_mirroring=false" ); } +END_TEST -END_TEST START_TEST(test_renders_clients_allowed) +START_TEST( test_renders_clients_allowed ) { - RENDER_TEST_SETUP status.clients_allowed = 1; - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "clients_allowed=true"); + RENDER_TEST_SETUP - status.clients_allowed = 0; - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "clients_allowed=false"); + status.clients_allowed = 1; + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "clients_allowed=true" ); + + status.clients_allowed = 0; + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "clients_allowed=false" ); } +END_TEST -END_TEST START_TEST(test_renders_num_clients) +START_TEST( test_renders_num_clients ) { - RENDER_TEST_SETUP status.num_clients = 0; - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "num_clients=0"); + RENDER_TEST_SETUP - status.num_clients = 4000; - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "num_clients=4000"); + status.num_clients = 0; + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "num_clients=0" ); + + status.num_clients = 4000; + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "num_clients=4000" ); } +END_TEST -END_TEST START_TEST(test_renders_pid) + +START_TEST( test_renders_pid ) { - RENDER_TEST_SETUP status.pid = 42; - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "pid=42"); + RENDER_TEST_SETUP + + status.pid = 42; + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "pid=42" ); } +END_TEST -END_TEST START_TEST(test_renders_size) +START_TEST( test_renders_size ) { - RENDER_TEST_SETUP status.size = ((uint64_t) 1 << 33); - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "size=8589934592"); + RENDER_TEST_SETUP + + status.size = ( (uint64_t)1 << 33 ); + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "size=8589934592" ); } +END_TEST -END_TEST START_TEST(test_renders_migration_statistics) +START_TEST( test_renders_migration_statistics ) { - RENDER_TEST_SETUP status.is_mirroring = 0; - status.migration_duration = 8; - status.migration_speed = 40000000; - status.migration_speed_limit = 40000001; - status.migration_seconds_left = 1; - status.migration_bytes_left = 5000; + RENDER_TEST_SETUP - status_write(&status, fds[1]); - fail_if_rendered(fds[0], "migration_duration"); + status.is_mirroring = 0; + status.migration_duration = 8; + status.migration_speed = 40000000; + status.migration_speed_limit = 40000001; + status.migration_seconds_left = 1; + status.migration_bytes_left = 5000; - status_write(&status, fds[1]); - fail_if_rendered(fds[0], "migration_speed"); + status_write( &status, fds[1] ); + fail_if_rendered( fds[0], "migration_duration" ); - status_write(&status, fds[1]); - fail_if_rendered(fds[0], "migration_speed_limit"); + status_write( &status, fds[1] ); + fail_if_rendered( fds[0], "migration_speed" ); - status_write(&status, fds[1]); - fail_if_rendered(fds[0], "migration_seconds_left"); + status_write( &status, fds[1] ); + fail_if_rendered( fds[0], "migration_speed_limit" ); - status.is_mirroring = 1; + status_write( &status, fds[1] ); + fail_if_rendered( fds[0], "migration_seconds_left" ); - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "migration_duration=8"); + status.is_mirroring = 1; - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "migration_speed=40000000"); + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "migration_duration=8" ); - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "migration_speed_limit=40000001"); + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "migration_speed=40000000" ); - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "migration_seconds_left=1"); + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "migration_speed_limit=40000001" ); - status_write(&status, fds[1]); - fail_unless_rendered(fds[0], "migration_bytes_left=5000"); + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "migration_seconds_left=1" ); - status.migration_speed_limit = UINT64_MAX; + status_write( &status, fds[1] ); + fail_unless_rendered( fds[0], "migration_bytes_left=5000" ); - status_write(&status, fds[1]); - fail_if_rendered(fds[0], "migration_speed_limit"); + status.migration_speed_limit = UINT64_MAX; + + status_write( &status, fds[1] ); + fail_if_rendered( fds[0], "migration_speed_limit" ); } +END_TEST -END_TEST Suite * status_suite(void) + +Suite *status_suite(void) { - Suite *s = suite_create("status"); - TCase *tc_create = tcase_create("create"); - TCase *tc_render = tcase_create("render"); + Suite *s = suite_create("status"); + TCase *tc_create = tcase_create("create"); + TCase *tc_render = tcase_create("render"); - tcase_add_test(tc_create, test_status_create); - tcase_add_test(tc_create, test_gets_has_control); - tcase_add_test(tc_create, test_gets_is_mirroring); - tcase_add_test(tc_create, test_gets_clients_allowed); - tcase_add_test(tc_create, test_gets_pid); - tcase_add_test(tc_create, test_gets_size); - tcase_add_test(tc_create, test_gets_migration_statistics); + tcase_add_test(tc_create, test_status_create); + tcase_add_test(tc_create, test_gets_has_control); + tcase_add_test(tc_create, test_gets_is_mirroring); + tcase_add_test(tc_create, test_gets_clients_allowed); + tcase_add_test(tc_create, test_gets_pid); + tcase_add_test(tc_create, test_gets_size); + tcase_add_test(tc_create, test_gets_migration_statistics); - tcase_add_test(tc_render, test_renders_has_control); - tcase_add_test(tc_render, test_renders_is_mirroring); - tcase_add_test(tc_render, test_renders_clients_allowed); - tcase_add_test(tc_render, test_renders_num_clients); - tcase_add_test(tc_render, test_renders_pid); - tcase_add_test(tc_render, test_renders_size); - tcase_add_test(tc_render, test_renders_migration_statistics); + tcase_add_test(tc_render, test_renders_has_control); + tcase_add_test(tc_render, test_renders_is_mirroring); + tcase_add_test(tc_render, test_renders_clients_allowed); + tcase_add_test(tc_render, test_renders_num_clients); + tcase_add_test(tc_render, test_renders_pid); + tcase_add_test(tc_render, test_renders_size); + tcase_add_test(tc_render, test_renders_migration_statistics); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_render); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_render); - return s; + return s; } int main(void) { - int number_failed; + int number_failed; - Suite *s = status_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; + Suite *s = status_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; } + diff --git a/tests/unit/check_util.c b/tests/unit/check_util.c index 5fdd588..63e2ade 100644 --- a/tests/unit/check_util.c +++ b/tests/unit/check_util.c @@ -9,156 +9,165 @@ struct cleanup_bucket { - struct self_pipe *called_signal; + struct self_pipe *called_signal; }; struct cleanup_bucket bkt; -void bucket_init(void) -{ - if (bkt.called_signal) { - self_pipe_destroy(bkt.called_signal); - } - bkt.called_signal = self_pipe_create(); +void bucket_init(void){ + if ( bkt.called_signal ) { + self_pipe_destroy( bkt.called_signal ); + } + bkt.called_signal = self_pipe_create(); } void setup(void) { - bkt.called_signal = NULL; + bkt.called_signal = NULL; } int handler_called(void) { - return self_pipe_signal_clear(bkt.called_signal); + return self_pipe_signal_clear( bkt.called_signal ); } -void dummy_cleanup(struct cleanup_bucket *foo, int fatal - __attribute__ ((unused))) +void dummy_cleanup( struct cleanup_bucket * foo, int fatal __attribute__((unused)) ) { - if (NULL != foo) { - self_pipe_signal(foo->called_signal); - } + if (NULL != foo){ + self_pipe_signal( foo->called_signal ); + } } void trigger_fatal(void) -{ - error_init(); - error_set_handler((cleanup_handler *) dummy_cleanup, &bkt); +{ + error_init(); + error_set_handler( (cleanup_handler*) dummy_cleanup, &bkt ); - log_level = 5; + log_level = 5; - fatal("Expected fatal error"); + fatal("Expected fatal error"); } -void trigger_error(void) +void trigger_error( void ) { - error_init(); - error_set_handler((cleanup_handler *) dummy_cleanup, &bkt); - log_level = 4; - error("Expected error"); + error_init(); + error_set_handler( (cleanup_handler *) dummy_cleanup, &bkt); + log_level = 4; + error("Expected error"); } -START_TEST(test_fatal_kills_process) +START_TEST( test_fatal_kills_process ) { - pid_t pid; + pid_t pid; - pid = fork(); + pid = fork(); - if (pid == 0) { - trigger_fatal(); - /* If we get here, just block so the test timeout fails - * us */ - sleep(10); - } else { - int kidret, kidstatus, result; - result = waitpid(pid, &kidret, 0); - fail_if(result < 0, "Wait failed."); - fail_unless(WIFSIGNALED(kidret), "Process didn't exit via signal"); - kidstatus = WTERMSIG(kidret); - ck_assert_int_eq(kidstatus, SIGABRT); - } + if ( pid == 0 ) { + trigger_fatal(); + /* If we get here, just block so the test timeout fails + * us */ + sleep(10); + } + else { + int kidret, kidstatus, result; + result = waitpid( pid, &kidret, 0 ); + fail_if( result < 0, "Wait failed." ); + fail_unless( WIFSIGNALED( kidret ), "Process didn't exit via signal" ); + kidstatus = WTERMSIG( kidret ); + ck_assert_int_eq( kidstatus, SIGABRT ); + } } +END_TEST -END_TEST void *error_thread(void *nothing __attribute__ ((unused))) + +void * error_thread( void *nothing __attribute__((unused)) ) { - trigger_error(); - return NULL; + trigger_error(); + return NULL; } -START_TEST(test_error_doesnt_kill_process) +START_TEST( test_error_doesnt_kill_process ) { - bucket_init(); - pthread_attr_t attr; - pthread_t tid; + bucket_init(); + pthread_attr_t attr; + pthread_t tid; - pthread_attr_init(&attr); + pthread_attr_init( &attr ); - pthread_create(&tid, &attr, error_thread, NULL); - pthread_join(tid, NULL); + pthread_create( &tid, &attr, error_thread, NULL ); + pthread_join( tid, NULL ); } +END_TEST -END_TEST START_TEST(test_error_calls_handler) + +START_TEST( test_error_calls_handler ) { - bucket_init(); + bucket_init(); - pthread_attr_t attr; - pthread_t tid; + pthread_attr_t attr; + pthread_t tid; - pthread_attr_init(&attr); + pthread_attr_init( &attr ); - pthread_create(&tid, &attr, error_thread, NULL); - pthread_join(tid, NULL); - fail_unless(handler_called(), "Handler wasn't called."); + pthread_create( &tid, &attr, error_thread, NULL ); + pthread_join( tid, NULL ); + fail_unless( handler_called(), "Handler wasn't called." ); } +END_TEST -END_TEST START_TEST(test_fatal_doesnt_call_handler) + +START_TEST( test_fatal_doesnt_call_handler ) { - bucket_init(); + bucket_init(); - pid_t kidpid; + pid_t kidpid; - kidpid = fork(); - if (kidpid == 0) { - trigger_fatal(); - } else { - int kidstatus; - int result = waitpid(kidpid, &kidstatus, 0); - fail_if(result < 0, "Wait failed"); - fail_if(handler_called(), "Handler was called."); - } + kidpid = fork(); + if ( kidpid == 0 ) { + trigger_fatal(); + } + else { + int kidstatus; + int result = waitpid( kidpid, &kidstatus, 0 ); + fail_if( result < 0, "Wait failed" ); + fail_if( handler_called(), "Handler was called."); + } } +END_TEST -END_TEST Suite * util_suite(void) + +Suite* util_suite(void) { - Suite *s = suite_create("util"); - TCase *tc_process = tcase_create("process"); - TCase *tc_handler = tcase_create("handler"); + Suite *s = suite_create("util"); + TCase *tc_process = tcase_create("process"); + TCase *tc_handler = tcase_create("handler"); - tcase_add_checked_fixture(tc_process, setup, NULL); + tcase_add_checked_fixture( tc_process, setup, NULL ); - tcase_add_test(tc_process, test_fatal_kills_process); - tcase_add_test(tc_process, test_error_doesnt_kill_process); - tcase_add_test(tc_handler, test_error_calls_handler); - tcase_add_test(tc_handler, test_fatal_doesnt_call_handler); + tcase_add_test(tc_process, test_fatal_kills_process); + tcase_add_test(tc_process, test_error_doesnt_kill_process); + tcase_add_test(tc_handler, test_error_calls_handler ); + tcase_add_test(tc_handler, test_fatal_doesnt_call_handler); - suite_add_tcase(s, tc_process); - suite_add_tcase(s, tc_handler); - - return s; + suite_add_tcase(s, tc_process); + suite_add_tcase(s, tc_handler); + + return s; } int main(void) { - int number_failed; - Suite *s = util_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; + int number_failed; + Suite *s = util_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; } + From 8893cd06c4b1e507c825d4f707049f9746cf4346 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 20 Feb 2018 11:02:33 +0000 Subject: [PATCH 69/71] Re-formatted tests with a bit of tinkering by hand --- tests/unit/check_acl.c | 261 ++++++++------- tests/unit/check_bitset.c | 614 +++++++++++++++++----------------- tests/unit/check_client.c | 121 ++++--- tests/unit/check_control.c | 40 ++- tests/unit/check_flexnbd.c | 49 ++- tests/unit/check_flexthread.c | 68 ++-- tests/unit/check_ioutil.c | 160 +++++---- tests/unit/check_mbox.c | 117 ++++--- tests/unit/check_nbdtypes.c | 326 +++++++++--------- tests/unit/check_parse.c | 45 ++- tests/unit/check_readwrite.c | 213 ++++++------ tests/unit/check_self_pipe.c | 295 ++++++++-------- tests/unit/check_serve.c | 330 +++++++++--------- tests/unit/check_sockutil.c | 133 ++++---- tests/unit/check_status.c | 428 +++++++++++------------- tests/unit/check_util.c | 185 +++++----- 16 files changed, 1676 insertions(+), 1709 deletions(-) diff --git a/tests/unit/check_acl.c b/tests/unit/check_acl.c index bb12f81..10a5047 100644 --- a/tests/unit/check_acl.c +++ b/tests/unit/check_acl.c @@ -4,226 +4,229 @@ #include "acl.h" #include "util.h" -START_TEST( test_null_acl ) +START_TEST(test_null_acl) { - struct acl *acl = acl_create( 0,NULL, 0 ); + struct acl *acl = acl_create(0, NULL, 0); - fail_if( NULL == acl, "No acl alloced." ); - fail_unless( 0 == acl->len, "Incorrect length" ); + fail_if(NULL == acl, "No acl alloced."); + fail_unless(0 == acl->len, "Incorrect length"); } END_TEST - -START_TEST( test_parses_single_line ) +START_TEST(test_parses_single_line) { - char *lines[] = {"127.0.0.1"}; - struct acl * acl = acl_create( 1, lines, 0 ); + char *lines[] = { "127.0.0.1" }; + struct acl *acl = acl_create(1, lines, 0); - fail_unless( 1 == acl->len, "Incorrect length." ); - fail_if( NULL == acl->entries, "No entries present." ); + fail_unless(1 == acl->len, "Incorrect length."); + fail_if(NULL == acl->entries, "No entries present."); } END_TEST -START_TEST( test_parses_multiple_lines ) +START_TEST(test_parses_multiple_lines) { - char *lines[] = {"127.0.0.1", "::1"}; - struct acl * acl = acl_create( 2, lines, 0 ); - union mysockaddr e0, e1; + char *lines[] = { "127.0.0.1", "::1" }; + struct acl *acl = acl_create(2, lines, 0); + union mysockaddr e0, e1; - parse_ip_to_sockaddr( &e0.generic, lines[0] ); - parse_ip_to_sockaddr( &e1.generic, lines[1] ); + parse_ip_to_sockaddr(&e0.generic, lines[0]); + parse_ip_to_sockaddr(&e1.generic, lines[1]); - fail_unless( acl->len == 2, "Multiple lines not parsed" ); + fail_unless(acl->len == 2, "Multiple lines not parsed"); - struct ip_and_mask *entry; - entry = &(*acl->entries)[0]; - fail_unless(entry->ip.family == e0.family, "entry 0 has wrong family!"); - entry = &(*acl->entries)[1]; - fail_unless(entry->ip.family == e1.family, "entry 1 has wrong family!"); + struct ip_and_mask *entry; + entry = &(*acl->entries)[0]; + fail_unless(entry->ip.family == e0.family, + "entry 0 has wrong family!"); + entry = &(*acl->entries)[1]; + fail_unless(entry->ip.family == e1.family, + "entry 1 has wrong family!"); } END_TEST -START_TEST( test_destroy_doesnt_crash ) +START_TEST(test_destroy_doesnt_crash) { - char *lines[] = {"127.0.0.1"}; - struct acl * acl = acl_create( 1, lines, 0 ); + char *lines[] = { "127.0.0.1" }; + struct acl *acl = acl_create(1, lines, 0); - acl_destroy( acl ); + acl_destroy(acl); } END_TEST - -START_TEST( test_includes_single_address ) +START_TEST(test_includes_single_address) { - char *lines[] = {"127.0.0.1"}; - struct acl * acl = acl_create( 1, lines, 0 ); - union mysockaddr x; + char *lines[] = { "127.0.0.1" }; + struct acl *acl = acl_create(1, lines, 0); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "127.0.0.1" ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.1"); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); } END_TEST -START_TEST( test_includes_single_address_when_netmask_specified_ipv4 ) +START_TEST(test_includes_single_address_when_netmask_specified_ipv4) { - char *lines[] = {"127.0.0.1/24"}; - struct acl * acl = acl_create( 1, lines, 0 ); - union mysockaddr x; + char *lines[] = { "127.0.0.1/24" }; + struct acl *acl = acl_create(1, lines, 0); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "127.0.0.0" ); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.0"); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); - parse_ip_to_sockaddr( &x.generic, "127.0.0.1" ); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.1"); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); - parse_ip_to_sockaddr( &x.generic, "127.0.0.255" ); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.255"); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); } END_TEST -START_TEST( test_includes_single_address_when_netmask_specified_ipv6 ) +START_TEST(test_includes_single_address_when_netmask_specified_ipv6) { - char *lines[] = {"fe80::/10"}; - struct acl * acl = acl_create( 1, lines, 0 ); - union mysockaddr x; + char *lines[] = { "fe80::/10" }; + struct acl *acl = acl_create(1, lines, 0); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "fe80::1" ); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + parse_ip_to_sockaddr(&x.generic, "fe80::1"); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); - parse_ip_to_sockaddr( &x.generic, "fe80::2" ); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + parse_ip_to_sockaddr(&x.generic, "fe80::2"); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); - parse_ip_to_sockaddr( &x.generic, "fe80:ffff:ffff::ffff" ); - fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" ); + parse_ip_to_sockaddr(&x.generic, "fe80:ffff:ffff::ffff"); + fail_unless(acl_includes(acl, &x), "Included address wasn't covered"); } END_TEST -START_TEST( test_includes_single_address_when_multiple_entries_exist ) +START_TEST(test_includes_single_address_when_multiple_entries_exist) { - char *lines[] = {"127.0.0.1", "::1"}; - struct acl * acl = acl_create( 2, lines, 0 ); - union mysockaddr e0; - union mysockaddr e1; + char *lines[] = { "127.0.0.1", "::1" }; + struct acl *acl = acl_create(2, lines, 0); + union mysockaddr e0; + union mysockaddr e1; - parse_ip_to_sockaddr( &e0.generic, "127.0.0.1" ); - parse_ip_to_sockaddr( &e1.generic, "::1" ); + parse_ip_to_sockaddr(&e0.generic, "127.0.0.1"); + parse_ip_to_sockaddr(&e1.generic, "::1"); - fail_unless( acl_includes( acl, &e0 ), "Included address 0 wasn't covered" ); - fail_unless( acl_includes( acl, &e1 ), "Included address 1 wasn't covered" ); + fail_unless(acl_includes(acl, &e0), + "Included address 0 wasn't covered"); + fail_unless(acl_includes(acl, &e1), + "Included address 1 wasn't covered"); } END_TEST - -START_TEST( test_doesnt_include_other_address ) +START_TEST(test_doesnt_include_other_address) { - char *lines[] = {"127.0.0.1"}; - struct acl * acl = acl_create( 1, lines, 0 ); - union mysockaddr x; + char *lines[] = { "127.0.0.1" }; + struct acl *acl = acl_create(1, lines, 0); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "127.0.0.2" ); - fail_if( acl_includes( acl, &x ), "Excluded address was covered." ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.2"); + fail_if(acl_includes(acl, &x), "Excluded address was covered."); } END_TEST -START_TEST( test_doesnt_include_other_address_when_netmask_specified ) +START_TEST(test_doesnt_include_other_address_when_netmask_specified) { - char *lines[] = {"127.0.0.1/32"}; - struct acl * acl = acl_create( 1, lines, 0 ); - union mysockaddr x; + char *lines[] = { "127.0.0.1/32" }; + struct acl *acl = acl_create(1, lines, 0); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "127.0.0.2" ); - fail_if( acl_includes( acl, &x ), "Excluded address was covered." ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.2"); + fail_if(acl_includes(acl, &x), "Excluded address was covered."); } END_TEST -START_TEST( test_doesnt_include_other_address_when_multiple_entries_exist ) +START_TEST(test_doesnt_include_other_address_when_multiple_entries_exist) { - char *lines[] = {"127.0.0.1", "::1"}; - struct acl * acl = acl_create( 2, lines, 0 ); - union mysockaddr e0; - union mysockaddr e1; + char *lines[] = { "127.0.0.1", "::1" }; + struct acl *acl = acl_create(2, lines, 0); + union mysockaddr e0; + union mysockaddr e1; - parse_ip_to_sockaddr( &e0.generic, "127.0.0.2" ); - parse_ip_to_sockaddr( &e1.generic, "::2" ); + parse_ip_to_sockaddr(&e0.generic, "127.0.0.2"); + parse_ip_to_sockaddr(&e1.generic, "::2"); - fail_if( acl_includes( acl, &e0 ), "Excluded address 0 was covered." ); - fail_if( acl_includes( acl, &e1 ), "Excluded address 1 was covered." ); + fail_if(acl_includes(acl, &e0), "Excluded address 0 was covered."); + fail_if(acl_includes(acl, &e1), "Excluded address 1 was covered."); } END_TEST -START_TEST( test_default_deny_rejects ) +START_TEST(test_default_deny_rejects) { - struct acl * acl = acl_create( 0, NULL, 1 ); - union mysockaddr x; + struct acl *acl = acl_create(0, NULL, 1); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "127.0.0.1" ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.1"); - fail_if( acl_includes( acl, &x ), "Default deny accepted." ); + fail_if(acl_includes(acl, &x), "Default deny accepted."); } END_TEST - -START_TEST( test_default_accept_rejects ) +START_TEST(test_default_accept_rejects) { - struct acl * acl = acl_create( 0, NULL, 0 ); - union mysockaddr x; + struct acl *acl = acl_create(0, NULL, 0); + union mysockaddr x; - parse_ip_to_sockaddr( &x.generic, "127.0.0.1" ); + parse_ip_to_sockaddr(&x.generic, "127.0.0.1"); - fail_unless( acl_includes( acl, &x ), "Default accept rejected." ); + fail_unless(acl_includes(acl, &x), "Default accept rejected."); } END_TEST - -Suite* acl_suite(void) +Suite * acl_suite(void) { - Suite *s = suite_create("acl"); - TCase *tc_create = tcase_create("create"); - TCase *tc_includes = tcase_create("includes"); - TCase *tc_destroy = tcase_create("destroy"); + Suite *s = suite_create("acl"); + TCase *tc_create = tcase_create("create"); + TCase *tc_includes = tcase_create("includes"); + TCase *tc_destroy = tcase_create("destroy"); - tcase_add_test(tc_create, test_null_acl); - tcase_add_test(tc_create, test_parses_single_line); - tcase_add_test(tc_includes, test_parses_multiple_lines); + tcase_add_test(tc_create, test_null_acl); + tcase_add_test(tc_create, test_parses_single_line); + tcase_add_test(tc_includes, test_parses_multiple_lines); - tcase_add_test(tc_includes, test_includes_single_address); - tcase_add_test(tc_includes, test_includes_single_address_when_netmask_specified_ipv4); - tcase_add_test(tc_includes, test_includes_single_address_when_netmask_specified_ipv6); + tcase_add_test(tc_includes, test_includes_single_address); + tcase_add_test(tc_includes, + test_includes_single_address_when_netmask_specified_ipv4); + tcase_add_test(tc_includes, + test_includes_single_address_when_netmask_specified_ipv6); - tcase_add_test(tc_includes, test_includes_single_address_when_multiple_entries_exist); + tcase_add_test(tc_includes, + test_includes_single_address_when_multiple_entries_exist); - tcase_add_test(tc_includes, test_doesnt_include_other_address); - tcase_add_test(tc_includes, test_doesnt_include_other_address_when_netmask_specified); - tcase_add_test(tc_includes, test_doesnt_include_other_address_when_multiple_entries_exist); + tcase_add_test(tc_includes, test_doesnt_include_other_address); + tcase_add_test(tc_includes, + test_doesnt_include_other_address_when_netmask_specified); + tcase_add_test(tc_includes, + test_doesnt_include_other_address_when_multiple_entries_exist); - tcase_add_test(tc_includes, test_default_deny_rejects); - tcase_add_test(tc_includes, test_default_accept_rejects); + tcase_add_test(tc_includes, test_default_deny_rejects); + tcase_add_test(tc_includes, test_default_accept_rejects); - tcase_add_test(tc_destroy, test_destroy_doesnt_crash); + tcase_add_test(tc_destroy, test_destroy_doesnt_crash); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_includes); - suite_add_tcase(s, tc_destroy); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_includes); + suite_add_tcase(s, tc_destroy); - return s; + return s; } int main(void) { #ifdef DEBUG - log_level = 0; + log_level = 0; #else - log_level = 2; + log_level = 2; #endif - int number_failed; - Suite *s = acl_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - log_level = 0; - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? 0 : 1; + int number_failed; + Suite *s = acl_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + log_level = 0; + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; } - diff --git a/tests/unit/check_bitset.c b/tests/unit/check_bitset.c index 36b4e55..9bd40c8 100644 --- a/tests/unit/check_bitset.c +++ b/tests/unit/check_bitset.c @@ -9,492 +9,492 @@ START_TEST(test_bit_set) { - uint64_t num = 0; - bitfield_p bits = (bitfield_p) # + uint64_t num = 0; + bitfield_p bits = (bitfield_p) & num; #define TEST_BIT_SET(bit, newvalue) \ bit_set(bits, (bit)); \ fail_unless(num == (newvalue), "num was %x instead of %x", num, (newvalue)); - TEST_BIT_SET(0, 1); - TEST_BIT_SET(1, 3); - TEST_BIT_SET(2, 7); - TEST_BIT_SET(7, 0x87); - TEST_BIT_SET(63, 0x8000000000000087); + TEST_BIT_SET(0, 1); + TEST_BIT_SET(1, 3); + TEST_BIT_SET(2, 7); + TEST_BIT_SET(7, 0x87); + TEST_BIT_SET(63, 0x8000000000000087); } END_TEST START_TEST(test_bit_clear) { - uint64_t num = 0xffffffffffffffff; - bitfield_p bits = (bitfield_p) # + uint64_t num = 0xffffffffffffffff; + bitfield_p bits = (bitfield_p) & num; #define TEST_BIT_CLEAR(bit, newvalue) \ bit_clear(bits, (bit)); \ fail_unless(num == (newvalue), "num was %x instead of %x", num, (newvalue)); - TEST_BIT_CLEAR(0, 0xfffffffffffffffe); - TEST_BIT_CLEAR(1, 0xfffffffffffffffc); - TEST_BIT_CLEAR(2, 0xfffffffffffffff8); - TEST_BIT_CLEAR(7, 0xffffffffffffff78); - TEST_BIT_CLEAR(63,0x7fffffffffffff78); + TEST_BIT_CLEAR(0, 0xfffffffffffffffe); + TEST_BIT_CLEAR(1, 0xfffffffffffffffc); + TEST_BIT_CLEAR(2, 0xfffffffffffffff8); + TEST_BIT_CLEAR(7, 0xffffffffffffff78); + TEST_BIT_CLEAR(63, 0x7fffffffffffff78); } END_TEST START_TEST(test_bit_tests) { - uint64_t num = 0x5555555555555555; - bitfield_p bits = (bitfield_p) # + uint64_t num = 0x5555555555555555; + bitfield_p bits = (bitfield_p) & num; - fail_unless(bit_has_value(bits, 0, 1), "bit_has_value malfunction"); - fail_unless(bit_has_value(bits, 1, 0), "bit_has_value malfunction"); - fail_unless(bit_has_value(bits, 63, 0), "bit_has_value malfunction"); - fail_unless(bit_is_set(bits, 0), "bit_is_set malfunction"); - fail_unless(bit_is_clear(bits, 1), "bit_is_clear malfunction"); - fail_unless(bit_is_set(bits, 62), "bit_is_set malfunction"); - fail_unless(bit_is_clear(bits, 63), "bit_is_clear malfunction"); + fail_unless(bit_has_value(bits, 0, 1), "bit_has_value malfunction"); + fail_unless(bit_has_value(bits, 1, 0), "bit_has_value malfunction"); + fail_unless(bit_has_value(bits, 63, 0), "bit_has_value malfunction"); + fail_unless(bit_is_set(bits, 0), "bit_is_set malfunction"); + fail_unless(bit_is_clear(bits, 1), "bit_is_clear malfunction"); + fail_unless(bit_is_set(bits, 62), "bit_is_set malfunction"); + fail_unless(bit_is_clear(bits, 63), "bit_is_clear malfunction"); } END_TEST START_TEST(test_bit_ranges) { - bitfield_word_t buffer[BIT_WORDS_FOR_SIZE(4160)]; - uint64_t *longs = (uint64_t *) buffer; - uint64_t i; + bitfield_word_t buffer[BIT_WORDS_FOR_SIZE(4160)]; + uint64_t *longs = (uint64_t *) buffer; + uint64_t i; - memset(buffer, 0, 4160); + memset(buffer, 0, 4160); - for (i=0; i<64; i++) { - bit_set_range(buffer, i*64, i); - fail_unless( - longs[i] == (1ULL<bits; + map = bitset_alloc(6400, 100); + num = (uint64_t *) map->bits; - bitset_set_range(map,0,50); - ck_assert_int_eq(1, *num); - bitset_set_range(map,99,1); - ck_assert_int_eq(1, *num); - bitset_set_range(map,100,1); - ck_assert_int_eq(3, *num); - bitset_set_range(map,0,800); - ck_assert_int_eq(255, *num); - bitset_set_range(map,1499,2); - ck_assert_int_eq(0xc0ff, *num); - bitset_clear_range(map,1499,2); - ck_assert_int_eq(255, *num); + bitset_set_range(map, 0, 50); + ck_assert_int_eq(1, *num); + bitset_set_range(map, 99, 1); + ck_assert_int_eq(1, *num); + bitset_set_range(map, 100, 1); + ck_assert_int_eq(3, *num); + bitset_set_range(map, 0, 800); + ck_assert_int_eq(255, *num); + bitset_set_range(map, 1499, 2); + ck_assert_int_eq(0xc0ff, *num); + bitset_clear_range(map, 1499, 2); + ck_assert_int_eq(255, *num); - *num = 0; - bitset_set_range(map, 1499, 2); - bitset_clear_range(map, 1300, 200); - ck_assert_int_eq(0x8000, *num); + *num = 0; + bitset_set_range(map, 1499, 2); + bitset_clear_range(map, 1300, 200); + ck_assert_int_eq(0x8000, *num); - *num = 0; - bitset_set_range(map, 0, 6400); - ck_assert_int_eq(0xffffffffffffffff, *num); - bitset_clear_range(map, 3200, 400); - ck_assert_int_eq(0xfffffff0ffffffff, *num); + *num = 0; + bitset_set_range(map, 0, 6400); + ck_assert_int_eq(0xffffffffffffffff, *num); + bitset_clear_range(map, 3200, 400); + ck_assert_int_eq(0xfffffff0ffffffff, *num); } END_TEST - -START_TEST( test_bitset_set ) +START_TEST(test_bitset_set) { - struct bitset * map; - uint64_t run; + struct bitset *map; + uint64_t run; - map = bitset_alloc(64, 1); + map = bitset_alloc(64, 1); - assert_bitset_is( map, 0x0000000000000000 ); - bitset_set( map ); - assert_bitset_is( map, 0xffffffffffffffff ); - bitset_free( map ); + assert_bitset_is(map, 0x0000000000000000); + bitset_set(map); + assert_bitset_is(map, 0xffffffffffffffff); + bitset_free(map); - map = bitset_alloc( 6400, 100 ); - assert_bitset_is( map, 0x0000000000000000 ); - bitset_set( map ); - assert_bitset_is( map, 0xffffffffffffffff ); - bitset_free( map ); + map = bitset_alloc(6400, 100); + assert_bitset_is(map, 0x0000000000000000); + bitset_set(map); + assert_bitset_is(map, 0xffffffffffffffff); + bitset_free(map); - // Now do something large and representative - map = bitset_alloc( 53687091200, 4096 ); - bitset_set( map ); + // Now do something large and representative + map = bitset_alloc(53687091200, 4096); + bitset_set(map); - run = bitset_run_count( map, 0, 53687091200 ); - ck_assert_int_eq( run, 53687091200 ); - bitset_free( map ); + run = bitset_run_count(map, 0, 53687091200); + ck_assert_int_eq(run, 53687091200); + bitset_free(map); } END_TEST - -START_TEST( test_bitset_clear ) +START_TEST(test_bitset_clear) { - struct bitset * map; - uint64_t *num; - uint64_t run; + struct bitset *map; + uint64_t *num; + uint64_t run; - map = bitset_alloc(64, 1); - num = (uint64_t*) map->bits; + map = bitset_alloc(64, 1); + num = (uint64_t *) map->bits; - ck_assert_int_eq( 0x0000000000000000, *num ); - bitset_set( map ); - bitset_clear( map ); - ck_assert_int_eq( 0x0000000000000000, *num ); + ck_assert_int_eq(0x0000000000000000, *num); + bitset_set(map); + bitset_clear(map); + ck_assert_int_eq(0x0000000000000000, *num); - bitset_free( map ); + bitset_free(map); - // Now do something large and representative - map = bitset_alloc( 53687091200, 4096 ); - bitset_set( map ); - bitset_clear( map ); - run = bitset_run_count( map, 0, 53687091200 ); - ck_assert_int_eq( run, 53687091200 ); - bitset_free( map ); + // Now do something large and representative + map = bitset_alloc(53687091200, 4096); + bitset_set(map); + bitset_clear(map); + run = bitset_run_count(map, 0, 53687091200); + ck_assert_int_eq(run, 53687091200); + bitset_free(map); } END_TEST -START_TEST( test_bitset_set_range ) +START_TEST(test_bitset_set_range) { - struct bitset* map = bitset_alloc( 64, 1 ); - assert_bitset_is( map, 0x0000000000000000 ); + struct bitset *map = bitset_alloc(64, 1); + assert_bitset_is(map, 0x0000000000000000); - bitset_set_range( map, 8, 8 ); - assert_bitset_is( map, 0x000000000000ff00 ); + bitset_set_range(map, 8, 8); + assert_bitset_is(map, 0x000000000000ff00); - bitset_clear( map ); - assert_bitset_is( map, 0x0000000000000000 ); - bitset_set_range( map, 0, 0 ); - assert_bitset_is( map, 0x0000000000000000 ); + bitset_clear(map); + assert_bitset_is(map, 0x0000000000000000); + bitset_set_range(map, 0, 0); + assert_bitset_is(map, 0x0000000000000000); - bitset_free( map ); + bitset_free(map); } END_TEST -START_TEST( test_bitset_clear_range ) +START_TEST(test_bitset_clear_range) { - struct bitset* map = bitset_alloc( 64, 1 ); - bitset_set( map ); - assert_bitset_is( map, 0xffffffffffffffff ); + struct bitset *map = bitset_alloc(64, 1); + bitset_set(map); + assert_bitset_is(map, 0xffffffffffffffff); - bitset_clear_range( map, 8, 8 ); - assert_bitset_is( map, 0xffffffffffff00ff ); + bitset_clear_range(map, 8, 8); + assert_bitset_is(map, 0xffffffffffff00ff); - bitset_set( map ); - assert_bitset_is( map, 0xffffffffffffffff ); - bitset_clear_range( map, 0, 0 ); - assert_bitset_is( map, 0xffffffffffffffff ); + bitset_set(map); + assert_bitset_is(map, 0xffffffffffffffff); + bitset_clear_range(map, 0, 0); + assert_bitset_is(map, 0xffffffffffffffff); - bitset_free( map ); + bitset_free(map); } END_TEST -START_TEST( test_bitset_run_count ) +START_TEST(test_bitset_run_count) { - struct bitset* map = bitset_alloc( 64, 1 ); - uint64_t run; + struct bitset *map = bitset_alloc(64, 1); + uint64_t run; - assert_bitset_is( map, 0x0000000000000000 ); + assert_bitset_is(map, 0x0000000000000000); - run = bitset_run_count( map, 0, 64 ); - ck_assert_int_eq( 64, run ); + run = bitset_run_count(map, 0, 64); + ck_assert_int_eq(64, run); - bitset_set_range( map, 0, 32 ); - assert_bitset_is( map, 0x00000000ffffffff ); + bitset_set_range(map, 0, 32); + assert_bitset_is(map, 0x00000000ffffffff); - run = bitset_run_count( map, 0, 64 ); - ck_assert_int_eq( 32, run ); + run = bitset_run_count(map, 0, 64); + ck_assert_int_eq(32, run); - run = bitset_run_count( map, 0, 16 ); - ck_assert_int_eq( 16, run ); + run = bitset_run_count(map, 0, 16); + ck_assert_int_eq(16, run); - run = bitset_run_count( map, 16, 64 ); - ck_assert_int_eq( 16, run ); + run = bitset_run_count(map, 16, 64); + ck_assert_int_eq(16, run); - run = bitset_run_count( map, 31, 64 ); - ck_assert_int_eq( 1, run ); + run = bitset_run_count(map, 31, 64); + ck_assert_int_eq(1, run); - run = bitset_run_count( map, 32, 64 ); - ck_assert_int_eq( 32, run ); + run = bitset_run_count(map, 32, 64); + ck_assert_int_eq(32, run); - run = bitset_run_count( map, 32, 32 ); - ck_assert_int_eq( 32, run ); + run = bitset_run_count(map, 32, 32); + ck_assert_int_eq(32, run); - run = bitset_run_count( map, 32, 16 ); - ck_assert_int_eq( 16, run ); + run = bitset_run_count(map, 32, 16); + ck_assert_int_eq(16, run); - bitset_free( map ); + bitset_free(map); - map = bitset_alloc( 6400, 100 ); - assert_bitset_is( map, 0x0000000000000000 ); + map = bitset_alloc(6400, 100); + assert_bitset_is(map, 0x0000000000000000); - run = bitset_run_count( map, 0, 6400 ); - ck_assert_int_eq( 6400, run ); + run = bitset_run_count(map, 0, 6400); + ck_assert_int_eq(6400, run); - bitset_set_range( map, 0, 3200 ); + bitset_set_range(map, 0, 3200); - run = bitset_run_count( map, 0, 6400 ); - ck_assert_int_eq( 3200, run ); + run = bitset_run_count(map, 0, 6400); + ck_assert_int_eq(3200, run); - run = bitset_run_count( map, 1, 6400 ); - ck_assert_int_eq( 3199, run ); + run = bitset_run_count(map, 1, 6400); + ck_assert_int_eq(3199, run); - run = bitset_run_count( map, 3200, 6400 ); - ck_assert_int_eq( 3200, run ); + run = bitset_run_count(map, 3200, 6400); + ck_assert_int_eq(3200, run); - run = bitset_run_count( map, 6500, 6400 ); - ck_assert_int_eq( 0, run ); - bitset_free( map ); + run = bitset_run_count(map, 6500, 6400); + ck_assert_int_eq(0, run); + bitset_free(map); - // Now do something large and representative - map = bitset_alloc( 53687091200, 4096 ); - bitset_set( map ); - run = bitset_run_count( map, 0, 53687091200 ); - ck_assert_int_eq( run, 53687091200 ); + // Now do something large and representative + map = bitset_alloc(53687091200, 4096); + bitset_set(map); + run = bitset_run_count(map, 0, 53687091200); + ck_assert_int_eq(run, 53687091200); - bitset_free( map ); + bitset_free(map); } END_TEST -START_TEST( test_bitset_set_range_doesnt_push_to_stream ) +START_TEST(test_bitset_set_range_doesnt_push_to_stream) { - struct bitset *map = bitset_alloc( 64, 1 ); - bitset_set_range( map, 0, 64 ); - ck_assert_int_eq( 0, bitset_stream_size( map ) ); - bitset_free( map ); + struct bitset *map = bitset_alloc(64, 1); + bitset_set_range(map, 0, 64); + ck_assert_int_eq(0, bitset_stream_size(map)); + bitset_free(map); } END_TEST -START_TEST( test_bitset_clear_range_doesnt_push_to_stream ) +START_TEST(test_bitset_clear_range_doesnt_push_to_stream) { - struct bitset *map = bitset_alloc( 64, 1 ); - bitset_clear_range( map, 0, 64 ); - ck_assert_int_eq( 0, bitset_stream_size( map ) ); - bitset_free( map ); + struct bitset *map = bitset_alloc(64, 1); + bitset_clear_range(map, 0, 64); + ck_assert_int_eq(0, bitset_stream_size(map)); + bitset_free(map); } END_TEST START_TEST(test_bitset_enable_stream) { - struct bitset *map = bitset_alloc( 64, 1 ); - struct bitset_stream_entry result; - memset( &result, 0, sizeof( result ) ); + struct bitset *map = bitset_alloc(64, 1); + struct bitset_stream_entry result; + memset(&result, 0, sizeof(result)); - bitset_enable_stream( map ); + bitset_enable_stream(map); - ck_assert_int_eq( 1, map->stream_enabled ); + ck_assert_int_eq(1, map->stream_enabled); - bitset_stream_dequeue( map, &result ); + bitset_stream_dequeue(map, &result); - ck_assert_int_eq( BITSET_STREAM_ON, result.event ); - ck_assert_int_eq( 0, result.from ); - ck_assert_int_eq( 64, result.len ); + ck_assert_int_eq(BITSET_STREAM_ON, result.event); + ck_assert_int_eq(0, result.from); + ck_assert_int_eq(64, result.len); - bitset_free( map ); + bitset_free(map); } END_TEST START_TEST(test_bitset_disable_stream) { - struct bitset *map = bitset_alloc( 64, 1 ); - struct bitset_stream_entry result; - memset( &result, 0, sizeof( result ) ); + struct bitset *map = bitset_alloc(64, 1); + struct bitset_stream_entry result; + memset(&result, 0, sizeof(result)); - bitset_enable_stream( map ); - bitset_disable_stream( map ); + bitset_enable_stream(map); + bitset_disable_stream(map); - ck_assert_int_eq( 0, map->stream_enabled ); - ck_assert_int_eq( 2, bitset_stream_size( map ) ); + ck_assert_int_eq(0, map->stream_enabled); + ck_assert_int_eq(2, bitset_stream_size(map)); - bitset_stream_dequeue( map, NULL ); // ON - bitset_stream_dequeue( map, &result ); // OFF + bitset_stream_dequeue(map, NULL); // ON + bitset_stream_dequeue(map, &result); // OFF - ck_assert_int_eq( BITSET_STREAM_OFF, result.event ); - ck_assert_int_eq( 0, result.from ); - ck_assert_int_eq( 64, result.len ); + ck_assert_int_eq(BITSET_STREAM_OFF, result.event); + ck_assert_int_eq(0, result.from); + ck_assert_int_eq(64, result.len); - bitset_free( map ); + bitset_free(map); } END_TEST START_TEST(test_bitset_stream_with_set_range) { - struct bitset *map = bitset_alloc( 64, 1 ); - struct bitset_stream_entry result; - memset( &result, 0, sizeof( result ) ); + struct bitset *map = bitset_alloc(64, 1); + struct bitset_stream_entry result; + memset(&result, 0, sizeof(result)); - bitset_enable_stream( map ); - bitset_set_range( map, 0, 32 ); + bitset_enable_stream(map); + bitset_set_range(map, 0, 32); - ck_assert_int_eq( 2, bitset_stream_size( map ) ); + ck_assert_int_eq(2, bitset_stream_size(map)); - bitset_stream_dequeue( map, NULL ); // ON - bitset_stream_dequeue( map, &result ); // SET + bitset_stream_dequeue(map, NULL); // ON + bitset_stream_dequeue(map, &result); // SET - ck_assert_int_eq( BITSET_STREAM_SET, result.event ); - ck_assert_int_eq( 0, result.from ); - ck_assert_int_eq( 32, result.len ); + ck_assert_int_eq(BITSET_STREAM_SET, result.event); + ck_assert_int_eq(0, result.from); + ck_assert_int_eq(32, result.len); - bitset_free( map ); + bitset_free(map); } END_TEST START_TEST(test_bitset_stream_with_clear_range) { - struct bitset *map = bitset_alloc( 64, 1 ); - struct bitset_stream_entry result; - memset( &result, 0, sizeof( result ) ); + struct bitset *map = bitset_alloc(64, 1); + struct bitset_stream_entry result; + memset(&result, 0, sizeof(result)); - bitset_enable_stream( map ); - bitset_clear_range( map, 0, 32 ); - ck_assert_int_eq( 2, bitset_stream_size( map ) ); + bitset_enable_stream(map); + bitset_clear_range(map, 0, 32); + ck_assert_int_eq(2, bitset_stream_size(map)); - bitset_stream_dequeue( map, NULL ); // ON - bitset_stream_dequeue( map, &result ); // UNSET + bitset_stream_dequeue(map, NULL); // ON + bitset_stream_dequeue(map, &result); // UNSET - ck_assert_int_eq( BITSET_STREAM_UNSET, result.event ); - ck_assert_int_eq( 0, result.from ); - ck_assert_int_eq( 32, result.len ); + ck_assert_int_eq(BITSET_STREAM_UNSET, result.event); + ck_assert_int_eq(0, result.from); + ck_assert_int_eq(32, result.len); - bitset_free( map ); + bitset_free(map); } END_TEST START_TEST(test_bitset_stream_size) { - struct bitset *map = bitset_alloc( 64, 1 ); - bitset_enable_stream( map ); - bitset_set_range( map, 0, 32 ); - bitset_set_range( map, 16, 32 ); - bitset_set_range( map, 7, 16 ); + struct bitset *map = bitset_alloc(64, 1); + bitset_enable_stream(map); + bitset_set_range(map, 0, 32); + bitset_set_range(map, 16, 32); + bitset_set_range(map, 7, 16); - bitset_clear_range( map, 0, 32 ); - bitset_clear_range( map, 16, 32 ); - bitset_clear_range( map, 48, 16 ); - bitset_disable_stream( map ); + bitset_clear_range(map, 0, 32); + bitset_clear_range(map, 16, 32); + bitset_clear_range(map, 48, 16); + bitset_disable_stream(map); - ck_assert_int_eq( 8, bitset_stream_size( map ) ); + ck_assert_int_eq(8, bitset_stream_size(map)); - bitset_free( map ); + bitset_free(map); } END_TEST START_TEST(test_bitset_stream_queued_bytes) { - struct bitset *map = bitset_alloc( 64, 1 ); - bitset_enable_stream( map ); - bitset_set_range( map, 0, 32 ); - bitset_set_range( map, 16, 32 ); - bitset_set_range( map, 7, 16 ); + struct bitset *map = bitset_alloc(64, 1); + bitset_enable_stream(map); + bitset_set_range(map, 0, 32); + bitset_set_range(map, 16, 32); + bitset_set_range(map, 7, 16); - bitset_clear_range( map, 0, 32 ); - bitset_clear_range( map, 16, 32 ); - bitset_clear_range( map, 48, 16 ); - bitset_clear_range( map, 0, 2 ); - bitset_disable_stream( map ); + bitset_clear_range(map, 0, 32); + bitset_clear_range(map, 16, 32); + bitset_clear_range(map, 48, 16); + bitset_clear_range(map, 0, 2); + bitset_disable_stream(map); - ck_assert_int_eq( 64, bitset_stream_queued_bytes( map, BITSET_STREAM_ON ) ); - ck_assert_int_eq( 80, bitset_stream_queued_bytes( map, BITSET_STREAM_SET ) ); - ck_assert_int_eq( 82, bitset_stream_queued_bytes( map, BITSET_STREAM_UNSET ) ); - ck_assert_int_eq( 64, bitset_stream_queued_bytes( map, BITSET_STREAM_OFF ) ); - bitset_free( map ); + ck_assert_int_eq(64, + bitset_stream_queued_bytes(map, BITSET_STREAM_ON)); + ck_assert_int_eq(80, + bitset_stream_queued_bytes(map, BITSET_STREAM_SET)); + ck_assert_int_eq(82, + bitset_stream_queued_bytes(map, BITSET_STREAM_UNSET)); + ck_assert_int_eq(64, + bitset_stream_queued_bytes(map, BITSET_STREAM_OFF)); + bitset_free(map); } END_TEST -Suite* bitset_suite(void) +Suite * bitset_suite(void) { - Suite *s = suite_create("bitset"); + Suite *s = suite_create("bitset"); - TCase *tc_bit = tcase_create("bit"); - tcase_add_test(tc_bit, test_bit_set); - tcase_add_test(tc_bit, test_bit_clear); - tcase_add_test(tc_bit, test_bit_tests); - tcase_add_test(tc_bit, test_bit_ranges); - tcase_add_test(tc_bit, test_bit_runs); - suite_add_tcase(s, tc_bit); + TCase *tc_bit = tcase_create("bit"); + tcase_add_test(tc_bit, test_bit_set); + tcase_add_test(tc_bit, test_bit_clear); + tcase_add_test(tc_bit, test_bit_tests); + tcase_add_test(tc_bit, test_bit_ranges); + tcase_add_test(tc_bit, test_bit_runs); + suite_add_tcase(s, tc_bit); - TCase *tc_bitset = tcase_create("bitset"); - tcase_add_test(tc_bitset, test_bitset); - tcase_add_test(tc_bitset, test_bitset_set); - tcase_add_test(tc_bitset, test_bitset_clear); - tcase_add_test(tc_bitset, test_bitset_run_count); - tcase_add_test(tc_bitset, test_bitset_set_range); - tcase_add_test(tc_bitset, test_bitset_clear_range); - tcase_add_test(tc_bitset, test_bitset_set_range_doesnt_push_to_stream); - tcase_add_test(tc_bitset, test_bitset_clear_range_doesnt_push_to_stream); - suite_add_tcase(s, tc_bitset); + TCase *tc_bitset = tcase_create("bitset"); + tcase_add_test(tc_bitset, test_bitset); + tcase_add_test(tc_bitset, test_bitset_set); + tcase_add_test(tc_bitset, test_bitset_clear); + tcase_add_test(tc_bitset, test_bitset_run_count); + tcase_add_test(tc_bitset, test_bitset_set_range); + tcase_add_test(tc_bitset, test_bitset_clear_range); + tcase_add_test(tc_bitset, test_bitset_set_range_doesnt_push_to_stream); + tcase_add_test(tc_bitset, + test_bitset_clear_range_doesnt_push_to_stream); + suite_add_tcase(s, tc_bitset); - TCase *tc_bitset_stream = tcase_create("bitset_stream"); - tcase_add_test(tc_bitset_stream, test_bitset_enable_stream); - tcase_add_test(tc_bitset_stream, test_bitset_disable_stream); - tcase_add_test(tc_bitset_stream, test_bitset_stream_with_set_range); - tcase_add_test(tc_bitset_stream, test_bitset_stream_with_clear_range); - tcase_add_test(tc_bitset_stream, test_bitset_stream_size); - tcase_add_test(tc_bitset_stream, test_bitset_stream_queued_bytes); - suite_add_tcase(s, tc_bitset_stream); + TCase *tc_bitset_stream = tcase_create("bitset_stream"); + tcase_add_test(tc_bitset_stream, test_bitset_enable_stream); + tcase_add_test(tc_bitset_stream, test_bitset_disable_stream); + tcase_add_test(tc_bitset_stream, test_bitset_stream_with_set_range); + tcase_add_test(tc_bitset_stream, test_bitset_stream_with_clear_range); + tcase_add_test(tc_bitset_stream, test_bitset_stream_size); + tcase_add_test(tc_bitset_stream, test_bitset_stream_queued_bytes); + suite_add_tcase(s, tc_bitset_stream); - return s; + return s; } int main(void) { - int number_failed; - Suite *s = bitset_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; + int number_failed; + Suite *s = bitset_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; } - diff --git a/tests/unit/check_client.c b/tests/unit/check_client.c index 188db10..1c6ca0b 100644 --- a/tests/unit/check_client.c +++ b/tests/unit/check_client.c @@ -9,114 +9,109 @@ #include -struct server fake_server = {0}; +struct server fake_server = { 0 }; + #define FAKE_SERVER &fake_server #define FAKE_SOCKET (42) -START_TEST( test_assigns_socket ) +START_TEST(test_assigns_socket) { - struct client * c; + struct client *c; - c = client_create( FAKE_SERVER, FAKE_SOCKET ); + c = client_create(FAKE_SERVER, FAKE_SOCKET); - fail_unless( 42 == c->socket, "Socket wasn't assigned." ); + fail_unless(42 == c->socket, "Socket wasn't assigned."); } END_TEST - -START_TEST( test_assigns_server ) +START_TEST(test_assigns_server) { - struct client * c; - /* can't predict the storage size so we can't allocate one on - * the stack - */ - c = client_create( FAKE_SERVER, FAKE_SOCKET ); + struct client *c; + /* can't predict the storage size so we can't allocate one on + * the stack + */ + c = client_create(FAKE_SERVER, FAKE_SOCKET); - fail_unless( FAKE_SERVER == c->serve, "Serve wasn't assigned." ); + fail_unless(FAKE_SERVER == c->serve, "Serve wasn't assigned."); } END_TEST - -START_TEST( test_opens_stop_signal ) +START_TEST(test_opens_stop_signal) { - struct client *c = client_create( FAKE_SERVER, FAKE_SOCKET ); + struct client *c = client_create(FAKE_SERVER, FAKE_SOCKET); - client_signal_stop( c ); + client_signal_stop(c); - fail_unless( 1 == self_pipe_signal_clear( c->stop_signal ), - "No signal was sent." ); + fail_unless(1 == self_pipe_signal_clear(c->stop_signal), + "No signal was sent."); } END_TEST - int fd_is_closed(int); -START_TEST( test_closes_stop_signal ) +START_TEST(test_closes_stop_signal) { - struct client *c = client_create( FAKE_SERVER, FAKE_SOCKET ); - int read_fd = c->stop_signal->read_fd; - int write_fd = c->stop_signal->write_fd; + struct client *c = client_create(FAKE_SERVER, FAKE_SOCKET); + int read_fd = c->stop_signal->read_fd; + int write_fd = c->stop_signal->write_fd; - client_destroy( c ); + client_destroy(c); - fail_unless( fd_is_closed( read_fd ), "Stop signal wasn't destroyed." ); - fail_unless( fd_is_closed( write_fd ), "Stop signal wasn't destroyed." ); + fail_unless(fd_is_closed(read_fd), "Stop signal wasn't destroyed."); + fail_unless(fd_is_closed(write_fd), "Stop signal wasn't destroyed."); } END_TEST - -START_TEST( test_read_request_quits_on_stop_signal ) +START_TEST(test_read_request_quits_on_stop_signal) { - int fds[2]; - struct nbd_request nbdr; - pipe( fds ); - struct client *c = client_create( FAKE_SERVER, fds[0] ); - - client_signal_stop( c ); + int fds[2]; + struct nbd_request nbdr; + pipe(fds); + struct client *c = client_create(FAKE_SERVER, fds[0]); - int client_serve_request( struct client *); - fail_unless( 1 == client_serve_request( c ), "Didn't quit on stop." ); + client_signal_stop(c); - close( fds[0] ); - close( fds[1] ); + int client_serve_request(struct client *); + fail_unless(1 == client_serve_request(c), "Didn't quit on stop."); + + close(fds[0]); + close(fds[1]); } END_TEST - -Suite *client_suite(void) +Suite * client_suite(void) { - Suite *s = suite_create("client"); + Suite *s = suite_create("client"); - TCase *tc_create = tcase_create("create"); - TCase *tc_signal = tcase_create("signal"); - TCase *tc_destroy = tcase_create("destroy"); + TCase *tc_create = tcase_create("create"); + TCase *tc_signal = tcase_create("signal"); + TCase *tc_destroy = tcase_create("destroy"); - tcase_add_test(tc_create, test_assigns_socket); - tcase_add_test(tc_create, test_assigns_server); + tcase_add_test(tc_create, test_assigns_socket); + tcase_add_test(tc_create, test_assigns_server); - tcase_add_test(tc_signal, test_opens_stop_signal); - tcase_add_test(tc_signal, test_read_request_quits_on_stop_signal); + tcase_add_test(tc_signal, test_opens_stop_signal); + tcase_add_test(tc_signal, test_read_request_quits_on_stop_signal); - tcase_add_test( tc_destroy, test_closes_stop_signal ); + tcase_add_test(tc_destroy, test_closes_stop_signal); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_signal); - suite_add_tcase(s, tc_destroy); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_signal); + suite_add_tcase(s, tc_destroy); - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = client_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; -} + int number_failed; + Suite *s = client_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; +} diff --git a/tests/unit/check_control.c b/tests/unit/check_control.c index fbb2ec9..bcaf0a6 100644 --- a/tests/unit/check_control.c +++ b/tests/unit/check_control.c @@ -4,39 +4,37 @@ #include -START_TEST( test_assigns_sock_name ) +START_TEST(test_assigns_sock_name) { - struct flexnbd flexnbd = {0}; - char csn[] = "foobar"; + struct flexnbd flexnbd = { 0 }; + char csn[] = "foobar"; - struct control * control = control_create(&flexnbd, csn ); + struct control *control = control_create(&flexnbd, csn); - fail_unless( csn == control->socket_name, "Socket name not assigned" ); + fail_unless(csn == control->socket_name, "Socket name not assigned"); } END_TEST - -Suite *control_suite(void) +Suite * control_suite(void) { - Suite *s = suite_create("control"); + Suite *s = suite_create("control"); - TCase *tc_create = tcase_create("create"); + TCase *tc_create = tcase_create("create"); - tcase_add_test(tc_create, test_assigns_sock_name); - suite_add_tcase( s, tc_create ); + tcase_add_test(tc_create, test_assigns_sock_name); + suite_add_tcase(s, tc_create); - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = control_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; -} + int number_failed; + Suite *s = control_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; +} diff --git a/tests/unit/check_flexnbd.c b/tests/unit/check_flexnbd.c index bff82e4..53a40a9 100644 --- a/tests/unit/check_flexnbd.c +++ b/tests/unit/check_flexnbd.c @@ -3,42 +3,39 @@ #include -START_TEST( test_listening_assigns_sock ) +START_TEST(test_listening_assigns_sock) { - struct flexnbd * flexnbd = flexnbd_create_listening( - "127.0.0.1", - "4777", - "fakefile", - "fakesock", - 0, - 0, - NULL ); - fail_if( NULL == flexnbd->control->socket_name, "No socket was copied" ); + struct flexnbd *flexnbd = flexnbd_create_listening("127.0.0.1", + "4777", + "fakefile", + "fakesock", + 0, + 0, + NULL); + fail_if(NULL == flexnbd->control->socket_name, "No socket was copied"); } END_TEST - -Suite *flexnbd_suite(void) +Suite * flexnbd_suite(void) { - Suite *s = suite_create("flexnbd"); + Suite *s = suite_create("flexnbd"); - TCase *tc_create = tcase_create("create"); + TCase *tc_create = tcase_create("create"); - tcase_add_test(tc_create, test_listening_assigns_sock); - suite_add_tcase( s, tc_create ); + tcase_add_test(tc_create, test_listening_assigns_sock); + suite_add_tcase(s, tc_create); - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = flexnbd_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; -} + int number_failed; + Suite *s = flexnbd_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; +} diff --git a/tests/unit/check_flexthread.c b/tests/unit/check_flexthread.c index 092ab5b..b3201e1 100644 --- a/tests/unit/check_flexthread.c +++ b/tests/unit/check_flexthread.c @@ -4,59 +4,59 @@ #include -START_TEST( test_mutex_create ) +START_TEST(test_mutex_create) { - struct flexthread_mutex * ftm = flexthread_mutex_create(); - NULLCHECK( ftm ); - flexthread_mutex_destroy( ftm ); + struct flexthread_mutex *ftm = flexthread_mutex_create(); + NULLCHECK(ftm); + flexthread_mutex_destroy(ftm); } END_TEST - -START_TEST( test_mutex_lock ) +START_TEST(test_mutex_lock) { - struct flexthread_mutex * ftm = flexthread_mutex_create(); + struct flexthread_mutex *ftm = flexthread_mutex_create(); - fail_if( flexthread_mutex_held( ftm ), "Flexthread_mutex is held before lock" ); - flexthread_mutex_lock( ftm ); - fail_unless( flexthread_mutex_held( ftm ), "Flexthread_mutex is not held inside lock" ); - flexthread_mutex_unlock( ftm ); - fail_if( flexthread_mutex_held( ftm ), "Flexthread_mutex is held after unlock" ); + fail_if(flexthread_mutex_held(ftm), + "Flexthread_mutex is held before lock"); + flexthread_mutex_lock(ftm); + fail_unless(flexthread_mutex_held(ftm), + "Flexthread_mutex is not held inside lock"); + flexthread_mutex_unlock(ftm); + fail_if(flexthread_mutex_held(ftm), + "Flexthread_mutex is held after unlock"); - flexthread_mutex_destroy( ftm ); + flexthread_mutex_destroy(ftm); } END_TEST - -Suite* flexthread_suite(void) +Suite * flexthread_suite(void) { - Suite *s = suite_create("flexthread"); - TCase *tc_create = tcase_create("create"); - TCase *tc_destroy = tcase_create("destroy"); + Suite *s = suite_create("flexthread"); + TCase *tc_create = tcase_create("create"); + TCase *tc_destroy = tcase_create("destroy"); - tcase_add_test( tc_create, test_mutex_create ); - tcase_add_test( tc_create, test_mutex_lock ); + tcase_add_test(tc_create, test_mutex_create); + tcase_add_test(tc_create, test_mutex_lock); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_destroy); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_destroy); - return s; + return s; } int main(void) { #ifdef DEBUG - log_level = 0; + log_level = 0; #else - log_level = 2; + log_level = 2; #endif - int number_failed; - Suite *s = flexthread_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - log_level = 0; - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? 0 : 1; + int number_failed; + Suite *s = flexthread_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + log_level = 0; + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; } - diff --git a/tests/unit/check_ioutil.c b/tests/unit/check_ioutil.c index b1f26a5..23f121b 100644 --- a/tests/unit/check_ioutil.c +++ b/tests/unit/check_ioutil.c @@ -2,133 +2,131 @@ #include -START_TEST( test_read_until_newline_returns_line_length_plus_null ) +START_TEST(test_read_until_newline_returns_line_length_plus_null) { - int fds[2]; - int nread; - char buf[5] = {0}; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = { 0 }; + pipe(fds); - write( fds[1], "1234\n", 5 ); - - nread = read_until_newline( fds[0], buf, 5 ); + write(fds[1], "1234\n", 5); - ck_assert_int_eq( 5, nread ); + nread = read_until_newline(fds[0], buf, 5); + + ck_assert_int_eq(5, nread); } END_TEST - -START_TEST( test_read_until_newline_inserts_null ) +START_TEST(test_read_until_newline_inserts_null) { - int fds[2]; - int nread; - char buf[5] = {0}; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = { 0 }; + pipe(fds); - write( fds[1], "1234\n", 5 ); - - nread = read_until_newline( fds[0], buf, 5 ); + write(fds[1], "1234\n", 5); - ck_assert_int_eq( '\0', buf[4] ); + nread = read_until_newline(fds[0], buf, 5); + + ck_assert_int_eq('\0', buf[4]); } END_TEST - -START_TEST( test_read_empty_line_inserts_null ) +START_TEST(test_read_empty_line_inserts_null) { - int fds[2]; - int nread; - char buf[5] = {0}; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = { 0 }; + pipe(fds); - write( fds[1], "\n", 1 ); - nread = read_until_newline( fds[0], buf, 1 ); + write(fds[1], "\n", 1); + nread = read_until_newline(fds[0], buf, 1); - ck_assert_int_eq( '\0', buf[0] ); - ck_assert_int_eq( 1, nread ); + ck_assert_int_eq('\0', buf[0]); + ck_assert_int_eq(1, nread); } END_TEST - -START_TEST( test_read_eof_returns_err ) +START_TEST(test_read_eof_returns_err) { - int fds[2]; - int nread; - char buf[5] = {0}; - pipe( fds ); + int fds[2]; + int nread; + char buf[5] = { 0 }; + pipe(fds); - close( fds[1] ); - nread = read_until_newline( fds[0], buf, 5 ); + close(fds[1]); + nread = read_until_newline(fds[0], buf, 5); - ck_assert_int_eq( -1, nread ); + ck_assert_int_eq(-1, nread); } END_TEST - -START_TEST( test_read_eof_fills_line ) +START_TEST(test_read_eof_fills_line) { - int fds[2]; - int nread; - char buf[5] = {0}; - pipe(fds); + int fds[2]; + int nread; + char buf[5] = { 0 }; + pipe(fds); - write( fds[1], "1234", 4 ); - close( fds[1] ); - nread = read_until_newline( fds[0], buf, 5 ); + write(fds[1], "1234", 4); + close(fds[1]); + nread = read_until_newline(fds[0], buf, 5); - ck_assert_int_eq( -1, nread ); - ck_assert_int_eq( '4', buf[3] ); + ck_assert_int_eq(-1, nread); + ck_assert_int_eq('4', buf[3]); } END_TEST - -START_TEST( test_read_lines_until_blankline ) +START_TEST(test_read_lines_until_blankline) { - char **lines = NULL; - int fds[2]; - int nlines; - pipe( fds ); + char **lines = NULL; + int fds[2]; + int nlines; + pipe(fds); - write( fds[1], "a\nb\nc\n\n", 7 ); + write(fds[1], "a\nb\nc\n\n", 7); - nlines = read_lines_until_blankline( fds[0], 256, &lines ); + nlines = read_lines_until_blankline(fds[0], 256, &lines); - ck_assert_int_eq( 3, nlines ); + ck_assert_int_eq(3, nlines); } END_TEST - -Suite *ioutil_suite(void) +Suite * ioutil_suite(void) { - Suite *s = suite_create("ioutil"); + Suite *s = suite_create("ioutil"); - TCase *tc_read_until_newline = tcase_create("read_until_newline"); - TCase *tc_read_lines_until_blankline = tcase_create("read_lines_until_blankline"); + TCase *tc_read_until_newline = tcase_create("read_until_newline"); + TCase *tc_read_lines_until_blankline = + tcase_create("read_lines_until_blankline"); - tcase_add_test(tc_read_until_newline, test_read_until_newline_returns_line_length_plus_null); - tcase_add_test(tc_read_until_newline, test_read_until_newline_inserts_null); - tcase_add_test(tc_read_until_newline, test_read_empty_line_inserts_null); - tcase_add_test(tc_read_until_newline, test_read_eof_returns_err); - tcase_add_test(tc_read_until_newline, test_read_eof_fills_line ); + tcase_add_test(tc_read_until_newline, + test_read_until_newline_returns_line_length_plus_null); + tcase_add_test(tc_read_until_newline, + test_read_until_newline_inserts_null); + tcase_add_test(tc_read_until_newline, + test_read_empty_line_inserts_null); + tcase_add_test(tc_read_until_newline, test_read_eof_returns_err); + tcase_add_test(tc_read_until_newline, test_read_eof_fills_line); - tcase_add_test(tc_read_lines_until_blankline, test_read_lines_until_blankline ); + tcase_add_test(tc_read_lines_until_blankline, + test_read_lines_until_blankline); - suite_add_tcase(s, tc_read_until_newline); - suite_add_tcase(s, tc_read_lines_until_blankline); + suite_add_tcase(s, tc_read_until_newline); + suite_add_tcase(s, tc_read_lines_until_blankline); - return s; + return s; } int main(void) { - int number_failed; - - Suite *s = ioutil_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; -} + int number_failed; + Suite *s = ioutil_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; +} diff --git a/tests/unit/check_mbox.c b/tests/unit/check_mbox.c index 5399531..e9dd638 100644 --- a/tests/unit/check_mbox.c +++ b/tests/unit/check_mbox.c @@ -4,83 +4,79 @@ #include #include -START_TEST( test_allocs_cvar ) +START_TEST(test_allocs_cvar) { - struct mbox * mbox = mbox_create(); - fail_if( NULL == mbox, "Nothing allocated" ); + struct mbox *mbox = mbox_create(); + fail_if(NULL == mbox, "Nothing allocated"); - pthread_cond_t cond_zero; - /* A freshly inited pthread_cond_t is set to {0} */ - memset( &cond_zero, 'X', sizeof( cond_zero ) ); - fail_if( memcmp( &cond_zero, &mbox->filled_cond, sizeof( cond_zero ) ) == 0 , - "Condition variable not allocated" ); - fail_if( memcmp( &cond_zero, &mbox->emptied_cond, sizeof( cond_zero ) ) == 0 , - "Condition variable not allocated" ); + pthread_cond_t cond_zero; + /* A freshly inited pthread_cond_t is set to {0} */ + memset(&cond_zero, 'X', sizeof(cond_zero)); + fail_if(memcmp(&cond_zero, &mbox->filled_cond, sizeof(cond_zero)) == 0, + "Condition variable not allocated"); + fail_if(memcmp(&cond_zero, &mbox->emptied_cond, sizeof(cond_zero)) == + 0, "Condition variable not allocated"); } END_TEST - -START_TEST( test_post_stores_value ) +START_TEST(test_post_stores_value) { - struct mbox * mbox = mbox_create(); - - void * deadbeef = (void *)0xDEADBEEF; - mbox_post( mbox, deadbeef ); + struct mbox *mbox = mbox_create(); - fail_unless( deadbeef == mbox_contents( mbox ), - "Contents were not posted" ); + void *deadbeef = (void *) 0xDEADBEEF; + mbox_post(mbox, deadbeef); + + fail_unless(deadbeef == mbox_contents(mbox), + "Contents were not posted"); } END_TEST - -void * mbox_receive_runner( void * mbox_uncast ) +void *mbox_receive_runner(void *mbox_uncast) { - struct mbox * mbox = (struct mbox *)mbox_uncast; - void * contents = NULL; + struct mbox *mbox = (struct mbox *) mbox_uncast; + void *contents = NULL; - contents = mbox_receive( mbox ); - return contents; + contents = mbox_receive(mbox); + return contents; } -START_TEST( test_receive_blocks_until_post ) +START_TEST(test_receive_blocks_until_post) { - struct mbox * mbox = mbox_create(); - pthread_t receiver; - pthread_create( &receiver, NULL, mbox_receive_runner, mbox ); - - void * deadbeef = (void *)0xDEADBEEF; - void * retval =NULL; - usleep(10000); - fail_unless( EBUSY == pthread_tryjoin_np( receiver, &retval ), - "Receiver thread wasn't blocked"); + struct mbox *mbox = mbox_create(); + pthread_t receiver; + pthread_create(&receiver, NULL, mbox_receive_runner, mbox); - mbox_post( mbox, deadbeef ); - fail_unless( 0 == pthread_join( receiver, &retval ), - "Failed to join the receiver thread" ); - fail_unless( retval == deadbeef, - "Return value was wrong" ); + void *deadbeef = (void *) 0xDEADBEEF; + void *retval = NULL; + usleep(10000); + fail_unless(EBUSY == pthread_tryjoin_np(receiver, &retval), + "Receiver thread wasn't blocked"); + + mbox_post(mbox, deadbeef); + fail_unless(0 == pthread_join(receiver, &retval), + "Failed to join the receiver thread"); + fail_unless(retval == deadbeef, "Return value was wrong"); } END_TEST - -Suite* mbox_suite(void) +Suite * mbox_suite(void) { - Suite *s = suite_create("mbox"); - TCase *tc_create = tcase_create("create"); - TCase *tc_post = tcase_create("post"); + Suite *s = suite_create("mbox"); + TCase *tc_create = tcase_create("create"); + TCase *tc_post = tcase_create("post"); - tcase_add_test(tc_create, test_allocs_cvar); + tcase_add_test(tc_create, test_allocs_cvar); - tcase_add_test( tc_post, test_post_stores_value ); - tcase_add_test( tc_post, test_receive_blocks_until_post); + tcase_add_test(tc_post, test_post_stores_value); + tcase_add_test(tc_post, test_receive_blocks_until_post); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_post); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_post); - return s; + return s; } @@ -88,17 +84,16 @@ Suite* mbox_suite(void) int main(void) { #ifdef DEBUG - log_level = 0; + log_level = 0; #else - log_level = 2; + log_level = 2; #endif - int number_failed; - Suite *s = mbox_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - log_level = 0; - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? 0 : 1; + int number_failed; + Suite *s = mbox_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + log_level = 0; + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; } - diff --git a/tests/unit/check_nbdtypes.c b/tests/unit/check_nbdtypes.c index 9124063..122fe55 100644 --- a/tests/unit/check_nbdtypes.c +++ b/tests/unit/check_nbdtypes.c @@ -4,257 +4,259 @@ START_TEST(test_init_passwd) { - struct nbd_init_raw init_raw; - struct nbd_init init; + struct nbd_init_raw init_raw; + struct nbd_init init; - memcpy( init_raw.passwd, INIT_PASSWD, 8 ); - - nbd_r2h_init( &init_raw, &init ); - memset( init_raw.passwd, 0, 8 ); - nbd_h2r_init( &init, &init_raw ); - - fail_unless( memcmp( init.passwd, INIT_PASSWD, 8 ) == 0, "The password was not copied." ); - fail_unless( memcmp( init_raw.passwd, INIT_PASSWD, 8 ) == 0, "The password was not copied back." ); + memcpy(init_raw.passwd, INIT_PASSWD, 8); + + nbd_r2h_init(&init_raw, &init); + memset(init_raw.passwd, 0, 8); + nbd_h2r_init(&init, &init_raw); + + fail_unless(memcmp(init.passwd, INIT_PASSWD, 8) == 0, + "The password was not copied."); + fail_unless(memcmp(init_raw.passwd, INIT_PASSWD, 8) == 0, + "The password was not copied back."); } END_TEST - START_TEST(test_init_magic) { - struct nbd_init_raw init_raw; - struct nbd_init init; + struct nbd_init_raw init_raw; + struct nbd_init init; - init_raw.magic = 12345; - nbd_r2h_init( &init_raw, &init ); - fail_unless( be64toh( 12345 ) == init.magic, "Magic was not converted." ); + init_raw.magic = 12345; + nbd_r2h_init(&init_raw, &init); + fail_unless(be64toh(12345) == init.magic, "Magic was not converted."); - init.magic = 67890; - nbd_h2r_init( &init, &init_raw ); - fail_unless( htobe64( 67890 ) == init_raw.magic, "Magic was not converted back." ); + init.magic = 67890; + nbd_h2r_init(&init, &init_raw); + fail_unless(htobe64(67890) == init_raw.magic, + "Magic was not converted back."); } END_TEST - START_TEST(test_init_size) { - struct nbd_init_raw init_raw; - struct nbd_init init; + struct nbd_init_raw init_raw; + struct nbd_init init; - init_raw.size = 12345; - nbd_r2h_init( &init_raw, &init ); - fail_unless( be64toh( 12345 ) == init.size, "Size was not converted." ); + init_raw.size = 12345; + nbd_r2h_init(&init_raw, &init); + fail_unless(be64toh(12345) == init.size, "Size was not converted."); - init.size = 67890; - nbd_h2r_init( &init, &init_raw ); - fail_unless( htobe64( 67890 ) == init_raw.size, "Size was not converted back." ); + init.size = 67890; + nbd_h2r_init(&init, &init_raw); + fail_unless(htobe64(67890) == init_raw.size, + "Size was not converted back."); } END_TEST - -START_TEST(test_request_magic ) +START_TEST(test_request_magic) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.magic = 12345; - nbd_r2h_request( &request_raw, &request ); - fail_unless( be32toh( 12345 ) == request.magic, "Magic was not converted." ); + request_raw.magic = 12345; + nbd_r2h_request(&request_raw, &request); + fail_unless(be32toh(12345) == request.magic, + "Magic was not converted."); - request.magic = 67890; - nbd_h2r_request( &request, &request_raw ); - fail_unless( htobe32( 67890 ) == request_raw.magic, "Magic was not converted back." ); + request.magic = 67890; + nbd_h2r_request(&request, &request_raw); + fail_unless(htobe32(67890) == request_raw.magic, + "Magic was not converted back."); } END_TEST START_TEST(test_request_type) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.type = 123; - nbd_r2h_request( &request_raw, &request ); - fail_unless( be16toh( 123 ) == request.type, "Type was not converted." ); + request_raw.type = 123; + nbd_r2h_request(&request_raw, &request); + fail_unless(be16toh(123) == request.type, "Type was not converted."); - request.type = 234; - nbd_h2r_request( &request, &request_raw ); - fail_unless( htobe16( 234 ) == request_raw.type, "Type was not converted back." ); + request.type = 234; + nbd_h2r_request(&request, &request_raw); + fail_unless(htobe16(234) == request_raw.type, + "Type was not converted back."); } END_TEST - - START_TEST(test_request_flags) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.flags = 123; - nbd_r2h_request( &request_raw, &request ); - fail_unless( be16toh( 123 ) == request.flags, "Flags were not converted." ); + request_raw.flags = 123; + nbd_r2h_request(&request_raw, &request); + fail_unless(be16toh(123) == request.flags, + "Flags were not converted."); - request.flags = 234; - nbd_h2r_request( &request, &request_raw ); - fail_unless( htobe16( 234 ) == request_raw.flags, "Flags were not converted back." ); + request.flags = 234; + nbd_h2r_request(&request, &request_raw); + fail_unless(htobe16(234) == request_raw.flags, + "Flags were not converted back."); } END_TEST - - START_TEST(test_request_handle) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - memcpy( request_raw.handle.b, "MYHANDLE", 8 ); - - nbd_r2h_request( &request_raw, &request ); - request_raw.handle.w = 0; - nbd_h2r_request( &request, &request_raw ); - - fail_unless( memcmp( request.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied." ); - fail_unless( memcmp( request_raw.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied back." ); + memcpy(request_raw.handle.b, "MYHANDLE", 8); + + nbd_r2h_request(&request_raw, &request); + request_raw.handle.w = 0; + nbd_h2r_request(&request, &request_raw); + + fail_unless(memcmp(request.handle.b, "MYHANDLE", 8) == 0, + "The handle was not copied."); + fail_unless(memcmp(request_raw.handle.b, "MYHANDLE", 8) == 0, + "The handle was not copied back."); } END_TEST - - -START_TEST(test_request_from ) +START_TEST(test_request_from) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.from = 12345; - nbd_r2h_request( &request_raw, &request ); - fail_unless( be64toh( 12345 ) == request.from, "From was not converted." ); + request_raw.from = 12345; + nbd_r2h_request(&request_raw, &request); + fail_unless(be64toh(12345) == request.from, "From was not converted."); - request.from = 67890; - nbd_h2r_request( &request, &request_raw ); - fail_unless( htobe64( 67890 ) == request_raw.from, "From was not converted back." ); + request.from = 67890; + nbd_h2r_request(&request, &request_raw); + fail_unless(htobe64(67890) == request_raw.from, + "From was not converted back."); } END_TEST - - -START_TEST(test_request_len ) +START_TEST(test_request_len) { - struct nbd_request_raw request_raw; - struct nbd_request request; + struct nbd_request_raw request_raw; + struct nbd_request request; - request_raw.len = 12345; - nbd_r2h_request( &request_raw, &request ); - fail_unless( be32toh( 12345 ) == request.len, "Type was not converted." ); + request_raw.len = 12345; + nbd_r2h_request(&request_raw, &request); + fail_unless(be32toh(12345) == request.len, "Type was not converted."); - request.len = 67890; - nbd_h2r_request( &request, &request_raw ); - fail_unless( htobe32( 67890 ) == request_raw.len, "Type was not converted back." ); + request.len = 67890; + nbd_h2r_request(&request, &request_raw); + fail_unless(htobe32(67890) == request_raw.len, + "Type was not converted back."); } END_TEST - -START_TEST(test_reply_magic ) +START_TEST(test_reply_magic) { - struct nbd_reply_raw reply_raw; - struct nbd_reply reply; + struct nbd_reply_raw reply_raw; + struct nbd_reply reply; - reply_raw.magic = 12345; - nbd_r2h_reply( &reply_raw, &reply ); - fail_unless( be32toh( 12345 ) == reply.magic, "Magic was not converted." ); + reply_raw.magic = 12345; + nbd_r2h_reply(&reply_raw, &reply); + fail_unless(be32toh(12345) == reply.magic, "Magic was not converted."); - reply.magic = 67890; - nbd_h2r_reply( &reply, &reply_raw ); - fail_unless( htobe32( 67890 ) == reply_raw.magic, "Magic was not converted back." ); + reply.magic = 67890; + nbd_h2r_reply(&reply, &reply_raw); + fail_unless(htobe32(67890) == reply_raw.magic, + "Magic was not converted back."); } END_TEST - -START_TEST(test_reply_error ) +START_TEST(test_reply_error) { - struct nbd_reply_raw reply_raw; - struct nbd_reply reply; + struct nbd_reply_raw reply_raw; + struct nbd_reply reply; - reply_raw.error = 12345; - nbd_r2h_reply( &reply_raw, &reply ); - fail_unless( be32toh( 12345 ) == reply.error, "Error was not converted." ); + reply_raw.error = 12345; + nbd_r2h_reply(&reply_raw, &reply); + fail_unless(be32toh(12345) == reply.error, "Error was not converted."); - reply.error = 67890; - nbd_h2r_reply( &reply, &reply_raw ); - fail_unless( htobe32( 67890 ) == reply_raw.error, "Error was not converted back." ); + reply.error = 67890; + nbd_h2r_reply(&reply, &reply_raw); + fail_unless(htobe32(67890) == reply_raw.error, + "Error was not converted back."); } END_TEST START_TEST(test_reply_handle) { - struct nbd_reply_raw reply_raw; - struct nbd_reply reply; + struct nbd_reply_raw reply_raw; + struct nbd_reply reply; - memcpy( reply_raw.handle.b, "MYHANDLE", 8 ); - - nbd_r2h_reply( &reply_raw, &reply ); - reply_raw.handle.w = 0; - nbd_h2r_reply( &reply, &reply_raw ); - - fail_unless( memcmp( reply.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied." ); - fail_unless( memcmp( reply_raw.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied back." ); + memcpy(reply_raw.handle.b, "MYHANDLE", 8); + + nbd_r2h_reply(&reply_raw, &reply); + reply_raw.handle.w = 0; + nbd_h2r_reply(&reply, &reply_raw); + + fail_unless(memcmp(reply.handle.b, "MYHANDLE", 8) == 0, + "The handle was not copied."); + fail_unless(memcmp(reply_raw.handle.b, "MYHANDLE", 8) == 0, + "The handle was not copied back."); } END_TEST - -START_TEST( test_convert_from ) +START_TEST(test_convert_from) { - /* Check that we can correctly pull numbers out of an - * nbd_request_raw */ - struct nbd_request_raw request_raw; - struct nbd_request request; + /* Check that we can correctly pull numbers out of an + * nbd_request_raw */ + struct nbd_request_raw request_raw; + struct nbd_request request; - uint64_t target = 0x8000000000000000; + uint64_t target = 0x8000000000000000; - /* this is stored big-endian */ - request_raw.from = htobe64(target); + /* this is stored big-endian */ + request_raw.from = htobe64(target); - /* We expect this to convert big-endian to the host format */ - nbd_r2h_request( &request_raw, &request ); + /* We expect this to convert big-endian to the host format */ + nbd_r2h_request(&request_raw, &request); - fail_unless( target == request.from, "from was wrong" ); -} + fail_unless(target == request.from, "from was wrong"); +} END_TEST -Suite *nbdtypes_suite(void) +Suite * nbdtypes_suite(void) { - Suite *s = suite_create( "nbdtypes" ); - TCase *tc_init = tcase_create( "nbd_init" ); - TCase *tc_request = tcase_create( "nbd_request" ); - TCase *tc_reply = tcase_create( "nbd_reply" ); + Suite *s = suite_create("nbdtypes"); + TCase *tc_init = tcase_create("nbd_init"); + TCase *tc_request = tcase_create("nbd_request"); + TCase *tc_reply = tcase_create("nbd_reply"); - tcase_add_test( tc_init, test_init_passwd ); - tcase_add_test( tc_init, test_init_magic ); - tcase_add_test( tc_init, test_init_size ); - tcase_add_test( tc_request, test_request_magic ); - tcase_add_test( tc_request, test_request_type ); - tcase_add_test( tc_request, test_request_handle ); - tcase_add_test( tc_request, test_request_from ); - tcase_add_test( tc_request, test_request_len ); - tcase_add_test( tc_request, test_convert_from ); - tcase_add_test( tc_reply, test_reply_magic ); - tcase_add_test( tc_reply, test_reply_error ); - tcase_add_test( tc_reply, test_reply_handle ); + tcase_add_test(tc_init, test_init_passwd); + tcase_add_test(tc_init, test_init_magic); + tcase_add_test(tc_init, test_init_size); + tcase_add_test(tc_request, test_request_magic); + tcase_add_test(tc_request, test_request_type); + tcase_add_test(tc_request, test_request_handle); + tcase_add_test(tc_request, test_request_from); + tcase_add_test(tc_request, test_request_len); + tcase_add_test(tc_request, test_convert_from); + tcase_add_test(tc_reply, test_reply_magic); + tcase_add_test(tc_reply, test_reply_error); + tcase_add_test(tc_reply, test_reply_handle); - suite_add_tcase( s, tc_init ); - suite_add_tcase( s, tc_request ); - suite_add_tcase( s, tc_reply ); + suite_add_tcase(s, tc_init); + suite_add_tcase(s, tc_request); + suite_add_tcase(s, tc_reply); - return s; + return s; } int main(void) { - int number_failed; - Suite *s = nbdtypes_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; + int number_failed; + Suite *s = nbdtypes_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; } - diff --git a/tests/unit/check_parse.c b/tests/unit/check_parse.c index b30ee6d..dab8886 100644 --- a/tests/unit/check_parse.c +++ b/tests/unit/check_parse.c @@ -3,45 +3,42 @@ #include -START_TEST( test_can_parse_ip_address_twice ) +START_TEST(test_can_parse_ip_address_twice) { - char ip_address[] = "127.0.0.1"; - struct sockaddr saddr; + char ip_address[] = "127.0.0.1"; + struct sockaddr saddr; - parse_ip_to_sockaddr( &saddr, ip_address ); - parse_ip_to_sockaddr( &saddr, ip_address ); + parse_ip_to_sockaddr(&saddr, ip_address); + parse_ip_to_sockaddr(&saddr, ip_address); } END_TEST - - -Suite* parse_suite(void) +Suite * parse_suite(void) { - Suite *s = suite_create("parse"); - TCase *tc_create = tcase_create("ip_to_sockaddr"); + Suite *s = suite_create("parse"); + TCase *tc_create = tcase_create("ip_to_sockaddr"); - tcase_add_test(tc_create, test_can_parse_ip_address_twice); + tcase_add_test(tc_create, test_can_parse_ip_address_twice); - suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_create); - return s; + return s; } #ifdef DEBUG -# define LOG_LEVEL 0 +#define LOG_LEVEL 0 #else -# define LOG_LEVEL 2 +#define LOG_LEVEL 2 #endif int main(void) { - log_level = LOG_LEVEL; - int number_failed; - Suite *s = parse_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; + log_level = LOG_LEVEL; + int number_failed; + Suite *s = parse_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; } - diff --git a/tests/unit/check_readwrite.c b/tests/unit/check_readwrite.c index c158d7b..cae6e6e 100644 --- a/tests/unit/check_readwrite.c +++ b/tests/unit/check_readwrite.c @@ -21,173 +21,172 @@ -int fd_read_request( int, struct nbd_request_raw *); -int fd_write_reply( int, uint64_t, int ); +int fd_read_request(int, struct nbd_request_raw *); +int fd_write_reply(int, uint64_t, int); int marker; -void error_marker(void * unused __attribute__((unused)), - int fatal __attribute__((unused))) +void error_marker(void *unused __attribute__ ((unused)), + int fatal __attribute__ ((unused))) { - marker = 1; - return; + marker = 1; + return; } struct respond { - int sock_fds[2]; // server end - int do_fail; - pthread_t thread_id; - pthread_attr_t thread_attr; - struct nbd_request received; + int sock_fds[2]; // server end + int do_fail; + pthread_t thread_id; + pthread_attr_t thread_attr; + struct nbd_request received; }; -void * responder( void *respond_uncast ) +void *responder(void *respond_uncast) { - struct respond * resp = (struct respond *) respond_uncast; - int sock_fd = resp->sock_fds[1]; - struct nbd_request_raw request_raw; - uint64_t wrong_handle = 0x80; + struct respond *resp = (struct respond *) respond_uncast; + int sock_fd = resp->sock_fds[1]; + struct nbd_request_raw request_raw; + uint64_t wrong_handle = 0x80; - if( fd_read_request( sock_fd, &request_raw ) == -1){ - fprintf(stderr, "Problem with fd_read_request\n"); + if (fd_read_request(sock_fd, &request_raw) == -1) { + fprintf(stderr, "Problem with fd_read_request\n"); + } else { + nbd_r2h_request(&request_raw, &resp->received); + if (resp->do_fail) { + fd_write_reply(sock_fd, wrong_handle, 0); } else { - nbd_r2h_request( &request_raw, &resp->received); - if (resp->do_fail){ - fd_write_reply( sock_fd, wrong_handle, 0 ); - } - else { - fd_write_reply( sock_fd, resp->received.handle.w, 0 ); - } - write( sock_fd, "12345678", 8 ); + fd_write_reply(sock_fd, resp->received.handle.w, 0); } - return NULL; + write(sock_fd, "12345678", 8); + } + return NULL; } -struct respond * respond_create( int do_fail ) +struct respond *respond_create(int do_fail) { - struct respond * respond = (struct respond *)calloc( 1, sizeof( struct respond ) ); - socketpair( PF_UNIX, SOCK_STREAM, 0, respond->sock_fds ); - respond->do_fail = do_fail; + struct respond *respond = + (struct respond *) calloc(1, sizeof(struct respond)); + socketpair(PF_UNIX, SOCK_STREAM, 0, respond->sock_fds); + respond->do_fail = do_fail; - pthread_attr_init( &respond->thread_attr ); - pthread_create( &respond->thread_id, &respond->thread_attr, responder, respond ); + pthread_attr_init(&respond->thread_attr); + pthread_create(&respond->thread_id, &respond->thread_attr, responder, + respond); - return respond; + return respond; } -void respond_destroy( struct respond * respond ){ - NULLCHECK( respond ); - - pthread_join( respond->thread_id, NULL ); - pthread_attr_destroy( &respond->thread_attr ); - - close( respond->sock_fds[0] ); - close( respond->sock_fds[1] ); - free( respond ); -} - - -void * reader( void * nothing __attribute__((unused))) +void respond_destroy(struct respond *respond) { - DECLARE_ERROR_CONTEXT( error_context ); - error_set_handler( (cleanup_handler *)error_marker, error_context ); + NULLCHECK(respond); - struct respond * respond = respond_create( 1 ); - int devnull = open("/dev/null", O_WRONLY); - char outbuf[8] = {0}; + pthread_join(respond->thread_id, NULL); + pthread_attr_destroy(&respond->thread_attr); - socket_nbd_read( respond->sock_fds[0], 0, 8, devnull, outbuf, 1 ); - - return NULL; + close(respond->sock_fds[0]); + close(respond->sock_fds[1]); + free(respond); } -START_TEST( test_rejects_mismatched_handle ) + +void *reader(void *nothing __attribute__ ((unused))) +{ + DECLARE_ERROR_CONTEXT(error_context); + error_set_handler((cleanup_handler *) error_marker, error_context); + + struct respond *respond = respond_create(1); + int devnull = open("/dev/null", O_WRONLY); + char outbuf[8] = { 0 }; + + socket_nbd_read(respond->sock_fds[0], 0, 8, devnull, outbuf, 1); + + return NULL; +} + +START_TEST(test_rejects_mismatched_handle) { - error_init(); - pthread_t reader_thread; + error_init(); + pthread_t reader_thread; - log_level=5; - - marker = 0; - pthread_create( &reader_thread, NULL, reader, NULL ); - FATAL_UNLESS( 0 == pthread_join( reader_thread, NULL ), - "pthread_join failed"); - - log_level=2; + log_level = 5; - fail_unless( marker == 1, "Error handler wasn't called" ); + marker = 0; + pthread_create(&reader_thread, NULL, reader, NULL); + FATAL_UNLESS(0 == pthread_join(reader_thread, NULL), + "pthread_join failed"); + + log_level = 2; + + fail_unless(marker == 1, "Error handler wasn't called"); } END_TEST - -START_TEST( test_accepts_matched_handle ) +START_TEST(test_accepts_matched_handle) { - struct respond * respond = respond_create( 0 ); + struct respond *respond = respond_create(0); - int devnull = open("/dev/null", O_WRONLY); - char outbuf[8] = {0}; + int devnull = open("/dev/null", O_WRONLY); + char outbuf[8] = { 0 }; - socket_nbd_read( respond->sock_fds[0], 0, 8, devnull, outbuf, 1 ); + socket_nbd_read(respond->sock_fds[0], 0, 8, devnull, outbuf, 1); - respond_destroy( respond ); + respond_destroy(respond); } END_TEST - -START_TEST( test_disconnect_doesnt_read_reply ) +START_TEST(test_disconnect_doesnt_read_reply) { - struct respond * respond = respond_create( 1 ); + struct respond *respond = respond_create(1); - socket_nbd_disconnect( respond->sock_fds[0] ); + socket_nbd_disconnect(respond->sock_fds[0]); - respond_destroy( respond ); + respond_destroy(respond); } END_TEST - -Suite* readwrite_suite(void) +Suite * readwrite_suite(void) { - Suite *s = suite_create("readwrite"); - TCase *tc_transfer = tcase_create("entrust"); - TCase *tc_disconnect = tcase_create("disconnect"); + Suite *s = suite_create("readwrite"); + TCase *tc_transfer = tcase_create("entrust"); + TCase *tc_disconnect = tcase_create("disconnect"); - tcase_add_test(tc_transfer, test_rejects_mismatched_handle); - tcase_add_exit_test(tc_transfer, test_accepts_matched_handle, 0); + tcase_add_test(tc_transfer, test_rejects_mismatched_handle); + tcase_add_exit_test(tc_transfer, test_accepts_matched_handle, 0); - /* This test is a little funny. We respond with a dodgy handle - * and check that this *doesn't* cause a message rejection, - * because we want to know that the sender won't even try to - * read the response. - */ - tcase_add_exit_test( tc_disconnect, test_disconnect_doesnt_read_reply,0 ); + /* This test is a little funny. We respond with a dodgy handle + * and check that this *doesn't* cause a message rejection, + * because we want to know that the sender won't even try to + * read the response. + */ + tcase_add_exit_test(tc_disconnect, test_disconnect_doesnt_read_reply, + 0); - suite_add_tcase(s, tc_transfer); - suite_add_tcase(s, tc_disconnect); + suite_add_tcase(s, tc_transfer); + suite_add_tcase(s, tc_disconnect); - return s; + return s; } #ifdef DEBUG -# define LOG_LEVEL 0 +#define LOG_LEVEL 0 #else -# define LOG_LEVEL 2 +#define LOG_LEVEL 2 #endif int main(void) { - log_level = LOG_LEVEL; - int number_failed; - Suite *s = readwrite_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - log_level = 0; - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? 0 : 1; + log_level = LOG_LEVEL; + int number_failed; + Suite *s = readwrite_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + log_level = 0; + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; } - diff --git a/tests/unit/check_self_pipe.c b/tests/unit/check_self_pipe.c index c3026c9..6f4d082 100644 --- a/tests/unit/check_self_pipe.c +++ b/tests/unit/check_self_pipe.c @@ -9,190 +9,185 @@ #include "self_pipe.h" -START_TEST( test_opens_pipe ) +START_TEST(test_opens_pipe) { - struct self_pipe* sig; - char buf[] = " "; + struct self_pipe *sig; + char buf[] = " "; - sig = self_pipe_create(); + sig = self_pipe_create(); - write( sig->write_fd, "1", 1 ); - read( sig->read_fd, buf, 1 ); + write(sig->write_fd, "1", 1); + read(sig->read_fd, buf, 1); - fail_unless( buf[0] == '1', "Pipe does not seem to be open;" ); - self_pipe_destroy( sig ); + fail_unless(buf[0] == '1', "Pipe does not seem to be open;"); + self_pipe_destroy(sig); } END_TEST - -void * signal_thread( void * thing ) +void *signal_thread(void *thing) { - struct self_pipe *sig = (struct self_pipe *)thing; - usleep( 100000 ); - self_pipe_signal( sig ); - return NULL; + struct self_pipe *sig = (struct self_pipe *) thing; + usleep(100000); + self_pipe_signal(sig); + return NULL; } -pthread_t start_signal_thread( struct self_pipe *sig ) +pthread_t start_signal_thread(struct self_pipe * sig) { - pthread_attr_t attr; - pthread_t thread_id; + pthread_attr_t attr; + pthread_t thread_id; - pthread_attr_init( &attr ); - pthread_create( &thread_id, &attr, signal_thread, sig ); - pthread_attr_destroy( &attr ); + pthread_attr_init(&attr); + pthread_create(&thread_id, &attr, signal_thread, sig); + pthread_attr_destroy(&attr); - return thread_id; + return thread_id; } -START_TEST( test_signals ) +START_TEST(test_signals) { - struct self_pipe* sig; - fd_set fds; - pthread_t signal_thread_id; + struct self_pipe *sig; + fd_set fds; + pthread_t signal_thread_id; - sig = self_pipe_create(); + sig = self_pipe_create(); - FD_ZERO( &fds ); - self_pipe_fd_set( sig, &fds ); + FD_ZERO(&fds); + self_pipe_fd_set(sig, &fds); - signal_thread_id = start_signal_thread( sig ); - if ( select( FD_SETSIZE, &fds, NULL, NULL, NULL ) == -1 ) { - fail( strerror(errno) ); + signal_thread_id = start_signal_thread(sig); + if (select(FD_SETSIZE, &fds, NULL, NULL, NULL) == -1) { + fail(strerror(errno)); + } + self_pipe_signal_clear(sig); + + fail_unless(self_pipe_fd_isset(sig, &fds), + "Signalled pipe was not FD_ISSET."); + pthread_join(signal_thread_id, NULL); + + self_pipe_destroy(sig); +} +END_TEST + +START_TEST(test_clear_returns_immediately) +{ + struct self_pipe *sig; + sig = self_pipe_create(); + fail_unless(0 == self_pipe_signal_clear(sig), "Wrong clear result."); +} +END_TEST + +START_TEST(test_destroy_closes_read_pipe) +{ + struct self_pipe *sig; + ssize_t read_len; + int orig_read_fd; + + sig = self_pipe_create(); + orig_read_fd = sig->read_fd; + self_pipe_destroy(sig); + + while ((read_len = read(orig_read_fd, "", 0)) == -1 && errno == EINTR); + + switch (read_len) { + case 0: + fail("The read fd wasn't closed."); + break; + case -1: + switch (errno) { + case EBADF: + /* This is what we want */ + break; + case EAGAIN: + fail("The read fd wasn't closed."); + break; + default: + fail(strerror(errno)); + break; } - self_pipe_signal_clear( sig ); - - fail_unless( self_pipe_fd_isset( sig, &fds ), "Signalled pipe was not FD_ISSET." ); - pthread_join( signal_thread_id, NULL ); - - self_pipe_destroy( sig ); + break; + default: + fail("The read fd wasn't closed, and had data in it."); + break; + } } END_TEST - -START_TEST( test_clear_returns_immediately ) +START_TEST(test_destroy_closes_write_pipe) { - struct self_pipe *sig; - sig = self_pipe_create(); - fail_unless( 0 == self_pipe_signal_clear( sig ), "Wrong clear result." ); -} -END_TEST + struct self_pipe *sig; + ssize_t write_len; + int orig_write_fd; + sig = self_pipe_create(); + orig_write_fd = sig->write_fd; + self_pipe_destroy(sig); -START_TEST( test_destroy_closes_read_pipe ) -{ - struct self_pipe* sig; - ssize_t read_len; - int orig_read_fd; + while ((write_len = write(orig_write_fd, "", 0)) == -1 + && errno == EINTR); - sig = self_pipe_create(); - orig_read_fd = sig->read_fd; - self_pipe_destroy( sig ); - - while( (read_len = read( orig_read_fd, "", 0 )) == -1 && errno == EINTR ); - - switch( read_len ) { - case 0: - fail("The read fd wasn't closed." ); - break; - case -1: - switch(errno) { - case EBADF: - /* This is what we want */ - break; - case EAGAIN: - fail( "The read fd wasn't closed." ); - break; - default: - fail( strerror( errno ) ); - break; - } - break; - default: - fail( "The read fd wasn't closed, and had data in it." ); - break; + switch (write_len) { + case 0: + fail("The write fd wasn't closed."); + break; + case -1: + switch (errno) { + case EPIPE: + case EBADF: + /* This is what we want */ + break; + case EAGAIN: + fail("The write fd wasn't closed."); + break; + default: + fail(strerror(errno)); + break; } -} -END_TEST - - -START_TEST( test_destroy_closes_write_pipe ) -{ - struct self_pipe * sig; - ssize_t write_len; - int orig_write_fd; - - sig = self_pipe_create(); - orig_write_fd = sig->write_fd; - self_pipe_destroy( sig ); - - while ( ( write_len = write( orig_write_fd, "", 0 ) ) == -1 && errno == EINTR ); - - switch( write_len ) { - case 0: - fail( "The write fd wasn't closed." ); - break; - case -1: - switch( errno ) { - case EPIPE: - case EBADF: - /* This is what we want */ - break; - case EAGAIN: - fail("The write fd wasn't closed." ); - break; - default: - fail( strerror( errno ) ); - break; - } - break; - default: - /* To get here, the write(_,_,0) would have to - * write some bytes. - */ - fail( "The write fd wasn't closed, and something REALLY WEIRD is going on." ); - break; - } - -} -END_TEST - - - -Suite *self_pipe_suite(void) -{ - Suite *s = suite_create("self_pipe"); - - TCase *tc_create = tcase_create("create"); - TCase *tc_signal = tcase_create("signal"); - TCase *tc_destroy = tcase_create("destroy"); - - tcase_add_test(tc_create, test_opens_pipe); - tcase_add_test(tc_signal, test_signals ); - tcase_add_test(tc_signal, test_clear_returns_immediately ); - tcase_add_test(tc_destroy, test_destroy_closes_read_pipe ); - tcase_add_test(tc_destroy, test_destroy_closes_write_pipe ); - /* We don't test that destroy free()'s the self_pipe pointer because - * that'll be caught by valgrind. + break; + default: + /* To get here, the write(_,_,0) would have to + * write some bytes. */ + fail("The write fd wasn't closed, and something REALLY WEIRD is going on."); + break; + } - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_signal); - suite_add_tcase(s, tc_destroy); +} +END_TEST - return s; +Suite * self_pipe_suite(void) +{ + Suite *s = suite_create("self_pipe"); + + TCase *tc_create = tcase_create("create"); + TCase *tc_signal = tcase_create("signal"); + TCase *tc_destroy = tcase_create("destroy"); + + tcase_add_test(tc_create, test_opens_pipe); + tcase_add_test(tc_signal, test_signals); + tcase_add_test(tc_signal, test_clear_returns_immediately); + tcase_add_test(tc_destroy, test_destroy_closes_read_pipe); + tcase_add_test(tc_destroy, test_destroy_closes_write_pipe); + /* We don't test that destroy free()'s the self_pipe pointer because + * that'll be caught by valgrind. + */ + + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_signal); + suite_add_tcase(s, tc_destroy); + + return s; } int main(void) { - int number_failed; - - Suite *s = self_pipe_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; -} + int number_failed; + Suite *s = self_pipe_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; +} diff --git a/tests/unit/check_serve.c b/tests/unit/check_serve.c index b00bb1a..03538d1 100644 --- a/tests/unit/check_serve.c +++ b/tests/unit/check_serve.c @@ -15,9 +15,9 @@ #include #ifdef DEBUG -# define LOG_LEVEL 0 +#define LOG_LEVEL 0 #else -# define LOG_LEVEL 2 +#define LOG_LEVEL 2 #endif @@ -28,237 +28,249 @@ #define myfail_if( tst, msg ) do { if( tst ) { myfail( msg ); } } while (0) #define myfail_unless( tst, msg ) myfail_if( !(tst), msg ) -char * dummy_file; +char *dummy_file; char *make_tmpfile(void) { - FILE *fp; - char *fn_buf; - char leader[] = "/tmp/check_serve"; + FILE *fp; + char *fn_buf; + char leader[] = "/tmp/check_serve"; - fn_buf = (char *)malloc( 1024 ); - strncpy( fn_buf, leader, sizeof( leader ) - 1); - snprintf( &fn_buf[sizeof( leader ) - 1], 10, "%d", getpid() ); - fp = fopen( fn_buf, "w" ); - fwrite( fn_buf, 1024, 1, fp ); - fclose( fp ); + fn_buf = (char *) malloc(1024); + strncpy(fn_buf, leader, sizeof(leader) - 1); + snprintf(&fn_buf[sizeof(leader) - 1], 10, "%d", getpid()); + fp = fopen(fn_buf, "w"); + fwrite(fn_buf, 1024, 1, fp); + fclose(fp); - return fn_buf; + return fn_buf; } -void setup( void ) +void setup(void) { - dummy_file = make_tmpfile(); + dummy_file = make_tmpfile(); } -void teardown( void ) +void teardown(void) { - if( dummy_file ){ unlink( dummy_file ); } - free( dummy_file ); - dummy_file = NULL; + if (dummy_file) { + unlink(dummy_file); + } + free(dummy_file); + dummy_file = NULL; } -START_TEST( test_replaces_acl ) +START_TEST(test_replaces_acl) { - struct flexnbd flexnbd; - flexnbd.signal_fd = -1; - struct server * s = server_create( &flexnbd, "127.0.0.1", "0", dummy_file, 0, 0, NULL, 1, 0, 1 ); - struct acl * new_acl = acl_create( 0, NULL, 0 ); + struct flexnbd flexnbd; + flexnbd.signal_fd = -1; + struct server *s = + server_create(&flexnbd, "127.0.0.1", "0", dummy_file, 0, 0, NULL, + 1, 0, 1); + struct acl *new_acl = acl_create(0, NULL, 0); - server_replace_acl( s, new_acl ); + server_replace_acl(s, new_acl); - myfail_unless( s->acl == new_acl, "ACL wasn't replaced." ); - server_destroy( s ); + myfail_unless(s->acl == new_acl, "ACL wasn't replaced."); + server_destroy(s); } END_TEST - -START_TEST( test_signals_acl_updated ) +START_TEST(test_signals_acl_updated) { - struct flexnbd flexnbd; - flexnbd.signal_fd = -1; - struct server * s = server_create( &flexnbd, "127.0.0.1", "0", dummy_file, 0, 0, NULL, 1, 0, 1 ); - struct acl * new_acl = acl_create( 0, NULL, 0 ); + struct flexnbd flexnbd; + flexnbd.signal_fd = -1; + struct server *s = + server_create(&flexnbd, "127.0.0.1", "0", dummy_file, 0, 0, NULL, + 1, 0, 1); + struct acl *new_acl = acl_create(0, NULL, 0); - server_replace_acl( s, new_acl ); + server_replace_acl(s, new_acl); - myfail_unless( 1 == self_pipe_signal_clear( s->acl_updated_signal ), - "No signal sent." ); - server_destroy( s ); + myfail_unless(1 == self_pipe_signal_clear(s->acl_updated_signal), + "No signal sent."); + server_destroy(s); } END_TEST - -int connect_client( char *addr, int actual_port, char *source_addr ) +int connect_client(char *addr, int actual_port, char *source_addr) { - int client_fd = -1; + int client_fd = -1; - struct addrinfo hint; - struct addrinfo *ailist, *aip; + struct addrinfo hint; + struct addrinfo *ailist, *aip; - memset( &hint, '\0', sizeof( struct addrinfo ) ); - hint.ai_socktype = SOCK_STREAM; + memset(&hint, '\0', sizeof(struct addrinfo)); + hint.ai_socktype = SOCK_STREAM; - myfail_if( getaddrinfo( addr, NULL, &hint, &ailist ) != 0, "getaddrinfo failed." ); + myfail_if(getaddrinfo(addr, NULL, &hint, &ailist) != 0, + "getaddrinfo failed."); - int connected = 0; - for( aip = ailist; aip; aip = aip->ai_next ) { - ((struct sockaddr_in *)aip->ai_addr)->sin_port = htons( actual_port ); - client_fd = socket( aip->ai_family, aip->ai_socktype, aip->ai_protocol ); + int connected = 0; + for (aip = ailist; aip; aip = aip->ai_next) { + ((struct sockaddr_in *) aip->ai_addr)->sin_port = + htons(actual_port); + client_fd = + socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol); - if (source_addr) { - struct sockaddr src; - if( !parse_ip_to_sockaddr(&src, source_addr)) { - close(client_fd); - continue; - } - bind(client_fd, &src, sizeof(struct sockaddr_in6)); - } - - if( client_fd == -1) { continue; } - if( connect( client_fd, aip->ai_addr, aip->ai_addrlen) == 0 ) { - connected = 1; - break; - } - close( client_fd ); + if (source_addr) { + struct sockaddr src; + if (!parse_ip_to_sockaddr(&src, source_addr)) { + close(client_fd); + continue; + } + bind(client_fd, &src, sizeof(struct sockaddr_in6)); } - myfail_unless( connected, "Didn't connect." ); - return client_fd; + if (client_fd == -1) { + continue; + } + if (connect(client_fd, aip->ai_addr, aip->ai_addrlen) == 0) { + connected = 1; + break; + } + close(client_fd); + } + + myfail_unless(connected, "Didn't connect."); + return client_fd; } /* These are "internal" functions we need for the following test. We * shouldn't need them but there's no other way at the moment. */ -void serve_open_server_socket( struct server * ); -int server_port( struct server * ); -void server_accept( struct server * ); -int fd_is_closed( int ); -void server_close_clients( struct server * ); +void serve_open_server_socket(struct server *); +int server_port(struct server *); +void server_accept(struct server *); +int fd_is_closed(int); +void server_close_clients(struct server *); -START_TEST( test_acl_update_closes_bad_client ) +START_TEST(test_acl_update_closes_bad_client) { - /* This is the wrong way round. Rather than pulling the thread - * and socket out of the server structure, we should be testing - * a client socket. - */ - struct flexnbd flexnbd; - flexnbd.signal_fd = -1; - struct server * s = server_create( &flexnbd, "127.0.0.7", "0", dummy_file, 0, 0, NULL, 1, 0, 1 ); - struct acl * new_acl = acl_create( 0, NULL, 1 ); - struct client * c; - struct client_tbl_entry * entry; + /* This is the wrong way round. Rather than pulling the thread + * and socket out of the server structure, we should be testing + * a client socket. + */ + struct flexnbd flexnbd; + flexnbd.signal_fd = -1; + struct server *s = + server_create(&flexnbd, "127.0.0.7", "0", dummy_file, 0, 0, NULL, + 1, 0, 1); + struct acl *new_acl = acl_create(0, NULL, 1); + struct client *c; + struct client_tbl_entry *entry; - int actual_port; - int client_fd; - int server_fd; + int actual_port; + int client_fd; + int server_fd; - serve_open_server_socket( s ); - actual_port = server_port( s ); + serve_open_server_socket(s); + actual_port = server_port(s); - client_fd = connect_client( "127.0.0.7", actual_port, "127.0.0.1" ); - server_accept( s ); - entry = &s->nbd_client[0]; - c = entry->client; - /* At this point there should be an entry in the nbd_clients - * table and a background thread to run the client loop - */ - myfail_if( entry->thread == 0, "No client thread was started." ); - server_fd = c->socket; - myfail_if( fd_is_closed(server_fd), - "Sanity check failed - client socket wasn't open." ); + client_fd = connect_client("127.0.0.7", actual_port, "127.0.0.1"); + server_accept(s); + entry = &s->nbd_client[0]; + c = entry->client; + /* At this point there should be an entry in the nbd_clients + * table and a background thread to run the client loop + */ + myfail_if(entry->thread == 0, "No client thread was started."); + server_fd = c->socket; + myfail_if(fd_is_closed(server_fd), + "Sanity check failed - client socket wasn't open."); - server_replace_acl( s, new_acl ); + server_replace_acl(s, new_acl); - /* accept again, so that we can react to the acl replacement signal */ - server_accept( s ); + /* accept again, so that we can react to the acl replacement signal */ + server_accept(s); - /* Fail if we time out here */ - while( !fd_is_closed( server_fd ) ); + /* Fail if we time out here */ + while (!fd_is_closed(server_fd)); - close( client_fd ); - server_close_clients( s ); - server_destroy( s ); + close(client_fd); + server_close_clients(s); + server_destroy(s); } END_TEST - -START_TEST( test_acl_update_leaves_good_client ) +START_TEST(test_acl_update_leaves_good_client) { - struct flexnbd flexnbd; - flexnbd.signal_fd = -1; + struct flexnbd flexnbd; + flexnbd.signal_fd = -1; - struct server * s = server_create( &flexnbd, "127.0.0.7", "0", dummy_file, 0, 0, NULL, 1, 0, 1 ); + struct server *s = + server_create(&flexnbd, "127.0.0.7", "0", dummy_file, 0, 0, NULL, + 1, 0, 1); - char *lines[] = {"127.0.0.1"}; - struct acl * new_acl = acl_create( 1, lines, 1 ); - struct client * c; - struct client_tbl_entry * entry; + char *lines[] = { "127.0.0.1" }; + struct acl *new_acl = acl_create(1, lines, 1); + struct client *c; + struct client_tbl_entry *entry; - int actual_port; - int client_fd; - int server_fd; + int actual_port; + int client_fd; + int server_fd; - serve_open_server_socket( s ); - actual_port = server_port( s ); - client_fd = connect_client( "127.0.0.7", actual_port, "127.0.0.1" ); - server_accept( s ); - entry = &s->nbd_client[0]; - c = entry->client; - /* At this point there should be an entry in the nbd_clients - * table and a background thread to run the client loop - */ - myfail_if( entry->thread == 0, "No client thread was started." ); - server_fd = c->socket; - myfail_if( fd_is_closed(server_fd), - "Sanity check failed - client socket wasn't open." ); + serve_open_server_socket(s); + actual_port = server_port(s); + client_fd = connect_client("127.0.0.7", actual_port, "127.0.0.1"); + server_accept(s); + entry = &s->nbd_client[0]; + c = entry->client; + /* At this point there should be an entry in the nbd_clients + * table and a background thread to run the client loop + */ + myfail_if(entry->thread == 0, "No client thread was started."); + server_fd = c->socket; + myfail_if(fd_is_closed(server_fd), + "Sanity check failed - client socket wasn't open."); - server_replace_acl( s, new_acl ); - server_accept( s ); + server_replace_acl(s, new_acl); + server_accept(s); - myfail_if( self_pipe_signal_clear( c->stop_signal ), - "Client was told to stop." ); + myfail_if(self_pipe_signal_clear(c->stop_signal), + "Client was told to stop."); - close( client_fd ); - server_close_clients( s ); - server_destroy( s ); + close(client_fd); + server_close_clients(s); + server_destroy(s); } END_TEST - -Suite* serve_suite(void) +Suite * serve_suite(void) { - Suite *s = suite_create("serve"); - TCase *tc_acl_update = tcase_create("acl_update"); + Suite *s = suite_create("serve"); + TCase *tc_acl_update = tcase_create("acl_update"); - tcase_add_checked_fixture( tc_acl_update, setup, NULL ); + tcase_add_checked_fixture(tc_acl_update, setup, NULL); - tcase_add_test(tc_acl_update, test_replaces_acl); - tcase_add_test(tc_acl_update, test_signals_acl_updated); + tcase_add_test(tc_acl_update, test_replaces_acl); + tcase_add_test(tc_acl_update, test_signals_acl_updated); - tcase_add_exit_test(tc_acl_update, test_acl_update_closes_bad_client, 0); - tcase_add_exit_test(tc_acl_update, test_acl_update_leaves_good_client, 0); + tcase_add_exit_test(tc_acl_update, test_acl_update_closes_bad_client, + 0); + tcase_add_exit_test(tc_acl_update, test_acl_update_leaves_good_client, + 0); - suite_add_tcase(s, tc_acl_update); + suite_add_tcase(s, tc_acl_update); - return s; + return s; } int main(void) { - log_level = LOG_LEVEL; - error_init(); - 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; + log_level = LOG_LEVEL; + error_init(); + 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; } - diff --git a/tests/unit/check_sockutil.c b/tests/unit/check_sockutil.c index 57626bb..883d056 100644 --- a/tests/unit/check_sockutil.c +++ b/tests/unit/check_sockutil.c @@ -6,110 +6,113 @@ #include -START_TEST( test_sockaddr_address_string_af_inet_converts_to_string ) +START_TEST(test_sockaddr_address_string_af_inet_converts_to_string) { - struct sockaddr sa; - struct sockaddr_in* v4 = (struct sockaddr_in*) &sa; - char testbuf[128]; - const char* result; + struct sockaddr sa; + struct sockaddr_in *v4 = (struct sockaddr_in *) &sa; + char testbuf[128]; + const char *result; - v4->sin_family = AF_INET; - v4->sin_port = htons( 4777 ); - ck_assert_int_eq( 1, inet_pton( AF_INET, "192.168.0.1", &v4->sin_addr )); + v4->sin_family = AF_INET; + v4->sin_port = htons(4777); + ck_assert_int_eq(1, inet_pton(AF_INET, "192.168.0.1", &v4->sin_addr)); - result = sockaddr_address_string( &sa, &testbuf[0], 128 ); - ck_assert( result != NULL ); + result = sockaddr_address_string(&sa, &testbuf[0], 128); + ck_assert(result != NULL); - ck_assert_str_eq( "192.168.0.1 port 4777", testbuf ); + ck_assert_str_eq("192.168.0.1 port 4777", testbuf); } END_TEST - -START_TEST( test_sockaddr_address_string_af_inet6_converts_to_string ) +START_TEST(test_sockaddr_address_string_af_inet6_converts_to_string) { - struct sockaddr_in6 v6_raw; - struct sockaddr_in6* v6 = &v6_raw; - struct sockaddr* sa = (struct sockaddr*) &v6_raw; + struct sockaddr_in6 v6_raw; + struct sockaddr_in6 *v6 = &v6_raw; + struct sockaddr *sa = (struct sockaddr *) &v6_raw; - char testbuf[128]; - const char* result; + char testbuf[128]; + const char *result; - v6->sin6_family = AF_INET6; - v6->sin6_port = htons( 4777 ); - ck_assert_int_eq( 1, inet_pton( AF_INET6, "fe80::1", &v6->sin6_addr )); + v6->sin6_family = AF_INET6; + v6->sin6_port = htons(4777); + ck_assert_int_eq(1, inet_pton(AF_INET6, "fe80::1", &v6->sin6_addr)); - result = sockaddr_address_string( sa, &testbuf[0], 128 ); - ck_assert( result != NULL ); + result = sockaddr_address_string(sa, &testbuf[0], 128); + ck_assert(result != NULL); - ck_assert_str_eq( "fe80::1 port 4777", testbuf ); + ck_assert_str_eq("fe80::1 port 4777", testbuf); } END_TEST /* We don't know what it is, so we just call it "???" and return NULL */ -START_TEST( test_sockaddr_address_string_af_unspec_is_failure ) +START_TEST(test_sockaddr_address_string_af_unspec_is_failure) { - struct sockaddr sa; - struct sockaddr_in* v4 = (struct sockaddr_in*) &sa; - char testbuf[128]; - const char* result; + struct sockaddr sa; + struct sockaddr_in *v4 = (struct sockaddr_in *) &sa; + char testbuf[128]; + const char *result; - v4->sin_family = AF_UNSPEC; - v4->sin_port = htons( 4777 ); - ck_assert_int_eq( 1, inet_pton( AF_INET, "192.168.0.1", &v4->sin_addr )); + v4->sin_family = AF_UNSPEC; + v4->sin_port = htons(4777); + ck_assert_int_eq(1, inet_pton(AF_INET, "192.168.0.1", &v4->sin_addr)); - result = sockaddr_address_string( &sa, &testbuf[0], 128 ); - ck_assert( result == NULL ); + result = sockaddr_address_string(&sa, &testbuf[0], 128); + ck_assert(result == NULL); - ck_assert_str_eq( "???", testbuf ); + ck_assert_str_eq("???", testbuf); } END_TEST /* This is a complete failure to parse, rather than a partial failure */ -START_TEST( test_sockaddr_address_string_doesnt_overflow_short_buffer ) +START_TEST(test_sockaddr_address_string_doesnt_overflow_short_buffer) { - struct sockaddr sa; - struct sockaddr_in* v4 = (struct sockaddr_in*) &sa; - char testbuf[128]; - const char* result; + struct sockaddr sa; + struct sockaddr_in *v4 = (struct sockaddr_in *) &sa; + char testbuf[128]; + const char *result; - memset( testbuf, 0, 128 ); - v4->sin_family = AF_INET; - v4->sin_port = htons( 4777 ); - ck_assert_int_eq( 1, inet_pton( AF_INET, "192.168.0.1", &v4->sin_addr )); - memset( &testbuf, 0, 128 ); + memset(testbuf, 0, 128); + v4->sin_family = AF_INET; + v4->sin_port = htons(4777); + ck_assert_int_eq(1, inet_pton(AF_INET, "192.168.0.1", &v4->sin_addr)); + memset(&testbuf, 0, 128); - result = sockaddr_address_string( &sa, &testbuf[0], 2 ); - ck_assert( result == NULL ); + result = sockaddr_address_string(&sa, &testbuf[0], 2); + ck_assert(result == NULL); - ck_assert_str_eq( "??", testbuf ); + ck_assert_str_eq("??", testbuf); } END_TEST -Suite *sockutil_suite(void) +Suite * sockutil_suite(void) { - Suite *s = suite_create("sockutil"); + Suite *s = suite_create("sockutil"); - TCase *tc_sockaddr_address_string = tcase_create("sockaddr_address_string"); + TCase *tc_sockaddr_address_string = + tcase_create("sockaddr_address_string"); - tcase_add_test(tc_sockaddr_address_string, test_sockaddr_address_string_af_inet_converts_to_string); - tcase_add_test(tc_sockaddr_address_string, test_sockaddr_address_string_af_inet6_converts_to_string); - tcase_add_test(tc_sockaddr_address_string, test_sockaddr_address_string_af_unspec_is_failure); - tcase_add_test(tc_sockaddr_address_string, test_sockaddr_address_string_doesnt_overflow_short_buffer); - suite_add_tcase(s, tc_sockaddr_address_string); + tcase_add_test(tc_sockaddr_address_string, + test_sockaddr_address_string_af_inet_converts_to_string); + tcase_add_test(tc_sockaddr_address_string, + test_sockaddr_address_string_af_inet6_converts_to_string); + tcase_add_test(tc_sockaddr_address_string, + test_sockaddr_address_string_af_unspec_is_failure); + tcase_add_test(tc_sockaddr_address_string, + test_sockaddr_address_string_doesnt_overflow_short_buffer); + suite_add_tcase(s, tc_sockaddr_address_string); - return s; + return s; } int main(void) { - int number_failed; + int number_failed; - Suite *s = sockutil_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; + Suite *s = sockutil_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; } - diff --git a/tests/unit/check_status.c b/tests/unit/check_status.c index ea89d3b..570e8ac 100644 --- a/tests/unit/check_status.c +++ b/tests/unit/check_status.c @@ -6,366 +6,344 @@ #include -struct server* mock_server(void) +struct server *mock_server(void) { - struct server* out = xmalloc( sizeof( struct server ) ); - out->l_start_mirror = flexthread_mutex_create(); - out->nbd_client = xmalloc( sizeof( struct client_tbl_entry ) * 4 ); - out->max_nbd_clients = 4; - out->size = 65536; + struct server *out = xmalloc(sizeof(struct server)); + out->l_start_mirror = flexthread_mutex_create(); + out->nbd_client = xmalloc(sizeof(struct client_tbl_entry) * 4); + out->max_nbd_clients = 4; + out->size = 65536; - out->allocation_map = bitset_alloc( 65536, 4096 ); + out->allocation_map = bitset_alloc(65536, 4096); - return out; + return out; } -struct server* mock_mirroring_server(void) +struct server *mock_mirroring_server(void) { - struct server *out = mock_server(); - out->mirror = xmalloc( sizeof( struct mirror ) ); - out->mirror_super = xmalloc( sizeof( struct mirror_super ) ); - return out; + struct server *out = mock_server(); + out->mirror = xmalloc(sizeof(struct mirror)); + out->mirror_super = xmalloc(sizeof(struct mirror_super)); + return out; } -void destroy_mock_server( struct server* serve ) +void destroy_mock_server(struct server *serve) { - if ( NULL != serve->mirror ) { - free( serve->mirror ); - } + if (NULL != serve->mirror) { + free(serve->mirror); + } - if ( NULL != serve->mirror_super ) { - free( serve->mirror_super ); - } + if (NULL != serve->mirror_super) { + free(serve->mirror_super); + } - flexthread_mutex_destroy( serve->l_start_mirror ); + flexthread_mutex_destroy(serve->l_start_mirror); - bitset_free( serve->allocation_map ); - free( serve->nbd_client ); - free( serve ); + bitset_free(serve->allocation_map); + free(serve->nbd_client); + free(serve); } -START_TEST( test_status_create ) +START_TEST(test_status_create) { - struct server * server = mock_server(); - struct status * status = status_create( server ); + struct server *server = mock_server(); + struct status *status = status_create(server); - fail_if( NULL == status, "Status wasn't allocated" ); - status_destroy( status ); - destroy_mock_server( server ); + fail_if(NULL == status, "Status wasn't allocated"); + status_destroy(status); + destroy_mock_server(server); } END_TEST -START_TEST( test_gets_has_control ) +START_TEST(test_gets_has_control) { - struct server * server = mock_server(); - server->success = 1; + struct server *server = mock_server(); + server->success = 1; - struct status * status = status_create( server ); + struct status *status = status_create(server); - fail_unless( status->has_control == 1, "has_control wasn't copied" ); - status_destroy( status ); - destroy_mock_server( server ); + fail_unless(status->has_control == 1, "has_control wasn't copied"); + status_destroy(status); + destroy_mock_server(server); } END_TEST - -START_TEST( test_gets_is_mirroring ) +START_TEST(test_gets_is_mirroring) { - struct server * server = mock_server(); - struct status * status = status_create( server ); + struct server *server = mock_server(); + struct status *status = status_create(server); - fail_if( status->is_mirroring, "is_mirroring was set" ); - status_destroy( status ); - destroy_mock_server( server ); + fail_if(status->is_mirroring, "is_mirroring was set"); + status_destroy(status); + destroy_mock_server(server); - server = mock_mirroring_server(); - status = status_create( server ); + server = mock_mirroring_server(); + status = status_create(server); - fail_unless( status->is_mirroring, "is_mirroring wasn't set" ); - status_destroy( status ); - destroy_mock_server( server ); + fail_unless(status->is_mirroring, "is_mirroring wasn't set"); + status_destroy(status); + destroy_mock_server(server); } END_TEST -START_TEST( test_gets_clients_allowed ) +START_TEST(test_gets_clients_allowed) { - struct server * server = mock_server(); - struct status * status = status_create( server ); + struct server *server = mock_server(); + struct status *status = status_create(server); - fail_if( status->clients_allowed, "clients_allowed was set" ); - status_destroy( status ); + fail_if(status->clients_allowed, "clients_allowed was set"); + status_destroy(status); - server->allow_new_clients = 1; - status = status_create( server ); + server->allow_new_clients = 1; + status = status_create(server); - fail_unless( status->clients_allowed, "clients_allowed was not set" ); - status_destroy( status ); - destroy_mock_server( server ); + fail_unless(status->clients_allowed, "clients_allowed was not set"); + status_destroy(status); + destroy_mock_server(server); } END_TEST -START_TEST( test_gets_pid ) +START_TEST(test_gets_pid) { - struct server * server = mock_server(); - struct status * status = status_create( server ); + struct server *server = mock_server(); + struct status *status = status_create(server); - fail_unless( getpid() == status->pid, "Pid wasn't gathered" ); + fail_unless(getpid() == status->pid, "Pid wasn't gathered"); - status_destroy( status ); - destroy_mock_server( server ); + status_destroy(status); + destroy_mock_server(server); } END_TEST -START_TEST( test_gets_size ) +START_TEST(test_gets_size) { - struct server * server = mock_server(); - server->size = 1024; + struct server *server = mock_server(); + server->size = 1024; - struct status * status = status_create( server ); + struct status *status = status_create(server); - fail_unless( 1024 == status->size, "Size wasn't gathered" ); + fail_unless(1024 == status->size, "Size wasn't gathered"); - status_destroy( status ); - destroy_mock_server( server ); + status_destroy(status); + destroy_mock_server(server); } END_TEST -START_TEST( test_gets_migration_statistics ) +START_TEST(test_gets_migration_statistics) { - struct server * server = mock_mirroring_server(); - server->mirror->all_dirty = 16384; - server->mirror->max_bytes_per_second = 32768; - server->mirror->offset = 0; + struct server *server = mock_mirroring_server(); + server->mirror->all_dirty = 16384; + server->mirror->max_bytes_per_second = 32768; + server->mirror->offset = 0; - /* we have a bit of a time dependency here */ - server->mirror->migration_started = monotonic_time_ms(); + /* we have a bit of a time dependency here */ + server->mirror->migration_started = monotonic_time_ms(); - struct status * status = status_create( server ); + struct status *status = status_create(server); - fail_unless ( - 0 == status->migration_duration || + fail_unless(0 == status->migration_duration || 1 == status->migration_duration || 2 == status->migration_duration, - "migration_duration is unreasonable!" - ); + "migration_duration is unreasonable!"); - fail_unless( - 16384 / ( status->migration_duration + 1 ) == status->migration_speed, - "migration_speed not calculated correctly" - ); + fail_unless(16384 / (status->migration_duration + 1) == + status->migration_speed, + "migration_speed not calculated correctly"); - fail_unless( 32768 == status->migration_speed_limit, "migration_speed_limit not read" ); + fail_unless(32768 == status->migration_speed_limit, + "migration_speed_limit not read"); - // ( size / current_bps ) + 1 happens to be 3 for this test - fail_unless( 3 == status->migration_seconds_left, "migration_seconds_left not gathered" ); + // ( size / current_bps ) + 1 happens to be 3 for this test + fail_unless(3 == status->migration_seconds_left, + "migration_seconds_left not gathered"); - status_destroy( status ); - destroy_mock_server( server ); + status_destroy(status); + destroy_mock_server(server); } + END_TEST - - #define RENDER_TEST_SETUP \ struct status status; \ int fds[2]; \ pipe( fds ); - -void fail_unless_rendered( int fd, char *fragment ) +void fail_unless_rendered(int fd, char *fragment) { - char buf[1024] = {0}; - char emsg[1024] = {0}; - char *found = NULL; + char buf[1024] = { 0 }; + char emsg[1024] = { 0 }; + char *found = NULL; - sprintf(emsg, "Fragment: %s not found", fragment ); + sprintf(emsg, "Fragment: %s not found", fragment); - fail_unless( read_until_newline( fd, buf, 1024 ) > 0, "Couldn't read" ); - found = strstr( buf, fragment ); - fail_if( NULL == found, emsg ); + fail_unless(read_until_newline(fd, buf, 1024) > 0, "Couldn't read"); + found = strstr(buf, fragment); + fail_if(NULL == found, emsg); - return; + return; } -void fail_if_rendered( int fd, char *fragment ) +void fail_if_rendered(int fd, char *fragment) { - char buf[1024] = {0}; - char emsg[1024] = {0}; - char *found = NULL; + char buf[1024] = { 0 }; + char emsg[1024] = { 0 }; + char *found = NULL; - sprintf(emsg, "Fragment: %s found", fragment ); + sprintf(emsg, "Fragment: %s found", fragment); - fail_unless( read_until_newline( fd, buf, 1024 ) > 0, "Couldn't read" ); - found = strstr( buf, fragment ); - fail_unless( NULL == found, emsg ); + fail_unless(read_until_newline(fd, buf, 1024) > 0, "Couldn't read"); + found = strstr(buf, fragment); + fail_unless(NULL == found, emsg); - return; + return; } -START_TEST( test_renders_has_control ) +START_TEST(test_renders_has_control) { - RENDER_TEST_SETUP + RENDER_TEST_SETUP status.has_control = 1; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "has_control=true"); - status.has_control = 1; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "has_control=true" ); - - status.has_control = 0; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "has_control=false" ); + status.has_control = 0; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "has_control=false"); } END_TEST - -START_TEST( test_renders_is_mirroring ) +START_TEST(test_renders_is_mirroring) { - RENDER_TEST_SETUP + RENDER_TEST_SETUP status.is_mirroring = 1; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "is_mirroring=true"); - status.is_mirroring = 1; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "is_mirroring=true" ); - - status.is_mirroring = 0; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "is_mirroring=false" ); + status.is_mirroring = 0; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "is_mirroring=false"); } END_TEST -START_TEST( test_renders_clients_allowed ) +START_TEST(test_renders_clients_allowed) { - RENDER_TEST_SETUP + RENDER_TEST_SETUP status.clients_allowed = 1; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "clients_allowed=true"); - status.clients_allowed = 1; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "clients_allowed=true" ); - - status.clients_allowed = 0; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "clients_allowed=false" ); + status.clients_allowed = 0; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "clients_allowed=false"); } END_TEST -START_TEST( test_renders_num_clients ) +START_TEST(test_renders_num_clients) { - RENDER_TEST_SETUP + RENDER_TEST_SETUP status.num_clients = 0; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "num_clients=0"); - status.num_clients = 0; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "num_clients=0" ); - - status.num_clients = 4000; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "num_clients=4000" ); + status.num_clients = 4000; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "num_clients=4000"); } END_TEST - -START_TEST( test_renders_pid ) +START_TEST(test_renders_pid) { - RENDER_TEST_SETUP - - status.pid = 42; - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "pid=42" ); + RENDER_TEST_SETUP status.pid = 42; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "pid=42"); } END_TEST -START_TEST( test_renders_size ) +START_TEST(test_renders_size) { - RENDER_TEST_SETUP - - status.size = ( (uint64_t)1 << 33 ); - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "size=8589934592" ); + RENDER_TEST_SETUP status.size = ((uint64_t) 1 << 33); + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "size=8589934592"); } END_TEST -START_TEST( test_renders_migration_statistics ) +START_TEST(test_renders_migration_statistics) { - RENDER_TEST_SETUP + RENDER_TEST_SETUP status.is_mirroring = 0; + status.migration_duration = 8; + status.migration_speed = 40000000; + status.migration_speed_limit = 40000001; + status.migration_seconds_left = 1; + status.migration_bytes_left = 5000; - status.is_mirroring = 0; - status.migration_duration = 8; - status.migration_speed = 40000000; - status.migration_speed_limit = 40000001; - status.migration_seconds_left = 1; - status.migration_bytes_left = 5000; + status_write(&status, fds[1]); + fail_if_rendered(fds[0], "migration_duration"); - status_write( &status, fds[1] ); - fail_if_rendered( fds[0], "migration_duration" ); + status_write(&status, fds[1]); + fail_if_rendered(fds[0], "migration_speed"); - status_write( &status, fds[1] ); - fail_if_rendered( fds[0], "migration_speed" ); + status_write(&status, fds[1]); + fail_if_rendered(fds[0], "migration_speed_limit"); - status_write( &status, fds[1] ); - fail_if_rendered( fds[0], "migration_speed_limit" ); + status_write(&status, fds[1]); + fail_if_rendered(fds[0], "migration_seconds_left"); - status_write( &status, fds[1] ); - fail_if_rendered( fds[0], "migration_seconds_left" ); + status.is_mirroring = 1; - status.is_mirroring = 1; + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "migration_duration=8"); - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "migration_duration=8" ); + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "migration_speed=40000000"); - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "migration_speed=40000000" ); + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "migration_speed_limit=40000001"); - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "migration_speed_limit=40000001" ); + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "migration_seconds_left=1"); - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "migration_seconds_left=1" ); + status_write(&status, fds[1]); + fail_unless_rendered(fds[0], "migration_bytes_left=5000"); - status_write( &status, fds[1] ); - fail_unless_rendered( fds[0], "migration_bytes_left=5000" ); + status.migration_speed_limit = UINT64_MAX; - status.migration_speed_limit = UINT64_MAX; - - status_write( &status, fds[1] ); - fail_if_rendered( fds[0], "migration_speed_limit" ); + status_write(&status, fds[1]); + fail_if_rendered(fds[0], "migration_speed_limit"); } END_TEST - -Suite *status_suite(void) +Suite * status_suite(void) { - Suite *s = suite_create("status"); - TCase *tc_create = tcase_create("create"); - TCase *tc_render = tcase_create("render"); + Suite *s = suite_create("status"); + TCase *tc_create = tcase_create("create"); + TCase *tc_render = tcase_create("render"); - tcase_add_test(tc_create, test_status_create); - tcase_add_test(tc_create, test_gets_has_control); - tcase_add_test(tc_create, test_gets_is_mirroring); - tcase_add_test(tc_create, test_gets_clients_allowed); - tcase_add_test(tc_create, test_gets_pid); - tcase_add_test(tc_create, test_gets_size); - tcase_add_test(tc_create, test_gets_migration_statistics); + tcase_add_test(tc_create, test_status_create); + tcase_add_test(tc_create, test_gets_has_control); + tcase_add_test(tc_create, test_gets_is_mirroring); + tcase_add_test(tc_create, test_gets_clients_allowed); + tcase_add_test(tc_create, test_gets_pid); + tcase_add_test(tc_create, test_gets_size); + tcase_add_test(tc_create, test_gets_migration_statistics); - tcase_add_test(tc_render, test_renders_has_control); - tcase_add_test(tc_render, test_renders_is_mirroring); - tcase_add_test(tc_render, test_renders_clients_allowed); - tcase_add_test(tc_render, test_renders_num_clients); - tcase_add_test(tc_render, test_renders_pid); - tcase_add_test(tc_render, test_renders_size); - tcase_add_test(tc_render, test_renders_migration_statistics); + tcase_add_test(tc_render, test_renders_has_control); + tcase_add_test(tc_render, test_renders_is_mirroring); + tcase_add_test(tc_render, test_renders_clients_allowed); + tcase_add_test(tc_render, test_renders_num_clients); + tcase_add_test(tc_render, test_renders_pid); + tcase_add_test(tc_render, test_renders_size); + tcase_add_test(tc_render, test_renders_migration_statistics); - suite_add_tcase(s, tc_create); - suite_add_tcase(s, tc_render); + suite_add_tcase(s, tc_create); + suite_add_tcase(s, tc_render); - return s; + return s; } int main(void) { - int number_failed; + int number_failed; - Suite *s = status_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; + Suite *s = status_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; } - diff --git a/tests/unit/check_util.c b/tests/unit/check_util.c index 63e2ade..8f5de29 100644 --- a/tests/unit/check_util.c +++ b/tests/unit/check_util.c @@ -9,165 +9,160 @@ struct cleanup_bucket { - struct self_pipe *called_signal; + struct self_pipe *called_signal; }; struct cleanup_bucket bkt; -void bucket_init(void){ - if ( bkt.called_signal ) { - self_pipe_destroy( bkt.called_signal ); - } - bkt.called_signal = self_pipe_create(); +void bucket_init(void) +{ + if (bkt.called_signal) { + self_pipe_destroy(bkt.called_signal); + } + bkt.called_signal = self_pipe_create(); } void setup(void) { - bkt.called_signal = NULL; + bkt.called_signal = NULL; } int handler_called(void) { - return self_pipe_signal_clear( bkt.called_signal ); + return self_pipe_signal_clear(bkt.called_signal); } -void dummy_cleanup( struct cleanup_bucket * foo, int fatal __attribute__((unused)) ) +void dummy_cleanup(struct cleanup_bucket *foo, int fatal + __attribute__ ((unused))) { - if (NULL != foo){ - self_pipe_signal( foo->called_signal ); - } + if (NULL != foo) { + self_pipe_signal(foo->called_signal); + } } void trigger_fatal(void) -{ - error_init(); - error_set_handler( (cleanup_handler*) dummy_cleanup, &bkt ); +{ + error_init(); + error_set_handler((cleanup_handler *) dummy_cleanup, &bkt); - log_level = 5; + log_level = 5; - fatal("Expected fatal error"); + fatal("Expected fatal error"); } -void trigger_error( void ) +void trigger_error(void) { - error_init(); - error_set_handler( (cleanup_handler *) dummy_cleanup, &bkt); - log_level = 4; - error("Expected error"); + error_init(); + error_set_handler((cleanup_handler *) dummy_cleanup, &bkt); + log_level = 4; + error("Expected error"); } -START_TEST( test_fatal_kills_process ) +START_TEST(test_fatal_kills_process) { - pid_t pid; + pid_t pid; - pid = fork(); + pid = fork(); - if ( pid == 0 ) { - trigger_fatal(); - /* If we get here, just block so the test timeout fails - * us */ - sleep(10); - } - else { - int kidret, kidstatus, result; - result = waitpid( pid, &kidret, 0 ); - fail_if( result < 0, "Wait failed." ); - fail_unless( WIFSIGNALED( kidret ), "Process didn't exit via signal" ); - kidstatus = WTERMSIG( kidret ); - ck_assert_int_eq( kidstatus, SIGABRT ); - } + if (pid == 0) { + trigger_fatal(); + /* If we get here, just block so the test timeout fails + * us */ + sleep(10); + } else { + int kidret, kidstatus, result; + result = waitpid(pid, &kidret, 0); + fail_if(result < 0, "Wait failed."); + fail_unless(WIFSIGNALED(kidret), "Process didn't exit via signal"); + kidstatus = WTERMSIG(kidret); + ck_assert_int_eq(kidstatus, SIGABRT); + } } END_TEST - -void * error_thread( void *nothing __attribute__((unused)) ) +void *error_thread(void *nothing __attribute__ ((unused))) { - trigger_error(); - return NULL; + trigger_error(); + return NULL; } -START_TEST( test_error_doesnt_kill_process ) +START_TEST(test_error_doesnt_kill_process) { - bucket_init(); - pthread_attr_t attr; - pthread_t tid; + bucket_init(); + pthread_attr_t attr; + pthread_t tid; - pthread_attr_init( &attr ); + pthread_attr_init(&attr); - pthread_create( &tid, &attr, error_thread, NULL ); - pthread_join( tid, NULL ); + pthread_create(&tid, &attr, error_thread, NULL); + pthread_join(tid, NULL); } END_TEST - -START_TEST( test_error_calls_handler ) +START_TEST(test_error_calls_handler) { - bucket_init(); + bucket_init(); - pthread_attr_t attr; - pthread_t tid; + pthread_attr_t attr; + pthread_t tid; - pthread_attr_init( &attr ); + pthread_attr_init(&attr); - pthread_create( &tid, &attr, error_thread, NULL ); - pthread_join( tid, NULL ); - fail_unless( handler_called(), "Handler wasn't called." ); + pthread_create(&tid, &attr, error_thread, NULL); + pthread_join(tid, NULL); + fail_unless(handler_called(), "Handler wasn't called."); } END_TEST - -START_TEST( test_fatal_doesnt_call_handler ) +START_TEST(test_fatal_doesnt_call_handler) { - bucket_init(); + bucket_init(); - pid_t kidpid; + pid_t kidpid; - kidpid = fork(); - if ( kidpid == 0 ) { - trigger_fatal(); - } - else { - int kidstatus; - int result = waitpid( kidpid, &kidstatus, 0 ); - fail_if( result < 0, "Wait failed" ); - fail_if( handler_called(), "Handler was called."); - } + kidpid = fork(); + if (kidpid == 0) { + trigger_fatal(); + } else { + int kidstatus; + int result = waitpid(kidpid, &kidstatus, 0); + fail_if(result < 0, "Wait failed"); + fail_if(handler_called(), "Handler was called."); + } } END_TEST - -Suite* util_suite(void) +Suite *util_suite(void) { - Suite *s = suite_create("util"); - TCase *tc_process = tcase_create("process"); - TCase *tc_handler = tcase_create("handler"); + Suite *s = suite_create("util"); + TCase *tc_process = tcase_create("process"); + TCase *tc_handler = tcase_create("handler"); - tcase_add_checked_fixture( tc_process, setup, NULL ); + tcase_add_checked_fixture(tc_process, setup, NULL); - tcase_add_test(tc_process, test_fatal_kills_process); - tcase_add_test(tc_process, test_error_doesnt_kill_process); - tcase_add_test(tc_handler, test_error_calls_handler ); - tcase_add_test(tc_handler, test_fatal_doesnt_call_handler); + tcase_add_test(tc_process, test_fatal_kills_process); + tcase_add_test(tc_process, test_error_doesnt_kill_process); + tcase_add_test(tc_handler, test_error_calls_handler); + tcase_add_test(tc_handler, test_fatal_doesnt_call_handler); - suite_add_tcase(s, tc_process); - suite_add_tcase(s, tc_handler); - - return s; + suite_add_tcase(s, tc_process); + suite_add_tcase(s, tc_handler); + + return s; } int main(void) { - int number_failed; - Suite *s = util_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; + int number_failed; + Suite *s = util_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; } - From 9cbcc7c95aaa0fa5c5f9dc75878cfc5847e65b3d Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 20 Feb 2018 11:05:36 +0000 Subject: [PATCH 70/71] Added note about the test file formatting --- CONTRIBUTING.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f53854e..d52ffb0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,24 @@ # Contribution guide The code is formatted using the K&R style of "indent". + +``` +indent -kr +``` + +The C unit tests have also been indented in the same way, but manually adjsted +such that the functions follow the normal libcheck layout. + +```c +START_TEST( ... ) { + + +} +END TEST +``` + +Indent tends to mangle the `END_TEST` macro, so that will need adjusting if +`indent` is run over the test files again. + + + From 331ca4be1463bd46c54885970e2b839666ab6c35 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 20 Feb 2018 11:45:42 +0000 Subject: [PATCH 71/71] Updated changelog for release --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index cc9148a..3fa18d8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -flexnbd (0.2.0) UNRELEASED; urgency=medium +flexnbd (0.2.0) stable; urgency=medium [ James Carter ] * Set TCP keepalive on sockets so broken connections are reaped (#33, !33, @@ -24,7 +24,7 @@ flexnbd (0.2.0) UNRELEASED; urgency=medium * Clean up dead threads before calculating the number of connected clients on the status command (!46) - -- James Carter Thu, 11 Jan 2018 10:05:35 +0000 + -- Patrick J Cherry Tue, 20 Feb 2018 11:43:22 +0000 flexnbd (0.1.7) stable; urgency=medium