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:
Alex Young
2012-07-14 12:10:12 +01:00
parent c6e6952def
commit 1ce1003d3d
2 changed files with 40 additions and 25 deletions

View File

@@ -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

View File

@@ -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;