svn commit: r256461 - projects/zfsd/head/cddl/sbin/zfsd

Alan Somers asomers at FreeBSD.org
Mon Oct 14 21:34:50 UTC 2013


Author: asomers
Date: Mon Oct 14 21:34:49 2013
New Revision: 256461
URL: http://svnweb.freebsd.org/changeset/base/256461

Log:
  When a vdev generates IO errors, mark it as FAULTED instead of DEGRADED.
  Checksum errors will still be marked as DEGRADED.  This matches the behavior
  of Illumos.  I had to make a number of methods virtual to facilitate unit
  testing.
  
  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/vdev.h

Modified: projects/zfsd/head/cddl/sbin/zfsd/case_file.cc
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/case_file.cc	Mon Oct 14 21:30:00 2013	(r256460)
+++ projects/zfsd/head/cddl/sbin/zfsd/case_file.cc	Mon Oct 14 21:34:49 2013	(r256461)
@@ -806,11 +806,13 @@ CaseFile::Close()
 void
 CaseFile::OnGracePeriodEnded()
 {
+	bool should_fault, should_degrade;
+	ZpoolList zpl(ZpoolList::ZpoolByGUID, &m_poolGUID);
 	m_events.splice(m_events.begin(), m_tentativeEvents);
+	should_fault = ShouldFault();
+	should_degrade = ShouldDegrade();
 
-	if (m_events.size() > ZFS_DEGRADE_IO_COUNT) {
-
-		ZpoolList zpl(ZpoolList::ZpoolByGUID, &m_poolGUID);
+	if (should_fault || should_degrade) {
 		if (zpl.empty()
 		 || (VdevIterator(zpl.front()).Find(m_vdevGUID)) == NULL) {
 			/*
@@ -822,6 +824,28 @@ CaseFile::OnGracePeriodEnded()
 			return;
 		}
 
+	}
+
+	/* A fault condition has priority over a degrade condition */
+	if (ShouldFault()) {
+		/* Fault the vdev and close the case. */
+		if (zpool_vdev_fault(zpl.front(), (uint64_t)m_vdevGUID,
+				       VDEV_AUX_ERR_EXCEEDED) == 0) {
+			syslog(LOG_INFO, "Faulting vdev(%s/%s)",
+			       PoolGUIDString().c_str(),
+			       VdevGUIDString().c_str());
+			Close();
+			return;
+		}
+		else {
+			syslog(LOG_ERR, "Fault vdev(%s/%s): %s: %s\n",
+			       PoolGUIDString().c_str(),
+			       VdevGUIDString().c_str(),
+			       libzfs_error_action(g_zfsHandle),
+			       libzfs_error_description(g_zfsHandle));
+		}
+	}
+	else if (ShouldDegrade()) {
 		/* Degrade the vdev and close the case. */
 		if (zpool_vdev_degrade(zpl.front(), (uint64_t)m_vdevGUID,
 				       VDEV_AUX_ERR_EXCEEDED) == 0) {
@@ -907,3 +931,25 @@ CaseFile::Replace(const char* vdev_type,
 
 	return (true);
 }
+
+/* Does the argument event refer to a checksum error? */
+static bool IsChecksumEvent(const DevCtlEvent* const event){
+	return ("ereport.fs.zfs.checksum" == event->Value("type"));
+}
+
+/* Does the argument event refer to an IO error? */
+static bool IsIOEvent(const DevCtlEvent* const event){
+	return ("ereport.fs.zfs.io" == event->Value("type"));
+}
+
+bool
+CaseFile::ShouldDegrade() const {
+	return (std::count_if(m_events.begin(), m_events.end(),
+	    		      IsChecksumEvent) > ZFS_DEGRADE_IO_COUNT);
+}
+
+bool
+CaseFile::ShouldFault() const {
+	return (std::count_if(m_events.begin(), m_events.end(),
+	    		      IsIOEvent) > ZFS_DEGRADE_IO_COUNT);
+}

Modified: projects/zfsd/head/cddl/sbin/zfsd/case_file.h
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/case_file.h	Mon Oct 14 21:30:00 2013	(r256460)
+++ projects/zfsd/head/cddl/sbin/zfsd/case_file.h	Mon Oct 14 21:34:49 2013	(r256461)
@@ -114,7 +114,7 @@ public:
 	 *
 	 * \param vdev  The vdev object for which to find/create a CaseFile.
 	 *
-	 * \return  A referenc eto a valid CaseFile object.
+	 * \return  A reference to a valid CaseFile object.
 	 */
 	static CaseFile &Create(Vdev &vdev);
 
@@ -173,7 +173,7 @@ public:
 	/**
 	 * \brief Register an itimer callout for the given event, if necessary
 	 */
-	void RegisterCallout(const DevCtlEvent &event);
+	virtual void RegisterCallout(const DevCtlEvent &event);
 
 	/**
 	 * \brief Close a case if it is no longer relevant.
@@ -192,6 +192,16 @@ public:
 	 */
 	void Log();
 
+	/**
+	 * \brief Whether we should degrade this vdev
+	 */
+	bool ShouldDegrade() const;
+
+	/**
+	 * \brief Whether we should fault this vdev
+	 */
+	bool ShouldFault() const;
+
 protected:
 	enum {
 		/**
@@ -228,8 +238,11 @@ protected:
 	/** Constructor. */
 	CaseFile(const Vdev &vdev);
 
-	/** Destructor. */
-	~CaseFile();
+	/**
+	 * Destructor.
+	 * Must be virtual so it can be subclassed in the unit tests
+	 */
+	virtual ~CaseFile();
 
 	/**
 	 * \brief Reload state for the vdev associated with this CaseFile.
@@ -237,7 +250,7 @@ protected:
 	 * \return  True if the refresh was successful.  False if the system
 	 *          has no record of the pool or vdev for this CaseFile.
 	 */
-	bool RefreshVdevState();
+	virtual bool RefreshVdevState();
 
 	/**
 	 * \brief Free all events in the m_events list.

Modified: projects/zfsd/head/cddl/sbin/zfsd/vdev.h
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/vdev.h	Mon Oct 14 21:30:00 2013	(r256460)
+++ projects/zfsd/head/cddl/sbin/zfsd/vdev.h	Mon Oct 14 21:34:49 2013	(r256461)
@@ -96,11 +96,11 @@ public:
 	 */
 	Vdev(nvlist_t *vdevConfig);
 
-	Guid		 GUID()		const;
-	Guid		 PoolGUID()	const;
-	vdev_state	 State()	const;
-	std::string	 Path()		const;
-	std::string	 PhysicalPath()	const;
+	virtual Guid	 	GUID()		const;
+	virtual Guid	 	PoolGUID()	const;
+	virtual vdev_state	State()		const;
+	std::string	 	Path()		const;
+	virtual std::string	PhysicalPath()	const;
 	std::string	 GUIDString()	const;
 	nvlist_t	*PoolConfig()	const;
 	nvlist_t	*Config()	const;


More information about the svn-src-projects mailing list