X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fbin%2Flttng-relayd%2Fmain.c;h=c4c609a4f2ecf0c5d20d3960d3395e44fbdf7e51;hb=a1ae2ea59428174575b7328b1062a6248d636b72;hp=7b313818e5c09a5719339740f47b2787304d461b;hpb=98ba050ed140ff29ac98f66dba0e47db70e4a0c5;p=lttng-tools.git diff --git a/src/bin/lttng-relayd/main.c b/src/bin/lttng-relayd/main.c index 7b313818e..c4c609a4f 100644 --- a/src/bin/lttng-relayd/main.c +++ b/src/bin/lttng-relayd/main.c @@ -70,6 +70,15 @@ #include "stream.h" #include "connection.h" #include "tracefile-array.h" +#include "tcp_keep_alive.h" + +static const char *help_msg = +#ifdef LTTNG_EMBED_HELP +#include +#else +NULL +#endif +; /* command line options */ char *opt_output_path; @@ -250,9 +259,9 @@ static int set_option(int opt, const char *arg, const char *optname) } break; case 'h': - ret = utils_show_man_page(8, "lttng-relayd"); + ret = utils_show_help(8, "lttng-relayd", help_msg); if (ret) { - ERR("Cannot view man page lttng-relayd(8)"); + ERR("Cannot show --help for `lttng-relayd`"); perror("exec"); } exit(EXIT_FAILURE); @@ -891,6 +900,15 @@ restart: lttcomm_destroy_sock(newsock); goto error; } + + ret = socket_apply_keep_alive_config(newsock->fd); + if (ret < 0) { + ERR("Failed to apply TCP keep-alive configuration on socket (%i)", + newsock->fd); + lttcomm_destroy_sock(newsock); + goto error; + } + new_conn = connection_create(newsock, type); if (!new_conn) { lttcomm_destroy_sock(newsock); @@ -969,12 +987,16 @@ static void *relay_thread_dispatcher(void *data) health_code_update(); - while (!CMM_LOAD_SHARED(dispatch_thread_exit)) { + for (;;) { health_code_update(); /* Atomically prepare the queue futex */ futex_nto1_prepare(&relay_conn_queue.futex); + if (CMM_LOAD_SHARED(dispatch_thread_exit)) { + break; + } + do { health_code_update(); @@ -1579,6 +1601,7 @@ static int relay_send_version(struct lttcomm_relayd_hdr *recv_hdr, { int ret; struct lttcomm_relayd_version reply, msg; + bool compatible = true; conn->version_check_done = 1; @@ -1603,9 +1626,7 @@ static int relay_send_version(struct lttcomm_relayd_hdr *recv_hdr, if (reply.major != be32toh(msg.major)) { DBG("Incompatible major versions (%u vs %u), deleting session", reply.major, be32toh(msg.major)); - connection_put(conn); - ret = 0; - goto end; + compatible = false; } conn->major = reply.major; @@ -1624,6 +1645,11 @@ static int relay_send_version(struct lttcomm_relayd_hdr *recv_hdr, ERR("Relay sending version"); } + if (!compatible) { + ret = -1; + goto end; + } + DBG("Version check done using protocol %u.%u", conn->major, conn->minor); @@ -2096,6 +2122,118 @@ end_no_session: return ret; } +/* + * relay_mkdir: Create a folder on the disk. + */ +static int relay_mkdir(struct lttcomm_relayd_hdr *recv_hdr, + struct relay_connection *conn) +{ + int ret; + ssize_t network_ret; + struct relay_session *session = conn->session; + struct lttcomm_relayd_mkdir path_info_header; + struct lttcomm_relayd_mkdir *path_info = NULL; + struct lttcomm_relayd_generic_reply reply; + char *path = NULL; + + if (!session || !conn->version_check_done) { + ERR("Trying to rename before version check"); + ret = -1; + goto end_no_session; + } + + if (session->major == 2 && session->minor < 11) { + /* + * This client is not supposed to use this command since + * it predates its introduction. + */ + ERR("relay_mkdir command is unsupported before LTTng 2.11"); + ret = -1; + goto end_no_session; + } + + network_ret = conn->sock->ops->recvmsg(conn->sock, &path_info_header, + sizeof(path_info_header), 0); + if (network_ret < (ssize_t) sizeof(path_info_header)) { + if (network_ret == 0) { + /* Orderly shutdown. Not necessary to print an error. */ + DBG("Socket %d did an orderly shutdown", conn->sock->fd); + } else { + ERR("Reception of mkdir command argument length failed with ret = %zi, expected %zu", + network_ret, sizeof(path_info_header)); + } + ret = -1; + goto end_no_session; + } + + path_info_header.length = be32toh(path_info_header.length); + + /* Ensure that it fits in local path length. */ + if (path_info_header.length >= LTTNG_PATH_MAX) { + ret = -ENAMETOOLONG; + ERR("Path name argument of mkdir command (%" PRIu32 " bytes) exceeds the maximal length allowed (%d bytes)", + path_info_header.length, LTTNG_PATH_MAX); + goto end; + } + + path_info = zmalloc(sizeof(path_info_header) + path_info_header.length); + if (!path_info) { + PERROR("zmalloc of mkdir command path"); + ret = -1; + goto end; + } + + network_ret = conn->sock->ops->recvmsg(conn->sock, path_info->path, + path_info_header.length, 0); + if (network_ret < (ssize_t) path_info_header.length) { + if (network_ret == 0) { + /* Orderly shutdown. Not necessary to print an error. */ + DBG("Socket %d did an orderly shutdown", conn->sock->fd); + } else { + ERR("Reception of mkdir path argument failed with ret = %zi, expected %" PRIu32, + network_ret, path_info_header.length); + } + ret = -1; + goto end_no_session; + } + + path = create_output_path(path_info->path); + if (!path) { + ERR("Failed to create output path"); + ret = -1; + goto end; + } + + ret = utils_mkdir_recursive(path, S_IRWXU | S_IRWXG, -1, -1); + if (ret < 0) { + ERR("relay creating output directory"); + goto end; + } + + ret = 0; + +end: + memset(&reply, 0, sizeof(reply)); + if (ret < 0) { + reply.ret_code = htobe32(LTTNG_ERR_UNK); + } else { + reply.ret_code = htobe32(LTTNG_OK); + } + network_ret = conn->sock->ops->sendmsg(conn->sock, &reply, + sizeof(struct lttcomm_relayd_generic_reply), 0); + if (network_ret < (ssize_t) sizeof(struct lttcomm_relayd_generic_reply)) { + ERR("Failed to send mkdir command status code with ret = %zi, expected %zu", + network_ret, + sizeof(struct lttcomm_relayd_generic_reply)); + ret = -1; + } + +end_no_session: + free(path); + free(path_info); + return ret; +} + /* * Process the commands received on the control socket */ @@ -2144,6 +2282,9 @@ static int relay_process_control(struct lttcomm_relayd_hdr *recv_hdr, case RELAYD_RESET_METADATA: ret = relay_reset_metadata(recv_hdr, conn); break; + case RELAYD_MKDIR: + ret = relay_mkdir(recv_hdr, conn); + break; case RELAYD_UPDATE_SYNC_INFO: default: ERR("Received unknown command (%u)", be32toh(recv_hdr->cmd)); @@ -2937,6 +3078,12 @@ exit_init_data: health_app_destroy(health_relayd); exit_health_app_create: exit_options: + /* + * Wait for all pending call_rcu work to complete before tearing + * down data structures. call_rcu worker may be trying to + * perform lookups in those structures. + */ + rcu_barrier(); relayd_cleanup(); /* Ensure all prior call_rcu are done. */