mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-03 05:18:29 +03:00
o adds dm_get_next_registered_device() (not functional yet)
to retrieve which devices got registered with the daemon; needs locking changes as well
This commit is contained in:
parent
b0c36cbd57
commit
e4fe47bc19
@ -109,13 +109,14 @@ struct dso_data {
|
|||||||
static LIST_INIT(dso_registry);
|
static LIST_INIT(dso_registry);
|
||||||
|
|
||||||
/* Structure to keep parsed register variables from client message. */
|
/* Structure to keep parsed register variables from client message. */
|
||||||
struct register_data {
|
struct message_data {
|
||||||
char *dso_name; /* Name of DSO. */
|
char *dso_name; /* Name of DSO. */
|
||||||
char *device_path; /* Mapped device path. */
|
char *device_path; /* Mapped device path. */
|
||||||
union {
|
union {
|
||||||
char *str; /* Events string as fetched from message. */
|
char *str; /* Events string as fetched from message. */
|
||||||
enum event_type field; /* Events bitfield. */
|
enum event_type field; /* Events bitfield. */
|
||||||
} events;
|
} events;
|
||||||
|
struct daemon_message *msg; /* Pointer to message buffer. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -139,7 +140,7 @@ struct thread_status {
|
|||||||
static LIST_INIT(thread_registry);
|
static LIST_INIT(thread_registry);
|
||||||
|
|
||||||
/* Allocate/free the status structure for a monitoring thread. */
|
/* Allocate/free the status structure for a monitoring thread. */
|
||||||
static struct thread_status *alloc_thread_status(struct register_data *data,
|
static struct thread_status *alloc_thread_status(struct message_data *data,
|
||||||
struct dso_data *dso_data)
|
struct dso_data *dso_data)
|
||||||
{
|
{
|
||||||
struct thread_status *ret = (typeof(ret)) dbg_malloc(sizeof(*ret));
|
struct thread_status *ret = (typeof(ret)) dbg_malloc(sizeof(*ret));
|
||||||
@ -165,7 +166,7 @@ static void free_thread_status(struct thread_status *thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate/free DSO data. */
|
/* Allocate/free DSO data. */
|
||||||
static struct dso_data *alloc_dso_data(struct register_data *data)
|
static struct dso_data *alloc_dso_data(struct message_data *data)
|
||||||
{
|
{
|
||||||
struct dso_data *ret = (typeof(ret)) dbg_malloc(sizeof(*ret));
|
struct dso_data *ret = (typeof(ret)) dbg_malloc(sizeof(*ret));
|
||||||
|
|
||||||
@ -187,12 +188,13 @@ static void free_dso_data(struct dso_data *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fetch a string off src and duplicate it into *dest. */
|
/* Fetch a string off src and duplicate it into *dest. */
|
||||||
|
/* FIXME: move to separate module to share with the client lib. */
|
||||||
static const char delimiter = ' ';
|
static const char delimiter = ' ';
|
||||||
static char *fetch_string(char **src)
|
static char *fetch_string(char **src)
|
||||||
{
|
{
|
||||||
char *p, *ret;
|
char *p, *ret = NULL;
|
||||||
|
|
||||||
if ((p = strchr(*src, delimiter)))
|
if ((p = strchr(*src, delimiter))) {
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
if ((ret = dbg_strdup(*src)))
|
if ((ret = dbg_strdup(*src)))
|
||||||
@ -200,44 +202,51 @@ static char *fetch_string(char **src)
|
|||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
*p = delimiter;
|
*p = delimiter;
|
||||||
|
} else if (*src)
|
||||||
|
ret = dbg_strdup(*src);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free message memory. */
|
/* Free message memory. */
|
||||||
static void free_message(struct register_data *register_data)
|
static void free_message(struct message_data *message_data)
|
||||||
{
|
{
|
||||||
if (register_data->dso_name)
|
if (message_data->dso_name)
|
||||||
dbg_free(register_data->dso_name);
|
dbg_free(message_data->dso_name);
|
||||||
|
|
||||||
if (register_data->device_path)
|
if (message_data->device_path)
|
||||||
dbg_free(register_data->device_path);
|
dbg_free(message_data->device_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse a register message from the client. */
|
/* Parse a register message from the client. */
|
||||||
static int parse_message(struct register_data *register_data, char *msg)
|
static int parse_message(struct message_data *message_data)
|
||||||
{
|
{
|
||||||
char *p = msg;
|
char *p = message_data->msg->msg;
|
||||||
|
|
||||||
memset(register_data, 0, sizeof(*register_data));
|
memset(message_data, 0, sizeof(*message_data));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Retrieve application identifier, mapped device
|
* Retrieve application identifier, mapped device
|
||||||
* path and events # string from message.
|
* path and events # string from message.
|
||||||
*/
|
*/
|
||||||
if ((register_data->dso_name = fetch_string(&p)) &&
|
if ((message_data->dso_name = fetch_string(&p)) &&
|
||||||
(register_data->device_path = fetch_string(&p)) &&
|
(message_data->device_path = fetch_string(&p)) &&
|
||||||
(register_data->events.str = fetch_string(&p))) {
|
(message_data->events.str = fetch_string(&p))) {
|
||||||
enum event_type i = atoi(register_data->events.str);
|
if (message_data->events.str) {
|
||||||
|
enum event_type i = atoi(message_data->events.str);
|
||||||
|
|
||||||
/* Free string representaion of events. Not needed an more. */
|
/*
|
||||||
dbg_free(register_data->events.str);
|
* Free string representaion of events.
|
||||||
register_data->events.field = i;
|
* Not needed an more.
|
||||||
|
*/
|
||||||
|
dbg_free(message_data->events.str);
|
||||||
|
message_data->events.field = i;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_message(register_data);
|
free_message(message_data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
@ -336,7 +345,7 @@ static int device_exists(char *device)
|
|||||||
*
|
*
|
||||||
* Mutex must be hold when calling this.
|
* Mutex must be hold when calling this.
|
||||||
*/
|
*/
|
||||||
static struct thread_status *lookup_thread_status(struct register_data *data)
|
static struct thread_status *lookup_thread_status(struct message_data *data)
|
||||||
{
|
{
|
||||||
struct thread_status *thread;
|
struct thread_status *thread;
|
||||||
|
|
||||||
@ -361,7 +370,8 @@ static int error_detected(struct thread_status *thread, char *params)
|
|||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if ((len = strlen(params)) && params[len - 1] == 'F') {
|
if ((len = strlen(params)) &&
|
||||||
|
params[len - 1] == 'F') {
|
||||||
thread->current_events |= DEVICE_ERROR;
|
thread->current_events |= DEVICE_ERROR;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -391,7 +401,7 @@ static int event_wait(struct thread_status *thread)
|
|||||||
&target_type, ¶ms);
|
&target_type, ¶ms);
|
||||||
|
|
||||||
log_print("%s: %s\n", __func__, params);
|
log_print("%s: %s\n", __func__, params);
|
||||||
if (error_detected(thread, params))
|
if ((ret = error_detected(thread, params)))
|
||||||
break;
|
break;
|
||||||
} while(next);
|
} while(next);
|
||||||
}
|
}
|
||||||
@ -431,7 +441,7 @@ static void monitor_unregister(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Device monitoring thread. */
|
/* Device monitoring thread. */
|
||||||
void *monitor_thread(void *arg)
|
static void *monitor_thread(void *arg)
|
||||||
{
|
{
|
||||||
struct thread_status *thread = arg;
|
struct thread_status *thread = arg;
|
||||||
|
|
||||||
@ -452,7 +462,14 @@ void *monitor_thread(void *arg)
|
|||||||
/* REMOVEME: */
|
/* REMOVEME: */
|
||||||
log_print("%s: cycle on %s\n", __func__, thread->device_path);
|
log_print("%s: cycle on %s\n", __func__, thread->device_path);
|
||||||
|
|
||||||
/* Check against filter. */
|
/*
|
||||||
|
* Check against filter.
|
||||||
|
*
|
||||||
|
* If there's current events delivered from event_wait() AND
|
||||||
|
* the device got registered for those events AND
|
||||||
|
* those events haven't been processed yet, call
|
||||||
|
* the DSO's process_event() handler.
|
||||||
|
*/
|
||||||
if (thread->events &
|
if (thread->events &
|
||||||
thread->current_events &
|
thread->current_events &
|
||||||
~thread->processed_events) {
|
~thread->processed_events) {
|
||||||
@ -492,7 +509,7 @@ static void lib_put(struct dso_data *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Find DSO data. */
|
/* Find DSO data. */
|
||||||
static struct dso_data *lookup_dso(struct register_data *data)
|
static struct dso_data *lookup_dso(struct message_data *data)
|
||||||
{
|
{
|
||||||
struct dso_data *dso_data, *ret = NULL;
|
struct dso_data *dso_data, *ret = NULL;
|
||||||
|
|
||||||
@ -500,8 +517,8 @@ static struct dso_data *lookup_dso(struct register_data *data)
|
|||||||
|
|
||||||
list_iterate_items(dso_data, &dso_registry) {
|
list_iterate_items(dso_data, &dso_registry) {
|
||||||
if (!strcmp(data->dso_name, dso_data->dso_name)) {
|
if (!strcmp(data->dso_name, dso_data->dso_name)) {
|
||||||
|
lib_get(dso_data);
|
||||||
ret = dso_data;
|
ret = dso_data;
|
||||||
lib_get(ret);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -534,7 +551,7 @@ static int lookup_symbols(void *dl, struct dso_data *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create a DSO file name based on its name. */
|
/* Create a DSO file name based on its name. */
|
||||||
static char *create_dso_file(char *dso_name)
|
static char *create_dso_file_name(char *dso_name)
|
||||||
{
|
{
|
||||||
char *ret;
|
char *ret;
|
||||||
static char *prefix = "libdmeventd_";
|
static char *prefix = "libdmeventd_";
|
||||||
@ -549,13 +566,13 @@ static char *create_dso_file(char *dso_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Load an application specific DSO. */
|
/* Load an application specific DSO. */
|
||||||
static struct dso_data *load_dso(struct register_data *data)
|
static struct dso_data *load_dso(struct message_data *data)
|
||||||
{
|
{
|
||||||
void *dl;
|
void *dl;
|
||||||
struct dso_data *ret = NULL;
|
struct dso_data *ret = NULL;
|
||||||
char *dso_file;
|
char *dso_file;
|
||||||
|
|
||||||
if (!(dso_file = create_dso_file(data->dso_name)))
|
if (!(dso_file = create_dso_file_name(data->dso_name)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!(dl = dlopen(dso_file, RTLD_NOW)))
|
if (!(dl = dlopen(dso_file, RTLD_NOW)))
|
||||||
@ -599,32 +616,27 @@ static struct dso_data *load_dso(struct register_data *data)
|
|||||||
* Only one caller at a time here, because we use a FIFO and lock
|
* Only one caller at a time here, because we use a FIFO and lock
|
||||||
* it against multiple accesses.
|
* it against multiple accesses.
|
||||||
*/
|
*/
|
||||||
static int register_for_event(char *msg)
|
static int register_for_event(struct message_data *message_data)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct register_data register_data;
|
|
||||||
struct thread_status *thread, *thread_new;
|
struct thread_status *thread, *thread_new;
|
||||||
struct dso_data *dso_data;
|
struct dso_data *dso_data;
|
||||||
|
|
||||||
/* Parse the register message and find/load the appropriate DSO. */
|
if (!device_exists(message_data->device_path)) {
|
||||||
if (!parse_message(®ister_data, msg))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (!device_exists(register_data.device_path)) {
|
|
||||||
stack;
|
stack;
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dso_data = lookup_dso(®ister_data)) &&
|
if (!(dso_data = lookup_dso(message_data)) &&
|
||||||
!(dso_data = load_dso(®ister_data))) {
|
!(dso_data = load_dso(message_data))) {
|
||||||
stack;
|
stack;
|
||||||
ret = -ELIBACC;
|
ret = -ELIBACC;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Preallocate thread status struct to avoid deadlock. */
|
/* Preallocate thread status struct to avoid deadlock. */
|
||||||
if (!(thread_new = alloc_thread_status(®ister_data, dso_data))) {
|
if (!(thread_new = alloc_thread_status(message_data, dso_data))) {
|
||||||
stack;
|
stack;
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
@ -635,7 +647,7 @@ static int register_for_event(char *msg)
|
|||||||
|
|
||||||
lock_mutex();
|
lock_mutex();
|
||||||
|
|
||||||
if ((thread = lookup_thread_status(®ister_data)))
|
if ((thread = lookup_thread_status(message_data)))
|
||||||
ret = -EPERM;
|
ret = -EPERM;
|
||||||
else {
|
else {
|
||||||
thread = thread_new;
|
thread = thread_new;
|
||||||
@ -651,7 +663,7 @@ static int register_for_event(char *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Or event # into events bitfield. */
|
/* Or event # into events bitfield. */
|
||||||
thread->events |= register_data.events.field;
|
thread->events |= message_data->events.field;
|
||||||
|
|
||||||
unlock_mutex();
|
unlock_mutex();
|
||||||
|
|
||||||
@ -663,7 +675,7 @@ static int register_for_event(char *msg)
|
|||||||
free_thread_status(thread_new);
|
free_thread_status(thread_new);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free_message(®ister_data);
|
free_message(message_data);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -673,29 +685,24 @@ static int register_for_event(char *msg)
|
|||||||
*
|
*
|
||||||
* Only one caller at a time here as with register_for_event().
|
* Only one caller at a time here as with register_for_event().
|
||||||
*/
|
*/
|
||||||
static int unregister_for_event(char *msg)
|
static int unregister_for_event(struct message_data *message_data)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct register_data register_data;
|
|
||||||
struct thread_status *thread;
|
struct thread_status *thread;
|
||||||
|
|
||||||
if (!parse_message(®ister_data, msg))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear event in bitfield and deactivate
|
* Clear event in bitfield and deactivate
|
||||||
* monitoring thread in case bitfield is 0.
|
* monitoring thread in case bitfield is 0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
lock_mutex();
|
lock_mutex();
|
||||||
|
|
||||||
if (!(thread = lookup_thread_status(®ister_data))) {
|
if (!(thread = lookup_thread_status(message_data))) {
|
||||||
unlock_mutex();
|
unlock_mutex();
|
||||||
ret = -ESRCH;
|
ret = -ESRCH;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread->events &= ~register_data.events.field;
|
thread->events &= ~message_data->events.field;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In case there's no events to monitor on this
|
* In case there's no events to monitor on this
|
||||||
@ -724,11 +731,58 @@ static int unregister_for_event(char *msg)
|
|||||||
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free_message(®ister_data);
|
free_message(message_data);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get next registered device.
|
||||||
|
*
|
||||||
|
* Only one caller at a time here as with register_for_event().
|
||||||
|
*/
|
||||||
|
static int next_registered_device(struct message_data *message_data)
|
||||||
|
{
|
||||||
|
struct daemon_message *msg = message_data->msg;
|
||||||
|
|
||||||
|
snprintf(msg->msg, sizeof(msg->msg), "%s %s %u",
|
||||||
|
message_data->dso_name, message_data->device_path,
|
||||||
|
message_data->events.field);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct list *device_iter = NULL;
|
||||||
|
static int get_next_registered_device(struct message_data *message_data)
|
||||||
|
{
|
||||||
|
struct thread_status *thread;
|
||||||
|
|
||||||
|
if (!device_iter) {
|
||||||
|
if (list_empty(&thread_registry))
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
device_iter = thread_registry.n;
|
||||||
|
} else if (device_iter == &thread_registry) {
|
||||||
|
device_iter = NULL;
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread = list_item(device_iter, struct thread_status);
|
||||||
|
device_iter = device_iter->n;
|
||||||
|
|
||||||
|
log_print("%s: device_path: %s\n", __func__, message_data->device_path);
|
||||||
|
if (message_data->device_path &&
|
||||||
|
!strcmp(thread->device_path, message_data->device_path))
|
||||||
|
return next_registered_device(message_data);
|
||||||
|
|
||||||
|
log_print("%s: dso_name: %s\n", __func__, message_data->dso_name);
|
||||||
|
if (message_data->dso_name &&
|
||||||
|
!strcmp(thread->dso_data->dso_name, message_data->dso_name))
|
||||||
|
return next_registered_device(message_data);
|
||||||
|
|
||||||
|
return next_registered_device(message_data);
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize a fifos structure with path names. */
|
/* Initialize a fifos structure with path names. */
|
||||||
static void init_fifos(struct fifos *fifos)
|
static void init_fifos(struct fifos *fifos)
|
||||||
{
|
{
|
||||||
@ -797,28 +851,39 @@ static int client_write(struct fifos *fifos, struct daemon_message *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Process a request passed from the communication thread. */
|
/* Process a request passed from the communication thread. */
|
||||||
static int _process_request(struct daemon_message *msg)
|
static int do_process_request(struct daemon_message *msg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
static struct message_data message_data;
|
||||||
|
|
||||||
|
/* Parse the message. */
|
||||||
|
message_data.msg = msg;
|
||||||
|
if (msg->opcode.cmd != CMD_ACTIVE &&
|
||||||
|
!parse_message(&message_data)) {
|
||||||
|
stack;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check the request type. */
|
/* Check the request type. */
|
||||||
switch (msg->opcode.cmd) {
|
switch (msg->opcode.cmd) {
|
||||||
case CMD_ACTIVE:
|
case CMD_ACTIVE:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_REGISTER_FOR_EVENT:
|
case CMD_REGISTER_FOR_EVENT:
|
||||||
ret = register_for_event(msg->msg);
|
ret = register_for_event(&message_data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_UNREGISTER_FOR_EVENT:
|
case CMD_UNREGISTER_FOR_EVENT:
|
||||||
ret = unregister_for_event(msg->msg);
|
ret = unregister_for_event(&message_data);
|
||||||
|
break;
|
||||||
|
case CMD_GET_NEXT_REGISTERED_DEVICE:
|
||||||
|
ret = get_next_registered_device(&message_data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Only one caller at a time. */
|
||||||
static void process_request(struct fifos *fifos, struct daemon_message *msg)
|
static void process_request(struct fifos *fifos, struct daemon_message *msg)
|
||||||
{
|
{
|
||||||
/* Read the request from the client. */
|
/* Read the request from the client. */
|
||||||
@ -828,7 +893,7 @@ static void process_request(struct fifos *fifos, struct daemon_message *msg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg->opcode.status = _process_request(msg);
|
msg->opcode.status = do_process_request(msg);
|
||||||
|
|
||||||
memset(&msg->msg, 0, sizeof(msg->msg));
|
memset(&msg->msg, 0, sizeof(msg->msg));
|
||||||
if (!client_write(fifos, msg))
|
if (!client_write(fifos, msg))
|
||||||
|
@ -30,6 +30,7 @@ enum dmeventd_command {
|
|||||||
CMD_ACTIVE = 1,
|
CMD_ACTIVE = 1,
|
||||||
CMD_REGISTER_FOR_EVENT,
|
CMD_REGISTER_FOR_EVENT,
|
||||||
CMD_UNREGISTER_FOR_EVENT,
|
CMD_UNREGISTER_FOR_EVENT,
|
||||||
|
CMD_GET_NEXT_REGISTERED_DEVICE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Message passed between client and daemon. */
|
/* Message passed between client and daemon. */
|
||||||
@ -65,6 +66,8 @@ enum event_type {
|
|||||||
int dm_register_for_event(char *dso_name, char *device, enum event_type events);
|
int dm_register_for_event(char *dso_name, char *device, enum event_type events);
|
||||||
int dm_unregister_for_event(char *dso_name, char *device,
|
int dm_unregister_for_event(char *dso_name, char *device,
|
||||||
enum event_type events);
|
enum event_type events);
|
||||||
|
int dm_get_next_registered_device(char **dso_name, char **device,
|
||||||
|
enum event_type *events);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user