]> sourceware.org Git - dm.git/commitdiff
Lots of dmeventd-related changes.
authorAlasdair Kergon <agk@redhat.com>
Thu, 11 Jan 2007 21:54:51 +0000 (21:54 +0000)
committerAlasdair Kergon <agk@redhat.com>
Thu, 11 Jan 2007 21:54:51 +0000 (21:54 +0000)
WHATS_NEW
configure
configure.in
dmeventd/.exported_symbols
dmeventd/dmeventd.c
dmeventd/libdevmapper-event.c
dmeventd/libdevmapper-event.h
include/configure.h.in
lib/.exported_symbols
lib/libdevmapper.h
lib/libdm-string.c

index fa6fc15b973be3d79eea6d2501186506a64b832d..52a9fa0500c95de41c8c8adf4dbd6f2c95bfe812 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,8 +1,9 @@
 Version 1.02.14 - 
 =============================
+  Add dm_saprintf().
   Use CFLAGS when linking so mixed sparc builds can supply -m64.
   Add dm_tree_use_no_flush_suspend().
-  Lots of dmevent changes.
+  Lots of dmevent changes including revised interface.
   Export dm_basename().
   Cope with a trailing space when comparing tables prior to possible reload.
   Fix dmeventd to cope if monitored device disappears.
index be99a46ba4d2ae6fb92f4148c60aeb61d2d9f079..3f3adbcccb21ffb63b599357776965128cce777d 100755 (executable)
--- a/configure
+++ b/configure
@@ -865,12 +865,13 @@ Optional Packages:
   --with-device-uid=UID   Set the owner used for new device nodes [UID=0]
   --with-device-gid=UID   Set the group used for new device nodes [GID=0]
   --with-device-mode=MODE Set the mode used for new device nodes [MODE=0600]
-  --with-optimisation=OPT C optimisation flag OPT=-O2
-  --with-localedir=DIR    Translation files in DIR PREFIX/share/locale
+  --with-optimisation=OPT C optimisation flag [OPT=-O2]
+  --with-localedir=DIR    Translation files in DIR [PREFIX/share/locale]
   --with-kernel-dir=DIR   linux kernel source in DIR
   --with-kernel-version=VERSION   linux kernel version
-  --with-tmp-dir=DIR      temp directory to make kernel patches /tmp/kerndiff
-  --with-interface=IFACE  Choose kernel interface (ioctl or fs) ioctl
+  --with-tmp-dir=DIR      temp dir to make kernel patches [/tmp/kerndiff]
+  --with-interface=IFACE  Choose kernel interface (ioctl or fs) [ioctl]
+  --with-dmeventd-pidfile=PATH    dmeventd pidfile [/var/run/dmeventd.pid]
 
 Some influential environment variables:
   CC          C compiler command
@@ -6039,6 +6040,25 @@ fi
 ################################################################################
 
 
+if test "$DMEVENTD" = yes; then
+
+# Check whether --with-dmeventd-pidfile or --without-dmeventd-pidfile was given.
+if test "${with_dmeventd_pidfile+set}" = set; then
+  withval="$with_dmeventd_pidfile"
+   cat >>confdefs.h <<_ACEOF
+#define DMEVENTD_PIDFILE "$withval"
+_ACEOF
+
+else
+   cat >>confdefs.h <<_ACEOF
+#define DMEVENTD_PIDFILE "/var/run/dmeventd.pid"
+_ACEOF
+
+fi;
+fi
+################################################################################
+
+
 
 
 
index 8d52822ad195c7879af49227898a4d9b4c87dfea..4e5a4ce7aec709d6603b739860d711830ee6185b 100644 (file)
@@ -168,7 +168,7 @@ fi
 dnl -- Override optimisation
 AC_MSG_CHECKING(for C optimisation flag)
 AC_ARG_WITH(optimisation,
-  [  --with-optimisation=OPT C optimisation flag [OPT=-O2] ],
+  [  --with-optimisation=OPT C optimisation flag [[OPT=-O2]] ],
   [ COPTIMISE_FLAG="$withval" ])
 AC_MSG_RESULT($COPTIMISE_FLAG)
 
@@ -262,7 +262,7 @@ if test x$INTL = xyes; then
        fi;
 
        AC_ARG_WITH(localedir,
-                   [  --with-localedir=DIR    Translation files in DIR [PREFIX/share/locale]],
+                   [  --with-localedir=DIR    Translation files in DIR [[PREFIX/share/locale]] ],
                    [ LOCALEDIR="$withval" ],
                    [ LOCALEDIR='${prefix}/share/locale' ])
 fi
@@ -328,7 +328,7 @@ AC_MSG_RESULT($kernelvsn)
 ################################################################################
 dnl -- Temporary directory for kernel diffs
 AC_ARG_WITH(tmp-dir,
-  [  --with-tmp-dir=DIR      temp directory to make kernel patches [/tmp/kerndiff]],
+  [  --with-tmp-dir=DIR      temp dir to make kernel patches [[/tmp/kerndiff]] ],
   [ tmpdir="$withval" ],
   [ tmpdir=/tmp/kerndiff ])
 if test "${with_tmp_dir+set}" = set; then
@@ -342,7 +342,7 @@ fi
 dnl -- which kernel interface to use (ioctl or fs)
 AC_MSG_CHECKING(for kernel interface choice)
 AC_ARG_WITH(interface,
-  [  --with-interface=IFACE  Choose kernel interface (ioctl or fs) [ioctl]],
+  [  --with-interface=IFACE  Choose kernel interface (ioctl or fs) [[ioctl]] ],
   [ interface="$withval" ],
   [ interface=ioctl ])
 if [[ "x$interface" != xfs -a "x$interface" != xioctl ]];
@@ -358,6 +358,15 @@ else
 fi
 
 
+################################################################################
+dnl -- dmeventd pidfile path
+AH_TEMPLATE(DMEVENTD_PIDFILE, [Path to dmeventd pidfile.])
+if test "$DMEVENTD" = yes; then
+       AC_ARG_WITH(dmeventd-pidfile,
+                   [  --with-dmeventd-pidfile=PATH    dmeventd pidfile [[/var/run/dmeventd.pid]] ],
+                   [ AC_DEFINE_UNQUOTED(DMEVENTD_PIDFILE,"$withval") ],
+                   [ AC_DEFINE_UNQUOTED(DMEVENTD_PIDFILE,"/var/run/dmeventd.pid") ])
+fi
 ################################################################################
 AC_SUBST(usrlibdir)
 AC_SUBST(JOBS)
index 75779d02b0c60fb9af32818bc8393903a195dcf3..2e0af3b1b197e10425c7896ae7d2115533f5b5df 100644 (file)
@@ -1,5 +1,16 @@
+dm_event_handler_create
+dm_event_handler_destroy
+dm_event_handler_set_dso
+dm_event_handler_set_name
+dm_event_handler_set_uuid
+dm_event_handler_set_major
+dm_event_handler_set_minor
+dm_event_handler_set_events
+dm_event_handler_get_dso
+dm_event_handler_get_name
+dm_event_handler_get_uuid
+dm_event_handler_get_major
+dm_event_handler_get_minor
+dm_event_handler_get_events
 dm_event_register
 dm_event_unregister
-dm_event_get_registered_device
-dm_event_set_timeout
-dm_event_get_timeout
index 2c9277984b4bb0413014c51c0dabdfedb1e5329b..59b058486dc9846ee2c8eceebd635dc3cbdcfd39 100644 (file)
@@ -19,6 +19,7 @@
 #define _GNU_SOURCE
 #define _FILE_OFFSET_BITS 64
 
+#include "configure.h"
 #include "libdevmapper.h"
 #include "libdevmapper-event.h"
 #include "list.h"
 #include <sys/resource.h>
 #include <unistd.h>
 #include <stdarg.h>
-#include <arpa/inet.h> /* for htonl, ntohl */
+#include <arpa/inet.h>         /* for htonl, ntohl */
 
 #ifdef linux
 #include <malloc.h>
 #endif
 
-/* We must use syslog for now, because multilog is not yet implemented */
+/* FIXME We use syslog for now, because multilog is not yet implemented */
 #include <syslog.h>
 
-static volatile sig_atomic_t _exit_now = 0; /* set to '1' when signal is given to exit */
-static volatile sig_atomic_t _thread_registries_empty = 1; /* registries are empty initially */
+static volatile sig_atomic_t _exit_now = 0;    /* set to '1' when signal is given to exit */
+static volatile sig_atomic_t _thread_registries_empty = 1;     /* registries are empty initially */
 
 /* List (un)link macros. */
 #define        LINK(x, head)           list_add(head, &(x)->list)
