flexnbd: Avoid a SIGSEGV when the allocation map fails to build.

In the event of a fiemap ioctl failing (when the file is on a tmpfs,
for instance), we would free() serve->allocation_map, but it would
remain not NULL, leading to segfaults in client.c when responding to
write requests.

Keeping the free() behaviour is more hassle than it's worth, as there
are synchronization problems with setting serve->allocation_map to
NULL, so we just omit the free() instead to avoid the segfault. This
is safe because we never consult the map until allocation_map_built is
set to true, and we never do that when the builder thread fails.
This commit is contained in:
nick
2013-02-08 16:17:16 +00:00
parent 2dd3db95bc
commit 8c04564645
3 changed files with 20 additions and 21 deletions

View File

@@ -29,7 +29,7 @@ int build_allocation_map(struct bitset_mapping* allocation_map, int fd)
memset(&fiemap_static, 0, sizeof(fiemap_static));
for (offset = 0; offset < allocation_map->size; ) {
unsigned int i;
fiemap->fm_start = offset;
@@ -45,9 +45,7 @@ int build_allocation_map(struct bitset_mapping* allocation_map, int fd)
if ( ioctl( fd, FS_IOC_FIEMAP, fiemap ) < 0 ) {
debug( "Couldn't get fiemap, returning no allocation_map" );
free(allocation_map);
allocation_map = NULL;
break;
return 0; /* it's up to the caller to free the map */
}
else {
for ( i = 0; i < fiemap->fm_mapped_extents; i++ ) {
@@ -55,9 +53,9 @@ int build_allocation_map(struct bitset_mapping* allocation_map, int fd)
fiemap->fm_extents[i].fe_logical,
fiemap->fm_extents[i].fe_length );
}
/* must move the offset on, but careful not to jump max_length
/* must move the offset on, but careful not to jump max_length
* if we've actually hit max_offsets.
*/
if (fiemap->fm_mapped_extents > 0) {
@@ -73,7 +71,7 @@ int build_allocation_map(struct bitset_mapping* allocation_map, int fd)
}
debug("Successfully built allocation map");
return NULL != allocation_map;
return 1;
}