Error when reading sent data fails
If the client cuts off part-way through the write, it should cause an error, not a fatal. Previously this happened if the open file had a fiemap, but not if there was no allocation map. This patch fixes that, along with an associated valgrind error.
This commit is contained in:
26
src/client.c
26
src/client.c
@@ -387,26 +387,28 @@ void client_reply_to_write( struct client* client, struct nbd_request request )
|
|||||||
write_not_zeroes( client, request.from, request.len );
|
write_not_zeroes( client, request.from, request.len );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FATAL_IF_NEGATIVE(
|
debug("No allocation map, writing directly.");
|
||||||
readloop(
|
/* If we get cut off partway through reading this data
|
||||||
client->socket,
|
* */
|
||||||
client->mapped + request.from,
|
ERROR_IF_NEGATIVE(
|
||||||
request.len),
|
readloop( client->socket,
|
||||||
"read failed from=%ld, len=%d",
|
client->mapped + request.from,
|
||||||
request.from,
|
request.len),
|
||||||
request.len );
|
"reading write data failed from=%ld, len=%d",
|
||||||
|
request.from,
|
||||||
|
request.len
|
||||||
|
);
|
||||||
server_dirty(client->serve, request.from, request.len);
|
server_dirty(client->serve, request.from, request.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1) /* not sure whether this is necessary... */
|
if (1) /* not sure whether this is necessary... */
|
||||||
{
|
{
|
||||||
/* multiple of 4K page size */
|
/* 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);
|
uint64_t len_rounded = request.len + (request.from - from_rounded);
|
||||||
|
|
||||||
FATAL_IF_NEGATIVE(
|
FATAL_IF_NEGATIVE(
|
||||||
msync(
|
msync( client->mapped + from_rounded,
|
||||||
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
|
||||||
|
39
src/ioutil.c
39
src/ioutil.c
@@ -15,7 +15,7 @@ struct bitset_mapping* build_allocation_map(int fd, uint64_t size, int resolutio
|
|||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct bitset_mapping* allocation_map = bitset_alloc(size, resolution);
|
struct bitset_mapping* allocation_map = bitset_alloc(size, resolution);
|
||||||
struct fiemap *fiemap_count, *fiemap;
|
struct fiemap *fiemap_count = NULL, *fiemap = NULL;
|
||||||
|
|
||||||
fiemap_count = (struct fiemap*) xmalloc(sizeof(struct fiemap));
|
fiemap_count = (struct fiemap*) xmalloc(sizeof(struct fiemap));
|
||||||
|
|
||||||
@@ -27,17 +27,18 @@ struct bitset_mapping* build_allocation_map(int fd, uint64_t size, int resolutio
|
|||||||
|
|
||||||
/* Find out how many extents there are */
|
/* Find out how many extents there are */
|
||||||
if (ioctl(fd, FS_IOC_FIEMAP, fiemap_count) < 0) {
|
if (ioctl(fd, FS_IOC_FIEMAP, fiemap_count) < 0) {
|
||||||
return NULL;
|
debug( "Couldn't get fiemap_count, returning no allocation_map" );
|
||||||
|
goto no_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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));
|
||||||
free( fiemap_count );
|
free( fiemap_count );
|
||||||
@@ -45,7 +46,10 @@ 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) { return NULL; }
|
if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) {
|
||||||
|
debug( "Couldn't get fiemap, returning no allocation_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(
|
||||||
@@ -54,7 +58,7 @@ struct bitset_mapping* build_allocation_map(int fd, uint64_t size, int resolutio
|
|||||||
fiemap->fm_extents[i].fe_length
|
fiemap->fm_extents[i].fe_length
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is pointlessly verbose for real discs, it's here as a
|
/* This is pointlessly verbose for real discs, it's here as a
|
||||||
* reference for pulling data out of the allocation map */
|
* reference for pulling data out of the allocation map */
|
||||||
if ( 0 ) {
|
if ( 0 ) {
|
||||||
@@ -72,13 +76,22 @@ struct bitset_mapping* build_allocation_map(int fd, uint64_t size, int resolutio
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
free(fiemap);
|
free(fiemap);
|
||||||
|
|
||||||
|
debug("Successfully built allocation map");
|
||||||
return allocation_map;
|
return allocation_map;
|
||||||
|
|
||||||
|
no_map:
|
||||||
|
fprintf(stderr, "Freeing");
|
||||||
|
free( allocation_map );
|
||||||
|
if ( NULL != fiemap ) { free( fiemap ); }
|
||||||
|
if ( NULL != fiemap_count ) { free( fiemap_count ); }
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
|
Reference in New Issue
Block a user