]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/test_filejournal.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / test / test_filejournal.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2#include <gtest/gtest.h>
3#include <stdlib.h>
4#include <limits.h>
5
6#include "common/ceph_argparse.h"
7#include "common/common_init.h"
8#include "global/global_init.h"
9#include "common/config.h"
10#include "common/Finisher.h"
11#include "os/filestore/FileJournal.h"
12#include "include/Context.h"
13#include "common/Mutex.h"
14#include "common/safe_io.h"
15#include "os/filestore/JournalingObjectStore.h"
16
17Finisher *finisher;
18Cond sync_cond;
19char path[200];
20uuid_d fsid;
21struct test_info {
22 bool directio, aio, faio;
23 const char *description;
24} subtests[3] = {
25 { false, false, false, "DIRECTIO OFF AIO OFF" },
26 { true, false, false, "DIRECTIO ON AIO OFF" },
27 { true, true, true, "DIRECTIO ON AIO ON"}
28};
29
30// ----
31Cond cond;
32Mutex wait_lock("lock");
33bool done;
34
35void wait()
36{
37 wait_lock.Lock();
38 while (!done)
39 cond.Wait(wait_lock);
40 wait_lock.Unlock();
41}
42
43// ----
44class C_Sync {
45public:
46 Cond cond;
47 Mutex lock;
48 bool done;
49 C_SafeCond *c;
50
51 C_Sync()
52 : lock("C_Sync::lock"), done(false) {
53 c = new C_SafeCond(&lock, &cond, &done);
54 }
55 ~C_Sync() {
56 lock.Lock();
57 //cout << "wait" << std::endl;
58 while (!done)
59 cond.Wait(lock);
60 //cout << "waited" << std::endl;
61 lock.Unlock();
62 }
63};
64
65unsigned size_mb = 200;
66//Gtest argument prefix
67const char GTEST_PRFIX[] = "--gtest_";
68
69int main(int argc, char **argv) {
70 vector<const char*> args;
71 argv_to_vec(argc, (const char **)argv, args);
72
73 auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
11fdf7f2
TL
74 CODE_ENVIRONMENT_UTILITY,
75 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
7c673cae
FG
76 common_init_finish(g_ceph_context);
77
78 char mb[10];
79 sprintf(mb, "%u", size_mb);
11fdf7f2
TL
80 g_ceph_context->_conf.set_val("osd_journal_size", mb);
81 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
82
83 finisher = new Finisher(g_ceph_context);
84
85 path[0] = '\0';
86 if (!args.empty()) {
87 for ( unsigned int i = 0; i < args.size(); ++i) {
88 if (strncmp(args[i], GTEST_PRFIX, sizeof(GTEST_PRFIX) - 1)) {
89 //Non gtest argument, set to path.
90 size_t copy_len = std::min(sizeof(path) - 1, strlen(args[i]));
91 strncpy(path, args[i], copy_len);
92 path[copy_len] = '\0';
93 break;
94 }
95 }
96 }
97 if ( path[0] == '\0') {
98 srand(getpid() + time(0));
99 snprintf(path, sizeof(path), "/var/tmp/ceph_test_filejournal.tmp.%d", rand());
100 }
101 cout << "path " << path << std::endl;
102
103 ::testing::InitGoogleTest(&argc, argv);
104
105 finisher->start();
106
107 int r = RUN_ALL_TESTS();
108
109 finisher->stop();
110
111 unlink(path);
112
113 return r;
114}
115
116TEST(TestFileJournal, Create) {
11fdf7f2
TL
117 g_ceph_context->_conf.set_val("journal_ignore_corruption", "false");
118 g_ceph_context->_conf.set_val("journal_write_header_frequency", "0");
119 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
120
121 for (unsigned i = 0 ; i < 3; ++i) {
122 SCOPED_TRACE(subtests[i].description);
123 fsid.generate_random();
31f18b77 124 FileJournal fj(g_ceph_context, fsid, finisher, &sync_cond, path,
7c673cae 125 subtests[i].directio, subtests[i].aio, subtests[i].faio);
31f18b77 126 ASSERT_EQ(0, fj.create());
7c673cae
FG
127 }
128}
129
130TEST(TestFileJournal, WriteSmall) {
11fdf7f2
TL
131 g_ceph_context->_conf.set_val("journal_ignore_corruption", "false");
132 g_ceph_context->_conf.set_val("journal_write_header_frequency", "0");
133 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
134
135 for (unsigned i = 0 ; i < 3; ++i) {
136 SCOPED_TRACE(subtests[i].description);
137 fsid.generate_random();
31f18b77 138 FileJournal fj(g_ceph_context, fsid, finisher, &sync_cond, path,
7c673cae 139 subtests[i].directio, subtests[i].aio, subtests[i].faio);
31f18b77
FG
140 ASSERT_EQ(0, fj.create());
141 ASSERT_EQ(0, fj.make_writeable());
7c673cae
FG
142
143 vector<ObjectStore::Transaction> tls;
144 bufferlist bl;
145 bl.append("small");
31f18b77
FG
146 int orig_len = fj.prepare_entry(tls, &bl);
147 fj.reserve_throttle_and_backoff(bl.length());
148 fj.submit_entry(1, bl, orig_len, new C_SafeCond(&wait_lock, &cond, &done));
7c673cae
FG
149 wait();
150
31f18b77 151 fj.close();
7c673cae
FG
152 }
153}
154
155TEST(TestFileJournal, WriteBig) {
11fdf7f2
TL
156 g_ceph_context->_conf.set_val("journal_ignore_corruption", "false");
157 g_ceph_context->_conf.set_val("journal_write_header_frequency", "0");
158 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
159
160 for (unsigned i = 0 ; i < 3; ++i) {
161 SCOPED_TRACE(subtests[i].description);
162 fsid.generate_random();
31f18b77 163 FileJournal fj(g_ceph_context, fsid, finisher, &sync_cond, path,
7c673cae 164 subtests[i].directio, subtests[i].aio, subtests[i].faio);
31f18b77
FG
165 ASSERT_EQ(0, fj.create());
166 ASSERT_EQ(0, fj.make_writeable());
7c673cae
FG
167
168 bufferlist bl;
169 while (bl.length() < size_mb*1000/2) {
170 char foo[1024*1024];
171 memset(foo, 1, sizeof(foo));
172 bl.append(foo, sizeof(foo));
173 }
174 vector<ObjectStore::Transaction> tls;
31f18b77
FG
175 int orig_len = fj.prepare_entry(tls, &bl);
176 fj.reserve_throttle_and_backoff(bl.length());
177 fj.submit_entry(1, bl, orig_len, new C_SafeCond(&wait_lock, &cond, &done));
7c673cae 178 wait();
31f18b77 179 fj.close();
7c673cae
FG
180 }
181}
182
183TEST(TestFileJournal, WriteMany) {
11fdf7f2
TL
184 g_ceph_context->_conf.set_val("journal_ignore_corruption", "false");
185 g_ceph_context->_conf.set_val("journal_write_header_frequency", "0");
186 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
187
188 for (unsigned i = 0 ; i < 3; ++i) {
189 SCOPED_TRACE(subtests[i].description);
190 fsid.generate_random();
31f18b77 191 FileJournal fj(g_ceph_context, fsid, finisher, &sync_cond, path,
7c673cae 192 subtests[i].directio, subtests[i].aio, subtests[i].faio);
31f18b77
FG
193 ASSERT_EQ(0, fj.create());
194 ASSERT_EQ(0, fj.make_writeable());
7c673cae
FG
195
196 C_GatherBuilder gb(g_ceph_context, new C_SafeCond(&wait_lock, &cond, &done));
197
198 vector<ObjectStore::Transaction> tls;
199 bufferlist bl;
200 bl.append("small");
201 uint64_t seq = 1;
202 for (int i=0; i<100; i++) {
203 bl.append("small");
31f18b77
FG
204 int orig_len = fj.prepare_entry(tls, &bl);
205 fj.reserve_throttle_and_backoff(bl.length());
206 fj.submit_entry(seq++, bl, orig_len, gb.new_sub());
7c673cae
FG
207 }
208 gb.activate();
209
210 wait();
211
31f18b77 212 fj.close();
7c673cae
FG
213 }
214}
215
216TEST(TestFileJournal, WriteManyVecs) {
11fdf7f2
TL
217 g_ceph_context->_conf.set_val("journal_ignore_corruption", "false");
218 g_ceph_context->_conf.set_val("journal_write_header_frequency", "0");
219 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
220
221 for (unsigned i = 0 ; i < 3; ++i) {
222 SCOPED_TRACE(subtests[i].description);
223 fsid.generate_random();
31f18b77 224 FileJournal fj(g_ceph_context, fsid, finisher, &sync_cond, path,
7c673cae 225 subtests[i].directio, subtests[i].aio, subtests[i].faio);
31f18b77
FG
226 ASSERT_EQ(0, fj.create());
227 ASSERT_EQ(0, fj.make_writeable());
7c673cae
FG
228
229 C_GatherBuilder gb(g_ceph_context, new C_SafeCond(&wait_lock, &cond, &done));
230
231 bufferlist first;
232 first.append("small");
233 vector<ObjectStore::Transaction> tls;
31f18b77
FG
234 int orig_len = fj.prepare_entry(tls, &first);
235 fj.reserve_throttle_and_backoff(first.length());
236 fj.submit_entry(1, first, orig_len, gb.new_sub());
7c673cae
FG
237
238 bufferlist bl;
239 for (int i=0; i<IOV_MAX * 2; i++) {
240 bufferptr bp = buffer::create_page_aligned(4096);
241 memset(bp.c_str(), (char)i, 4096);
242 bl.append(bp);
243 }
244 bufferlist origbl = bl;
31f18b77
FG
245 orig_len = fj.prepare_entry(tls, &bl);
246 fj.reserve_throttle_and_backoff(bl.length());
247 fj.submit_entry(2, bl, orig_len, gb.new_sub());
7c673cae
FG
248 gb.activate();
249 wait();
250
31f18b77 251 fj.close();
7c673cae 252
31f18b77 253 fj.open(1);
7c673cae
FG
254 bufferlist inbl;
255 string v;
256 uint64_t seq = 0;
31f18b77 257 ASSERT_EQ(true, fj.read_entry(inbl, seq));
7c673cae
FG
258 ASSERT_EQ(seq, 2ull);
259 ASSERT_TRUE(inbl.contents_equal(origbl));
31f18b77
FG
260 ASSERT_EQ(0, fj.make_writeable());
261 fj.close();
7c673cae
FG
262
263 }
264}
265
266TEST(TestFileJournal, ReplaySmall) {
11fdf7f2
TL
267 g_ceph_context->_conf.set_val("journal_ignore_corruption", "false");
268 g_ceph_context->_conf.set_val("journal_write_header_frequency", "0");
269 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
270
271 vector<ObjectStore::Transaction> tls;
272
273 for (unsigned i = 0 ; i < 3; ++i) {
274 SCOPED_TRACE(subtests[i].description);
275 fsid.generate_random();
31f18b77 276 FileJournal fj(g_ceph_context, fsid, finisher, &sync_cond, path,
7c673cae 277 subtests[i].directio, subtests[i].aio, subtests[i].faio);
31f18b77
FG
278 ASSERT_EQ(0, fj.create());
279 ASSERT_EQ(0, fj.make_writeable());
7c673cae
FG
280
281 C_GatherBuilder gb(g_ceph_context, new C_SafeCond(&wait_lock, &cond, &done));
282
283 bufferlist bl;
284 bl.append("small");
31f18b77
FG
285 int orig_len = fj.prepare_entry(tls, &bl);
286 fj.reserve_throttle_and_backoff(bl.length());
287 fj.submit_entry(1, bl, orig_len, gb.new_sub());
7c673cae 288 bl.append("small");
31f18b77
FG
289 orig_len = fj.prepare_entry(tls, &bl);
290 fj.reserve_throttle_and_backoff(bl.length());
291 fj.submit_entry(2, bl, orig_len, gb.new_sub());
7c673cae 292 bl.append("small");
31f18b77
FG
293 orig_len = fj.prepare_entry(tls, &bl);
294 fj.reserve_throttle_and_backoff(bl.length());
295 fj.submit_entry(3, bl, orig_len, gb.new_sub());
7c673cae
FG
296 gb.activate();
297 wait();
298
31f18b77 299 fj.close();
7c673cae 300
31f18b77 301 fj.open(1);
7c673cae
FG
302
303 bufferlist inbl;
304 string v;
305 uint64_t seq = 0;
31f18b77 306 ASSERT_EQ(true, fj.read_entry(inbl, seq));
7c673cae
FG
307 ASSERT_EQ(seq, 2ull);
308 inbl.copy(0, inbl.length(), v);
309 ASSERT_EQ("small", v);
310 inbl.clear();
311 v.clear();
312
31f18b77 313 ASSERT_EQ(true, fj.read_entry(inbl, seq));
7c673cae
FG
314 ASSERT_EQ(seq, 3ull);
315 inbl.copy(0, inbl.length(), v);
316 ASSERT_EQ("small", v);
317 inbl.clear();
318 v.clear();
319
31f18b77 320 ASSERT_TRUE(!fj.read_entry(inbl, seq));
7c673cae 321
31f18b77
FG
322 ASSERT_EQ(0, fj.make_writeable());
323 fj.close();
7c673cae
FG
324 }
325}
326
327TEST(TestFileJournal, ReplayCorrupt) {
11fdf7f2
TL
328 g_ceph_context->_conf.set_val("journal_ignore_corruption", "true");
329 g_ceph_context->_conf.set_val("journal_write_header_frequency", "0");
330 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
331
332 vector<ObjectStore::Transaction> tls;
333 for (unsigned i = 0 ; i < 3; ++i) {
334 SCOPED_TRACE(subtests[i].description);
335 fsid.generate_random();
31f18b77 336 FileJournal fj(g_ceph_context, fsid, finisher, &sync_cond, path,
7c673cae 337 subtests[i].directio, subtests[i].aio, subtests[i].faio);
31f18b77
FG
338 ASSERT_EQ(0, fj.create());
339 ASSERT_EQ(0, fj.make_writeable());
7c673cae
FG
340
341 C_GatherBuilder gb(g_ceph_context, new C_SafeCond(&wait_lock, &cond, &done));
342
343 const char *needle = "i am a needle";
344 const char *newneedle = "in a haystack";
345 bufferlist bl;
346 bl.append(needle);
31f18b77
FG
347 int orig_len = fj.prepare_entry(tls, &bl);
348 fj.reserve_throttle_and_backoff(bl.length());
349 fj.submit_entry(1, bl, orig_len, gb.new_sub());
7c673cae 350 bl.append(needle);
31f18b77
FG
351 orig_len = fj.prepare_entry(tls, &bl);
352 fj.reserve_throttle_and_backoff(bl.length());
353 fj.submit_entry(2, bl, orig_len, gb.new_sub());
7c673cae 354 bl.append(needle);
31f18b77
FG
355 orig_len = fj.prepare_entry(tls, &bl);
356 fj.reserve_throttle_and_backoff(bl.length());
357 fj.submit_entry(3, bl, orig_len, gb.new_sub());
7c673cae 358 bl.append(needle);
31f18b77
FG
359 orig_len = fj.prepare_entry(tls, &bl);
360 fj.reserve_throttle_and_backoff(bl.length());
361 fj.submit_entry(4, bl, orig_len, gb.new_sub());
7c673cae
FG
362 gb.activate();
363 wait();
364
31f18b77 365 fj.close();
7c673cae
FG
366
367 cout << "corrupting journal" << std::endl;
368 char buf[1024*128];
369 int fd = open(path, O_RDONLY);
370 ASSERT_GE(fd, 0);
371 int r = safe_read_exact(fd, buf, sizeof(buf));
372 ASSERT_EQ(0, r);
373 int n = 0;
374 for (unsigned o=0; o < sizeof(buf) - strlen(needle); o++) {
375 if (memcmp(buf+o, needle, strlen(needle)) == 0) {
376 if (n >= 2) {
377 cout << "replacing at offset " << o << std::endl;
378 memcpy(buf+o, newneedle, strlen(newneedle));
379 } else {
380 cout << "leaving at offset " << o << std::endl;
381 }
382 n++;
383 }
384 }
385 ASSERT_EQ(n, 4);
386 close(fd);
387 fd = open(path, O_WRONLY);
388 ASSERT_GE(fd, 0);
389 r = safe_write(fd, buf, sizeof(buf));
390 ASSERT_EQ(r, 0);
391 close(fd);
392
31f18b77 393 fj.open(1);
7c673cae
FG
394
395 bufferlist inbl;
396 string v;
397 uint64_t seq = 0;
31f18b77 398 ASSERT_EQ(true, fj.read_entry(inbl, seq));
7c673cae
FG
399 ASSERT_EQ(seq, 2ull);
400 inbl.copy(0, inbl.length(), v);
401 ASSERT_EQ(needle, v);
402 inbl.clear();
403 v.clear();
404 bool corrupt;
31f18b77 405 ASSERT_FALSE(fj.read_entry(inbl, seq, &corrupt));
7c673cae
FG
406 ASSERT_TRUE(corrupt);
407
31f18b77
FG
408 ASSERT_EQ(0, fj.make_writeable());
409 fj.close();
7c673cae
FG
410 }
411}
412
413TEST(TestFileJournal, WriteTrim) {
11fdf7f2
TL
414 g_ceph_context->_conf.set_val("journal_ignore_corruption", "false");
415 g_ceph_context->_conf.set_val("journal_write_header_frequency", "0");
416 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
417
418 for (unsigned i = 0 ; i < 3; ++i) {
419 SCOPED_TRACE(subtests[i].description);
420 fsid.generate_random();
31f18b77 421 FileJournal fj(g_ceph_context, fsid, finisher, &sync_cond, path,
7c673cae 422 subtests[i].directio, subtests[i].aio, subtests[i].faio);
31f18b77
FG
423 ASSERT_EQ(0, fj.create());
424 ASSERT_EQ(0, fj.make_writeable());
7c673cae
FG
425
426 list<C_Sync*> ls;
427
428 bufferlist bl;
429 char foo[1024*1024];
430 memset(foo, 1, sizeof(foo));
431
432 uint64_t seq = 1, committed = 0;
433 vector<ObjectStore::Transaction> tls;
434
435 for (unsigned i=0; i<size_mb*2; i++) {
436 bl.clear();
437 bl.push_back(buffer::copy(foo, sizeof(foo)));
438 bl.zero();
439 ls.push_back(new C_Sync);
31f18b77
FG
440 int orig_len = fj.prepare_entry(tls, &bl);
441 fj.reserve_throttle_and_backoff(bl.length());
442 fj.submit_entry(seq++, bl, orig_len, ls.back()->c);
7c673cae
FG
443
444 while (ls.size() > size_mb/2) {
445 delete ls.front();
446 ls.pop_front();
447 committed++;
31f18b77 448 fj.committed_thru(committed);
7c673cae
FG
449 }
450 }
451
452 while (ls.size()) {
453 delete ls.front();
454 ls.pop_front();
31f18b77 455 fj.committed_thru(++committed);
7c673cae
FG
456 }
457
31f18b77 458 ASSERT_TRUE(fj.journalq_empty());
7c673cae 459
31f18b77 460 fj.close();
7c673cae
FG
461 }
462}
463
464TEST(TestFileJournal, WriteTrimSmall) {
11fdf7f2
TL
465 g_ceph_context->_conf.set_val("journal_ignore_corruption", "false");
466 g_ceph_context->_conf.set_val("journal_write_header_frequency", "0");
467 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
468 vector<ObjectStore::Transaction> tls;
469
470 for (unsigned i = 0 ; i < 3; ++i) {
471 SCOPED_TRACE(subtests[i].description);
472 fsid.generate_random();
31f18b77 473 FileJournal fj(g_ceph_context, fsid, finisher, &sync_cond, path,
7c673cae 474 subtests[i].directio, subtests[i].aio, subtests[i].faio);
31f18b77
FG
475 ASSERT_EQ(0, fj.create());
476 ASSERT_EQ(0, fj.make_writeable());
7c673cae
FG
477
478 list<C_Sync*> ls;
479
480 bufferlist bl;
481 char foo[1024*1024];
482 memset(foo, 1, sizeof(foo));
483
484 uint64_t seq = 1, committed = 0;
485
486 for (unsigned i=0; i<size_mb*2; i++) {
487 bl.clear();
488 for (int k=0; k<128; k++)
489 bl.push_back(buffer::copy(foo, sizeof(foo) / 128));
490 bl.zero();
491 ls.push_back(new C_Sync);
31f18b77
FG
492 int orig_len = fj.prepare_entry(tls, &bl);
493 fj.reserve_throttle_and_backoff(bl.length());
494 fj.submit_entry(seq++, bl, orig_len, ls.back()->c);
7c673cae
FG
495
496 while (ls.size() > size_mb/2) {
497 delete ls.front();
498 ls.pop_front();
499 committed++;
31f18b77 500 fj.committed_thru(committed);
7c673cae
FG
501 }
502 }
503
504 while (ls.size()) {
505 delete ls.front();
506 ls.pop_front();
31f18b77 507 fj.committed_thru(committed);
7c673cae
FG
508 }
509
31f18b77 510 fj.close();
7c673cae
FG
511 }
512}
513
514TEST(TestFileJournal, ReplayDetectCorruptFooterMagic) {
11fdf7f2
TL
515 g_ceph_context->_conf.set_val("journal_ignore_corruption", "true");
516 g_ceph_context->_conf.set_val("journal_write_header_frequency", "1");
517 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
518
519 vector<ObjectStore::Transaction> tls;
520 for (unsigned i = 0 ; i < 3; ++i) {
521 SCOPED_TRACE(subtests[i].description);
522 fsid.generate_random();
31f18b77 523 FileJournal fj(g_ceph_context, fsid, finisher, &sync_cond, path,
7c673cae 524 subtests[i].directio, subtests[i].aio, subtests[i].faio);
31f18b77
FG
525 ASSERT_EQ(0, fj.create());
526 ASSERT_EQ(0, fj.make_writeable());
7c673cae
FG
527
528 C_GatherBuilder gb(g_ceph_context, new C_SafeCond(&wait_lock, &cond, &done));
529
530 const char *needle = "i am a needle";
531 for (unsigned i = 1; i <= 4; ++i) {
532 bufferlist bl;
533 bl.append(needle);
31f18b77
FG
534 int orig_len = fj.prepare_entry(tls, &bl);
535 fj.reserve_throttle_and_backoff(bl.length());
536 fj.submit_entry(i, bl, orig_len, gb.new_sub());
7c673cae
FG
537 }
538 gb.activate();
539 wait();
540
541 bufferlist bl;
542 bl.append("needle");
31f18b77
FG
543 int orig_len = fj.prepare_entry(tls, &bl);
544 fj.reserve_throttle_and_backoff(bl.length());
545 fj.submit_entry(5, bl, orig_len, new C_SafeCond(&wait_lock, &cond, &done));
7c673cae
FG
546 wait();
547
31f18b77 548 fj.close();
7c673cae
FG
549 int fd = open(path, O_WRONLY);
550
551 cout << "corrupting journal" << std::endl;
31f18b77
FG
552 fj.open(0);
553 fj.corrupt_footer_magic(fd, 2);
7c673cae
FG
554
555 uint64_t seq = 0;
556 bl.clear();
557 bool corrupt = false;
31f18b77 558 bool result = fj.read_entry(bl, seq, &corrupt);
7c673cae
FG
559 ASSERT_TRUE(result);
560 ASSERT_EQ(seq, 1UL);
561 ASSERT_FALSE(corrupt);
562
31f18b77 563 result = fj.read_entry(bl, seq, &corrupt);
7c673cae
FG
564 ASSERT_FALSE(result);
565 ASSERT_TRUE(corrupt);
566
31f18b77
FG
567 ASSERT_EQ(0, fj.make_writeable());
568 fj.close();
7c673cae
FG
569 ::close(fd);
570 }
571}
572
573TEST(TestFileJournal, ReplayDetectCorruptPayload) {
11fdf7f2
TL
574 g_ceph_context->_conf.set_val("journal_ignore_corruption", "true");
575 g_ceph_context->_conf.set_val("journal_write_header_frequency", "1");
576 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
577
578 vector<ObjectStore::Transaction> tls;
579 for (unsigned i = 0 ; i < 3; ++i) {
580 SCOPED_TRACE(subtests[i].description);
581 fsid.generate_random();
31f18b77 582 FileJournal fj(g_ceph_context, fsid, finisher, &sync_cond, path,
7c673cae 583 subtests[i].directio, subtests[i].aio, subtests[i].faio);
31f18b77
FG
584 ASSERT_EQ(0, fj.create());
585 ASSERT_EQ(0, fj.make_writeable());
7c673cae
FG
586
587 C_GatherBuilder gb(g_ceph_context, new C_SafeCond(&wait_lock, &cond, &done));
588
589 const char *needle = "i am a needle";
590 for (unsigned i = 1; i <= 4; ++i) {
591 bufferlist bl;
592 bl.append(needle);
31f18b77
FG
593 int orig_len = fj.prepare_entry(tls, &bl);
594 fj.reserve_throttle_and_backoff(bl.length());
595 fj.submit_entry(i, bl, orig_len, gb.new_sub());
7c673cae
FG
596 }
597 gb.activate();
598 wait();
599
600 bufferlist bl;
601 bl.append("needle");
31f18b77
FG
602 int orig_len = fj.prepare_entry(tls, &bl);
603 fj.reserve_throttle_and_backoff(bl.length());
604 fj.submit_entry(5, bl, orig_len, new C_SafeCond(&wait_lock, &cond, &done));
7c673cae
FG
605 wait();
606
31f18b77 607 fj.close();
7c673cae
FG
608 int fd = open(path, O_WRONLY);
609
610 cout << "corrupting journal" << std::endl;
31f18b77
FG
611 fj.open(0);
612 fj.corrupt_payload(fd, 2);
7c673cae
FG
613
614 uint64_t seq = 0;
615 bl.clear();
616 bool corrupt = false;
31f18b77 617 bool result = fj.read_entry(bl, seq, &corrupt);
7c673cae
FG
618 ASSERT_TRUE(result);
619 ASSERT_EQ(seq, 1UL);
620 ASSERT_FALSE(corrupt);
621
31f18b77 622 result = fj.read_entry(bl, seq, &corrupt);
7c673cae
FG
623 ASSERT_FALSE(result);
624 ASSERT_TRUE(corrupt);
625
31f18b77
FG
626 ASSERT_EQ(0, fj.make_writeable());
627 fj.close();
7c673cae
FG
628 ::close(fd);
629 }
630}
631
632TEST(TestFileJournal, ReplayDetectCorruptHeader) {
11fdf7f2
TL
633 g_ceph_context->_conf.set_val("journal_ignore_corruption", "true");
634 g_ceph_context->_conf.set_val("journal_write_header_frequency", "1");
635 g_ceph_context->_conf.apply_changes(nullptr);
7c673cae
FG
636
637 vector<ObjectStore::Transaction> tls;
638 for (unsigned i = 0 ; i < 3; ++i) {
639 SCOPED_TRACE(subtests[i].description);
640 fsid.generate_random();
31f18b77 641 FileJournal fj(g_ceph_context, fsid, finisher, &sync_cond, path,
7c673cae 642 subtests[i].directio, subtests[i].aio, subtests[i].faio);
31f18b77
FG
643 ASSERT_EQ(0, fj.create());
644 ASSERT_EQ(0, fj.make_writeable());
7c673cae
FG
645
646 C_GatherBuilder gb(g_ceph_context, new C_SafeCond(&wait_lock, &cond, &done));
647
648 const char *needle = "i am a needle";
649 for (unsigned i = 1; i <= 4; ++i) {
650 bufferlist bl;
651 bl.append(needle);
31f18b77
FG
652 int orig_len = fj.prepare_entry(tls, &bl);
653 fj.reserve_throttle_and_backoff(bl.length());
654 fj.submit_entry(i, bl, orig_len, gb.new_sub());
7c673cae
FG
655 }
656 gb.activate();
657 wait();
658
659 bufferlist bl;
660 bl.append("needle");
31f18b77
FG
661 int orig_len = fj.prepare_entry(tls, &bl);
662 fj.reserve_throttle_and_backoff(bl.length());
663 fj.submit_entry(5, bl, orig_len, new C_SafeCond(&wait_lock, &cond, &done));
7c673cae
FG
664 wait();
665
31f18b77 666 fj.close();
7c673cae
FG
667 int fd = open(path, O_WRONLY);
668
669 cout << "corrupting journal" << std::endl;
31f18b77
FG
670 fj.open(0);
671 fj.corrupt_header_magic(fd, 2);
7c673cae
FG
672
673 uint64_t seq = 0;
674 bl.clear();
675 bool corrupt = false;
31f18b77 676 bool result = fj.read_entry(bl, seq, &corrupt);
7c673cae
FG
677 ASSERT_TRUE(result);
678 ASSERT_EQ(seq, 1UL);
679 ASSERT_FALSE(corrupt);
680
31f18b77 681 result = fj.read_entry(bl, seq, &corrupt);
7c673cae
FG
682 ASSERT_FALSE(result);
683 ASSERT_TRUE(corrupt);
684
31f18b77
FG
685 ASSERT_EQ(0, fj.make_writeable());
686 fj.close();
7c673cae
FG
687 ::close(fd);
688 }
689}