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:
parent
71f3bbd53f
commit
3f694b1265
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user