Whitespace

This commit is contained in:
nick
2012-09-20 13:37:48 +01:00
parent ddc57e76d1
commit ccbfce1075
5 changed files with 166 additions and 165 deletions

View File

@@ -61,13 +61,13 @@ void client_destroy( struct client *client )
* So waiting on client->socket is len bytes of data, and we must write it all * So waiting on client->socket is len bytes of data, and we must write it all
* to client->mapped. However while doing do we must consult the bitmap * to client->mapped. However while doing do we must consult the bitmap
* client->block_allocation_map, which is a bitmap where one bit represents * client->block_allocation_map, which is a bitmap where one bit represents
* block_allocation_resolution bytes. Where a bit isn't set, there are no * block_allocation_resolution bytes. Where a bit isn't set, there are no
* disc blocks allocated for that portion of the file, and we'd like to keep * disc blocks allocated for that portion of the file, and we'd like to keep
* it that way. * it that way.
* *
* If the bitmap shows that every block in our prospective write is already * If the bitmap shows that every block in our prospective write is already
* allocated, we can proceed as normal and make one call to writeloop. * allocated, we can proceed as normal and make one call to writeloop.
* *
*/ */
void write_not_zeroes(struct client* client, uint64_t from, int len) void write_not_zeroes(struct client* client, uint64_t from, int len)
{ {
@@ -83,30 +83,30 @@ void write_not_zeroes(struct client* client, uint64_t from, int len)
* how many blocks our write covers, then cut off the start * how many blocks our write covers, then cut off the start
* and end to get the exact number of bytes. * and end to get the exact number of bytes.
*/ */
int run = bitset_run_count(map, from, len); int 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) { if (run > len) {
run = len; run = len;
debug("(run adjusted to %d)", run); debug("(run adjusted to %d)", run);
} }
if (0) /* useful but expensive */ if (0) /* useful but expensive */
{ {
uint64_t i; uint64_t i;
fprintf(stderr, "full map resolution=%d: ", map->resolution); fprintf(stderr, "full map resolution=%d: ", map->resolution);
for (i=0; i<client->serve->size; i+=map->resolution) { for (i=0; i<client->serve->size; i+=map->resolution) {
int here = (from >= i && from < i+map->resolution); int here = (from >= i && from < i+map->resolution);
if (here) { fprintf(stderr, ">"); } if (here) { fprintf(stderr, ">"); }
fprintf(stderr, bitset_is_set_at(map, i) ? "1" : "0"); fprintf(stderr, bitset_is_set_at(map, i) ? "1" : "0");
if (here) { fprintf(stderr, "<"); } if (here) { fprintf(stderr, "<"); }
} }
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
#define DO_READ(dst, len) ERROR_IF_NEGATIVE( \ #define DO_READ(dst, len) ERROR_IF_NEGATIVE( \
readloop( \ readloop( \
client->socket, \ client->socket, \
@@ -115,7 +115,7 @@ void write_not_zeroes(struct client* client, uint64_t from, int len)
), \ ), \
"read failed %ld+%d", from, (len) \ "read failed %ld+%d", from, (len) \
) )
if (bitset_is_set_at(map, from)) { if (bitset_is_set_at(map, from)) {
debug("writing the lot: from=%ld, run=%d", from, run); debug("writing the lot: from=%ld, run=%d", from, run);
/* already allocated, just write it all */ /* already allocated, just write it all */
@@ -128,19 +128,19 @@ void write_not_zeroes(struct client* client, uint64_t from, int len)
char zerobuffer[block_allocation_resolution]; char zerobuffer[block_allocation_resolution];
/* not allocated, read in block_allocation_resoution */ /* not allocated, read in block_allocation_resoution */
while (run > 0) { while (run > 0) {
int blockrun = block_allocation_resolution - int blockrun = block_allocation_resolution -
(from % block_allocation_resolution); (from % block_allocation_resolution);
if (blockrun > run) if (blockrun > run)
blockrun = run; blockrun = run;
DO_READ(zerobuffer, blockrun); DO_READ(zerobuffer, blockrun);
/* This reads the buffer twice in the worst case /* This reads the buffer twice in the worst case
* but we're leaning on memcmp failing early * but we're leaning on memcmp failing early
* and memcpy being fast, rather than try to * and memcpy being fast, rather than try to
* hand-optimized something specific. * hand-optimized something specific.
*/ */
if (zerobuffer[0] != 0 || if (zerobuffer[0] != 0 ||
memcmp(zerobuffer, zerobuffer + 1, blockrun - 1)) { memcmp(zerobuffer, zerobuffer + 1, blockrun - 1)) {
memcpy(client->mapped+from, zerobuffer, blockrun); memcpy(client->mapped+from, zerobuffer, blockrun);
bitset_set_range(map, from, blockrun); bitset_set_range(map, from, blockrun);
@@ -148,7 +148,7 @@ void write_not_zeroes(struct client* client, uint64_t from, int len)
/* at this point we could choose to /* at this point we could choose to
* short-cut the rest of the write for * short-cut the rest of the write for
* faster I/O but by continuing to do it * faster I/O but by continuing to do it
* the slow way we preserve as much * the slow way we preserve as much
* sparseness as possible. * sparseness as possible.
*/ */
} }
@@ -185,18 +185,18 @@ int client_read_request( struct client * client , struct nbd_request *out_reques
* otherwise * otherwise
*/ */
ptv = server_is_in_control( client->serve ) ? NULL : &tv; ptv = server_is_in_control( client->serve ) ? NULL : &tv;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(client->socket, &fds); FD_SET(client->socket, &fds);
self_pipe_fd_set( client->stop_signal, &fds ); self_pipe_fd_set( client->stop_signal, &fds );
fd_count = select(FD_SETSIZE, &fds, NULL, NULL, ptv); fd_count = select(FD_SETSIZE, &fds, NULL, NULL, ptv);
if ( fd_count == 0 ) { if ( fd_count == 0 ) {
/* This "can't ever happen" */ /* This "can't ever happen" */
if ( NULL == ptv ) { fatal( "No FDs selected, and no timeout!" ); } if ( NULL == ptv ) { fatal( "No FDs selected, and no timeout!" ); }
else { error("Timed out waiting for I/O"); } else { error("Timed out waiting for I/O"); }
} }
else if ( fd_count < 0 ) { fatal( "Select failed" ); } else if ( fd_count < 0 ) { fatal( "Select failed" ); }
if ( self_pipe_fd_isset( client->stop_signal, &fds ) ){ if ( self_pipe_fd_isset( client->stop_signal, &fds ) ){
debug("Client received stop signal."); debug("Client received stop signal.");
return 0; return 0;
@@ -220,9 +220,9 @@ int client_read_request( struct client * client , struct nbd_request *out_reques
* again. It should *probably* be an * again. It should *probably* be an
* error() call, but I want to be sure. * error() call, but I want to be sure.
* */ * */
fatal("Error reading request: %d, %s", fatal("Error reading request: %d, %s",
errno, errno,
strerror( errno )); strerror( errno ));
} }
} }
@@ -299,7 +299,7 @@ void client_write_init( struct client * client, uint64_t size )
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); int devnull = open("/dev/null", O_WRONLY);
FATAL_IF_NEGATIVE( devnull, FATAL_IF_NEGATIVE( devnull,
"Couldn't open /dev/null: %s", strerror(errno)); "Couldn't open /dev/null: %s", strerror(errno));
int pipes[2]; int pipes[2];
pipe( pipes ); pipe( pipes );
@@ -308,9 +308,9 @@ void client_flush( struct client * client, size_t len )
size_t spliced = 0; size_t spliced = 0;
while ( spliced < len ) { while ( spliced < len ) {
ssize_t received = splice( ssize_t received = splice(
client->socket, NULL, client->socket, NULL,
pipes[1], NULL, pipes[1], NULL,
len-spliced, flags ); len-spliced, flags );
FATAL_IF_NEGATIVE( received, FATAL_IF_NEGATIVE( received,
"splice error: %s", "splice error: %s",
@@ -318,9 +318,9 @@ void client_flush( struct client * client, size_t len )
ssize_t junked = 0; ssize_t junked = 0;
while( junked < received ) { while( junked < received ) {
ssize_t junk; ssize_t junk;
junk = splice( junk = splice(
pipes[0], NULL, pipes[0], NULL,
devnull, NULL, devnull, NULL,
received, flags ); received, flags );
FATAL_IF_NEGATIVE( junk, FATAL_IF_NEGATIVE( junk,
"splice error: %s", "splice error: %s",
@@ -341,15 +341,15 @@ void client_flush( struct client * client, size_t len )
* request_err is set to 0 if the client sent a bad request, in which * request_err is set to 0 if the client sent a bad request, in which
* case we drop the connection. * case we drop the connection.
*/ */
int client_request_needs_reply( struct client * client, int client_request_needs_reply( struct client * client,
struct nbd_request request ) struct nbd_request request )
{ {
debug("request type %d", request.type); debug("request type %d", request.type);
if (request.magic != REQUEST_MAGIC) { if (request.magic != REQUEST_MAGIC) {
fatal("Bad magic %08x", request.magic); fatal("Bad magic %08x", request.magic);
} }
switch (request.type) switch (request.type)
{ {
case REQUEST_READ: case REQUEST_READ:
@@ -358,7 +358,7 @@ int client_request_needs_reply( struct client * client,
/* check it's not out of range */ /* check it's not out of range */
if ( request.from+request.len > client->serve->size) { if ( request.from+request.len > client->serve->size) {
warn("write request %d+%d out of range", warn("write request %d+%d out of range",
request.from, request.from,
request.len request.len
); );
client_write_reply( client, &request, 1 ); client_write_reply( client, &request, 1 );
@@ -367,12 +367,12 @@ int client_request_needs_reply( struct client * client,
return 0; return 0;
} }
break; break;
case REQUEST_DISCONNECT: case REQUEST_DISCONNECT:
debug("request disconnect"); debug("request disconnect");
client->disconnect = 1; client->disconnect = 1;
return 0; return 0;
default: default:
fatal("Unknown request %08x", request.type); fatal("Unknown request %08x", request.type);
} }
@@ -394,9 +394,9 @@ void client_reply_to_read( struct client* client, struct nbd_request request )
*/ */
ERROR_IF_NEGATIVE( ERROR_IF_NEGATIVE(
sendfileloop( sendfileloop(
client->socket, client->socket,
client->fileno, client->fileno,
&offset, &offset,
request.len), request.len),
"sendfile failed from=%ld, len=%d", "sendfile failed from=%ld, len=%d",
offset, offset,
@@ -420,7 +420,7 @@ void client_reply_to_write( struct client* client, struct nbd_request request )
request.len), request.len),
"reading write data failed from=%ld, len=%d", "reading write data failed from=%ld, len=%d",
request.from, request.from,
request.len request.len
); );
server_dirty(client->serve, request.from, request.len); server_dirty(client->serve, request.from, request.len);
} }
@@ -432,8 +432,8 @@ void client_reply_to_write( struct client* client, struct nbd_request request )
uint64_t len_rounded = request.len + (request.from - from_rounded); uint64_t len_rounded = request.len + (request.from - from_rounded);
FATAL_IF_NEGATIVE( FATAL_IF_NEGATIVE(
msync( client->mapped + from_rounded, msync( client->mapped + from_rounded,
len_rounded, len_rounded,
MS_SYNC), MS_SYNC),
"msync failed %ld %ld", request.from, request.len "msync failed %ld %ld", request.from, request.len
); );
@@ -466,7 +466,7 @@ int client_serve_request(struct client* client)
if ( disconnected ) { return stop; } if ( disconnected ) { return stop; }
if ( !client_request_needs_reply( client, request ) ) { if ( !client_request_needs_reply( client, request ) ) {
return client->disconnect; return client->disconnect;
} }
server_lock_io( client->serve ); server_lock_io( client->serve );
{ {
@@ -486,12 +486,12 @@ 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, void client_cleanup(struct client* client,
int fatal __attribute__ ((unused)) ) int fatal __attribute__ ((unused)) )
{ {
info("client cleanup for client %p", client); info("client cleanup for client %p", client);
if (client->socket) { if (client->socket) {
FATAL_IF_NEGATIVE( close(client->socket), FATAL_IF_NEGATIVE( close(client->socket),
"Error closing client socket %d", "Error closing client socket %d",
client->socket ); client->socket );
@@ -501,7 +501,7 @@ void client_cleanup(struct client* client,
if (client->mapped) { if (client->mapped) {
munmap(client->mapped, client->serve->size); munmap(client->mapped, client->serve->size);
} }
if (client->fileno) { if (client->fileno) {
FATAL_IF_NEGATIVE( close(client->fileno), FATAL_IF_NEGATIVE( close(client->fileno),
"Error closing file %d", "Error closing file %d",
client->fileno ); client->fileno );
@@ -517,15 +517,15 @@ void client_cleanup(struct client* client,
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"); info("client: mmaping file");
FATAL_IF_NEGATIVE( FATAL_IF_NEGATIVE(
open_and_mmap( open_and_mmap(
client->serve->filename, client->serve->filename,
&client->fileno, &client->fileno,
NULL, NULL,
(void**) &client->mapped (void**) &client->mapped
), ),
"Couldn't open/mmap file %s: %s", client->serve->filename, strerror( errno ) "Couldn't open/mmap file %s: %s", client->serve->filename, strerror( errno )
@@ -533,13 +533,13 @@ void* client_serve(void* client_uncast)
debug( "Opened client file fd %d", client->fileno); debug( "Opened client file fd %d", client->fileno);
debug("client: sending hello"); debug("client: sending hello");
client_send_hello(client); client_send_hello(client);
debug("client: serving requests"); debug("client: serving requests");
while (client_serve_request(client) == 0) while (client_serve_request(client) == 0)
; ;
debug("client: stopped serving requests"); debug("client: stopped serving requests");
client->stopped = 1; client->stopped = 1;
if ( client->disconnect ){ if ( client->disconnect ){
debug("client: control arrived" ); debug("client: control arrived" );
server_control_arrived( client->serve ); server_control_arrived( client->serve );
@@ -548,6 +548,7 @@ void* client_serve(void* client_uncast)
debug("Cleaning client %p up normally in thread %p", client, pthread_self()); debug("Cleaning client %p up normally in thread %p", client, pthread_self());
client_cleanup(client, 0); client_cleanup(client, 0);
debug("Client thread done" ); debug("Client thread done" );
return NULL; return NULL;
} }

View File

@@ -34,10 +34,10 @@ struct bitset_mapping* build_allocation_map(int fd, uint64_t size, int resolutio
/* Resize fiemap to allow us to read in the extents */ /* Resize fiemap to allow us to read in the extents */
fiemap = (struct fiemap*)xmalloc( fiemap = (struct fiemap*)xmalloc(
sizeof(struct fiemap) + ( sizeof(struct fiemap) + (
sizeof(struct fiemap_extent) * sizeof(struct fiemap_extent) *
fiemap_count->fm_mapped_extents fiemap_count->fm_mapped_extents
) )
); );
/* realloc makes valgrind complain a lot */ /* realloc makes valgrind complain a lot */
memcpy(fiemap, fiemap_count, sizeof(struct fiemap)); memcpy(fiemap, fiemap_count, sizeof(struct fiemap));
@@ -46,15 +46,15 @@ struct bitset_mapping* build_allocation_map(int fd, uint64_t size, int resolutio
fiemap->fm_extent_count = fiemap->fm_mapped_extents; fiemap->fm_extent_count = fiemap->fm_mapped_extents;
fiemap->fm_mapped_extents = 0; fiemap->fm_mapped_extents = 0;
if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) { if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) {
debug( "Couldn't get fiemap, returning no allocation_map" ); debug( "Couldn't get fiemap, returning no allocation_map" );
goto no_map; goto no_map;
} }
for (i=0;i<fiemap->fm_mapped_extents;i++) { for (i=0;i<fiemap->fm_mapped_extents;i++) {
bitset_set_range( bitset_set_range(
allocation_map, allocation_map,
fiemap->fm_extents[i].fe_logical, fiemap->fm_extents[i].fe_logical,
fiemap->fm_extents[i].fe_length fiemap->fm_extents[i].fe_length
); );
} }
@@ -94,7 +94,7 @@ no_map:
int open_and_mmap(const char* filename, int* out_fd, off64_t *out_size, void **out_map) int open_and_mmap(const char* filename, int* out_fd, off64_t *out_size, void **out_map)
{ {
off64_t size; off64_t size;
/* O_DIRECT seems to be intermittently supported. Leaving it as /* O_DIRECT seems to be intermittently supported. Leaving it as
* a compile-time option for now. */ * a compile-time option for now. */
#ifdef DIRECT_IO #ifdef DIRECT_IO
@@ -107,7 +107,7 @@ int open_and_mmap(const char* filename, int* out_fd, off64_t *out_size, void **o
warn("open(%s) failed: does it exist?", filename); warn("open(%s) failed: does it exist?", filename);
return *out_fd; return *out_fd;
} }
size = lseek64(*out_fd, 0, SEEK_END); size = lseek64(*out_fd, 0, SEEK_END);
if (size < 0) { if (size < 0) {
warn("lseek64() failed"); warn("lseek64() failed");
@@ -116,9 +116,9 @@ int open_and_mmap(const char* filename, int* out_fd, off64_t *out_size, void **o
if (out_size) { if (out_size) {
*out_size = size; *out_size = size;
} }
if (out_map) { if (out_map) {
*out_map = mmap64(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, *out_map = mmap64(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
*out_fd, 0); *out_fd, 0);
if (((long) *out_map) == -1) { if (((long) *out_map) == -1) {
warn("mmap64() failed"); warn("mmap64() failed");
@@ -126,7 +126,7 @@ int open_and_mmap(const char* filename, int* out_fd, off64_t *out_size, void **o
} }
} }
debug("opened %s size %ld on fd %d @ %p", filename, size, *out_fd, *out_map); debug("opened %s size %ld on fd %d @ %p", filename, size, *out_fd, *out_map);
return 0; return 0;
} }
@@ -175,16 +175,16 @@ ssize_t spliceloop(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_
{ {
const unsigned int flags = SPLICE_F_MORE|SPLICE_F_MOVE|flags2; const unsigned int flags = SPLICE_F_MORE|SPLICE_F_MOVE|flags2;
size_t spliced=0; 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) { while (spliced < len) {
ssize_t result = splice(fd_in, off_in, fd_out, off_out, len, flags); ssize_t result = splice(fd_in, off_in, fd_out, off_out, len, flags);
if (result < 0) { if (result < 0) {
//debug("result=%ld (%s), spliced=%ld, len=%ld", result, strerror(errno), spliced, len); //debug("result=%ld (%s), spliced=%ld, len=%ld", result, strerror(errno), spliced, len);
if (errno == EAGAIN && (flags & SPLICE_F_NONBLOCK) ) { if (errno == EAGAIN && (flags & SPLICE_F_NONBLOCK) ) {
return spliced; return spliced;
} }
else { else {
return -1; return -1;
} }
@@ -193,7 +193,7 @@ ssize_t spliceloop(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_
//debug("result=%ld (%s), spliced=%ld, len=%ld", result, strerror(errno), spliced, len); //debug("result=%ld (%s), spliced=%ld, len=%ld", result, strerror(errno), spliced, len);
} }
} }
return spliced; return spliced;
} }
@@ -202,25 +202,25 @@ int splice_via_pipe_loop(int fd_in, int fd_out, size_t len)
int pipefd[2]; /* read end, write end */ int pipefd[2]; /* read end, write end */
size_t spliced=0; size_t spliced=0;
if (pipe(pipefd) == -1) { if (pipe(pipefd) == -1) {
return -1; return -1;
} }
while (spliced < len) { while (spliced < len) {
ssize_t run = len-spliced; ssize_t run = len-spliced;
ssize_t s2, s1 = spliceloop(fd_in, NULL, pipefd[1], NULL, run, SPLICE_F_NONBLOCK); ssize_t s2, s1 = spliceloop(fd_in, NULL, pipefd[1], NULL, run, SPLICE_F_NONBLOCK);
/*if (run > 65535) /*if (run > 65535)
run = 65535;*/ run = 65535;*/
if (s1 < 0) { break; } if (s1 < 0) { break; }
s2 = spliceloop(pipefd[0], NULL, fd_out, NULL, s1, 0); s2 = spliceloop(pipefd[0], NULL, fd_out, NULL, s1, 0);
if (s2 < 0) { break; } if (s2 < 0) { break; }
spliced += s2; spliced += s2;
} }
close(pipefd[0]); close(pipefd[0]);
close(pipefd[1]); close(pipefd[1]);
return spliced < len ? -1 : 0; return spliced < len ? -1 : 0;
} }
@@ -234,16 +234,16 @@ int splice_via_pipe_loop(int fd_in, int fd_out, size_t len)
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++) { for (cur=0; cur < bufsize; cur++) {
int result = read(fd, buf+cur, 1); int result = read(fd, buf+cur, 1);
if (result <= 0) { return -1; } if (result <= 0) { return -1; }
if (buf[cur] == 10) { if (buf[cur] == 10) {
buf[cur] = '\0'; buf[cur] = '\0';
break; break;
} }
} }
return cur+1; return cur+1;
} }
@@ -252,9 +252,9 @@ int read_lines_until_blankline(int fd, int max_line_length, char ***lines)
int lines_count = 0; int lines_count = 0;
char line[max_line_length+1]; char line[max_line_length+1];
*lines = NULL; *lines = NULL;
memset(line, 0, max_line_length+1); memset(line, 0, max_line_length+1);
while (1) { while (1) {
int readden = read_until_newline(fd, line, max_line_length); int readden = read_until_newline(fd, line, max_line_length);
/* readden will be: /* readden will be:
@@ -280,3 +280,4 @@ int fd_is_closed( int fd_in )
errno = errno_old; errno = errno_old;
return result; return result;
} }

View File

@@ -4,7 +4,7 @@
#include "serve.h" #include "serve.h"
struct bitset_mapping; /* don't need whole of bitset.h here */ struct bitset_mapping; /* don't need whole of bitset.h here */
/** Returns a bit field representing which blocks are allocated in file /** Returns a bit field representing which blocks are allocated in file
* descriptor ''fd''. You must supply the size, and the resolution at which * descriptor ''fd''. You must supply the size, and the resolution at which
* you want the bits to represent allocated blocks. If the OS represents * you want the bits to represent allocated blocks. If the OS represents
* allocated blocks at a finer resolution than you've asked for, any block * allocated blocks at a finer resolution than you've asked for, any block
@@ -43,15 +43,15 @@ int splice_via_pipe_loop(int fd_in, int fd_out, size_t len);
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 /** 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 * received (i.e. the sequence LF LF). The data is read from ''fd'' and
* lines must be a maximum of ''max_line_length''. The set of lines is * lines must be a maximum of ''max_line_length''. The set of lines is
* returned as an array of zero-terminated strings; you must pass an address * returned as an array of zero-terminated strings; you must pass an address
* ''lines'' in which you want the address of this array returned. * ''lines'' in which you want the address of this array returned.
*/ */
int read_lines_until_blankline(int fd, int max_line_length, char ***lines); int read_lines_until_blankline(int fd, int max_line_length, char ***lines);
/** Open the given ''filename'', determine its size, and mmap it in its /** Open the given ''filename'', determine its size, and mmap it in its
* entirety. The file descriptor is stored in ''out_fd'', the size in * entirety. The file descriptor is stored in ''out_fd'', the size in
* ''out_size'' and the address of the mmap in ''out_map''. If anything goes * ''out_size'' and the address of the mmap in ''out_map''. If anything goes
* wrong, returns -1 setting errno, otherwise 0. * wrong, returns -1 setting errno, otherwise 0.
*/ */

View File

@@ -79,15 +79,15 @@ void mirror_init( struct mirror * mirror, const char * filename )
FATAL_IF_NEGATIVE( FATAL_IF_NEGATIVE(
open_and_mmap( open_and_mmap(
filename, filename,
&map_fd, &map_fd,
&size, &size,
(void**) &mirror->mapped (void**) &mirror->mapped
), ),
"Failed to open and mmap %s", "Failed to open and mmap %s",
filename filename
); );
mirror->dirty_map = bitset_alloc(size, 4096); mirror->dirty_map = bitset_alloc(size, 4096);
} }
@@ -119,7 +119,7 @@ struct mirror * mirror_create(
max_Bps, max_Bps,
action_at_finish, action_at_finish,
commit_signal); commit_signal);
mirror_init( mirror, filename ); mirror_init( mirror, filename );
mirror_reset( mirror ); mirror_reset( mirror );
@@ -146,7 +146,7 @@ static const int mirror_longest_write = 8<<20;
*/ */
static const unsigned int mirror_last_pass_after_bytes_written = 100<<20; static const unsigned int mirror_last_pass_after_bytes_written = 100<<20;
/** The largest number of full passes we'll do - the last one will always /** The largest number of full passes we'll do - the last one will always
* cause the I/O to freeze, however many bytes are left to copy. * cause the I/O to freeze, however many bytes are left to copy.
*/ */
static const int mirror_maximum_passes = 7; static const int mirror_maximum_passes = 7;
@@ -166,15 +166,15 @@ int mirror_pass(struct server * serve, int should_lock, uint64_t *written)
debug("mirror current=%ld, run=%d", current, run); debug("mirror current=%ld, run=%d", current, run);
/* FIXME: we could avoid sending sparse areas of the /* FIXME: we could avoid sending sparse areas of the
* disc here, and probably save a lot of bandwidth and * disc here, and probably save a lot of bandwidth and
* time (if we know the destination starts off zeroed). * time (if we know the destination starts off zeroed).
*/ */
if (bitset_is_set_at(map, current)) { if (bitset_is_set_at(map, current)) {
/* We've found a dirty area, send it */ /* We've found a dirty area, send it */
debug("^^^ writing"); debug("^^^ writing");
/* We need to stop the main thread from working /* We need to stop the main thread from working
* because it might corrupt the dirty map. This * because it might corrupt the dirty map. This
* is likely to slow things down but will be * is likely to slow things down but will be
* safe. * safe.
@@ -185,7 +185,7 @@ int mirror_pass(struct server * serve, int should_lock, uint64_t *written)
/** FIXME: do something useful with bytes/second */ /** FIXME: do something useful with bytes/second */
/** FIXME: error handling code here won't unlock */ /** FIXME: error handling code here won't unlock */
socket_nbd_write( serve->mirror->client, socket_nbd_write( serve->mirror->client,
current, current,
run, run,
0, 0,
@@ -292,7 +292,7 @@ int mirror_connect( struct mirror * mirror, off64_t local_size )
mirror_set_state( mirror, MS_GO ); mirror_set_state( mirror, MS_GO );
} }
else { else {
warn("Remote size (%d) doesn't match local (%d)", warn("Remote size (%d) doesn't match local (%d)",
remote_size, local_size ); remote_size, local_size );
mirror_set_state( mirror, MS_FAIL_SIZE_MISMATCH ); mirror_set_state( mirror, MS_FAIL_SIZE_MISMATCH );
} }
@@ -341,11 +341,11 @@ void mirror_run( struct server *serve )
for (pass=0; pass < mirror_maximum_passes-1; pass++) { for (pass=0; pass < mirror_maximum_passes-1; pass++) {
debug("mirror start pass=%d", pass); debug("mirror start pass=%d", pass);
if ( !mirror_pass( serve, 1, &written ) ){ if ( !mirror_pass( serve, 1, &written ) ){
debug("Failed mirror pass state is %d", mirror_get_state( serve->mirror ) ); debug("Failed mirror pass state is %d", mirror_get_state( serve->mirror ) );
debug("pass failed, giving up"); debug("pass failed, giving up");
return; } return; }
/* if we've not written anything */ /* if we've not written anything */
if (written < mirror_last_pass_after_bytes_written) { break; } if (written < mirror_last_pass_after_bytes_written) { break; }
} }
@@ -358,7 +358,7 @@ void mirror_run( struct server *serve )
mirror_on_exit( serve ); mirror_on_exit( serve );
info("Server closed, quitting " info("Server closed, quitting "
"after successful migration"); "after successful migration");
} }
} }
server_unlock_io( serve ); server_unlock_io( serve );
} }
@@ -379,11 +379,11 @@ void mirror_signal_commit( struct mirror * mirror )
{ {
NULLCHECK( mirror ); NULLCHECK( mirror );
mbox_post_mirror_state( mirror->commit_signal, mbox_post_mirror_state( mirror->commit_signal,
mirror_get_state( mirror ) ); mirror_get_state( mirror ) );
} }
/** Thread launched to drive mirror process /** Thread launched to drive mirror process
* This is needed for two reasons: firstly, it decouples the mirroring * This is needed for two reasons: firstly, it decouples the mirroring
* from the control thread (although that's less valid with mboxes * from the control thread (although that's less valid with mboxes
* passing state back and forth) and to provide an error context so that * passing state back and forth) and to provide an error context so that
@@ -408,7 +408,7 @@ void* mirror_runner(void* serve_params_uncast)
error_set_handler( (cleanup_handler *) mirror_cleanup, serve ); error_set_handler( (cleanup_handler *) mirror_cleanup, serve );
info( "Connecting to mirror" ); info( "Connecting to mirror" );
time_t start_time = time(NULL); time_t start_time = time(NULL);
int connected = mirror_connect( mirror, serve->size ); int connected = mirror_connect( mirror, serve->size );
mirror_signal_commit( mirror ); mirror_signal_commit( mirror );
@@ -418,8 +418,8 @@ void* mirror_runner(void* serve_params_uncast)
* and retry everything from mirror_set_state(_, MS_INIT), but * and retry everything from mirror_set_state(_, MS_INIT), but
* *without* signaling the commit or abandoning the mirror. * *without* signaling the commit or abandoning the mirror.
* */ * */
if ( (time(NULL) - start_time) > MS_CONNECT_TIME_SECS ){ if ( (time(NULL) - start_time) > MS_CONNECT_TIME_SECS ){
/* If we get here, then we managed to connect but the /* If we get here, then we managed to connect but the
* control thread feeding status back to the user will * control thread feeding status back to the user will
* have gone away, leaving the user without meaningful * have gone away, leaving the user without meaningful
@@ -449,11 +449,11 @@ struct mirror_super * mirror_super_create(
struct mbox * state_mbox) struct mbox * state_mbox)
{ {
struct mirror_super * super = xmalloc( sizeof( struct mirror_super) ); struct mirror_super * super = xmalloc( sizeof( struct mirror_super) );
super->mirror = mirror_create( super->mirror = mirror_create(
filename, filename,
connect_to, connect_to,
connect_from, connect_from,
max_Bps, max_Bps,
action_at_finish, action_at_finish,
mbox_create() ) ; mbox_create() ) ;
super->state_mbox = state_mbox; super->state_mbox = state_mbox;
@@ -462,15 +462,15 @@ struct mirror_super * mirror_super_create(
/* Post the current state of the mirror into super->state_mbox.*/ /* Post the current state of the mirror into super->state_mbox.*/
void mirror_super_signal_committed( void mirror_super_signal_committed(
struct mirror_super * super , struct mirror_super * super ,
enum mirror_state commit_state ) enum mirror_state commit_state )
{ {
NULLCHECK( super ); NULLCHECK( super );
NULLCHECK( super->state_mbox ); NULLCHECK( super->state_mbox );
mbox_post_mirror_state( mbox_post_mirror_state(
super->state_mbox, super->state_mbox,
commit_state ); commit_state );
} }
@@ -506,14 +506,14 @@ void * mirror_super_runner( void * serve_uncast )
do { do {
FATAL_IF( 0 != pthread_create( FATAL_IF( 0 != pthread_create(
&mirror->thread, &mirror->thread,
NULL, NULL,
mirror_runner, mirror_runner,
serve), serve),
"Failed to create mirror thread"); "Failed to create mirror thread");
debug("Supervisor waiting for commit signal"); debug("Supervisor waiting for commit signal");
enum mirror_state * commit_state = enum mirror_state * commit_state =
mbox_receive( mirror->commit_signal ); mbox_receive( mirror->commit_signal );
debug( "Supervisor got commit signal" ); debug( "Supervisor got commit signal" );
@@ -526,7 +526,7 @@ void * mirror_super_runner( void * serve_uncast )
should_retry = *commit_state == MS_GO; should_retry = *commit_state == MS_GO;
/* Only send this signal the first time */ /* Only send this signal the first time */
mirror_super_signal_committed( mirror_super_signal_committed(
super, super,
*commit_state); *commit_state);
debug("Mirror supervisor committed"); debug("Mirror supervisor committed");
} }
@@ -540,7 +540,7 @@ void * mirror_super_runner( void * serve_uncast )
success = MS_DONE == mirror_get_state( mirror ); success = MS_DONE == mirror_get_state( mirror );
if( success ){ if( success ){
info( "Mirror supervisor success, exiting" ); } info( "Mirror supervisor success, exiting" ); }
else if ( mirror->signal_abandon ) { else if ( mirror->signal_abandon ) {
info( "Mirror abandoned" ); info( "Mirror abandoned" );
@@ -553,7 +553,7 @@ void * mirror_super_runner( void * serve_uncast )
first_pass = 0; first_pass = 0;
if ( should_retry ) { if ( should_retry ) {
/* We don't want to hammer the destination too /* We don't want to hammer the destination too
* hard, so if this is a retry, insert a delay. */ * hard, so if this is a retry, insert a delay. */
sleep( MS_RETRY_DELAY_SECS ); sleep( MS_RETRY_DELAY_SECS );
@@ -563,7 +563,7 @@ void * mirror_super_runner( void * serve_uncast )
mirror_reset( mirror ); mirror_reset( mirror );
} }
} }
while ( should_retry && !success ); while ( should_retry && !success );
serve->mirror = NULL; serve->mirror = NULL;
@@ -575,4 +575,3 @@ void * mirror_super_runner( void * serve_uncast )
return NULL; return NULL;
} }

View File

@@ -26,7 +26,7 @@ static inline void* sockaddr_address_data(struct sockaddr* sockaddr)
struct sockaddr_in* in = (struct sockaddr_in*) sockaddr; struct sockaddr_in* in = (struct sockaddr_in*) sockaddr;
struct sockaddr_in6* in6 = (struct sockaddr_in6*) sockaddr; struct sockaddr_in6* in6 = (struct sockaddr_in6*) sockaddr;
if (sockaddr->sa_family == AF_INET) { if (sockaddr->sa_family == AF_INET) {
return &in->sin_addr; return &in->sin_addr;
} }
@@ -64,7 +64,7 @@ struct server * server_create (
FATAL_IF_ZERO( FATAL_IF_ZERO(
parse_ip_to_sockaddr(&out->bind_to.generic, s_ip_address), parse_ip_to_sockaddr(&out->bind_to.generic, s_ip_address),
"Couldn't parse server address '%s' (use 0 if " "Couldn't parse server address '%s' (use 0 if "
"you want to bind to all IPs)", "you want to bind to all IPs)",
s_ip_address s_ip_address
); );
@@ -103,7 +103,7 @@ void server_destroy( struct server * serve )
flexthread_mutex_destroy( serve->l_acl ); flexthread_mutex_destroy( serve->l_acl );
flexthread_mutex_destroy( serve->l_io ); flexthread_mutex_destroy( serve->l_io );
if ( serve->acl ) { if ( serve->acl ) {
acl_destroy( serve->acl ); acl_destroy( serve->acl );
serve->acl = NULL; serve->acl = NULL;
} }
@@ -220,20 +220,20 @@ void serve_bind( struct server * serve )
do { do {
bind_result = bind( bind_result = bind(
serve->server_fd, serve->server_fd,
&serve->bind_to.generic, &serve->bind_to.generic,
sizeof(serve->bind_to)); sizeof(serve->bind_to));
if ( 0 == bind_result ) { if ( 0 == bind_result ) {
info( "Bound to %s port %d", info( "Bound to %s port %d",
s_address, s_address,
ntohs(serve->bind_to.v4.sin_port)); ntohs(serve->bind_to.v4.sin_port));
break; break;
} }
else { else {
warn( "Couldn't bind to %s port %d: %s", warn( "Couldn't bind to %s port %d: %s",
s_address, s_address,
ntohs(serve->bind_to.v4.sin_port), ntohs(serve->bind_to.v4.sin_port),
strerror( errno ) ); strerror( errno ) );
@@ -242,10 +242,10 @@ void serve_bind( struct server * serve )
* EADDRINUSE, EADDRNOTAVAIL, EBADF, * EADDRINUSE, EADDRNOTAVAIL, EBADF,
* EINVAL or ENOTSOCK. * EINVAL or ENOTSOCK.
* *
* Any of these other than EACCES, * Any of these other than EACCES,
* EADDRINUSE or EADDRNOTAVAIL signify * EADDRINUSE or EADDRNOTAVAIL signify
* that there's a logic error somewhere. * that there's a logic error somewhere.
* *
* EADDRINUSE is fatal: if there's * EADDRINUSE is fatal: if there's
* something already where we want to be * something already where we want to be
* listening, we have no guarantees that * listening, we have no guarantees that
@@ -258,7 +258,7 @@ void serve_bind( struct server * serve )
continue; continue;
case EADDRINUSE: case EADDRINUSE:
fatal( "%s port %d in use, giving up.", fatal( "%s port %d in use, giving up.",
s_address, s_address,
ntohs(serve->bind_to.v4.sin_port)); ntohs(serve->bind_to.v4.sin_port));
default: default:
fatal( "Giving up" ); fatal( "Giving up" );
@@ -275,11 +275,11 @@ void serve_open_server_socket(struct server* params)
NULLCHECK( params ); NULLCHECK( params );
int optval=1; int optval=1;
params->server_fd= socket(params->bind_to.generic.sa_family == AF_INET ? params->server_fd= socket(params->bind_to.generic.sa_family == AF_INET ?
PF_INET : PF_INET6, SOCK_STREAM, 0); PF_INET : PF_INET6, SOCK_STREAM, 0);
FATAL_IF_NEGATIVE(params->server_fd, FATAL_IF_NEGATIVE(params->server_fd,
"Couldn't create server socket"); "Couldn't create server socket");
/* We need SO_REUSEADDR so that when we switch from listening to /* We need SO_REUSEADDR so that when we switch from listening to
@@ -308,7 +308,7 @@ void serve_open_server_socket(struct server* params)
* squatting on our ip/port combo, or the ip isn't yet * squatting on our ip/port combo, or the ip isn't yet
* configured. Ideally we want to retry this. */ * configured. Ideally we want to retry this. */
serve_bind(params); serve_bind(params);
FATAL_IF_NEGATIVE( FATAL_IF_NEGATIVE(
listen(params->server_fd, params->tcp_backlog), listen(params->server_fd, params->tcp_backlog),
"Couldn't listen on server socket" "Couldn't listen on server socket"
@@ -332,9 +332,9 @@ int tryjoin_client_thread( struct client_tbl_entry *entry, int (*joinfunc)(pthre
memset(s_client_address, 0, 64); memset(s_client_address, 0, 64);
strcpy(s_client_address, "???"); strcpy(s_client_address, "???");
inet_ntop( entry->address.generic.sa_family, inet_ntop( entry->address.generic.sa_family,
sockaddr_address_data(&entry->address.generic), sockaddr_address_data(&entry->address.generic),
s_client_address, s_client_address,
64 ); 64 );
debug( "%s(%p,...)", joinfunc == pthread_join ? "joining" : "tryjoining", entry->thread ); debug( "%s(%p,...)", joinfunc == pthread_join ? "joining" : "tryjoining", entry->thread );
@@ -343,15 +343,15 @@ int tryjoin_client_thread( struct client_tbl_entry *entry, int (*joinfunc)(pthre
* already dead, but the client still needs tidying up. */ * already dead, but the client still needs tidying up. */
if (join_errno != 0 && !entry->client->stopped ) { if (join_errno != 0 && !entry->client->stopped ) {
debug( "join_errno was %s, stopped was %d", strerror( join_errno ), entry->client->stopped ); debug( "join_errno was %s, stopped was %d", strerror( join_errno ), entry->client->stopped );
FATAL_UNLESS( join_errno == EBUSY, FATAL_UNLESS( join_errno == EBUSY,
"Problem with joining thread %p: %s", "Problem with joining thread %p: %s",
entry->thread, entry->thread,
strerror(join_errno) ); strerror(join_errno) );
} }
else if ( join_errno == 0 ) { else if ( join_errno == 0 ) {
debug("nbd thread %016x exited (%s) with status %ld", debug("nbd thread %016x exited (%s) with status %ld",
entry->thread, entry->thread,
s_client_address, s_client_address,
(uint64_t)status); (uint64_t)status);
client_destroy( entry->client ); client_destroy( entry->client );
entry->client = NULL; entry->client = NULL;
@@ -447,8 +447,8 @@ int server_acl_accepts( struct server *params, union mysockaddr * client_address
} }
int server_should_accept_client( int server_should_accept_client(
struct server * params, struct server * params,
union mysockaddr * client_address, union mysockaddr * client_address,
char *s_client_address, char *s_client_address,
size_t s_client_address_len ) size_t s_client_address_len )
@@ -466,7 +466,7 @@ int server_should_accept_client(
if ( !server_acl_accepts( params, client_address ) ) { if ( !server_acl_accepts( params, client_address ) ) {
warn( "Rejecting client %s: Access control error", s_client_address ); warn( "Rejecting client %s: Access control error", s_client_address );
debug( "We %s have an acl, and default_deny is %s", debug( "We %s have an acl, and default_deny is %s",
(params->acl ? "do" : "do not"), (params->acl ? "do" : "do not"),
(params->acl->default_deny ? "true" : "false") ); (params->acl->default_deny ? "true" : "false") );
return 0; return 0;
@@ -477,8 +477,8 @@ int server_should_accept_client(
int spawn_client_thread( int spawn_client_thread(
struct client * client_params, struct client * client_params,
pthread_t *out_thread) 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);
@@ -492,8 +492,8 @@ int spawn_client_thread(
* address doesn't match, or if there are too many clients already connected. * address doesn't match, or if there are too many clients already connected.
*/ */
void accept_nbd_client( void accept_nbd_client(
struct server* params, struct server* params,
int client_fd, int client_fd,
union mysockaddr* client_address) union mysockaddr* client_address)
{ {
NULLCHECK(params); NULLCHECK(params);
@@ -511,7 +511,7 @@ void accept_nbd_client(
return; return;
} }
slot = cleanup_and_find_client_slot(params); slot = cleanup_and_find_client_slot(params);
if (slot < 0) { if (slot < 0) {
warn("too many clients to accept connection"); warn("too many clients to accept connection");
FATAL_IF_NEGATIVE( close( client_fd ), FATAL_IF_NEGATIVE( close( client_fd ),
@@ -519,14 +519,14 @@ void accept_nbd_client(
debug("Closed client socket fd %d", client_fd); debug("Closed client socket fd %d", client_fd);
return; return;
} }
info( "Client %s accepted on fd %d.", s_client_address, client_fd ); info( "Client %s accepted on fd %d.", s_client_address, client_fd );
client_params = client_create( params, client_fd ); client_params = client_create( params, client_fd );
params->nbd_client[slot].client = client_params; params->nbd_client[slot].client = client_params;
memcpy(&params->nbd_client[slot].address, client_address, memcpy(&params->nbd_client[slot].address, client_address,
sizeof(union mysockaddr)); sizeof(union mysockaddr));
pthread_t * thread = &params->nbd_client[slot].thread; pthread_t * thread = &params->nbd_client[slot].thread;
if ( 0 != spawn_client_thread( client_params, thread ) ) { if ( 0 != spawn_client_thread( client_params, thread ) ) {
@@ -537,7 +537,7 @@ void accept_nbd_client(
debug("Closed client socket fd %d", client_fd); debug("Closed client socket fd %d", client_fd);
return; 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);
} }
@@ -576,7 +576,7 @@ int server_is_closed(struct server* serve)
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; */ int i; /* , j; */
@@ -587,7 +587,7 @@ void server_close_clients( struct server *params )
if ( entry->thread != 0 ) { if ( entry->thread != 0 ) {
debug( "Stop signaling client %p", entry->client ); debug( "Stop signaling client %p", entry->client );
client_signal_stop( entry->client ); client_signal_stop( entry->client );
} }
} }
/* We don't join the clients here. When we enter the final /* We don't join the clients here. When we enter the final
@@ -648,7 +648,7 @@ int server_accept( struct server * params )
self_pipe_fd_set( params->close_signal, &fds ); self_pipe_fd_set( params->close_signal, &fds );
self_pipe_fd_set( params->acl_updated_signal, &fds ); self_pipe_fd_set( params->acl_updated_signal, &fds );
FATAL_IF_NEGATIVE(select(FD_SETSIZE, &fds, FATAL_IF_NEGATIVE(select(FD_SETSIZE, &fds,
NULL, NULL, NULL), "select() failed"); NULL, NULL, NULL), "select() failed");
if ( self_pipe_fd_isset( params->close_signal, &fds ) ){ if ( self_pipe_fd_isset( params->close_signal, &fds ) ){
@@ -672,13 +672,13 @@ int server_accept( struct server * params )
client_fd = accept( params->server_fd, &client_address.generic, &socklen ); client_fd = accept( params->server_fd, &client_address.generic, &socklen );
debug("Accepted nbd client socket fd %d", client_fd); debug("Accepted nbd client socket fd %d", client_fd);
accept_nbd_client(params, client_fd, &client_address); accept_nbd_client(params, client_fd, &client_address);
} }
return 1; return 1;
} }
void serve_accept_loop(struct server* params) void serve_accept_loop(struct server* params)
{ {
NULLCHECK( params ); NULLCHECK( params );
while( server_accept( params ) ); while( server_accept( params ) );
@@ -697,9 +697,9 @@ void serve_init_allocation_map(struct server* params)
FATAL_IF_NEGATIVE(fd, "Couldn't open %s", params->filename); FATAL_IF_NEGATIVE(fd, "Couldn't open %s", params->filename);
size = lseek64(fd, 0, SEEK_END); size = lseek64(fd, 0, SEEK_END);
params->size = size; params->size = size;
FATAL_IF_NEGATIVE(size, "Couldn't find size of %s", FATAL_IF_NEGATIVE(size, "Couldn't find size of %s",
params->filename); params->filename);
params->allocation_map = params->allocation_map =
build_allocation_map(fd, size, block_allocation_resolution); build_allocation_map(fd, size, block_allocation_resolution);
close(fd); close(fd);
} }
@@ -737,29 +737,29 @@ void server_control_arrived( struct server *serve )
/** Closes sockets, frees memory and waits for all client threads to finish */ /** Closes sockets, frees memory and waits for all client threads to finish */
void serve_cleanup(struct server* params, void serve_cleanup(struct server* params,
int fatal __attribute__ ((unused)) ) int fatal __attribute__ ((unused)) )
{ {
NULLCHECK( params ); NULLCHECK( params );
info("cleaning up"); info("cleaning up");
int i; int i;
if (params->server_fd){ close(params->server_fd); } if (params->server_fd){ close(params->server_fd); }
if (params->allocation_map) { if (params->allocation_map) {
free(params->allocation_map); free(params->allocation_map);
} }
if ( server_is_mirroring( params ) ) { if ( server_is_mirroring( params ) ) {
server_abandon_mirror( params ); server_abandon_mirror( params );
} }
for (i=0; i < params->max_nbd_clients; i++) { for (i=0; i < params->max_nbd_clients; i++) {
void* status; void* status;
pthread_t thread_id = params->nbd_client[i].thread; pthread_t thread_id = params->nbd_client[i].thread;
if (thread_id != 0) { if (thread_id != 0) {
debug("joining thread %p", thread_id); debug("joining thread %p", thread_id);
pthread_join(thread_id, &status); pthread_join(thread_id, &status);
@@ -790,7 +790,7 @@ void server_abandon_mirror( struct server * serve )
{ {
NULLCHECK( serve ); NULLCHECK( serve );
if ( serve->mirror_super ) { if ( serve->mirror_super ) {
/* FIXME: AWOOGA! RACE! /* FIXME: AWOOGA! RACE!
* We can set signal_abandon after mirror_super has * We can set signal_abandon after mirror_super has
* checked it, but before the reset. This would lead to * checked it, but before the reset. This would lead to
* a hang. However, mirror_reset doesn't change the * a hang. However, mirror_reset doesn't change the
@@ -814,7 +814,7 @@ int do_serve(struct server* params)
NULLCHECK( params ); NULLCHECK( params );
int has_control; int has_control;
error_set_handler((cleanup_handler*) serve_cleanup, params); error_set_handler((cleanup_handler*) serve_cleanup, params);
serve_open_server_socket(params); serve_open_server_socket(params);
serve_init_allocation_map(params); serve_init_allocation_map(params);