svn commit: r256479 - projects/zfsd/head/cddl/sbin/zfsd
Alan Somers
asomers at FreeBSD.org
Mon Oct 14 23:41:56 UTC 2013
Author: asomers
Date: Mon Oct 14 23:41:55 2013
New Revision: 256479
URL: http://svnweb.freebsd.org/changeset/base/256479
Log:
Fix a bug in zfsd: zfsd will fail to autoreplace by physical path a drive if
it had previously replaced that same drive when it belonged to a different
pool. The solution is to delete case files when their pools are destroyed.
A better fix would be to refactor zfsd to eliminate casefiles altogether,
and use a more stateless approach.
cddl/sbin/zfsd/case_file.cc
cddl/sbin/zfsd/zfsd_event.cc
Close a case file when its pool is destroyed. Log a warning
when two open case files correspond to the same physical
path.
Submitted by: alans
Approved by: ken (mentor)
Sponsored by: Spectra Logic Corporation
Modified:
projects/zfsd/head/cddl/sbin/zfsd/case_file.cc
projects/zfsd/head/cddl/sbin/zfsd/case_file.h
projects/zfsd/head/cddl/sbin/zfsd/zfsd_event.cc
Modified: projects/zfsd/head/cddl/sbin/zfsd/case_file.cc
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/case_file.cc Mon Oct 14 23:36:10 2013 (r256478)
+++ projects/zfsd/head/cddl/sbin/zfsd/case_file.cc Mon Oct 14 23:41:55 2013 (r256479)
@@ -150,15 +150,23 @@ CaseFile::Find(Guid poolGUID, Guid vdevG
CaseFile *
CaseFile::Find(const string &physPath)
{
+ CaseFile *result = NULL;
+
for (CaseFileList::iterator curCase = s_activeCases.begin();
curCase != s_activeCases.end(); curCase++) {
if ((*curCase)->PhysicalPath() != physPath)
continue;
- return (*curCase);
+ if (result != NULL) {
+ syslog(LOG_WARNING, "Multiple casefiles found for "
+ "physical path %s. "
+ "This is most likely a bug in zfsd",
+ physPath.c_str());
+ }
+ result = *curCase;
}
- return (NULL);
+ return (result);
}
@@ -370,8 +378,12 @@ CaseFile::ReEvaluate(const ZfsEvent &eve
Close();
return (/*consumed*/true);
- }
- else if (event.Value("type") == "misc.fs.zfs.config_sync") {
+ } else if (event.Value("type") == "misc.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") {
RefreshVdevState();
if (VdevState() < VDEV_STATE_HEALTHY)
consumed = ActivateSpare();
Modified: projects/zfsd/head/cddl/sbin/zfsd/case_file.h
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/case_file.h Mon Oct 14 23:36:10 2013 (r256478)
+++ projects/zfsd/head/cddl/sbin/zfsd/case_file.h Mon Oct 14 23:41:55 2013 (r256479)
@@ -296,7 +296,7 @@ protected:
/**
* \brief Unconditionally close a CaseFile.
*/
- void Close();
+ virtual void Close();
/**
* \brief Callout callback invoked when the remove timer grace
Modified: projects/zfsd/head/cddl/sbin/zfsd/zfsd_event.cc
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/zfsd_event.cc Mon Oct 14 23:36:10 2013 (r256478)
+++ projects/zfsd/head/cddl/sbin/zfsd/zfsd_event.cc Mon Oct 14 23:41:55 2013 (r256479)
@@ -195,6 +195,10 @@ DevfsEvent::Process() const
"as a replace by physical path candidate.\n",
devName.c_str());
} else if (havePhysPath && IsWholeDev()) {
+ /*
+ * TODO: attempt to resolve events using every casefile
+ * that matches this physpath
+ */
CaseFile *caseFile(CaseFile::Find(physPath));
if (caseFile != NULL) {
syslog(LOG_INFO,
@@ -371,6 +375,12 @@ ZfsEvent::ProcessPoolEvent() const
{
bool degradedDevice(false);
+ /* The pool is destroyed. Discard any open cases */
+ if (Value("type") == "misc.fs.zfs.pool_destroy") {
+ CaseFile::ReEvaluateByGuid(PoolGUID(), *this);
+ return;
+ }
+
CaseFile *caseFile(CaseFile::Find(PoolGUID(), VdevGUID()));
if (caseFile != NULL) {
if (caseFile->VdevState() != VDEV_STATE_UNKNOWN
More information about the svn-src-projects
mailing list