aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/zed/zed.c29
-rw-r--r--cmd/zed/zed_conf.c7
-rw-r--r--cmd/zed/zed_conf.h1
-rw-r--r--cmd/zed/zed_event.c26
-rw-r--r--cmd/zed/zed_event.h4
-rw-r--r--man/man8/zed.8.in7
6 files changed, 62 insertions, 12 deletions
diff --git a/cmd/zed/zed.c b/cmd/zed/zed.c
index bba8b8f64..0784e3834 100644
--- a/cmd/zed/zed.c
+++ b/cmd/zed/zed.c
@@ -263,18 +263,43 @@ main(int argc, char *argv[])
if (zed_conf_read_state(zcp, &saved_eid, saved_etime) < 0)
exit(EXIT_FAILURE);
- zed_event_init(zcp);
+idle:
+ /*
+ * If -I is specified, attempt to open /dev/zfs repeatedly until
+ * successful.
+ */
+ do {
+ if (!zed_event_init(zcp))
+ break;
+ /* Wait for some time and try again. tunable? */
+ sleep(30);
+ } while (!_got_exit && zcp->do_idle);
+
+ if (_got_exit)
+ goto out;
+
zed_event_seek(zcp, saved_eid, saved_etime);
while (!_got_exit) {
+ int rv;
if (_got_hup) {
_got_hup = 0;
(void) zed_conf_scan_dir(zcp);
}
- zed_event_service(zcp);
+ rv = zed_event_service(zcp);
+
+ /* ENODEV: When kernel module is unloaded (osx) */
+ if (rv == ENODEV)
+ break;
}
+
zed_log_msg(LOG_NOTICE, "Exiting");
zed_event_fini(zcp);
+
+ if (zcp->do_idle && !_got_exit)
+ goto idle;
+
+out:
zed_conf_destroy(zcp);
zed_log_fini();
exit(EXIT_SUCCESS);
diff --git a/cmd/zed/zed_conf.c b/cmd/zed/zed_conf.c
index 86671369c..52370eb87 100644
--- a/cmd/zed/zed_conf.c
+++ b/cmd/zed/zed_conf.c
@@ -153,6 +153,8 @@ _zed_conf_display_help(const char *prog, int got_err)
"Force daemon to run.");
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-F",
"Run daemon in the foreground.");
+ fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-I",
+ "Idle daemon until kernel module is (re)loaded.");
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-M",
"Lock all pages in memory.");
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-P",
@@ -249,7 +251,7 @@ _zed_conf_parse_path(char **resultp, const char *path)
void
zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
{
- const char * const opts = ":hLVc:d:p:P:s:vfFMZ";
+ const char * const opts = ":hLVc:d:p:P:s:vfFMZI";
int opt;
if (!zcp || !argv || !argv[0])
@@ -274,6 +276,9 @@ zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
case 'd':
_zed_conf_parse_path(&zcp->zedlet_dir, optarg);
break;
+ case 'I':
+ zcp->do_idle = 1;
+ break;
case 'p':
_zed_conf_parse_path(&zcp->pid_file, optarg);
break;
diff --git a/cmd/zed/zed_conf.h b/cmd/zed/zed_conf.h
index 7d6b63b1d..424cb2c01 100644
--- a/cmd/zed/zed_conf.h
+++ b/cmd/zed/zed_conf.h
@@ -25,6 +25,7 @@ struct zed_conf {
unsigned do_memlock:1; /* true if locking memory */
unsigned do_verbose:1; /* true if verbosity enabled */
unsigned do_zero:1; /* true if zeroing state */
+ unsigned do_idle:1; /* true if idle enabled */
int syslog_facility; /* syslog facility value */
int min_events; /* RESERVED FOR FUTURE USE */
int max_events; /* RESERVED FOR FUTURE USE */
diff --git a/cmd/zed/zed_event.c b/cmd/zed/zed_event.c
index 197c25386..1c5d00e29 100644
--- a/cmd/zed/zed_event.c
+++ b/cmd/zed/zed_event.c
@@ -41,25 +41,36 @@
/*
* Open the libzfs interface.
*/
-void
+int
zed_event_init(struct zed_conf *zcp)
{
if (!zcp)
zed_log_die("Failed zed_event_init: %s", strerror(EINVAL));
zcp->zfs_hdl = libzfs_init();
- if (!zcp->zfs_hdl)
+ if (!zcp->zfs_hdl) {
+ if (zcp->do_idle)
+ return (-1);
zed_log_die("Failed to initialize libzfs");
+ }
zcp->zevent_fd = open(ZFS_DEV, O_RDWR);
- if (zcp->zevent_fd < 0)
+ if (zcp->zevent_fd < 0) {
+ if (zcp->do_idle)
+ return (-1);
zed_log_die("Failed to open \"%s\": %s",
ZFS_DEV, strerror(errno));
+ }
zfs_agent_init(zcp->zfs_hdl);
- if (zed_disk_event_init() != 0)
+ if (zed_disk_event_init() != 0) {
+ if (zcp->do_idle)
+ return (-1);
zed_log_die("Failed to initialize disk events");
+ }
+
+ return (0);
}
/*
@@ -873,7 +884,7 @@ _zed_event_add_time_strings(uint64_t eid, zed_strings_t *zsp, int64_t etime[])
/*
* Service the next zevent, blocking until one is available.
*/
-void
+int
zed_event_service(struct zed_conf *zcp)
{
nvlist_t *nvl;
@@ -891,13 +902,13 @@ zed_event_service(struct zed_conf *zcp)
errno = EINVAL;
zed_log_msg(LOG_ERR, "Failed to service zevent: %s",
strerror(errno));
- return;
+ return (EINVAL);
}
rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped, ZEVENT_NONE,
zcp->zevent_fd);
if ((rv != 0) || !nvl)
- return;
+ return (errno);
if (n_dropped > 0) {
zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
@@ -950,4 +961,5 @@ zed_event_service(struct zed_conf *zcp)
zed_strings_destroy(zsp);
}
nvlist_free(nvl);
+ return (0);
}
diff --git a/cmd/zed/zed_event.h b/cmd/zed/zed_event.h
index 9f37b80fe..c1455c3a0 100644
--- a/cmd/zed/zed_event.h
+++ b/cmd/zed/zed_event.h
@@ -17,13 +17,13 @@
#include <stdint.h>
-void zed_event_init(struct zed_conf *zcp);
+int zed_event_init(struct zed_conf *zcp);
void zed_event_fini(struct zed_conf *zcp);
int zed_event_seek(struct zed_conf *zcp, uint64_t saved_eid,
int64_t saved_etime[]);
-void zed_event_service(struct zed_conf *zcp);
+int zed_event_service(struct zed_conf *zcp);
#endif /* !ZED_EVENT_H */
diff --git a/man/man8/zed.8.in b/man/man8/zed.8.in
index 2db223a68..2ca393572 100644
--- a/man/man8/zed.8.in
+++ b/man/man8/zed.8.in
@@ -24,6 +24,7 @@ ZED \- ZFS Event Daemon
[\fB\-f\fR]
[\fB\-F\fR]
[\fB\-h\fR]
+[\fB\-I\fR]
[\fB\-L\fR]
[\fB\-M\fR]
[\fB\-p\fR \fIpidfile\fR]
@@ -66,6 +67,12 @@ Lock all current and future pages in the virtual memory address space.
This may help the daemon remain responsive when the system is under heavy
memory pressure.
.TP
+.BI \-I
+Request that the daemon idle rather than exit when the kernel modules are
+not loaded. Processing of events will start, or resume, when the kernel
+modules are (re)loaded. Under Linux the kernel modules cannot be unloaded
+while the daemon is running.
+.TP
.BI \-Z
Zero the daemon's state, thereby allowing zevents still within the kernel
to be reprocessed.