1515
1616#include < string>
1717
18+ #include < boost/icl/interval_set.hpp>
1819#include < folly/init/Init.h>
1920#include < gtest/gtest.h>
2021#include < sisl/options/options.h>
@@ -56,6 +57,7 @@ class VolumeIOImpl {
5657public:
5758 void create_volume () {
5859 auto vinfo = gen_vol_info (m_volume_id_++);
60+ m_vol_name = vinfo.name ;
5961 m_vol_id = vinfo.id ;
6062
6163 auto vol_mgr = g_helper->inst ()->volume_manager ();
@@ -78,13 +80,39 @@ class VolumeIOImpl {
7880 ASSERT_TRUE (m_vol_ptr != nullptr );
7981 }
8082
83+ void get_random_non_overlapping_lba (lba_t & start_lba, uint32_t & nblks, uint64_t max_blks) {
84+ if (start_lba != 0 && nblks != 0 ) {
85+ lba_t end_lba = start_lba + nblks - 1 ;
86+ auto new_range = boost::icl::interval< int >::closed (start_lba, end_lba);
87+ // For user provided lba and nblks, check if they are already in flight.
88+ std::lock_guard lock (m_mutex);
89+ ASSERT_TRUE (m_inflight_ios.find (new_range) == m_inflight_ios.end ());
90+ m_inflight_ios.insert (new_range);
91+ return ;
92+ }
93+
94+ do {
95+ // Generate lba which are not overlapped with the inflight ios, otherwise
96+ // we cant decide which io completed last and cant verify the data.
97+ start_lba = rand () % max_blks;
98+ nblks = std::max (1 , rand () % 64 );
99+ lba_t end_lba = start_lba + nblks - 1 ;
100+ auto new_range = boost::icl::interval< int >::closed (start_lba, end_lba);
101+ std::lock_guard lock (m_mutex);
102+ if (m_inflight_ios.find (new_range) == m_inflight_ios.end ()) {
103+ m_inflight_ios.insert (new_range);
104+ break ;
105+ }
106+
107+ } while (true );
108+ }
109+
81110 auto build_random_data (lba_t & start_lba, uint32_t & nblks) {
82111 // Write upto 1-64 nblks * 4k = 256k size.
83112 auto info = m_vol_ptr->info ();
84113 uint64_t page_size = info->page_size ;
85114 uint64_t max_blks = info->size_bytes / page_size;
86- start_lba = start_lba == 0 ? rand () % max_blks : start_lba;
87- nblks = nblks == 0 ? std::max (1 , rand () % 64 ) : nblks;
115+ get_random_non_overlapping_lba (start_lba, nblks, max_blks);
88116 nblks = std::min (static_cast < uint64_t >(nblks), max_blks - static_cast < uint64_t >(start_lba));
89117
90118 auto data_size = nblks * page_size;
@@ -94,9 +122,13 @@ class VolumeIOImpl {
94122 uint64_t data_pattern = ((long long )rand () << 32 ) | rand ();
95123 test_common::HBTestHelper::fill_data_buf (data_bytes, page_size, data_pattern);
96124 data_bytes += page_size;
97- // Store the lba to pattern mapping
98- m_lba_data[lba] = data_pattern;
99- LOGINFO (" Generate data lba={} pattern={}" , lba, data_pattern);
125+ {
126+ // Store the lba to pattern mapping
127+ std::lock_guard lock (m_mutex);
128+ m_lba_data[lba] = data_pattern;
129+ }
130+
131+ LOGDEBUG (" Generate data vol={} lba={} pattern={}" , m_vol_name, lba, data_pattern);
100132 lba++;
101133 }
102134
@@ -112,8 +144,13 @@ class VolumeIOImpl {
112144 auto vol_mgr = g_helper->inst ()->volume_manager ();
113145 vol_mgr->write (m_vol_ptr, req)
114146 .via (&folly::InlineExecutor::instance ())
115- .thenValue ([this , data, &waiter](auto && result) {
147+ .thenValue ([this , data, req, &waiter](auto && result) {
116148 ASSERT_FALSE (result.hasError ());
149+ {
150+ std::lock_guard lock (m_mutex);
151+ m_inflight_ios.erase (boost::icl::interval< int >::closed (req->lba , req->lba + req->nlbas - 1 ));
152+ }
153+
117154 waiter.one_complete ();
118155 });
119156 });
@@ -125,22 +162,28 @@ class VolumeIOImpl {
125162 auto data = build_random_data (start_lba, nblks);
126163 vol_interface_req_ptr req (new vol_interface_req{data->bytes (), start_lba, nblks});
127164 auto vol_mgr = g_helper->inst ()->volume_manager ();
128- vol_mgr->write (m_vol_ptr, req).via (&folly::InlineExecutor::instance ()).thenValue ([this , data](auto && result) {
129- ASSERT_FALSE (result.hasError ());
130- g_helper->runner ().next_task ();
131- });
165+ vol_mgr->write (m_vol_ptr, req)
166+ .via (&folly::InlineExecutor::instance ())
167+ .thenValue ([this , req, data](auto && result) {
168+ ASSERT_FALSE (result.hasError ());
169+ {
170+ std::lock_guard lock (m_mutex);
171+ m_inflight_ios.erase (boost::icl::interval< int >::closed (req->lba , req->lba + req->nlbas - 1 ));
172+ }
173+ g_helper->runner ().next_task ();
174+ });
132175 }
133176
134- void verify_data () {
177+ void verify_all_data () {
135178 for (auto & [lba, data_pattern] : m_lba_data) {
136179 auto buffer = iomanager.iobuf_alloc (512 , 4096 );
137180 vol_interface_req_ptr req (new vol_interface_req{buffer, lba, 1 });
138181
139182 auto vol_mgr = g_helper->inst ()->volume_manager ();
140183 vol_mgr->read (m_vol_ptr, req).get ();
141- // LOGINFO("Data read={}", fmt::format("{}", spdlog::to_hex((buffer), (buffer) + (128))));
142184 test_common::HBTestHelper::validate_data_buf (buffer, 4096 , data_pattern);
143- LOGINFO (" Verify data lba={} pattern={} {}" , lba, data_pattern, *r_cast< uint64_t * >(buffer));
185+ LOGDEBUG (" Verify data vol={} lba={} pattern={} {}" , m_vol_name, lba, data_pattern,
186+ *r_cast< uint64_t * >(buffer));
144187 iomanager.iobuf_free (buffer);
145188 }
146189 }
@@ -160,10 +203,13 @@ class VolumeIOImpl {
160203#ifdef _PRERELEASE
161204 flip::FlipClient m_fc{iomgr_flip::instance ()};
162205#endif
206+ std::mutex m_mutex;
207+ std::string m_vol_name;
163208 VolumePtr m_vol_ptr;
164209 volume_id_t m_vol_id;
165210 static inline uint32_t m_volume_id_{1 };
166211 std::map< lba_t , uint64_t > m_lba_data;
212+ boost::icl::interval_set< int > m_inflight_ios;
167213};
168214
169215class VolumeIOTest : public ::testing::Test {
@@ -199,14 +245,21 @@ class VolumeIOTest : public ::testing::Test {
199245 LOGINFO (" IO completed" );
200246 }
201247
202- void verify_data (shared< VolumeIOImpl > vol_impl = nullptr ) {
248+ void verify_all_data (shared< VolumeIOImpl > vol_impl = nullptr ) {
203249 if (vol_impl) {
204- vol_impl->verify_data ();
250+ vol_impl->verify_all_data ();
205251 return ;
206252 }
207253
208254 for (auto & vol_impl : m_vols_impl) {
209- vol_impl->verify_data ();
255+ vol_impl->verify_all_data ();
256+ }
257+ }
258+
259+ void restart (int shutdown_delay) {
260+ g_helper->restart (shutdown_delay);
261+ for (auto & vol_impl : m_vols_impl) {
262+ vol_impl->reset ();
210263 }
211264 }
212265
@@ -219,29 +272,28 @@ class VolumeIOTest : public ::testing::Test {
219272TEST_F (VolumeIOTest, SingleVolumeWriteData) {
220273 // Write and verify fixed LBA range to single volume multiple times.
221274 auto vol = volume_list ().back ();
222- uint32_t nblks = 100 ;
275+ uint32_t nblks = 10 ;
223276 lba_t start_lba = 1 ;
224277 uint32_t num_iter = 1 ;
225278 LOGINFO (" Write and verify data with num_iter={} start={} nblks={}" , num_iter, start_lba, nblks);
226279 for (uint32_t i = 0 ; i < num_iter; i++) {
227280 generate_io_single (vol, start_lba, nblks);
228- verify_data (vol);
281+ verify_all_data (vol);
229282 }
230283
231284 // Verify data after restart.
232- g_helper->restart (10 );
233- vol->reset ();
285+ restart (5 );
234286
235287 LOGINFO (" Verify data" );
236- verify_data (vol);
288+ verify_all_data (vol);
237289
238290 // Write and verify again on same LBA range to single volume multiple times.
239291 LOGINFO (" Write and verify data with num_iter={} start={} nblks={}" , num_iter, start_lba, nblks);
240292 for (uint32_t i = 0 ; i < num_iter; i++) {
241293 generate_io_single (vol, start_lba, nblks);
242294 }
243295
244- verify_data (vol);
296+ verify_all_data (vol);
245297 LOGINFO (" SingleVolumeWriteData test done." );
246298}
247299
@@ -251,24 +303,38 @@ TEST_F(VolumeIOTest, MultipleVolumeWriteData) {
251303 generate_io ();
252304
253305 LOGINFO (" Verify data" );
254- verify_data ();
306+ verify_all_data ();
307+
308+ restart (5 );
309+
310+ LOGINFO (" Verify data again" );
311+ verify_all_data ();
312+
313+ LOGINFO (" Write data randomly" );
314+ generate_io ();
315+
316+ LOGINFO (" Verify data" );
317+ verify_all_data ();
318+
255319 LOGINFO (" MultipleVolumeWriteData test done." );
256320}
257321
258322int main (int argc, char * argv[]) {
259323 int parsed_argc = argc;
260- ::testing::InitGoogleTest (&parsed_argc, argv);
261- SISL_OPTIONS_LOAD (parsed_argc, argv, logging, test_common_setup, test_volume_io_setup, homeblocks);
262- spdlog::set_pattern (" [%D %T%z] [%^%l%$] [%n] [%t] %v" );
263- parsed_argc = 1 ;
264- auto f = ::folly::Init (&parsed_argc, &argv, true );
324+ char ** orig_argv = argv;
265325
266326 std::vector< std::string > args;
267327 for (int i = 0 ; i < argc; ++i) {
268328 args.emplace_back (argv[i]);
269329 }
270330
271- g_helper = std::make_unique< test_common::HBTestHelper >(" test_volume_io" , args, argv);
331+ ::testing::InitGoogleTest (&parsed_argc, argv);
332+ SISL_OPTIONS_LOAD (parsed_argc, argv, logging, test_common_setup, test_volume_io_setup, homeblocks);
333+ spdlog::set_pattern (" [%D %T%z] [%^%l%$] [%n] [%t] %v" );
334+ parsed_argc = 1 ;
335+ auto f = ::folly::Init (&parsed_argc, &argv, true );
336+
337+ g_helper = std::make_unique< test_common::HBTestHelper >(" test_volume_io" , args, orig_argv);
272338 g_helper->setup ();
273339 auto ret = RUN_ALL_TESTS ();
274340 g_helper->teardown ();
0 commit comments