Compare commits
3 Commits
master
...
change-mma
Author | SHA1 | Date | |
---|---|---|---|
![]() |
29306a716e | ||
![]() |
0ba90b39a3 | ||
![]() |
7f98f6ef9e |
7
Makefile
7
Makefile
@@ -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)
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user