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

@@ -12,6 +12,11 @@ else
CFLAGS_EXTRA=-O2
endif
NO_MSYNC=1
ifdef NO_MSYNC
CFLAGS_EXTRA += -DNO_MSYNC
endif
CFLAGS_EXTRA += -fPIC --std=gnu99
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;
}
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;
}
if (out_map) {
if (0) {
*out_map = mmap64(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
*out_fd, 0);
if (((long) *out_map) == -1) {
@@ -349,3 +348,36 @@ ssize_t iobuf_write( int fd, struct iobuf *iobuf )
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_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"
struct bitset; /* don't need whole of bitset.h here */
/** 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);
struct iommap *iommap = iommap_alloc(client->fileno, from, len);
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)) {
debug("writing the lot: from=%ld, run=%d", from, run);
/* 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
* 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
@@ -186,7 +187,7 @@ void write_not_zeroes(struct client* client, uint64_t from, uint64_t len)
(0 == memcmp( zerobuffer, zerobuffer+1, blockrun-1 ));
if ( !all_zeros ) {
memcpy(client->mapped+from, zerobuffer, blockrun);
memcpy(iommap->buf, zerobuffer, blockrun);
bitset_set_range(map, from, blockrun);
/* at this point we could choose to
* 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;
}
}
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 )
{
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 );
}
else {
debug("No allocation map, writing directly.");
/* If we get cut off partway through reading this data:
* */
struct iommap *iommap = iommap_alloc(client->fileno, request.from, request.len);
ERROR_IF_NEGATIVE(
readloop( client->socket,
client->mapped + request.from,
iommap->buf,
request.len),
"reading write data failed from=%ld, len=%d",
request.from,
request.len
);
iommap_sync(iommap);
iommap_free(iommap);
/* 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.
@@ -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);
}
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);
}
@@ -650,9 +646,6 @@ void client_cleanup(struct client* client,
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",
@@ -668,25 +661,20 @@ void client_cleanup(struct client* client,
void* client_serve(void* client_uncast)
{
struct client* client = (struct client*) client_uncast;
void** a = NULL;
error_set_handler((cleanup_handler*) client_cleanup, client);
info("client: mmaping file");
FATAL_IF_NEGATIVE(
open_and_mmap(
client->serve->filename,
&client->fileno,
NULL,
(void**) &client->mapped
a
),
"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("client: sending hello");
client_send_hello(client);

View File

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