xref: /freebsd/cddl/usr.sbin/zfsd/zfsd.cc (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
17a0c41d5SAlan Somers /*-
27a0c41d5SAlan Somers  * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016  Spectra Logic Corporation
37a0c41d5SAlan Somers  * All rights reserved.
47a0c41d5SAlan Somers  *
57a0c41d5SAlan Somers  * Redistribution and use in source and binary forms, with or without
67a0c41d5SAlan Somers  * modification, are permitted provided that the following conditions
77a0c41d5SAlan Somers  * are met:
87a0c41d5SAlan Somers  * 1. Redistributions of source code must retain the above copyright
97a0c41d5SAlan Somers  *    notice, this list of conditions, and the following disclaimer,
107a0c41d5SAlan Somers  *    without modification.
117a0c41d5SAlan Somers  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
127a0c41d5SAlan Somers  *    substantially similar to the "NO WARRANTY" disclaimer below
137a0c41d5SAlan Somers  *    ("Disclaimer") and any redistribution must be conditioned upon
147a0c41d5SAlan Somers  *    including a substantially similar Disclaimer requirement for further
157a0c41d5SAlan Somers  *    binary redistribution.
167a0c41d5SAlan Somers  *
177a0c41d5SAlan Somers  * NO WARRANTY
187a0c41d5SAlan Somers  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
197a0c41d5SAlan Somers  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
207a0c41d5SAlan Somers  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
217a0c41d5SAlan Somers  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
227a0c41d5SAlan Somers  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
237a0c41d5SAlan Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
247a0c41d5SAlan Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
257a0c41d5SAlan Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
267a0c41d5SAlan Somers  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
277a0c41d5SAlan Somers  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
287a0c41d5SAlan Somers  * POSSIBILITY OF SUCH DAMAGES.
297a0c41d5SAlan Somers  *
307a0c41d5SAlan Somers  * Authors: Justin T. Gibbs     (Spectra Logic Corporation)
317a0c41d5SAlan Somers  */
327a0c41d5SAlan Somers 
337a0c41d5SAlan Somers /**
347a0c41d5SAlan Somers  * \file zfsd.cc
357a0c41d5SAlan Somers  *
367a0c41d5SAlan Somers  * The ZFS daemon consumes kernel devdctl(4) event data via devd(8)'s
377a0c41d5SAlan Somers  * unix domain socket in order to react to system changes that impact
387a0c41d5SAlan Somers  * the function of ZFS storage pools.  The goal of this daemon is to
397a0c41d5SAlan Somers  * provide similar functionality to the Solaris ZFS Diagnostic Engine
407a0c41d5SAlan Somers  * (zfs-diagnosis), the Solaris ZFS fault handler (zfs-retire), and
417a0c41d5SAlan Somers  * the Solaris ZFS vdev insertion agent (zfs-mod sysevent handler).
427a0c41d5SAlan Somers  */
437a0c41d5SAlan Somers 
447a0c41d5SAlan Somers #include <sys/cdefs.h>
459e5787d2SMatt Macy #include <sys/byteorder.h>
467a0c41d5SAlan Somers #include <sys/param.h>
477a0c41d5SAlan Somers #include <sys/fs/zfs.h>
487a0c41d5SAlan Somers 
497a0c41d5SAlan Somers #include <err.h>
509e5787d2SMatt Macy #include <fcntl.h>
517a0c41d5SAlan Somers #include <libgeom.h>
527a0c41d5SAlan Somers #include <libutil.h>
537a0c41d5SAlan Somers #include <poll.h>
547a0c41d5SAlan Somers #include <syslog.h>
557a0c41d5SAlan Somers 
567a0c41d5SAlan Somers #include <libzfs.h>
577a0c41d5SAlan Somers 
587a0c41d5SAlan Somers #include <list>
597a0c41d5SAlan Somers #include <map>
607a0c41d5SAlan Somers #include <string>
617a0c41d5SAlan Somers 
627a0c41d5SAlan Somers #include <devdctl/guid.h>
637a0c41d5SAlan Somers #include <devdctl/event.h>
647a0c41d5SAlan Somers #include <devdctl/event_factory.h>
657a0c41d5SAlan Somers #include <devdctl/exception.h>
667a0c41d5SAlan Somers #include <devdctl/consumer.h>
677a0c41d5SAlan Somers 
687a0c41d5SAlan Somers #include "callout.h"
697a0c41d5SAlan Somers #include "vdev_iterator.h"
707a0c41d5SAlan Somers #include "zfsd_event.h"
717a0c41d5SAlan Somers #include "case_file.h"
727a0c41d5SAlan Somers #include "vdev.h"
737a0c41d5SAlan Somers #include "vdev_iterator.h"
747a0c41d5SAlan Somers #include "zfsd.h"
757a0c41d5SAlan Somers #include "zfsd_exception.h"
767a0c41d5SAlan Somers #include "zpool_list.h"
777a0c41d5SAlan Somers /*================================== Macros ==================================*/
787a0c41d5SAlan Somers #define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
797a0c41d5SAlan Somers 
807a0c41d5SAlan Somers /*============================ Namespace Control =============================*/
817a0c41d5SAlan Somers using DevdCtl::Event;
827a0c41d5SAlan Somers using DevdCtl::EventFactory;
837a0c41d5SAlan Somers using DevdCtl::EventList;
847a0c41d5SAlan Somers 
857a0c41d5SAlan Somers /*================================ Global Data ===============================*/
867a0c41d5SAlan Somers int              g_debug = 0;
877a0c41d5SAlan Somers libzfs_handle_t *g_zfsHandle;
887a0c41d5SAlan Somers 
897a0c41d5SAlan Somers /*--------------------------------- ZfsDaemon --------------------------------*/
907a0c41d5SAlan Somers //- ZfsDaemon Static Private Data ----------------------------------------------
917a0c41d5SAlan Somers ZfsDaemon	    *ZfsDaemon::s_theZfsDaemon;
927a0c41d5SAlan Somers bool		     ZfsDaemon::s_logCaseFiles;
937a0c41d5SAlan Somers bool		     ZfsDaemon::s_terminateEventLoop;
947a0c41d5SAlan Somers char		     ZfsDaemon::s_pidFilePath[] = "/var/run/zfsd.pid";
957a0c41d5SAlan Somers pidfh		    *ZfsDaemon::s_pidFH;
967a0c41d5SAlan Somers int		     ZfsDaemon::s_signalPipeFD[2];
977a0c41d5SAlan Somers bool		     ZfsDaemon::s_systemRescanRequested(false);
987a0c41d5SAlan Somers EventFactory::Record ZfsDaemon::s_registryEntries[] =
997a0c41d5SAlan Somers {
1007a0c41d5SAlan Somers 	{ Event::NOTIFY, "GEOM",  &GeomEvent::Builder },
1017a0c41d5SAlan Somers 	{ Event::NOTIFY, "ZFS",   &ZfsEvent::Builder }
1027a0c41d5SAlan Somers };
1037a0c41d5SAlan Somers 
1047a0c41d5SAlan Somers //- ZfsDaemon Static Public Methods --------------------------------------------
1057a0c41d5SAlan Somers ZfsDaemon &
Get()1067a0c41d5SAlan Somers ZfsDaemon::Get()
1077a0c41d5SAlan Somers {
1087a0c41d5SAlan Somers 	return (*s_theZfsDaemon);
1097a0c41d5SAlan Somers }
1107a0c41d5SAlan Somers 
1117a0c41d5SAlan Somers void
WakeEventLoop()1127a0c41d5SAlan Somers ZfsDaemon::WakeEventLoop()
1137a0c41d5SAlan Somers {
1147a0c41d5SAlan Somers 	write(s_signalPipeFD[1], "+", 1);
1157a0c41d5SAlan Somers }
1167a0c41d5SAlan Somers 
1177a0c41d5SAlan Somers void
RequestSystemRescan()1187a0c41d5SAlan Somers ZfsDaemon::RequestSystemRescan()
1197a0c41d5SAlan Somers {
1207a0c41d5SAlan Somers 	s_systemRescanRequested = true;
1217a0c41d5SAlan Somers 	ZfsDaemon::WakeEventLoop();
1227a0c41d5SAlan Somers }
1237a0c41d5SAlan Somers 
1247a0c41d5SAlan Somers void
Run()1257a0c41d5SAlan Somers ZfsDaemon::Run()
1267a0c41d5SAlan Somers {
1277a0c41d5SAlan Somers 	ZfsDaemon daemon;
1287a0c41d5SAlan Somers 
1297a0c41d5SAlan Somers 	while (s_terminateEventLoop == false) {
1307a0c41d5SAlan Somers 
1317a0c41d5SAlan Somers 		try {
1327a0c41d5SAlan Somers 			daemon.DisconnectFromDevd();
1337a0c41d5SAlan Somers 
1347a0c41d5SAlan Somers 			if (daemon.ConnectToDevd() == false) {
1357a0c41d5SAlan Somers 				sleep(30);
1367a0c41d5SAlan Somers 				continue;
1377a0c41d5SAlan Somers 			}
1387a0c41d5SAlan Somers 
1397a0c41d5SAlan Somers 			daemon.DetectMissedEvents();
1407a0c41d5SAlan Somers 
1417a0c41d5SAlan Somers 			daemon.EventLoop();
1427a0c41d5SAlan Somers 
1437a0c41d5SAlan Somers 		} catch (const DevdCtl::Exception &exp) {
1447a0c41d5SAlan Somers 			exp.Log();
1457a0c41d5SAlan Somers 		}
1467a0c41d5SAlan Somers 	}
1477a0c41d5SAlan Somers 
1487a0c41d5SAlan Somers 	daemon.DisconnectFromDevd();
1497a0c41d5SAlan Somers }
1507a0c41d5SAlan Somers 
1517a0c41d5SAlan Somers //- ZfsDaemon Private Methods --------------------------------------------------
ZfsDaemon()1527a0c41d5SAlan Somers ZfsDaemon::ZfsDaemon()
1537a0c41d5SAlan Somers  : Consumer(/*defBuilder*/NULL, s_registryEntries,
1547a0c41d5SAlan Somers 	    NUM_ELEMENTS(s_registryEntries))
1557a0c41d5SAlan Somers {
1567a0c41d5SAlan Somers 	if (s_theZfsDaemon != NULL)
1577a0c41d5SAlan Somers 		errx(1, "Multiple ZfsDaemon instances created. Exiting");
1587a0c41d5SAlan Somers 
1597a0c41d5SAlan Somers 	s_theZfsDaemon = this;
1607a0c41d5SAlan Somers 
1617a0c41d5SAlan Somers 	if (pipe(s_signalPipeFD) != 0)
1627a0c41d5SAlan Somers 		errx(1, "Unable to allocate signal pipe. Exiting");
1637a0c41d5SAlan Somers 
1647a0c41d5SAlan Somers 	if (fcntl(s_signalPipeFD[0], F_SETFL, O_NONBLOCK) == -1)
1657a0c41d5SAlan Somers 		errx(1, "Unable to set pipe as non-blocking. Exiting");
1667a0c41d5SAlan Somers 
1677a0c41d5SAlan Somers 	if (fcntl(s_signalPipeFD[1], F_SETFL, O_NONBLOCK) == -1)
1687a0c41d5SAlan Somers 		errx(1, "Unable to set pipe as non-blocking. Exiting");
1697a0c41d5SAlan Somers 
1707a0c41d5SAlan Somers 	signal(SIGHUP,  ZfsDaemon::RescanSignalHandler);
1717a0c41d5SAlan Somers 	signal(SIGINFO, ZfsDaemon::InfoSignalHandler);
1727a0c41d5SAlan Somers 	signal(SIGINT,  ZfsDaemon::QuitSignalHandler);
1737a0c41d5SAlan Somers 	signal(SIGTERM, ZfsDaemon::QuitSignalHandler);
1747a0c41d5SAlan Somers 	signal(SIGUSR1, ZfsDaemon::RescanSignalHandler);
1757a0c41d5SAlan Somers 
1767a0c41d5SAlan Somers 	g_zfsHandle = libzfs_init();
1777a0c41d5SAlan Somers 	if (g_zfsHandle == NULL)
1787a0c41d5SAlan Somers 		errx(1, "Unable to initialize ZFS library. Exiting");
1797a0c41d5SAlan Somers 
1807a0c41d5SAlan Somers 	Callout::Init();
1817a0c41d5SAlan Somers 	InitializeSyslog();
1827a0c41d5SAlan Somers 	OpenPIDFile();
1837a0c41d5SAlan Somers 
1847a0c41d5SAlan Somers 	if (g_debug == 0)
1857a0c41d5SAlan Somers 		daemon(0, 0);
1867a0c41d5SAlan Somers 
1877a0c41d5SAlan Somers 	UpdatePIDFile();
1887a0c41d5SAlan Somers }
1897a0c41d5SAlan Somers 
~ZfsDaemon()1907a0c41d5SAlan Somers ZfsDaemon::~ZfsDaemon()
1917a0c41d5SAlan Somers {
1927a0c41d5SAlan Somers 	PurgeCaseFiles();
1937a0c41d5SAlan Somers 	ClosePIDFile();
1947a0c41d5SAlan Somers }
1957a0c41d5SAlan Somers 
1967a0c41d5SAlan Somers void
PurgeCaseFiles()1977a0c41d5SAlan Somers ZfsDaemon::PurgeCaseFiles()
1987a0c41d5SAlan Somers {
1997a0c41d5SAlan Somers 	CaseFile::PurgeAll();
2007a0c41d5SAlan Somers }
2017a0c41d5SAlan Somers 
2027a0c41d5SAlan Somers bool
VdevAddCaseFile(Vdev & vdev,void * cbArg)2037a0c41d5SAlan Somers ZfsDaemon::VdevAddCaseFile(Vdev &vdev, void *cbArg)
2047a0c41d5SAlan Somers {
2057a0c41d5SAlan Somers 	if (vdev.State() != VDEV_STATE_HEALTHY)
2067a0c41d5SAlan Somers 		CaseFile::Create(vdev);
2077a0c41d5SAlan Somers 
2087a0c41d5SAlan Somers 	return (/*break early*/false);
2097a0c41d5SAlan Somers }
2107a0c41d5SAlan Somers 
2117a0c41d5SAlan Somers void
BuildCaseFiles()2127a0c41d5SAlan Somers ZfsDaemon::BuildCaseFiles()
2137a0c41d5SAlan Somers {
2147a0c41d5SAlan Somers 	ZpoolList zpl;
2157a0c41d5SAlan Somers 	ZpoolList::iterator pool;
2167a0c41d5SAlan Somers 
2177a0c41d5SAlan Somers 	/* Add CaseFiles for vdevs with issues. */
2187a0c41d5SAlan Somers 	for (pool = zpl.begin(); pool != zpl.end(); pool++)
2197a0c41d5SAlan Somers 		VdevIterator(*pool).Each(VdevAddCaseFile, NULL);
2207a0c41d5SAlan Somers 
2217a0c41d5SAlan Somers 	/* De-serialize any saved cases. */
2227a0c41d5SAlan Somers 	CaseFile::DeSerialize();
2237a0c41d5SAlan Somers 
2247a0c41d5SAlan Somers 	/* Simulate config_sync events to force CaseFile reevaluation */
2257a0c41d5SAlan Somers 	for (pool = zpl.begin(); pool != zpl.end(); pool++) {
2267a0c41d5SAlan Somers 		char evString[160];
2277a0c41d5SAlan Somers 		Event *event;
2287a0c41d5SAlan Somers 		nvlist_t *config;
2297a0c41d5SAlan Somers 		uint64_t poolGUID;
2307a0c41d5SAlan Somers 		const char *poolname;
2317a0c41d5SAlan Somers 
2327a0c41d5SAlan Somers 		poolname = zpool_get_name(*pool);
2337a0c41d5SAlan Somers 		config = zpool_get_config(*pool, NULL);
2347a0c41d5SAlan Somers 		if (config == NULL) {
2357a0c41d5SAlan Somers 			syslog(LOG_ERR, "ZFSDaemon::BuildCaseFiles: Could not "
2367a0c41d5SAlan Somers 			    "find pool config for pool %s", poolname);
2377a0c41d5SAlan Somers 			continue;
2387a0c41d5SAlan Somers 		}
2397a0c41d5SAlan Somers 		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
2407a0c41d5SAlan Somers 				     &poolGUID) != 0) {
2417a0c41d5SAlan Somers 			syslog(LOG_ERR, "ZFSDaemon::BuildCaseFiles: Could not "
2427a0c41d5SAlan Somers 			    "find pool guid for pool %s", poolname);
2437a0c41d5SAlan Somers 			continue;
2447a0c41d5SAlan Somers 		}
2457a0c41d5SAlan Somers 
2467a0c41d5SAlan Somers 
2477a0c41d5SAlan Somers 		snprintf(evString, 160, "!system=ZFS subsystem=ZFS "
248*92642bbaSAlan Somers 		    "type=sysevent.fs.zfs.config_sync sub_type=synthesized "
2497a0c41d5SAlan Somers 		    "pool_name=%s pool_guid=%" PRIu64 "\n", poolname, poolGUID);
2507a0c41d5SAlan Somers 		event = Event::CreateEvent(GetFactory(), string(evString));
2517a0c41d5SAlan Somers 		if (event != NULL) {
2527a0c41d5SAlan Somers 			event->Process();
2537a0c41d5SAlan Somers 			delete event;
2547a0c41d5SAlan Somers 		}
2557a0c41d5SAlan Somers 	}
2567a0c41d5SAlan Somers }
2577a0c41d5SAlan Somers 
2587a0c41d5SAlan Somers void
RescanSystem()2597a0c41d5SAlan Somers ZfsDaemon::RescanSystem()
2607a0c41d5SAlan Somers {
2617a0c41d5SAlan Somers         struct gmesh	  mesh;
2627a0c41d5SAlan Somers         struct gclass	 *mp;
2637a0c41d5SAlan Somers         struct ggeom	 *gp;
2647a0c41d5SAlan Somers         struct gprovider *pp;
2657a0c41d5SAlan Somers 	int		  result;
2667a0c41d5SAlan Somers 
2677a0c41d5SAlan Somers         /*
2687a0c41d5SAlan Somers 	 * The devdctl system doesn't replay events for new consumers
2697a0c41d5SAlan Somers 	 * of the interface.  Emit manufactured DEVFS arrival events
2707a0c41d5SAlan Somers 	 * for any devices that already before we started or during
2717a0c41d5SAlan Somers 	 * periods where we've lost our connection to devd.
2727a0c41d5SAlan Somers          */
2737a0c41d5SAlan Somers 	result = geom_gettree(&mesh);
2747a0c41d5SAlan Somers 	if (result != 0) {
2757a0c41d5SAlan Somers 		syslog(LOG_ERR, "ZfsDaemon::RescanSystem: "
2764bd5e622SGordon Bergling 		       "geom_gettree failed with error %d\n", result);
2777a0c41d5SAlan Somers 		return;
2787a0c41d5SAlan Somers 	}
2797a0c41d5SAlan Somers 
2807a0c41d5SAlan Somers 	const string evStart("!system=DEVFS subsystem=CDEV type=CREATE "
2817a0c41d5SAlan Somers 			     "sub_type=synthesized cdev=");
2827a0c41d5SAlan Somers         LIST_FOREACH(mp, &mesh.lg_class, lg_class) {
2837a0c41d5SAlan Somers                 LIST_FOREACH(gp, &mp->lg_geom, lg_geom) {
2847a0c41d5SAlan Somers                         LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
2857a0c41d5SAlan Somers 				Event *event;
2867a0c41d5SAlan Somers 
2877a0c41d5SAlan Somers 				string evString(evStart + pp->lg_name + "\n");
2887a0c41d5SAlan Somers 				event = Event::CreateEvent(GetFactory(),
2897a0c41d5SAlan Somers 							   evString);
2907a0c41d5SAlan Somers 				if (event != NULL) {
2917a0c41d5SAlan Somers 					if (event->Process())
2927a0c41d5SAlan Somers 						SaveEvent(*event);
2937a0c41d5SAlan Somers 					delete event;
2947a0c41d5SAlan Somers 				}
2957a0c41d5SAlan Somers                         }
2967a0c41d5SAlan Somers                 }
2977a0c41d5SAlan Somers 	}
2987a0c41d5SAlan Somers 	geom_deletetree(&mesh);
2997a0c41d5SAlan Somers }
3007a0c41d5SAlan Somers 
3017a0c41d5SAlan Somers void
DetectMissedEvents()3027a0c41d5SAlan Somers ZfsDaemon::DetectMissedEvents()
3037a0c41d5SAlan Somers {
3047a0c41d5SAlan Somers 	do {
3057a0c41d5SAlan Somers 		PurgeCaseFiles();
3067a0c41d5SAlan Somers 
3077a0c41d5SAlan Somers 		/*
3087a0c41d5SAlan Somers 		 * Discard any events waiting for us.  We don't know
3097a0c41d5SAlan Somers 		 * if they still apply to the current state of the
3107a0c41d5SAlan Somers 		 * system.
3117a0c41d5SAlan Somers 		 */
3127a0c41d5SAlan Somers 		FlushEvents();
3137a0c41d5SAlan Somers 
3147a0c41d5SAlan Somers 		BuildCaseFiles();
3157a0c41d5SAlan Somers 
3167a0c41d5SAlan Somers 		/*
3177a0c41d5SAlan Somers 		 * If the system state has changed during our
3187a0c41d5SAlan Somers 		 * interrogation, start over.
3197a0c41d5SAlan Somers 		 */
3207a0c41d5SAlan Somers 	} while (s_terminateEventLoop == false && EventsPending());
3217a0c41d5SAlan Somers 
3227a0c41d5SAlan Somers 	RescanSystem();
3237a0c41d5SAlan Somers }
3247a0c41d5SAlan Somers 
3257a0c41d5SAlan Somers void
EventLoop()3267a0c41d5SAlan Somers ZfsDaemon::EventLoop()
3277a0c41d5SAlan Somers {
3287a0c41d5SAlan Somers 	while (s_terminateEventLoop == false) {
3297a0c41d5SAlan Somers 		struct pollfd fds[2];
3307a0c41d5SAlan Somers 		int	      result;
3317a0c41d5SAlan Somers 
3327a0c41d5SAlan Somers 		if (s_logCaseFiles == true) {
3337a0c41d5SAlan Somers 			EventList::iterator event(m_unconsumedEvents.begin());
3347a0c41d5SAlan Somers 			s_logCaseFiles = false;
3357a0c41d5SAlan Somers 			CaseFile::LogAll();
3367a0c41d5SAlan Somers 			while (event != m_unconsumedEvents.end())
3377a0c41d5SAlan Somers 				(*event++)->Log(LOG_INFO);
3387a0c41d5SAlan Somers 		}
3397a0c41d5SAlan Somers 
3407a0c41d5SAlan Somers 		Callout::ExpireCallouts();
3417a0c41d5SAlan Somers 
3427a0c41d5SAlan Somers 		/* Wait for data. */
3437a0c41d5SAlan Somers 		fds[0].fd      = m_devdSockFD;
3447a0c41d5SAlan Somers 		fds[0].events  = POLLIN;
3457a0c41d5SAlan Somers 		fds[0].revents = 0;
3467a0c41d5SAlan Somers 		fds[1].fd      = s_signalPipeFD[0];
3477a0c41d5SAlan Somers 		fds[1].events  = POLLIN;
3487a0c41d5SAlan Somers 		fds[1].revents = 0;
3497a0c41d5SAlan Somers 		result = poll(fds, NUM_ELEMENTS(fds), /*timeout*/INFTIM);
3507a0c41d5SAlan Somers 		if (result == -1) {
3517a0c41d5SAlan Somers 			if (errno == EINTR)
3527a0c41d5SAlan Somers 				continue;
3537a0c41d5SAlan Somers 			else
3547a0c41d5SAlan Somers 				err(1, "Polling for devd events failed");
3557a0c41d5SAlan Somers 		} else if (result == 0) {
3567a0c41d5SAlan Somers 			errx(1, "Unexpected result of 0 from poll. Exiting");
3577a0c41d5SAlan Somers 		}
3587a0c41d5SAlan Somers 
3597a0c41d5SAlan Somers 		if ((fds[0].revents & POLLIN) != 0)
3607a0c41d5SAlan Somers 			ProcessEvents();
3617a0c41d5SAlan Somers 
3627a0c41d5SAlan Somers 		if ((fds[1].revents & POLLIN) != 0) {
3637a0c41d5SAlan Somers 			static char discardBuf[128];
3647a0c41d5SAlan Somers 
3657a0c41d5SAlan Somers 			/*
3667a0c41d5SAlan Somers 			 * This pipe exists just to close the signal
3677a0c41d5SAlan Somers 			 * race.  Its contents are of no interest to
3687a0c41d5SAlan Somers 			 * us, but we must ensure that future signals
3697a0c41d5SAlan Somers 			 * have space in the pipe to write.
3707a0c41d5SAlan Somers 			 */
3717a0c41d5SAlan Somers 			while (read(s_signalPipeFD[0], discardBuf,
3727a0c41d5SAlan Somers 				    sizeof(discardBuf)) > 0)
3737a0c41d5SAlan Somers 				;
3747a0c41d5SAlan Somers 		}
3757a0c41d5SAlan Somers 
3767a0c41d5SAlan Somers 		if (s_systemRescanRequested == true) {
3777a0c41d5SAlan Somers 			s_systemRescanRequested = false;
3787a0c41d5SAlan Somers 			syslog(LOG_INFO, "System Rescan request processed.");
3797a0c41d5SAlan Somers 			RescanSystem();
3807a0c41d5SAlan Somers 		}
3817a0c41d5SAlan Somers 
3827a0c41d5SAlan Somers 		if ((fds[0].revents & POLLERR) != 0) {
3837a0c41d5SAlan Somers 			syslog(LOG_INFO, "POLLERROR detected on devd socket.");
3847a0c41d5SAlan Somers 			break;
3857a0c41d5SAlan Somers 		}
3867a0c41d5SAlan Somers 
3877a0c41d5SAlan Somers 		if ((fds[0].revents & POLLHUP) != 0) {
3887a0c41d5SAlan Somers 			syslog(LOG_INFO, "POLLHUP detected on devd socket.");
3897a0c41d5SAlan Somers 			break;
3907a0c41d5SAlan Somers 		}
3917a0c41d5SAlan Somers 	}
3927a0c41d5SAlan Somers }
3937a0c41d5SAlan Somers //- ZfsDaemon staic Private Methods --------------------------------------------
3947a0c41d5SAlan Somers void
InfoSignalHandler(int)3957a0c41d5SAlan Somers ZfsDaemon::InfoSignalHandler(int)
3967a0c41d5SAlan Somers {
3977a0c41d5SAlan Somers 	s_logCaseFiles = true;
3987a0c41d5SAlan Somers 	ZfsDaemon::WakeEventLoop();
3997a0c41d5SAlan Somers }
4007a0c41d5SAlan Somers 
4017a0c41d5SAlan Somers void
RescanSignalHandler(int)4027a0c41d5SAlan Somers ZfsDaemon::RescanSignalHandler(int)
4037a0c41d5SAlan Somers {
4047a0c41d5SAlan Somers 	RequestSystemRescan();
4057a0c41d5SAlan Somers }
4067a0c41d5SAlan Somers 
4077a0c41d5SAlan Somers void
QuitSignalHandler(int)4087a0c41d5SAlan Somers ZfsDaemon::QuitSignalHandler(int)
4097a0c41d5SAlan Somers {
4107a0c41d5SAlan Somers 	s_terminateEventLoop = true;
4117a0c41d5SAlan Somers 	ZfsDaemon::WakeEventLoop();
4127a0c41d5SAlan Somers }
4137a0c41d5SAlan Somers 
4147a0c41d5SAlan Somers void
OpenPIDFile()4157a0c41d5SAlan Somers ZfsDaemon::OpenPIDFile()
4167a0c41d5SAlan Somers {
4177a0c41d5SAlan Somers 	pid_t otherPID;
4187a0c41d5SAlan Somers 
4197a0c41d5SAlan Somers 	s_pidFH = pidfile_open(s_pidFilePath, 0600, &otherPID);
4207a0c41d5SAlan Somers 	if (s_pidFH == NULL) {
4217a0c41d5SAlan Somers 		if (errno == EEXIST)
4227a0c41d5SAlan Somers 			errx(1, "already running as PID %d. Exiting", otherPID);
4237a0c41d5SAlan Somers 		warn("cannot open PID file");
4247a0c41d5SAlan Somers 	}
4257a0c41d5SAlan Somers }
4267a0c41d5SAlan Somers 
4277a0c41d5SAlan Somers void
UpdatePIDFile()4287a0c41d5SAlan Somers ZfsDaemon::UpdatePIDFile()
4297a0c41d5SAlan Somers {
4307a0c41d5SAlan Somers 	if (s_pidFH != NULL)
4317a0c41d5SAlan Somers 		pidfile_write(s_pidFH);
4327a0c41d5SAlan Somers }
4337a0c41d5SAlan Somers 
4347a0c41d5SAlan Somers void
ClosePIDFile()4357a0c41d5SAlan Somers ZfsDaemon::ClosePIDFile()
4367a0c41d5SAlan Somers {
4377a0c41d5SAlan Somers 	if (s_pidFH != NULL)
43819d04786SAlan Somers 		pidfile_remove(s_pidFH);
4397a0c41d5SAlan Somers }
4407a0c41d5SAlan Somers 
4417a0c41d5SAlan Somers void
InitializeSyslog()4427a0c41d5SAlan Somers ZfsDaemon::InitializeSyslog()
4437a0c41d5SAlan Somers {
4447a0c41d5SAlan Somers 	openlog("zfsd", LOG_NDELAY, LOG_DAEMON);
4457a0c41d5SAlan Somers }
4467a0c41d5SAlan Somers 
447