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,14 @@ 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 };
211+ // Mapping from lba to data patttern.
166212 std::map< lba_t , uint64_t > m_lba_data;
213+ boost::icl::interval_set< int > m_inflight_ios;
167214};
168215
169216class VolumeIOTest : public ::testing::Test {
@@ -199,14 +246,21 @@ class VolumeIOTest : public ::testing::Test {
199246 LOGINFO (" IO completed" );
200247 }
201248
202- void verify_data (shared< VolumeIOImpl > vol_impl = nullptr ) {
249+ void verify_all_data (shared< VolumeIOImpl > vol_impl = nullptr ) {
203250 if (vol_impl) {
204- vol_impl->verify_data ();
251+ vol_impl->verify_all_data ();
205252 return ;
206253 }
207254
208255 for (auto & vol_impl : m_vols_impl) {
209- vol_impl->verify_data ();
256+ vol_impl->verify_all_data ();
257+ }
258+ }
259+
260+ void restart (int shutdown_delay) {
261+ g_helper->restart (shutdown_delay);
262+ for (auto & vol_impl : m_vols_impl) {
263+ vol_impl->reset ();
210264 }
211265 }
212266
@@ -225,23 +279,22 @@ TEST_F(VolumeIOTest, SingleVolumeWriteData) {
225279 LOGINFO (" Write and verify data with num_iter={} start={} nblks={}" , num_iter, start_lba, nblks);
226280 for (uint32_t i = 0 ; i < num_iter; i++) {
227281 generate_io_single (vol, start_lba, nblks);
228- verify_data (vol);
282+ verify_all_data (vol);
229283 }
230284
231285 // Verify data after restart.
232- g_helper->restart (10 );
233- vol->reset ();
286+ restart (5 );
234287
235288 LOGINFO (" Verify data" );
236- verify_data (vol);
289+ verify_all_data (vol);
237290
238291 // Write and verify again on same LBA range to single volume multiple times.
239292 LOGINFO (" Write and verify data with num_iter={} start={} nblks={}" , num_iter, start_lba, nblks);
240293 for (uint32_t i = 0 ; i < num_iter; i++) {
241294 generate_io_single (vol, start_lba, nblks);
242295 }
243296
244- verify_data (vol);
297+ verify_all_data (vol);
245298 LOGINFO (" SingleVolumeWriteData test done." );
246299}
247300
@@ -251,24 +304,38 @@ TEST_F(VolumeIOTest, MultipleVolumeWriteData) {
251304 generate_io ();
252305
253306 LOGINFO (" Verify data" );
254- verify_data ();
307+ verify_all_data ();
308+
309+ restart (5 );
310+
311+ LOGINFO (" Verify data again" );
312+ verify_all_data ();
313+
314+ LOGINFO (" Write data randomly" );
315+ generate_io ();
316+
317+ LOGINFO (" Verify data" );
318+ verify_all_data ();
319+
255320 LOGINFO (" MultipleVolumeWriteData test done." );
256321}
257322
258323int main (int argc, char * argv[]) {
259324 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 );
325+ char ** orig_argv = argv;
265326
266327 std::vector< std::string > args;
267328 for (int i = 0 ; i < argc; ++i) {
268329 args.emplace_back (argv[i]);
269330 }
270331
271- g_helper = std::make_unique< test_common::HBTestHelper >(" test_volume_io" , args, argv);
332+ ::testing::InitGoogleTest (&parsed_argc, argv);
333+ SISL_OPTIONS_LOAD (parsed_argc, argv, logging, test_common_setup, test_volume_io_setup, homeblocks);
334+ spdlog::set_pattern (" [%D %T%z] [%^%l%$] [%n] [%t] %v" );
335+ parsed_argc = 1 ;
336+ auto f = ::folly::Init (&parsed_argc, &argv, true );
337+
338+ g_helper = std::make_unique< test_common::HBTestHelper >(" test_volume_io" , args, orig_argv);
272339 g_helper->setup ();
273340 auto ret = RUN_ALL_TESTS ();
274341 g_helper->teardown ();
0 commit comments