3 Commits

Author SHA1 Message Date
Patrick J Cherry
29306a716e Changed msync to actually sync 2018-01-31 23:03:28 +00:00
Patrick J Cherry
0ba90b39a3 Change from one giant mmap to lots of individual mmaps
This copies xnbd's style
2018-01-31 22:56:59 +00:00
Patrick J Cherry
7f98f6ef9e Add compiler flag to disable explicit msync() calls 2018-01-31 20:45:48 +00:00
5 changed files with 68 additions and 31 deletions

View File

@@ -4,7 +4,7 @@ VPATH=src:tests/unit
DESTDIR?=/ DESTDIR?=/
PREFIX?=/usr/local/bin PREFIX?=/usr/local/bin
INSTALLDIR=$(DESTDIR)/$(PREFIX) INSTALLDIR=$(DESTDIR)/$(PREFIX)
ifdef DEBUG ifdef DEBUG
CFLAGS_EXTRA=-g -DDEBUG CFLAGS_EXTRA=-g -DDEBUG
LDFLAGS_EXTRA=-g LDFLAGS_EXTRA=-g
@@ -12,6 +12,11 @@ else
CFLAGS_EXTRA=-O2 CFLAGS_EXTRA=-O2
endif endif
NO_MSYNC=1
ifdef NO_MSYNC
CFLAGS_EXTRA += -DNO_MSYNC
endif
CFLAGS_EXTRA += -fPIC --std=gnu99 CFLAGS_EXTRA += -fPIC --std=gnu99
LDFLAGS_EXTRA += -Wl,--relax,--gc-sections -L$(LIB) -Wl,-rpath-link,$(LIB) LDFLAGS_EXTRA += -Wl,--relax,--gc-sections -L$(LIB) -Wl,-rpath-link,$(LIB)

View File

