Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/cddl/usr.sbin/zfsd/tests/zfsd_unittest.cc
108545 views
1
/*-
2
* Copyright (c) 2012, 2013, 2014 Spectra Logic Corporation
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions, and the following disclaimer,
10
* without modification.
11
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
12
* substantially similar to the "NO WARRANTY" disclaimer below
13
* ("Disclaimer") and any redistribution must be conditioned upon
14
* including a substantially similar Disclaimer requirement for further
15
* binary redistribution.
16
*
17
* NO WARRANTY
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
* POSSIBILITY OF SUCH DAMAGES.
29
*
30
* Authors: Alan Somers (Spectra Logic Corporation)
31
*/
32
#include <sys/cdefs.h>
33
#include <sys/byteorder.h>
34
35
#include <stdarg.h>
36
#include <syslog.h>
37
38
#include <libnvpair.h>
39
#include <libzfs.h>
40
41
#include <list>
42
#include <map>
43
#include <sstream>
44
#include <string>
45
46
#include <gmock/gmock.h>
47
#include <gtest/gtest.h>
48
49
#include <devdctl/guid.h>
50
#include <devdctl/event.h>
51
#include <devdctl/event_factory.h>
52
#include <devdctl/exception.h>
53
#include <devdctl/consumer.h>
54
55
#include <zfsd/callout.h>
56
#include <zfsd/vdev_iterator.h>
57
#include <zfsd/zfsd_event.h>
58
#include <zfsd/case_file.h>
59
#include <zfsd/vdev.h>
60
#include <zfsd/zfsd.h>
61
#include <zfsd/zfsd_exception.h>
62
#include <zfsd/zpool_list.h>
63
64
#include "libmocks.h"
65
/*================================== Macros ==================================*/
66
#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
67
68
/*============================ Namespace Control =============================*/
69
using std::string;
70
using std::stringstream;
71
72
using DevdCtl::Event;
73
using DevdCtl::EventFactory;
74
using DevdCtl::EventList;
75
using DevdCtl::Guid;
76
using DevdCtl::NVPairMap;
77
78
/* redefine zpool_handle here because libzfs_impl.h is not includable */
79
struct zpool_handle
80
{
81
libzfs_handle_t *zpool_hdl;
82
zpool_handle_t *zpool_next;
83
char zpool_name[ZFS_MAX_DATASET_NAME_LEN];
84
int zpool_state;
85
unsigned int zpool_n_propnames;
86
#define ZHP_MAX_PROPNAMES 4
87
const char *zpool_propnames[ZHP_MAX_PROPNAMES];
88
size_t zpool_config_size;
89
nvlist_t *zpool_config;
90
nvlist_t *zpool_old_config;
91
nvlist_t *zpool_props;
92
diskaddr_t zpool_start_block;
93
};
94
95
class MockZfsEvent : public ZfsEvent
96
{
97
public:
98
MockZfsEvent(Event::Type, NVPairMap&, const string&);
99
virtual ~MockZfsEvent() {}
100
101
static BuildMethod MockZfsEventBuilder;
102
103
MOCK_CONST_METHOD0(ProcessPoolEvent, void());
104
105
static EventFactory::Record s_buildRecords[];
106
};
107
108
EventFactory::Record MockZfsEvent::s_buildRecords[] =
109
{
110
{ Event::NOTIFY, "ZFS", &MockZfsEvent::MockZfsEventBuilder }
111
};
112
113
MockZfsEvent::MockZfsEvent(Event::Type type, NVPairMap& map,
114
const string& str)
115
: ZfsEvent(type, map, str)
116
{
117
}
118
119
Event *
120
MockZfsEvent::MockZfsEventBuilder(Event::Type type,
121
NVPairMap &nvpairs,
122
const string &eventString)
123
{
124
return (new MockZfsEvent(type, nvpairs, eventString));
125
}
126
127
/*
128
* A dummy Vdev class used for testing other classes
129
*/
130
class MockVdev : public Vdev
131
{
132
public:
133
MockVdev(nvlist_t *vdevConfig);
134
virtual ~MockVdev() {}
135
136
MOCK_CONST_METHOD0(GUID, Guid());
137
MOCK_CONST_METHOD0(PoolGUID, Guid());
138
MOCK_CONST_METHOD0(State, vdev_state());
139
MOCK_CONST_METHOD0(PhysicalPath, string());
140
MOCK_CONST_METHOD2(Name, string(zpool_handle_t * zhp, bool verbose));
141
};
142
143
MockVdev::MockVdev(nvlist_t *vdevConfig)
144
: Vdev(vdevConfig)
145
{
146
}
147
148
/*
149
* A CaseFile class with side effects removed, for testing
150
*/
151
class TestableCaseFile : public CaseFile
152
{
153
public:
154
static TestableCaseFile &Create(Vdev &vdev);
155
TestableCaseFile(Vdev &vdev);
156
virtual ~TestableCaseFile() {}
157
158
MOCK_METHOD0(Close, void());
159
MOCK_METHOD1(RegisterCallout, void(const Event &event));
160
MOCK_METHOD0(RefreshVdevState, bool());
161
MOCK_METHOD1(ReEvaluate, bool(const ZfsEvent &event));
162
163
bool RealReEvaluate(const ZfsEvent &event)
164
{
165
return (CaseFile::ReEvaluate(event));
166
}
167
168
/*
169
* This splices the event lists, a procedure that would normally be done
170
* by OnGracePeriodEnded, but we don't necessarily call that in the
171
* unit tests
172
*/
173
void SpliceEvents();
174
175
/*
176
* Used by some of our expectations. CaseFile does not publicize this
177
*/
178
static int getActiveCases()
179
{
180
return (s_activeCases.size());
181
}
182
};
183
184
TestableCaseFile::TestableCaseFile(Vdev &vdev)
185
: CaseFile(vdev)
186
{
187
}
188
189
TestableCaseFile &
190
TestableCaseFile::Create(Vdev &vdev)
191
{
192
TestableCaseFile *newCase;
193
newCase = new TestableCaseFile(vdev);
194
return (*newCase);
195
}
196
197
void
198
TestableCaseFile::SpliceEvents()
199
{
200
m_events.splice(m_events.begin(), m_tentativeEvents);
201
}
202
203
204
/*
205
* Test class ZfsdException
206
*/
207
class ZfsdExceptionTest : public ::testing::Test
208
{
209
protected:
210
virtual void SetUp()
211
{
212
ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0));
213
ASSERT_EQ(0, nvlist_add_string(poolConfig,
214
ZPOOL_CONFIG_POOL_NAME, "unit_test_pool"));
215
ASSERT_EQ(0, nvlist_add_uint64(poolConfig,
216
ZPOOL_CONFIG_POOL_GUID, 0x1234));
217
218
ASSERT_EQ(0, nvlist_alloc(&vdevConfig, NV_UNIQUE_NAME, 0));
219
ASSERT_EQ(0, nvlist_add_uint64(vdevConfig,
220
ZPOOL_CONFIG_GUID, 0x5678));
221
bzero(&poolHandle, sizeof(poolHandle));
222
poolHandle.zpool_config = poolConfig;
223
}
224
225
virtual void TearDown()
226
{
227
nvlist_free(poolConfig);
228
nvlist_free(vdevConfig);
229
}
230
231
nvlist_t *poolConfig;
232
nvlist_t *vdevConfig;
233
zpool_handle_t poolHandle;
234
};
235
236
TEST_F(ZfsdExceptionTest, StringConstructorNull)
237
{
238
ZfsdException ze("");
239
EXPECT_STREQ("", ze.GetString().c_str());
240
}
241
242
TEST_F(ZfsdExceptionTest, StringConstructorFormatted)
243
{
244
ZfsdException ze(" %d %s", 55, "hello world");
245
EXPECT_STREQ(" 55 hello world", ze.GetString().c_str());
246
}
247
248
TEST_F(ZfsdExceptionTest, LogSimple)
249
{
250
ZfsdException ze("unit test w/o vdev or pool");
251
ze.Log();
252
EXPECT_EQ(LOG_ERR, syslog_last_priority);
253
EXPECT_STREQ("unit test w/o vdev or pool\n", syslog_last_message);
254
}
255
256
TEST_F(ZfsdExceptionTest, Pool)
257
{
258
const char msg[] = "Exception with pool name";
259
char expected[4096];
260
sprintf(expected, "Pool unit_test_pool: %s\n", msg);
261
ZfsdException ze(poolConfig, msg);
262
ze.Log();
263
EXPECT_STREQ(expected, syslog_last_message);
264
}
265
266
TEST_F(ZfsdExceptionTest, PoolHandle)
267
{
268
const char msg[] = "Exception with pool handle";
269
char expected[4096];
270
sprintf(expected, "Pool unit_test_pool: %s\n", msg);
271
ZfsdException ze(&poolHandle, msg);
272
ze.Log();
273
EXPECT_STREQ(expected, syslog_last_message);
274
}
275
276
/*
277
* Test class Vdev
278
*/
279
class VdevTest : public ::testing::Test
280
{
281
protected:
282
virtual void SetUp()
283
{
284
ASSERT_EQ(0, nvlist_alloc(&m_poolConfig, NV_UNIQUE_NAME, 0));
285
ASSERT_EQ(0, nvlist_add_uint64(m_poolConfig,
286
ZPOOL_CONFIG_POOL_GUID,
287
0x1234));
288
289
ASSERT_EQ(0, nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0));
290
ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_GUID,
291
0x5678));
292
}
293
294
virtual void TearDown()
295
{
296
nvlist_free(m_poolConfig);
297
nvlist_free(m_vdevConfig);
298
}
299
300
nvlist_t *m_poolConfig;
301
nvlist_t *m_vdevConfig;
302
};
303
304
305
TEST_F(VdevTest, StateFromConfig)
306
{
307
vdev_stat_t vs;
308
309
vs.vs_state = VDEV_STATE_OFFLINE;
310
311
ASSERT_EQ(0, nvlist_add_uint64_array(m_vdevConfig,
312
ZPOOL_CONFIG_VDEV_STATS,
313
(uint64_t*)&vs,
314
sizeof(vs) / sizeof(uint64_t)));
315
316
Vdev vdev(m_poolConfig, m_vdevConfig);
317
318
EXPECT_EQ(VDEV_STATE_OFFLINE, vdev.State());
319
}
320
321
TEST_F(VdevTest, StateFaulted)
322
{
323
ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_FAULTED, 1));
324
325
Vdev vdev(m_poolConfig, m_vdevConfig);
326
327
EXPECT_EQ(VDEV_STATE_FAULTED, vdev.State());
328
}
329
330
/*
331
* Test that we can construct a Vdev from the label information that is stored
332
* on an available spare drive
333
*/
334
TEST_F(VdevTest, ConstructAvailSpare)
335
{
336
nvlist_t *labelConfig;
337
338
ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0));
339
ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID,
340
1948339428197961030));
341
ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE,
342
POOL_STATE_SPARE));
343
344
EXPECT_NO_THROW(Vdev vdev(labelConfig));
345
346
nvlist_free(labelConfig);
347
}
348
349
/* Available spares will always show the HEALTHY state */
350
TEST_F(VdevTest, AvailSpareState) {
351
nvlist_t *labelConfig;
352
353
ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0));
354
ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID,
355
1948339428197961030));
356
ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE,
357
POOL_STATE_SPARE));
358
359
Vdev vdev(labelConfig);
360
EXPECT_EQ(VDEV_STATE_HEALTHY, vdev.State());
361
362
nvlist_free(labelConfig);
363
}
364
365
/* Test the Vdev::IsSpare method */
366
TEST_F(VdevTest, IsSpare) {
367
Vdev notSpare(m_poolConfig, m_vdevConfig);
368
EXPECT_EQ(false, notSpare.IsSpare());
369
370
ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_IS_SPARE, 1));
371
Vdev isSpare(m_poolConfig, m_vdevConfig);
372
EXPECT_EQ(true, isSpare.IsSpare());
373
}
374
375
/*
376
* Test class ZFSEvent
377
*/
378
class ZfsEventTest : public ::testing::Test
379
{
380
protected:
381
virtual void SetUp()
382
{
383
m_eventFactory = new EventFactory();
384
m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
385
NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
386
387
m_event = NULL;
388
}
389
390
virtual void TearDown()
391
{
392
delete m_eventFactory;
393
delete m_event;
394
}
395
396
EventFactory *m_eventFactory;
397
Event *m_event;
398
};
399
400
TEST_F(ZfsEventTest, ProcessPoolEventGetsCalled)
401
{
402
string evString("!system=ZFS "
403
"subsystem=ZFS "
404
"type=sysevent.fs.zfs.vdev_remove "
405
"pool_name=foo "
406
"pool_guid=9756779504028057996 "
407
"vdev_guid=1631193447431603339 "
408
"vdev_path=/dev/da1 "
409
"timestamp=1348871594");
410
m_event = Event::CreateEvent(*m_eventFactory, evString);
411
MockZfsEvent *mock_event = static_cast<MockZfsEvent*>(m_event);
412
413
EXPECT_CALL(*mock_event, ProcessPoolEvent()).Times(1);
414
mock_event->Process();
415
}
416
417
/*
418
* Test class CaseFile
419
*/
420
421
class CaseFileTest : public ::testing::Test
422
{
423
protected:
424
virtual void SetUp()
425
{
426
m_eventFactory = new EventFactory();
427
m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
428
NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
429
430
m_event = NULL;
431
432
nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0);
433
ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig,
434
ZPOOL_CONFIG_GUID, 0xbeef));
435
m_vdev = new MockVdev(m_vdevConfig);
436
ON_CALL(*m_vdev, GUID())
437
.WillByDefault(::testing::Return(Guid(123)));
438
ON_CALL(*m_vdev, Name(::testing::_, ::testing::_))
439
.WillByDefault(::testing::Return(string("/dev/da999")));
440
ON_CALL(*m_vdev, PoolGUID())
441
.WillByDefault(::testing::Return(Guid(456)));
442
ON_CALL(*m_vdev, State())
443
.WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
444
m_caseFile = &TestableCaseFile::Create(*m_vdev);
445
ON_CALL(*m_caseFile, ReEvaluate(::testing::_))
446
.WillByDefault(::testing::Invoke(m_caseFile, &TestableCaseFile::RealReEvaluate));
447
return;
448
}
449
450
virtual void TearDown()
451
{
452
delete m_caseFile;
453
nvlist_free(m_vdevConfig);
454
delete m_vdev;
455
delete m_event;
456
delete m_eventFactory;
457
}
458
459
nvlist_t *m_vdevConfig;
460
MockVdev *m_vdev;
461
TestableCaseFile *m_caseFile;
462
Event *m_event;
463
EventFactory *m_eventFactory;
464
};
465
466
/*
467
* A Vdev with no events should not be degraded or faulted
468
*/
469
TEST_F(CaseFileTest, HealthyVdev)
470
{
471
EXPECT_FALSE(m_caseFile->ShouldDegrade());
472
EXPECT_FALSE(m_caseFile->ShouldFault());
473
}
474
475
/*
476
* A Vdev with only one event should not be degraded or faulted
477
* For performance reasons, RefreshVdevState should not be called.
478
*/
479
TEST_F(CaseFileTest, HealthyishVdev)
480
{
481
string evString("!system=ZFS "
482
"class=ereport.fs.zfs.io "
483
"ena=12091638756982918145 "
484
"parent_guid=13237004955564865395 "
485
"parent_type=raidz "
486
"pool=testpool.4415 "
487
"pool_context=0 "
488
"pool_failmode=wait "
489
"pool_guid=456 "
490
"subsystem=ZFS "
491
"timestamp=1348867914 "
492
"type=ereport.fs.zfs.io "
493
"vdev_guid=123 "
494
"vdev_path=/dev/da400 "
495
"vdev_type=disk "
496
"zio_blkid=622 "
497
"zio_err=1 "
498
"zio_level=-2 "
499
"zio_object=0 "
500
"zio_objset=37 "
501
"zio_offset=25598976 "
502
"zio_size=1024");
503
m_event = Event::CreateEvent(*m_eventFactory, evString);
504
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
505
506
EXPECT_CALL(*m_caseFile, RefreshVdevState())
507
.Times(::testing::Exactly(0));
508
EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
509
EXPECT_FALSE(m_caseFile->ShouldDegrade());
510
EXPECT_FALSE(m_caseFile->ShouldFault());
511
}
512
513
/* The case file should be closed when its pool is destroyed */
514
TEST_F(CaseFileTest, PoolDestroy)
515
{
516
string evString("!system=ZFS "
517
"pool_name=testpool.4415 "
518
"pool_guid=456 "
519
"subsystem=ZFS "
520
"timestamp=1348867914 "
521
"type=sysevent.fs.zfs.pool_destroy ");
522
m_event = Event::CreateEvent(*m_eventFactory, evString);
523
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
524
EXPECT_CALL(*m_caseFile, Close());
525
EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
526
}
527
528
/*
529
* A Vdev with a very large number of Delay errors should fault
530
* For performance reasons, RefreshVdevState should be called at most once
531
*/
532
TEST_F(CaseFileTest, VeryManyDelayErrors)
533
{
534
EXPECT_CALL(*m_caseFile, RefreshVdevState())
535
.Times(::testing::AtMost(1))
536
.WillRepeatedly(::testing::Return(true));
537
538
for(int i=0; i<100; i++) {
539
stringstream evStringStream;
540
evStringStream <<
541
"!system=ZFS "
542
"class=ereport.fs.zfs.delay "
543
"ena=12091638756982918145 "
544
"parent_guid=13237004955564865395 "
545
"parent_type=raidz "
546
"pool=testpool.4415 "
547
"pool_context=0 "
548
"pool_failmode=wait "
549
"pool_guid=456 "
550
"pool_state= 0"
551
"subsystem=ZFS "
552
"time=";
553
evStringStream << i << "0000000000000000 ";
554
evStringStream << "timestamp=" << i << " ";
555
evStringStream <<
556
"type=ereport.fs.zfs.delay "
557
"vdev_ashift=12 "
558
"vdev_cksum_errors=0 "
559
"vdev_complete_ts=948336226469 "
560
"vdev_delays=77 "
561
"vdev_delta_ts=123998485899 "
562
"vdev_guid=123 "
563
"vdev_path=/dev/da400 "
564
"vdev_read_errors=0 "
565
"vdev_spare_guids= "
566
"vdev_type=disk "
567
"vdev_write_errors=0 "
568
"zio_blkid=622 "
569
"zio_delay=31000041101 "
570
"zio_delta=123998485899 "
571
"zio_err=0 "
572
"zio_flags=1572992 "
573
"zio_level=-2 "
574
"zio_object=0 "
575
"zio_objset=37 "
576
"zio_offset=25598976 "
577
"zio_pipeline=48234496 "
578
"zio_priority=3 "
579
"zio_size=1024"
580
"zio_stage=33554432 "
581
"zio_timestamp=824337740570 ";
582
Event *event(Event::CreateEvent(*m_eventFactory,
583
evStringStream.str()));
584
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
585
EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
586
delete event;
587
}
588
589
m_caseFile->SpliceEvents();
590
EXPECT_FALSE(m_caseFile->ShouldDegrade());
591
EXPECT_TRUE(m_caseFile->ShouldFault());
592
}
593
594
/*
595
* A Vdev with a very large number of IO errors should fault
596
* For performance reasons, RefreshVdevState should be called at most once
597
*/
598
TEST_F(CaseFileTest, VeryManyIOErrors)
599
{
600
EXPECT_CALL(*m_caseFile, RefreshVdevState())
601
.Times(::testing::AtMost(1))
602
.WillRepeatedly(::testing::Return(true));
603
604
for(int i=0; i<100; i++) {
605
stringstream evStringStream;
606
evStringStream <<
607
"!system=ZFS "
608
"class=ereport.fs.zfs.io "
609
"ena=12091638756982918145 "
610
"parent_guid=13237004955564865395 "
611
"parent_type=raidz "
612
"pool=testpool.4415 "
613
"pool_context=0 "
614
"pool_failmode=wait "
615
"pool_guid=456 "
616
"subsystem=ZFS "
617
"timestamp=";
618
evStringStream << i << " ";
619
evStringStream <<
620
"type=ereport.fs.zfs.io "
621
"vdev_guid=123 "
622
"vdev_path=/dev/da400 "
623
"vdev_type=disk "
624
"zio_blkid=622 "
625
"zio_err=1 "
626
"zio_level=-2 "
627
"zio_object=0 "
628
"zio_objset=37 "
629
"zio_offset=25598976 "
630
"zio_size=1024";
631
Event *event(Event::CreateEvent(*m_eventFactory,
632
evStringStream.str()));
633
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
634
EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
635
delete event;
636
}
637
638
m_caseFile->SpliceEvents();
639
EXPECT_FALSE(m_caseFile->ShouldDegrade());
640
EXPECT_TRUE(m_caseFile->ShouldFault());
641
}
642
643
/*
644
* A Vdev with a very large number of checksum errors should degrade
645
* For performance reasons, RefreshVdevState should be called at most once
646
*/
647
TEST_F(CaseFileTest, VeryManyChecksumErrors)
648
{
649
EXPECT_CALL(*m_caseFile, RefreshVdevState())
650
.Times(::testing::AtMost(1))
651
.WillRepeatedly(::testing::Return(true));
652
653
for(int i=0; i<100; i++) {
654
stringstream evStringStream;
655
evStringStream <<
656
"!system=ZFS "
657
"bad_cleared_bits=03000000000000803f50b00000000000 "
658
"bad_range_clears=0000000e "
659
"bad_range_sets=00000000 "
660
"bad_ranges=0000000000000010 "
661
"bad_ranges_min_gap=8 "
662
"bad_set_bits=00000000000000000000000000000000 "
663
"class=ereport.fs.zfs.checksum "
664
"ena=12272856582652437505 "
665
"parent_guid=5838204195352909894 "
666
"parent_type=raidz pool=testpool.7640 "
667
"pool_context=0 "
668
"pool_failmode=wait "
669
"pool_guid=456 "
670
"subsystem=ZFS timestamp=";
671
evStringStream << i << " ";
672
evStringStream <<
673
"type=ereport.fs.zfs.checksum "
674
"vdev_guid=123 "
675
"vdev_path=/mnt/tmp/file1.7702 "
676
"vdev_type=file "
677
"zio_blkid=0 "
678
"zio_err=0 "
679
"zio_level=0 "
680
"zio_object=3 "
681
"zio_objset=0 "
682
"zio_offset=16896 "
683
"zio_size=512";
684
Event *event(Event::CreateEvent(*m_eventFactory,
685
evStringStream.str()));
686
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
687
EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
688
delete event;
689
}
690
691
m_caseFile->SpliceEvents();
692
EXPECT_TRUE(m_caseFile->ShouldDegrade());
693
EXPECT_FALSE(m_caseFile->ShouldFault());
694
}
695
696
/*
697
* Test CaseFile::ReEvaluateByGuid
698
*/
699
class ReEvaluateByGuidTest : public ::testing::Test
700
{
701
protected:
702
virtual void SetUp()
703
{
704
m_eventFactory = new EventFactory();
705
m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
706
NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
707
m_event = Event::CreateEvent(*m_eventFactory, s_evString);
708
nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0);
709
ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig,
710
ZPOOL_CONFIG_GUID, 0xbeef));
711
m_vdev456 = new ::testing::NiceMock<MockVdev>(m_vdevConfig);
712
m_vdev789 = new ::testing::NiceMock<MockVdev>(m_vdevConfig);
713
ON_CALL(*m_vdev456, GUID())
714
.WillByDefault(::testing::Return(Guid(123)));
715
ON_CALL(*m_vdev456, PoolGUID())
716
.WillByDefault(::testing::Return(Guid(456)));
717
ON_CALL(*m_vdev456, State())
718
.WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
719
ON_CALL(*m_vdev789, GUID())
720
.WillByDefault(::testing::Return(Guid(123)));
721
ON_CALL(*m_vdev789, PoolGUID())
722
.WillByDefault(::testing::Return(Guid(789)));
723
ON_CALL(*m_vdev789, State())
724
.WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
725
m_caseFile456 = NULL;
726
m_caseFile789 = NULL;
727
return;
728
}
729
730
virtual void TearDown()
731
{
732
delete m_caseFile456;
733
delete m_caseFile789;
734
nvlist_free(m_vdevConfig);
735
delete m_vdev456;
736
delete m_vdev789;
737
delete m_event;
738
delete m_eventFactory;
739
}
740
741
static string s_evString;
742
nvlist_t *m_vdevConfig;
743
::testing::NiceMock<MockVdev> *m_vdev456;
744
::testing::NiceMock<MockVdev> *m_vdev789;
745
TestableCaseFile *m_caseFile456;
746
TestableCaseFile *m_caseFile789;
747
Event *m_event;
748
EventFactory *m_eventFactory;
749
};
750
751
string ReEvaluateByGuidTest::s_evString(
752
"!system=ZFS "
753
"pool_guid=16271873792808333580 "
754
"pool_name=foo "
755
"subsystem=ZFS "
756
"timestamp=1360620391 "
757
"type=sysevent.fs.zfs.config_sync");
758
759
760
/*
761
* Test the ReEvaluateByGuid method on an empty list of casefiles.
762
* We must create one event, even though it never gets used, because it will
763
* be passed by reference to ReEvaluateByGuid
764
*/
765
TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_empty)
766
{
767
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
768
769
EXPECT_EQ(0, TestableCaseFile::getActiveCases());
770
CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
771
EXPECT_EQ(0, TestableCaseFile::getActiveCases());
772
}
773
774
/*
775
* Test the ReEvaluateByGuid method on a list of CaseFiles that contains only
776
* one CaseFile, which doesn't match the criteria
777
*/
778
TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneFalse)
779
{
780
m_caseFile456 = &TestableCaseFile::Create(*m_vdev456);
781
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
782
783
EXPECT_EQ(1, TestableCaseFile::getActiveCases());
784
EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_))
785
.Times(::testing::Exactly(0));
786
CaseFile::ReEvaluateByGuid(Guid(789), *zfs_event);
787
EXPECT_EQ(1, TestableCaseFile::getActiveCases());
788
}
789
790
/*
791
* Test the ReEvaluateByGuid method on a list of CaseFiles that contains only
792
* one CaseFile, which does match the criteria
793
*/
794
TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneTrue)
795
{
796
m_caseFile456 = &TestableCaseFile::Create(*m_vdev456);
797
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
798
799
EXPECT_EQ(1, TestableCaseFile::getActiveCases());
800
EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_))
801
.Times(::testing::Exactly(1))
802
.WillRepeatedly(::testing::Return(false));
803
CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
804
EXPECT_EQ(1, TestableCaseFile::getActiveCases());
805
}
806
807
/*
808
* Test the ReEvaluateByGuid method on a long list of CaseFiles that contains a
809
* few cases which meet the criteria
810
*/
811
TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_five)
812
{
813
TestableCaseFile *CaseFile1 = &TestableCaseFile::Create(*m_vdev456);
814
TestableCaseFile *CaseFile2 = &TestableCaseFile::Create(*m_vdev789);
815
TestableCaseFile *CaseFile3 = &TestableCaseFile::Create(*m_vdev456);
816
TestableCaseFile *CaseFile4 = &TestableCaseFile::Create(*m_vdev789);
817
TestableCaseFile *CaseFile5 = &TestableCaseFile::Create(*m_vdev789);
818
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
819
820
EXPECT_EQ(5, TestableCaseFile::getActiveCases());
821
EXPECT_CALL(*CaseFile1, ReEvaluate(::testing::_))
822
.Times(::testing::Exactly(1))
823
.WillRepeatedly(::testing::Return(false));
824
EXPECT_CALL(*CaseFile3, ReEvaluate(::testing::_))
825
.Times(::testing::Exactly(1))
826
.WillRepeatedly(::testing::Return(false));
827
EXPECT_CALL(*CaseFile2, ReEvaluate(::testing::_))
828
.Times(::testing::Exactly(0));
829
EXPECT_CALL(*CaseFile4, ReEvaluate(::testing::_))
830
.Times(::testing::Exactly(0));
831
EXPECT_CALL(*CaseFile5, ReEvaluate(::testing::_))
832
.Times(::testing::Exactly(0));
833
CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
834
EXPECT_EQ(5, TestableCaseFile::getActiveCases());
835
delete CaseFile1;
836
delete CaseFile2;
837
delete CaseFile3;
838
delete CaseFile4;
839
delete CaseFile5;
840
}
841
842
/*
843
* Test VdevIterator
844
*/
845
class VdevIteratorTest : public ::testing::Test
846
{
847
};
848
849
bool VdevIteratorTestCB(Vdev &vdev, void *cbArg) {
850
return (false);
851
}
852
853
/*
854
* VdevIterator::Next should not crash when run on a pool that has a previously
855
* removed vdev. Regression for
856
* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=273663
857
*/
858
TEST_F(VdevIteratorTest, VdevRemoval)
859
{
860
nvlist_t* poolConfig, *rootVdev;
861
862
ASSERT_EQ(0, nvlist_alloc(&rootVdev, NV_UNIQUE_NAME, 0));
863
ASSERT_EQ(0, nvlist_add_uint64(rootVdev, ZPOOL_CONFIG_GUID, 0x5678));
864
/*
865
* Note: pools with previously-removed top-level VDEVs will contain a
866
* TLV in their labels that has 0 children.
867
*/
868
ASSERT_EQ(0, nvlist_add_nvlist_array(rootVdev, ZPOOL_CONFIG_CHILDREN,
869
NULL, 0));
870
ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0));
871
ASSERT_EQ(0, nvlist_add_uint64(poolConfig,
872
ZPOOL_CONFIG_POOL_GUID, 0x1234));
873
ASSERT_EQ(0, nvlist_add_nvlist(poolConfig, ZPOOL_CONFIG_VDEV_TREE,
874
rootVdev));
875
876
VdevIterator(poolConfig).Each(VdevIteratorTestCB, NULL);
877
}
878
879