zfsd(8), the ZFS fault management daemon
Add zfsd, which deals with hard drive faults in ZFS pools. It manages
hotspares and replements in drive slots that publish physical paths.
cddl/usr.sbin/zfsd
Add zfsd(8) and its unit tests
cddl/usr.sbin/Makefile
Add zfsd to the build
lib/libdevdctl
A C++ library that helps devd clients process events
lib/Makefile
share/mk/bsd.libnames.mk
share/mk/src.libnames.mk
Add libdevdctl to the build. It's a private library, unusable by
out-of-tree software.
etc/defaults/rc.conf
By default, set zfsd_enable to NO
etc/mtree/BSD.include.dist
Add a directory for libdevdctl's include files
etc/mtree/BSD.tests.dist
Add a directory for zfsd's unit tests
etc/mtree/BSD.var.dist
Add /var/db/zfsd/cases, where zfsd stores case files while it's shut
down.
etc/rc.d/Makefile
etc/rc.d/zfsd
Add zfsd's rc script
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
Fix the resource.fs.zfs.statechange message. It had a number of
problems:
It was only being emitted on a transition to the HEALTHY state.
That made it impossible for zfsd to take actions based on drives
getting sicker.
It compared the new state to vdev_prevstate, which is the state that
the vdev had the last time it was opened. That doesn't make sense,
because a vdev can change state multiple times without being
reopened.
vdev_set_state contains logic that will change the device's new
state based on various conditions. However, the statechange event
was being posted _before_ that logic took effect. Now it's being
posted after.
Submitted by: gibbs, asomers, mav, allanjude
Reviewed by: mav, delphij
Relnotes: yes
Sponsored by: Spectra Logic Corp, iX Systems
Differential Revision: https://reviews.freebsd.org/D6564
2016-05-28 17:43:40 +00:00
|
|
|
/*-
|
|
|
|
* Copyright (c) 2011, 2012, 2013, 2016 Spectra Logic Corporation
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions, and the following disclaimer,
|
|
|
|
* without modification.
|
|
|
|
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
|
|
|
* substantially similar to the "NO WARRANTY" disclaimer below
|
|
|
|
* ("Disclaimer") and any redistribution must be conditioned upon
|
|
|
|
* including a substantially similar Disclaimer requirement for further
|
|
|
|
* binary redistribution.
|
|
|
|
*
|
|
|
|
* NO WARRANTY
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
|
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGES.
|
|
|
|
*
|
|
|
|
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
|
|
|
|
*
|
|
|
|
* $FreeBSD$
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \file devdctl_event.h
|
|
|
|
*
|
|
|
|
* \brief Class hierarchy used to express events received via
|
|
|
|
* the devdctl API.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _DEVDCTL_EVENT_H_
|
|
|
|
#define _DEVDCTL_EVENT_H_
|
|
|
|
|
|
|
|
/*============================ Namespace Control =============================*/
|
|
|
|
namespace DevdCtl
|
|
|
|
{
|
|
|
|
|
|
|
|
/*=========================== Forward Declarations ===========================*/
|
|
|
|
class EventFactory;
|
|
|
|
|
|
|
|
/*============================= Class Definitions ============================*/
|
|
|
|
/*-------------------------------- NVPairMap ---------------------------------*/
|
|
|
|
/**
|
|
|
|
* NVPairMap is a specialization of the standard map STL container.
|
|
|
|
*/
|
|
|
|
typedef std::map<std::string, std::string> NVPairMap;
|
|
|
|
|
|
|
|
/*----------------------------------- Event ----------------------------------*/
|
|
|
|
/**
|
|
|
|
* \brief Container for the name => value pairs that comprise the content of
|
|
|
|
* a device control event.
|
|
|
|
*
|
|
|
|
* All name => value data for events can be accessed via the Contains()
|
|
|
|
* and Value() methods. name => value pairs for data not explicitly
|
|
|
|
* received as a name => value pair are synthesized during parsing. For
|
|
|
|
* example, ATTACH and DETACH events have "device-name" and "parent"
|
|
|
|
* name => value pairs added.
|
|
|
|
*/
|
|
|
|
class Event
|
|
|
|
{
|
|
|
|
friend class EventFactory;
|
|
|
|
|
|
|
|
public:
|
|
|
|
/** Event type */
|
|
|
|
enum Type {
|
|
|
|
/** Generic event notification. */
|
|
|
|
NOTIFY = '!',
|
|
|
|
|
|
|
|
/** A driver was not found for this device. */
|
|
|
|
NOMATCH = '?',
|
|
|
|
|
|
|
|
/** A bus device instance has been added. */
|
|
|
|
ATTACH = '+',
|
|
|
|
|
|
|
|
/** A bus device instance has been removed. */
|
|
|
|
DETACH = '-'
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Factory method type to construct an Event given
|
|
|
|
* the type of event and an NVPairMap populated from
|
|
|
|
* the event string received from devd.
|
|
|
|
*/
|
|
|
|
typedef Event* (BuildMethod)(Type, NVPairMap &, const std::string &);
|
|
|
|
|
|
|
|
/** Generic Event object factory. */
|
|
|
|
static BuildMethod Builder;
|
|
|
|
|
|
|
|
static Event *CreateEvent(const EventFactory &factory,
|
|
|
|
const std::string &eventString);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the devname, if any, associated with the event
|
|
|
|
*
|
|
|
|
* \param name Devname, returned by reference
|
|
|
|
* \return True iff the event contained a devname
|
|
|
|
*/
|
|
|
|
virtual bool DevName(std::string &name) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the absolute pathname of the device associated with this
|
|
|
|
* event.
|
|
|
|
*
|
|
|
|
* \param name Devname, returned by reference
|
|
|
|
* \return True iff the event contained a devname
|
|
|
|
*/
|
|
|
|
bool DevPath(std::string &path) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true iff this event refers to a disk device
|
|
|
|
*/
|
|
|
|
bool IsDiskDev() const;
|
|
|
|
|
|
|
|
/** Returns the physical path of the device, if any
|
|
|
|
*
|
|
|
|
* \param path Physical path, returned by reference
|
|
|
|
* \return True iff the event contains a device with a physical
|
|
|
|
* path
|
|
|
|
*/
|
|
|
|
bool PhysicalPath(std::string &path) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provide a user friendly string representation of an
|
|
|
|
* event type.
|
|
|
|
*
|
|
|
|
* \param type The type of event to map to a string.
|
|
|
|
*
|
|
|
|
* \return A user friendly string representing the input type.
|
|
|
|
*/
|
|
|
|
static const char *TypeToString(Type type);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine the availability of a name => value pair by name.
|
|
|
|
*
|
|
|
|
* \param name The key name to search for in this event instance.
|
|
|
|
*
|
|
|
|
* \return true if the specified key is available in this
|
|
|
|
* event, otherwise false.
|
|
|
|
*/
|
|
|
|
bool Contains(const std::string &name) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \param key The name of the key for which to retrieve its
|
|
|
|
* associated value.
|
|
|
|
*
|
|
|
|
* \return A const reference to the string representing the
|
|
|
|
* value associated with key.
|
|
|
|
*
|
|
|
|
* \note For key's with no registered value, the empty string
|
|
|
|
* is returned.
|
|
|
|
*/
|
|
|
|
const std::string &Value(const std::string &key) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the type of this event instance.
|
|
|
|
*
|
|
|
|
* \return The type of this event instance.
|
|
|
|
*/
|
|
|
|
Type GetType() const;
|
|
|
|
|
|
|
|
/**
|
2016-05-30 19:25:00 +00:00
|
|
|
* Get the original DevdCtl event string for this event.
|
zfsd(8), the ZFS fault management daemon
Add zfsd, which deals with hard drive faults in ZFS pools. It manages
hotspares and replements in drive slots that publish physical paths.
cddl/usr.sbin/zfsd
Add zfsd(8) and its unit tests
cddl/usr.sbin/Makefile
Add zfsd to the build
lib/libdevdctl
A C++ library that helps devd clients process events
lib/Makefile
share/mk/bsd.libnames.mk
share/mk/src.libnames.mk
Add libdevdctl to the build. It's a private library, unusable by
out-of-tree software.
etc/defaults/rc.conf
By default, set zfsd_enable to NO
etc/mtree/BSD.include.dist
Add a directory for libdevdctl's include files
etc/mtree/BSD.tests.dist
Add a directory for zfsd's unit tests
etc/mtree/BSD.var.dist
Add /var/db/zfsd/cases, where zfsd stores case files while it's shut
down.
etc/rc.d/Makefile
etc/rc.d/zfsd
Add zfsd's rc script
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
Fix the resource.fs.zfs.statechange message. It had a number of
problems:
It was only being emitted on a transition to the HEALTHY state.
That made it impossible for zfsd to take actions based on drives
getting sicker.
It compared the new state to vdev_prevstate, which is the state that
the vdev had the last time it was opened. That doesn't make sense,
because a vdev can change state multiple times without being
reopened.
vdev_set_state contains logic that will change the device's new
state based on various conditions. However, the statechange event
was being posted _before_ that logic took effect. Now it's being
posted after.
Submitted by: gibbs, asomers, mav, allanjude
Reviewed by: mav, delphij
Relnotes: yes
Sponsored by: Spectra Logic Corp, iX Systems
Differential Revision: https://reviews.freebsd.org/D6564
2016-05-28 17:43:40 +00:00
|
|
|
*
|
|
|
|
* \return The DevdCtl event string.
|
|
|
|
*/
|
|
|
|
const std::string &GetEventString() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert the event instance into a string suitable for
|
|
|
|
* printing to the console or emitting to syslog.
|
|
|
|
*
|
|
|
|
* \return A string of formatted event data.
|
|
|
|
*/
|
|
|
|
std::string ToString() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Pretty-print this event instance to cout.
|
|
|
|
*/
|
|
|
|
void Print() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Pretty-print this event instance to syslog.
|
|
|
|
*
|
|
|
|
* \param priority The logging priority/facility.
|
|
|
|
* See syslog(3).
|
|
|
|
*/
|
|
|
|
void Log(int priority) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create and return a fully independent clone
|
|
|
|
* of this event.
|
|
|
|
*/
|
|
|
|
virtual Event *DeepCopy() const;
|
|
|
|
|
|
|
|
/** Destructor */
|
|
|
|
virtual ~Event();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Interpret and perform any actions necessary to
|
|
|
|
* consume the event.
|
|
|
|
*
|
|
|
|
* \return True if this event should be queued for later reevaluation
|
|
|
|
*/
|
|
|
|
virtual bool Process() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the time that the event was created
|
|
|
|
*/
|
|
|
|
timeval GetTimestamp() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a timestamp to the event string, if one does not already exist
|
|
|
|
* TODO: make this an instance method that operates on the std::map
|
|
|
|
* instead of the string. We must fix zfsd's CaseFile serialization
|
|
|
|
* routines first, so that they don't need the raw event string.
|
|
|
|
*
|
|
|
|
* \param[in,out] eventString The devd event string to modify
|
|
|
|
*/
|
|
|
|
static void TimestampEventString(std::string &eventString);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Access all parsed key => value pairs.
|
|
|
|
*/
|
|
|
|
const NVPairMap &GetMap() const;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/** Table entries used to map a type to a user friendly string. */
|
|
|
|
struct EventTypeRecord
|
|
|
|
{
|
|
|
|
Type m_type;
|
|
|
|
const char *m_typeName;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* \param type The type of event to create.
|
|
|
|
*/
|
|
|
|
Event(Type type, NVPairMap &map, const std::string &eventString);
|
|
|
|
|
|
|
|
/** Deep copy constructor. */
|
|
|
|
Event(const Event &src);
|
|
|
|
|
|
|
|
/** Always empty string returned when NVPairMap lookups fail. */
|
|
|
|
static const std::string s_theEmptyString;
|
|
|
|
|
|
|
|
/** Unsorted table of event types. */
|
|
|
|
static EventTypeRecord s_typeTable[];
|
|
|
|
|
|
|
|
/** The type of this event. */
|
|
|
|
const Type m_type;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Event attribute storage.
|
|
|
|
*
|
|
|
|
* \note Although stored by reference (since m_nvPairs can
|
|
|
|
* never be NULL), the NVPairMap referenced by this field
|
|
|
|
* is dynamically allocated and owned by this event object.
|
2016-05-30 19:25:00 +00:00
|
|
|
* m_nvPairs must be deleted at event destruction.
|
zfsd(8), the ZFS fault management daemon
Add zfsd, which deals with hard drive faults in ZFS pools. It manages
hotspares and replements in drive slots that publish physical paths.
cddl/usr.sbin/zfsd
Add zfsd(8) and its unit tests
cddl/usr.sbin/Makefile
Add zfsd to the build
lib/libdevdctl
A C++ library that helps devd clients process events
lib/Makefile
share/mk/bsd.libnames.mk
share/mk/src.libnames.mk
Add libdevdctl to the build. It's a private library, unusable by
out-of-tree software.
etc/defaults/rc.conf
By default, set zfsd_enable to NO
etc/mtree/BSD.include.dist
Add a directory for libdevdctl's include files
etc/mtree/BSD.tests.dist
Add a directory for zfsd's unit tests
etc/mtree/BSD.var.dist
Add /var/db/zfsd/cases, where zfsd stores case files while it's shut
down.
etc/rc.d/Makefile
etc/rc.d/zfsd
Add zfsd's rc script
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
Fix the resource.fs.zfs.statechange message. It had a number of
problems:
It was only being emitted on a transition to the HEALTHY state.
That made it impossible for zfsd to take actions based on drives
getting sicker.
It compared the new state to vdev_prevstate, which is the state that
the vdev had the last time it was opened. That doesn't make sense,
because a vdev can change state multiple times without being
reopened.
vdev_set_state contains logic that will change the device's new
state based on various conditions. However, the statechange event
was being posted _before_ that logic took effect. Now it's being
posted after.
Submitted by: gibbs, asomers, mav, allanjude
Reviewed by: mav, delphij
Relnotes: yes
Sponsored by: Spectra Logic Corp, iX Systems
Differential Revision: https://reviews.freebsd.org/D6564
2016-05-28 17:43:40 +00:00
|
|
|
*/
|
|
|
|
NVPairMap &m_nvPairs;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The unaltered event string, as received from devd, used to
|
|
|
|
* create this event object.
|
|
|
|
*/
|
|
|
|
std::string m_eventString;
|
|
|
|
|
|
|
|
private:
|
|
|
|
/**
|
|
|
|
* Ingest event data from the supplied string.
|
|
|
|
*
|
|
|
|
* \param[in] eventString The string of devd event data to parse.
|
|
|
|
* \param[out] nvpairs Returns the parsed data
|
|
|
|
*/
|
|
|
|
static void ParseEventString(Type type, const std::string &eventString,
|
|
|
|
NVPairMap &nvpairs);
|
|
|
|
};
|
|
|
|
|
|
|
|
inline Event::Type
|
|
|
|
Event::GetType() const
|
|
|
|
{
|
|
|
|
return (m_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const std::string &
|
|
|
|
Event::GetEventString() const
|
|
|
|
{
|
|
|
|
return (m_eventString);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const NVPairMap &
|
|
|
|
Event::GetMap() const
|
|
|
|
{
|
|
|
|
return (m_nvPairs);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*--------------------------------- EventList --------------------------------*/
|
|
|
|
/**
|
|
|
|
* EventList is a specialization of the standard list STL container.
|
|
|
|
*/
|
|
|
|
typedef std::list<Event *> EventList;
|
|
|
|
|
|
|
|
/*-------------------------------- DevfsEvent --------------------------------*/
|
|
|
|
class DevfsEvent : public Event
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Specialized Event object factory for Devfs events. */
|
|
|
|
static BuildMethod Builder;
|
|
|
|
|
|
|
|
virtual Event *DeepCopy() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Interpret and perform any actions necessary to
|
|
|
|
* consume the event.
|
|
|
|
* \return True if this event should be queued for later reevaluation
|
|
|
|
*/
|
|
|
|
virtual bool Process() const;
|
|
|
|
|
|
|
|
bool IsWholeDev() const;
|
|
|
|
virtual bool DevName(std::string &name) const;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/**
|
|
|
|
* Given the device name of a disk, determine if the device
|
|
|
|
* represents the whole device, not just a partition.
|
|
|
|
*
|
|
|
|
* \param devName Device name of disk device to test.
|
|
|
|
*
|
|
|
|
* \return True if the device name represents the whole device.
|
|
|
|
* Otherwise false.
|
|
|
|
*/
|
|
|
|
static bool IsWholeDev(const std::string &devName);
|
|
|
|
|
|
|
|
/** DeepCopy Constructor. */
|
|
|
|
DevfsEvent(const DevfsEvent &src);
|
|
|
|
|
|
|
|
/** Constructor */
|
|
|
|
DevfsEvent(Type, NVPairMap &, const std::string &);
|
|
|
|
};
|
|
|
|
|
|
|
|
/*--------------------------------- GeomEvent --------------------------------*/
|
|
|
|
class GeomEvent : public Event
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Specialized Event object factory for GEOM events. */
|
|
|
|
static BuildMethod Builder;
|
|
|
|
|
|
|
|
virtual Event *DeepCopy() const;
|
|
|
|
|
|
|
|
virtual bool DevName(std::string &name) const;
|
|
|
|
|
|
|
|
const std::string &DeviceName() const;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/** Constructor */
|
|
|
|
GeomEvent(Type, NVPairMap &, const std::string &);
|
|
|
|
|
|
|
|
/** Deep copy constructor. */
|
|
|
|
GeomEvent(const GeomEvent &src);
|
|
|
|
|
|
|
|
std::string m_devname;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*--------------------------------- ZfsEvent ---------------------------------*/
|
|
|
|
class ZfsEvent : public Event
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Specialized Event object factory for ZFS events. */
|
|
|
|
static BuildMethod Builder;
|
|
|
|
|
|
|
|
virtual Event *DeepCopy() const;
|
|
|
|
|
|
|
|
virtual bool DevName(std::string &name) const;
|
|
|
|
|
|
|
|
const std::string &PoolName() const;
|
|
|
|
Guid PoolGUID() const;
|
|
|
|
Guid VdevGUID() const;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/** Constructor */
|
|
|
|
ZfsEvent(Type, NVPairMap &, const std::string &);
|
|
|
|
|
|
|
|
/** Deep copy constructor. */
|
|
|
|
ZfsEvent(const ZfsEvent &src);
|
|
|
|
|
|
|
|
Guid m_poolGUID;
|
|
|
|
Guid m_vdevGUID;
|
|
|
|
};
|
|
|
|
|
|
|
|
//- ZfsEvent Inline Public Methods --------------------------------------------
|
|
|
|
inline const std::string&
|
|
|
|
ZfsEvent::PoolName() const
|
|
|
|
{
|
|
|
|
/* The pool name is reported as the subsystem of ZFS events. */
|
|
|
|
return (Value("subsystem"));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Guid
|
|
|
|
ZfsEvent::PoolGUID() const
|
|
|
|
{
|
|
|
|
return (m_poolGUID);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Guid
|
|
|
|
ZfsEvent::VdevGUID() const
|
|
|
|
{
|
|
|
|
return (m_vdevGUID);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace DevdCtl
|
|
|
|
#endif /*_DEVDCTL_EVENT_H_ */
|