From 1e70dee6d903370e82f8c7413f037532ce916c9b Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Fri, 2 Dec 2005 15:39:16 +0000 Subject: [PATCH] dmeventd updates --- Makefile.in | 5 +- configure | 17 +- configure.in | 11 +- dmeventd/.exported_symbols | 8 +- dmeventd/Makefile.in | 51 +- dmeventd/dmeventd.c | 825 +++++++++++------- {lib/event => dmeventd}/dmeventd.h | 0 .../libdevmapper-event.c | 99 ++- dmeventd/libdevmapper-event.h | 99 +++ dmeventd/old/.exported_symbols | 3 + dmeventd/old/Makefile.in | 51 ++ dmeventd/{ => old}/dmevent.c | 0 {lib/event => dmeventd/old}/dmeventd.c | 767 ++++++---------- dmeventd/{ => old}/mktestdevices | 0 dmeventd/{ => old}/noop.c | 0 dmeventd/old/noop.d | 1 + include/.symlinks | 2 +- lib/Makefile.in | 8 - lib/event/Makefile.in | 56 -- lib/libdm-event.h | 95 -- 20 files changed, 1054 insertions(+), 1044 deletions(-) rename {lib/event => dmeventd}/dmeventd.h (100%) rename lib/event/libdm-event.c => dmeventd/libdevmapper-event.c (78%) create mode 100644 dmeventd/libdevmapper-event.h create mode 100644 dmeventd/old/.exported_symbols create mode 100644 dmeventd/old/Makefile.in rename dmeventd/{ => old}/dmevent.c (100%) rename {lib/event => dmeventd/old}/dmeventd.c (58%) rename dmeventd/{ => old}/mktestdevices (100%) rename dmeventd/{ => old}/noop.c (100%) create mode 100644 dmeventd/old/noop.d delete mode 100644 lib/event/Makefile.in delete mode 100644 lib/libdm-event.h diff --git a/Makefile.in b/Makefile.in index b904777..d383281 100644 --- a/Makefile.in +++ b/Makefile.in @@ -25,7 +25,7 @@ ifeq ("@INTL@", "yes") endif ifeq ("@DMEVENTD@", "yes") - SUBDIRS += multilog dmeventd + SUBDIRS += dmeventd endif SUBDIRS += lib dmsetup @@ -42,7 +42,8 @@ include make.tmpl lib: include dmsetup: lib -dmeventd: lib multilog +# dmeventd: lib multilog +dmeventd: lib po: dmsetup dmeventd ifeq ("@INTL@", "yes") diff --git a/configure b/configure index 3ca2008..4461d1e 100755 --- a/configure +++ b/configure @@ -850,7 +850,7 @@ Optional Features: --enable-debug Enable debugging --enable-compat Enable support for old device-mapper versions --disable-driver Disable calls to device-mapper in the kernel - --enable-eventd Build the new event daemon + --enable-dmeventd Build the new event daemon --enable-static_link Use this to link the tools to their libraries statically. Default is dynamic linking --disable-selinux Disable selinux support @@ -5329,9 +5329,9 @@ if test "${enable_ioctl+set}" = set; then fi; ################################################################################ -# Check whether --enable-eventd or --disable-eventd was given. -if test "${enable_eventd+set}" = set; then - enableval="$enable_eventd" +# Check whether --enable-dmeventd or --disable-dmeventd was given. +if test "${enable_dmeventd+set}" = set; then + enableval="$enable_dmeventd" DMEVENTD=$enableval else DMEVENTD=no @@ -5810,7 +5810,7 @@ fi ################################################################################ - ac_config_files="$ac_config_files Makefile make.tmpl include/Makefile dmeventd/Makefile dmsetup/Makefile lib/Makefile lib/event/Makefile lib/libdm-common.h kernel/Makefile man/Makefile multilog/Makefile multilog/async/Makefile multilog/pthread_lock/Makefile multilog/tests/Makefile po/Makefile" + ac_config_files="$ac_config_files Makefile make.tmpl include/Makefile dmsetup/Makefile lib/Makefile lib/libdm-common.h dmeventd/Makefile kernel/Makefile man/Makefile po/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -6365,17 +6365,12 @@ do "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "make.tmpl" ) CONFIG_FILES="$CONFIG_FILES make.tmpl" ;; "include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; - "dmeventd/Makefile" ) CONFIG_FILES="$CONFIG_FILES dmeventd/Makefile" ;; "dmsetup/Makefile" ) CONFIG_FILES="$CONFIG_FILES dmsetup/Makefile" ;; "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; - "lib/event/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/event/Makefile" ;; "lib/libdm-common.h" ) CONFIG_FILES="$CONFIG_FILES lib/libdm-common.h" ;; + "dmeventd/Makefile" ) CONFIG_FILES="$CONFIG_FILES dmeventd/Makefile" ;; "kernel/Makefile" ) CONFIG_FILES="$CONFIG_FILES kernel/Makefile" ;; "man/Makefile" ) CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; - "multilog/Makefile" ) CONFIG_FILES="$CONFIG_FILES multilog/Makefile" ;; - "multilog/async/Makefile" ) CONFIG_FILES="$CONFIG_FILES multilog/async/Makefile" ;; - "multilog/pthread_lock/Makefile" ) CONFIG_FILES="$CONFIG_FILES multilog/pthread_lock/Makefile" ;; - "multilog/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES multilog/tests/Makefile" ;; "po/Makefile" ) CONFIG_FILES="$CONFIG_FILES po/Makefile" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} diff --git a/configure.in b/configure.in index 9a8c23d..0ccf78c 100644 --- a/configure.in +++ b/configure.in @@ -176,8 +176,8 @@ AC_ARG_ENABLE(ioctl, [ --disable-driver Disable calls to device-mapper DMIOCTLS=$enableval) ################################################################################ -dnl -- Enable eventd -AC_ARG_ENABLE(eventd, [ --enable-eventd Build the new event daemon], +dnl -- Enable dmeventd +AC_ARG_ENABLE(dmeventd, [ --enable-dmeventd Build the new event daemon], DMEVENTD=$enableval, DMEVENTD=no) ################################################################################ @@ -364,17 +364,12 @@ AC_OUTPUT( \ Makefile \ make.tmpl \ include/Makefile \ -dmeventd/Makefile \ dmsetup/Makefile \ lib/Makefile \ -lib/event/Makefile \ lib/libdm-common.h \ +dmeventd/Makefile \ kernel/Makefile \ man/Makefile \ -multilog/Makefile \ -multilog/async/Makefile \ -multilog/pthread_lock/Makefile \ -multilog/tests/Makefile \ po/Makefile \ ) diff --git a/dmeventd/.exported_symbols b/dmeventd/.exported_symbols index 4854e98..7847409 100644 --- a/dmeventd/.exported_symbols +++ b/dmeventd/.exported_symbols @@ -1,3 +1,5 @@ -process_event -register_device -unregister_device \ No newline at end of file +dm_register_for_event +dm_unregister_for_event +dm_get_registered_device +dm_set_event_timeout +dm_get_event_timeout diff --git a/dmeventd/Makefile.in b/dmeventd/Makefile.in index 394f61e..369f5e2 100644 --- a/dmeventd/Makefile.in +++ b/dmeventd/Makefile.in @@ -1,51 +1,56 @@ # -# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. -# Copyright (C) 2004 Red Hat, Inc. All rights reserved. +# Copyright (C) 2005 Red Hat, Inc. All rights reserved. # # This file is part of the device-mapper userspace tools. # # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions -# of the GNU General Public License v.2. +# of the GNU Lesser General Public License v.2.1. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ +interface = @interface@ -TARGETS = dmevent dmeventd -INSTALL_TYPE = install_dynamic +SOURCES = libdevmapper-event.c \ + dmeventd.c -SOURCES = noop.c -CLEAN_TARGETS = dmevent.o dmeventd.o +LIB_STATIC = libdevmapper-event.a ifeq ("@LIB_SUFFIX@","dylib") - LIB_SHARED = libdmeventdnoop.dylib + LIB_SHARED = libdevmapper-event.dylib else - LIB_SHARED = libdmeventdnoop.so + LIB_SHARED = libdevmapper-event.so endif - -LDFLAGS += -ldl -ldevmapper -lmultilog + +CLDFLAGS += -ldl -ldevmapper -lpthread include ../make.tmpl -libdmeventdnoop.so: noop.o +.PHONY: install_dynamic install_static -dmevent: dmevent.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX) - $(CC) -o $@ dmevent.o $(LDFLAGS) \ - -L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog $(LIBS) +INSTALL_TYPE = install_dynamic -dmeventd: dmeventd.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX) - $(CC) -o $@ dmeventd.o $(LDFLAGS) \ - -L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog -lpthread -ldmevent $(LIBS) +ifeq ("@STATIC_LINK@", "yes") + INSTALL_TYPE += install_static +endif install: $(INSTALL_TYPE) -.PHONY: install_dynamic - -install_dynamic: dmeventd - $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) dmeventd $(sbindir)/dmeventd +install_dynamic: libdevmapper-event.$(LIB_SUFFIX) + $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \ + $(libdir)/libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) + $(LN_S) -f libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) \ + $(libdir)/libdevmapper-event.$(LIB_SUFFIX) + $(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.h \ + $(includedir)/libdevmapper-event.h + +install_static: libdevmapper-event.a + $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \ + $(libdir)/libdevmapper-event.a.$(LIB_VERSION) + $(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a diff --git a/dmeventd/dmeventd.c b/dmeventd/dmeventd.c index 572bce0..8ec2b31 100644 --- a/dmeventd/dmeventd.c +++ b/dmeventd/dmeventd.c @@ -14,20 +14,19 @@ /* * dmeventd - dm event daemon to monitor active mapped devices - * - * Author - Heinz Mauelshagen, Red Hat GmbH. */ #include "libdevmapper.h" -#include "libdm-event.h" +#include "libdevmapper-event.h" #include "list.h" +#include "dmeventd.h" +//#include "libmultilog.h" +#include "log.h" #include #include #include -#include #include -#include #include #include #include @@ -40,16 +39,19 @@ #include #include #include +#include -#include "libmultilog.h" - +#ifdef linux +#include +#endif +/* FIXME Use dm library */ #define dbg_malloc(x...) malloc(x) #define dbg_strdup(x...) strdup(x) #define dbg_free(x...) free(x) /* List (un)link macros. */ -#define LINK(x, head) list_add(&(x)->list, head) +#define LINK(x, head) list_add(head, &(x)->list) #define LINK_DSO(dso) LINK(dso, &dso_registry) #define LINK_THREAD(thread) LINK(thread, &thread_registry) @@ -57,7 +59,7 @@ #define UNLINK_DSO(x) UNLINK(x) #define UNLINK_THREAD(x) UNLINK(x) -#define DAEMON_NAME "dmeventd" +#define DAEMON_NAME "dmeventd" /* Global mutex for list accesses. */ static pthread_mutex_t mutex; @@ -78,7 +80,7 @@ struct dso_data { * such as changing the mapping in case a mirror fails, update * the application metadata etc. */ - void (*process_event)(char *device, enum event_type event); + void (*process_event)(const char *device, enum dm_event_type event); /* * Device registration. @@ -88,7 +90,7 @@ struct dso_data { * the process_event() function is sane (eg, read metadata * and activate a mapping). */ - int (*register_device)(char *device); + int (*register_device)(const char *device); /* * Device unregistration. @@ -97,7 +99,7 @@ struct dso_data { * for events, the DSO can recognize this and carry out appropriate * steps (eg, deactivate mapping, metadata update). */ - int (*unregister_device)(char *device); + int (*unregister_device)(const char *device); }; static LIST_INIT(dso_registry); @@ -107,9 +109,13 @@ struct message_data { char *device_path; /* Mapped device path. */ union { char *str; /* Events string as fetched from message. */ - enum event_type field; /* Events bitfield. */ + enum dm_event_type field; /* Events bitfield. */ } events; - struct daemon_message *msg; /* Pointer to message buffer. */ + union { + char *str; + uint32_t secs; + } timeout; + struct dm_event_daemon_message *msg; /* Pointer to message buffer. */ }; /* @@ -121,17 +127,26 @@ struct message_data { struct thread_status { struct list list; - pthread_t thread; + pthread_t thread; struct dso_data *dso_data;/* DSO this thread accesses. */ char *device_path; /* Mapped device path. */ - enum event_type events; /* bitfield for event filter. */ - enum event_type current_events;/* bitfield for occured events. */ - enum event_type processed_events;/* bitfield for processed events. */ + int event_nr; /* event number */ + enum dm_event_type events; /* bitfield for event filter. */ + enum dm_event_type current_events;/* bitfield for occured events. */ + enum dm_event_type processed_events;/* bitfield for processed events. */ + time_t next_time; + uint32_t timeout; + struct list timeout_list; }; static LIST_INIT(thread_registry); +static int timeout_running; +static LIST_INIT(timeout_registry); +static pthread_mutex_t timeout_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t timeout_cond = PTHREAD_COND_INITIALIZER; + /* Allocate/free the status structure for a monitoring thread. */ static struct thread_status *alloc_thread_status(struct message_data *data, struct dso_data *dso_data) @@ -139,13 +154,15 @@ static struct thread_status *alloc_thread_status(struct message_data *data, struct thread_status *ret = (typeof(ret)) dbg_malloc(sizeof(*ret)); if (ret) { - memset(ret, 0, sizeof(*ret)); - if ((ret->device_path = dbg_strdup(data->device_path))) { - ret->dso_data = dso_data; - ret->events = data->events.field; - } else { + if (!memset(ret, 0, sizeof(*ret)) || + !(ret->device_path = dbg_strdup(data->device_path))) { dbg_free(ret); ret = NULL; + } else { + ret->dso_data = dso_data; + ret->events = data->events.field; + ret->timeout = data->timeout.secs; + list_init(&ret->timeout_list); } } @@ -164,8 +181,8 @@ static struct dso_data *alloc_dso_data(struct message_data *data) struct dso_data *ret = (typeof(ret)) dbg_malloc(sizeof(*ret)); if (ret) { - memset(ret, 0, sizeof(*ret)); - if (!(ret->dso_name = dbg_strdup(data->dso_name))) { + if (!memset(ret, 0, sizeof(*ret)) || + !(ret->dso_name = dbg_strdup(data->dso_name))) { dbg_free(ret); ret = NULL; } @@ -180,18 +197,40 @@ static void free_dso_data(struct dso_data *data) dbg_free(data); } -/* Fetch a string off src and duplicate it into *dest. */ +/* FIXME: Factor out. */ +static char *dm_basename(char *str) +{ + char *p = strrchr(str, '/'); + + return p ? p + 1 : str; +} + +/* + * Fetch a string off src and duplicate it into *ptr. + * Pay attention to 0 lenght strings. + */ /* FIXME: move to separate module to share with the client lib. */ static const char delimiter = ' '; -static char *fetch_string(char **src) +static int fetch_string(char **ptr, char **src) { - char *p, *ret; + int ret = 0; + char *p; + size_t len; if ((p = strchr(*src, delimiter))) *p = 0; - if ((ret = strdup(*src))) - *src += strlen(ret) + 1; + if ((*ptr = dbg_strdup(*src))) { + if ((len = strlen(*ptr))) + *src += len; + else { + dbg_free(*ptr); + *ptr = NULL; + } + + (*src)++; + ret = 1; + } if (p) *p = delimiter; @@ -214,19 +253,16 @@ static int parse_message(struct message_data *message_data) { char *p = message_data->msg->msg; -log_print("%s: here\n", __func__); -fflush(stdout); - /* * Retrieve application identifier, mapped device * path and events # string from message. */ - if ((message_data->dso_name = fetch_string(&p)) && - (message_data->device_path = fetch_string(&p)) && - (message_data->events.str = fetch_string(&p))) { -log_print("%s: %s %s %s\n", __func__, message_data->dso_name, message_data->device_path, message_data->events.str); + if (fetch_string(&message_data->dso_name, &p) && + fetch_string(&message_data->device_path, &p) && + fetch_string(&message_data->events.str, &p) && + fetch_string(&message_data->timeout.str, &p)) { if (message_data->events.str) { - enum event_type i = atoi(message_data->events.str); + enum dm_event_type i = atoi(message_data->events.str); /* * Free string representaion of events. @@ -235,12 +271,16 @@ log_print("%s: %s %s %s\n", __func__, message_data->dso_name, message_data->devi dbg_free(message_data->events.str); message_data->events.field = i; } + if (message_data->timeout.str) { + uint32_t secs = atoi(message_data->timeout.str); + dbg_free(message_data->timeout.str); + message_data->timeout.secs = secs ? secs : + DM_EVENT_DEFAULT_TIMEOUT; + } return 1; } - free_message(message_data); - return 0; }; @@ -275,50 +315,6 @@ static int storepid(int lf) return 1; } -/* - * create+flock file. - * - * Used to synchronize daemon startups. - */ -static int lf = -1; -static char pidfile[] = "/var/run/dmeventd.pid"; - -/* Store pid in pidfile. */ -static int lock(void) -{ - /* Already locked. */ - if (lf > -1) - return 1; - - if ((lf = open(pidfile, O_CREAT | O_RDWR, 0644)) == -1) { - log_err("opening pid file\n"); - return 0; - } - - if (flock(lf, LOCK_EX | LOCK_NB) == -1) { - log_err("lock pid file\n"); - close(lf); - lf = -1; - return 0; - } - - return 1; -} - -static void unlock(void) -{ - /* Not locked! */ - if (lf == -1) - return; - - if (flock(lf, LOCK_UN)) - log_err("flock unlock %s\n", pidfile); - - if (close(lf)) - log_err("close %s\n", pidfile); - - lf = -1; -} /* Check, if a device exists. */ static int device_exists(char *device) @@ -354,46 +350,199 @@ static void exit_dm_lib(void) } /* Derive error case from target parameter string. */ +/* FIXME Remove? */ +static int error_detected(struct thread_status *thread, char *params) __attribute__ ((unused)); static int error_detected(struct thread_status *thread, char *params) { size_t len; - +/* + Leave it to the DSO to decide how to interpret the status info if ((len = strlen(params)) && params[len - 1] == 'F') { - thread->current_events |= DEVICE_ERROR; +*/ + if (params && (len = strlen(params))) { + thread->current_events |= DM_EVENT_DEVICE_ERROR; return 1; } return 0; } +static void exit_timeout(void *unused) +{ + timeout_running = 0; + pthread_mutex_unlock(&timeout_mutex); +} + +/* Wake up monitor threads every so often. */ +static void *timeout_thread(void *unused) +{ + struct timespec timeout; + time_t curr_time; + + timeout.tv_nsec = 0; + pthread_cleanup_push(exit_timeout, NULL); + pthread_mutex_lock(&timeout_mutex); + + while (!list_empty(&timeout_registry)) { + struct thread_status *thread; + + timeout.tv_sec = (time_t)-1; + curr_time = time(NULL); + + list_iterate_items_gen(thread, &timeout_registry, + timeout_list) { + if (thread->next_time < curr_time) { + thread->next_time = curr_time + thread->timeout; + pthread_kill(thread->thread, SIGALRM); + } + + if (thread->next_time < timeout.tv_sec) + timeout.tv_sec = thread->next_time; + } + + pthread_cond_timedwait(&timeout_cond, &timeout_mutex, &timeout); + } + + pthread_cleanup_pop(1); + + return NULL; +} + +static int register_for_timeout(struct thread_status *thread) +{ + int ret = 0; + + pthread_mutex_lock(&timeout_mutex); + + thread->next_time = time(NULL) + thread->timeout; + + if (list_empty(&thread->timeout_list)) { + list_add(&timeout_registry, &thread->timeout_list); + if (timeout_running) + pthread_cond_signal(&timeout_cond); + } + + if (!timeout_running) { + pthread_t timeout_id; + + if (!(ret = -pthread_create(&timeout_id, NULL, + timeout_thread, NULL))) + timeout_running = 1; + } + + pthread_mutex_unlock(&timeout_mutex); + + return ret; +} + +static void unregister_for_timeout(struct thread_status *thread) +{ + pthread_mutex_lock(&timeout_mutex); + if (!list_empty(&thread->timeout_list)) { + list_del(&thread->timeout_list); + list_init(&thread->timeout_list); + } + pthread_mutex_unlock(&timeout_mutex); +} + +static void no_intr_log(int level, const char *file, int line, + const char *f, ...) +{ + va_list ap; + + if (errno == EINTR) + return; + if (level > _LOG_WARN) + return; + + va_start(ap, f); + + if (level < _LOG_WARN) + vfprintf(stderr, f, ap); + else + vprintf(f, ap); + + va_end(ap); + + if (level < _LOG_WARN) + fprintf(stderr, "\n"); + else + fprintf(stdout, "\n"); +} + +static sigset_t unblock_sigalrm(void) +{ + sigset_t set, old; + + sigemptyset(&set); + sigaddset(&set, SIGALRM); + pthread_sigmask(SIG_UNBLOCK, &set, &old); + return old; +} + /* Wait on a device until an event occurs. */ static int event_wait(struct thread_status *thread) { + sigset_t set; int ret = 0; +/* void *next = NULL; char *params, *target_type; uint64_t start, length; +*/ struct dm_task *dmt; + struct dm_info info; if (!(dmt = dm_task_create(DM_DEVICE_WAITEVENT))) return 0; - if ((ret = dm_task_set_name(dmt, basename(thread->device_path))) && - (ret = dm_task_set_event_nr(dmt, 0)) && - (ret = dm_task_run(dmt))) { + if (!(ret = dm_task_set_name(dmt, dm_basename(thread->device_path))) || + !(ret = dm_task_set_event_nr(dmt, thread->event_nr))) + goto out; + + /* + * This is so that you can break out of waiting on an event, + * either for a timeout event, or to cancel the thread. + */ + set = unblock_sigalrm(); + dm_log_init(no_intr_log); + errno = 0; + if ((ret = dm_task_run(dmt))) { +/* do { - /* Retrieve next target. */ params = NULL; next = dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); -log_print("%s: %s\n", __func__, params); + log_error("%s: %s\n", __func__, params); if ((ret = error_detected(thread, params))) break; } while(next); +*/ + thread->current_events |= DM_EVENT_DEVICE_ERROR; + ret = 1; + + /* + * FIXME: I am setting processed_events to zero here + * because it is causing problems. for example, the + * mirror target emits a signal for INSYNC, then + * subsequent events (device failures) are not handled + */ + thread->processed_events = 0; + + if ((ret = dm_task_get_info(dmt, &info))) + thread->event_nr = info.event_nr; + } else if (thread->events & DM_EVENT_TIMEOUT && errno == EINTR) { + thread->current_events |= DM_EVENT_TIMEOUT; + ret = 1; + thread->processed_events = 0; } + pthread_sigmask(SIG_SETMASK, &set, NULL); + dm_log_init(NULL); + + out: dm_task_destroy(dmt); return ret; @@ -411,7 +560,7 @@ static int do_unregister_device(struct thread_status *thread) return thread->dso_data->unregister_device(thread->device_path); } -/* Process an event the DSO. */ +/* Process an event in the DSO. */ static void do_process_event(struct thread_status *thread) { thread->dso_data->process_event(thread->device_path, @@ -424,7 +573,7 @@ static void monitor_unregister(void *arg) struct thread_status *thread = arg; if (!do_unregister_device(thread)) - log_err("%s: %s unregister failed\n", __func__, + log_error("%s: %s unregister failed\n", __func__, thread->device_path); } @@ -436,7 +585,7 @@ static void *monitor_thread(void *arg) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); pthread_cleanup_push(monitor_unregister, thread); - /* Wait for comm_thread() to finish its task. */ + /* Wait for do_process_reques() to finish its task. */ lock_mutex(); unlock_mutex(); @@ -447,9 +596,6 @@ static void *monitor_thread(void *arg) if (!event_wait(thread)) continue; -/* REMOVEME: */ -log_print("%s: cycle on %s\n", __func__, thread->device_path); - /* * Check against filter. * @@ -478,7 +624,12 @@ static int create_thread(struct thread_status *thread) static int terminate_thread(struct thread_status *thread) { - return pthread_cancel(thread->thread); + int ret; + + if ((ret = pthread_cancel(thread->thread))) + return ret; + + return pthread_kill(thread->thread, SIGALRM); } /* DSO reference counting. */ @@ -523,7 +674,7 @@ static int lookup_symbol(void *dl, struct dso_data *data, if ((*symbol = dlsym(dl, name))) return 1; - log_err("looking up %s symbol in %s\n", name, data->dso_name); + log_error("looking up %s symbol in %s\n", name, data->dso_name); return 0; } @@ -550,8 +701,6 @@ static char *create_dso_file_name(char *dso_name) strlen(suffix) + 1))) sprintf(ret, "%s%s%s", prefix, dso_name, suffix); -log_print("%s: \"%s\"\n", __func__, ret); - return ret; } @@ -562,13 +711,13 @@ static struct dso_data *load_dso(struct message_data *data) struct dso_data *ret = NULL; char *dso_file; -log_print("%s: \"%s\"\n", __func__, data->dso_name); - if (!(dso_file = create_dso_file_name(data->dso_name))) return NULL; - if (!(dl = dlopen(dso_file, RTLD_NOW))) + if (!(dl = dlopen(dso_file, RTLD_NOW))){ + log_error("%s\n", dlerror()); goto free_dso_file; + } if (!(ret = alloc_dso_data(data))) goto close; @@ -602,16 +751,22 @@ log_print("%s: \"%s\"\n", __func__, data->dso_name); } +/* Return success on daemon active check. */ +static int active(struct message_data *message_data) +{ + return 0; +} + /* * Register for an event. * - * Only one caller at a time here, because we use a FIFO and lock - * it against multiple accesses. + * Only one caller at a time here, because we use + * a FIFO and lock it against multiple accesses. */ static int register_for_event(struct message_data *message_data) { int ret = 0; - struct thread_status *thread, *thread_new; + struct thread_status *thread, *thread_new = NULL; struct dso_data *dso_data; if (!device_exists(message_data->device_path)) { @@ -619,13 +774,16 @@ static int register_for_event(struct message_data *message_data) ret = -ENODEV; goto out; } -log_print("%s\n", __func__); -fflush(stdout); if (!(dso_data = lookup_dso(message_data)) && !(dso_data = load_dso(message_data))) { stack; +/* FIXME */ +#ifdef ELIBACC ret = -ELIBACC; +#else + ret = -ENODEV; +#endif goto out; } @@ -636,20 +794,26 @@ fflush(stdout); goto out; } - if (!(ret = do_register_device(thread_new))) - goto out; - lock_mutex(); - if ((thread = lookup_thread_status(message_data))) - ret = -EPERM; - else { + if (!(thread = lookup_thread_status(message_data))) { + unlock_mutex(); + + /* + * FIXME: better do this asynchronously in the + * monitoring thread ? + */ + if (!(ret = do_register_device(thread_new))) + goto out; + thread = thread_new; thread_new = NULL; /* Try to create the monitoring thread for this device. */ + lock_mutex(); if ((ret = -create_thread(thread))) { unlock_mutex(); + do_unregister_device(thread); free_thread_status(thread); goto out; } else @@ -659,8 +823,18 @@ fflush(stdout); /* Or event # into events bitfield. */ thread->events |= message_data->events.field; - unlock_mutex(); + unlock_mutex(); + /* FIXME - If you fail to register for timeout events, you + still monitor all the other events. Is this the right + action for newly created devices? Also, you are still + on the timeout registry, so if a timeout thread is + successfully started up later, you will start receiving + DM_EVENT_TIMEOUT events */ + if (thread->events & DM_EVENT_TIMEOUT) + ret = -register_for_timeout(thread); + + out: /* * Deallocate thread status after releasing * the lock in case we haven't used it. @@ -668,9 +842,6 @@ fflush(stdout); if (thread_new) free_thread_status(thread_new); - out: - free_message(message_data); - return ret; } @@ -692,15 +863,17 @@ static int unregister_for_event(struct message_data *message_data) if (!(thread = lookup_thread_status(message_data))) { unlock_mutex(); - ret = -ESRCH; + ret = -ENODEV; goto out; } thread->events &= ~message_data->events.field; + if (!(thread->events & DM_EVENT_TIMEOUT)) + unregister_for_timeout(thread); /* - * In case there's no events to monitor on this - * device -> unlink and terminate its monitoring thread. + * In case there's no events to monitor on this device -> + * unlink and terminate its monitoring thread. */ if (!thread->events) UNLINK_THREAD(thread); @@ -709,12 +882,12 @@ static int unregister_for_event(struct message_data *message_data) if (!thread->events) { /* turn codes negative */ - if ((ret = -terminate_thread(thread))) { + if ((ret = -terminate_thread(thread))) stack; - } else { + else { pthread_join(thread->thread, NULL); - lib_put(thread->dso_data); free_thread_status(thread); + lib_put(thread->dso_data); lock_mutex(); if (list_empty(&thread_registry)) @@ -725,20 +898,18 @@ static int unregister_for_event(struct message_data *message_data) out: - free_message(message_data); - return ret; } /* - * Get next registered device. + * Get registered device. * * Only one caller at a time here as with register_for_event(). */ static int registered_device(struct message_data *message_data, struct thread_status *thread) { - struct daemon_message *msg = message_data->msg; + struct dm_event_daemon_message *msg = message_data->msg; snprintf(msg->msg, sizeof(msg->msg), "%s %s %u", thread->dso_data->dso_name, thread->device_path, @@ -749,104 +920,139 @@ static int registered_device(struct message_data *message_data, return 0; } -static int get_registered_device(struct message_data *message_data, int next) +static int want_registered_device(char *dso_name, char *device_path, + struct thread_status *thread) { - int dev, dso, hit = 0; - struct thread_status *thread; + /* If DSO names and device paths are equal. */ + if (dso_name && device_path) + return !strcmp(dso_name, thread->dso_data->dso_name) && + !strcmp(device_path, thread->device_path); + + /* If DSO names are equal. */ + if (dso_name) + return !strcmp(dso_name, thread->dso_data->dso_name); + + /* If device paths are equal. */ + if (device_path) + return !strcmp(device_path, thread->device_path); - lock_mutex(); + return 1; +} - thread = list_item(thread_registry.n, struct thread_status); +static int _get_registered_device(struct message_data *message_data, int next) +{ + int hit = 0; + struct thread_status *thread; - if (!message_data->dso_name && - !message_data->device_path) - goto out; - + lock_mutex(); + /* Iterate list of threads checking if we want a particular one. */ list_iterate_items(thread, &thread_registry) { - dev = dso = 0; - -log_print("%s: working %s %s %u\n", __func__, thread->dso_data->dso_name, thread->device_path, thread->events); - /* If DSO name equals. */ - if (message_data->dso_name && - !strcmp(message_data->dso_name, - thread->dso_data->dso_name)) - dso = 1; - - /* If dev path equals. */ - if (message_data->device_path && - !strcmp(message_data->device_path, - thread->device_path)) - dev = 1; - - /* We've got both DSO name and device patch or either. */ - /* FIXME: wrong logic! */ - if (message_data->dso_name && message_data->device_path && - dso && dev) - hit = 1; - else if (message_data->dso_name && dso) - hit = 1; - else if (message_data->device_path && - dev) - hit = 1; - - if (hit) -{log_print("%s: HIT %s %s %u\n", __func__, thread->dso_data->dso_name, thread->device_path, thread->events); + if ((hit = want_registered_device(message_data->dso_name, + message_data->device_path, + thread))) break; -} } /* * If we got a registered device and want the next one -> - * fetch next element off the list. + * fetch next conforming element off the list. */ - if (hit && next) - thread = list_item(&thread->list.n, struct thread_status); + if (hit) { + if (next) { + do { + if (list_end(&thread_registry, &thread->list)) + goto out; + + thread = list_item(thread->list.n, + struct thread_status); + } while (!want_registered_device(message_data->dso_name, + NULL, thread)); + } - out: - if (list_empty(&thread->list) || - &thread->list == &thread_registry) { - unlock_mutex(); - return -ENOENT; + return registered_device(message_data, thread); } + out: unlock_mutex(); - return registered_device(message_data, thread); + return -ENOENT; +} + +static int get_registered_device(struct message_data *message_data) +{ + return _get_registered_device(message_data, 0); +} + +static int get_next_registered_device(struct message_data *message_data) +{ + return _get_registered_device(message_data, 1); } +static int set_timeout(struct message_data *message_data) +{ + struct thread_status *thread; + + lock_mutex(); + if ((thread = lookup_thread_status(message_data))) + thread->timeout = message_data->timeout.secs; + unlock_mutex(); + + return thread ? 0 : -ENODEV; +} + +static int get_timeout(struct message_data *message_data) +{ + struct thread_status *thread; + struct dm_event_daemon_message *msg = message_data->msg; + + lock_mutex(); + if ((thread = lookup_thread_status(message_data))) + snprintf(msg->msg, sizeof(msg->msg), + "%"PRIu32, thread->timeout); + unlock_mutex(); + + return thread ? 0 : -ENODEV; +} + + /* Initialize a fifos structure with path names. */ -static void init_fifos(struct fifos *fifos) +static int init_fifos(struct dm_event_fifos *fifos) { - memset(fifos, 0, sizeof(*fifos)); - fifos->client_path = FIFO_CLIENT; - fifos->server_path = FIFO_SERVER; + if (memset(fifos, 0, sizeof(*fifos))) { + fifos->client_path = DM_EVENT_FIFO_CLIENT; + fifos->server_path = DM_EVENT_FIFO_SERVER; + + return 0; + } + + return -ENOMEM; } /* Open fifos used for client communication. */ -static int open_fifos(struct fifos *fifos) +static int open_fifos(struct dm_event_fifos *fifos) { /* Blocks until client is ready to write. */ - if ((fifos->server = open(fifos->server_path, O_WRONLY)) == -1) { + if ((fifos->server = open(fifos->server_path, O_WRONLY)) < 0) { stack; - return 0; + return -EXIT_FIFO_FAILURE; } /* Need to open read+write for select() to work. */ - if ((fifos->client = open(fifos->client_path, O_RDWR)) == -1) { + if ((fifos->client = open(fifos->client_path, O_RDWR)) < 0) { stack; close(fifos->server); - return 0; + return -EXIT_FIFO_FAILURE; } - return 1; + return 0; } /* * Read message from client making sure that data is available * and a complete message is read. */ -static int client_read(struct fifos *fifos, struct daemon_message *msg) +static int client_read(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg) { int bytes = 0, ret = 0; fd_set fds; @@ -869,7 +1075,7 @@ static int client_read(struct fifos *fifos, struct daemon_message *msg) /* * Write a message to the client making sure that it is ready to write. */ -static int client_write(struct fifos *fifos, struct daemon_message *msg) +static int client_write(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg) { int bytes = 0, ret = 0; fd_set fds; @@ -889,184 +1095,181 @@ static int client_write(struct fifos *fifos, struct daemon_message *msg) return bytes == sizeof(*msg); } +/* + * Handle a client request. + * + * We put the request handling functions into + * a list because of the growing number. + */ +static int handle_request(struct dm_event_daemon_message *msg, + struct message_data *message_data) +{ + static struct { + unsigned int cmd; + int (*f)(struct message_data*); + } requests[] = { + { DM_EVENT_CMD_REGISTER_FOR_EVENT, register_for_event }, + { DM_EVENT_CMD_UNREGISTER_FOR_EVENT, unregister_for_event }, + { DM_EVENT_CMD_GET_REGISTERED_DEVICE, get_registered_device }, + { DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE, get_next_registered_device }, + { DM_EVENT_CMD_SET_TIMEOUT, set_timeout }, + { DM_EVENT_CMD_GET_TIMEOUT, get_timeout }, + { DM_EVENT_CMD_ACTIVE, active }, + }, *req; + + for (req = requests; req < requests + sizeof(requests); req++) { + if (req->cmd == msg->opcode.cmd) + return req->f(message_data); + } + + return -EINVAL; +} + /* Process a request passed from the communication thread. */ -static int do_process_request(struct daemon_message *msg) +static int do_process_request(struct dm_event_daemon_message *msg) { int ret; static struct message_data message_data; -log_print("%s: \"%s\"\n", __func__, msg->msg); /* Parse the message. */ + memset(&message_data, 0, sizeof(message_data)); message_data.msg = msg; - if (msg->opcode.cmd != CMD_ACTIVE && + if (msg->opcode.cmd != DM_EVENT_CMD_ACTIVE && !parse_message(&message_data)) { stack; -fflush(stdout); - return -EINVAL; - } - -fflush(stdout); - - /* Check the request type. */ - switch (msg->opcode.cmd) { - case CMD_ACTIVE: - ret = 0; - break; - case CMD_REGISTER_FOR_EVENT: - ret = register_for_event(&message_data); - break; - case CMD_UNREGISTER_FOR_EVENT: - ret = unregister_for_event(&message_data); - break; - case CMD_GET_REGISTERED_DEVICE: - ret = get_registered_device(&message_data, 0); - break; - case CMD_GET_NEXT_REGISTERED_DEVICE: - ret = get_registered_device(&message_data, 1); - break; - default: ret = -EINVAL; - break; + } else { +log_print("%s: %u \"%s\"\n", __func__, msg->opcode.cmd, message_data.msg->msg); + ret = handle_request(msg, &message_data); } + free_message(&message_data); + return ret; } /* Only one caller at a time. */ -static void process_request(struct fifos *fifos, struct daemon_message *msg) +static void process_request(struct dm_event_fifos *fifos) { + struct dm_event_daemon_message msg; + + /* FIXME: better error handling */ + /* Read the request from the client. */ - memset(msg, 0, sizeof(*msg)); - if (!client_read(fifos, msg)) { + if (!memset(&msg, 0, sizeof(msg)) || + !client_read(fifos, &msg)) { stack; return; } - msg->opcode.status = do_process_request(msg); + msg.opcode.status = do_process_request(&msg); - memset(&msg->msg, 0, sizeof(msg->msg)); - if (!client_write(fifos, msg)) +log_print("%s: status: %s\n", __func__, strerror(-msg.opcode.status)); + if (!client_write(fifos, &msg)) stack; } -/* Communication thread. */ -static void comm_thread(struct fifos *fifos) +static void sig_alarm(int signum) { - struct daemon_message msg; + pthread_testcancel(); +} - /* Open fifos (must be created by client). */ - if (!open_fifos(fifos)) { - stack; - return; - } +/* Init thread signal handling. */ +static void init_thread_signals(void) +{ + sigset_t sigset; + struct sigaction act; - /* Exit after last unregister. */ - do { - process_request(fifos, &msg); - } while (!list_empty(&thread_registry)); + memset(&act, 0, sizeof(act)); + act.sa_handler = sig_alarm; + sigaction(SIGALRM, &act, NULL); + sigfillset(&sigset); + pthread_sigmask(SIG_BLOCK, &sigset, NULL); } -/* Fork into the background and detach from our parent process. */ static int daemonize(void) { - pid_t pid; - - if ((pid = fork()) == -1) { - log_err("%s: fork", __func__); - return 0; - } else if (pid > 0) /* Parent. */ - return 2; + setsid(); + if (chdir("/")) + return -EXIT_CHDIR_FAILURE; -log_print("daemonizing 2nd...\n"); +/* FIXME: activate again after we're done with tracing. + if ((close(STDIN_FILENO) < 0) || + (close(STDOUT_FILENO) < 0) || + (close(STDERR_FILENO) < 0)) + return -EXIT_DESC_CLOSE_FAILURE; +*/ - setsid(); - if (chdir("/")) { - log_err("%s: chdir /", __func__); - return 0; - } + return 0; +} -/* REMOVEME: */ - return 1; +static int lock_pidfile(void) +{ + int lf; + char pidfile[] = "/var/run/dmeventd.pid"; - log_print("daemonizing 3rd...\n"); + if ((lf = open(pidfile, O_CREAT | O_RDWR, 0644)) < 0) + return -EXIT_OPEN_PID_FAILURE; - /* Detach ourself. */ - if (close(STDIN_FILENO) == -1 || - close(STDOUT_FILENO) == -1 || - close(STDERR_FILENO) == -1) - return 0; + if (flock(lf, LOCK_EX | LOCK_NB) < 0) + return -EXIT_LOCKFILE_INUSE; -log_print("daemonized\n"); + if (!storepid(lf)) + return -EXIT_FAILURE; - return 1; + return 0; } -/* Init thread signal handling. */ -#define HANGUP SIGHUP -static void init_thread_signals(int hup) +void dmeventd(void) { - sigset_t sigset; - - sigfillset(&sigset); + int ret; + struct dm_event_fifos fifos; + // struct sys_log logdata = {DAEMON_NAME, LOG_DAEMON}; - if (hup) - sigdelset(&sigset, HANGUP); + if ((ret = daemonize())) + exit(-ret); - pthread_sigmask(SIG_SETMASK, &sigset, NULL); -} + /* FIXME: set daemon name. */ + // set_name(); -int main(void) -{ - struct fifos fifos; - struct sys_log logdata = {DAEMON_NAME, LOG_DAEMON}; - /* Make sure, parent accepts HANGUP signal. */ - init_thread_signals(1); - - switch (daemonize()) { - case 1: /* Child. */ - /* Try to lock pidfile. */ - if (!lock()) { - fprintf(stderr, "daemon already running\n"); - break; - } + if ((ret = lock_pidfile())) + exit(-ret); - init_thread_signals(0); - kill(getppid(), HANGUP); + init_thread_signals(); - multilog_clear_logging(); - multilog_add_type(std_syslog, &logdata); - multilog_init_verbose(std_syslog, _LOG_DEBUG); - multilog_async(1); + //multilog_clear_logging(); + //multilog_add_type(std_syslog, &logdata); + //multilog_init_verbose(std_syslog, _LOG_DEBUG); + //multilog_async(1); - init_fifos(&fifos); - pthread_mutex_init(&mutex, NULL); + if ((ret = init_fifos(&fifos))) + exit(-ret); - if (!storepid(lf)) { - stack; - exit(EXIT_FAILURE); - } + pthread_mutex_init(&mutex, NULL); - if (mlockall(MCL_FUTURE) == -1) { - stack; - exit(EXIT_FAILURE); - } +#ifdef MCL_CURRENT + if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) + exit(EXIT_FAILURE); +#endif - /* Communication thread runs forever... */ - comm_thread(&fifos); + if ((ret = open_fifos(&fifos))) + exit(-ret); - /* We should never get here. */ - munlockall(); - pthread_mutex_destroy(&mutex); + /* Signal parent, letting them know we are ready to go. */ + kill(getppid(), SIGUSR1); - case 0: /* Error (either on daemonize() or on comm_thread() return. */ - unlock(); - exit(EXIT_FAILURE); - break; + /* + * We exit when there are no more devices to watch. + * That is, when the last unregister happens. + */ + do { + process_request(&fifos); + } while(!list_empty(&thread_registry)); - case 2: /* Parent. */ - wait(NULL); - break; - } +#ifdef MCL_CURRENT + munlockall(); +#endif + pthread_mutex_destroy(&mutex); exit(EXIT_SUCCESS); } diff --git a/lib/event/dmeventd.h b/dmeventd/dmeventd.h similarity index 100% rename from lib/event/dmeventd.h rename to dmeventd/dmeventd.h diff --git a/lib/event/libdm-event.c b/dmeventd/libdevmapper-event.c similarity index 78% rename from lib/event/libdm-event.c rename to dmeventd/libdevmapper-event.c index df56b6c..62b12b7 100644 --- a/lib/event/libdm-event.c +++ b/dmeventd/libdevmapper-event.c @@ -13,8 +13,8 @@ */ #include "lib.h" -#include "libdm-event.h" -#include "libmultilog.h" +#include "libdevmapper-event.h" +//#include "libmultilog.h" #include "dmeventd.h" #include @@ -31,7 +31,8 @@ #include /* Set by any of the external fxns the first time one of them is called */ -static int _logging = 0; +/* FIXME Unused */ +// static int _logging = 0; /* Fetch a string off src and duplicate it into *dest. */ /* FIXME: move to seperate module to share with the daemon. */ @@ -53,8 +54,8 @@ static char *fetch_string(char **src) } /* Parse a device message from the daemon. */ -static int parse_message(struct daemon_message *msg, char **dso_name, - char **device, enum event_type *events) +static int parse_message(struct dm_event_daemon_message *msg, char **dso_name, + char **device, enum dm_event_type *events) { char *p = msg->msg; @@ -69,7 +70,7 @@ static int parse_message(struct daemon_message *msg, char **dso_name, } /* Read message from daemon. */ -static int daemon_read(struct fifos *fifos, struct daemon_message *msg) +static int daemon_read(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg) { int bytes = 0, ret = 0; fd_set fds; @@ -95,7 +96,7 @@ static int daemon_read(struct fifos *fifos, struct daemon_message *msg) } /* Write message to daemon. */ -static int daemon_write(struct fifos *fifos, struct daemon_message *msg) +static int daemon_write(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg) { int bytes = 0, ret = 0; fd_set fds; @@ -119,9 +120,9 @@ static int daemon_write(struct fifos *fifos, struct daemon_message *msg) return bytes == sizeof(*msg); } -static int daemon_talk(struct fifos *fifos, struct daemon_message *msg, +static int daemon_talk(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg, int cmd, char *dso_name, char *device, - enum event_type events, uint32_t timeout) + enum dm_event_type events, uint32_t timeout) { memset(msg, 0, sizeof(*msg)); @@ -177,25 +178,27 @@ static void daemon_running_signal_handler(int sig) static int start_daemon(void) { int pid, ret=0; - int slept=0; int old_mask; void *old_hand; /* Must be able to acquire signal */ old_hand = signal(SIGUSR1, &daemon_running_signal_handler); if (old_hand == SIG_ERR) { - log_err("Unable to setup signal handler."); + log_error("Unable to setup signal handler."); return 0; } +#ifdef linux + /* FIXME Deprecated. Try posix sigprocmask instead. */ old_mask = siggetmask(); old_mask &= ~sigmask(SIGUSR1); old_mask = sigsetmask(old_mask); +#endif pid = fork(); if (pid < 0) - log_err("Unable to fork.\n"); + log_error("Unable to fork.\n"); else if (pid) { /* parent waits for child to get ready for requests */ int status; @@ -218,7 +221,7 @@ static int start_daemon(void) ret = 1; break; default: - log_err("Unable to start dmeventd.\n"); + log_error("Unable to start dmeventd.\n"); break; } } @@ -234,41 +237,41 @@ static int start_daemon(void) /* FIXME What if old_hand is SIG_ERR? */ if (signal(SIGUSR1, old_hand) == SIG_ERR) - log_err("Unable to reset signal handler."); + log_error("Unable to reset signal handler."); sigsetmask(old_mask); return ret; } /* Initialize client. */ -static int init_client(struct fifos *fifos) +static int init_client(struct dm_event_fifos *fifos) { /* FIXME Is fifo the most suitable method? */ /* FIXME Why not share comms/daemon code with something else e.g. multipath? */ /* init fifos */ memset(fifos, 0, sizeof(*fifos)); - fifos->client_path = FIFO_CLIENT; - fifos->server_path = FIFO_SERVER; + fifos->client_path = DM_EVENT_FIFO_CLIENT; + fifos->server_path = DM_EVENT_FIFO_SERVER; /* FIXME The server should be responsible for these, not the client. */ /* Create fifos */ if (((mkfifo(fifos->client_path, 0600) == -1) && errno != EEXIST) || ((mkfifo(fifos->server_path, 0600) == -1) && errno != EEXIST)) { - log_err("%s: Failed to create a fifo.\n", __func__); + log_error("%s: Failed to create a fifo.\n", __func__); return 0; } /* FIXME Warn/abort if perms are wrong - not something to fix silently. */ /* If they were already there, make sure permissions are ok. */ if (chmod(fifos->client_path, 0600)) { - log_err("Unable to set correct file permissions on %s", + log_error("Unable to set correct file permissions on %s", fifos->client_path); return 0; } if (chmod(fifos->server_path, 0600)) { - log_err("Unable to set correct file permissions on %s", + log_error("Unable to set correct file permissions on %s", fifos->server_path); return 0; } @@ -278,7 +281,7 @@ static int init_client(struct fifos *fifos) * Allows daemon to create its write fifo... */ if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) { - log_err("%s: open server fifo %s\n", + log_error("%s: open server fifo %s\n", __func__, fifos->server_path); stack; return 0; @@ -287,7 +290,7 @@ static int init_client(struct fifos *fifos) /* Lock out anyone else trying to do communication with the daemon. */ /* FIXME Why failure not retry? How do multiple processes communicate? */ if (flock(fifos->server, LOCK_EX) < 0){ - log_err("%s: flock %s\n", __func__, fifos->server_path); + log_error("%s: flock %s\n", __func__, fifos->server_path); close(fifos->server); return 0; } @@ -296,7 +299,7 @@ static int init_client(struct fifos *fifos) if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) { if (errno != ENXIO) { - log_err("%s: open client fifo %s\n", + log_error("%s: open client fifo %s\n", __func__, fifos->client_path); close(fifos->server); stack; @@ -313,7 +316,7 @@ static int init_client(struct fifos *fifos) /* Daemon is started, retry the open */ fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK); if (fifos->client < 0) { - log_err("%s: open client fifo %s\n", + log_error("%s: open client fifo %s\n", __func__, fifos->client_path); close(fifos->server); stack; @@ -324,10 +327,10 @@ static int init_client(struct fifos *fifos) return 1; } -static void dtr_client(struct fifos *fifos) +static void dtr_client(struct dm_event_fifos *fifos) { if (flock(fifos->server, LOCK_UN)) - log_err("flock unlock %s\n", fifos->server_path); + log_error("flock unlock %s\n", fifos->server_path); close(fifos->client); close(fifos->server); @@ -352,12 +355,12 @@ static int device_exists(char *device) } /* Handle the event (de)registration call and return negative error codes. */ -static int do_event(int cmd, struct daemon_message *msg, - char *dso_name, char *device, enum event_type events, +static int do_event(int cmd, struct dm_event_daemon_message *msg, + char *dso_name, char *device, enum dm_event_type events, uint32_t timeout) { int ret; - struct fifos fifos; + struct dm_event_fifos fifos; /* FIXME Start the daemon here if it's not running e.g. exclusive lock file */ @@ -375,39 +378,39 @@ static int do_event(int cmd, struct daemon_message *msg, } /* External library interface. */ -int dm_register_for_event(char *dso_name, char *device_path, - enum event_type events) +int dm_event_register(char *dso_name, char *device_path, + enum dm_event_type events) { - struct daemon_message msg; + struct dm_event_daemon_message msg; if (!device_exists(device_path)) return -ENODEV; - return do_event(CMD_REGISTER_FOR_EVENT, &msg, + return do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg, dso_name, device_path, events, 0); } -int dm_unregister_for_event(char *dso_name, char *device_path, - enum event_type events) +int dm_event_unregister(char *dso_name, char *device_path, + enum dm_event_type events) { - struct daemon_message msg; + struct dm_event_daemon_message msg; if (!device_exists(device_path)) return -ENODEV; - return do_event(CMD_UNREGISTER_FOR_EVENT, &msg, + return do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg, dso_name, device_path, events, 0); } -int dm_get_registered_device(char **dso_name, char **device_path, - enum event_type *events, int next) +int dm_event_get_registered_device(char **dso_name, char **device_path, + enum dm_event_type *events, int next) { int ret; char *dso_name_arg = NULL, *device_path_arg = NULL; - struct daemon_message msg; + struct dm_event_daemon_message msg; - if (!(ret = do_event(next ? CMD_GET_NEXT_REGISTERED_DEVICE : - CMD_GET_REGISTERED_DEVICE, + if (!(ret = do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE : + DM_EVENT_CMD_GET_REGISTERED_DEVICE, &msg, *dso_name, *device_path, *events, 0))) ret = parse_message(&msg, &dso_name_arg, &device_path_arg, events); @@ -429,24 +432,24 @@ int dm_get_registered_device(char **dso_name, char **device_path, return ret; } -int dm_set_event_timeout(char *device_path, uint32_t timeout) +int dm_event_set_timeout(char *device_path, uint32_t timeout) { - struct daemon_message msg; + struct dm_event_daemon_message msg; if (!device_exists(device_path)) return -ENODEV; - return do_event(CMD_SET_TIMEOUT, &msg, + return do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg, NULL, device_path, 0, timeout); } -int dm_get_event_timeout(char *device_path, uint32_t *timeout) +int dm_event_get_timeout(char *device_path, uint32_t *timeout) { int ret; - struct daemon_message msg; + struct dm_event_daemon_message msg; if (!device_exists(device_path)) return -ENODEV; - if (!(ret = do_event(CMD_GET_TIMEOUT, &msg, NULL, device_path, 0, 0))) + if (!(ret = do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path, 0, 0))) *timeout = atoi(msg.msg); return ret; } diff --git a/dmeventd/libdevmapper-event.h b/dmeventd/libdevmapper-event.h new file mode 100644 index 0000000..9c9d637 --- /dev/null +++ b/dmeventd/libdevmapper-event.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2005 Red Hat, Inc. All rights reserved. + * + * This file is part of the device-mapper userspace tools. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Note that this file is released only as part of a technology preview + * and its contents may change in future updates in ways that do not + * preserve compatibility. + */ + +#ifndef LIB_DMEVENT_H +#define LIB_DMEVENT_H + +#include + +/* FIXME This stuff must be configurable. */ + +#define DM_EVENT_DAEMON "/sbin/dmeventd" +#define DM_EVENT_LOCKFILE "/var/lock/dmeventd" +#define DM_EVENT_FIFO_CLIENT "/var/run/dmeventd-client" +#define DM_EVENT_FIFO_SERVER "/var/run/dmeventd-server" +#define DM_EVENT_PIDFILE "/var/run/dmeventd.pid" + +#define DM_EVENT_DEFAULT_TIMEOUT 10 + +/* Commands for the daemon passed in the message below. */ +enum dm_event_command { + DM_EVENT_CMD_ACTIVE = 1, + DM_EVENT_CMD_REGISTER_FOR_EVENT, + DM_EVENT_CMD_UNREGISTER_FOR_EVENT, + DM_EVENT_CMD_GET_REGISTERED_DEVICE, + DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE, + DM_EVENT_CMD_SET_TIMEOUT, + DM_EVENT_CMD_GET_TIMEOUT, +}; + +/* Message passed between client and daemon. */ +struct dm_event_daemon_message { + union { + unsigned int cmd; /* FIXME Use fixed size. */ + int status; /* FIXME Use fixed size. */ + } opcode; + char msg[252]; /* FIXME Why is this 252 ? */ +} __attribute__((packed)); /* FIXME Do this properly! */ + +/* FIXME Is this meant to be exported? I can't see where the interface uses it. */ +/* Fifos for client/daemon communication. */ +struct dm_event_fifos { + int client; + int server; + const char *client_path; + const char *server_path; +}; + +/* Event type definitions. */ +/* FIXME Use masks to separate the types and provide for extension. */ +enum dm_event_type { + DM_EVENT_SINGLE = 0x01, /* Report multiple errors just once. */ + DM_EVENT_MULTI = 0x02, /* Report all of them. */ + + DM_EVENT_SECTOR_ERROR = 0x04, /* Failure on a particular sector. */ + DM_EVENT_DEVICE_ERROR = 0x08, /* Device failure. */ + DM_EVENT_PATH_ERROR = 0x10, /* Failure on an io path. */ + DM_EVENT_ADAPTOR_ERROR = 0x20, /* Failure off a host adaptor. */ + + DM_EVENT_SYNC_STATUS = 0x40, /* Mirror synchronization completed/failed. */ + DM_EVENT_TIMEOUT = 0x80, /* Timeout has occured */ +}; + +/* FIXME Use a mask. */ +#define DM_EVENT_ALL_ERRORS (DM_EVENT_SECTOR_ERROR | DM_EVENT_DEVICE_ERROR | \ + DM_EVENT_PATH_ERROR | DM_EVENT_ADAPTOR_ERROR) + +/* Prototypes for event lib interface. */ +/* FIXME Missing consts? */ +int dm_event_register(char *dso_name, char *device, enum dm_event_type events); +int dm_event_unregister(char *dso_name, char *device, + enum dm_event_type events); +int dm_event_get_registered_device(char **dso_name, char **device, + enum dm_event_type *events, int next); +int dm_event_set_timeout(char *device, uint32_t timeout); +int dm_event_get_timeout(char *device, uint32_t *timeout); + +/* Prototypes for DSO interface. */ +void process_event(const char *device, enum dm_event_type event); +int register_device(const char *device); +int unregister_device(const char *device); + +#endif diff --git a/dmeventd/old/.exported_symbols b/dmeventd/old/.exported_symbols new file mode 100644 index 0000000..4854e98 --- /dev/null +++ b/dmeventd/old/.exported_symbols @@ -0,0 +1,3 @@ +process_event +register_device +unregister_device \ No newline at end of file diff --git a/dmeventd/old/Makefile.in b/dmeventd/old/Makefile.in new file mode 100644 index 0000000..394f61e --- /dev/null +++ b/dmeventd/old/Makefile.in @@ -0,0 +1,51 @@ +# +# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. +# Copyright (C) 2004 Red Hat, Inc. All rights reserved. +# +# This file is part of the device-mapper userspace tools. +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions +# of the GNU General Public License v.2. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +TARGETS = dmevent dmeventd +INSTALL_TYPE = install_dynamic + +SOURCES = noop.c +CLEAN_TARGETS = dmevent.o dmeventd.o + +ifeq ("@LIB_SUFFIX@","dylib") + LIB_SHARED = libdmeventdnoop.dylib +else + LIB_SHARED = libdmeventdnoop.so +endif + +LDFLAGS += -ldl -ldevmapper -lmultilog + +include ../make.tmpl + +libdmeventdnoop.so: noop.o + +dmevent: dmevent.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX) + $(CC) -o $@ dmevent.o $(LDFLAGS) \ + -L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog $(LIBS) + +dmeventd: dmeventd.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX) + $(CC) -o $@ dmeventd.o $(LDFLAGS) \ + -L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog -lpthread -ldmevent $(LIBS) + +install: $(INSTALL_TYPE) + +.PHONY: install_dynamic + +install_dynamic: dmeventd + $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) dmeventd $(sbindir)/dmeventd + diff --git a/dmeventd/dmevent.c b/dmeventd/old/dmevent.c similarity index 100% rename from dmeventd/dmevent.c rename to dmeventd/old/dmevent.c diff --git a/lib/event/dmeventd.c b/dmeventd/old/dmeventd.c similarity index 58% rename from lib/event/dmeventd.c rename to dmeventd/old/dmeventd.c index 6b2627d..572bce0 100644 --- a/lib/event/dmeventd.c +++ b/dmeventd/old/dmeventd.c @@ -14,13 +14,13 @@ /* * dmeventd - dm event daemon to monitor active mapped devices + * + * Author - Heinz Mauelshagen, Red Hat GmbH. */ #include "libdevmapper.h" #include "libdm-event.h" #include "list.h" -#include "dmeventd.h" -#include "libmultilog.h" #include #include @@ -40,7 +40,8 @@ #include #include #include -#include + +#include "libmultilog.h" #define dbg_malloc(x...) malloc(x) @@ -48,7 +49,7 @@ #define dbg_free(x...) free(x) /* List (un)link macros. */ -#define LINK(x, head) list_add(head, &(x)->list) +#define LINK(x, head) list_add(&(x)->list, head) #define LINK_DSO(dso) LINK(dso, &dso_registry) #define LINK_THREAD(thread) LINK(thread, &thread_registry) @@ -56,7 +57,7 @@ #define UNLINK_DSO(x) UNLINK(x) #define UNLINK_THREAD(x) UNLINK(x) -#define DAEMON_NAME "dmeventd" +#define DAEMON_NAME "dmeventd" /* Global mutex for list accesses. */ static pthread_mutex_t mutex; @@ -108,10 +109,6 @@ struct message_data { char *str; /* Events string as fetched from message. */ enum event_type field; /* Events bitfield. */ } events; - union { - char *str; - uint32_t secs; - } timeout; struct daemon_message *msg; /* Pointer to message buffer. */ }; @@ -124,26 +121,17 @@ struct message_data { struct thread_status { struct list list; - pthread_t thread; + pthread_t thread; struct dso_data *dso_data;/* DSO this thread accesses. */ char *device_path; /* Mapped device path. */ - int event_nr; /* event number */ enum event_type events; /* bitfield for event filter. */ enum event_type current_events;/* bitfield for occured events. */ enum event_type processed_events;/* bitfield for processed events. */ - time_t next_time; - uint32_t timeout; - struct list timeout_list; }; static LIST_INIT(thread_registry); -static int timeout_running; -static LIST_INIT(timeout_registry); -static pthread_mutex_t timeout_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t timeout_cond = PTHREAD_COND_INITIALIZER; - /* Allocate/free the status structure for a monitoring thread. */ static struct thread_status *alloc_thread_status(struct message_data *data, struct dso_data *dso_data) @@ -151,15 +139,13 @@ static struct thread_status *alloc_thread_status(struct message_data *data, struct thread_status *ret = (typeof(ret)) dbg_malloc(sizeof(*ret)); if (ret) { - if (!memset(ret, 0, sizeof(*ret)) || - !(ret->device_path = dbg_strdup(data->device_path))) { - dbg_free(ret); - ret = NULL; - } else { + memset(ret, 0, sizeof(*ret)); + if ((ret->device_path = dbg_strdup(data->device_path))) { ret->dso_data = dso_data; ret->events = data->events.field; - ret->timeout = data->timeout.secs; - list_init(&ret->timeout_list); + } else { + dbg_free(ret); + ret = NULL; } } @@ -178,8 +164,8 @@ static struct dso_data *alloc_dso_data(struct message_data *data) struct dso_data *ret = (typeof(ret)) dbg_malloc(sizeof(*ret)); if (ret) { - if (!memset(ret, 0, sizeof(*ret)) || - !(ret->dso_name = dbg_strdup(data->dso_name))) { + memset(ret, 0, sizeof(*ret)); + if (!(ret->dso_name = dbg_strdup(data->dso_name))) { dbg_free(ret); ret = NULL; } @@ -194,40 +180,18 @@ static void free_dso_data(struct dso_data *data) dbg_free(data); } -/* FIXME: Factor out. */ -static char *dm_basename(char *str) -{ - char *p = strrchr(str, '/'); - - return p ? p + 1 : str; -} - -/* - * Fetch a string off src and duplicate it into *ptr. - * Pay attention to 0 lenght strings. - */ +/* Fetch a string off src and duplicate it into *dest. */ /* FIXME: move to separate module to share with the client lib. */ static const char delimiter = ' '; -static int fetch_string(char **ptr, char **src) +static char *fetch_string(char **src) { - int ret = 0; - char *p; - size_t len; + char *p, *ret; if ((p = strchr(*src, delimiter))) *p = 0; - if ((*ptr = dbg_strdup(*src))) { - if ((len = strlen(*ptr))) - *src += len; - else { - dbg_free(*ptr); - *ptr = NULL; - } - - (*src)++; - ret = 1; - } + if ((ret = strdup(*src))) + *src += strlen(ret) + 1; if (p) *p = delimiter; @@ -250,14 +214,17 @@ static int parse_message(struct message_data *message_data) { char *p = message_data->msg->msg; +log_print("%s: here\n", __func__); +fflush(stdout); + /* * Retrieve application identifier, mapped device * path and events # string from message. */ - if (fetch_string(&message_data->dso_name, &p) && - fetch_string(&message_data->device_path, &p) && - fetch_string(&message_data->events.str, &p) && - fetch_string(&message_data->timeout.str, &p)) { + if ((message_data->dso_name = fetch_string(&p)) && + (message_data->device_path = fetch_string(&p)) && + (message_data->events.str = fetch_string(&p))) { +log_print("%s: %s %s %s\n", __func__, message_data->dso_name, message_data->device_path, message_data->events.str); if (message_data->events.str) { enum event_type i = atoi(message_data->events.str); @@ -268,16 +235,12 @@ static int parse_message(struct message_data *message_data) dbg_free(message_data->events.str); message_data->events.field = i; } - if (message_data->timeout.str) { - uint32_t secs = atoi(message_data->timeout.str); - dbg_free(message_data->timeout.str); - message_data->timeout.secs = secs ? secs : - DEFAULT_TIMEOUT; - } return 1; } + free_message(message_data); + return 0; }; @@ -312,6 +275,50 @@ static int storepid(int lf) return 1; } +/* + * create+flock file. + * + * Used to synchronize daemon startups. + */ +static int lf = -1; +static char pidfile[] = "/var/run/dmeventd.pid"; + +/* Store pid in pidfile. */ +static int lock(void) +{ + /* Already locked. */ + if (lf > -1) + return 1; + + if ((lf = open(pidfile, O_CREAT | O_RDWR, 0644)) == -1) { + log_err("opening pid file\n"); + return 0; + } + + if (flock(lf, LOCK_EX | LOCK_NB) == -1) { + log_err("lock pid file\n"); + close(lf); + lf = -1; + return 0; + } + + return 1; +} + +static void unlock(void) +{ + /* Not locked! */ + if (lf == -1) + return; + + if (flock(lf, LOCK_UN)) + log_err("flock unlock %s\n", pidfile); + + if (close(lf)) + log_err("close %s\n", pidfile); + + lf = -1; +} /* Check, if a device exists. */ static int device_exists(char *device) @@ -350,12 +357,9 @@ static void exit_dm_lib(void) static int error_detected(struct thread_status *thread, char *params) { size_t len; -/* - Leave it to the DSO to decide how to interpret the status info + if ((len = strlen(params)) && params[len - 1] == 'F') { -*/ - if (params && (len = strlen(params))) { thread->current_events |= DEVICE_ERROR; return 1; } @@ -363,181 +367,33 @@ static int error_detected(struct thread_status *thread, char *params) return 0; } -static void exit_timeout(void *unused) -{ - timeout_running = 0; - pthread_mutex_unlock(&timeout_mutex); -} - -/* Wake up monitor threads every so often. */ -static void *timeout_thread(void *unused) -{ - struct timespec timeout; - time_t curr_time; - - timeout.tv_nsec = 0; - pthread_cleanup_push(exit_timeout, NULL); - pthread_mutex_lock(&timeout_mutex); - - while (!list_empty(&timeout_registry)) { - struct thread_status *thread; - - timeout.tv_sec = (time_t)-1; - curr_time = time(NULL); - - list_iterate_items_gen(thread, &timeout_registry, - timeout_list) { - if (thread->next_time < curr_time) { - thread->next_time = curr_time + thread->timeout; - pthread_kill(thread->thread, SIGALRM); - } - - if (thread->next_time < timeout.tv_sec) - timeout.tv_sec = thread->next_time; - } - - pthread_cond_timedwait(&timeout_cond, &timeout_mutex, &timeout); - } - - pthread_cleanup_pop(1); - - return NULL; -} - -static int register_for_timeout(struct thread_status *thread) -{ - int ret = 0; - - pthread_mutex_lock(&timeout_mutex); - - thread->next_time = time(NULL) + thread->timeout; - - if (list_empty(&thread->timeout_list)) { - list_add(&timeout_registry, &thread->timeout_list); - if (timeout_running) - pthread_cond_signal(&timeout_cond); - } - - if (!timeout_running) { - pthread_t timeout_id; - - if (!(ret = -pthread_create(&timeout_id, NULL, - timeout_thread, NULL))) - timeout_running = 1; - } - - pthread_mutex_unlock(&timeout_mutex); - - return ret; -} - -static void unregister_for_timeout(struct thread_status *thread) -{ - pthread_mutex_lock(&timeout_mutex); - if (!list_empty(&thread->timeout_list)) { - list_del(&thread->timeout_list); - list_init(&thread->timeout_list); - } - pthread_mutex_unlock(&timeout_mutex); -} - -static void no_intr_log(int level, const char *file, int line, - const char *f, ...) -{ - va_list ap; - - if (errno == EINTR) - return; - if (level > _LOG_WARN) - return; - - va_start(ap, f); - - if (level < _LOG_WARN) - vfprintf(stderr, f, ap); - else - vprintf(f, ap); - - va_end(ap); - - if (level < _LOG_WARN) - fprintf(stderr, "\n"); - else - fprintf(stdout, "\n"); -} - -static sigset_t unblock_sigalrm(void) -{ - sigset_t set, old; - - sigemptyset(&set); - sigaddset(&set, SIGALRM); - pthread_sigmask(SIG_UNBLOCK, &set, &old); - return old; -} - /* Wait on a device until an event occurs. */ static int event_wait(struct thread_status *thread) { - sigset_t set; int ret = 0; -/* void *next = NULL; char *params, *target_type; uint64_t start, length; -*/ struct dm_task *dmt; - struct dm_info info; if (!(dmt = dm_task_create(DM_DEVICE_WAITEVENT))) return 0; - if (!(ret = dm_task_set_name(dmt, dm_basename(thread->device_path))) || - !(ret = dm_task_set_event_nr(dmt, thread->event_nr))) - goto out; - - /* - * This is so that you can break out of waiting on an event, - * either for a timeout event, or to cancel the thread. - */ - set = unblock_sigalrm(); - dm_log_init(no_intr_log); - errno = 0; - if ((ret = dm_task_run(dmt))) { -/* + if ((ret = dm_task_set_name(dmt, basename(thread->device_path))) && + (ret = dm_task_set_event_nr(dmt, 0)) && + (ret = dm_task_run(dmt))) { do { + /* Retrieve next target. */ params = NULL; next = dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); - log_err("%s: %s\n", __func__, params); +log_print("%s: %s\n", __func__, params); if ((ret = error_detected(thread, params))) break; } while(next); -*/ - thread->current_events |= DEVICE_ERROR; - ret = 1; - - /* - * FIXME: I am setting processed_events to zero here - * because it is causing problems. for example, the - * mirror target emits a signal for INSYNC, then - * subsequent events (device failures) are not handled - */ - thread->processed_events = 0; - - if ((ret = dm_task_get_info(dmt, &info))) - thread->event_nr = info.event_nr; - } else if (thread->events & TIMEOUT && errno == EINTR) { - thread->current_events |= TIMEOUT; - ret = 1; - thread->processed_events = 0; } - pthread_sigmask(SIG_SETMASK, &set, NULL); - dm_log_init(NULL); - - out: dm_task_destroy(dmt); return ret; @@ -555,7 +411,7 @@ static int do_unregister_device(struct thread_status *thread) return thread->dso_data->unregister_device(thread->device_path); } -/* Process an event in the DSO. */ +/* Process an event the DSO. */ static void do_process_event(struct thread_status *thread) { thread->dso_data->process_event(thread->device_path, @@ -580,7 +436,7 @@ static void *monitor_thread(void *arg) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); pthread_cleanup_push(monitor_unregister, thread); - /* Wait for do_process_reques() to finish its task. */ + /* Wait for comm_thread() to finish its task. */ lock_mutex(); unlock_mutex(); @@ -591,6 +447,9 @@ static void *monitor_thread(void *arg) if (!event_wait(thread)) continue; +/* REMOVEME: */ +log_print("%s: cycle on %s\n", __func__, thread->device_path); + /* * Check against filter. * @@ -619,12 +478,7 @@ static int create_thread(struct thread_status *thread) static int terminate_thread(struct thread_status *thread) { - int ret; - - if ((ret = pthread_cancel(thread->thread))) - return ret; - - return pthread_kill(thread->thread, SIGALRM); + return pthread_cancel(thread->thread); } /* DSO reference counting. */ @@ -696,6 +550,8 @@ static char *create_dso_file_name(char *dso_name) strlen(suffix) + 1))) sprintf(ret, "%s%s%s", prefix, dso_name, suffix); +log_print("%s: \"%s\"\n", __func__, ret); + return ret; } @@ -706,13 +562,13 @@ static struct dso_data *load_dso(struct message_data *data) struct dso_data *ret = NULL; char *dso_file; +log_print("%s: \"%s\"\n", __func__, data->dso_name); + if (!(dso_file = create_dso_file_name(data->dso_name))) return NULL; - if (!(dl = dlopen(dso_file, RTLD_NOW))){ - log_err("%s\n", dlerror()); + if (!(dl = dlopen(dso_file, RTLD_NOW))) goto free_dso_file; - } if (!(ret = alloc_dso_data(data))) goto close; @@ -746,22 +602,16 @@ static struct dso_data *load_dso(struct message_data *data) } -/* Return success on daemon active check. */ -static int active(struct message_data *message_data) -{ - return 0; -} - /* * Register for an event. * - * Only one caller at a time here, because we use - * a FIFO and lock it against multiple accesses. + * Only one caller at a time here, because we use a FIFO and lock + * it against multiple accesses. */ static int register_for_event(struct message_data *message_data) { int ret = 0; - struct thread_status *thread, *thread_new = NULL; + struct thread_status *thread, *thread_new; struct dso_data *dso_data; if (!device_exists(message_data->device_path)) { @@ -769,6 +619,8 @@ static int register_for_event(struct message_data *message_data) ret = -ENODEV; goto out; } +log_print("%s\n", __func__); +fflush(stdout); if (!(dso_data = lookup_dso(message_data)) && !(dso_data = load_dso(message_data))) { @@ -784,26 +636,20 @@ static int register_for_event(struct message_data *message_data) goto out; } - lock_mutex(); - - if (!(thread = lookup_thread_status(message_data))) { - unlock_mutex(); - - /* - * FIXME: better do this asynchronously in the - * monitoring thread ? - */ - if (!(ret = do_register_device(thread_new))) + if (!(ret = do_register_device(thread_new))) goto out; + lock_mutex(); + + if ((thread = lookup_thread_status(message_data))) + ret = -EPERM; + else { thread = thread_new; thread_new = NULL; /* Try to create the monitoring thread for this device. */ - lock_mutex(); if ((ret = -create_thread(thread))) { unlock_mutex(); - do_unregister_device(thread); free_thread_status(thread); goto out; } else @@ -813,18 +659,8 @@ static int register_for_event(struct message_data *message_data) /* Or event # into events bitfield. */ thread->events |= message_data->events.field; - unlock_mutex(); - - /* FIXME - If you fail to register for timeout events, you - still monitor all the other events. Is this the right - action for newly created devices? Also, you are still - on the timeout registry, so if a timeout thread is - successfully started up later, you will start receiving - TIMEOUT events */ - if (thread->events & TIMEOUT) - ret = -register_for_timeout(thread); + unlock_mutex(); - out: /* * Deallocate thread status after releasing * the lock in case we haven't used it. @@ -832,6 +668,9 @@ static int register_for_event(struct message_data *message_data) if (thread_new) free_thread_status(thread_new); + out: + free_message(message_data); + return ret; } @@ -853,17 +692,15 @@ static int unregister_for_event(struct message_data *message_data) if (!(thread = lookup_thread_status(message_data))) { unlock_mutex(); - ret = -ENODEV; + ret = -ESRCH; goto out; } thread->events &= ~message_data->events.field; - if (!(thread->events & TIMEOUT)) - unregister_for_timeout(thread); /* - * In case there's no events to monitor on this device -> - * unlink and terminate its monitoring thread. + * In case there's no events to monitor on this + * device -> unlink and terminate its monitoring thread. */ if (!thread->events) UNLINK_THREAD(thread); @@ -872,12 +709,12 @@ static int unregister_for_event(struct message_data *message_data) if (!thread->events) { /* turn codes negative */ - if ((ret = -terminate_thread(thread))) + if ((ret = -terminate_thread(thread))) { stack; - else { + } else { pthread_join(thread->thread, NULL); - free_thread_status(thread); lib_put(thread->dso_data); + free_thread_status(thread); lock_mutex(); if (list_empty(&thread_registry)) @@ -888,11 +725,13 @@ static int unregister_for_event(struct message_data *message_data) out: + free_message(message_data); + return ret; } /* - * Get registered device. + * Get next registered device. * * Only one caller at a time here as with register_for_event(). */ @@ -910,132 +749,97 @@ static int registered_device(struct message_data *message_data, return 0; } -static int want_registered_device(char *dso_name, char *device_path, - struct thread_status *thread) -{ - /* If DSO names and device paths are equal. */ - if (dso_name && device_path) - return !strcmp(dso_name, thread->dso_data->dso_name) && - !strcmp(device_path, thread->device_path); - - /* If DSO names are equal. */ - if (dso_name) - return !strcmp(dso_name, thread->dso_data->dso_name); - - /* If device paths are equal. */ - if (device_path) - return !strcmp(device_path, thread->device_path); - - return 1; -} - -static int _get_registered_device(struct message_data *message_data, int next) +static int get_registered_device(struct message_data *message_data, int next) { - int hit = 0; + int dev, dso, hit = 0; struct thread_status *thread; lock_mutex(); - /* Iterate list of threads checking if we want a particular one. */ + thread = list_item(thread_registry.n, struct thread_status); + + if (!message_data->dso_name && + !message_data->device_path) + goto out; + + list_iterate_items(thread, &thread_registry) { - if ((hit = want_registered_device(message_data->dso_name, - message_data->device_path, - thread))) + dev = dso = 0; + +log_print("%s: working %s %s %u\n", __func__, thread->dso_data->dso_name, thread->device_path, thread->events); + /* If DSO name equals. */ + if (message_data->dso_name && + !strcmp(message_data->dso_name, + thread->dso_data->dso_name)) + dso = 1; + + /* If dev path equals. */ + if (message_data->device_path && + !strcmp(message_data->device_path, + thread->device_path)) + dev = 1; + + /* We've got both DSO name and device patch or either. */ + /* FIXME: wrong logic! */ + if (message_data->dso_name && message_data->device_path && + dso && dev) + hit = 1; + else if (message_data->dso_name && dso) + hit = 1; + else if (message_data->device_path && + dev) + hit = 1; + + if (hit) +{log_print("%s: HIT %s %s %u\n", __func__, thread->dso_data->dso_name, thread->device_path, thread->events); break; +} } /* * If we got a registered device and want the next one -> - * fetch next conforming element off the list. + * fetch next element off the list. */ - if (hit) { - if (next) { - do { - if (list_end(&thread_registry, &thread->list)) - goto out; - - thread = list_item(thread->list.n, - struct thread_status); - } while (!want_registered_device(message_data->dso_name, - NULL, thread)); - } - - return registered_device(message_data, thread); - } + if (hit && next) + thread = list_item(&thread->list.n, struct thread_status); out: - unlock_mutex(); - - return -ENOENT; -} - -static int get_registered_device(struct message_data *message_data) -{ - return _get_registered_device(message_data, 0); -} - -static int get_next_registered_device(struct message_data *message_data) -{ - return _get_registered_device(message_data, 1); -} - -static int set_timeout(struct message_data *message_data) -{ - struct thread_status *thread; - - lock_mutex(); - if ((thread = lookup_thread_status(message_data))) - thread->timeout = message_data->timeout.secs; - unlock_mutex(); - - return thread ? 0 : -ENODEV; -} - -static int get_timeout(struct message_data *message_data) -{ - struct thread_status *thread; - struct daemon_message *msg = message_data->msg; + if (list_empty(&thread->list) || + &thread->list == &thread_registry) { + unlock_mutex(); + return -ENOENT; + } - lock_mutex(); - if ((thread = lookup_thread_status(message_data))) - snprintf(msg->msg, sizeof(msg->msg), - "%"PRIu32, thread->timeout); unlock_mutex(); - return thread ? 0 : -ENODEV; + return registered_device(message_data, thread); } - /* Initialize a fifos structure with path names. */ -static int init_fifos(struct fifos *fifos) +static void init_fifos(struct fifos *fifos) { - if (memset(fifos, 0, sizeof(*fifos))) { - fifos->client_path = FIFO_CLIENT; - fifos->server_path = FIFO_SERVER; - - return 0; - } - - return -ENOMEM; + memset(fifos, 0, sizeof(*fifos)); + fifos->client_path = FIFO_CLIENT; + fifos->server_path = FIFO_SERVER; } /* Open fifos used for client communication. */ static int open_fifos(struct fifos *fifos) { /* Blocks until client is ready to write. */ - if ((fifos->server = open(fifos->server_path, O_WRONLY)) < 0) { + if ((fifos->server = open(fifos->server_path, O_WRONLY)) == -1) { stack; - return -EXIT_FIFO_FAILURE; + return 0; } /* Need to open read+write for select() to work. */ - if ((fifos->client = open(fifos->client_path, O_RDWR)) < 0) { + if ((fifos->client = open(fifos->client_path, O_RDWR)) == -1) { stack; close(fifos->server); - return -EXIT_FIFO_FAILURE; + return 0; } - return 0; + return 1; } /* @@ -1085,177 +889,184 @@ static int client_write(struct fifos *fifos, struct daemon_message *msg) return bytes == sizeof(*msg); } -/* - * Handle a client request. - * - * We put the request handling functions into - * a list because of the growing number. - */ -static int handle_request(struct daemon_message *msg, - struct message_data *message_data) -{ - static struct { - unsigned int cmd; - int (*f)(struct message_data*); - } requests[] = { - { CMD_REGISTER_FOR_EVENT, register_for_event }, - { CMD_UNREGISTER_FOR_EVENT, unregister_for_event }, - { CMD_GET_REGISTERED_DEVICE, get_registered_device }, - { CMD_GET_NEXT_REGISTERED_DEVICE, get_next_registered_device }, - { CMD_SET_TIMEOUT, set_timeout }, - { CMD_GET_TIMEOUT, get_timeout }, - { CMD_ACTIVE, active }, - }, *req; - - for (req = requests; req < requests + sizeof(requests); req++) { - if (req->cmd == msg->opcode.cmd) - return req->f(message_data); - } - - return -EINVAL; -} - /* Process a request passed from the communication thread. */ static int do_process_request(struct daemon_message *msg) { int ret; static struct message_data message_data; +log_print("%s: \"%s\"\n", __func__, msg->msg); /* Parse the message. */ - memset(&message_data, 0, sizeof(message_data)); message_data.msg = msg; if (msg->opcode.cmd != CMD_ACTIVE && !parse_message(&message_data)) { stack; - ret = -EINVAL; - } else { -log_print("%s: %u \"%s\"\n", __func__, msg->opcode.cmd, message_data.msg->msg); - ret = handle_request(msg, &message_data); +fflush(stdout); + return -EINVAL; } - free_message(&message_data); +fflush(stdout); + + /* Check the request type. */ + switch (msg->opcode.cmd) { + case CMD_ACTIVE: + ret = 0; + break; + case CMD_REGISTER_FOR_EVENT: + ret = register_for_event(&message_data); + break; + case CMD_UNREGISTER_FOR_EVENT: + ret = unregister_for_event(&message_data); + break; + case CMD_GET_REGISTERED_DEVICE: + ret = get_registered_device(&message_data, 0); + break; + case CMD_GET_NEXT_REGISTERED_DEVICE: + ret = get_registered_device(&message_data, 1); + break; + default: + ret = -EINVAL; + break; + } return ret; } /* Only one caller at a time. */ -static void process_request(struct fifos *fifos) +static void process_request(struct fifos *fifos, struct daemon_message *msg) { - struct daemon_message msg; - - /* FIXME: better error handling */ - /* Read the request from the client. */ - if (!memset(&msg, 0, sizeof(msg)) || - !client_read(fifos, &msg)) { + memset(msg, 0, sizeof(*msg)); + if (!client_read(fifos, msg)) { stack; return; } - msg.opcode.status = do_process_request(&msg); + msg->opcode.status = do_process_request(msg); -log_print("%s: status: %s\n", __func__, strerror(-msg.opcode.status)); - if (!client_write(fifos, &msg)) + memset(&msg->msg, 0, sizeof(msg->msg)); + if (!client_write(fifos, msg)) stack; } -static void sig_alarm(int signum) +/* Communication thread. */ +static void comm_thread(struct fifos *fifos) { - pthread_testcancel(); -} + struct daemon_message msg; -/* Init thread signal handling. */ -static void init_thread_signals(void) -{ - sigset_t sigset; - struct sigaction act; + /* Open fifos (must be created by client). */ + if (!open_fifos(fifos)) { + stack; + return; + } - memset(&act, 0, sizeof(act)); - act.sa_handler = sig_alarm; - sigaction(SIGALRM, &act, NULL); - sigfillset(&sigset); - pthread_sigmask(SIG_BLOCK, &sigset, NULL); + /* Exit after last unregister. */ + do { + process_request(fifos, &msg); + } while (!list_empty(&thread_registry)); } +/* Fork into the background and detach from our parent process. */ static int daemonize(void) { + pid_t pid; + + if ((pid = fork()) == -1) { + log_err("%s: fork", __func__); + return 0; + } else if (pid > 0) /* Parent. */ + return 2; + +log_print("daemonizing 2nd...\n"); + setsid(); - if (chdir("/")) - return -EXIT_CHDIR_FAILURE; + if (chdir("/")) { + log_err("%s: chdir /", __func__); + return 0; + } -/* FIXME: activate again after we're done with tracing. - if ((close(STDIN_FILENO) < 0) || - (close(STDOUT_FILENO) < 0) || - (close(STDERR_FILENO) < 0)) - return -EXIT_DESC_CLOSE_FAILURE; -*/ +/* REMOVEME: */ + return 1; - return 0; -} + log_print("daemonizing 3rd...\n"); -static int lock_pidfile(void) -{ - int lf; - char pidfile[] = "/var/run/dmeventd.pid"; + /* Detach ourself. */ + if (close(STDIN_FILENO) == -1 || + close(STDOUT_FILENO) == -1 || + close(STDERR_FILENO) == -1) + return 0; - if ((lf = open(pidfile, O_CREAT | O_RDWR, 0644)) < 0) - return -EXIT_OPEN_PID_FAILURE; +log_print("daemonized\n"); - if (flock(lf, LOCK_EX | LOCK_NB) < 0) - return -EXIT_LOCKFILE_INUSE; + return 1; +} - if (!storepid(lf)) - return -EXIT_FAILURE; +/* Init thread signal handling. */ +#define HANGUP SIGHUP +static void init_thread_signals(int hup) +{ + sigset_t sigset; + + sigfillset(&sigset); - return 0; + if (hup) + sigdelset(&sigset, HANGUP); + + pthread_sigmask(SIG_SETMASK, &sigset, NULL); } -void dmeventd(void) +int main(void) { - int ret; struct fifos fifos; struct sys_log logdata = {DAEMON_NAME, LOG_DAEMON}; + /* Make sure, parent accepts HANGUP signal. */ + init_thread_signals(1); + + switch (daemonize()) { + case 1: /* Child. */ + /* Try to lock pidfile. */ + if (!lock()) { + fprintf(stderr, "daemon already running\n"); + break; + } - if ((ret = daemonize())) - exit(-ret); + init_thread_signals(0); + kill(getppid(), HANGUP); - /* FIXME: set daemon name. */ - // set_name(); + multilog_clear_logging(); + multilog_add_type(std_syslog, &logdata); + multilog_init_verbose(std_syslog, _LOG_DEBUG); + multilog_async(1); - if ((ret = lock_pidfile())) - exit(-ret); + init_fifos(&fifos); + pthread_mutex_init(&mutex, NULL); - init_thread_signals(); + if (!storepid(lf)) { + stack; + exit(EXIT_FAILURE); + } - multilog_clear_logging(); - multilog_add_type(std_syslog, &logdata); - multilog_init_verbose(std_syslog, _LOG_DEBUG); - multilog_async(1); + if (mlockall(MCL_FUTURE) == -1) { + stack; + exit(EXIT_FAILURE); + } - if ((ret = init_fifos(&fifos))) - exit(-ret); + /* Communication thread runs forever... */ + comm_thread(&fifos); - pthread_mutex_init(&mutex, NULL); + /* We should never get here. */ + munlockall(); + pthread_mutex_destroy(&mutex); - if (mlockall(MCL_FUTURE) == -1) + case 0: /* Error (either on daemonize() or on comm_thread() return. */ + unlock(); exit(EXIT_FAILURE); + break; - if ((ret = open_fifos(&fifos))) - exit(-ret); - - /* Signal parent, letting them know we are ready to go. */ - kill(getppid(), SIGUSR1); - - /* - * We exit when there are no more devices to watch. - * That is, when the last unregister happens. - */ - do { - process_request(&fifos); - } while(!list_empty(&thread_registry)); - - munlockall(); - pthread_mutex_destroy(&mutex); + case 2: /* Parent. */ + wait(NULL); + break; + } exit(EXIT_SUCCESS); } diff --git a/dmeventd/mktestdevices b/dmeventd/old/mktestdevices similarity index 100% rename from dmeventd/mktestdevices rename to dmeventd/old/mktestdevices diff --git a/dmeventd/noop.c b/dmeventd/old/noop.c similarity index 100% rename from dmeventd/noop.c rename to dmeventd/old/noop.c diff --git a/dmeventd/old/noop.d b/dmeventd/old/noop.d new file mode 100644 index 0000000..d6d912c --- /dev/null +++ b/dmeventd/old/noop.d @@ -0,0 +1 @@ +noop.o noop.d noop.pot: ../make.tmpl ../VERSION Makefile ../include/.symlinks_created noop.c ../include/libdm-event.h ../include/libmultilog.h diff --git a/include/.symlinks b/include/.symlinks index 696e46d..538b8ef 100644 --- a/include/.symlinks +++ b/include/.symlinks @@ -1,5 +1,5 @@ ../lib/libdevmapper.h ../lib/libdm-file.h -../lib/libdm-event.h +../dmeventd/libdevmapper-event.h ../multilog/libmultilog.h ../po/pogen.h diff --git a/lib/Makefile.in b/lib/Makefile.in index d90a77b..f2c8df3 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -17,14 +17,6 @@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ interface = @interface@ -ifeq ("@DMEVENTD@", "yes") - SUBDIRS += event -endif - -ifeq ($(MAKECMDGOALS),distclean) - SUBDIRS += event -endif - SOURCES =\ datastruct/bitset.c \ datastruct/hash.c \ diff --git a/lib/event/Makefile.in b/lib/event/Makefile.in deleted file mode 100644 index 3fb7c47..0000000 --- a/lib/event/Makefile.in +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright (C) 2005 Red Hat, Inc. All rights reserved. -# -# This file is part of the device-mapper userspace tools. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions -# of the GNU Lesser General Public License v.2.1. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -interface = @interface@ - -SOURCES = libdm-event.c \ - dmeventd.c - -LIB_STATIC = libdmevent.a - -ifeq ("@LIB_SUFFIX@","dylib") - LIB_SHARED = libdmevent.dylib -else - LIB_SHARED = libdmevent.so -endif - -CLDFLAGS += -ldl -ldevmapper -lpthread - -include ../../make.tmpl - -.PHONY: install_dynamic install_static - -INSTALL_TYPE = install_dynamic - -ifeq ("@STATIC_LINK@", "yes") - INSTALL_TYPE += install_static -endif - -install: $(INSTALL_TYPE) - -install_dynamic: libdmevent.$(LIB_SUFFIX) - $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \ - $(libdir)/libdmevent.$(LIB_SUFFIX).$(LIB_VERSION) - $(LN_S) -f libdmevent.$(LIB_SUFFIX).$(LIB_VERSION) \ - $(libdir)/libdmevent.$(LIB_SUFFIX) - $(INSTALL) -D $(OWNER) $(GROUP) -m 444 ../libdm-event.h \ - $(includedir)/libdm-event.h - -install_static: libdmevent.a - $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \ - $(libdir)/libdmevent.a.$(LIB_VERSION) - $(LN_S) -f libdmevent.a.$(LIB_VERSION) $(libdir)/libdmevent.a - diff --git a/lib/libdm-event.h b/lib/libdm-event.h deleted file mode 100644 index d92eb71..0000000 --- a/lib/libdm-event.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2005 Red Hat, Inc. All rights reserved. - * - * This file is part of the device-mapper userspace tools. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU Lesser General Public License v.2.1. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef LIB_DMEVENT_H -#define LIB_DMEVENT_H - -#include "list.h" - -#include - -#define DAEMON "/sbin/dmeventd" -#define LOCKFILE "/var/lock/dmeventd" -#define FIFO_CLIENT "/var/run/dmeventd-client" -#define FIFO_SERVER "/var/run/dmeventd-server" -#define PIDFILE "/var/run/dmeventd.pid" - -#define DEFAULT_TIMEOUT 10 -/* Commands for the daemon passed in the message below. */ -enum dmeventd_command { - CMD_ACTIVE = 1, - CMD_REGISTER_FOR_EVENT, - CMD_UNREGISTER_FOR_EVENT, - CMD_GET_REGISTERED_DEVICE, - CMD_GET_NEXT_REGISTERED_DEVICE, - CMD_SET_TIMEOUT, - CMD_GET_TIMEOUT, -}; - -/* Message passed between client and daemon. */ -struct daemon_message { - union { - unsigned int cmd; - int status; - } opcode; - char msg[252]; -} __attribute__((packed)); - -/* Fifos for client/daemon communication. */ -struct fifos { - int client; - int server; - const char *client_path; - const char *server_path; -}; - -/* Event type definitions. */ -enum event_type { - SINGLE = 0x01, /* Report multiple errors just once. */ - MULTI = 0x02, /* Report all of them. */ - SECTOR_ERROR = 0x04, /* Failure on a particular sector. */ - DEVICE_ERROR = 0x08, /* Device failure. */ - PATH_ERROR = 0x10, /* Failure on an io path. */ - ADAPTOR_ERROR = 0x20, /* Failure off a host adaptor. */ - SYNC_STATUS = 0x40, /* Mirror synchronization completed/failed. */ - TIMEOUT = 0x80, /* Timeout has occured */ -}; -#define ALL_ERRORS (SECTOR_ERROR | DEVICE_ERROR | PATH_ERROR | ADAPTOR_ERROR) - -/* Prototypes for event lib interface. */ -int dm_register_for_event(char *dso_name, char *device, enum event_type events); -int dm_unregister_for_event(char *dso_name, char *device, - enum event_type events); -int dm_get_registered_device(char **dso_name, char **device, - enum event_type *events, int next); -int dm_set_event_timeout(char *device, uint32_t timeout); -int dm_get_event_timeout(char *device, uint32_t *timeout); - -/* Prototypes for DSO interface. */ -void process_event(char *device, enum event_type event); -int register_device(char *device); -int unregister_device(char *device); - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ -- 2.43.5