diff options
Diffstat (limited to 'daemons/dmeventd/libdevmapper-event.c')
-rw-r--r-- | daemons/dmeventd/libdevmapper-event.c | 142 |
1 files changed, 93 insertions, 49 deletions
diff --git a/daemons/dmeventd/libdevmapper-event.c b/daemons/dmeventd/libdevmapper-event.c index bc8ad99..1f8fbef 100644 --- a/daemons/dmeventd/libdevmapper-event.c +++ b/daemons/dmeventd/libdevmapper-event.c @@ -59,14 +59,10 @@ struct dm_event_handler *dm_event_handler_create(void) { struct dm_event_handler *dmevh = NULL; - if (!(dmevh = dm_malloc(sizeof(*dmevh)))) + if (!(dmevh = dm_zalloc(sizeof(*dmevh)))) { + log_error("Failed to allocate event handler."); return NULL; - - dmevh->dmeventd_path = NULL; - dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL; - dmevh->major = dmevh->minor = 0; - dmevh->mask = 0; - dmevh->timeout = 0; + } return dmevh; } @@ -245,6 +241,10 @@ static int _daemon_read(struct dm_event_fifos *fifos, log_error("Unable to read from event server"); return 0; } + if ((ret == 0) && (i > 4) && !bytes) { + log_error("No input from event server."); + return 0; + } } if (ret < 1) { log_error("Unable to read from event server."); @@ -309,7 +309,7 @@ static int _daemon_write(struct dm_event_fifos *fifos, } if (ret == 0) break; - read(fifos->server, drainbuf, 127); + ret = read(fifos->server, drainbuf, 127); } while (bytes < size) { @@ -424,30 +424,27 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos) fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK); if (fifos->client >= 0) { /* server is running and listening */ - - close(fifos->client); + if (close(fifos->client)) + log_sys_error("close", fifos->client_path); return 1; } else if (errno != ENXIO) { /* problem */ - - log_error("%s: Can't open client fifo %s: %s", - __func__, fifos->client_path, strerror(errno)); - stack; + log_sys_error("open", fifos->client_path); return 0; } start_server: /* server is not running */ - if (!strncmp(DMEVENTD_PATH, "/", 1) && stat(DMEVENTD_PATH, &statbuf)) { - log_error("Unable to find dmeventd."); - return_0; + if ((args[0][0] == '/') && stat(args[0], &statbuf)) { + log_sys_error("stat", args[0]); + return 0; } pid = fork(); if (pid < 0) - log_error("Unable to fork."); + log_sys_error("fork", ""); else if (!pid) { execvp(args[0], args); @@ -477,25 +474,23 @@ int init_fifos(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); - stack; + log_sys_error("open", fifos->server_path); return 0; } /* Lock out anyone else trying to do communication with the daemon. */ if (flock(fifos->server, LOCK_EX) < 0) { - log_error("%s: flock %s", __func__, fifos->server_path); - close(fifos->server); + log_sys_error("flock", fifos->server_path); + if (close(fifos->server)) + log_sys_error("close", fifos->server_path); return 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)); - close(fifos->server); - stack; + log_sys_error("open", fifos->client_path); + if (close(fifos->server)) + log_sys_error("close", fifos->server_path); return 0; } @@ -523,8 +518,10 @@ void fini_fifos(struct dm_event_fifos *fifos) if (flock(fifos->server, LOCK_UN)) log_error("flock unlock %s", fifos->server_path); - close(fifos->client); - close(fifos->server); + if (close(fifos->client)) + log_sys_error("close", fifos->client_path); + if (close(fifos->server)) + log_sys_error("close", fifos->server_path); } /* Get uuid of a device */ @@ -538,34 +535,46 @@ static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh) return NULL; } - if (dmevh->uuid) - dm_task_set_uuid(dmt, dmevh->uuid); - else if (dmevh->dev_name) - dm_task_set_name(dmt, dmevh->dev_name); - else if (dmevh->major && dmevh->minor) { - dm_task_set_major(dmt, dmevh->major); - dm_task_set_minor(dmt, dmevh->minor); - } + if (dmevh->uuid) { + if (!dm_task_set_uuid(dmt, dmevh->uuid)) + goto_bad; + } else if (dmevh->dev_name) { + if (!dm_task_set_name(dmt, dmevh->dev_name)) + goto_bad; + } else if (dmevh->major && dmevh->minor) { + if (!dm_task_set_major(dmt, dmevh->major) || + !dm_task_set_minor(dmt, dmevh->minor)) + goto_bad; + } /* FIXME Add name or uuid or devno to messages */ if (!dm_task_run(dmt)) { log_error("_get_device_info: dm_task_run() failed"); - goto failed; + goto bad; } if (!dm_task_get_info(dmt, &info)) { log_error("_get_device_info: failed to get info for device"); - goto failed; + goto bad; } if (!info.exists) { - log_error("_get_device_info: device not found"); - goto failed; + log_error("_get_device_info: %s%s%s%.0d%s%.0d%s%s: device not found", + dmevh->uuid ? : "", + (!dmevh->uuid && dmevh->dev_name) ? dmevh->dev_name : "", + (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? "(" : "", + (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? dmevh->major : 0, + (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ":" : "", + (!dmevh->uuid && !dmevh->dev_name && dmevh->minor > 0) ? dmevh->minor : 0, + (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) && dmevh->minor == 0 ? "0" : "", + (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ") " : ""); + goto bad; } + return dmt; -failed: + bad: dm_task_destroy(dmt); return NULL; } @@ -715,17 +724,18 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next) uuid = dm_task_get_uuid(dmt); - if (!(ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE : - DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path, - &msg, dmevh->dso, uuid, dmevh->mask, 0))) { - /* FIXME this will probably horribly break if we get - ill-formatted reply */ - ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask); - } else { + if (_do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE : + DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path, + &msg, dmevh->dso, uuid, dmevh->mask, 0)) { + log_debug("%s: device not registered.", dm_task_get_name(dmt)); ret = -ENOENT; goto fail; } + /* FIXME this will probably horribly break if we get + ill-formatted reply */ + ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask); + dm_task_destroy(dmt); dmt = NULL; @@ -733,6 +743,10 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next) msg.data = NULL; _dm_event_handler_clear_dev_info(dmevh); + if (!reply_uuid) { + ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */ + goto fail; + } dmevh->uuid = dm_strdup(reply_uuid); if (!dmevh->uuid) { ret = -ENOMEM; @@ -781,6 +795,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, ' '); /* Message ID */ + if (!p) return 0; + p = strchr(p + 1, ' '); /* HELLO */ + if (!p) return 0; + p = strchr(p + 1, ' '); /* 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) |