@@ -78,19 +79,24 @@ static pthread_mutex_t _global_mutex;
 struct dso_data {
        struct list list;
 
-       char *dso_name; /* DSO name (eg, "evms", "dmraid", "lvm2"). */
+       char *dso_name;         /* DSO name (eg, "evms", "dmraid", "lvm2"). */
 
-       void *dso_handle; /* Opaque handle as returned from dlopen(). */
-       unsigned int ref_count; /* Library reference count. */
+       void *dso_handle;       /* Opaque handle as returned from dlopen(). */
+       unsigned int ref_count; /* Library reference count. */
 
        /*
         * Event processing.
         *
-        * The DSO can do whatever appropriate steps if an event happens
-        * such as changing the mapping in case a mirror fails, update
-        * the application metadata etc.
+        * The DSO can do whatever appropriate steps if an event
+        * happens such as changing the mapping in case a mirror
+        * fails, update the application metadata etc.
+        *
+        * This function gets a dm_task that is a result of
+        * DM_DEVICE_WAITEVENT ioctl (results equivalent to
+        * DM_DEVICE_STATUS). It should not destroy it.
+        * The caller must dispose of the task.
         */
-       void (*process_event)(const char *device, enum dm_event_type event);
+       void (*process_event)(struct dm_task *dmt, enum dm_event_type event);
 
        /*
         * Device registration.
@@ -100,7 +106,8 @@ struct dso_data {
         * the process_event() function is sane (eg, read metadata
         * and activate a mapping).
         */
-       int (*register_device)(const char *device);
+       int (*register_device)(const char *device, const char *uuid, int major,
+                              int minor);
 
        /*
         * Device unregistration.
@@ -109,14 +116,15 @@ struct dso_data {
         * for events, the DSO can recognize this and carry out appropriate
         * steps (eg, deactivate mapping, metadata update).
         */
-       int (*unregister_device)(const char *device);
+       int (*unregister_device)(const char *device, const char *uuid,
+                                int major, int minor);
 };
 static LIST_INIT(_dso_registry);
 
 /* Structure to keep parsed register variables from client message. */
 struct message_data {
        char *dso_name;         /* Name of DSO. */
-       char *device_path;      /* Mapped device path. */
+       char *device_uuid;      /* Mapped device path. */
        union {
                char *str;      /* Events string as fetched from message. */
                enum dm_event_type field;       /* Events bitfield. */
@@ -139,15 +147,19 @@ struct thread_status {
 
        pthread_t thread;
 
-       struct dso_data *dso_data;/* DSO this thread accesses. */
-       
-       char *device_path;      /* Mapped device path. */
+       struct dso_data *dso_data;      /* DSO this thread accesses. */
+
+       struct {
+               char *uuid;
+               char *name;
+               int major, minor;
+       } device;
        uint32_t event_nr;      /* event number */
        int processing;         /* Set when event is being processed */
        int status;             /* running/shutdown/done */
        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. */
+       enum dm_event_type current_events;      /* bitfield for occured events. */
+       struct dm_task *current_task;
        time_t next_time;
        uint32_t timeout;
        struct list timeout_list;
@@ -168,13 +180,16 @@ static struct thread_status *alloc_thread_status(struct message_data *data,
 
        if (ret) {
                if (!memset(ret, 0, sizeof(*ret)) ||
-                   !(ret->device_path = dm_strdup(data->device_path))) {
+                   !(ret->device.uuid = dm_strdup(data->device_uuid))) {
                        dm_free(ret);
                        ret = NULL;
                } else {
+                       ret->current_task = NULL;
+                       ret->device.name = NULL;
+                       ret->device.major = ret->device.minor = 0;
                        ret->dso_data = dso_data;
-                       ret->events   = data->events.field;
-                       ret->timeout  = data->timeout.secs;
+                       ret->events = data->events.field;
+                       ret->timeout = data->timeout.secs;
                        list_init(&ret->timeout_list);
                }
        }
@@ -184,7 +199,8 @@ static struct thread_status *alloc_thread_status(struct message_data *data,
 
 static void free_thread_status(struct thread_status *thread)
 {
-       dm_free(thread->device_path);
+       dm_free(thread->device.uuid);
+       dm_free(thread->device.name);
        dm_free(thread);
 }
 
@@ -213,9 +229,10 @@ static void free_dso_data(struct dso_data *data)
 
 /*
  * Fetch a string off src and duplicate it into *ptr.
- * Pay attention to 0 lenght strings.
+ * Pay attention to zero-length strings.
  */
-/* FIXME: move to separate module to share with the client lib. */
+/* FIXME? move to libdevmapper to share with the client lib (need to
+   make delimiter a parameter then) */
 static const char delimiter = ' ';
 static int fetch_string(char **ptr, char **src)
 {
@@ -250,8 +267,8 @@ static void free_message(struct message_data *message_data)
        if (message_data->dso_name)
                dm_free(message_data->dso_name);
 
-       if (message_data->device_path)
-               dm_free(message_data->device_path);
+       if (message_data->device_uuid)
+               dm_free(message_data->device_uuid);
 
 }
 
@@ -270,7 +287,7 @@ static int parse_message(struct message_data *message_data)
         * 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->device_uuid, &p) &&
            fetch_string(&message_data->events.str, &p) &&
            fetch_string(&message_data->timeout.str, &p)) {
                if (message_data->events.str) {
@@ -287,7 +304,7 @@ static int parse_message(struct message_data *message_data)
                        uint32_t secs = atoi(message_data->timeout.str);
                        dm_free(message_data->timeout.str);
                        message_data->timeout.secs = secs ? secs :
-                                                           DM_EVENT_DEFAULT_TIMEOUT;
+                           DM_EVENT_DEFAULT_TIMEOUT;
                }
 
                ret = 1;
@@ -330,23 +347,43 @@ static int storepid(int lf)
        return 1;
 }
 
-/* FIXME This is unreliable: should use DM_DEVICE_INFO ioctl instead. */
 /* Check, if a device exists. */
-static int device_exists(char *device)
+static int fill_device_data(struct thread_status *ts)
 {
-       struct stat st_buf;
-       char path2[PATH_MAX];
+       struct dm_task *dmt;
+       struct dm_info dmi;
 
-       if (!device || !*device)
+       if (!ts->device.uuid)
                return 0;
 
-       if (device[0] == '/') /* absolute path */
-               return !stat(device, &st_buf) && S_ISBLK(st_buf.st_mode);
+       ts->device.name = NULL;
+       ts->device.major = ts->device.minor = 0;
 
-       if (PATH_MAX <= snprintf(path2, PATH_MAX, "%s/%s", dm_dir(), device))
+       dmt = dm_task_create(DM_DEVICE_INFO);
+       if (!dmt)
                return 0;
 
-       return !stat(path2, &st_buf) && S_ISBLK(st_buf.st_mode);
+       dm_task_set_uuid(dmt, ts->device.uuid);
+       if (!dm_task_run(dmt))
+               goto fail;
+
+       ts->device.name = dm_strdup(dm_task_get_name(dmt));
+       if (!ts->device.name)
+               goto fail;
+
+       if (!dm_task_get_info(dmt, &dmi))
+               goto fail;
+
+       ts->device.major = dmi.major;
+       ts->device.minor = dmi.minor;
+
+       dm_task_destroy(dmt);
+       return 1;
+
+      fail:
+       dm_task_destroy(dmt);
+       dm_free(ts->device.name);
+       return 0;
 }
 
 /*
@@ -359,13 +396,12 @@ static struct thread_status *lookup_thread_status(struct message_data *data)
        struct thread_status *thread;
 
        list_iterate_items(thread, &_thread_registry)
-               if (!strcmp(data->device_path, thread->device_path))
-                       return thread;
+           if (!strcmp(data->device_uuid, thread->device.uuid))
+               return thread;
 
        return NULL;
 }
 
-
 /* Cleanup at exit. */
 static void exit_dm_lib(void)
 {
@@ -392,11 +428,10 @@ static void *timeout_thread(void *unused)
        while (!list_empty(&timeout_registry)) {
                struct thread_status *thread;
 
-               timeout.tv_sec = (time_t)-1;
+               timeout.tv_sec = (time_t) -1;
                curr_time = time(NULL);
 
-               list_iterate_items_gen(thread, &timeout_registry,
-                                      timeout_list) {
+               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);
@@ -406,7 +441,8 @@ static void *timeout_thread(void *unused)
                                timeout.tv_sec = thread->next_time;
                }
 
-               pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex, &timeout);
+               pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex,
+                                      &timeout);
        }
 
        pthread_cleanup_pop(1);
@@ -452,7 +488,7 @@ static void unregister_for_timeout(struct thread_status *thread)
 }
 
 static void no_intr_log(int level, const char *file, int line,
-                      const char *f, ...)
+                       const char *f, ...)
 {
        va_list ap;
 
@@ -491,23 +527,22 @@ static sigset_t unblock_sigalrm(void)
 #define DM_WAIT_FATAL 2
 
 /* Wait on a device until an event occurs. */
-static int event_wait(struct thread_status *thread)
+static int event_wait(struct thread_status *thread, struct dm_task **task)
 {
        sigset_t set;
        int ret = DM_WAIT_RETRY;
-/*
-       void *next = NULL;
-       char *params, *target_type;
-       uint64_t start, length;
-*/
        struct dm_task *dmt;
        struct dm_info info;
 
+       *task = 0;
+
        if (!(dmt = dm_task_create(DM_DEVICE_WAITEVENT)))
                return DM_WAIT_RETRY;
 
-       if (!(ret = dm_task_set_name(dmt, dm_basename(thread->device_path))) ||
-           !(ret = dm_task_set_event_nr(dmt, thread->event_nr)))
+       thread->current_task = dmt;
+
+       if (!dm_task_set_uuid(dmt, thread->device.uuid) ||
+           !dm_task_set_event_nr(dmt, thread->event_nr))
                goto out;
 
        /*
@@ -517,31 +552,21 @@ static int event_wait(struct thread_status *thread)
        set = unblock_sigalrm();
        dm_log_init(no_intr_log);
        errno = 0;
-       if ((ret = dm_task_run(dmt))) {
+       if (dm_task_run(dmt)) {
                thread->current_events |= DM_EVENT_DEVICE_ERROR;
                ret = DM_WAIT_INTR;
 
-               /*
-                * 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 = DM_WAIT_INTR;
-               thread->processed_events = 0;
        } else {
-               /* FIXME replace with log_* macro */
                syslog(LOG_NOTICE, "dm_task_run failed, errno = %d, %s",
                       errno, strerror(errno));
                if (errno == ENXIO) {
-                       /* FIXME replace with log_* macro */
-                       syslog(LOG_ERR, "%s disappeared, detaching", thread->device_path);
+                       syslog(LOG_ERR, "%s disappeared, detaching",
+                              thread->device.name);
                        ret = DM_WAIT_FATAL;
                }
        }
@@ -549,8 +574,12 @@ static int event_wait(struct thread_status *thread)
        pthread_sigmask(SIG_SETMASK, &set, NULL);
        dm_log_init(NULL);
 
-   out:
-       dm_task_destroy(dmt);
+      out:
+       if (ret == DM_WAIT_FATAL || ret == DM_WAIT_RETRY) {
+               dm_task_destroy(dmt);
+               thread->current_task = NULL;
+       } else
+               *task = dmt;
 
        return ret;
 }
