1*7a0c41d5SAlan Somers /*- 2*7a0c41d5SAlan Somers * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Spectra Logic Corporation 3*7a0c41d5SAlan Somers * All rights reserved. 4*7a0c41d5SAlan Somers * 5*7a0c41d5SAlan Somers * Redistribution and use in source and binary forms, with or without 6*7a0c41d5SAlan Somers * modification, are permitted provided that the following conditions 7*7a0c41d5SAlan Somers * are met: 8*7a0c41d5SAlan Somers * 1. Redistributions of source code must retain the above copyright 9*7a0c41d5SAlan Somers * notice, this list of conditions, and the following disclaimer, 10*7a0c41d5SAlan Somers * without modification. 11*7a0c41d5SAlan Somers * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12*7a0c41d5SAlan Somers * substantially similar to the "NO WARRANTY" disclaimer below 13*7a0c41d5SAlan Somers * ("Disclaimer") and any redistribution must be conditioned upon 14*7a0c41d5SAlan Somers * including a substantially similar Disclaimer requirement for further 15*7a0c41d5SAlan Somers * binary redistribution. 16*7a0c41d5SAlan Somers * 17*7a0c41d5SAlan Somers * NO WARRANTY 18*7a0c41d5SAlan Somers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19*7a0c41d5SAlan Somers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20*7a0c41d5SAlan Somers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21*7a0c41d5SAlan Somers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22*7a0c41d5SAlan Somers * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23*7a0c41d5SAlan Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24*7a0c41d5SAlan Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25*7a0c41d5SAlan Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26*7a0c41d5SAlan Somers * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27*7a0c41d5SAlan Somers * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28*7a0c41d5SAlan Somers * POSSIBILITY OF SUCH DAMAGES. 29*7a0c41d5SAlan Somers * 30*7a0c41d5SAlan Somers * Authors: Justin T. Gibbs (Spectra Logic Corporation) 31*7a0c41d5SAlan Somers */ 32*7a0c41d5SAlan Somers 33*7a0c41d5SAlan Somers /** 34*7a0c41d5SAlan Somers * \file zfsd.cc 35*7a0c41d5SAlan Somers * 36*7a0c41d5SAlan Somers * The ZFS daemon consumes kernel devdctl(4) event data via devd(8)'s 37*7a0c41d5SAlan Somers * unix domain socket in order to react to system changes that impact 38*7a0c41d5SAlan Somers * the function of ZFS storage pools. The goal of this daemon is to 39*7a0c41d5SAlan Somers * provide similar functionality to the Solaris ZFS Diagnostic Engine 40*7a0c41d5SAlan Somers * (zfs-diagnosis), the Solaris ZFS fault handler (zfs-retire), and 41*7a0c41d5SAlan Somers * the Solaris ZFS vdev insertion agent (zfs-mod sysevent handler). 42*7a0c41d5SAlan Somers */ 43*7a0c41d5SAlan Somers 44*7a0c41d5SAlan Somers #include <sys/cdefs.h> 45*7a0c41d5SAlan Somers #include <sys/param.h> 46*7a0c41d5SAlan Somers #include <sys/fs/zfs.h> 47*7a0c41d5SAlan Somers 48*7a0c41d5SAlan Somers #include <err.h> 49*7a0c41d5SAlan Somers #include <libgeom.h> 50*7a0c41d5SAlan Somers #include <libutil.h> 51*7a0c41d5SAlan Somers #include <poll.h> 52*7a0c41d5SAlan Somers #include <syslog.h> 53*7a0c41d5SAlan Somers 54*7a0c41d5SAlan Somers #include <libzfs.h> 55*7a0c41d5SAlan Somers 56*7a0c41d5SAlan Somers #include <list> 57*7a0c41d5SAlan Somers #include <map> 58*7a0c41d5SAlan Somers #include <string> 59*7a0c41d5SAlan Somers 60*7a0c41d5SAlan Somers #include <devdctl/guid.h> 61*7a0c41d5SAlan Somers #include <devdctl/event.h> 62*7a0c41d5SAlan Somers #include <devdctl/event_factory.h> 63*7a0c41d5SAlan Somers #include <devdctl/exception.h> 64*7a0c41d5SAlan Somers #include <devdctl/consumer.h> 65*7a0c41d5SAlan Somers 66*7a0c41d5SAlan Somers #include "callout.h" 67*7a0c41d5SAlan Somers #include "vdev_iterator.h" 68*7a0c41d5SAlan Somers #include "zfsd_event.h" 69*7a0c41d5SAlan Somers #include "case_file.h" 70*7a0c41d5SAlan Somers #include "vdev.h" 71*7a0c41d5SAlan Somers #include "vdev_iterator.h" 72*7a0c41d5SAlan Somers #include "zfsd.h" 73*7a0c41d5SAlan Somers #include "zfsd_exception.h" 74*7a0c41d5SAlan Somers #include "zpool_list.h" 75*7a0c41d5SAlan Somers 76*7a0c41d5SAlan Somers __FBSDID("$FreeBSD$"); 77*7a0c41d5SAlan Somers 78*7a0c41d5SAlan Somers /*================================== Macros ==================================*/ 79*7a0c41d5SAlan Somers #define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) 80*7a0c41d5SAlan Somers 81*7a0c41d5SAlan Somers /*============================ Namespace Control =============================*/ 82*7a0c41d5SAlan Somers using DevdCtl::Event; 83*7a0c41d5SAlan Somers using DevdCtl::EventFactory; 84*7a0c41d5SAlan Somers using DevdCtl::EventList; 85*7a0c41d5SAlan Somers 86*7a0c41d5SAlan Somers /*================================ Global Data ===============================*/ 87*7a0c41d5SAlan Somers int g_debug = 0; 88*7a0c41d5SAlan Somers libzfs_handle_t *g_zfsHandle; 89*7a0c41d5SAlan Somers 90*7a0c41d5SAlan Somers /*--------------------------------- ZfsDaemon --------------------------------*/ 91*7a0c41d5SAlan Somers //- ZfsDaemon Static Private Data ---------------------------------------------- 92*7a0c41d5SAlan Somers ZfsDaemon *ZfsDaemon::s_theZfsDaemon; 93*7a0c41d5SAlan Somers bool ZfsDaemon::s_logCaseFiles; 94*7a0c41d5SAlan Somers bool ZfsDaemon::s_terminateEventLoop; 95*7a0c41d5SAlan Somers char ZfsDaemon::s_pidFilePath[] = "/var/run/zfsd.pid"; 96*7a0c41d5SAlan Somers pidfh *ZfsDaemon::s_pidFH; 97*7a0c41d5SAlan Somers int ZfsDaemon::s_signalPipeFD[2]; 98*7a0c41d5SAlan Somers bool ZfsDaemon::s_systemRescanRequested(false); 99*7a0c41d5SAlan Somers EventFactory::Record ZfsDaemon::s_registryEntries[] = 100*7a0c41d5SAlan Somers { 101*7a0c41d5SAlan Somers { Event::NOTIFY, "DEVFS", &DevfsEvent::Builder }, 102*7a0c41d5SAlan Somers { Event::NOTIFY, "GEOM", &GeomEvent::Builder }, 103*7a0c41d5SAlan Somers { Event::NOTIFY, "ZFS", &ZfsEvent::Builder } 104*7a0c41d5SAlan Somers }; 105*7a0c41d5SAlan Somers 106*7a0c41d5SAlan Somers //- ZfsDaemon Static Public Methods -------------------------------------------- 107*7a0c41d5SAlan Somers ZfsDaemon & 108*7a0c41d5SAlan Somers ZfsDaemon::Get() 109*7a0c41d5SAlan Somers { 110*7a0c41d5SAlan Somers return (*s_theZfsDaemon); 111*7a0c41d5SAlan Somers } 112*7a0c41d5SAlan Somers 113*7a0c41d5SAlan Somers void 114*7a0c41d5SAlan Somers ZfsDaemon::WakeEventLoop() 115*7a0c41d5SAlan Somers { 116*7a0c41d5SAlan Somers write(s_signalPipeFD[1], "+", 1); 117*7a0c41d5SAlan Somers } 118*7a0c41d5SAlan Somers 119*7a0c41d5SAlan Somers void 120*7a0c41d5SAlan Somers ZfsDaemon::RequestSystemRescan() 121*7a0c41d5SAlan Somers { 122*7a0c41d5SAlan Somers s_systemRescanRequested = true; 123*7a0c41d5SAlan Somers ZfsDaemon::WakeEventLoop(); 124*7a0c41d5SAlan Somers } 125*7a0c41d5SAlan Somers 126*7a0c41d5SAlan Somers void 127*7a0c41d5SAlan Somers ZfsDaemon::Run() 128*7a0c41d5SAlan Somers { 129*7a0c41d5SAlan Somers ZfsDaemon daemon; 130*7a0c41d5SAlan Somers 131*7a0c41d5SAlan Somers while (s_terminateEventLoop == false) { 132*7a0c41d5SAlan Somers 133*7a0c41d5SAlan Somers try { 134*7a0c41d5SAlan Somers daemon.DisconnectFromDevd(); 135*7a0c41d5SAlan Somers 136*7a0c41d5SAlan Somers if (daemon.ConnectToDevd() == false) { 137*7a0c41d5SAlan Somers sleep(30); 138*7a0c41d5SAlan Somers continue; 139*7a0c41d5SAlan Somers } 140*7a0c41d5SAlan Somers 141*7a0c41d5SAlan Somers daemon.DetectMissedEvents(); 142*7a0c41d5SAlan Somers 143*7a0c41d5SAlan Somers daemon.EventLoop(); 144*7a0c41d5SAlan Somers 145*7a0c41d5SAlan Somers } catch (const DevdCtl::Exception &exp) { 146*7a0c41d5SAlan Somers exp.Log(); 147*7a0c41d5SAlan Somers } 148*7a0c41d5SAlan Somers } 149*7a0c41d5SAlan Somers 150*7a0c41d5SAlan Somers daemon.DisconnectFromDevd(); 151*7a0c41d5SAlan Somers } 152*7a0c41d5SAlan Somers 153*7a0c41d5SAlan Somers //- ZfsDaemon Private Methods -------------------------------------------------- 154*7a0c41d5SAlan Somers ZfsDaemon::ZfsDaemon() 155*7a0c41d5SAlan Somers : Consumer(/*defBuilder*/NULL, s_registryEntries, 156*7a0c41d5SAlan Somers NUM_ELEMENTS(s_registryEntries)) 157*7a0c41d5SAlan Somers { 158*7a0c41d5SAlan Somers if (s_theZfsDaemon != NULL) 159*7a0c41d5SAlan Somers errx(1, "Multiple ZfsDaemon instances created. Exiting"); 160*7a0c41d5SAlan Somers 161*7a0c41d5SAlan Somers s_theZfsDaemon = this; 162*7a0c41d5SAlan Somers 163*7a0c41d5SAlan Somers if (pipe(s_signalPipeFD) != 0) 164*7a0c41d5SAlan Somers errx(1, "Unable to allocate signal pipe. Exiting"); 165*7a0c41d5SAlan Somers 166*7a0c41d5SAlan Somers if (fcntl(s_signalPipeFD[0], F_SETFL, O_NONBLOCK) == -1) 167*7a0c41d5SAlan Somers errx(1, "Unable to set pipe as non-blocking. Exiting"); 168*7a0c41d5SAlan Somers 169*7a0c41d5SAlan Somers if (fcntl(s_signalPipeFD[1], F_SETFL, O_NONBLOCK) == -1) 170*7a0c41d5SAlan Somers errx(1, "Unable to set pipe as non-blocking. Exiting"); 171*7a0c41d5SAlan Somers 172*7a0c41d5SAlan Somers signal(SIGHUP, ZfsDaemon::RescanSignalHandler); 173*7a0c41d5SAlan Somers signal(SIGINFO, ZfsDaemon::InfoSignalHandler); 174*7a0c41d5SAlan Somers signal(SIGINT, ZfsDaemon::QuitSignalHandler); 175*7a0c41d5SAlan Somers signal(SIGTERM, ZfsDaemon::QuitSignalHandler); 176*7a0c41d5SAlan Somers signal(SIGUSR1, ZfsDaemon::RescanSignalHandler); 177*7a0c41d5SAlan Somers 178*7a0c41d5SAlan Somers g_zfsHandle = libzfs_init(); 179*7a0c41d5SAlan Somers if (g_zfsHandle == NULL) 180*7a0c41d5SAlan Somers errx(1, "Unable to initialize ZFS library. Exiting"); 181*7a0c41d5SAlan Somers 182*7a0c41d5SAlan Somers Callout::Init(); 183*7a0c41d5SAlan Somers InitializeSyslog(); 184*7a0c41d5SAlan Somers OpenPIDFile(); 185*7a0c41d5SAlan Somers 186*7a0c41d5SAlan Somers if (g_debug == 0) 187*7a0c41d5SAlan Somers daemon(0, 0); 188*7a0c41d5SAlan Somers 189*7a0c41d5SAlan Somers UpdatePIDFile(); 190*7a0c41d5SAlan Somers } 191*7a0c41d5SAlan Somers 192*7a0c41d5SAlan Somers ZfsDaemon::~ZfsDaemon() 193*7a0c41d5SAlan Somers { 194*7a0c41d5SAlan Somers PurgeCaseFiles(); 195*7a0c41d5SAlan Somers ClosePIDFile(); 196*7a0c41d5SAlan Somers } 197*7a0c41d5SAlan Somers 198*7a0c41d5SAlan Somers void 199*7a0c41d5SAlan Somers ZfsDaemon::PurgeCaseFiles() 200*7a0c41d5SAlan Somers { 201*7a0c41d5SAlan Somers CaseFile::PurgeAll(); 202*7a0c41d5SAlan Somers } 203*7a0c41d5SAlan Somers 204*7a0c41d5SAlan Somers bool 205*7a0c41d5SAlan Somers ZfsDaemon::VdevAddCaseFile(Vdev &vdev, void *cbArg) 206*7a0c41d5SAlan Somers { 207*7a0c41d5SAlan Somers if (vdev.State() != VDEV_STATE_HEALTHY) 208*7a0c41d5SAlan Somers CaseFile::Create(vdev); 209*7a0c41d5SAlan Somers 210*7a0c41d5SAlan Somers return (/*break early*/false); 211*7a0c41d5SAlan Somers } 212*7a0c41d5SAlan Somers 213*7a0c41d5SAlan Somers void 214*7a0c41d5SAlan Somers ZfsDaemon::BuildCaseFiles() 215*7a0c41d5SAlan Somers { 216*7a0c41d5SAlan Somers ZpoolList zpl; 217*7a0c41d5SAlan Somers ZpoolList::iterator pool; 218*7a0c41d5SAlan Somers 219*7a0c41d5SAlan Somers /* Add CaseFiles for vdevs with issues. */ 220*7a0c41d5SAlan Somers for (pool = zpl.begin(); pool != zpl.end(); pool++) 221*7a0c41d5SAlan Somers VdevIterator(*pool).Each(VdevAddCaseFile, NULL); 222*7a0c41d5SAlan Somers 223*7a0c41d5SAlan Somers /* De-serialize any saved cases. */ 224*7a0c41d5SAlan Somers CaseFile::DeSerialize(); 225*7a0c41d5SAlan Somers 226*7a0c41d5SAlan Somers /* Simulate config_sync events to force CaseFile reevaluation */ 227*7a0c41d5SAlan Somers for (pool = zpl.begin(); pool != zpl.end(); pool++) { 228*7a0c41d5SAlan Somers char evString[160]; 229*7a0c41d5SAlan Somers Event *event; 230*7a0c41d5SAlan Somers nvlist_t *config; 231*7a0c41d5SAlan Somers uint64_t poolGUID; 232*7a0c41d5SAlan Somers const char *poolname; 233*7a0c41d5SAlan Somers 234*7a0c41d5SAlan Somers poolname = zpool_get_name(*pool); 235*7a0c41d5SAlan Somers config = zpool_get_config(*pool, NULL); 236*7a0c41d5SAlan Somers if (config == NULL) { 237*7a0c41d5SAlan Somers syslog(LOG_ERR, "ZFSDaemon::BuildCaseFiles: Could not " 238*7a0c41d5SAlan Somers "find pool config for pool %s", poolname); 239*7a0c41d5SAlan Somers continue; 240*7a0c41d5SAlan Somers } 241*7a0c41d5SAlan Somers if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 242*7a0c41d5SAlan Somers &poolGUID) != 0) { 243*7a0c41d5SAlan Somers syslog(LOG_ERR, "ZFSDaemon::BuildCaseFiles: Could not " 244*7a0c41d5SAlan Somers "find pool guid for pool %s", poolname); 245*7a0c41d5SAlan Somers continue; 246*7a0c41d5SAlan Somers } 247*7a0c41d5SAlan Somers 248*7a0c41d5SAlan Somers 249*7a0c41d5SAlan Somers snprintf(evString, 160, "!system=ZFS subsystem=ZFS " 250*7a0c41d5SAlan Somers "type=misc.fs.zfs.config_sync sub_type=synthesized " 251*7a0c41d5SAlan Somers "pool_name=%s pool_guid=%" PRIu64 "\n", poolname, poolGUID); 252*7a0c41d5SAlan Somers event = Event::CreateEvent(GetFactory(), string(evString)); 253*7a0c41d5SAlan Somers if (event != NULL) { 254*7a0c41d5SAlan Somers event->Process(); 255*7a0c41d5SAlan Somers delete event; 256*7a0c41d5SAlan Somers } 257*7a0c41d5SAlan Somers } 258*7a0c41d5SAlan Somers } 259*7a0c41d5SAlan Somers 260*7a0c41d5SAlan Somers void 261*7a0c41d5SAlan Somers ZfsDaemon::RescanSystem() 262*7a0c41d5SAlan Somers { 263*7a0c41d5SAlan Somers struct gmesh mesh; 264*7a0c41d5SAlan Somers struct gclass *mp; 265*7a0c41d5SAlan Somers struct ggeom *gp; 266*7a0c41d5SAlan Somers struct gprovider *pp; 267*7a0c41d5SAlan Somers int result; 268*7a0c41d5SAlan Somers 269*7a0c41d5SAlan Somers /* 270*7a0c41d5SAlan Somers * The devdctl system doesn't replay events for new consumers 271*7a0c41d5SAlan Somers * of the interface. Emit manufactured DEVFS arrival events 272*7a0c41d5SAlan Somers * for any devices that already before we started or during 273*7a0c41d5SAlan Somers * periods where we've lost our connection to devd. 274*7a0c41d5SAlan Somers */ 275*7a0c41d5SAlan Somers result = geom_gettree(&mesh); 276*7a0c41d5SAlan Somers if (result != 0) { 277*7a0c41d5SAlan Somers syslog(LOG_ERR, "ZfsDaemon::RescanSystem: " 278*7a0c41d5SAlan Somers "geom_gettree faild with error %d\n", result); 279*7a0c41d5SAlan Somers return; 280*7a0c41d5SAlan Somers } 281*7a0c41d5SAlan Somers 282*7a0c41d5SAlan Somers const string evStart("!system=DEVFS subsystem=CDEV type=CREATE " 283*7a0c41d5SAlan Somers "sub_type=synthesized cdev="); 284*7a0c41d5SAlan Somers LIST_FOREACH(mp, &mesh.lg_class, lg_class) { 285*7a0c41d5SAlan Somers LIST_FOREACH(gp, &mp->lg_geom, lg_geom) { 286*7a0c41d5SAlan Somers LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { 287*7a0c41d5SAlan Somers Event *event; 288*7a0c41d5SAlan Somers 289*7a0c41d5SAlan Somers string evString(evStart + pp->lg_name + "\n"); 290*7a0c41d5SAlan Somers event = Event::CreateEvent(GetFactory(), 291*7a0c41d5SAlan Somers evString); 292*7a0c41d5SAlan Somers if (event != NULL) { 293*7a0c41d5SAlan Somers if (event->Process()) 294*7a0c41d5SAlan Somers SaveEvent(*event); 295*7a0c41d5SAlan Somers delete event; 296*7a0c41d5SAlan Somers } 297*7a0c41d5SAlan Somers } 298*7a0c41d5SAlan Somers } 299*7a0c41d5SAlan Somers } 300*7a0c41d5SAlan Somers geom_deletetree(&mesh); 301*7a0c41d5SAlan Somers } 302*7a0c41d5SAlan Somers 303*7a0c41d5SAlan Somers void 304*7a0c41d5SAlan Somers ZfsDaemon::DetectMissedEvents() 305*7a0c41d5SAlan Somers { 306*7a0c41d5SAlan Somers do { 307*7a0c41d5SAlan Somers PurgeCaseFiles(); 308*7a0c41d5SAlan Somers 309*7a0c41d5SAlan Somers /* 310*7a0c41d5SAlan Somers * Discard any events waiting for us. We don't know 311*7a0c41d5SAlan Somers * if they still apply to the current state of the 312*7a0c41d5SAlan Somers * system. 313*7a0c41d5SAlan Somers */ 314*7a0c41d5SAlan Somers FlushEvents(); 315*7a0c41d5SAlan Somers 316*7a0c41d5SAlan Somers BuildCaseFiles(); 317*7a0c41d5SAlan Somers 318*7a0c41d5SAlan Somers /* 319*7a0c41d5SAlan Somers * If the system state has changed during our 320*7a0c41d5SAlan Somers * interrogation, start over. 321*7a0c41d5SAlan Somers */ 322*7a0c41d5SAlan Somers } while (s_terminateEventLoop == false && EventsPending()); 323*7a0c41d5SAlan Somers 324*7a0c41d5SAlan Somers RescanSystem(); 325*7a0c41d5SAlan Somers } 326*7a0c41d5SAlan Somers 327*7a0c41d5SAlan Somers void 328*7a0c41d5SAlan Somers ZfsDaemon::EventLoop() 329*7a0c41d5SAlan Somers { 330*7a0c41d5SAlan Somers while (s_terminateEventLoop == false) { 331*7a0c41d5SAlan Somers struct pollfd fds[2]; 332*7a0c41d5SAlan Somers int result; 333*7a0c41d5SAlan Somers 334*7a0c41d5SAlan Somers if (s_logCaseFiles == true) { 335*7a0c41d5SAlan Somers EventList::iterator event(m_unconsumedEvents.begin()); 336*7a0c41d5SAlan Somers s_logCaseFiles = false; 337*7a0c41d5SAlan Somers CaseFile::LogAll(); 338*7a0c41d5SAlan Somers while (event != m_unconsumedEvents.end()) 339*7a0c41d5SAlan Somers (*event++)->Log(LOG_INFO); 340*7a0c41d5SAlan Somers } 341*7a0c41d5SAlan Somers 342*7a0c41d5SAlan Somers Callout::ExpireCallouts(); 343*7a0c41d5SAlan Somers 344*7a0c41d5SAlan Somers /* Wait for data. */ 345*7a0c41d5SAlan Somers fds[0].fd = m_devdSockFD; 346*7a0c41d5SAlan Somers fds[0].events = POLLIN; 347*7a0c41d5SAlan Somers fds[0].revents = 0; 348*7a0c41d5SAlan Somers fds[1].fd = s_signalPipeFD[0]; 349*7a0c41d5SAlan Somers fds[1].events = POLLIN; 350*7a0c41d5SAlan Somers fds[1].revents = 0; 351*7a0c41d5SAlan Somers result = poll(fds, NUM_ELEMENTS(fds), /*timeout*/INFTIM); 352*7a0c41d5SAlan Somers if (result == -1) { 353*7a0c41d5SAlan Somers if (errno == EINTR) 354*7a0c41d5SAlan Somers continue; 355*7a0c41d5SAlan Somers else 356*7a0c41d5SAlan Somers err(1, "Polling for devd events failed"); 357*7a0c41d5SAlan Somers } else if (result == 0) { 358*7a0c41d5SAlan Somers errx(1, "Unexpected result of 0 from poll. Exiting"); 359*7a0c41d5SAlan Somers } 360*7a0c41d5SAlan Somers 361*7a0c41d5SAlan Somers if ((fds[0].revents & POLLIN) != 0) 362*7a0c41d5SAlan Somers ProcessEvents(); 363*7a0c41d5SAlan Somers 364*7a0c41d5SAlan Somers if ((fds[1].revents & POLLIN) != 0) { 365*7a0c41d5SAlan Somers static char discardBuf[128]; 366*7a0c41d5SAlan Somers 367*7a0c41d5SAlan Somers /* 368*7a0c41d5SAlan Somers * This pipe exists just to close the signal 369*7a0c41d5SAlan Somers * race. Its contents are of no interest to 370*7a0c41d5SAlan Somers * us, but we must ensure that future signals 371*7a0c41d5SAlan Somers * have space in the pipe to write. 372*7a0c41d5SAlan Somers */ 373*7a0c41d5SAlan Somers while (read(s_signalPipeFD[0], discardBuf, 374*7a0c41d5SAlan Somers sizeof(discardBuf)) > 0) 375*7a0c41d5SAlan Somers ; 376*7a0c41d5SAlan Somers } 377*7a0c41d5SAlan Somers 378*7a0c41d5SAlan Somers if (s_systemRescanRequested == true) { 379*7a0c41d5SAlan Somers s_systemRescanRequested = false; 380*7a0c41d5SAlan Somers syslog(LOG_INFO, "System Rescan request processed."); 381*7a0c41d5SAlan Somers RescanSystem(); 382*7a0c41d5SAlan Somers } 383*7a0c41d5SAlan Somers 384*7a0c41d5SAlan Somers if ((fds[0].revents & POLLERR) != 0) { 385*7a0c41d5SAlan Somers syslog(LOG_INFO, "POLLERROR detected on devd socket."); 386*7a0c41d5SAlan Somers break; 387*7a0c41d5SAlan Somers } 388*7a0c41d5SAlan Somers 389*7a0c41d5SAlan Somers if ((fds[0].revents & POLLHUP) != 0) { 390*7a0c41d5SAlan Somers syslog(LOG_INFO, "POLLHUP detected on devd socket."); 391*7a0c41d5SAlan Somers break; 392*7a0c41d5SAlan Somers } 393*7a0c41d5SAlan Somers } 394*7a0c41d5SAlan Somers } 395*7a0c41d5SAlan Somers //- ZfsDaemon staic Private Methods -------------------------------------------- 396*7a0c41d5SAlan Somers void 397*7a0c41d5SAlan Somers ZfsDaemon::InfoSignalHandler(int) 398*7a0c41d5SAlan Somers { 399*7a0c41d5SAlan Somers s_logCaseFiles = true; 400*7a0c41d5SAlan Somers ZfsDaemon::WakeEventLoop(); 401*7a0c41d5SAlan Somers } 402*7a0c41d5SAlan Somers 403*7a0c41d5SAlan Somers void 404*7a0c41d5SAlan Somers ZfsDaemon::RescanSignalHandler(int) 405*7a0c41d5SAlan Somers { 406*7a0c41d5SAlan Somers RequestSystemRescan(); 407*7a0c41d5SAlan Somers } 408*7a0c41d5SAlan Somers 409*7a0c41d5SAlan Somers void 410*7a0c41d5SAlan Somers ZfsDaemon::QuitSignalHandler(int) 411*7a0c41d5SAlan Somers { 412*7a0c41d5SAlan Somers s_terminateEventLoop = true; 413*7a0c41d5SAlan Somers ZfsDaemon::WakeEventLoop(); 414*7a0c41d5SAlan Somers } 415*7a0c41d5SAlan Somers 416*7a0c41d5SAlan Somers void 417*7a0c41d5SAlan Somers ZfsDaemon::OpenPIDFile() 418*7a0c41d5SAlan Somers { 419*7a0c41d5SAlan Somers pid_t otherPID; 420*7a0c41d5SAlan Somers 421*7a0c41d5SAlan Somers s_pidFH = pidfile_open(s_pidFilePath, 0600, &otherPID); 422*7a0c41d5SAlan Somers if (s_pidFH == NULL) { 423*7a0c41d5SAlan Somers if (errno == EEXIST) 424*7a0c41d5SAlan Somers errx(1, "already running as PID %d. Exiting", otherPID); 425*7a0c41d5SAlan Somers warn("cannot open PID file"); 426*7a0c41d5SAlan Somers } 427*7a0c41d5SAlan Somers } 428*7a0c41d5SAlan Somers 429*7a0c41d5SAlan Somers void 430*7a0c41d5SAlan Somers ZfsDaemon::UpdatePIDFile() 431*7a0c41d5SAlan Somers { 432*7a0c41d5SAlan Somers if (s_pidFH != NULL) 433*7a0c41d5SAlan Somers pidfile_write(s_pidFH); 434*7a0c41d5SAlan Somers } 435*7a0c41d5SAlan Somers 436*7a0c41d5SAlan Somers void 437*7a0c41d5SAlan Somers ZfsDaemon::ClosePIDFile() 438*7a0c41d5SAlan Somers { 439*7a0c41d5SAlan Somers if (s_pidFH != NULL) 440*7a0c41d5SAlan Somers pidfile_close(s_pidFH); 441*7a0c41d5SAlan Somers } 442*7a0c41d5SAlan Somers 443*7a0c41d5SAlan Somers void 444*7a0c41d5SAlan Somers ZfsDaemon::InitializeSyslog() 445*7a0c41d5SAlan Somers { 446*7a0c41d5SAlan Somers openlog("zfsd", LOG_NDELAY, LOG_DAEMON); 447*7a0c41d5SAlan Somers } 448*7a0c41d5SAlan Somers 449