diff options
Diffstat (limited to 'cddl/usr.sbin/zfsd')
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, ×tamp, &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 |