@@ -558,20 +587,25 @@ static int event_wait(struct thread_status *thread)
 /* Register a device with the DSO. */
 static int do_register_device(struct thread_status *thread)
 {
-       return thread->dso_data->register_device(thread->device_path);
+       return thread->dso_data->register_device(thread->device.name,
+                                                thread->device.uuid,
+                                                thread->device.major,
+                                                thread->device.minor);
 }
 
 /* Unregister a device with the DSO. */
 static int do_unregister_device(struct thread_status *thread)
 {
-       return thread->dso_data->unregister_device(thread->device_path);
+       return thread->dso_data->unregister_device(thread->device.name,
+                                                  thread->device.uuid,
+                                                  thread->device.major,
+                                                  thread->device.minor);
 }
 
 /* Process an event in the DSO. */
-static void do_process_event(struct thread_status *thread)
+static void do_process_event(struct thread_status *thread, struct dm_task *task)
 {
-       thread->dso_data->process_event(thread->device_path,
-                                       thread->current_events);
+       thread->dso_data->process_event(task, thread->current_events);
 }
 
 /* Thread cleanup handler to unregister device. */
@@ -581,7 +615,10 @@ static void monitor_unregister(void *arg)
 
        if (!do_unregister_device(thread))
                syslog(LOG_ERR, "%s: %s unregister failed\n", __func__,
-                       thread->device_path);
+                      thread->device.name);
+       if (thread->current_task)
+               dm_task_destroy(thread->current_task);
+       thread->current_task = NULL;
 }
 
 /* Device monitoring thread. */
