diff --git a/daemons/dmeventd/.exported_symbols b/daemons/dmeventd/.exported_symbols index 25690c8d1..fab74dc1d 100644 --- a/daemons/dmeventd/.exported_symbols +++ b/daemons/dmeventd/.exported_symbols @@ -1,3 +1,4 @@ init_fifos fini_fifos daemon_talk +dm_event_get_version diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c index fe5f0194b..1a91cb858 100644 --- a/daemons/dmeventd/dmeventd.c +++ b/daemons/dmeventd/dmeventd.c @@ -1424,8 +1424,9 @@ static int _do_process_request(struct dm_event_daemon_message *msg) ret = 0; answer = msg->data; if (answer) { - msg->size = dm_asprintf(&(msg->data), "%s %s", answer, - msg->cmd == DM_EVENT_CMD_DIE ? "DYING" : "HELLO"); + msg->size = dm_asprintf(&(msg->data), "%s %s %d", answer, + msg->cmd == DM_EVENT_CMD_DIE ? "DYING" : "HELLO", + DM_EVENT_PROTOCOL_VERSION); dm_free(answer); } else { msg->size = 0; @@ -1704,6 +1705,7 @@ static void restart(void) int i, count = 0; char *message; int length; + int version; /* Get the list of registrations from the running daemon. */ @@ -1712,12 +1714,19 @@ static void restart(void) return; } - if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0)) { + if (!dm_event_get_version(&fifos, &version)) { fprintf(stderr, "WARNING: Could not communicate with existing dmeventd.\n"); fini_fifos(&fifos); return; } + if (version < 1) { + fprintf(stderr, "WARNING: The running dmeventd instance is too old.\n" + "Protocol version %d (required: 1). Action cancelled.\n", + version); + exit(EXIT_FAILURE); + } + if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0)) { exit(EXIT_FAILURE); } diff --git a/daemons/dmeventd/dmeventd.h b/daemons/dmeventd/dmeventd.h index 3a13f1180..c60d402c7 100644 --- a/daemons/dmeventd/dmeventd.h +++ b/daemons/dmeventd/dmeventd.h @@ -69,5 +69,6 @@ int daemon_talk(struct dm_event_fifos *fifos, enum dm_event_mask evmask, uint32_t timeout); int init_fifos(struct dm_event_fifos *fifos); void fini_fifos(struct dm_event_fifos *fifos); +int dm_event_get_version(struct dm_event_fifos *fifos, int *version); #endif /* __DMEVENTD_DOT_H__ */ diff --git a/daemons/dmeventd/libdevmapper-event.c b/daemons/dmeventd/libdevmapper-event.c index 8dc83284a..2a3545f0e 100644 --- a/daemons/dmeventd/libdevmapper-event.c +++ b/daemons/dmeventd/libdevmapper-event.c @@ -782,6 +782,36 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next) return ret; } +/* + * You can (and have to) call this at the stage of the protocol where + * daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0) + * + * would be normally sent. This call will parse the version reply from + * dmeventd, in addition to above call. It is not safe to call this at any + * other place in the protocol. + * + * This is an internal function, not exposed in the public API. + */ + +int dm_event_get_version(struct dm_event_fifos *fifos, int *version) { + char *p; + struct dm_event_daemon_message msg = { 0, 0, NULL }; + + if (daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0)) + return 0; + p = msg.data; + *version = 0; + + p = strchr(p, ' ') + 1; /* Message ID */ + if (!p) return 0; + p = strchr(p, ' ') + 1; /* HELLO */ + if (!p) return 0; + p = strchr(p, ' '); /* HELLO, once more */ + if (p) + *version = atoi(p); + return 1; +} + #if 0 /* left out for now */ static char *_skip_string(char *src, const int delimiter) diff --git a/daemons/dmeventd/libdevmapper-event.h b/daemons/dmeventd/libdevmapper-event.h index 0de20c145..e07eaf6f2 100644 --- a/daemons/dmeventd/libdevmapper-event.h +++ b/daemons/dmeventd/libdevmapper-event.h @@ -46,6 +46,7 @@ enum dm_event_mask { }; #define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK +#define DM_EVENT_PROTOCOL_VERSION 1 struct dm_event_handler;