mirror of
git://sourceware.org/git/lvm2.git
synced 2025-03-11 20:58:50 +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:
parent
71f3bbd53f
commit
3f694b1265
@ -9,7 +9,7 @@
|
|||||||
#include <errno.h> // ENOMEM
|
#include <errno.h> // ENOMEM
|
||||||
|
|
||||||
daemon_handle daemon_open(daemon_info i) {
|
daemon_handle daemon_open(daemon_info i) {
|
||||||
daemon_handle h = { .protocol = 0 };
|
daemon_handle h = { .protocol_version = 0 };
|
||||||
struct sockaddr_un sockaddr;
|
struct sockaddr_un sockaddr;
|
||||||
|
|
||||||
if ((h.socket_fd = socket(PF_UNIX, SOCK_STREAM /* | SOCK_NONBLOCK */, 0)) < 0) {
|
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");
|
perror("connect");
|
||||||
goto error;
|
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;
|
return h;
|
||||||
error:
|
error:
|
||||||
if (h.socket_fd >= 0)
|
if (h.socket_fd >= 0)
|
||||||
close(h.socket_fd);
|
close(h.socket_fd);
|
||||||
|
if (r.cft)
|
||||||
|
daemon_reply_destroy(r);
|
||||||
h.socket_fd = -1;
|
h.socket_fd = -1;
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
@ -43,6 +61,7 @@ daemon_reply daemon_send(daemon_handle h, daemon_request rq)
|
|||||||
|
|
||||||
assert(rq.buffer);
|
assert(rq.buffer);
|
||||||
write_buffer(h.socket_fd, rq.buffer, strlen(rq.buffer));
|
write_buffer(h.socket_fd, rq.buffer, strlen(rq.buffer));
|
||||||
|
dm_free(rq.buffer);
|
||||||
|
|
||||||
if (read_buffer(h.socket_fd, &reply.buffer)) {
|
if (read_buffer(h.socket_fd, &reply.buffer)) {
|
||||||
reply.cft = dm_config_from_string(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) {
|
void daemon_reply_destroy(daemon_reply r) {
|
||||||
if (r.cft)
|
if (r.cft)
|
||||||
dm_config_destroy(r.cft);
|
dm_config_destroy(r.cft);
|
||||||
|
dm_free(r.buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
daemon_reply daemon_send_simple(daemon_handle h, const char *id, ...)
|
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;
|
return err;
|
||||||
|
|
||||||
repl = daemon_send(h, rq);
|
repl = daemon_send(h, rq);
|
||||||
dm_free(rq.buffer);
|
|
||||||
return repl;
|
return repl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void daemon_close(daemon_handle h)
|
void daemon_close(daemon_handle h)
|
||||||
{
|
{
|
||||||
|
dm_free((char *)h.protocol);
|
||||||
}
|
}
|
||||||
|
@ -19,13 +19,21 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int socket_fd; /* the fd we use to talk to the daemon */
|
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;
|
} daemon_handle;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *path; /* the binary of the daemon */
|
const char *path; /* the binary of the daemon */
|
||||||
const char *socket; /* path to the comms socket */
|
const char *socket; /* path to the comms socket */
|
||||||
unsigned autostart:1; /* start the daemon if not running? */
|
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;
|
} daemon_info;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -239,6 +239,19 @@ static int buffer_line(const char *line, void *baton) {
|
|||||||
return 0;
|
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)
|
static void *client_thread(void *baton)
|
||||||
{
|
{
|
||||||
struct thread_baton *b = baton;
|
struct thread_baton *b = baton;
|
||||||
@ -252,7 +265,11 @@ static void *client_thread(void *baton)
|
|||||||
req.cft = dm_config_from_string(req.buffer);
|
req.cft = dm_config_from_string(req.buffer);
|
||||||
if (!req.cft)
|
if (!req.cft)
|
||||||
fprintf(stderr, "error parsing request:\n %s\n", req.buffer);
|
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) {
|
if (!res.buffer) {
|
||||||
dm_config_write_node(res.cft->root, buffer_line, &res);
|
dm_config_write_node(res.cft->root, buffer_line, &res);
|
||||||
|
@ -78,6 +78,9 @@ typedef struct daemon_state {
|
|||||||
const char *name;
|
const char *name;
|
||||||
const char *pidfile;
|
const char *pidfile;
|
||||||
const char *socket_path;
|
const char *socket_path;
|
||||||
|
const char *protocol;
|
||||||
|
int protocol_version;
|
||||||
|
|
||||||
int log_level;
|
int log_level;
|
||||||
handle_request handler;
|
handle_request handler;
|
||||||
int (*daemon_init)(struct daemon_state *st);
|
int (*daemon_init)(struct daemon_state *st);
|
||||||
|
@ -64,6 +64,8 @@ static inline daemon_handle lvmetad_open(const char *socket)
|
|||||||
daemon_info lvmetad_info = {
|
daemon_info lvmetad_info = {
|
||||||
.path = "lvmetad",
|
.path = "lvmetad",
|
||||||
.socket = socket ?: DEFAULT_RUN_DIR "/lvmetad.socket",
|
.socket = socket ?: DEFAULT_RUN_DIR "/lvmetad.socket",
|
||||||
|
.protocol = "lvmetad",
|
||||||
|
.protocol_version = 1,
|
||||||
.autostart = 0
|
.autostart = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -984,6 +984,8 @@ int main(int argc, char *argv[])
|
|||||||
s.socket_path = DEFAULT_RUN_DIR "/lvmetad.socket";
|
s.socket_path = DEFAULT_RUN_DIR "/lvmetad.socket";
|
||||||
s.pidfile = DEFAULT_RUN_DIR "/lvmetad.pid";
|
s.pidfile = DEFAULT_RUN_DIR "/lvmetad.pid";
|
||||||
s.log_level = 0;
|
s.log_level = 0;
|
||||||
|
s.protocol = "lvmetad";
|
||||||
|
s.protocol_version = 1;
|
||||||
|
|
||||||
// use getopt_long
|
// use getopt_long
|
||||||
while ((opt = getopt(argc, argv, "?fhVdRs:")) != EOF) {
|
while ((opt = getopt(argc, argv, "?fhVdRs:")) != EOF) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user