diff --git a/cmd/zfsd/case_file.cc b/cmd/zfsd/case_file.cc index 2545370387..0013cc55f7 100644 --- a/cmd/zfsd/case_file.cc +++ b/cmd/zfsd/case_file.cc @@ -116,6 +116,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 +237,12 @@ CaseFile::PurgeAll() } +int +CaseFile::IsSpare() +{ + return (m_is_spare); +} + //- CaseFile Public Methods ---------------------------------------------------- bool CaseFile::RefreshVdevState() @@ -240,6 +266,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 +307,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; zpool_vdev_online(pool, vdev->GUIDString().c_str(), - ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE, - &m_vdevState); + flags, &m_vdevState); syslog(LOG_INFO, "Onlined vdev(%s/%s:%s). State now %s.\n", zpool_get_name(pool), vdev->GUIDString().c_str(), devPath.c_str(), @@ -783,7 +811,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; diff --git a/cmd/zfsd/case_file.h b/cmd/zfsd/case_file.h index b4dc2dee5d..d7475d331a 100644 --- a/cmd/zfsd/case_file.h +++ b/cmd/zfsd/case_file.h @@ -98,6 +98,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,6 +232,11 @@ public: */ bool ShouldFault() const; + /** + * \brief If this vdev is spare + */ + int IsSpare(); + protected: enum { /** @@ -384,6 +402,7 @@ protected: string m_poolGUIDString; string m_vdevGUIDString; string m_vdevPhysPath; + int m_is_spare; /** * \brief Callout activated when a grace period diff --git a/cmd/zfsd/vdev_iterator.cc b/cmd/zfsd/vdev_iterator.cc index b5a4f22c1c..c23399ed68 100644 --- a/cmd/zfsd/vdev_iterator.cc +++ b/cmd/zfsd/vdev_iterator.cc @@ -78,8 +78,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 +97,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 * diff --git a/cmd/zfsd/zfsd_event.cc b/cmd/zfsd/zfsd_event.cc index 253d620c9a..9f63dd88e2 100644 --- a/cmd/zfsd/zfsd_event.cc +++ b/cmd/zfsd/zfsd_event.cc @@ -231,7 +231,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 @@ -240,10 +242,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 + ": "); @@ -251,7 +255,7 @@ GeomEvent::OnlineByLabel(const string &devPath, const string& physPath, exp.GetString().insert(0, context); exp.Log(); } - return (false); + return (ret); }