@@ -589,6 +626,7 @@ static void *monitor_thread(void *arg)
 {
        struct thread_status *thread = arg;
        int wait_error = 0;
+       struct dm_task *task;
 
        pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
        pthread_cleanup_push(monitor_unregister, thread);
@@ -602,14 +640,18 @@ static void *monitor_thread(void *arg)
        while (1) {
                thread->current_events = 0;
 
-               wait_error = event_wait(thread);
+               wait_error = event_wait(thread, &task);
                if (wait_error == DM_WAIT_RETRY)
                        continue;
 
-               /* FIXME Give a DSO a chance to clean up. */
                if (wait_error == DM_WAIT_FATAL)
                        break;
 
+               /*
+                * We know that wait succeeded and stored a
+                * pointer to dm_task with device status into task.
+                */
+
                /*
                 * Check against filter.
                 *
@@ -617,10 +659,6 @@ static void *monitor_thread(void *arg)
                 * the device got registered for those events AND
                 * those events haven't been processed yet, call
                 * the DSO's process_event() handler.
-                *
-                * FIXME: when does processed_events get cleared?  What if
-                * the same type of event happens later... after the first
-                * was handled properly?
                 */
                lock_mutex();
                if (thread->status == DM_THREAD_SHUTDOWN) {
@@ -629,17 +667,21 @@ static void *monitor_thread(void *arg)
                }
                unlock_mutex();
 
-               if (thread->events &
-                   thread->current_events &
-                   ~thread->processed_events) {
+               if (thread->events & thread->current_events) {
                        lock_mutex();
                        thread->processing = 1;
                        unlock_mutex();
-                       do_process_event(thread);
-                       thread->processed_events |= thread->current_events;
+
+                       do_process_event(thread, task);
+                       dm_task_destroy(task);
+                       thread->current_task = NULL;
+
                        lock_mutex();
                        thread->processing = 0;
                        unlock_mutex();
+               } else {
+                       dm_task_destroy(task);
+                       thread->current_task = NULL;
                }
        }
 
@@ -647,12 +689,12 @@ static void *monitor_thread(void *arg)
        thread->status = DM_THREAD_DONE;
        unlock_mutex();
 
-       pthread_cleanup_pop(0);
+       pthread_cleanup_pop(1);
+
        return NULL;
 }
 
 /* Create a device monitoring thread. */
-/* FIXME: call this with mutex hold ? */
 static int create_thread(struct thread_status *thread)
 {
        return pthread_create(&thread->thread, NULL, monitor_thread, thread);
@@ -691,11 +733,11 @@ static struct dso_data *lookup_dso(struct message_data *data)
        lock_mutex();
 
        list_iterate_items(dso_data, &_dso_registry)
-               if (!strcmp(data->dso_name, dso_data->dso_name)) {
-                       lib_get(dso_data);
-                       ret = dso_data;
-                       break;
-               }
+           if (!strcmp(data->dso_name, dso_data->dso_name)) {
+               lib_get(dso_data);
+               ret = dso_data;
+               break;
+       }
 
        unlock_mutex();
 
@@ -714,12 +756,12 @@ static int lookup_symbol(void *dl, struct dso_data *data,
 
 static int lookup_symbols(void *dl, struct dso_data *data)
 {
-       return lookup_symbol(dl, data, (void*) &data->process_event,
+       return lookup_symbol(dl, data, (void *) &data->process_event,
                             "process_event") &&
-              lookup_symbol(dl, data, (void*) &data->register_device,
-                            "register_device") &&
-              lookup_symbol(dl, data, (void*) &data->unregister_device,
-                            "unregister_device");
+           lookup_symbol(dl, data, (void *) &data->register_device,
+                         "register_device") &&
+           lookup_symbol(dl, data, (void *) &data->unregister_device,
+                         "unregister_device");
 }
 
 /* Load an application specific DSO. */
@@ -728,13 +770,13 @@ static struct dso_data *load_dso(struct message_data *data)
        void *dl;
        struct dso_data *ret = NULL;
 
-       if (!(dl = dlopen(data->dso_name, RTLD_NOW))){
+       if (!(dl = dlopen(data->dso_name, RTLD_NOW))) {
                const char *dlerr = dlerror();
-               syslog(LOG_ERR, "dmeventd %s dlopen failed: %s", data->dso_name, dlerr);
-               char buf[1024]; /* FIXME */
-               snprintf(buf, 1024, "%s dlopen failed: %s", data->dso_name, dlerr);
-               data->msg->size = strlen(buf) + 1;
-               data->msg->data = dm_strdup(buf);
+               syslog(LOG_ERR, "dmeventd %s dlopen failed: %s", data->dso_name,
+                      dlerr);
+               data->msg->size =
+                   dm_saprintf(&(data->msg->data), "%s dlopen failed: %s",
+                               data->dso_name, dlerr);
                return NULL;
        }
 
@@ -763,7 +805,6 @@ static struct dso_data *load_dso(struct message_data *data)
        return ret;
 }
 
-
 /* Return success on daemon active check. */
 static int active(struct message_data *message_data)
 {
@@ -782,16 +823,9 @@ static int register_for_event(struct message_data *message_data)
        struct thread_status *thread, *thread_new = NULL;
        struct dso_data *dso_data;
 
-       if (!device_exists(message_data->device_path)) {
-               stack;
-               ret = -ENODEV;
-               goto out;
-       }
-
        if (!(dso_data = lookup_dso(message_data)) &&
            !(dso_data = load_dso(message_data))) {
                stack;
-/* FIXME */
 #ifdef ELIBACC
                ret = -ELIBACC;
 #else
@@ -799,7 +833,7 @@ static int register_for_event(struct message_data *message_data)
 #endif
                goto out;
        }
-               
+
        /* Preallocate thread status struct to avoid deadlock. */
        if (!(thread_new = alloc_thread_status(message_data, dso_data))) {
                stack;
@@ -807,15 +841,17 @@ static int register_for_event(struct message_data *message_data)
                goto out;
        }
 
+       if (!fill_device_data(thread_new)) {
+               stack;
+               ret = -ENODEV;
+               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)))
                        goto out;
 
@@ -836,7 +872,7 @@ static int register_for_event(struct message_data *message_data)
        /* 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
@@ -847,7 +883,7 @@ static int register_for_event(struct message_data *message_data)
        if (thread->events & DM_EVENT_TIMEOUT)
                ret = -register_for_timeout(thread);
 
-   out:
+      out:
        /*
         * Deallocate thread status after releasing
         * the lock in case we haven't used it.
@@ -894,7 +930,7 @@ static int unregister_for_event(struct message_data *message_data)
        }
        unlock_mutex();
 
-   out:
+      out:
        return ret;
 }
 
@@ -906,42 +942,40 @@ static int unregister_for_event(struct message_data *message_data)
 static int registered_device(struct message_data *message_data,
                             struct thread_status *thread)
 {
-       char test[1];
        struct dm_event_daemon_message *msg = message_data->msg;
 
        const char *fmt = "%s %s %u";
        const char *dso = thread->dso_data->dso_name;
-       const char *dev = thread->device_path;
-       unsigned events = ((thread->status == DM_THREAD_RUNNING) && (thread->events)) ?
-                         thread->events : thread->events | DM_EVENT_REGISTRATION_PENDING;
+       const char *dev = thread->device.uuid;
+       unsigned events = ((thread->status == DM_THREAD_RUNNING)
+                          && (thread->events)) ? thread->events : thread->
+           events | DM_EVENT_REGISTRATION_PENDING;
 
        if (msg->data)
                dm_free(msg->data);
 
-       msg->size = snprintf(test, 1, fmt, dso, dev, events);
-       msg->data = dm_malloc(msg->size);
-       snprintf(msg->data, msg->size, fmt, dso, dev, events);
+       msg->size = dm_saprintf(&(msg->data), fmt, dso, dev, events);
 
        unlock_mutex();
 
        return 0;
 }
 
-static int want_registered_device(char *dso_name, char *device_path,
+static int want_registered_device(char *dso_name, char *device_uuid,
                                  struct thread_status *thread)
 {
        /* If DSO names and device paths are equal. */
-       if (dso_name && device_path)
+       if (dso_name && device_uuid)
                return !strcmp(dso_name, thread->dso_data->dso_name) &&
-                      !strcmp(device_path, thread->device_path);
+                   !strcmp(device_uuid, thread->device.uuid);
 
        /* 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);
+       if (device_uuid)
+               return !strcmp(device_uuid, thread->device.uuid);
 
        return 1;
 }
@@ -955,10 +989,10 @@ static int _get_registered_device(struct message_data *message_data, int next)
 
        /* Iterate list of threads checking if we want a particular one. */
        list_iterate_items(thread, &_thread_registry)
-               if ((hit = want_registered_device(message_data->dso_name,
-                                                 message_data->device_path,
-                                                 thread)))
-                       break;
+           if ((hit = want_registered_device(message_data->dso_name,
+                                             message_data->device_uuid,
+                                             thread)))
+               break;
 
        /*
         * If we got a registered device and want the next one ->
@@ -970,15 +1004,13 @@ static int _get_registered_device(struct message_data *message_data, int 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));
+
+               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);
 
-   out:
+      out:
        unlock_mutex();
 
        return -ENOENT;
@@ -1000,7 +1032,7 @@ static int set_timeout(struct message_data *message_data)
 
        lock_mutex();
        if ((thread = lookup_thread_status(message_data)))
-               thread->timeout = message_data->timeout.secs; 
+               thread->timeout = message_data->timeout.secs;
        unlock_mutex();
 
        return thread ? 0 : -ENODEV;
@@ -1016,9 +1048,8 @@ static int get_timeout(struct message_data *message_data)
 
        lock_mutex();
        if ((thread = lookup_thread_status(message_data))) {
-               msg->data = dm_malloc(8*sizeof(uint32_t)); /* FIXME */
-               msg->size = snprintf(msg->data, 8*sizeof(uint32_t),
-                                    "%"PRIu32, thread->timeout);
+               msg->size =
+                   dm_saprintf(&(msg->data), "%" PRIu32, thread->timeout);
        } else {
                msg->data = NULL;
                msg->size = 0;
@@ -1027,7 +1058,6 @@ static int get_timeout(struct message_data *message_data)
 
        return thread ? 0 : -ENODEV;
 }
-       
 
 /* Initialize a fifos structure with path names. */
 static void init_fifos(struct dm_event_fifos *fifos)
@@ -1049,17 +1079,27 @@ static int open_fifos(struct dm_event_fifos *fifos)
                return -errno;
        }
 
-       /* FIXME Warn/abort if perms are wrong - not something to fix silently. */
+       struct stat st;
+
+       /* Warn about wrong permissions if applicable */
+       if ((!stat(fifos->client_path, &st)) && (st.st_mode & 0777) != 0600)
+               syslog(LOG_WARNING, "Fixing wrong permissions on %s",
+                      fifos->client_path);
+
+       if ((!stat(fifos->server_path, &st)) && (st.st_mode & 0777) != 0600)
+               syslog(LOG_WARNING, "Fixing wrong permissions on %s",
+                      fifos->server_path);
+
        /* If they were already there, make sure permissions are ok. */
        if (chmod(fifos->client_path, 0600)) {
                syslog(LOG_ERR, "Unable to set correct file permissions on %s",
-                         fifos->client_path);
+                      fifos->client_path);
                return -errno;
        }
 
        if (chmod(fifos->server_path, 0600)) {
                syslog(LOG_ERR, "Unable to set correct file permissions on %s",
-                         fifos->server_path);
+                      fifos->server_path);
                return -errno;
        }
 
@@ -1083,7 +1123,8 @@ static int open_fifos(struct dm_event_fifos *fifos)
  * Read message from client making sure that data is available
  * and a complete message is read.  Must not block indefinitely.
  */
