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