11#include " EcIoSequence.h"
22
3+ #include < algorithm>
34#include < memory>
45
56using IoOp = ceph::io_exerciser::IoOp;
@@ -11,7 +12,9 @@ using ReadInjectSequence = ceph::io_exerciser::ReadInjectSequence;
1112bool EcIoSequence::is_supported (Sequence sequence) const { return true ; }
1213
1314std::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
94170ceph::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
106186std::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
112196std::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
173258std::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) {
0 commit comments