@@ -73,7 +73,6 @@ int build_allocation_map(struct bitset * allocation_map, int fd)
return 1; 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)
{ {
/* /*
@@ -101,7 +100,7 @@ int open_and_mmap(const char* filename, int* out_fd, uint64_t *out_size, void **
*out_size = size; *out_size = size;
} }
if (out_map) { if (0) {
*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) {
@@ -349,3 +348,36 @@ ssize_t iobuf_write( int fd, struct iobuf *iobuf )
return count; return count;
} }
struct iommap *iommap_alloc(int fd, off64_t from, uint64_t len) {
off66_t mmap_from = from & ~((off64_t) getpagesize() - 1);
uint64_t mmap_len = len + (from - mmap_from);
void *mmap_buf = NULL;
// TODO: Check the error code from mmap64
if(mmap_len)
mmap_buf = mmap64(NULL, mmap_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mmap_from);
struct iommap *im = xmalloc(sizeof(struct iommap ));
im->mmap_buf = mmap_buf;
im->mmap_len = mmap_len;
im->buf = (char *) mmap_buf + from - mmap_from;
debug("mmapped file from %ld:%d", mmap_from, mmap_len);
return im;
}
void iommap_sync(struct iommap *im) {
if (im->mmap_len)
msync(im->mmap_buf, im->mmap_len, MS_SYNC | MS_INVALIDATE);
return;
}
void iommap_free(struct iommap *im) {
if (im->mmap_len)
munmap(im->mmap_buf, im->mmap_len);
free(im);
}

View File

@@ -11,7 +11,20 @@ struct iobuf {
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 );
ssize_t iobuf_write( int fd, struct iobuf* iobuf ); ssize_t iobuf_write( int fd, struct iobuf* iobuf );
#include <inttypes.h>
struct iommap {
char *buf;
char *mmap_buf;
uint64_t mmap_len;
};
struct iommap *iommap_alloc(int fd, off64_t from, uint64_t len);
void iommap_sync(struct iommap *im);
void iommap_free(struct iommap *im);
#include "serve.h" #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 /** Scan the file opened in ''fd'', set bits in ''allocation_map'' that

View File

@@ -118,6 +118,7 @@ void write_not_zeroes(struct client* client, uint64_t from, uint64_t len)
*/ */
uint64_t run = bitset_run_count(map, from, len); uint64_t run = bitset_run_count(map, from, len);
struct iommap *iommap = iommap_alloc(client->fileno, 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);
@@ -155,7 +156,7 @@ void write_not_zeroes(struct client* client, uint64_t from, uint64_t 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 */
DO_READ(client->mapped + from, run); DO_READ(iommap->buf, run);
/* We know from our earlier call to bitset_run_count that the /* 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 * 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 * sake of the event stream - the actual bytes have changed, and we
@@ -186,7 +187,7 @@ void write_not_zeroes(struct client* client, uint64_t from, uint64_t len)
(0 == memcmp( zerobuffer, zerobuffer+1, blockrun-1 )); (0 == memcmp( zerobuffer, zerobuffer+1, blockrun-1 ));
if ( !all_zeros ) { if ( !all_zeros ) {
memcpy(client->mapped+from, zerobuffer, blockrun); memcpy(iommap->buf, zerobuffer, blockrun);
bitset_set_range(map, from, blockrun); bitset_set_range(map, from, blockrun);
/* 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
@@ -205,6 +206,8 @@ void write_not_zeroes(struct client* client, uint64_t from, uint64_t len)
from += blockrun; from += blockrun;
} }
} }
iommap_sync(iommap);
iommap_free(iommap);
} }
} }
@@ -449,22 +452,28 @@ void client_reply_to_read( struct client* client, struct nbd_request request )
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); debug("request write from=%"PRIu64", len=%"PRIu32", handle=0x%08X", request.from, request.len, request.handle);
if (client->serve->allocation_map_built) { // TODO: Just write directly for now. Not (yet) convinced my changes later on work.
// if (client->serve->allocation_map_built) {
if (0) {
write_not_zeroes( client, request.from, request.len ); write_not_zeroes( client, request.from, request.len );
} }
else { else {
debug("No allocation map, writing directly."); debug("No allocation map, writing directly.");
/* If we get cut off partway through reading this data: /* If we get cut off partway through reading this data:
* */ * */
struct iommap *iommap = iommap_alloc(client->fileno, request.from, request.len);
ERROR_IF_NEGATIVE( ERROR_IF_NEGATIVE(
readloop( client->socket, readloop( client->socket,
client->mapped + request.from, iommap->buf,
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
); );
iommap_sync(iommap);
iommap_free(iommap);
/* the allocation_map is shared between client threads, and may be /* 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 * being built. We need to reflect the write in it, as it may be in
* a position the builder has already gone over. * a position the builder has already gone over.
@@ -472,19 +481,6 @@ void client_reply_to_write( struct client* client, struct nbd_request request )
bitset_set_range(client->serve->allocation_map, request.from, request.len); bitset_set_range(client->serve->allocation_map, request.from, request.len);
} }
if (1) /* not sure whether this is necessary... */
{
/* multiple of 4K page size */
uint64_t from_rounded = request.from & (!0xfff);
uint64_t len_rounded = request.len + (request.from - 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); client_write_reply( client, &request, 0);
} }
@@ -650,9 +646,6 @@ void client_cleanup(struct client* client,
debug("Closed client socket fd %d", client->socket); debug("Closed client socket fd %d", client->socket);
client->socket = -1; client->socket = -1;
} }
if (client->mapped) {
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",
@@ -668,25 +661,20 @@ 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;
void** a = NULL;
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 a
), ),
"Couldn't open/mmap file %s: %s", client->serve->filename, strerror( errno ) "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 )
);
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);

View File

@@ -29,7 +29,6 @@ struct client {
int socket; int socket;
int fileno; int fileno;
char* mapped;
struct self_pipe * stop_signal; struct self_pipe * stop_signal;