forked from vitalif/vitastor
Fix incorrect parity read-modify-write calculation when writing into a lost chunk
parent
baaf8f6f44
commit
3237014608
|
@ -677,11 +677,11 @@ void* calc_rmw(void *request_buf, osd_rmw_stripe_t *stripes, uint64_t *read_osd_
|
||||||
static void get_old_new_buffers(osd_rmw_stripe_t & stripe, uint32_t wr_start, uint32_t wr_end, buf_len_t *bufs, int & nbufs)
|
static void get_old_new_buffers(osd_rmw_stripe_t & stripe, uint32_t wr_start, uint32_t wr_end, buf_len_t *bufs, int & nbufs)
|
||||||
{
|
{
|
||||||
uint32_t ns = 0, ne = 0, os = 0, oe = 0;
|
uint32_t ns = 0, ne = 0, os = 0, oe = 0;
|
||||||
if (stripe.req_end > wr_start &&
|
if (stripe.write_end > wr_start &&
|
||||||
stripe.req_start < wr_end)
|
stripe.write_start < wr_end)
|
||||||
{
|
{
|
||||||
ns = std::max(stripe.req_start, wr_start);
|
ns = std::max(stripe.write_start, wr_start);
|
||||||
ne = std::min(stripe.req_end, wr_end);
|
ne = std::min(stripe.write_end, wr_end);
|
||||||
}
|
}
|
||||||
if (stripe.read_end > wr_start &&
|
if (stripe.read_end > wr_start &&
|
||||||
stripe.read_start < wr_end)
|
stripe.read_start < wr_end)
|
||||||
|
@ -692,7 +692,7 @@ static void get_old_new_buffers(osd_rmw_stripe_t & stripe, uint32_t wr_start, ui
|
||||||
if (ne && (!oe || ns <= os))
|
if (ne && (!oe || ns <= os))
|
||||||
{
|
{
|
||||||
// NEW or NEW->OLD
|
// NEW or NEW->OLD
|
||||||
bufs[nbufs++] = { .buf = (uint8_t*)stripe.write_buf + ns - stripe.req_start, .len = ne-ns };
|
bufs[nbufs++] = { .buf = (uint8_t*)stripe.write_buf + ns - stripe.write_start, .len = ne-ns };
|
||||||
if (os < ne)
|
if (os < ne)
|
||||||
os = ne;
|
os = ne;
|
||||||
if (oe > os)
|
if (oe > os)
|
||||||
|
@ -708,7 +708,7 @@ static void get_old_new_buffers(osd_rmw_stripe_t & stripe, uint32_t wr_start, ui
|
||||||
{
|
{
|
||||||
// OLD->NEW or OLD->NEW->OLD
|
// OLD->NEW or OLD->NEW->OLD
|
||||||
bufs[nbufs++] = { .buf = (uint8_t*)stripe.read_buf + os - stripe.read_start, .len = ns-os };
|
bufs[nbufs++] = { .buf = (uint8_t*)stripe.read_buf + os - stripe.read_start, .len = ns-os };
|
||||||
bufs[nbufs++] = { .buf = (uint8_t*)stripe.write_buf + ns - stripe.req_start, .len = ne-ns };
|
bufs[nbufs++] = { .buf = (uint8_t*)stripe.write_buf + ns - stripe.write_start, .len = ne-ns };
|
||||||
if (oe > ne)
|
if (oe > ne)
|
||||||
{
|
{
|
||||||
// OLD->NEW->OLD
|
// OLD->NEW->OLD
|
||||||
|
|
|
@ -17,6 +17,7 @@ void test4();
|
||||||
void test5();
|
void test5();
|
||||||
void test6();
|
void test6();
|
||||||
void test7();
|
void test7();
|
||||||
|
void test_rmw_4k_degraded_into_lost_to_normal(bool ec);
|
||||||
void test8();
|
void test8();
|
||||||
void test9();
|
void test9();
|
||||||
void test10();
|
void test10();
|
||||||
|
@ -39,6 +40,8 @@ int main(int narg, char *args[])
|
||||||
test6();
|
test6();
|
||||||
// Test 7
|
// Test 7
|
||||||
test7();
|
test7();
|
||||||
|
test_rmw_4k_degraded_into_lost_to_normal(false);
|
||||||
|
test_rmw_4k_degraded_into_lost_to_normal(true);
|
||||||
// Test 8
|
// Test 8
|
||||||
test8();
|
test8();
|
||||||
// Test 9
|
// Test 9
|
||||||
|
@ -316,6 +319,69 @@ void test7()
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
|
||||||
|
7/2. calc_rmw(offset=48K, len=4K, osd_set=[0,2,3], write_set=[1,2,3])
|
||||||
|
= {
|
||||||
|
read: [ [ 0, 128K ], [ 0, 128K ], [ 0, 128K ] ],
|
||||||
|
write: [ [ 48K, 52K ], [ 0, 0 ], [ 48K, 52K ] ],
|
||||||
|
input buffer: [ write0 ],
|
||||||
|
rmw buffer: [ write2, read0, read1, read2 ],
|
||||||
|
}
|
||||||
|
then, after calc_rmw_parity_xor/ec(): {
|
||||||
|
write: [ [ 0, 128K ], [ 0, 0 ], [ 48K, 52K ] ],
|
||||||
|
write0==read0,
|
||||||
|
}
|
||||||
|
+ check write0, write2 buffers
|
||||||
|
|
||||||
|
***/
|
||||||
|
|
||||||
|
void test_rmw_4k_degraded_into_lost_to_normal(bool ec)
|
||||||
|
{
|
||||||
|
osd_num_t osd_set[3] = { 0, 2, 3 };
|
||||||
|
osd_num_t write_osd_set[3] = { 1, 2, 3 };
|
||||||
|
osd_rmw_stripe_t stripes[3] = {};
|
||||||
|
// Subtest 1
|
||||||
|
split_stripes(2, 128*1024, 48*1024, 4096, stripes);
|
||||||
|
void *write_buf = malloc(4096);
|
||||||
|
void *rmw_buf = calc_rmw(write_buf, stripes, osd_set, 3, 2, 3, write_osd_set, 128*1024, 0);
|
||||||
|
assert(stripes[0].read_start == 0 && stripes[0].read_end == 128*1024);
|
||||||
|
assert(stripes[1].read_start == 0 && stripes[1].read_end == 128*1024);
|
||||||
|
assert(stripes[2].read_start == 0 && stripes[2].read_end == 128*1024);
|
||||||
|
assert(stripes[0].write_start == 48*1024 && stripes[0].write_end == 52*1024);
|
||||||
|
assert(stripes[1].write_start == 0 && stripes[1].write_end == 0);
|
||||||
|
assert(stripes[2].write_start == 48*1024 && stripes[2].write_end == 52*1024);
|
||||||
|
assert(stripes[0].read_buf == (uint8_t*)rmw_buf+4*1024);
|
||||||
|
assert(stripes[1].read_buf == (uint8_t*)rmw_buf+4*1024+128*1024);
|
||||||
|
assert(stripes[2].read_buf == (uint8_t*)rmw_buf+4*1024+2*128*1024);
|
||||||
|
assert(stripes[0].write_buf == write_buf);
|
||||||
|
assert(stripes[1].write_buf == NULL);
|
||||||
|
assert(stripes[2].write_buf == rmw_buf);
|
||||||
|
// Subtest 2
|
||||||
|
set_pattern(write_buf, 4096, PATTERN2);
|
||||||
|
set_pattern(stripes[1].read_buf, 128*1024, PATTERN1);
|
||||||
|
set_pattern(stripes[2].read_buf, 128*1024, PATTERN0^PATTERN1);
|
||||||
|
if (!ec)
|
||||||
|
calc_rmw_parity_xor(stripes, 3, osd_set, write_osd_set, 128*1024, 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
use_ec(3, 2, true);
|
||||||
|
calc_rmw_parity_ec(stripes, 3, 2, osd_set, write_osd_set, 128*1024, 0);
|
||||||
|
use_ec(3, 2, false);
|
||||||
|
}
|
||||||
|
assert(stripes[0].write_start == 0 && stripes[0].write_end == 128*1024);
|
||||||
|
assert(stripes[1].write_start == 0 && stripes[1].write_end == 0);
|
||||||
|
assert(stripes[2].write_start == 48*1024 && stripes[2].write_end == 52*1024);
|
||||||
|
assert(stripes[0].write_buf == stripes[0].read_buf);
|
||||||
|
assert(stripes[1].write_buf == NULL);
|
||||||
|
assert(stripes[2].write_buf == rmw_buf);
|
||||||
|
check_pattern(stripes[0].write_buf, 4096, PATTERN0);
|
||||||
|
check_pattern(stripes[0].write_buf+48*1024, 4096, PATTERN2);
|
||||||
|
check_pattern(stripes[2].write_buf, 4096, PATTERN2^PATTERN1); // new parity
|
||||||
|
free(rmw_buf);
|
||||||
|
free(write_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
|
||||||
8. calc_rmw(offset=0, len=128K+4K, osd_set=[0,2,3], write_set=[1,2,3])
|
8. calc_rmw(offset=0, len=128K+4K, osd_set=[0,2,3], write_set=[1,2,3])
|
||||||
= {
|
= {
|
||||||
read: [ [ 0, 0 ], [ 4K, 128K ], [ 0, 0 ] ],
|
read: [ [ 0, 0 ], [ 4K, 128K ], [ 0, 0 ] ],
|
||||||
|
|
Loading…
Reference in New Issue