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);
|
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 *
|
||||||
CaseFile::Find(const string &physPath)
|
CaseFile::Find(const string &physPath)
|
||||||
{
|
{
|
||||||
|
@ -217,6 +237,12 @@ CaseFile::PurgeAll()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
CaseFile::IsSpare()
|
||||||
|
{
|
||||||
|
return (m_is_spare);
|
||||||
|
}
|
||||||
|
|
||||||
//- CaseFile Public Methods ----------------------------------------------------
|
//- CaseFile Public Methods ----------------------------------------------------
|
||||||
bool
|
bool
|
||||||
CaseFile::RefreshVdevState()
|
CaseFile::RefreshVdevState()
|
||||||
|
@ -240,6 +266,7 @@ CaseFile::ReEvaluate(const string &devPath, const string &physPath, Vdev *vdev)
|
||||||
{
|
{
|
||||||
ZpoolList zpl(ZpoolList::ZpoolByGUID, &m_poolGUID);
|
ZpoolList zpl(ZpoolList::ZpoolByGUID, &m_poolGUID);
|
||||||
zpool_handle_t *pool(zpl.empty() ? NULL : zpl.front());
|
zpool_handle_t *pool(zpl.empty() ? NULL : zpl.front());
|
||||||
|
int flags = ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE;
|
||||||
|
|
||||||
if (pool == NULL || !RefreshVdevState()) {
|
if (pool == NULL || !RefreshVdevState()) {
|
||||||
/*
|
/*
|
||||||
|
@ -280,9 +307,10 @@ CaseFile::ReEvaluate(const string &devPath, const string &physPath, Vdev *vdev)
|
||||||
|| vdev->PoolGUID() == Guid::InvalidGuid())
|
|| vdev->PoolGUID() == Guid::InvalidGuid())
|
||||||
&& vdev->GUID() == m_vdevGUID) {
|
&& vdev->GUID() == m_vdevGUID) {
|
||||||
|
|
||||||
|
if (IsSpare())
|
||||||
|
flags |= ZFS_ONLINE_SPARE;
|
||||||
zpool_vdev_online(pool, vdev->GUIDString().c_str(),
|
zpool_vdev_online(pool, vdev->GUIDString().c_str(),
|
||||||
ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE,
|
flags, &m_vdevState);
|
||||||
&m_vdevState);
|
|
||||||
syslog(LOG_INFO, "Onlined vdev(%s/%s:%s). State now %s.\n",
|
syslog(LOG_INFO, "Onlined vdev(%s/%s:%s). State now %s.\n",
|
||||||
zpool_get_name(pool), vdev->GUIDString().c_str(),
|
zpool_get_name(pool), vdev->GUIDString().c_str(),
|
||||||
devPath.c_str(),
|
devPath.c_str(),
|
||||||
|
@ -783,7 +811,8 @@ CaseFile::CaseFile(const Vdev &vdev)
|
||||||
: m_poolGUID(vdev.PoolGUID()),
|
: m_poolGUID(vdev.PoolGUID()),
|
||||||
m_vdevGUID(vdev.GUID()),
|
m_vdevGUID(vdev.GUID()),
|
||||||
m_vdevState(vdev.State()),
|
m_vdevState(vdev.State()),
|
||||||
m_vdevPhysPath(vdev.PhysicalPath())
|
m_vdevPhysPath(vdev.PhysicalPath()),
|
||||||
|
m_is_spare(vdev.IsSpare())
|
||||||
{
|
{
|
||||||
stringstream guidString;
|
stringstream guidString;
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,19 @@ public:
|
||||||
*/
|
*/
|
||||||
static CaseFile *Find(DevdCtl::Guid poolGUID, DevdCtl::Guid vdevGUID);
|
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
|
* \brief Find a CaseFile object by a vdev's current/last known
|
||||||
* physical path.
|
* physical path.
|
||||||
|
@ -219,6 +232,11 @@ public:
|
||||||
*/
|
*/
|
||||||
bool ShouldFault() const;
|
bool ShouldFault() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief If this vdev is spare
|
||||||
|
*/
|
||||||
|
int IsSpare();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum {
|
enum {
|
||||||
/**
|
/**
|
||||||
|
@ -384,6 +402,7 @@ protected:
|
||||||
string m_poolGUIDString;
|
string m_poolGUIDString;
|
||||||
string m_vdevGUIDString;
|
string m_vdevGUIDString;
|
||||||
string m_vdevPhysPath;
|
string m_vdevPhysPath;
|
||||||
|
int m_is_spare;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Callout activated when a grace period
|
* \brief Callout activated when a grace period
|
||||||
|
|
|
@ -78,8 +78,10 @@ VdevIterator::Reset()
|
||||||
{
|
{
|
||||||
nvlist_t *rootVdev;
|
nvlist_t *rootVdev;
|
||||||
nvlist **cache_child;
|
nvlist **cache_child;
|
||||||
|
nvlist **spare_child;
|
||||||
int result;
|
int result;
|
||||||
uint_t cache_children;
|
uint_t cache_children;
|
||||||
|
uint_t spare_children;
|
||||||
|
|
||||||
result = nvlist_lookup_nvlist(m_poolConfig,
|
result = nvlist_lookup_nvlist(m_poolConfig,
|
||||||
ZPOOL_CONFIG_VDEV_TREE,
|
ZPOOL_CONFIG_VDEV_TREE,
|
||||||
|
@ -95,6 +97,13 @@ VdevIterator::Reset()
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
for (uint_t c = 0; c < cache_children; c++)
|
for (uint_t c = 0; c < cache_children; c++)
|
||||||
m_vdevQueue.push_back(cache_child[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 *
|
nvlist_t *
|
||||||
|
|
|
@ -231,7 +231,9 @@ bool
|
||||||
GeomEvent::OnlineByLabel(const string &devPath, const string& physPath,
|
GeomEvent::OnlineByLabel(const string &devPath, const string& physPath,
|
||||||
nvlist_t *devConfig)
|
nvlist_t *devConfig)
|
||||||
{
|
{
|
||||||
|
bool ret = false;
|
||||||
try {
|
try {
|
||||||
|
CaseFileList case_list;
|
||||||
/*
|
/*
|
||||||
* A device with ZFS label information has been
|
* A device with ZFS label information has been
|
||||||
* inserted. If it matches a device for which we
|
* 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",
|
syslog(LOG_INFO, "Interrogating VDEV label for %s\n",
|
||||||
devPath.c_str());
|
devPath.c_str());
|
||||||
Vdev vdev(devConfig);
|
Vdev vdev(devConfig);
|
||||||
CaseFile *caseFile(CaseFile::Find(vdev.PoolGUID(),
|
CaseFile::Find(vdev.PoolGUID(),vdev.GUID(), case_list);
|
||||||
vdev.GUID()));
|
for (CaseFileList::iterator curr = case_list.begin();
|
||||||
if (caseFile != NULL)
|
curr != case_list.end(); curr++) {
|
||||||
return (caseFile->ReEvaluate(devPath, physPath, &vdev));
|
ret |= (*curr)->ReEvaluate(devPath, physPath, &vdev);
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
|
||||||
} catch (ZfsdException &exp) {
|
} catch (ZfsdException &exp) {
|
||||||
string context("GeomEvent::OnlineByLabel: " + devPath + ": ");
|
string context("GeomEvent::OnlineByLabel: " + devPath + ": ");
|
||||||
|
@ -251,7 +255,7 @@ GeomEvent::OnlineByLabel(const string &devPath, const string& physPath,
|
||||||
exp.GetString().insert(0, context);
|
exp.GetString().insert(0, context);
|
||||||
exp.Log();
|
exp.Log();
|
||||||
}
|
}
|
||||||
return (false);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue