zfsd: add support for hotplugging spares
If you remove an unused spare and then reinsert it, zfsd will now online it in all pools. Signed-off-by: Ameer Hamza <ahamza@ixsystems.com>
This commit is contained in:
parent
0b58a60509
commit
f34365ed28
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue