*/
int buffer_reg_uid_create(uint64_t session_id, uint32_t bits_per_long, uid_t uid,
enum lttng_domain_type domain, struct buffer_reg_uid **regp,
- const char *shm_path)
+ const char *root_shm_path, const char *shm_path)
{
int ret = 0;
struct buffer_reg_uid *reg = NULL;
reg->uid = uid;
reg->domain = domain;
if (shm_path[0]) {
+ strncpy(reg->root_shm_path, root_shm_path, sizeof(reg->root_shm_path));
+ reg->root_shm_path[sizeof(reg->root_shm_path) - 1] = '\0';
strncpy(reg->shm_path, shm_path, sizeof(reg->shm_path));
reg->shm_path[sizeof(reg->shm_path) - 1] = '\0';
DBG3("shm path '%s' is assigned to uid buffer registry for session id %" PRIu64,
* Return 0 on success else a negative value and regp is untouched.
*/
int buffer_reg_pid_create(uint64_t session_id, struct buffer_reg_pid **regp,
- const char *shm_path)
+ const char *root_shm_path, const char *shm_path)
{
int ret = 0;
struct buffer_reg_pid *reg = NULL;
/* A cast is done here so we can use the session ID as a u64 ht node. */
reg->session_id = session_id;
if (shm_path[0]) {
+ strncpy(reg->root_shm_path, root_shm_path, sizeof(reg->root_shm_path));
+ reg->root_shm_path[sizeof(reg->root_shm_path) - 1] = '\0';
strncpy(reg->shm_path, shm_path, sizeof(reg->shm_path));
reg->shm_path[sizeof(reg->shm_path) - 1] = '\0';
DBG3("shm path '%s' is assigned to pid buffer registry for session id %" PRIu64,
/* Node of a linked list used to teardown object at a destroy session. */
struct cds_list_head lnode;
+ char root_shm_path[PATH_MAX];
char shm_path[PATH_MAX];
};
/* Indexed by session id. */
struct lttng_ht_node_u64 node;
+ char root_shm_path[PATH_MAX];
char shm_path[PATH_MAX];
};
void buffer_reg_init_uid_registry(void);
int buffer_reg_uid_create(uint64_t session_id, uint32_t bits_per_long, uid_t uid,
enum lttng_domain_type domain, struct buffer_reg_uid **regp,
- const char *shm_path);
+ const char *root_shm_path, const char *shm_path);
void buffer_reg_uid_add(struct buffer_reg_uid *reg);
struct buffer_reg_uid *buffer_reg_uid_find(uint64_t session_id,
uint32_t bits_per_long, uid_t uid);
/* Buffer registry per PID. */
void buffer_reg_init_pid_registry(void);
int buffer_reg_pid_create(uint64_t session_id, struct buffer_reg_pid **regp,
- const char *shm_path);
+ const char *root_shm_path, const char *shm_path);
void buffer_reg_pid_add(struct buffer_reg_pid *reg);
struct buffer_reg_pid *buffer_reg_pid_find(uint64_t session_id);
void buffer_reg_pid_remove(struct buffer_reg_pid *regp);
uint64_t session_id_per_pid,
unsigned int monitor,
uint32_t ust_app_uid,
+ const char *root_shm_path,
const char *shm_path)
{
assert(msg);
strncpy(msg->u.ask_channel.name, name, sizeof(msg->u.ask_channel.name));
msg->u.ask_channel.name[sizeof(msg->u.ask_channel.name) - 1] = '\0';
+ if (root_shm_path) {
+ strncpy(msg->u.ask_channel.root_shm_path, root_shm_path,
+ sizeof(msg->u.ask_channel.root_shm_path));
+ msg->u.ask_channel.root_shm_path[sizeof(msg->u.ask_channel.root_shm_path) - 1] = '\0';
+ }
if (shm_path) {
strncpy(msg->u.ask_channel.shm_path, shm_path,
sizeof(msg->u.ask_channel.shm_path));
uint64_t session_id_per_pid,
unsigned int monitor,
uint32_t ust_app_uid,
+ const char *root_shm_path,
const char *shm_path);
void consumer_init_stream_comm_msg(struct lttcomm_consumer_msg *msg,
enum lttng_consumer_command cmd,
lus->live_timer_interval = session->live_timer;
session->ust_session = lus;
if (session->shm_path[0]) {
+ strncpy(lus->root_shm_path, session->shm_path,
+ sizeof(lus->root_shm_path));
+ lus->root_shm_path[sizeof(lus->root_shm_path) - 1] = '\0';
strncpy(lus->shm_path, session->shm_path,
sizeof(lus->shm_path));
lus->shm_path[sizeof(lus->shm_path) - 1] = '\0';
#include <string.h>
#include <sys/stat.h>
#include <urcu.h>
+#include <dirent.h>
+#include <sys/types.h>
#include <common/common.h>
#include <common/sessiond-comm/sessiond-comm.h>
/*
* Path where to keep the shared memory files.
*/
+ char root_shm_path[PATH_MAX];
char shm_path[PATH_MAX];
};
goto error;
}
+ strncpy(ua_sess->root_shm_path, usess->root_shm_path,
+ sizeof(ua_sess->root_shm_path));
+ ua_sess->root_shm_path[sizeof(ua_sess->root_shm_path) - 1] = '\0';
strncpy(ua_sess->shm_path, usess->shm_path,
sizeof(ua_sess->shm_path));
ua_sess->shm_path[sizeof(ua_sess->shm_path) - 1] = '\0';
* registry available, we have to create one for this session.
*/
ret = buffer_reg_pid_create(ua_sess->id, ®_pid,
- ua_sess->shm_path);
+ ua_sess->root_shm_path, ua_sess->shm_path);
if (ret < 0) {
goto error;
}
app->uint16_t_alignment, app->uint32_t_alignment,
app->uint64_t_alignment, app->long_alignment,
app->byte_order, app->version.major,
- app->version.minor, reg_pid->shm_path,
+ app->version.minor, reg_pid->root_shm_path,
+ reg_pid->shm_path,
ua_sess->euid, ua_sess->egid);
if (ret < 0) {
/*
* registry available, we have to create one for this session.
*/
ret = buffer_reg_uid_create(usess->id, app->bits_per_long, app->uid,
- LTTNG_DOMAIN_UST, ®_uid, ua_sess->shm_path);
+ LTTNG_DOMAIN_UST, ®_uid,
+ ua_sess->root_shm_path, ua_sess->shm_path);
if (ret < 0) {
goto error;
}
app->uint16_t_alignment, app->uint32_t_alignment,
app->uint64_t_alignment, app->long_alignment,
app->byte_order, app->version.major,
- app->version.minor, reg_uid->shm_path,
- usess->uid, usess->gid);
+ app->version.minor, reg_uid->root_shm_path,
+ reg_uid->shm_path, usess->uid, usess->gid);
if (ret < 0) {
/*
* reg_uid->registry->reg.ust is NULL upon error, so we need to
/* Metadata channel attributes. */
struct ustctl_consumer_channel_attr metadata_attr;
+ char root_shm_path[PATH_MAX];
char shm_path[PATH_MAX];
};
struct lttcomm_consumer_msg msg;
struct ust_registry_channel *chan_reg;
char shm_path[PATH_MAX] = "";
+ char root_shm_path[PATH_MAX] = "";
assert(ua_sess);
assert(ua_chan);
strncat(shm_path, "_",
sizeof(shm_path) - strlen(shm_path) - 1);
}
+ strncpy(root_shm_path, ua_sess->root_shm_path, sizeof(root_shm_path));
+ root_shm_path[sizeof(root_shm_path) - 1] = '\0';
}
switch (ua_chan->attr.output) {
ua_sess->id,
ua_sess->output_traces,
ua_sess->uid,
- shm_path);
+ root_shm_path, shm_path);
health_code_update();
int byte_order,
uint32_t major,
uint32_t minor,
+ const char *root_shm_path,
const char *shm_path,
uid_t euid,
gid_t egid)
session->long_alignment = long_alignment;
session->byte_order = byte_order;
session->metadata_fd = -1;
+ strncpy(session->root_shm_path, root_shm_path,
+ sizeof(session->root_shm_path));
+ session->root_shm_path[sizeof(session->root_shm_path) - 1] = '\0';
if (shm_path[0]) {
strncpy(session->shm_path, shm_path,
sizeof(session->shm_path));
PERROR("unlink");
}
}
+ if (reg->root_shm_path[0]) {
+ /*
+ * Try deleting the directory hierarchy.
+ */
+ (void) utils_recursive_rmdir(reg->root_shm_path);
+ }
}
/* Length of bytes sent to the consumer. */
size_t metadata_len_sent;
+ char root_shm_path[PATH_MAX];
char shm_path[PATH_MAX];
char metadata_path[PATH_MAX];
int metadata_fd; /* file-backed metadata FD */
int byte_order,
uint32_t major,
uint32_t minor,
+ const char *root_shm_path,
const char *shm_path,
uid_t euid,
gid_t egid);
uint64_t session_id_per_pid,
unsigned int monitor,
unsigned int live_timer_interval,
+ const char *root_shm_path,
const char *shm_path)
{
struct lttng_consumer_channel *channel;
strncpy(channel->name, name, sizeof(channel->name));
channel->name[sizeof(channel->name) - 1] = '\0';
+ if (root_shm_path) {
+ strncpy(channel->root_shm_path, root_shm_path, sizeof(channel->root_shm_path));
+ channel->root_shm_path[sizeof(channel->root_shm_path) - 1] = '\0';
+ }
if (shm_path) {
strncpy(channel->shm_path, shm_path, sizeof(channel->shm_path));
channel->shm_path[sizeof(channel->shm_path) - 1] = '\0';
/* Timer value in usec for live streaming. */
unsigned int live_timer_interval;
+ char root_shm_path[PATH_MAX];
char shm_path[PATH_MAX];
};
uint64_t session_id_per_pid,
unsigned int monitor,
unsigned int live_timer_interval,
+ const char *root_shm_path,
const char *shm_path);
void consumer_del_stream(struct lttng_consumer_stream *stream,
struct lttng_ht *ht);
msg.u.channel.tracefile_count, 0,
msg.u.channel.monitor,
msg.u.channel.live_timer_interval,
- NULL);
+ NULL, NULL);
if (new_channel == NULL) {
lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_OUTFD_ERROR);
goto end_nosignal;
* because the application can be in the tracing for instance.
*/
uint32_t ust_app_uid;
+ char root_shm_path[PATH_MAX];
char shm_path[PATH_MAX];
} LTTNG_PACKED ask_channel;
struct {
if (channel->uchan) {
lttng_ustconsumer_del_channel(channel);
}
+ /* Try to rmdir all directories under shm_path root. */
+ if (channel->root_shm_path[0]) {
+ (void) utils_recursive_rmdir(channel->root_shm_path);
+ }
free(channel);
}
uint64_t tracefile_size, uint64_t tracefile_count,
uint64_t session_id_per_pid, unsigned int monitor,
unsigned int live_timer_interval,
- const char *shm_path)
+ const char *root_shm_path, const char *shm_path)
{
assert(pathname);
assert(name);
return consumer_allocate_channel(key, session_id, pathname, name, uid,
gid, relayd_id, output, tracefile_size,
tracefile_count, session_id_per_pid, monitor,
- live_timer_interval, shm_path);
+ live_timer_interval, root_shm_path, shm_path);
}
/*
msg.u.ask_channel.session_id_per_pid,
msg.u.ask_channel.monitor,
msg.u.ask_channel.live_timer_interval,
+ msg.u.ask_channel.root_shm_path,
msg.u.ask_channel.shm_path);
if (!channel) {
goto end_channel_error;
}
consumer_metadata_cache_destroy(chan);
ustctl_destroy_channel(chan->uchan);
+ /* Try to rmdir all directories under shm_path root. */
+ if (chan->root_shm_path[0]) {
+ (void) utils_recursive_rmdir(chan->root_shm_path);
+ }
}
void lttng_ustconsumer_del_stream(struct lttng_consumer_stream *stream)
#include <grp.h>
#include <pwd.h>
#include <sys/file.h>
+#include <dirent.h>
#include <common/common.h>
#include <common/runas.h>
end:
return optstring;
}
+
+/*
+ * Try to remove a hierarchy of empty directories, recursively. Don't unlink
+ * any file.
+ */
+LTTNG_HIDDEN
+int utils_recursive_rmdir(const char *path)
+{
+ DIR *dir;
+ int dir_fd, ret = 0, closeret;
+ struct dirent *entry;
+
+ /* Open directory */
+ dir = opendir(path);
+ if (!dir) {
+ PERROR("Cannot open '%s' path", path);
+ return -1;
+ }
+ dir_fd = dirfd(dir);
+ if (dir_fd < 0) {
+ PERROR("dirfd");
+ return -1;
+ }
+
+ while ((entry = readdir(dir))) {
+ if (!strcmp(entry->d_name, ".")
+ || !strcmp(entry->d_name, ".."))
+ continue;
+ switch (entry->d_type) {
+ case DT_DIR:
+ {
+ char subpath[PATH_MAX];
+
+ strncpy(subpath, path, PATH_MAX);
+ subpath[PATH_MAX - 1] = '\0';
+ strncat(subpath, "/",
+ PATH_MAX - strlen(subpath) - 1);
+ strncat(subpath, entry->d_name,
+ PATH_MAX - strlen(subpath) - 1);
+ ret = utils_recursive_rmdir(subpath);
+ if (ret) {
+ goto end;
+ }
+ break;
+ }
+ case DT_REG:
+ ret = -EBUSY;
+ goto end;
+ default:
+ ret = -EINVAL;
+ goto end;
+ }
+ }
+end:
+ closeret = closedir(dir);
+ if (closeret) {
+ PERROR("closedir");
+ }
+ if (!ret) {
+ DBG3("Attempting rmdir %s", path);
+ ret = rmdir(path);
+ }
+ return ret;
+}
char *utils_generate_optstring(const struct option *long_options,
size_t opt_count);
int utils_create_lock_file(const char *filepath);
+int utils_recursive_rmdir(const char *path);
#endif /* _COMMON_UTILS_H */