aboutsummaryrefslogtreecommitdiff
path: root/cddl/usr.sbin/zfsd
diff options
context:
space:
mode:
Diffstat (limited to 'cddl/usr.sbin/zfsd')
-rw-r--r--cddl/usr.sbin/zfsd/Makefile2
-rw-r--r--cddl/usr.sbin/zfsd/Makefile.common3
-rw-r--r--cddl/usr.sbin/zfsd/Makefile.depend8
-rw-r--r--cddl/usr.sbin/zfsd/callout.cc2
-rw-r--r--cddl/usr.sbin/zfsd/callout.h2
-rw-r--r--cddl/usr.sbin/zfsd/case_file.cc151
-rw-r--r--cddl/usr.sbin/zfsd/case_file.h45
-rw-r--r--cddl/usr.sbin/zfsd/tests/Makefile1
-rw-r--r--cddl/usr.sbin/zfsd/tests/libmocks.c2
-rw-r--r--cddl/usr.sbin/zfsd/tests/libmocks.h2
-rw-r--r--cddl/usr.sbin/zfsd/tests/zfsd_unittest.cc115
-rw-r--r--cddl/usr.sbin/zfsd/tests/zfsd_unittest.supp1
-rw-r--r--cddl/usr.sbin/zfsd/vdev.cc8
-rw-r--r--cddl/usr.sbin/zfsd/vdev.h4
-rw-r--r--cddl/usr.sbin/zfsd/vdev_iterator.cc16
-rw-r--r--cddl/usr.sbin/zfsd/vdev_iterator.h2
-rw-r--r--cddl/usr.sbin/zfsd/zfsd.860
-rw-r--r--cddl/usr.sbin/zfsd/zfsd.cc7
-rw-r--r--cddl/usr.sbin/zfsd/zfsd.h2
-rw-r--r--cddl/usr.sbin/zfsd/zfsd_event.cc26
-rw-r--r--cddl/usr.sbin/zfsd/zfsd_event.h2
-rw-r--r--cddl/usr.sbin/zfsd/zfsd_exception.cc4
-rw-r--r--cddl/usr.sbin/zfsd/zfsd_exception.h2
-rw-r--r--cddl/usr.sbin/zfsd/zfsd_main.cc3
-rw-r--r--cddl/usr.sbin/zfsd/zpool_list.cc2
-rw-r--r--cddl/usr.sbin/zfsd/zpool_list.h4
26 files changed, 346 insertions, 130 deletions
diff --git a/cddl/usr.sbin/zfsd/Makefile b/cddl/usr.sbin/zfsd/Makefile
index 88eb9220a8cc..93426c0320af 100644
--- a/cddl/usr.sbin/zfsd/Makefile
+++ b/cddl/usr.sbin/zfsd/Makefile
@@ -1,9 +1,9 @@
-# $FreeBSD$
.include <src.opts.mk>
.include "Makefile.common"
+PACKAGE= zfs
PROG_CXX= zfsd
MAN= zfsd.8
diff --git a/cddl/usr.sbin/zfsd/Makefile.common b/cddl/usr.sbin/zfsd/Makefile.common
index 68d921c90e37..c1ed4bba9289 100644
--- a/cddl/usr.sbin/zfsd/Makefile.common
+++ b/cddl/usr.sbin/zfsd/Makefile.common
@@ -1,4 +1,3 @@
-# $FreeBSD$
SRCS= callout.cc \
case_file.cc \
@@ -23,8 +22,8 @@ CFLAGS+= -I${SRCTOP}/sys
CFLAGS+= -include ${SRCTOP}/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h
CFLAGS+= -I${SRCTOP}/cddl/usr.sbin
-# use issetugid(2)
CFLAGS+= -DHAVE_ISSETUGID
+CFLAGS+= -DHAVE_EXECVPE
LIBADD+= devdctl zfs util geom bsdxml sbuf nvpair avl uutil zutil
diff --git a/cddl/usr.sbin/zfsd/Makefile.depend b/cddl/usr.sbin/zfsd/Makefile.depend
index 023a4456ec68..4b9049efecdc 100644
--- a/cddl/usr.sbin/zfsd/Makefile.depend
+++ b/cddl/usr.sbin/zfsd/Makefile.depend
@@ -1,14 +1,11 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
cddl/lib/libavl \
cddl/lib/libnvpair \
- cddl/lib/libumem \
cddl/lib/libuutil \
cddl/lib/libzfs \
- cddl/lib/libzfs_core \
- gnu/lib/csu \
+ cddl/lib/libzutil \
include \
include/xlocale \
lib/${CSU_DIR} \
@@ -19,11 +16,8 @@ DIRDEPS = \
lib/libdevdctl \
lib/libexpat \
lib/libgeom \
- lib/libmd \
lib/libsbuf \
- lib/libthr \
lib/libutil \
- lib/libz \
lib/msun \
diff --git a/cddl/usr.sbin/zfsd/callout.cc b/cddl/usr.sbin/zfsd/callout.cc
index 3e5cd5779559..c141e6550f41 100644
--- a/cddl/usr.sbin/zfsd/callout.cc
+++ b/cddl/usr.sbin/zfsd/callout.cc
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
/**
diff --git a/cddl/usr.sbin/zfsd/callout.h b/cddl/usr.sbin/zfsd/callout.h
index d6b83bcfe5f5..69a4cf123162 100644
--- a/cddl/usr.sbin/zfsd/callout.h
+++ b/cddl/usr.sbin/zfsd/callout.h
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
/**
diff --git a/cddl/usr.sbin/zfsd/case_file.cc b/cddl/usr.sbin/zfsd/case_file.cc
index 8da711fc10cb..f9fd84da7277 100644
--- a/cddl/usr.sbin/zfsd/case_file.cc
+++ b/cddl/usr.sbin/zfsd/case_file.cc
@@ -53,6 +53,7 @@
#include <syslog.h>
#include <unistd.h>
+#include <libzutil.h>
#include <libzfs.h>
#include <list>
@@ -73,9 +74,6 @@
#include "zfsd.h"
#include "zfsd_exception.h"
#include "zpool_list.h"
-
-__FBSDID("$FreeBSD$");
-
/*============================ Namespace Control =============================*/
using std::hex;
using std::ifstream;
@@ -94,7 +92,6 @@ using DevdCtl::ParseException;
CaseFileList CaseFile::s_activeCases;
const string CaseFile::s_caseFilePath = "/var/db/zfsd/cases";
-const timeval CaseFile::s_removeGracePeriod = { 60 /*sec*/, 0 /*usec*/};
//- CaseFile Static Public Methods ---------------------------------------------
CaseFile *
@@ -116,6 +113,26 @@ CaseFile::Find(Guid poolGUID, Guid vdevGUID)
return (NULL);
}
+void
+CaseFile::Find(Guid poolGUID, Guid vdevGUID, CaseFileList &cases)
+{
+ for (CaseFileList::iterator curCase = s_activeCases.begin();
+ curCase != s_activeCases.end(); curCase++) {
+ if (((*curCase)->PoolGUID() != poolGUID &&
+ Guid::InvalidGuid() != poolGUID) ||
+ (*curCase)->VdevGUID() != vdevGUID)
+ continue;
+
+ /*
+ * We can have multiple cases for spare vdevs
+ */
+ cases.push_back(*curCase);
+ if (!(*curCase)->IsSpare()) {
+ return;
+ }
+ }
+}
+
CaseFile *
CaseFile::Find(const string &physPath)
{
@@ -217,6 +234,12 @@ CaseFile::PurgeAll()
}
+int
+CaseFile::IsSpare()
+{
+ return (m_is_spare);
+}
+
//- CaseFile Public Methods ----------------------------------------------------
bool
CaseFile::RefreshVdevState()
@@ -232,6 +255,7 @@ CaseFile::RefreshVdevState()
m_vdevState = vd.State();
m_vdevPhysPath = vd.PhysicalPath();
+ m_vdevName = vd.Name(casePool, false);
return (true);
}
@@ -240,6 +264,7 @@ CaseFile::ReEvaluate(const string &devPath, const string &physPath, Vdev *vdev)
{
ZpoolList zpl(ZpoolList::ZpoolByGUID, &m_poolGUID);
zpool_handle_t *pool(zpl.empty() ? NULL : zpl.front());
+ int flags = ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE;
if (pool == NULL || !RefreshVdevState()) {
/*
@@ -280,9 +305,10 @@ CaseFile::ReEvaluate(const string &devPath, const string &physPath, Vdev *vdev)
|| vdev->PoolGUID() == Guid::InvalidGuid())
&& vdev->GUID() == m_vdevGUID) {
+ if (IsSpare())
+ flags |= ZFS_ONLINE_SPARE;
if (zpool_vdev_online(pool, vdev->GUIDString().c_str(),
- ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE,
- &m_vdevState) != 0) {
+ flags, &m_vdevState) != 0) {
syslog(LOG_ERR,
"Failed to online vdev(%s/%s:%s): %s: %s\n",
zpool_get_name(pool), vdev->GUIDString().c_str(),
@@ -360,7 +386,7 @@ CaseFile::ReEvaluate(const ZfsEvent &event)
{
bool consumed(false);
- if (event.Value("type") == "misc.fs.zfs.vdev_remove") {
+ if (event.Value("type") == "sysevent.fs.zfs.vdev_remove") {
/*
* The Vdev we represent has been removed from the
* configuration. This case is no longer of value.
@@ -368,12 +394,12 @@ CaseFile::ReEvaluate(const ZfsEvent &event)
Close();
return (/*consumed*/true);
- } else if (event.Value("type") == "misc.fs.zfs.pool_destroy") {
+ } else if (event.Value("type") == "sysevent.fs.zfs.pool_destroy") {
/* This Pool has been destroyed. Discard the case */
Close();
return (/*consumed*/true);
- } else if (event.Value("type") == "misc.fs.zfs.config_sync") {
+ } else if (event.Value("type") == "sysevent.fs.zfs.config_sync") {
RefreshVdevState();
if (VdevState() < VDEV_STATE_HEALTHY)
consumed = ActivateSpare();
@@ -445,7 +471,8 @@ CaseFile::ReEvaluate(const ZfsEvent &event)
consumed = true;
}
else if (event.Value("class") == "ereport.fs.zfs.io" ||
- event.Value("class") == "ereport.fs.zfs.checksum") {
+ event.Value("class") == "ereport.fs.zfs.checksum" ||
+ event.Value("class") == "ereport.fs.zfs.delay") {
m_tentativeEvents.push_front(event.DeepCopy());
RegisterCallout(event);
@@ -490,8 +517,7 @@ bool
CaseFile::ActivateSpare() {
nvlist_t *config, *nvroot, *parent_config;
nvlist_t **spares;
- char *devPath, *vdev_type;
- const char *poolname;
+ const char *devPath, *poolname, *vdev_type;
u_int nspares, i;
int error;
@@ -518,7 +544,7 @@ CaseFile::ActivateSpare() {
parent_config = find_parent(config, nvroot, m_vdevGUID);
if (parent_config != NULL) {
- char *parent_type;
+ const char *parent_type;
/*
* Don't activate spares for members of a "replacing" vdev.
@@ -585,15 +611,55 @@ CaseFile::ActivateSpare() {
return (Replace(vdev_type, devPath, /*isspare*/true));
}
+/* Does the argument event refer to a checksum error? */
+static bool
+IsChecksumEvent(const Event* const event)
+{
+ return ("ereport.fs.zfs.checksum" == event->Value("type"));
+}
+
+/* Does the argument event refer to an IO error? */
+static bool
+IsIOEvent(const Event* const event)
+{
+ return ("ereport.fs.zfs.io" == event->Value("type"));
+}
+
+/* Does the argument event refer to an IO delay? */
+static bool
+IsDelayEvent(const Event* const event)
+{
+ return ("ereport.fs.zfs.delay" == event->Value("type"));
+}
+
void
CaseFile::RegisterCallout(const Event &event)
{
timeval now, countdown, elapsed, timestamp, zero, remaining;
+ /**
+ * The time ZFSD waits before promoting a tentative event
+ * into a permanent event.
+ */
+ int sec = -1;
+ if (IsChecksumEvent(&event))
+ sec = CaseFile::GetVdevProp(VDEV_PROP_CHECKSUM_T);
+ else if (IsIOEvent(&event))
+ sec = CaseFile::GetVdevProp(VDEV_PROP_IO_T);
+ else if (IsDelayEvent(&event))
+ sec = CaseFile::GetVdevProp(VDEV_PROP_SLOW_IO_T);
+
+ if (sec == -1)
+ sec = 60; /* default */
+
+ timeval removeGracePeriod = {
+ sec, /*sec*/
+ 0 /*usec*/
+ };
gettimeofday(&now, 0);
timestamp = event.GetTimestamp();
timersub(&now, &timestamp, &elapsed);
- timersub(&s_removeGracePeriod, &elapsed, &countdown);
+ timersub(&removeGracePeriod, &elapsed, &countdown);
/*
* If countdown is <= zero, Reset the timer to the
* smallest positive time value instead
@@ -791,7 +857,8 @@ CaseFile::CaseFile(const Vdev &vdev)
: m_poolGUID(vdev.PoolGUID()),
m_vdevGUID(vdev.GUID()),
m_vdevState(vdev.State()),
- m_vdevPhysPath(vdev.PhysicalPath())
+ m_vdevPhysPath(vdev.PhysicalPath()),
+ m_is_spare(vdev.IsSpare())
{
stringstream guidString;
@@ -801,6 +868,10 @@ CaseFile::CaseFile(const Vdev &vdev)
guidString << m_poolGUID;
m_poolGUIDString = guidString.str();
+ ZpoolList zpl(ZpoolList::ZpoolByGUID, &m_poolGUID);
+ zpool_handle_t *zhp(zpl.empty() ? NULL : zpl.front());
+ m_vdevName = vdev.Name(zhp, false);
+
s_activeCases.push_back(this);
syslog(LOG_INFO, "Creating new CaseFile:\n");
@@ -1132,32 +1203,56 @@ CaseFile::Replace(const char* vdev_type, const char* path, bool isspare) {
return (retval);
}
-/* Does the argument event refer to a checksum error? */
-static bool
-IsChecksumEvent(const Event* const event)
+/* Lookup the vdev prop. Used for checksum, IO, or slow IO props */
+int
+CaseFile::GetVdevProp(vdev_prop_t vdev_prop) const
{
- return ("ereport.fs.zfs.checksum" == event->Value("type"));
-}
+ char val[ZFS_MAXPROPLEN];
+ zprop_source_t srctype;
+ DevdCtl::Guid poolGUID = PoolGUID();
+ ZpoolList zpl(ZpoolList::ZpoolByGUID, &poolGUID);
+ zpool_handle_t *zhp(zpl.empty() ? NULL : zpl.front());
-/* Does the argument event refer to an IO error? */
-static bool
-IsIOEvent(const Event* const event)
-{
- return ("ereport.fs.zfs.io" == event->Value("type"));
+ char *prop_str = (char *) vdev_prop_to_name(vdev_prop);
+ if (zhp == NULL || zpool_get_vdev_prop(zhp, m_vdevName.c_str(),
+ vdev_prop, prop_str, val, sizeof (val), &srctype, B_FALSE) != 0)
+ return (-1);
+
+ /* we'll get "-" from libzfs for a prop that is not set */
+ if (zfs_isnumber(val) == B_FALSE)
+ return (-1);
+
+ return (atoi(val));
}
bool
CaseFile::ShouldDegrade() const
{
+ int checksum_n = GetVdevProp(VDEV_PROP_CHECKSUM_N);
+ if (checksum_n == -1)
+ checksum_n = DEFAULT_ZFS_DEGRADE_IO_COUNT;
return (std::count_if(m_events.begin(), m_events.end(),
- IsChecksumEvent) > ZFS_DEGRADE_IO_COUNT);
+ IsChecksumEvent) > checksum_n);
}
bool
CaseFile::ShouldFault() const
{
- return (std::count_if(m_events.begin(), m_events.end(),
- IsIOEvent) > ZFS_DEGRADE_IO_COUNT);
+ bool should_fault_for_io, should_fault_for_delay;
+ int io_n = GetVdevProp(VDEV_PROP_IO_N);
+ int slow_io_n = GetVdevProp(VDEV_PROP_SLOW_IO_N);
+
+ if (io_n == -1)
+ io_n = DEFAULT_ZFS_DEGRADE_IO_COUNT;
+ if (slow_io_n == -1)
+ slow_io_n = DEFAULT_ZFS_FAULT_SLOW_IO_COUNT;
+
+ should_fault_for_io = std::count_if(m_events.begin(), m_events.end(),
+ IsIOEvent) > io_n;
+ should_fault_for_delay = std::count_if(m_events.begin(), m_events.end(),
+ IsDelayEvent) > slow_io_n;
+
+ return (should_fault_for_io || should_fault_for_delay);
}
nvlist_t *
diff --git a/cddl/usr.sbin/zfsd/case_file.h b/cddl/usr.sbin/zfsd/case_file.h
index b4dc2dee5d96..199918c4fead 100644
--- a/cddl/usr.sbin/zfsd/case_file.h
+++ b/cddl/usr.sbin/zfsd/case_file.h
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
/**
@@ -99,6 +97,19 @@ public:
static CaseFile *Find(DevdCtl::Guid poolGUID, DevdCtl::Guid vdevGUID);
/**
+ * \brief Find multiple CaseFile objects by a vdev's pool/vdev
+ * GUID tuple (special case for spare vdevs)
+ *
+ * \param poolGUID Pool GUID for the vdev of the CaseFile to find.
+ * If InvalidGuid, then only match the vdev GUID
+ * instead of both pool and vdev GUIDs.
+ * \param vdevGUID Vdev GUID for the vdev of the CaseFile to find.
+ * \param caseList List of cases associated with the vdev.
+ */
+ static void Find(DevdCtl::Guid poolGUID, DevdCtl::Guid vdevGUID,
+ CaseFileList &caseList);
+
+ /**
* \brief Find a CaseFile object by a vdev's current/last known
* physical path.
*
@@ -219,14 +230,32 @@ public:
*/
bool ShouldFault() const;
+ /**
+ * \brief If this vdev is spare
+ */
+ int IsSpare();
+
+ /**
+ * \brief Get case vdev's specified property
+ */
+ int GetVdevProp(vdev_prop_t) const;
+
protected:
enum {
+ /*
+ * Use these defaults if we can't get the corresponding vdev
+ * prop or if the prop is not set
+ */
/**
* The number of soft errors on a vdev required
* to transition a vdev from healthy to degraded
- * status.
+ * status
*/
- ZFS_DEGRADE_IO_COUNT = 50
+ DEFAULT_ZFS_DEGRADE_IO_COUNT = 50,
+ /**
+ * The number of delay errors on a vdev required to fault it
+ */
+ DEFAULT_ZFS_FAULT_SLOW_IO_COUNT = 8,
};
static CalloutFunc_t OnGracePeriodEnded;
@@ -360,12 +389,6 @@ protected:
static const string s_caseFilePath;
/**
- * \brief The time ZFSD waits before promoting a tentative event
- * into a permanent event.
- */
- static const timeval s_removeGracePeriod;
-
- /**
* \brief A list of soft error events counted against the health of
* a vdev.
*/
@@ -384,6 +407,8 @@ protected:
string m_poolGUIDString;
string m_vdevGUIDString;
string m_vdevPhysPath;
+ string m_vdevName;
+ int m_is_spare;
/**
* \brief Callout activated when a grace period
diff --git a/cddl/usr.sbin/zfsd/tests/Makefile b/cddl/usr.sbin/zfsd/tests/Makefile
index 1b776b217776..a4613e4cb1e8 100644
--- a/cddl/usr.sbin/zfsd/tests/Makefile
+++ b/cddl/usr.sbin/zfsd/tests/Makefile
@@ -1,4 +1,3 @@
-# $FreeBSD$
.include "${.CURDIR}/../Makefile.common"
.PATH: ${.CURDIR:H}
diff --git a/cddl/usr.sbin/zfsd/tests/libmocks.c b/cddl/usr.sbin/zfsd/tests/libmocks.c
index e3c90a46920f..64eb02b1d480 100644
--- a/cddl/usr.sbin/zfsd/tests/libmocks.c
+++ b/cddl/usr.sbin/zfsd/tests/libmocks.c
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Alan Somers (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
#include <stdio.h>
diff --git a/cddl/usr.sbin/zfsd/tests/libmocks.h b/cddl/usr.sbin/zfsd/tests/libmocks.h
index 130f4389f70a..ffa2f0673e1d 100644
--- a/cddl/usr.sbin/zfsd/tests/libmocks.h
+++ b/cddl/usr.sbin/zfsd/tests/libmocks.h
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Alan Somers (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
#ifndef _LIBMOCKS_H_
diff --git a/cddl/usr.sbin/zfsd/tests/zfsd_unittest.cc b/cddl/usr.sbin/zfsd/tests/zfsd_unittest.cc
index e2833170f9ac..f1e925b0b4ef 100644
--- a/cddl/usr.sbin/zfsd/tests/zfsd_unittest.cc
+++ b/cddl/usr.sbin/zfsd/tests/zfsd_unittest.cc
@@ -62,9 +62,6 @@
#include <zfsd/zpool_list.h>
#include "libmocks.h"
-
-__FBSDID("$FreeBSD$");
-
/*================================== Macros ==================================*/
#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
@@ -137,6 +134,7 @@ public:
MOCK_CONST_METHOD0(PoolGUID, Guid());
MOCK_CONST_METHOD0(State, vdev_state());
MOCK_CONST_METHOD0(PhysicalPath, string());
+ MOCK_CONST_METHOD2(Name, string(zpool_handle_t * zhp, bool verbose));
};
MockVdev::MockVdev(nvlist_t *vdevConfig)
@@ -400,7 +398,7 @@ TEST_F(ZfsEventTest, ProcessPoolEventGetsCalled)
{
string evString("!system=ZFS "
"subsystem=ZFS "
- "type=misc.fs.zfs.vdev_remove "
+ "type=sysevent.fs.zfs.vdev_remove "
"pool_name=foo "
"pool_guid=9756779504028057996 "
"vdev_guid=1631193447431603339 "
@@ -434,6 +432,8 @@ protected:
m_vdev = new MockVdev(m_vdevConfig);
ON_CALL(*m_vdev, GUID())
.WillByDefault(::testing::Return(Guid(123)));
+ ON_CALL(*m_vdev, Name(::testing::_, ::testing::_))
+ .WillByDefault(::testing::Return(string("/dev/da999")));
ON_CALL(*m_vdev, PoolGUID())
.WillByDefault(::testing::Return(Guid(456)));
ON_CALL(*m_vdev, State())
@@ -515,7 +515,7 @@ TEST_F(CaseFileTest, PoolDestroy)
"pool_guid=456 "
"subsystem=ZFS "
"timestamp=1348867914 "
- "type=misc.fs.zfs.pool_destroy ");
+ "type=sysevent.fs.zfs.pool_destroy ");
m_event = Event::CreateEvent(*m_eventFactory, evString);
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
EXPECT_CALL(*m_caseFile, Close());
@@ -523,6 +523,72 @@ TEST_F(CaseFileTest, PoolDestroy)
}
/*
+ * A Vdev with a very large number of Delay errors should fault
+ * For performance reasons, RefreshVdevState should be called at most once
+ */
+TEST_F(CaseFileTest, VeryManyDelayErrors)
+{
+ EXPECT_CALL(*m_caseFile, RefreshVdevState())
+ .Times(::testing::AtMost(1))
+ .WillRepeatedly(::testing::Return(true));
+
+ for(int i=0; i<100; i++) {
+ stringstream evStringStream;
+ evStringStream <<
+ "!system=ZFS "
+ "class=ereport.fs.zfs.delay "
+ "ena=12091638756982918145 "
+ "parent_guid=13237004955564865395 "
+ "parent_type=raidz "
+ "pool=testpool.4415 "
+ "pool_context=0 "
+ "pool_failmode=wait "
+ "pool_guid=456 "
+ "pool_state= 0"
+ "subsystem=ZFS "
+ "time=";
+ evStringStream << i << "0000000000000000 ";
+ evStringStream << "timestamp=" << i << " ";
+ evStringStream <<
+ "type=ereport.fs.zfs.delay "
+ "vdev_ashift=12 "
+ "vdev_cksum_errors=0 "
+ "vdev_complete_ts=948336226469 "
+ "vdev_delays=77 "
+ "vdev_delta_ts=123998485899 "
+ "vdev_guid=123 "
+ "vdev_path=/dev/da400 "
+ "vdev_read_errors=0 "
+ "vdev_spare_guids= "
+ "vdev_type=disk "
+ "vdev_write_errors=0 "
+ "zio_blkid=622 "
+ "zio_delay=31000041101 "
+ "zio_delta=123998485899 "
+ "zio_err=0 "
+ "zio_flags=1572992 "
+ "zio_level=-2 "
+ "zio_object=0 "
+ "zio_objset=37 "
+ "zio_offset=25598976 "
+ "zio_pipeline=48234496 "
+ "zio_priority=3 "
+ "zio_size=1024"
+ "zio_stage=33554432 "
+ "zio_timestamp=824337740570 ";
+ Event *event(Event::CreateEvent(*m_eventFactory,
+ evStringStream.str()));
+ ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
+ EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
+ delete event;
+ }
+
+ m_caseFile->SpliceEvents();
+ EXPECT_FALSE(m_caseFile->ShouldDegrade());
+ EXPECT_TRUE(m_caseFile->ShouldFault());
+}
+
+/*
* A Vdev with a very large number of IO errors should fault
* For performance reasons, RefreshVdevState should be called at most once
*/
@@ -685,7 +751,7 @@ string ReEvaluateByGuidTest::s_evString(
"pool_name=foo "
"subsystem=ZFS "
"timestamp=1360620391 "
- "type=misc.fs.zfs.config_sync");
+ "type=sysevent.fs.zfs.config_sync");
/*
@@ -769,3 +835,40 @@ TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_five)
delete CaseFile4;
delete CaseFile5;
}
+
+/*
+ * Test VdevIterator
+ */
+class VdevIteratorTest : public ::testing::Test
+{
+};
+
+bool VdevIteratorTestCB(Vdev &vdev, void *cbArg) {
+ return (false);
+}
+
+/*
+ * VdevIterator::Next should not crash when run on a pool that has a previously
+ * removed vdev. Regression for
+ * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=273663
+ */
+TEST_F(VdevIteratorTest, VdevRemoval)
+{
+ nvlist_t* poolConfig, *rootVdev;
+
+ ASSERT_EQ(0, nvlist_alloc(&rootVdev, NV_UNIQUE_NAME, 0));
+ ASSERT_EQ(0, nvlist_add_uint64(rootVdev, ZPOOL_CONFIG_GUID, 0x5678));
+ /*
+ * Note: pools with previously-removed top-level VDEVs will contain a
+ * TLV in their labels that has 0 children.
+ */
+ ASSERT_EQ(0, nvlist_add_nvlist_array(rootVdev, ZPOOL_CONFIG_CHILDREN,
+ NULL, 0));
+ ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0));
+ ASSERT_EQ(0, nvlist_add_uint64(poolConfig,
+ ZPOOL_CONFIG_POOL_GUID, 0x1234));
+ ASSERT_EQ(0, nvlist_add_nvlist(poolConfig, ZPOOL_CONFIG_VDEV_TREE,
+ rootVdev));
+
+ VdevIterator(poolConfig).Each(VdevIteratorTestCB, NULL);
+}
diff --git a/cddl/usr.sbin/zfsd/tests/zfsd_unittest.supp b/cddl/usr.sbin/zfsd/tests/zfsd_unittest.supp
index 138ef6907e62..377ca1e10746 100644
--- a/cddl/usr.sbin/zfsd/tests/zfsd_unittest.supp
+++ b/cddl/usr.sbin/zfsd/tests/zfsd_unittest.supp
@@ -29,7 +29,6 @@
#
# Authors: Alan Somers (Spectra Logic Corporation)
#
-# $FreeBSD$
# This is a valgrind suppression file used for running zfsd_unittest with
diff --git a/cddl/usr.sbin/zfsd/vdev.cc b/cddl/usr.sbin/zfsd/vdev.cc
index 508af8cda925..1a37340fb76e 100644
--- a/cddl/usr.sbin/zfsd/vdev.cc
+++ b/cddl/usr.sbin/zfsd/vdev.cc
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
/**
@@ -65,8 +63,6 @@
#include "zfsd.h"
#include "zfsd_exception.h"
#include "zpool_list.h"
-
-__FBSDID("$FreeBSD$");
/*============================ Namespace Control =============================*/
using std::string;
using std::stringstream;
@@ -336,7 +332,7 @@ Vdev::Name(zpool_handle_t *zhp, bool verbose) const
string
Vdev::Path() const
{
- char *path(NULL);
+ const char *path(NULL);
if ((m_config != NULL)
&& (nvlist_lookup_string(m_config, ZPOOL_CONFIG_PATH, &path) == 0))
@@ -348,7 +344,7 @@ Vdev::Path() const
string
Vdev::PhysicalPath() const
{
- char *path(NULL);
+ const char *path(NULL);
if ((m_config != NULL) && (nvlist_lookup_string(m_config,
ZPOOL_CONFIG_PHYS_PATH, &path) == 0))
diff --git a/cddl/usr.sbin/zfsd/vdev.h b/cddl/usr.sbin/zfsd/vdev.h
index 322efc8f4e53..42278a3d7229 100644
--- a/cddl/usr.sbin/zfsd/vdev.h
+++ b/cddl/usr.sbin/zfsd/vdev.h
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
/**
@@ -132,7 +130,7 @@ public:
nvlist_t *Config() const;
Vdev Parent();
Vdev RootVdev();
- std::string Name(zpool_handle_t *, bool verbose) const;
+ virtual std::string Name(zpool_handle_t *, bool verbose) const;
bool IsSpare();
bool IsAvailableSpare() const;
bool IsActiveSpare() const;
diff --git a/cddl/usr.sbin/zfsd/vdev_iterator.cc b/cddl/usr.sbin/zfsd/vdev_iterator.cc
index b5a4f22c1c60..e9283108ed3c 100644
--- a/cddl/usr.sbin/zfsd/vdev_iterator.cc
+++ b/cddl/usr.sbin/zfsd/vdev_iterator.cc
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
/**
@@ -78,8 +76,10 @@ VdevIterator::Reset()
{
nvlist_t *rootVdev;
nvlist **cache_child;
+ nvlist **spare_child;
int result;
uint_t cache_children;
+ uint_t spare_children;
result = nvlist_lookup_nvlist(m_poolConfig,
ZPOOL_CONFIG_VDEV_TREE,
@@ -95,6 +95,13 @@ VdevIterator::Reset()
if (result == 0)
for (uint_t c = 0; c < cache_children; c++)
m_vdevQueue.push_back(cache_child[c]);
+ result = nvlist_lookup_nvlist_array(rootVdev,
+ ZPOOL_CONFIG_SPARES,
+ &spare_child,
+ &spare_children);
+ if (result == 0)
+ for (uint_t c = 0; c < spare_children; c++)
+ m_vdevQueue.push_back(spare_child[c]);
}
nvlist_t *
@@ -102,10 +109,7 @@ VdevIterator::Next()
{
nvlist_t *vdevConfig;
- if (m_vdevQueue.empty())
- return (NULL);
-
- for (;;) {
+ for (vdevConfig = NULL; !m_vdevQueue.empty();) {
nvlist_t **vdevChildren;
int result;
u_int numChildren;
diff --git a/cddl/usr.sbin/zfsd/vdev_iterator.h b/cddl/usr.sbin/zfsd/vdev_iterator.h
index 435582ec1f84..439f987ba6e1 100644
--- a/cddl/usr.sbin/zfsd/vdev_iterator.h
+++ b/cddl/usr.sbin/zfsd/vdev_iterator.h
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
/**
diff --git a/cddl/usr.sbin/zfsd/zfsd.8 b/cddl/usr.sbin/zfsd/zfsd.8
index ce7550b891a3..d6b0e1d4bd22 100644
--- a/cddl/usr.sbin/zfsd/zfsd.8
+++ b/cddl/usr.sbin/zfsd/zfsd.8
@@ -23,9 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd April 18, 2020
+.Dd February 20, 2024
.Dt ZFSD 8
.Os
.Sh NAME
@@ -57,7 +55,7 @@ directly.
Instead, they control its behavior indirectly through zpool configuration.
There are two ways to influence
.Nm :
-assigning hotspares and setting pool properties.
+assigning hot spares and setting pool properties.
Currently, only the
.Em autoreplace
property has any effect.
@@ -71,7 +69,7 @@ will attempt to resolve the following types of fault:
.It device removal
When a leaf vdev disappears,
.Nm
-will activate any available hotspare.
+will activate any available hot spare.
.It device arrival
When a new GEOM device appears,
.Nm
@@ -79,40 +77,71 @@ will attempt to read its ZFS label, if any.
If it matches a previously removed vdev on an active pool,
.Nm
will online it.
-Once resilvering completes, any active hotspare will detach automatically.
+Once resilvering completes, any active hot spare will detach automatically.
.Pp
If the new device has no ZFS label but its physical path matches the
physical path of a previously removed vdev on an active pool, and that
pool has the autoreplace property set, then
.Nm
will replace the missing vdev with the newly arrived device.
-Once resilvering completes, any active hotspare will detach automatically.
+Once resilvering completes, any active hot spare will detach automatically.
.It vdev degrade or fault events
If a vdev becomes degraded or faulted,
.Nm
-will activate any available hotspare.
+will activate any available hot spare.
.It I/O errors
-If a leaf vdev generates more than 50 I/O errors in a 60 second period, then
+By default, if a leaf vdev generates more than 50 I/O errors in a 60 second
+period, then
.Nm
will mark that vdev as
.Em FAULTED .
ZFS will no longer issue any I/Os to it.
.Nm
-will activate a hotspare if one is available.
+will activate a hot spare if one is available. The defaults can be changed by
+setting the
+.Em io_n
+and/or
+.Em io_t
+vdev properties. See
+.Xr vdevprops 7
+for details.
+.It I/O delays
+By default, if a leaf vdev generates more than delayed 8 I/O events in a 60
+second period, then
+.Nm
+will mark that vdev as
+.Em FAULTED .
+ZFS will no longer issue any I/Os to it.
+.Nm
+will activate a hot spare if one is available. The defaults can be changed by
+setting the
+.Em slow_io_n
+and/or
+.Em slow_io_t
+vdev properties. See
+.Xr vdevprops 7
+for details.
.It Checksum errors
-If a leaf vdev generates more than 50 checksum errors in a 60 second
-period, then
+By default, if a leaf vdev generates more than 50 checksum errors in a 60
+second period, then
.Nm
will mark that vdev as
.Em DEGRADED .
-ZFS will still use it, but zfsd will activate a spare anyway.
+ZFS will still use it, but zfsd will also activate a hot spare if one is
+available. The defaults can be changed by setting the
+.Em checksum_n
+and/or
+.Em checksum_t
+vdev properties. See
+.Xr vdevprops 7
+for details.
.It Spare addition
-If the system administrator adds a hotspare to a pool that is already degraded,
+If the system administrator adds a hot spare to a pool that is already degraded,
.Nm
will activate the spare.
.It Resilver complete
.Nm
-will detach any hotspare once a permanent replacement finishes resilvering.
+will detach any hot spare once a permanent replacement finishes resilvering.
.It Physical path change
If the physical path of an existing disk changes,
.Nm
@@ -136,6 +165,7 @@ then reads them back in when next it starts up.
.El
.Sh SEE ALSO
.Xr devctl 4 ,
+.Xr vdevprops 7 ,
.Xr zpool 8
.Sh HISTORY
.Nm
diff --git a/cddl/usr.sbin/zfsd/zfsd.cc b/cddl/usr.sbin/zfsd/zfsd.cc
index 876cca836e9e..210cc4b85a44 100644
--- a/cddl/usr.sbin/zfsd/zfsd.cc
+++ b/cddl/usr.sbin/zfsd/zfsd.cc
@@ -74,9 +74,6 @@
#include "zfsd.h"
#include "zfsd_exception.h"
#include "zpool_list.h"
-
-__FBSDID("$FreeBSD$");
-
/*================================== Macros ==================================*/
#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
@@ -248,7 +245,7 @@ ZfsDaemon::BuildCaseFiles()
snprintf(evString, 160, "!system=ZFS subsystem=ZFS "
- "type=misc.fs.zfs.config_sync sub_type=synthesized "
+ "type=sysevent.fs.zfs.config_sync sub_type=synthesized "
"pool_name=%s pool_guid=%" PRIu64 "\n", poolname, poolGUID);
event = Event::CreateEvent(GetFactory(), string(evString));
if (event != NULL) {
@@ -276,7 +273,7 @@ ZfsDaemon::RescanSystem()
result = geom_gettree(&mesh);
if (result != 0) {
syslog(LOG_ERR, "ZfsDaemon::RescanSystem: "
- "geom_gettree faild with error %d\n", result);
+ "geom_gettree failed with error %d\n", result);
return;
}
diff --git a/cddl/usr.sbin/zfsd/zfsd.h b/cddl/usr.sbin/zfsd/zfsd.h
index 7b4019c7ae10..8c7c63a7c9c4 100644
--- a/cddl/usr.sbin/zfsd/zfsd.h
+++ b/cddl/usr.sbin/zfsd/zfsd.h
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
/**
diff --git a/cddl/usr.sbin/zfsd/zfsd_event.cc b/cddl/usr.sbin/zfsd/zfsd_event.cc
index 688e7c0354a2..7a19b95abeed 100644
--- a/cddl/usr.sbin/zfsd/zfsd_event.cc
+++ b/cddl/usr.sbin/zfsd/zfsd_event.cc
@@ -68,8 +68,6 @@
#include "zfsd.h"
#include "zfsd_exception.h"
#include "zpool_list.h"
-
-__FBSDID("$FreeBSD$");
/*============================ Namespace Control =============================*/
using DevdCtl::Event;
using DevdCtl::Guid;
@@ -229,7 +227,9 @@ bool
GeomEvent::OnlineByLabel(const string &devPath, const string& physPath,
nvlist_t *devConfig)
{
+ bool ret = false;
try {
+ CaseFileList case_list;
/*
* A device with ZFS label information has been
* inserted. If it matches a device for which we
@@ -238,10 +238,12 @@ GeomEvent::OnlineByLabel(const string &devPath, const string& physPath,
syslog(LOG_INFO, "Interrogating VDEV label for %s\n",
devPath.c_str());
Vdev vdev(devConfig);
- CaseFile *caseFile(CaseFile::Find(vdev.PoolGUID(),
- vdev.GUID()));
- if (caseFile != NULL)
- return (caseFile->ReEvaluate(devPath, physPath, &vdev));
+ CaseFile::Find(vdev.PoolGUID(),vdev.GUID(), case_list);
+ for (CaseFileList::iterator curr = case_list.begin();
+ curr != case_list.end(); curr++) {
+ ret |= (*curr)->ReEvaluate(devPath, physPath, &vdev);
+ }
+ return (ret);
} catch (ZfsdException &exp) {
string context("GeomEvent::OnlineByLabel: " + devPath + ": ");
@@ -249,7 +251,7 @@ GeomEvent::OnlineByLabel(const string &devPath, const string& physPath,
exp.GetString().insert(0, context);
exp.Log();
}
- return (false);
+ return (ret);
}
@@ -281,7 +283,7 @@ ZfsEvent::Process() const
}
/* On config syncs, replay any queued events first. */
- if (Value("type").find("misc.fs.zfs.config_sync") == 0) {
+ if (Value("type").find("sysevent.fs.zfs.config_sync") == 0) {
/*
* Even if saved events are unconsumed the second time
* around, drop them. Any events that still can't be
@@ -292,7 +294,7 @@ ZfsEvent::Process() const
CaseFile::ReEvaluateByGuid(PoolGUID(), *this);
}
- if (Value("type").find("misc.fs.zfs.") == 0) {
+ if (Value("type").find("sysevent.fs.zfs.") == 0) {
/* Configuration changes, resilver events, etc. */
ProcessPoolEvent();
return (false);
@@ -405,7 +407,7 @@ ZfsEvent::ProcessPoolEvent() const
bool degradedDevice(false);
/* The pool is destroyed. Discard any open cases */
- if (Value("type") == "misc.fs.zfs.pool_destroy") {
+ if (Value("type") == "sysevent.fs.zfs.pool_destroy") {
Log(LOG_INFO);
CaseFile::ReEvaluateByGuid(PoolGUID(), *this);
return;
@@ -420,7 +422,7 @@ ZfsEvent::ProcessPoolEvent() const
Log(LOG_INFO);
caseFile->ReEvaluate(*this);
}
- else if (Value("type") == "misc.fs.zfs.resilver_finish")
+ else if (Value("type") == "sysevent.fs.zfs.resilver_finish")
{
/*
* It's possible to get a resilver_finish event with no
@@ -431,7 +433,7 @@ ZfsEvent::ProcessPoolEvent() const
CleanupSpares();
}
- if (Value("type") == "misc.fs.zfs.vdev_remove"
+ if (Value("type") == "sysevent.fs.zfs.vdev_remove"
&& degradedDevice == false) {
/* See if any other cases can make use of this device. */
diff --git a/cddl/usr.sbin/zfsd/zfsd_event.h b/cddl/usr.sbin/zfsd/zfsd_event.h
index fd3f9f7c5200..6398cb3c0c13 100644
--- a/cddl/usr.sbin/zfsd/zfsd_event.h
+++ b/cddl/usr.sbin/zfsd/zfsd_event.h
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
/**
diff --git a/cddl/usr.sbin/zfsd/zfsd_exception.cc b/cddl/usr.sbin/zfsd/zfsd_exception.cc
index 7ebb74ca8c6a..d5b3cab24f02 100644
--- a/cddl/usr.sbin/zfsd/zfsd_exception.cc
+++ b/cddl/usr.sbin/zfsd/zfsd_exception.cc
@@ -52,8 +52,6 @@
#include "vdev.h"
#include "zfsd_exception.h"
-
-__FBSDID("$FreeBSD$");
/*============================ Namespace Control =============================*/
using std::endl;
using std::string;
@@ -106,7 +104,7 @@ ZfsdException::Log() const
output << "Pool ";
- char *poolName;
+ const char *poolName;
if (nvlist_lookup_string(m_poolConfig, ZPOOL_CONFIG_POOL_NAME,
&poolName) == 0)
output << poolName;
diff --git a/cddl/usr.sbin/zfsd/zfsd_exception.h b/cddl/usr.sbin/zfsd/zfsd_exception.h
index 5170b2d0dbb1..6cb182e7223b 100644
--- a/cddl/usr.sbin/zfsd/zfsd_exception.h
+++ b/cddl/usr.sbin/zfsd/zfsd_exception.h
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
/**
diff --git a/cddl/usr.sbin/zfsd/zfsd_main.cc b/cddl/usr.sbin/zfsd/zfsd_main.cc
index f090631e21f2..cc9ce6044384 100644
--- a/cddl/usr.sbin/zfsd/zfsd_main.cc
+++ b/cddl/usr.sbin/zfsd/zfsd_main.cc
@@ -55,9 +55,6 @@
#include "vdev_iterator.h"
#include "zfsd.h"
-
-__FBSDID("$FreeBSD$");
-
/*=============================== Program Main ===============================*/
static void
usage()
diff --git a/cddl/usr.sbin/zfsd/zpool_list.cc b/cddl/usr.sbin/zfsd/zpool_list.cc
index 82c35736df13..65612ca0591c 100644
--- a/cddl/usr.sbin/zfsd/zpool_list.cc
+++ b/cddl/usr.sbin/zfsd/zpool_list.cc
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
/**
diff --git a/cddl/usr.sbin/zfsd/zpool_list.h b/cddl/usr.sbin/zfsd/zpool_list.h
index 6ee30892aedd..3043d35731eb 100644
--- a/cddl/usr.sbin/zfsd/zpool_list.h
+++ b/cddl/usr.sbin/zfsd/zpool_list.h
@@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
- *
- * $FreeBSD$
*/
/**
@@ -95,7 +93,7 @@ public:
static PoolFilter_t ZpoolByName;
/**
- * \brief ZpoolList contructor
+ * \brief ZpoolList constructor
*
* \param filter The filter function to use when constructing
* the ZpoolList. This may be one of the static