Enable writing after the 2G boundary
This patch fixes a bug in readwrite.c which truncated the 'from' field in nbd requests. It was casting them down from an off64_t to an int.
This commit is contained in:
10
src/client.c
10
src/client.c
@@ -136,7 +136,6 @@ void write_not_zeroes(struct client* client, uint64_t from, int len)
|
|||||||
*/
|
*/
|
||||||
if (zerobuffer[0] != 0 ||
|
if (zerobuffer[0] != 0 ||
|
||||||
memcmp(zerobuffer, zerobuffer + 1, blockrun - 1)) {
|
memcmp(zerobuffer, zerobuffer + 1, blockrun - 1)) {
|
||||||
debug("non-zero, writing from=%ld, blockrun=%d", from, blockrun);
|
|
||||||
memcpy(client->mapped+from, zerobuffer, blockrun);
|
memcpy(client->mapped+from, zerobuffer, blockrun);
|
||||||
bitset_set_range(map, from, blockrun);
|
bitset_set_range(map, from, blockrun);
|
||||||
server_dirty(client->serve, from, blockrun);
|
server_dirty(client->serve, from, blockrun);
|
||||||
@@ -147,9 +146,7 @@ void write_not_zeroes(struct client* client, uint64_t from, int len)
|
|||||||
* sparseness as possible.
|
* sparseness as possible.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
debug("all zero, skip write");
|
|
||||||
}
|
|
||||||
len -= blockrun;
|
len -= blockrun;
|
||||||
run -= blockrun;
|
run -= blockrun;
|
||||||
from += blockrun;
|
from += blockrun;
|
||||||
@@ -164,6 +161,7 @@ int fd_read_request( int fd, struct nbd_request_raw *out_request)
|
|||||||
return readloop(fd, out_request, sizeof(struct nbd_request_raw));
|
return readloop(fd, out_request, sizeof(struct nbd_request_raw));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Returns 1 if *request was filled with a valid request which we should
|
/* Returns 1 if *request was filled with a valid request which we should
|
||||||
* try to honour. 0 otherwise. */
|
* try to honour. 0 otherwise. */
|
||||||
int client_read_request( struct client * client , struct nbd_request *out_request, int * disconnected )
|
int client_read_request( struct client * client , struct nbd_request *out_request, int * disconnected )
|
||||||
@@ -318,7 +316,7 @@ int client_request_needs_reply( struct client * client,
|
|||||||
"after an entrust message.");
|
"after an entrust message.");
|
||||||
/* check it's not out of range */
|
/* check it's not out of range */
|
||||||
if ( request.from+request.len > client->serve->size) {
|
if ( request.from+request.len > client->serve->size) {
|
||||||
debug("request read %ld+%d out of range",
|
debug("request read %llx+%ld out of range",
|
||||||
request.from,
|
request.from,
|
||||||
request.len
|
request.len
|
||||||
);
|
);
|
||||||
@@ -495,7 +493,7 @@ void* client_serve(void* client_uncast)
|
|||||||
NULL,
|
NULL,
|
||||||
(void**) &client->mapped
|
(void**) &client->mapped
|
||||||
),
|
),
|
||||||
"Couldn't open/mmap file %s", client->serve->filename
|
"Couldn't open/mmap file %s: %s", client->serve->filename, strerror( errno )
|
||||||
);
|
);
|
||||||
debug("client: sending hello");
|
debug("client: sending hello");
|
||||||
client_send_hello(client);
|
client_send_hello(client);
|
||||||
|
@@ -55,6 +55,9 @@ struct bitset_mapping* build_allocation_map(int fd, uint64_t size, int resolutio
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is pointlessly verbose for real discs, it's here as a
|
||||||
|
* reference for pulling data out of the allocation map */
|
||||||
|
if ( 0 ) {
|
||||||
for (i=0; i<(size/resolution); i++) {
|
for (i=0; i<(size/resolution); 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,
|
||||||
@@ -68,6 +71,7 @@ struct bitset_mapping* build_allocation_map(int fd, uint64_t size, int resolutio
|
|||||||
(allocation_map->bits[i] & 128) == 128
|
(allocation_map->bits[i] & 128) == 128
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
free(fiemap);
|
free(fiemap);
|
||||||
|
@@ -56,7 +56,7 @@ fail:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_request(struct nbd_request *request, int type, int from, int len)
|
void fill_request(struct nbd_request *request, int type, off64_t from, int len)
|
||||||
{
|
{
|
||||||
request->magic = htobe32(REQUEST_MAGIC);
|
request->magic = htobe32(REQUEST_MAGIC);
|
||||||
request->type = htobe32(type);
|
request->type = htobe32(type);
|
||||||
|
@@ -79,6 +79,10 @@ class Environment
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def truncate1( size )
|
||||||
|
system "truncate -s #{size} #{@filename1}"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def listening_ports
|
def listening_ports
|
||||||
`netstat -ltn`.
|
`netstat -ltn`.
|
||||||
|
@@ -81,4 +81,15 @@ class TestHappyPath < Test::Unit::TestCase
|
|||||||
assert @env.status2['has_control'], "destination didn't take control"
|
assert @env.status2['has_control'], "destination didn't take control"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def test_write_to_high_block
|
||||||
|
# Create a large file, then try to write to somewhere after the 2G boundary
|
||||||
|
@env.truncate1 "4G"
|
||||||
|
@env.serve1
|
||||||
|
|
||||||
|
@env.nbd1.write( 2**31+2**29, "12345678" )
|
||||||
|
sleep(1)
|
||||||
|
assert_equal "12345678", @env.nbd1.read( 2**31+2**29, 8 )
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@@ -182,6 +182,24 @@ START_TEST(test_reply_handle)
|
|||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
|
START_TEST( test_convert_from )
|
||||||
|
{
|
||||||
|
/* Check that we can correctly pull numbers out of an
|
||||||
|
* nbd_request_raw */
|
||||||
|
struct nbd_request_raw request_raw;
|
||||||
|
struct nbd_request request;
|
||||||
|
char readbuf[] = {0x80, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
memcpy( &request_raw.from, readbuf, 8 );
|
||||||
|
|
||||||
|
nbd_r2h_request( &request_raw, &request );
|
||||||
|
|
||||||
|
uint64_t target = 1;
|
||||||
|
target <<= 63;
|
||||||
|
fail_unless( target == request.from, "from was wrong" );
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
Suite *nbdtypes_suite(void)
|
Suite *nbdtypes_suite(void)
|
||||||
{
|
{
|
||||||
Suite *s = suite_create( "nbdtypes" );
|
Suite *s = suite_create( "nbdtypes" );
|
||||||
@@ -197,6 +215,7 @@ Suite *nbdtypes_suite(void)
|
|||||||
tcase_add_test( tc_request, test_request_handle );
|
tcase_add_test( tc_request, test_request_handle );
|
||||||
tcase_add_test( tc_request, test_request_from );
|
tcase_add_test( tc_request, test_request_from );
|
||||||
tcase_add_test( tc_request, test_request_len );
|
tcase_add_test( tc_request, test_request_len );
|
||||||
|
tcase_add_test( tc_request, test_convert_from );
|
||||||
tcase_add_test( tc_reply, test_reply_magic );
|
tcase_add_test( tc_reply, test_reply_magic );
|
||||||
tcase_add_test( tc_reply, test_reply_error );
|
tcase_add_test( tc_reply, test_reply_error );
|
||||||
tcase_add_test( tc_reply, test_reply_handle );
|
tcase_add_test( tc_reply, test_reply_handle );
|
||||||
|
Reference in New Issue
Block a user