Refactored write_not_zeroes to use struct bitset_mapping instead of

repeating all that code (has not fixed earlier bug yet, but lots of
repetition cut).
This commit is contained in:
Matthew Bloch
2012-06-07 11:17:02 +01:00
parent 08f3d42b34
commit 5710431780
4 changed files with 32 additions and 43 deletions

View File

@@ -26,7 +26,7 @@
*/ */
void write_not_zeroes(struct client* client, off64_t from, int len) void write_not_zeroes(struct client* client, off64_t from, int len)
{ {
char *map = client->serve->block_allocation_map; struct bitset_mapping *map = client->serve->allocation_map;
while (len > 0) { while (len > 0) {
/* so we have to calculate how much of our input to consider /* so we have to calculate how much of our input to consider
@@ -36,17 +36,15 @@ void write_not_zeroes(struct client* client, off64_t from, int len)
* how many blocks our write covers, then cut off the start * how many blocks our write covers, then cut off the start
* and end to get the exact number of bytes. * and end to get the exact number of bytes.
*/ */
int first_bit = from/block_allocation_resolution;
int last_bit = (from+len+block_allocation_resolution-1) /
block_allocation_resolution;
int run = bit_run_count(map, first_bit, last_bit-first_bit) *
block_allocation_resolution;
if (run > len) int run = bitset_run_count(map, from, len);
debug("write_not_zeroes: from=%ld, len=%d, run=%d", from, len, run);
if (run > len) {
run = len; run = len;
debug("(run adjusted to %d)", run);
debug("write_not_zeroes: %ld+%d, first_bit=%d, last_bit=%d, run=%d", }
from, len, first_bit, last_bit, run);
#define DO_READ(dst, len) CLIENT_ERROR_ON_FAILURE( \ #define DO_READ(dst, len) CLIENT_ERROR_ON_FAILURE( \
readloop( \ readloop( \
@@ -57,8 +55,8 @@ void write_not_zeroes(struct client* client, off64_t from, int len)
"read failed %ld+%d", from, (len) \ "read failed %ld+%d", from, (len) \
) )
if (bit_is_set(map, from/block_allocation_resolution)) { if (bitset_is_set_at(map, from)) {
debug("writing the lot"); 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(client->mapped + from, run);
server_dirty(client->serve, from, run); server_dirty(client->serve, from, run);
@@ -69,16 +67,11 @@ void write_not_zeroes(struct client* client, off64_t from, int len)
char zerobuffer[block_allocation_resolution]; char zerobuffer[block_allocation_resolution];
/* not allocated, read in block_allocation_resoution */ /* not allocated, read in block_allocation_resoution */
while (run > 0) { while (run > 0) {
char *dst = client->mapped+from;
int bit = from/block_allocation_resolution;
int blockrun = block_allocation_resolution - int blockrun = block_allocation_resolution -
(from % block_allocation_resolution); (from % block_allocation_resolution);
if (blockrun > run) if (blockrun > run)
blockrun = run; blockrun = run;
debug("writing partial: bit=%d, blockrun=%d (run=%d)",
bit, blockrun, run);
DO_READ(zerobuffer, blockrun); DO_READ(zerobuffer, blockrun);
/* This reads the buffer twice in the worst case /* This reads the buffer twice in the worst case
@@ -88,10 +81,9 @@ void write_not_zeroes(struct client* client, off64_t from, int len)
*/ */
if (zerobuffer[0] != 0 || if (zerobuffer[0] != 0 ||
memcmp(zerobuffer, zerobuffer + 1, blockrun - 1)) { memcmp(zerobuffer, zerobuffer + 1, blockrun - 1)) {
memcpy(dst, zerobuffer, blockrun); memcpy(client->mapped+from, zerobuffer, blockrun);
bit_set(map, bit); bitset_set_range(map, from, blockrun);
server_dirty(client->serve, from, blockrun); server_dirty(client->serve, from, blockrun);
debug("non-zero, copied and set bit %d", bit);
/* 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
* faster I/O but by continuing to do it * faster I/O but by continuing to do it
@@ -247,7 +239,7 @@ 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 %ld+%d", request.from, request.len); debug("request write %ld+%d", request.from, request.len);
if (client->serve->block_allocation_map) { if (client->serve->allocation_map) {
write_not_zeroes( client, request.from, request.len ); write_not_zeroes( client, request.from, request.len );
} }
else { else {

View File

@@ -14,10 +14,10 @@
#include "util.h" #include "util.h"
#include "bitset.h" #include "bitset.h"
char* build_allocation_map(int fd, off64_t size, int resolution) struct bitset_mapping* build_allocation_map(int fd, off64_t size, int resolution)
{ {
int i; int i;
char *allocation_map = xmalloc((size+resolution)/resolution); struct bitset_mapping* allocation_map = bitset_alloc(size, resolution);
struct fiemap *fiemap_count, *fiemap; struct fiemap *fiemap_count, *fiemap;
fiemap_count = (struct fiemap*) xmalloc(sizeof(struct fiemap)); fiemap_count = (struct fiemap*) xmalloc(sizeof(struct fiemap));
@@ -49,27 +49,24 @@ char* build_allocation_map(int fd, off64_t size, int resolution)
if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0)
return NULL; return NULL;
for (i=0;i<fiemap->fm_mapped_extents;i++) { for (i=0;i<fiemap->fm_mapped_extents;i++)
int first_bit = fiemap->fm_extents[i].fe_logical / resolution; bitset_set_range(
int last_bit = (fiemap->fm_extents[i].fe_logical + allocation_map,
fiemap->fm_extents[i].fe_length + resolution - 1) / fiemap->fm_extents[i].fe_logical,
resolution; fiemap->fm_extents[i].fe_length
int run = last_bit - first_bit; );
bit_set_range(allocation_map, first_bit, run);
}
for (i=0; i<16; i++) { for (i=0; i<16; i++) {
debug("map[%d] = %d%d%d%d%d%d%d%d", debug("map[%d] = %d%d%d%d%d%d%d%d",
i, i,
(allocation_map[i] & 1) == 1, (allocation_map->bits[i] & 1) == 1,
(allocation_map[i] & 2) == 2, (allocation_map->bits[i] & 2) == 2,
(allocation_map[i] & 4) == 4, (allocation_map->bits[i] & 4) == 4,
(allocation_map[i] & 8) == 8, (allocation_map->bits[i] & 8) == 8,
(allocation_map[i] & 16) == 16, (allocation_map->bits[i] & 16) == 16,
(allocation_map[i] & 32) == 32, (allocation_map->bits[i] & 32) == 32,
(allocation_map[i] & 64) == 64, (allocation_map->bits[i] & 64) == 64,
(allocation_map[i] & 128) == 128 (allocation_map->bits[i] & 128) == 128
); );
} }

View File

@@ -305,7 +305,7 @@ void serve_init_allocation_map(struct server* params)
params->size = size; params->size = size;
SERVER_ERROR_ON_FAILURE(size, "Couldn't find size of %s", SERVER_ERROR_ON_FAILURE(size, "Couldn't find size of %s",
params->filename); params->filename);
params->block_allocation_map = params->allocation_map =
build_allocation_map(fd, size, block_allocation_resolution); build_allocation_map(fd, size, block_allocation_resolution);
close(fd); close(fd);
} }
@@ -336,7 +336,7 @@ void serve_cleanup(struct server* params)
self_pipe_destroy( params->close_signal ); self_pipe_destroy( params->close_signal );
free(params->block_allocation_map); free(params->allocation_map);
if (params->mirror) if (params->mirror)
debug("mirror thread running! this should not happen!"); debug("mirror thread running! this should not happen!");

View File

@@ -69,7 +69,7 @@ struct server {
int server_fd; int server_fd;
int control_fd; int control_fd;
char* block_allocation_map; struct bitset_mapping* allocation_map;
struct { pthread_t thread; union mysockaddr address; } struct { pthread_t thread; union mysockaddr address; }
nbd_client[MAX_NBD_CLIENTS]; nbd_client[MAX_NBD_CLIENTS];