osd: account for key_index_bytes when calculating chained read bitmap_len #89
@@ -586,9 +586,10 @@ void osd_t::send_chained_read_results(pg_t *pg, osd_op_t *cur_op)
|
||||
// Send bitmap
|
||||
cur_op->bitmap = op_data->stripes[0].bmp_buf;
|
||||
cur_op->reply.rw.bitmap_len = (pg ? pg->pg_data_size : 1) * clean_entry_bitmap_size;
|
||||
size_t key_index_bytes = osd_op_rw_t::chain_info_bytes(op_data->chain_size);
|
||||
if (cur_op->req.rw.flags & OSD_OP_RETURN_CHAIN)
|
||||
{
|
||||
cur_op->reply.rw.bitmap_len += (cur_op->req.rw.len / bs_bitmap_granularity);
|
||||
cur_op->reply.rw.bitmap_len += key_index_bytes * (cur_op->req.rw.len / bs_bitmap_granularity);
|
||||
}
|
||||
// And finally compose the result
|
||||
uint64_t sent = 0;
|
||||
@@ -597,7 +598,6 @@ void osd_t::send_chained_read_results(pg_t *pg, osd_op_t *cur_op)
|
||||
int prev = (cur_op->req.rw.offset - op_data->oid.stripe) / bs_bitmap_granularity;
|
||||
int end = prev + cur_op->req.rw.len/bs_bitmap_granularity;
|
||||
int cur = prev;
|
||||
size_t key_index_bytes = osd_op_rw_t::chain_info_bytes(op_data->chain_size);
|
||||
while (cur <= end)
|
||||
{
|
||||
bool has_bit = false;
|
||||
|
||||
@@ -455,7 +455,7 @@ void test_ec33_scrub_only_first_part()
|
||||
for (int i = 0; i < 6; i++)
|
||||
stripes[i].bmp_buf = bmp_buf.data() + i*4;
|
||||
split_stripes(3, 128*1024, 0, 128*1024, stripes);
|
||||
void *rmw_buf = calc_rmw(data_buf.data(), stripes, fake_osd_set, 6, 3, 6, fake_osd_set, 128*1024, 4);
|
||||
uint8_t *rmw_buf = (uint8_t*)calc_rmw(data_buf.data(), stripes, fake_osd_set, 6, 3, 6, fake_osd_set, 128*1024, 4);
|
||||
assert(rmw_buf);
|
||||
calc_rmw_parity_ec(stripes, 6, 3, fake_osd_set, fake_osd_set, 128*1024, 4);
|
||||
use_ec(6, 3, false);
|
||||
@@ -1124,6 +1124,71 @@ void test_chained_read_eio_retry()
|
||||
printf("test_chained_read_eio_retry passed\n");
|
||||
}
|
||||
|
||||
void test_chained_read_large_chain_info()
|
||||
{
|
||||
printf("test_chained_read_large_chain_info\n");
|
||||
|
||||
osd_test_fixture_t f;
|
||||
f.configure_replicated_pool(1, 2, 1, 1, { { 1, 2 } });
|
||||
|
||||
// Build 300-layer snapshot chain in pool 1:
|
||||
// Inode 1 (root) <- Inode 2 <- ... <- Inode 300 (leaf)
|
||||
const int NUM_SNAPS = 300;
|
||||
for (int i = 1; i <= NUM_SNAPS; i++)
|
||||
{
|
||||
json11::Json::object obj;
|
||||
if (i > 1)
|
||||
obj["parent_id"] = i - 1;
|
||||
f.st_cli->set("/vitastor/config/inode/1/" + std::to_string(i), obj);
|
||||
}
|
||||
|
||||
f.start(json11::Json::object {
|
||||
{ "osd_num", 1 },
|
||||
{ "etcd_address", "127.0.0.1:2379" },
|
||||
{ "immediate_commit", "none" },
|
||||
{ "block_size", 131072 },
|
||||
{ "bitmap_granularity", 4096 },
|
||||
});
|
||||
f.connect_peer(2);
|
||||
f.complete_peering_empty();
|
||||
assert(f.pg(1, 1).state == PG_ACTIVE);
|
||||
|
||||
uint64_t client_id = f.connect_client();
|
||||
|
||||
inode_t leaf_inode = INODE_WITH_POOL(1, NUM_SNAPS);
|
||||
uint64_t meta_rev = f.st_cli->inode_config.at(leaf_inode).mod_revision;
|
||||
|
||||
auto *read_op = new osd_op_t();
|
||||
read_op->op_type = OSD_OP_IN;
|
||||
read_op->client_id = client_id;
|
||||
read_op->req.rw.header.magic = SECONDARY_OSD_OP_MAGIC;
|
||||
read_op->req.rw.header.id = 1;
|
||||
read_op->req.rw.header.opcode = OSD_OP_READ;
|
||||
read_op->req.rw.inode = leaf_inode;
|
||||
read_op->req.rw.offset = 0;
|
||||
read_op->req.rw.len = 128 * 1024;
|
||||
read_op->req.rw.meta_revision = meta_rev;
|
||||
read_op->req.rw.flags = OSD_OP_RETURN_CHAIN;
|
||||
|
||||
f.exec(read_op);
|
||||
|
||||
// Verify op completed and replied to client
|
||||
assert(f.client(client_id)->sent_ops.count(read_op->req.hdr.id) == 1);
|
||||
auto *reply_op = f.client(client_id)->sent_ops.at(read_op->req.hdr.id);
|
||||
assert(reply_op == read_op);
|
||||
assert(reply_op->reply.hdr.retval == (int64_t)read_op->req.rw.len);
|
||||
|
||||
// Replicated pool clean_entry_bitmap_size = 131072 / 4096 / 8 = 4 bytes
|
||||
// For chain_size = 300, key_index_bytes = osd_op_rw_t::chain_info_bytes(300) = 2
|
||||
// 32 blocks (128k / 4k) * 2 bytes = 64 bytes of chain_info
|
||||
// Total bitmap_len must be 4 + 64 = 68 bytes.
|
||||
// If osd_primary_chain.cpp missed multiplying key_index_bytes, bitmap_len would be 4 + 32 = 36.
|
||||
assert(reply_op->reply.rw.bitmap_len == 68);
|
||||
|
||||
printf("test_chained_read_large_chain_info passed\n");
|
||||
}
|
||||
|
||||
|
||||
// A degraded EC read may leave its parity read ranges behind when the object state
|
||||
// changes under the operation (recovery brings a chunk back while subops are in flight)
|
||||
// and a failed subop retries the whole read. The retry then takes the fast path, which
|
||||
@@ -2707,5 +2772,6 @@ int main(int narg, char *args[])
|
||||
test_peering_outdated_copy_other_role();
|
||||
test_pg_epoch_base_is_reported_epoch();
|
||||
test_pg_epoch_bump_above_reported_epoch();
|
||||
test_chained_read_large_chain_info();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user