diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM index f87bdf34c..b4b8a57c2 100644 --- a/WHATS_NEW_DM +++ b/WHATS_NEW_DM @@ -1,5 +1,7 @@ Version 1.02.16 - =================================== + Add dm_event_handler_[gs]et_timeout functions. + Streamline dm_report_field_* interface. Add cmdline debug & version options to dmeventd. Add DM_LIB_VERSION definition to configure.h. Suppress 'Unrecognised field' error if report field is 'help'. diff --git a/daemons/dmeventd/.exported_symbols b/daemons/dmeventd/.exported_symbols index bccfd085a..6c892d302 100644 --- a/daemons/dmeventd/.exported_symbols +++ b/daemons/dmeventd/.exported_symbols @@ -15,3 +15,5 @@ dm_event_handler_get_event_mask dm_event_register_handler dm_event_unregister_handler dm_event_get_registered_device +dm_event_handler_set_timeout +dm_event_handler_get_timeout diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c index 1487701cb..e51914fe3 100644 --- a/daemons/dmeventd/dmeventd.c +++ b/daemons/dmeventd/dmeventd.c @@ -41,6 +41,8 @@ #ifdef linux # include +# define OOM_ADJ_FILE "/proc/self/oom_adj" + /* From linux/oom.h */ # define OOM_DISABLE (-17) # define OOM_ADJUST_MIN (-16) @@ -64,7 +66,6 @@ static int _debug = 0; #define UNLINK_THREAD(x) UNLINK(x) #define DAEMON_NAME "dmeventd" -#define OOM_ADJ_FILE "/proc/self/oom_adj" /* Global mutex for thread list access. Has to be held when: @@ -192,7 +193,7 @@ static void _debuglog(const char *fmt, ...) va_start(ap,fmt); time(&P); - fprintf(stderr, "dmeventd[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 ); + fprintf(stderr, "dmeventd[%p]: %.15s ", (void *) pthread_self(), ctime(&P)+4 ); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); @@ -449,14 +450,14 @@ static void _exit_dm_lib(void) dm_lib_exit(); } -static void _exit_timeout(void *unused) +static void _exit_timeout(void *unused __attribute((unused))) { _timeout_running = 0; pthread_mutex_unlock(&_timeout_mutex); } /* Wake up monitor threads every so often. */ -static void *_timeout_thread(void *unused) +static void *_timeout_thread(void *unused __attribute((unused))) { struct timespec timeout; time_t curr_time; @@ -468,16 +469,16 @@ static void *_timeout_thread(void *unused) while (!list_empty(&_timeout_registry)) { struct thread_status *thread; - timeout.tv_sec = (time_t) -1; + timeout.tv_sec = 0; curr_time = time(NULL); list_iterate_items_gen(thread, &_timeout_registry, timeout_list) { - if (thread->next_time < curr_time) { + 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) + if (thread->next_time < timeout.tv_sec || !timeout.tv_sec) timeout.tv_sec = thread->next_time; } @@ -682,6 +683,23 @@ static void _monitor_unregister(void *arg) _unlock_mutex(); } +static struct dm_task *_get_device_status(struct thread_status *ts) +{ + struct dm_task *dmt = dm_task_create(DM_DEVICE_STATUS); + + if (!dmt) + return NULL; + + dm_task_set_uuid(dmt, ts->device.uuid); + + if (!dm_task_run(dmt)) { + dm_task_destroy(dmt); + return NULL; + } + + return dmt; +} + /* Device monitoring thread. */ static void *_monitor_thread(void *arg) { @@ -708,6 +726,18 @@ static void *_monitor_thread(void *arg) if (wait_error == DM_WAIT_FATAL) break; + /* Timeout occurred, task is not filled properly. + * We get device status here for processing it in DSO. + */ + if (wait_error == DM_WAIT_INTR && + thread->current_events & DM_EVENT_TIMEOUT) { + dm_task_destroy(task); + task = _get_device_status(thread); + /* FIXME: syslog fail here ? */ + if (!(thread->current_task = task)) + continue; + } + /* * We know that wait succeeded and stored a * pointer to dm_task with device status into task. @@ -798,8 +828,7 @@ static struct dso_data *_lookup_dso(struct message_data *data) } /* Lookup DSO symbols we need. */ -static int _lookup_symbol(void *dl, struct dso_data *data, - void **symbol, const char *name) +static int _lookup_symbol(void *dl, void **symbol, const char *name) { if ((*symbol = dlsym(dl, name))) return 1; @@ -809,11 +838,11 @@ 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, (void *) &data->process_event, "process_event") && - _lookup_symbol(dl, data, (void *) &data->register_device, + _lookup_symbol(dl, (void *) &data->register_device, "register_device") && - _lookup_symbol(dl, data, (void *) &data->unregister_device, + _lookup_symbol(dl, (void *) &data->unregister_device, "unregister_device"); } @@ -909,7 +938,7 @@ static int _register_for_event(struct message_data *message_data) usually means we are so starved on resources that we are almost as good as dead already... */ if (thread_new->events & DM_EVENT_TIMEOUT) { - ret = -_register_for_timeout(thread); + ret = -_register_for_timeout(thread_new); if (ret) { _unlock_mutex(); goto out; @@ -1426,7 +1455,7 @@ static void _cleanup_unused_threads(void) _unlock_mutex(); } -static void _sig_alarm(int signum) +static void _sig_alarm(int signum __attribute((unused))) { pthread_testcancel(); } @@ -1458,7 +1487,7 @@ static void _init_thread_signals(void) * Set the global variable which the process should * be watching to determine when to exit. */ -static void _exit_handler(int sig) +static void _exit_handler(int sig __attribute((unused))) { /* * We exit when '_exit_now' is set. @@ -1492,6 +1521,7 @@ static int _lock_pidfile(void) return 0; } +#ifdef linux /* * Protection against OOM killer if kernel supports it */ @@ -1519,6 +1549,7 @@ static int _set_oom_adj(int val) return 1; } +#endif static void _daemonize(void) { @@ -1643,8 +1674,10 @@ int main(int argc, char *argv[]) signal(SIGHUP, &_exit_handler); signal(SIGQUIT, &_exit_handler); +#ifdef linux if (!_set_oom_adj(OOM_DISABLE) && !_set_oom_adj(OOM_ADJUST_MIN)) syslog(LOG_ERR, "Failed to set oom_adj to protect against OOM killer"); +#endif _init_thread_signals(); diff --git a/daemons/dmeventd/libdevmapper-event.c b/daemons/dmeventd/libdevmapper-event.c index 78301eb60..6a1d31c1d 100644 --- a/daemons/dmeventd/libdevmapper-event.c +++ b/daemons/dmeventd/libdevmapper-event.c @@ -38,6 +38,7 @@ struct dm_event_handler { char *uuid; int major; int minor; + uint32_t timeout; enum dm_event_mask mask; }; @@ -62,6 +63,7 @@ struct dm_event_handler *dm_event_handler_create(void) dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL; dmevh->major = dmevh->minor = 0; dmevh->mask = 0; + dmevh->timeout = 0; return dmevh; } @@ -140,6 +142,11 @@ void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh, dmevh->mask = evmask; } +void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout) +{ + dmevh->timeout = timeout; +} + const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh) { return dmevh->dso; @@ -165,6 +172,11 @@ int dm_event_handler_get_minor(const struct dm_event_handler *dmevh) return dmevh->minor; } +int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh) +{ + return dmevh->timeout; +} + enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh) { return dmevh->mask; @@ -484,8 +496,8 @@ failed: /* 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 *dev_name, - enum dm_event_mask evmask, uint32_t timeout) + const char *dso_name, const char *dev_name, + enum dm_event_mask evmask, uint32_t timeout) { int ret; struct dm_event_fifos fifos; @@ -519,7 +531,7 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh) uuid = dm_task_get_uuid(dmt); if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg, - dmevh->dso, uuid, dmevh->mask, 0)) < 0) { + dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) { log_error("%s: event registration failed: %s", dm_task_get_name(dmt), msg.data ? msg.data : strerror(-err)); @@ -549,7 +561,7 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh) uuid = dm_task_get_uuid(dmt); if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg, - dmevh->dso, uuid, dmevh->mask, 0)) < 0) { + dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) { log_error("%s: event deregistration failed: %s", dm_task_get_name(dmt), msg.data ? msg.data : strerror(-err)); @@ -690,8 +702,9 @@ int dm_event_set_timeout(const char *device_path, uint32_t timeout) if (!device_exists(device_path)) return -ENODEV; + return _do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg, - NULL, device_path, 0, timeout); + NULL, device_path, 0, timeout); } int dm_event_get_timeout(const char *device_path, uint32_t *timeout) diff --git a/daemons/dmeventd/libdevmapper-event.h b/daemons/dmeventd/libdevmapper-event.h index 0a6b7e029..f10e7a4bd 100644 --- a/daemons/dmeventd/libdevmapper-event.h +++ b/daemons/dmeventd/libdevmapper-event.h @@ -71,6 +71,7 @@ int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid); void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major); void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor); +void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout); /* * Specify mask for events to monitor. @@ -83,6 +84,7 @@ const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh); const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh); int dm_event_handler_get_major(const struct dm_event_handler *dmevh); int dm_event_handler_get_minor(const struct dm_event_handler *dmevh); +int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh); enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh); /* FIXME Review interface (what about this next thing?) */ diff --git a/libdm/datastruct/hash.c b/libdm/datastruct/hash.c index 1a3ea8167..d44d40d89 100644 --- a/libdm/datastruct/hash.c +++ b/libdm/datastruct/hash.c @@ -230,12 +230,14 @@ void dm_hash_wipe(struct dm_hash_table *t) t->num_nodes = 0u; } -char *dm_hash_get_key(struct dm_hash_table *t, struct dm_hash_node *n) +char *dm_hash_get_key(struct dm_hash_table *t __attribute((unused)), + struct dm_hash_node *n) { return n->key; } -void *dm_hash_get_data(struct dm_hash_table *t, struct dm_hash_node *n) +void *dm_hash_get_data(struct dm_hash_table *t __attribute((unused)), + struct dm_hash_node *n) { return n->data; } diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index e6cd8d661..5df406866 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -687,26 +687,27 @@ int dm_report_object(struct dm_report *rh, void *object); int dm_report_output(struct dm_report *rh); void dm_report_free(struct dm_report *rh); -/* report functions for common types */ -int dm_report_field_string(struct dm_report *rh, struct dm_pool *mem, - struct dm_report_field *field, const void *data); -int dm_report_field_int32(struct dm_report *rh, struct dm_pool *mem, - struct dm_report_field *field, const void *data); -int dm_report_field_uint32(struct dm_report *rh, struct dm_pool *mem, - struct dm_report_field *field, const void *data); -int dm_report_field_int(struct dm_report *rh, struct dm_pool *mem, - struct dm_report_field *field, const void *data); -int dm_report_field_uint64(struct dm_report *rh, struct dm_pool *mem, - struct dm_report_field *field, const void *data); +/* + * Report functions are provided for simple data types. + * They take care of allocating copies of the data. + */ +int dm_report_field_string(struct dm_report *rh, struct dm_report_field *field, + const char **data); +int dm_report_field_int32(struct dm_report *rh, struct dm_report_field *field, + const int32_t *data); +int dm_report_field_uint32(struct dm_report *rh, struct dm_report_field *field, + const uint32_t *data); +int dm_report_field_int(struct dm_report *rh, struct dm_report_field *field, + const int *data); +int dm_report_field_uint64(struct dm_report *rh, struct dm_report_field *field, + const uint64_t *data); /* - * Helper function for custom reporting functions + * For custom fields, allocate the data in 'mem' and use + * dm_report_field_set_value(). + * 'sortvalue' may be NULL if it matches 'value' */ - -/* - * sortvalue may be NULL if it's the same as value - */ -void dm_report_field_set_value(struct dm_report_field *field, - const void *value, const void *sortvalue); +void dm_report_field_set_value(struct dm_report_field *field, const void *value, + const void *sortvalue); #endif /* LIB_DEVICE_MAPPER_H */ diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c index 71b11ff6d..4aa533b39 100644 --- a/libdm/libdm-common.c +++ b/libdm/libdm-common.c @@ -38,8 +38,8 @@ static int _verbose = 0; * Library users can provide their own logging * function. */ -static void _default_log(int level, const char *file, int line, - const char *f, ...) +static void _default_log(int level, const char *file __attribute((unused)), + int line __attribute((unused)), const char *f, ...) { va_list ap; diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c index 03e8fdf44..ec96e908b 100644 --- a/libdm/libdm-deptree.c +++ b/libdm/libdm-deptree.c @@ -1212,7 +1212,9 @@ static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node * return 1; } -static int _emit_areas_line(struct dm_task *dmt, struct load_segment *seg, char *params, size_t paramsize, int *pos) +static int _emit_areas_line(struct dm_task *dmt __attribute((unused)), + struct load_segment *seg, char *params, + size_t paramsize, int *pos) { struct seg_area *area; char devbuf[10]; diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c index c6852a9a0..ff21e8c9a 100644 --- a/libdm/libdm-report.c +++ b/libdm/libdm-report.c @@ -99,12 +99,12 @@ static const struct dm_report_object_type *_find_type(struct dm_report *rh, * Data-munging functions to prepare each data type for display and sorting */ -int dm_report_field_string(struct dm_report *rh, struct dm_pool *mem, - struct dm_report_field *field, const void *data) +int dm_report_field_string(struct dm_report *rh, + struct dm_report_field *field, const char **data) { char *repstr; - if (!(repstr = dm_pool_strdup(rh->mem, *(const char **) data))) { + if (!(repstr = dm_pool_strdup(rh->mem, *data))) { log_error("dm_report_field_string: dm_pool_strdup failed"); return 0; } @@ -115,10 +115,10 @@ int dm_report_field_string(struct dm_report *rh, struct dm_pool *mem, return 1; } -int dm_report_field_int(struct dm_report *rh, struct dm_pool *mem, - struct dm_report_field *field, const void *data) +int dm_report_field_int(struct dm_report *rh, + struct dm_report_field *field, const int *data) { - const int value = *(const int *) data; + const int value = *data; uint64_t *sortval; char *repstr; @@ -144,10 +144,10 @@ int dm_report_field_int(struct dm_report *rh, struct dm_pool *mem, return 1; } -int dm_report_field_uint32(struct dm_report *rh, struct dm_pool *mem, - struct dm_report_field *field, const void *data) +int dm_report_field_uint32(struct dm_report *rh, + struct dm_report_field *field, const uint32_t *data) { - const uint32_t value = *(const uint32_t *) data; + const uint32_t value = *data; uint64_t *sortval; char *repstr; @@ -173,10 +173,10 @@ int dm_report_field_uint32(struct dm_report *rh, struct dm_pool *mem, return 1; } -int dm_report_field_int32(struct dm_report *rh, struct dm_pool *mem, - struct dm_report_field *field, const void *data) +int dm_report_field_int32(struct dm_report *rh, + struct dm_report_field *field, const int32_t *data) { - const int32_t value = *(const int32_t *) data; + const int32_t value = *data; uint64_t *sortval; char *repstr; @@ -202,10 +202,10 @@ int dm_report_field_int32(struct dm_report *rh, struct dm_pool *mem, return 1; } -int dm_report_field_uint64(struct dm_report *rh, struct dm_pool *mem, - struct dm_report_field *field, const void *data) +int dm_report_field_uint64(struct dm_report *rh, + struct dm_report_field *field, const uint64_t *data) { - const int value = *(const uint64_t *) data; + const int value = *data; uint64_t *sortval; char *repstr; diff --git a/libdm/libdm-string.c b/libdm/libdm-string.c index a9ab98518..698111c2b 100644 --- a/libdm/libdm-string.c +++ b/libdm/libdm-string.c @@ -37,7 +37,8 @@ static int _isword(int c) * Split buffer into NULL-separated words in argv. * Returns number of words. */ -int dm_split_words(char *buffer, unsigned max, unsigned ignore_comments, +int dm_split_words(char *buffer, unsigned max, + unsigned ignore_comments __attribute((unused)), char **argv) { unsigned arg; diff --git a/libdm/mm/dbg_malloc.c b/libdm/mm/dbg_malloc.c index 54d838401..24044fec9 100644 --- a/libdm/mm/dbg_malloc.c +++ b/libdm/mm/dbg_malloc.c @@ -231,7 +231,8 @@ void dm_bounds_check_debug(void) } } -void *dm_malloc_aux(size_t s, const char *file, int line) +void *dm_malloc_aux(size_t s, const char *file __attribute((unused)), + int line __attribute((unused))) { if (s > 50000000) { log_error("Huge memory allocation (size %" PRIsize_t diff --git a/tools/dmsetup.c b/tools/dmsetup.c index c1261db0f..3c81874c9 100644 --- a/tools/dmsetup.c +++ b/tools/dmsetup.c @@ -1705,7 +1705,8 @@ error: /* * create a table for a mapped device using the loop target. */ -static int _loop_table(char *table, size_t tlen, char *file, char *dev, off_t off) +static int _loop_table(char *table, size_t tlen, char *file, + char *dev __attribute((unused)), off_t off) { struct stat fbuf; off_t size, sectors;