1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-03-10 16:58:47 +03:00

Couple of improvements in the daemon (common + lvmetad) code:

- some client-side memory leak fixes
- announce and check protocols and protocol versions
This commit is contained in:
Petr Rockai 2012-02-23 23:52:11 +00:00
parent 71f3bbd53f
commit 3f694b1265
6 changed files with 56 additions and 4 deletions

View File

@ -9,7 +9,7 @@
#include <errno.h> // ENOMEM
daemon_handle daemon_open(daemon_info i) {
daemon_handle h = { .protocol = 0 };
daemon_handle h = { .protocol_version = 0 };
struct sockaddr_un sockaddr;
if ((h.socket_fd = socket(PF_UNIX, SOCK_STREAM /* | SOCK_NONBLOCK */, 0)) < 0) {
@ -24,10 +24,28 @@ daemon_handle daemon_open(daemon_info i) {
perror("connect");
goto error;
}
daemon_reply r = daemon_send_simple(h, "hello", NULL);
if (r.error || strcmp(daemon_reply_str(r, "response", "unknown"), "OK"))
goto error;
h.protocol = daemon_reply_str(r, "protocol", NULL);
if (h.protocol)
h.protocol = dm_strdup(h.protocol); /* keep around */
h.protocol_version = daemon_reply_int(r, "version", 0);
if (i.protocol && (!h.protocol || strcmp(h.protocol, i.protocol)))
goto error;
if (i.protocol_version && h.protocol_version != i.protocol_version)
goto error;
daemon_reply_destroy(r);
return h;
error:
if (h.socket_fd >= 0)
close(h.socket_fd);
if (r.cft)
daemon_reply_destroy(r);
h.socket_fd = -1;
return h;
}
@ -43,6 +61,7 @@ daemon_reply daemon_send(daemon_handle h, daemon_request rq)
assert(rq.buffer);
write_buffer(h.socket_fd, rq.buffer, strlen(rq.buffer));
dm_free(rq.buffer);
if (read_buffer(h.socket_fd, &reply.buffer)) {
reply.cft = dm_config_from_string(reply.buffer);
@ -55,6 +74,7 @@ daemon_reply daemon_send(daemon_handle h, daemon_request rq)
void daemon_reply_destroy(daemon_reply r) {
if (r.cft)
dm_config_destroy(r.cft);
dm_free(r.buffer);
}
daemon_reply daemon_send_simple(daemon_handle h, const char *id, ...)
@ -72,10 +92,10 @@ daemon_reply daemon_send_simple(daemon_handle h, const char *id, ...)
return err;
repl = daemon_send(h, rq);
dm_free(rq.buffer);
return repl;
}
void daemon_close(daemon_handle h)
{
dm_free((char *)h.protocol);
}

View File

@ -19,13 +19,21 @@
typedef struct {
int socket_fd; /* the fd we use to talk to the daemon */
int protocol; /* version of the protocol the daemon uses */
const char *protocol;
int protocol_version; /* version of the protocol the daemon uses */
} daemon_handle;
typedef struct {
const char *path; /* the binary of the daemon */
const char *socket; /* path to the comms socket */
unsigned autostart:1; /* start the daemon if not running? */
/*
* If the following are not NULL/0, an attempt to talk to a daemon which
* uses a different protocol or version will fail.
*/
const char *protocol;
int protocol_version;
} daemon_info;
typedef struct {

View File

@ -239,6 +239,19 @@ static int buffer_line(const char *line, void *baton) {
return 0;
}
static response builtin_handler(daemon_state s, client_handle h, request r)
{
const char *rq = daemon_request_str(r, "request", "NONE");
if (!strcmp(rq, "hello")) {
return daemon_reply_simple("OK", "protocol = %s", s.protocol ?: "default",
"version = %d", s.protocol_version, NULL);
}
response res = { .buffer = NULL, .error = EPROTO };
return res;
}
static void *client_thread(void *baton)
{
struct thread_baton *b = baton;
@ -252,7 +265,11 @@ static void *client_thread(void *baton)
req.cft = dm_config_from_string(req.buffer);
if (!req.cft)
fprintf(stderr, "error parsing request:\n %s\n", req.buffer);
res = b->s.handler(b->s, b->client, req);
res = builtin_handler(b->s, b->client, req);
if (res.error == EPROTO) /* Not a builtin, delegate to the custom handler. */
res = b->s.handler(b->s, b->client, req);
if (!res.buffer) {
dm_config_write_node(res.cft->root, buffer_line, &res);

View File

@ -78,6 +78,9 @@ typedef struct daemon_state {
const char *name;
const char *pidfile;
const char *socket_path;
const char *protocol;
int protocol_version;
int log_level;
handle_request handler;
int (*daemon_init)(struct daemon_state *st);

View File

@ -64,6 +64,8 @@ static inline daemon_handle lvmetad_open(const char *socket)
daemon_info lvmetad_info = {
.path = "lvmetad",
.socket = socket ?: DEFAULT_RUN_DIR "/lvmetad.socket",
.protocol = "lvmetad",
.protocol_version = 1,
.autostart = 0
};

View File

@ -984,6 +984,8 @@ int main(int argc, char *argv[])
s.socket_path = DEFAULT_RUN_DIR "/lvmetad.socket";
s.pidfile = DEFAULT_RUN_DIR "/lvmetad.pid";
s.log_level = 0;
s.protocol = "lvmetad";
s.protocol_version = 1;
// use getopt_long
while ((opt = getopt(argc, argv, "?fhVdRs:")) != EOF) {