Skip to content

Commit 36c3a2b

Browse files
Merge pull request ceph#61404 from JonBailey1993/JonBailey1993/ceph_test_rados_io_sequence_plugin_support
common/io_exerciser: ceph_test_rados_io_sequence plugin/profile support
2 parents dce8e3f + fd18489 commit 36c3a2b

19 files changed

+1576
-588
lines changed

src/common/io_exerciser/EcIoSequence.cc

Lines changed: 118 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "EcIoSequence.h"
22

3+
#include <algorithm>
34
#include <memory>
45

56
using IoOp = ceph::io_exerciser::IoOp;
@@ -11,7 +12,9 @@ using ReadInjectSequence = ceph::io_exerciser::ReadInjectSequence;
1112
bool EcIoSequence::is_supported(Sequence sequence) const { return true; }
1213

1314
std::unique_ptr<IoSequence> EcIoSequence::generate_sequence(
14-
Sequence sequence, std::pair<int, int> obj_size_range, int k, int m,
15+
Sequence sequence, std::pair<int, int> obj_size_range,
16+
std::optional<std::pair<int, int>> km,
17+
std::optional<std::pair<std::string_view, std::string_view>> mappinglayers,
1518
int seed) {
1619
switch (sequence) {
1720
case Sequence::SEQUENCE_SEQ0:
@@ -42,9 +45,9 @@ std::unique_ptr<IoSequence> EcIoSequence::generate_sequence(
4245
[[fallthrough]];
4346
case Sequence::SEQUENCE_SEQ14:
4447
return std::make_unique<ReadInjectSequence>(obj_size_range, seed,
45-
sequence, k, m);
48+
sequence, km, mappinglayers);
4649
case Sequence::SEQUENCE_SEQ10:
47-
return std::make_unique<Seq10>(obj_size_range, seed, k, m);
50+
return std::make_unique<Seq10>(obj_size_range, seed, km, mappinglayers);
4851
default:
4952
ceph_abort_msg("Unrecognised sequence");
5053
}
@@ -56,26 +59,99 @@ EcIoSequence::EcIoSequence(std::pair<int, int> obj_size_range, int seed)
5659
clear_inject(false),
5760
shard_to_inject(std::nullopt) {}
5861

59-
void EcIoSequence::select_random_data_shard_to_inject_read_error(int k, int m) {
60-
shard_to_inject = rng(k - 1);
62+
void EcIoSequence::select_random_data_shard_to_inject_read_error(
63+
std::optional<std::pair<int, int>> km,
64+
std::optional<std::pair<std::string_view, std::string_view>>
65+
mappinglayers) {
66+
if (km) {
67+
shard_to_inject = rng(km->first - 1);
68+
}
69+
if (mappinglayers) {
70+
int count = std::ranges::count(mappinglayers->first, 'D');
71+
int data_shard_position = rng(count - 1);
72+
shard_to_inject = 0;
73+
for (int i = 0; i < data_shard_position; i++) {
74+
shard_to_inject =
75+
std::distance(std::find(mappinglayers->first.begin(),
76+
mappinglayers->first.end(), *shard_to_inject),
77+
mappinglayers->first.begin());
78+
ceph_assert(*shard_to_inject != std::string::npos);
79+
}
80+
}
6181
setup_inject = true;
6282
}
6383

64-
void EcIoSequence::select_random_data_shard_to_inject_write_error(int k,
65-
int m) {
84+
void EcIoSequence::select_random_data_shard_to_inject_write_error(
85+
std::optional<std::pair<int, int>> km,
86+
std::optional<std::pair<std::string_view, std::string_view>>
87+
mappinglayers) {
6688
// Write errors do not support injecting to the primary OSD
67-
shard_to_inject = rng(1, k - 1);
89+
if (km) {
90+
shard_to_inject = rng(1, km->first - 1);
91+
}
92+
if (mappinglayers) {
93+
int count = std::ranges::count(mappinglayers->first, 'D');
94+
if (mappinglayers->first[0] == 'D') {
95+
count--;
96+
}
97+
int data_shard_position = rng(1, count - 1);
98+
shard_to_inject = 0;
99+
for (int i = 1; i < data_shard_position; i++) {
100+
shard_to_inject =
101+
std::distance(std::find(mappinglayers->first.begin(),
102+
mappinglayers->first.end(), *shard_to_inject),
103+
mappinglayers->first.begin());
104+
ceph_assert(*shard_to_inject != std::string::npos);
105+
}
106+
}
68107
setup_inject = true;
69108
}
70109

71-
void EcIoSequence::select_random_shard_to_inject_read_error(int k, int m) {
72-
shard_to_inject = rng(k + m - 1);
110+
void EcIoSequence::select_random_shard_to_inject_read_error(
111+
std::optional<std::pair<int, int>> km,
112+
std::optional<std::pair<std::string_view, std::string_view>>
113+
mappinglayers) {
114+
if (km) {
115+
shard_to_inject = rng(km->first + km->second - 1);
116+
}
117+
if (mappinglayers) {
118+
int count = std::ranges::count(mappinglayers->first, 'D');
119+
int data_shard_position = rng(count - 1);
120+
shard_to_inject = 0;
121+
for (int i = 0; i < data_shard_position; i++) {
122+
shard_to_inject =
123+
std::distance(std::find(mappinglayers->first.begin(),
124+
mappinglayers->first.end(), *shard_to_inject),
125+
mappinglayers->first.begin());
126+
ceph_assert(*shard_to_inject != std::string::npos);
127+
}
128+
}
73129
setup_inject = true;
74130
}
75131

76-
void EcIoSequence::select_random_shard_to_inject_write_error(int k, int m) {
132+
void EcIoSequence::select_random_shard_to_inject_write_error(
133+
std::optional<std::pair<int, int>> km,
134+
std::optional<std::pair<std::string_view, std::string_view>>
135+
mappinglayers) {
77136
// Write errors do not support injecting to the primary OSD
78-
shard_to_inject = rng(1, k + m - 1);
137+
if (km) {
138+
shard_to_inject = rng(1, km->first + km->second - 1);
139+
}
140+
if (mappinglayers) {
141+
int count = std::ranges::count(mappinglayers->first, 'D');
142+
if (mappinglayers->first[0] == 'D') {
143+
count--;
144+
}
145+
int data_shard_position = rng(count - 1);
146+
shard_to_inject = 0;
147+
for (int i = 0; i < data_shard_position; i++) {
148+
shard_to_inject =
149+
std::distance(std::find(mappinglayers->first.begin(),
150+
mappinglayers->first.end(), *shard_to_inject),
151+
mappinglayers->first.begin());
152+
ceph_assert(*shard_to_inject != std::string::npos);
153+
}
154+
}
79155
setup_inject = true;
80156
}
81157

@@ -92,10 +168,14 @@ void EcIoSequence::generate_random_write_inject_type() {
92168
}
93169

94170
ceph::io_exerciser::ReadInjectSequence::ReadInjectSequence(
95-
std::pair<int, int> obj_size_range, int seed, Sequence s, int k, int m)
171+
std::pair<int, int> obj_size_range,
172+
int seed,
173+
Sequence s,
174+
std::optional<std::pair<int, int>> km,
175+
std::optional<std::pair<std::string_view, std::string_view>> mappinglayers)
96176
: EcIoSequence(obj_size_range, seed) {
97177
child_sequence = IoSequence::generate_sequence(s, obj_size_range, seed);
98-
select_random_data_shard_to_inject_read_error(k, m);
178+
select_random_data_shard_to_inject_read_error(km, mappinglayers);
99179
generate_random_read_inject_type();
100180
}
101181

@@ -104,26 +184,31 @@ Sequence ceph::io_exerciser::ReadInjectSequence::get_id() const {
104184
}
105185

106186
std::string ceph::io_exerciser::ReadInjectSequence::get_name() const {
187+
std::string injected_shard = "UNKNOWN";
188+
if (shard_to_inject) {
189+
injected_shard = std::to_string(*shard_to_inject);
190+
}
191+
107192
return child_sequence->get_name() +
108-
" running with read errors injected on shard " +
109-
std::to_string(*shard_to_inject);
193+
" running with read errors injected on shard " + injected_shard;
110194
}
111195

112196
std::unique_ptr<IoOp> ReadInjectSequence::next() {
113197
step++;
114198

115-
if (nextOp) {
116-
std::unique_ptr<IoOp> retOp = nullptr;
117-
nextOp.swap(retOp);
118-
return retOp;
199+
if (next_op) {
200+
std::unique_ptr<IoOp> ret_op = nullptr;
201+
next_op.swap(ret_op);
202+
return ret_op;
119203
}
120204

121-
std::unique_ptr<IoOp> childOp = child_sequence->next();
205+
std::unique_ptr<IoOp> child_op = child_sequence->next();
122206

123-
switch (childOp->getOpType()) {
207+
switch (child_op->getOpType()) {
124208
case OpType::Remove:
125-
nextOp.swap(childOp);
209+
next_op.swap(child_op);
126210
switch (inject_op_type) {
211+
ceph_assert(shard_to_inject.has_value());
127212
case InjectOpType::ReadEIO:
128213
return ClearReadErrorInjectOp::generate(*shard_to_inject, 0);
129214
case InjectOpType::ReadMissingShard:
@@ -141,19 +226,19 @@ std::unique_ptr<IoOp> ReadInjectSequence::next() {
141226
case OpType::Create:
142227
switch (inject_op_type) {
143228
case InjectOpType::ReadEIO:
144-
nextOp = InjectReadErrorOp::generate(
229+
next_op = InjectReadErrorOp::generate(
145230
*shard_to_inject, 0, 0, std::numeric_limits<uint64_t>::max());
146231
break;
147232
case InjectOpType::ReadMissingShard:
148-
nextOp = InjectReadErrorOp::generate(
233+
next_op = InjectReadErrorOp::generate(
149234
*shard_to_inject, 1, 0, std::numeric_limits<uint64_t>::max());
150235
break;
151236
case InjectOpType::WriteFailAndRollback:
152-
nextOp = InjectWriteErrorOp::generate(
237+
next_op = InjectWriteErrorOp::generate(
153238
*shard_to_inject, 0, 0, std::numeric_limits<uint64_t>::max());
154239
break;
155240
case InjectOpType::WriteOSDAbort:
156-
nextOp = InjectWriteErrorOp::generate(
241+
next_op = InjectWriteErrorOp::generate(
157242
*shard_to_inject, 3, 0, std::numeric_limits<uint64_t>::max());
158243
break;
159244
case InjectOpType::None:
@@ -167,7 +252,7 @@ std::unique_ptr<IoOp> ReadInjectSequence::next() {
167252
break;
168253
}
169254

170-
return childOp;
255+
return child_op;
171256
}
172257

173258
std::unique_ptr<ceph::io_exerciser::IoOp>
@@ -179,8 +264,10 @@ ceph::io_exerciser::ReadInjectSequence::_next() {
179264
return DoneOp::generate();
180265
}
181266

182-
ceph::io_exerciser::Seq10::Seq10(std::pair<int, int> obj_size_range, int seed,
183-
int k, int m)
267+
ceph::io_exerciser::Seq10::Seq10(
268+
std::pair<int, int> obj_size_range, int seed,
269+
std::optional<std::pair<int, int>> km,
270+
std::optional<std::pair<std::string_view, std::string_view>> mappinglayers)
184271
: EcIoSequence(obj_size_range, seed),
185272
offset(0),
186273
length(1),
@@ -192,7 +279,7 @@ ceph::io_exerciser::Seq10::Seq10(std::pair<int, int> obj_size_range, int seed,
192279
test_all_sizes(
193280
false) // Only test obj_size(rand()) due to time constraints
194281
{
195-
select_random_shard_to_inject_write_error(k, m);
282+
select_random_shard_to_inject_write_error(km, mappinglayers);
196283
// We will inject specifically as part of our sequence in this sequence
197284
setup_inject = false;
198285
if (!test_all_sizes) {

src/common/io_exerciser/EcIoSequence.h

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#pragma once
2+
13
#include "IoSequence.h"
24

35
namespace ceph {
@@ -6,7 +8,11 @@ class EcIoSequence : public IoSequence {
68
public:
79
virtual bool is_supported(Sequence sequence) const override;
810
static std::unique_ptr<IoSequence> generate_sequence(
9-
Sequence s, std::pair<int, int> obj_size_range, int k, int m, int seed);
11+
Sequence s, std::pair<int, int> obj_size_range,
12+
std::optional<std::pair<int, int>> km,
13+
std::optional<std::pair<std::string_view, std::string_view>>
14+
mappinglayers,
15+
int seed);
1016

1117
protected:
1218
bool setup_inject;
@@ -18,18 +24,33 @@ class EcIoSequence : public IoSequence {
1824

1925
// Writes cannot be sent to injected on shard zero, so selections seperated
2026
// out
21-
void select_random_data_shard_to_inject_read_error(int k, int m);
22-
void select_random_data_shard_to_inject_write_error(int k, int m);
23-
void select_random_shard_to_inject_read_error(int k, int m);
24-
void select_random_shard_to_inject_write_error(int k, int m);
27+
void select_random_data_shard_to_inject_read_error(
28+
std::optional<std::pair<int, int>> km,
29+
std::optional<std::pair<std::string_view, std::string_view>>
30+
mappinglayers);
31+
void select_random_data_shard_to_inject_write_error(
32+
std::optional<std::pair<int, int>> km,
33+
std::optional<std::pair<std::string_view, std::string_view>>
34+
mappinglayers);
35+
void select_random_shard_to_inject_read_error(
36+
std::optional<std::pair<int, int>> km,
37+
std::optional<std::pair<std::string_view, std::string_view>>
38+
mappinglayers);
39+
void select_random_shard_to_inject_write_error(
40+
std::optional<std::pair<int, int>> km,
41+
std::optional<std::pair<std::string_view, std::string_view>>
42+
mappinglayers);
2543
void generate_random_read_inject_type();
2644
void generate_random_write_inject_type();
2745
};
2846

2947
class ReadInjectSequence : public EcIoSequence {
3048
public:
31-
ReadInjectSequence(std::pair<int, int> obj_size_range, int seed, Sequence s,
32-
int k, int m);
49+
ReadInjectSequence(
50+
std::pair<int, int> obj_size_range, int seed, Sequence s,
51+
std::optional<std::pair<int, int>> km,
52+
std::optional<std::pair<std::string_view, std::string_view>>
53+
mappinglayers);
3354

3455
Sequence get_id() const override;
3556
std::string get_name() const override;
@@ -38,12 +59,15 @@ class ReadInjectSequence : public EcIoSequence {
3859

3960
private:
4061
std::unique_ptr<IoSequence> child_sequence;
41-
std::unique_ptr<IoOp> nextOp;
62+
std::unique_ptr<IoOp> next_op;
4263
};
4364

4465
class Seq10 : public EcIoSequence {
4566
public:
46-
Seq10(std::pair<int, int> obj_size_range, int seed, int k, int m);
67+
Seq10(std::pair<int, int> obj_size_range, int seed,
68+
std::optional<std::pair<int, int>> km,
69+
std::optional<std::pair<std::string_view, std::string_view>>
70+
mappinglayers);
4771

4872
Sequence get_id() const override;
4973
std::string get_name() const override;

src/common/json/OSDStructures.cc

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,17 @@ void OSDECProfileGetReply::dump(Formatter* f) const {
8585
encode_json("crush-osds-per-failure-domain", crush_osds_per_failure_domain,
8686
f);
8787
encode_json("crush-root", crush_root, f);
88-
encode_json("jerasure-per-chunk-alignment", jerasure_per_chunk_alignment, f);
88+
encode_json("plugin", plugin, f);
8989
encode_json("k", k, f);
9090
encode_json("m", m, f);
91-
encode_json("plugin", plugin, f);
92-
encode_json("technique", technique, f);
91+
encode_json("l", l, f);
9392
encode_json("w", w, f);
93+
encode_json("c", c, f);
94+
encode_json("packetsize", packetsize, f);
95+
encode_json("technique", technique, f);
96+
encode_json("layers", layers, f);
97+
encode_json("mapping", mapping, f);
98+
encode_json("jerasure-per-chunk-alignment", jerasure_per_chunk_alignment, f);
9499
}
95100

96101
void OSDECProfileGetReply::decode_json(JSONObj* obj) {
@@ -101,24 +106,31 @@ void OSDECProfileGetReply::decode_json(JSONObj* obj) {
101106
JSONDecoder::decode_json("crush-osds-per-failure-domain",
102107
crush_osds_per_failure_domain, obj);
103108
JSONDecoder::decode_json("crush-root", crush_root, obj);
104-
JSONDecoder::decode_json("jerasure-per-chunk-alignment",
105-
jerasure_per_chunk_alignment, obj);
109+
JSONDecoder::decode_json("plugin", plugin, obj);
106110
JSONDecoder::decode_json("k", k, obj);
107111
JSONDecoder::decode_json("m", m, obj);
108-
JSONDecoder::decode_json("plugin", plugin, obj);
109-
JSONDecoder::decode_json("technique", technique, obj);
112+
JSONDecoder::decode_json("l", l, obj);
110113
JSONDecoder::decode_json("w", w, obj);
114+
JSONDecoder::decode_json("c", c, obj);
115+
JSONDecoder::decode_json("packetsize", packetsize, obj);
116+
JSONDecoder::decode_json("technique", technique, obj);
117+
JSONDecoder::decode_json("layers", layers, obj);
118+
JSONDecoder::decode_json("mapping", mapping, obj);
119+
JSONDecoder::decode_json("jerasure-per-chunk-alignment",
120+
jerasure_per_chunk_alignment, obj);
111121
}
112122

113123
void OSDECProfileSetRequest::dump(Formatter* f) const {
114124
encode_json("prefix", "osd erasure-code-profile set", f);
115125
encode_json("name", name, f);
116126
encode_json("profile", profile, f);
127+
encode_json("force", force, f);
117128
}
118129

119130
void OSDECProfileSetRequest::decode_json(JSONObj* obj) {
120131
JSONDecoder::decode_json("name", name, obj);
121132
JSONDecoder::decode_json("profile", profile, obj);
133+
JSONDecoder::decode_json("force", force, obj);
122134
}
123135

124136
void OSDECPoolCreateRequest::dump(Formatter* f) const {

0 commit comments

Comments
 (0)