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:
34
src/client.c
34
src/client.c
@@ -26,7 +26,7 @@
|
||||
*/
|
||||
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) {
|
||||
/* 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
|
||||
* 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;
|
||||
|
||||
int run = bitset_run_count(map, from, len);
|
||||
|
||||
if (run > len)
|
||||
debug("write_not_zeroes: from=%ld, len=%d, run=%d", from, len, run);
|
||||
|
||||
if (run > len) {
|
||||
run = len;
|
||||
|
||||
debug("write_not_zeroes: %ld+%d, first_bit=%d, last_bit=%d, run=%d",
|
||||
from, len, first_bit, last_bit, run);
|
||||
debug("(run adjusted to %d)", run);
|
||||
}
|
||||
|
||||
#define DO_READ(dst, len) CLIENT_ERROR_ON_FAILURE( \
|
||||
readloop( \
|
||||
@@ -57,8 +55,8 @@ void write_not_zeroes(struct client* client, off64_t from, int len)
|
||||
"read failed %ld+%d", from, (len) \
|
||||
)
|
||||
|
||||
if (bit_is_set(map, from/block_allocation_resolution)) {
|
||||
debug("writing the lot");
|
||||
if (bitset_is_set_at(map, from)) {
|
||||
debug("writing the lot: from=%ld, run=%d", from, run);
|
||||
/* already allocated, just write it all */
|
||||
DO_READ(client->mapped + 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];
|
||||
/* not allocated, read in block_allocation_resoution */
|
||||
while (run > 0) {
|
||||
char *dst = client->mapped+from;
|
||||
int bit = from/block_allocation_resolution;
|
||||
int blockrun = block_allocation_resolution -
|
||||
(from % block_allocation_resolution);
|
||||
if (blockrun > run)
|
||||
blockrun = run;
|
||||
|
||||
debug("writing partial: bit=%d, blockrun=%d (run=%d)",
|
||||
bit, blockrun, run);
|
||||
|
||||
DO_READ(zerobuffer, blockrun);
|
||||
|
||||
/* 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 ||
|
||||
memcmp(zerobuffer, zerobuffer + 1, blockrun - 1)) {
|
||||
memcpy(dst, zerobuffer, blockrun);
|
||||
bit_set(map, bit);
|
||||
memcpy(client->mapped+from, zerobuffer, blockrun);
|
||||
bitset_set_range(map, from, blockrun);
|
||||
server_dirty(client->serve, from, blockrun);
|
||||
debug("non-zero, copied and set bit %d", bit);
|
||||
/* at this point we could choose to
|
||||
* short-cut the rest of the write for
|
||||
* 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 )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
else {
|
||||
|
Reference in New Issue
Block a user