-static int client_read(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
+static int client_read(struct dm_event_fifos *fifos,
+                      struct dm_event_daemon_message *msg)
 {
        struct timeval t;
        unsigned bytes = 0;
@@ -1102,22 +1143,22 @@ static int client_read(struct dm_event_fifos *fifos, struct dm_event_daemon_mess
                FD_SET(fifos->client, &fds);
                t.tv_sec = 1;
                t.tv_usec = 0;
-               ret = select(fifos->client+1, &fds, NULL, NULL, &t);
+               ret = select(fifos->client + 1, &fds, NULL, NULL, &t);
 
-               if (!ret && !bytes) /* nothing to read */
+               if (!ret && !bytes)     /* nothing to read */
                        return 0;
 
-               if (!ret)     /* trying to finish read */
+               if (!ret)       /* trying to finish read */
                        continue;
 
-               if (ret < 0)  /* error */
+               if (ret < 0)    /* error */
                        return 0;
 
                ret = read(fifos->client, buf + bytes, size - bytes);
                bytes += ret > 0 ? ret : 0;
-               if (bytes == 2*sizeof(uint32_t) && header) {
-                       msg->cmd = ntohl(*((uint32_t *)buf));
-                       msg->size = ntohl(*((uint32_t *)buf + 1));
+               if (bytes == 2 * sizeof(uint32_t) && header) {
+                       msg->cmd = ntohl(*((uint32_t *) buf));
+                       msg->size = ntohl(*((uint32_t *) buf + 1));
                        buf = msg->data = dm_malloc(msg->size);
                        size = msg->size;
                        bytes = 0;
@@ -1129,6 +1170,7 @@ static int client_read(struct dm_event_fifos *fifos, struct dm_event_daemon_mess
                if (msg->data)
                        dm_free(msg->data);
                msg->data = NULL;
+               msg->size = 0;
        }
 
        return bytes == size;
@@ -1137,18 +1179,20 @@ static int client_read(struct dm_event_fifos *fifos, struct dm_event_daemon_mess
 /*
  * Write a message to the client making sure that it is ready to write.
  */
-static int client_write(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
+static int client_write(struct dm_event_fifos *fifos,
+                       struct dm_event_daemon_message *msg)
 {
        unsigned bytes = 0;
        int ret = 0;
        fd_set fds;
 
-       size_t size = 2*sizeof(uint32_t) + msg->size;
+       size_t size = 2 * sizeof(uint32_t) + msg->size;
        char *buf = alloca(size);
 
        *((uint32_t *)buf) = htonl(msg->cmd);
        *((uint32_t *)buf + 1) = htonl(msg->size);
-       memcpy(buf + 2*sizeof(uint32_t), msg->data, msg->size);
+       if (msg->data)
+               memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
 
        errno = 0;
        while (bytes < size && errno != EIO) {
@@ -1156,7 +1200,8 @@ static int client_write(struct dm_event_fifos *fifos, struct dm_event_daemon_mes
                        /* Watch client write FIFO to be ready for output. */
                        FD_ZERO(&fds);
                        FD_SET(fifos->server, &fds);
-               } while (select(fifos->server +1, NULL, &fds, NULL, NULL) != 1);
+               } while (select(fifos->server + 1, NULL, &fds, NULL, NULL) !=
+                        1);
 
                ret = write(fifos->server, buf + bytes, size - bytes);
                bytes += ret > 0 ? ret : 0;
@@ -1176,15 +1221,16 @@ static int handle_request(struct dm_event_daemon_message *msg,
 {
        static struct {
                unsigned int cmd;
-               int (*f)(struct message_data*);
+               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 },
+               { 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++)
@@ -1203,8 +1249,7 @@ static int do_process_request(struct dm_event_daemon_message *msg)
        /* Parse the message. */
        memset(&message_data, 0, sizeof(message_data));
        message_data.msg = msg;
-       if (msg->cmd != DM_EVENT_CMD_ACTIVE &&
-           !parse_message(&message_data)) {
+       if (msg->cmd != DM_EVENT_CMD_ACTIVE && !parse_message(&message_data)) {
                stack;
                ret = -EINVAL;
        } else
@@ -1220,15 +1265,11 @@ static void process_request(struct dm_event_fifos *fifos)
 {
        struct dm_event_daemon_message msg;
 
-       /* FIXME: better error handling */
-
        memset(&msg, 0, sizeof(msg));
 
        /*
-        * Read the request from the client.
-        * Of course, it's tough to tell what to do when
-        * we use fucking retarded return codes like
-        * 0 for error.
+        * Read the request from the client (client_read, client_write
+        * give true on success and false on failure).
         */
        if (!client_read(fifos, &msg))
                return;
@@ -1236,7 +1277,12 @@ static void process_request(struct dm_event_fifos *fifos)
        msg.cmd = do_process_request(&msg);
        if (!msg.data) {
                msg.data = dm_strdup(strerror(-msg.cmd));
-               msg.size = strlen(msg.data) + 1;
+               if (msg.data)
+                       msg.size = strlen(msg.data) + 1;
+               else {
+                       msg.size = 0;
+                       stack;
+               }
        }
 
        if (!client_write(fifos, &msg))
@@ -1256,7 +1302,7 @@ static void cleanup_unused_threads(void)
        while ((l = list_first(&_thread_registry_unused))) {
                thread = list_item(l, struct thread_status);
                if (thread->processing) {
-                       goto out;  /* cleanup on the next round */
+                       goto out;       /* cleanup on the next round */
                }
 
                if (thread->status == DM_THREAD_RUNNING) {
@@ -1270,14 +1316,16 @@ static void cleanup_unused_threads(void)
                                if (ret == ESRCH) {
                                        thread->status = DM_THREAD_DONE;
                                } else if (ret) {
-                                       syslog(LOG_ERR, "Unable to terminate thread: %s\n",
+                                       syslog(LOG_ERR,
+                                              "Unable to terminate thread: %s\n",
                                               strerror(-ret));
                                        stack;
                                }
                                goto out;
                        } else {
                                list_del(l);
-                               syslog(LOG_ERR, "thread can't be on unused list unless !thread->events");
+                               syslog(LOG_ERR,
+                                      "thread can't be on unused list unless !thread->events");
                                thread->status = DM_THREAD_RUNNING;
                                LINK_THREAD(thread);
                        }
@@ -1288,7 +1336,7 @@ static void cleanup_unused_threads(void)
                        free_thread_status(thread);
                }
        }
-out:
+      out:
        unlock_mutex();
 }
 
@@ -1302,7 +1350,7 @@ static void init_thread_signals(void)
 {
        sigset_t my_sigset;
        struct sigaction act;
-       
+
        memset(&act, 0, sizeof(act));
        act.sa_handler = sig_alarm;
        sigaction(SIGALRM, &act, NULL);
@@ -1344,7 +1392,7 @@ static void exit_handler(int sig)
 static int lock_pidfile(void)
 {
        int lf;
-       char pidfile[] = "/var/run/dmeventd.pid"; /* FIXME Must be configurable at compile-time! */
+       char pidfile[] = DMEVENTD_PIDFILE;
 
        if ((lf = open(pidfile, O_CREAT | O_RDWR, 0644)) < 0)
                exit(EXIT_OPEN_PID_FAILURE);
@@ -1383,11 +1431,11 @@ static void daemonize(void)
                /* Wait for response from child */
                while (!waitpid(pid, &status, WNOHANG) && !_exit_now) {
                        tval.tv_sec = 0;
-                       tval.tv_usec = 250000; /* .25 sec */
+                       tval.tv_usec = 250000;  /* .25 sec */
                        select(0, NULL, NULL, NULL, &tval);
                }
 
-               if (_exit_now) /* Child has signaled it is ok - we can exit now */
+               if (_exit_now)  /* Child has signaled it is ok - we can exit now */
                        exit(EXIT_SUCCESS);
 
                /* Problem with child.  Determine what it is by exit code */
@@ -1408,7 +1456,7 @@ static void daemonize(void)
                        break;
                }
 
-               exit(EXIT_FAILURE);  /* Redundant */
+               exit(EXIT_FAILURE);     /* Redundant */
        }
 
        setsid();
@@ -1416,7 +1464,7 @@ static void daemonize(void)
                exit(EXIT_CHDIR_FAILURE);
 
        if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
-               fd = 256;  /* just have to guess */
+               fd = 256;       /* just have to guess */
        else
                fd = rlim.rlim_cur;
 
@@ -1430,7 +1478,7 @@ static void daemonize(void)
 
        openlog("dmeventd", LOG_PID, LOG_DAEMON);
 
-       lock_pidfile();  /* exits if failure */
+       lock_pidfile();         /* exits if failure */
 
        /* Set the rest of the signals to cause '_exit_now' to be set */
        signal(SIGINT, &exit_handler);
@@ -1472,7 +1520,8 @@ int main(int argc, char *argv[])
        while (!_exit_now) {
                process_request(&fifos);
                cleanup_unused_threads();
-               if (!list_empty(&_thread_registry) || !list_empty(&_thread_registry_unused))
+               if (!list_empty(&_thread_registry)
+                   || !list_empty(&_thread_registry_unused))
                        _thread_registries_empty = 0;
                else
                        _thread_registries_empty = 1;
index ccbc36fb81f39c1138cf0049f8855c26b230c2b4..ce22e61238ad0b68b928429d6bf66d2f508be417 100644 (file)
 #include <sys/stat.h>
 #include <unistd.h>
 #include <sys/wait.h>
-#include <arpa/inet.h> /* for htonl, ntohl */
+#include <arpa/inet.h>         /* for htonl, ntohl */
+
+struct dm_event_handler {
+       const char *dso;
+       const char *device;
+       const char *uuid;
+       int major;
+       int minor;
+       enum dm_event_type events;
+};
+
+static void dm_event_handler_clear_device(struct dm_event_handler *h)
+{
+       h->device = h->uuid = NULL;
+       h->major = h->minor = 0;
+}
 
-/* Set by any of the external fxns the first time one of them is called */
-/* FIXME Unused */
-// static int _logging = 0;
+struct dm_event_handler *dm_event_handler_create(void)
+{
+       struct dm_event_handler *ret = 0;
 
-/* Fetch a string off src and duplicate it into *dest. */
-/* FIXME: move to seperate module to share with the daemon. */
-static const char delimiter = ' ';
-static char *fetch_string(char **src)
+       if (!(ret = dm_malloc(sizeof(*ret))))
+               return NULL;
+
+       ret->dso = ret->device = ret->uuid = NULL;
+       ret->major = ret->minor = 0;
+       ret->events = 0;
+
+       return ret;
+}
+
+void dm_event_handler_destroy(struct dm_event_handler *h)
 {
-       char *p, *ret;
+       dm_free(h);
+}
 
-       if ((p = strchr(*src, delimiter)))
-               *p = 0;
+void dm_event_handler_set_dso(struct dm_event_handler *h, const char *path)
+{
+       h->dso = path;
+}
 
-       if ((ret = dm_strdup(*src)))
-               *src += strlen(ret) + 1;
+void dm_event_handler_set_name(struct dm_event_handler *h, const char *name)
+{
+       dm_event_handler_clear_device(h);
+       h->device = name;
+}
 
-       if (p)
-               *p = delimiter;
+void dm_event_handler_set_uuid(struct dm_event_handler *h, const char *uuid)
+{
+       dm_event_handler_clear_device(h);
+       h->uuid = uuid;
+}
 
-       return ret;
+void dm_event_handler_set_major(struct dm_event_handler *h, int major)
+{
+       int minor = h->minor;
+
+       dm_event_handler_clear_device(h);
+       h->major = major;
+       h->minor = minor;
 }
 
-/* Parse a device message from the daemon. */
-static int parse_message(struct dm_event_daemon_message *msg, char **dso_name,
-                        char **device, enum dm_event_type *events)
+void dm_event_handler_set_minor(struct dm_event_handler *h, int minor)
 {
-       char *p = msg->data;
+       int major = h->major;
 
-       if ((*dso_name = fetch_string(&p)) &&
-           (*device   = fetch_string(&p))) {
-               *events = atoi(p);
+       dm_event_handler_clear_device(h);
 
-               return 0;
-       }
+       h->major = major;
+       h->minor = minor;
+}
 
-       return -ENOMEM;
+void dm_event_handler_set_events(struct dm_event_handler *h,
+                                enum dm_event_type event)
+{
+       h->events = event;
+}
+
+const char *dm_event_handler_get_dso(const struct dm_event_handler *h)
+{
+       return h->dso;
+}
+
+const char *dm_event_handler_get_name(const struct dm_event_handler *h)
+{
+       return h->device;
+}
+
+const char *dm_event_handler_get_uuid(const struct dm_event_handler *h)
+{
+       return h->uuid;
+}
+
+int dm_event_handler_get_major(const struct dm_event_handler *h)
+{
+       return h->major;
+}
+
+int dm_event_handler_get_minor(const struct dm_event_handler *h)
+{
+       return h->minor;
+}
+
+enum dm_event_type dm_event_handler_get_events(const struct dm_event_handler *h)
+{
+       return h->events;
 }
 
 /*
@@ -78,13 +145,14 @@ static int parse_message(struct dm_event_daemon_message *msg, char **dso_name,
  *
  * Returns: 0 on failure, 1 on success
  */
-static int daemon_read(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
+static int daemon_read(struct dm_event_fifos *fifos,
+                      struct dm_event_daemon_message *msg)
 {
        unsigned bytes = 0;
        int ret, i;
        fd_set fds;
-       struct timeval tval = {0, 0};
-       size_t size = 2 * sizeof(uint32_t); // status + size
+       struct timeval tval = { 0, 0 };
+       size_t size = 2 * sizeof(uint32_t);     /* status + size */
        char *buf = alloca(size);
        int header = 1;
 
@@ -94,7 +162,8 @@ static int daemon_read(struct dm_event_fifos *fifos, struct dm_event_daemon_mess
                        FD_ZERO(&fds);
                        FD_SET(fifos->server, &fds);
                        tval.tv_sec = 1;
-                       ret = select(fifos->server+1, &fds, NULL, NULL, &tval);
+                       ret = select(fifos->server + 1, &fds, NULL, NULL,
+                                    &tval);
                        if (ret < 0 && errno != EINTR) {
                                log_error("Unable to read from event server");
                                return 0;
@@ -116,7 +185,7 @@ static int daemon_read(struct dm_event_fifos *fifos, struct dm_event_daemon_mess
                }
 
                bytes += ret;
-               if (bytes == 2*sizeof(uint32_t) && header) {
+               if (bytes == 2 * sizeof(uint32_t) && header) {
                        msg->cmd = ntohl(*((uint32_t *)buf));
                        msg->size = ntohl(*((uint32_t *)buf + 1));
                        buf = msg->data = dm_malloc(msg->size);
@@ -136,32 +205,34 @@ static int daemon_read(struct dm_event_fifos *fifos, struct dm_event_daemon_mess
 }
 
 /* Write message to daemon. */
-static int daemon_write(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
+static int daemon_write(struct dm_event_fifos *fifos,
+                       struct dm_event_daemon_message *msg)
 {
        unsigned bytes = 0;
        int ret = 0;
        fd_set fds;
 
-       size_t size = 2*sizeof(uint32_t) + msg->size;
+       size_t size = 2 * sizeof(uint32_t) + msg->size;
        char *buf = alloca(size);
 
        *((uint32_t *)buf) = htonl(msg->cmd);
        *((uint32_t *)buf + 1) = htonl(msg->size);
-       memcpy(buf + 2*sizeof(uint32_t), msg->data, msg->size);
+       memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
 
        while (bytes < size) {
                do {
                        /* Watch daemon write FIFO to be ready for output. */
                        FD_ZERO(&fds);
                        FD_SET(fifos->client, &fds);
-                       ret = select(fifos->client +1, NULL, &fds, NULL, NULL);
+                       ret = select(fifos->client + 1, NULL, &fds, NULL, NULL);
                        if ((ret < 0) && (errno != EINTR)) {
                                log_error("Unable to talk to event daemon");
                                return 0;
                        }
                } while (ret < 1);
 
-               ret = write(fifos->client, ((char *) buf) + bytes, size - bytes);
+               ret = write(fifos->client, ((char *) buf) + bytes,
+                           size - bytes);
                if (ret < 0) {
                        if ((errno == EINTR) || (errno == EAGAIN))
                                continue;
@@ -177,14 +248,14 @@ static int daemon_write(struct dm_event_fifos *fifos, struct dm_event_daemon_mes
        return bytes == size;
 }
 
-static int daemon_talk(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg,
-                      int cmd, const char *dso_name, const char *device,
+static int daemon_talk(struct dm_event_fifos *fifos,
+                      struct dm_event_daemon_message *msg, int cmd,
+                      const char *dso_name, const char *device,
                       enum dm_event_type events, uint32_t timeout)
 {
-       char test[1];
        const char *dso = dso_name ? dso_name : "";
        const char *dev = device ? device : "";
-       const char *fmt = "%s %s %u %"PRIu32;
+       const char *fmt = "%s %s %u %" PRIu32;
        memset(msg, 0, sizeof(*msg));
 
        /*
@@ -192,10 +263,7 @@ static int daemon_talk(struct dm_event_fifos *fifos, struct dm_event_daemon_mess
         * into ASCII message string.
         */
        msg->cmd = cmd;
-       /* FIXME depends on glibc 2.1+ */
-       msg->size = snprintf(test, 1, fmt, dso, dev, events, timeout);
-       msg->data = alloca(msg->size);
-       snprintf(msg->data, msg->size, fmt, dso, dev, events, timeout);
+       msg->size = dm_saprintf(&(msg->data), fmt, dso, dev, events, timeout);
 
        /*
         * Write command and message to and
@@ -256,7 +324,7 @@ static int start_daemon(struct dm_event_fifos *fifos)
                return 0;
        }
 
-start_server:
+      start_server:
        /* server is not running */
        pid = fork();
 
@@ -264,11 +332,13 @@ start_server:
                log_error("Unable to fork.");
 
        else if (!pid) {
-               execvp("dmeventd", NULL); /* security risk if admin has bad PATH */
+               /* FIXME configure path (cf. lvm2 modprobe) */
+               execvp("dmeventd", NULL);
                exit(EXIT_FAILURE);
        } else {
                if (waitpid(pid, &status, 0) < 0)
-                       log_error("Unable to start dmeventd: %s", strerror(errno));
+                       log_error("Unable to start dmeventd: %s",
+                                 strerror(errno));
                else if (WEXITSTATUS(status))
                        log_error("Unable to start dmeventd.");
                else
@@ -281,8 +351,8 @@ start_server:
 /* Initialize client. */
 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? */
+       /* FIXME? Is fifo the most suitable method? Why not share
+          comms/daemon code with something else e.g. multipath? */
 
        /* init fifos */
        memset(fifos, 0, sizeof(*fifos));
@@ -297,20 +367,19 @@ static int init_client(struct dm_event_fifos *fifos)
        /* Open the fifo used to read from the daemon. */
        if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
                log_error("%s: open server fifo %s",
-                       __func__, fifos->server_path);
+                         __func__, fifos->server_path);
                stack;
                return 0;
        }
 
        /* Lock out anyone else trying to do communication with the daemon. */
-       if (flock(fifos->server, LOCK_EX) < 0){
+       if (flock(fifos->server, LOCK_EX) < 0) {
                log_error("%s: flock %s", __func__, fifos->server_path);
                close(fifos->server);
                return 0;
        }
 
-/*     if ((fifos->client = open(fifos->client_path,
-  O_WRONLY | O_NONBLOCK)) < 0) {*/
+/*     if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
        if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) {
                log_error("%s: Can't open client fifo %s: %s",
                          __func__, fifos->client_path, strerror(errno));
@@ -318,7 +387,7 @@ static int init_client(struct dm_event_fifos *fifos)
                stack;
                return 0;
        }
-       
+
        return 1;
 }
 
@@ -331,65 +400,72 @@ static void dtr_client(struct dm_event_fifos *fifos)
        close(fifos->server);
 }
 
-/* Check, if a block device exists. */
-static int device_exists(const char *device)
+/* Get uuid of a device, if it exists (otherwise NULL). */
+static struct dm_task *get_device_info(const struct dm_event_handler *h)
 {
-       struct stat st_buf;
-       char path2[PATH_MAX];
-
-       if (!device)
-               return 0;
-
-       if (device[0] == '/') /* absolute path */
-               return !stat(device, &st_buf) && S_ISBLK(st_buf.st_mode);
+       struct dm_task *dmt = dm_task_create(DM_DEVICE_INFO);
+       struct dm_task *ret;
+
+       if (!dmt)
+               return NULL;
+
+       if (h->uuid)
+               dm_task_set_uuid(dmt, h->uuid);
+       else if (h->device)
+               dm_task_set_name(dmt, h->device);
+       else if (h->major && h->minor) {
+               dm_task_set_major(dmt, h->major);
+               dm_task_set_minor(dmt, h->minor);
+       }
 
-       if (PATH_MAX <= snprintf(path2, PATH_MAX, "%s/%s", dm_dir(), device))
-               return 0;
+       if (!dm_task_run(dmt))
+               ret = NULL;
+       else
+               ret = dmt;
 
-       return !stat(path2, &st_buf) && S_ISBLK(st_buf.st_mode);
+       return ret;
 }
 
 /* Handle the event (de)registration call and return negative error codes. */
 static int do_event(int cmd, struct dm_event_daemon_message *msg,
-                   const char *dso_name, const char *device, enum dm_event_type events,
-                   uint32_t timeout)
+                   const char *dso_name, const char *device,
+                   enum dm_event_type events, uint32_t timeout)
 {
        int ret;
        struct dm_event_fifos fifos;
 
-       /* FIXME Start the daemon here if it's not running e.g. exclusive lock file */
-       /* FIXME Move this to separate 'dm_event_register_handler' - if no daemon here, fail */
        if (!init_client(&fifos)) {
                stack;
                return -ESRCH;
        }
 
-       /* FIXME Use separate 'dm_event_register_handler' function to pass in dso? */
        ret = daemon_talk(&fifos, msg, cmd, dso_name, device, events, timeout);
 
        /* what is the opposite of init? */
        dtr_client(&fifos);
-       
+
        return ret;
 }
 
-/* FIXME remove dso_name - use handle instead */
-/* FIXME Use uuid not path! */
 /* External library interface. */
-int dm_event_register(const char *dso_name, const char *device_path,
-                     enum dm_event_type events)
+int dm_event_register(const struct dm_event_handler *h)
 {
        int ret, err;
+       const char *uuid;
+       struct dm_task *dmt;
        struct dm_event_daemon_message msg;
 
-       if (!device_exists(device_path)) {
-               log_error("%s: device not found", device_path);
+       if (!(dmt = get_device_info(h))) {
+               log_error("%s: device not found", h->device);
                return 0;
        }
 
+       uuid = dm_task_get_uuid(dmt);
+
        if ((err = do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,
-                           dso_name, device_path, events, 0)) < 0) {
-               log_error("%s: event registration failed: %s", device_path,
+                           h->dso, uuid, h->events, 0)) < 0) {
+               log_error("%s: event registration failed: %s",
+                         dm_task_get_name(dmt),
                          msg.data ? msg.data : strerror(-err));
                ret = 0;
        } else
@@ -398,23 +474,29 @@ int dm_event_register(const char *dso_name, const char *device_path,
        if (msg.data)
                dm_free(msg.data);
 
+       dm_task_destroy(dmt);
+
        return ret;
 }
 
-int dm_event_unregister(const char *dso_name, const char *device_path,
-                       enum dm_event_type events)
+int dm_event_unregister(const struct dm_event_handler *h)
 {
        int ret, err;
+       const char *uuid;
+       struct dm_task *dmt;
        struct dm_event_daemon_message msg;
 
-       if (!device_exists(device_path)) {
-               log_error("%s: device not found", device_path);
+       if (!(dmt = get_device_info(h))) {
+               log_error("%s: device not found", dm_task_get_name(dmt));
                return 0;
        }
 
+       uuid = dm_task_get_uuid(dmt);
+
        if ((err = do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,
-                           dso_name, device_path, events, 0)) < 0) {
-               log_error("%s: event deregistration failed: %s", device_path,
+                           h->dso, uuid, h->events, 0)) < 0) {
+               log_error("%s: event deregistration failed: %s",
+                         dm_task_get_name(dmt),
                          msg.data ? msg.data : strerror(-err));
                ret = 0;
        } else
@@ -422,9 +504,48 @@ int dm_event_unregister(const char *dso_name, const char *device_path,
 
        if (msg.data)
                dm_free(msg.data);
+
+       dm_task_destroy(dmt);
+
+       return ret;
+}
+
+#if 0                          /* left out for now */
+
+/* Fetch a string off src and duplicate it into *dest. */
+/* FIXME: move to seperate module to share with the daemon. */
+static const char delimiter = ' ';
+static char *fetch_string(char **src)
+{
+       char *p, *ret;
+
+       if ((p = strchr(*src, delimiter)))
+               *p = 0;
+
+       if ((ret = dm_strdup(*src)))
+               *src += strlen(ret) + 1;
+
+       if (p)
+               *p = delimiter;
+
        return ret;
 }
 
+/* Parse a device message from the daemon. */
+static int parse_message(struct dm_event_daemon_message *msg, char **dso_name,
+                        char **device, enum dm_event_type *events)
+{
+       char *p = msg->data;
+
+       if ((*dso_name = fetch_string(&p)) && (*device = fetch_string(&p))) {
+               *events = atoi(p);
+
+               return 0;
+       }
+
+       return -ENOMEM;
+}
+
 /*
  * dm_event_get_registered_device
  * @dso_name
@@ -437,18 +558,18 @@ int dm_event_unregister(const char *dso_name, const char *device_path,
  * Returns: 1 if device found, 0 otherwise (even on error)
  */
 int dm_event_get_registered_device(char **dso_name, char **device_path,
-                            enum dm_event_type *events, int next)
+                                  enum dm_event_type *events, int next)
 {
        int ret;
        char *dso_name_arg = NULL, *device_path_arg = NULL;
        struct dm_event_daemon_message msg;
 
        if (!(ret = do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
-                                   DM_EVENT_CMD_GET_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);
-       } else /* FIXME: Make sure this is ENOENT */
+       } else                  /* FIXME: Make sure this is ENOENT */
                ret = 0;
 
        if (msg.data)
@@ -488,9 +609,11 @@ int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
 
        if (!device_exists(device_path))
                return -ENODEV;
-       if (!(ret = do_event(DM_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.data);
        if (msg.data)
                dm_free(msg.data);
        return ret;
 }
+#endif
index 77460fcc66fdd210a6c17a9930905974daef5328..151b178841d9fda0c853ca1a3b580d49fdcc1b31 100644 (file)
 #include <stdint.h>
 
 /* 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_SETTINGS_MASK  = 0x0000FF,
+       DM_EVENT_SINGLE         = 0x000001, /* Report multiple errors just once. */
+       DM_EVENT_MULTI          = 0x000002, /* 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_ERROR_MASK     = 0x00FF00,
+       DM_EVENT_SECTOR_ERROR   = 0x000100, /* Failure on a particular sector. */
+       DM_EVENT_DEVICE_ERROR   = 0x000200, /* Device failure. */
+       DM_EVENT_PATH_ERROR     = 0x000400, /* Failure on an io path. */
+       DM_EVENT_ADAPTOR_ERROR  = 0x000800, /* Failure off a host adaptor. */
 
-       DM_EVENT_SYNC_STATUS    = 0x40, /* Mirror synchronization completed/failed. */
-       DM_EVENT_TIMEOUT        = 0x80, /* Timeout has occured */
-       DM_EVENT_REGISTRATION_PENDING        = 0X100, /* Monitor thread is setting-up/shutting-down */
+       DM_EVENT_STATUS_MASK    = 0xFF0000,
+       DM_EVENT_SYNC_STATUS    = 0x010000, /* Mirror synchronization completed/failed. */
+       DM_EVENT_TIMEOUT        = 0x020000, /* Timeout has occured */
+
+       DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
 };
 
-/* 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)
+#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
 
 /* Prototypes for event lib interface. */
 
-/* FIXME Replace device with standard name/uuid/devno choice */
-/* Interface changes: 
-   First register a handler, passing in a unique ref for the device. */
-
-//  int dm_event_register_handler(const char *dso_name, const char *device);
-//  int dm_event_register(const char *dso_name, const char *name, const char *uuid, uint32_t major, uint32_t minor, enum dm_event_type events);
-
-/* Or (better?) add to task structure and use existing functions - run
-   a task to register/unregister events - we may need to run task
-   withe that with the new event mechanism anyway, then the dso calls
-   just hook in. */
-int dm_event_register(const char *dso_name, const char *device, enum dm_event_type events);
-int dm_event_unregister(const char *dso_name, const 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(const char *device, uint32_t timeout);
-int dm_event_get_timeout(const 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);
+struct dm_event_handler;
+
+/* Create and destroy dm_event_handler struct, which is passed to
+   register/unregister functions below */
+struct dm_event_handler *dm_event_handler_create(void);
+void dm_event_handler_destroy(struct dm_event_handler *h);
+
+/* Set parameters of a handler:
+   - dso - shared library path to handle the events
+   (only one of the following three needs to be set)
+   - name - device name or path
+   - uuid - device uuid
+   - major and minor - device major/minor numbers
+   - events - a bitfield defining which events to handle (see
+              enum dm_event_type above)
+*/
+void dm_event_handler_set_dso(struct dm_event_handler *h, const char *path);
+void dm_event_handler_set_name(struct dm_event_handler *h, const char *name);
+void dm_event_handler_set_uuid(struct dm_event_handler *h, const char *uuid);
+void dm_event_handler_set_major(struct dm_event_handler *h, int major);
+void dm_event_handler_set_minor(struct dm_event_handler *h, int minor);
+void dm_event_handler_set_events(struct dm_event_handler *h,
+                                enum dm_event_type event);
+
+/* Get parameters of a handler, same as above */
+const char *dm_event_handler_get_dso(const struct dm_event_handler *h);
+const char *dm_event_handler_get_name(const struct dm_event_handler *h);
+const char *dm_event_handler_get_uuid(const struct dm_event_handler *h);
+int dm_event_handler_get_major(const struct dm_event_handler *h);
+int dm_event_handler_get_minor(const struct dm_event_handler *h);
+enum dm_event_type dm_event_handler_get_events(const struct dm_event_handler *h);
+
+/* Call out to dmeventd to register or unregister a handler. If
+   dmeventd is not running, it is spawned first. */
+int dm_event_register(const struct dm_event_handler *h);
+int dm_event_unregister(const struct dm_event_handler *h);
+
+/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
+   detailed descriptions. */
+void process_event(struct dm_task *dmt, enum dm_event_type event);
+int register_device(const char *device, const char *uuid, int major, int minor);
+int unregister_device(const char *device, const char *uuid, int major,
+                     int minor);
 
 #endif
index 889cd059a1e7ab7725a4a7f8efe2383f5519a80b..e94f3dbb42a04cd60084c9567198d242f44c72f9 100644 (file)
@@ -3,6 +3,9 @@
 /* Define to 1 if the `closedir' function returns void instead of `int'. */
 #undef CLOSEDIR_VOID
 
+/* Path to dmeventd pidfile. */
+#undef DMEVENTD_PIDFILE
+
 /* Define to 1 if canonicalize_file_name is available. */
 #undef HAVE_CANONICALIZE_FILE_NAME
 
 /* Define to empty if `const' does not conform to ANSI C. */
 #undef const
 
-/* Define to `__inline__' or `__inline' if that's what the C compiler
-   calls it, or to nothing if 'inline' is not supported under any name.  */
-#ifndef __cplusplus
+/* Define as `__inline' if that's what the C compiler calls it, or to nothing
+   if it is not supported. */
 #undef inline
-#endif
 
 /* Define to rpl_malloc if the replacement function should be used. */
 #undef malloc
index 34a623ad91a943e75f8db7b7dcc7217e076b3c23..93046fa3290f04de99c55cd11e7412b8d548f164 100644 (file)
@@ -115,3 +115,4 @@ dm_split_lvm_name
 dm_split_words
 dm_snprintf
 dm_basename
+dm_saprintf
index 3fda02a7c0ba7761f29180325d1128b17be6d706..ece3604931ce396ba9143dc6890dabaabed225de 100644 (file)
@@ -623,4 +623,10 @@ int dm_snprintf(char *buf, size_t bufsize, const char *format, ...);
  */
 char *dm_basename(const char *path);
 
+/*
+ * Returns size of a buffer which is allocated with dm_malloc.
+ * Pointer to the buffer is stored in *buf.
+ */
+int dm_saprintf(char **buf, const char *format, ...);
+
 #endif                         /* LIB_DEVICE_MAPPER_H */
index 098fc0d9d47392a7acbe8581234363a19d1a1b5d..65b1c12ad9ebfbc785349f3388fb3609571329d7 100644 (file)
@@ -129,3 +129,33 @@ char *dm_basename(const char *path)
        return p ? p + 1 : (char *) path;
 }
 
+int dm_saprintf(char **result, const char *format, ...)
+{
+       int n, ok = 0, size = 32;
+       va_list ap;
+       char *buf = dm_malloc(size);
+
+       *result = 0;
+
+       if (!buf)
+               return -1;
+
+       while (!ok) {
+               va_start(ap, format);
+               n = vsnprintf(buf, size, format, ap);
+               if (0 <= n && n < size)
+                       ok = 1;
+               else {
+                       dm_free(buf);
+                       size *= 2;
+                       buf = dm_malloc(size);
+                       if (!buf)
+                               return -1;
+               };
+               va_end(ap);
+       }
+
+       *result = dm_strdup(buf);
+       dm_free(buf);
+       return n + 1;
+}
This page took 0.091349 seconds and 5 git commands to generate.