Ensure we don't bust the open FD limit with many sessions.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
unsigned int switch_timer_interval; /* usecs */
unsigned int read_timer_interval; /* usecs */
enum lttng_ust_output output; /* output mode */
- /* The following fields are used internally within UST. */
- int shm_fd;
- int wait_fd;
- uint64_t memory_map_size;
};
/*
struct lttng_ust_obj;
+union ust_args {
+ struct {
+ int *shm_fd;
+ int *wait_fd;
+ uint64_t *memory_map_size;
+ } channel;
+ struct {
+ int *shm_fd;
+ int *wait_fd;
+ uint64_t *memory_map_size;
+ } stream;
+};
+
struct lttng_ust_objd_ops {
- long (*cmd)(int objd, unsigned int cmd, unsigned long arg);
+ long (*cmd)(int objd, unsigned int cmd, unsigned long arg,
+ union ust_args *args);
int (*release)(int objd);
};
size_t subbuf_size, size_t num_subbuf,
unsigned int switch_timer_interval,
unsigned int read_timer_interval,
- int *shm_fd, int *wait_fd,
- uint64_t *memory_map_size,
+ int **shm_fd, int **wait_fd,
+ uint64_t **memory_map_size,
struct ltt_channel *chan_priv_init);
void (*channel_destroy)(struct ltt_channel *ltt_chan);
struct lttng_ust_lib_ring_buffer *(*buffer_read_open)(struct channel *chan,
struct lttng_ust_shm_handle *handle,
- int *shm_fd, int *wait_fd,
- uint64_t *memory_map_size);
+ int **shm_fd, int **wait_fd,
+ uint64_t **memory_map_size);
void (*buffer_read_close)(struct lttng_ust_lib_ring_buffer *buf,
struct lttng_ust_shm_handle *handle);
int (*event_reserve)(struct lttng_ust_lib_ring_buffer_ctx *ctx,
size_t subbuf_size, size_t num_subbuf,
unsigned int switch_timer_interval,
unsigned int read_timer_interval,
- int *shm_fd, int *wait_fd,
- uint64_t *memory_map_size,
+ int **shm_fd, int **wait_fd,
+ uint64_t **memory_map_size,
struct ltt_channel *chan_priv_init);
struct ltt_channel *ltt_global_channel_create(struct ltt_session *session,
int overwrite, void *buf_addr,
size_t subbuf_size, size_t num_subbuf,
unsigned int switch_timer_interval,
unsigned int read_timer_interval,
- int *shm_fd, int *wait_fd,
- uint64_t *memory_map_size);
+ int **shm_fd, int **wait_fd,
+ uint64_t **memory_map_size);
int ltt_event_create(struct ltt_channel *chan,
struct lttng_ust_event *event_param,
int cpu)
{
struct channel *chan = handle->shadow_chan;
- int shm_fd, wait_fd;
- uint64_t memory_map_size;
+ int *shm_fd, *wait_fd;
+ uint64_t *memory_map_size;
struct lttng_ust_lib_ring_buffer *buf;
int ret;
size_t subbuf_size, size_t num_subbuf,
unsigned int switch_timer_interval,
unsigned int read_timer_interval,
- int *shm_fd, int *wait_fd,
- uint64_t *memory_map_size,
+ int **shm_fd, int **wait_fd,
+ uint64_t **memory_map_size,
struct ltt_channel *chan_priv_init)
{
struct ltt_channel *chan = NULL;
size_t subbuf_size, size_t num_subbuf,
unsigned int switch_timer_interval,
unsigned int read_timer_interval,
- int *shm_fd, int *wait_fd,
- uint64_t *memory_map_size,
+ int **shm_fd, int **wait_fd,
+ uint64_t **memory_map_size,
struct ltt_channel *chan_priv_init)
{
void *priv;
static
struct lttng_ust_lib_ring_buffer *ltt_buffer_read_open(struct channel *chan,
struct lttng_ust_shm_handle *handle,
- int *shm_fd, int *wait_fd,
- uint64_t *memory_map_size)
+ int **shm_fd, int **wait_fd,
+ uint64_t **memory_map_size)
{
struct lttng_ust_lib_ring_buffer *buf;
int cpu;
int cpu;
for_each_channel_cpu(cpu, chan) {
- int shm_fd, wait_fd;
- uint64_t memory_map_size;
+ int *shm_fd, *wait_fd;
+ uint64_t *memory_map_size;
buf = channel_get_ring_buffer(&client_config, chan,
cpu, handle, &shm_fd, &wait_fd,
size_t subbuf_size, size_t num_subbuf,
unsigned int switch_timer_interval,
unsigned int read_timer_interval,
- int *shm_fd, int *wait_fd,
- uint64_t *memory_map_size,
+ int **shm_fd, int **wait_fd,
+ uint64_t **memory_map_size,
struct ltt_channel *chan_priv_init)
{
void *priv;
static
struct lttng_ust_lib_ring_buffer *ltt_buffer_read_open(struct channel *chan,
struct lttng_ust_shm_handle *handle,
- int *shm_fd, int *wait_fd,
- uint64_t *memory_map_size)
+ int **shm_fd, int **wait_fd,
+ uint64_t **memory_map_size)
{
struct lttng_ust_lib_ring_buffer *buf;
int ltt_flush_buffer(struct channel *chan, struct lttng_ust_shm_handle *handle)
{
struct lttng_ust_lib_ring_buffer *buf;
- int shm_fd, wait_fd;
- uint64_t memory_map_size;
+ int *shm_fd, *wait_fd;
+ uint64_t *memory_map_size;
buf = channel_get_ring_buffer(&client_config, chan,
0, handle, &shm_fd, &wait_fd,
* @objd: the object descriptor
* @cmd: the command
* @arg: command arg
+ * @uargs: UST arguments (internal)
*
* This descriptor implements lttng commands:
* LTTNG_UST_SESSION
* The returned session will be deleted when its file descriptor is closed.
*/
static
-long lttng_cmd(int objd, unsigned int cmd, unsigned long arg)
+long lttng_cmd(int objd, unsigned int cmd, unsigned long arg,
+ union ust_args *uargs)
{
switch (cmd) {
case LTTNG_UST_SESSION:
int lttng_abi_create_channel(int session_objd,
struct lttng_ust_channel *chan_param,
- enum channel_type channel_type)
+ enum channel_type channel_type,
+ union ust_args *uargs)
{
struct ltt_session *session = objd_private(session_objd);
const struct lttng_ust_objd_ops *ops;
chan_param->num_subbuf,
chan_param->switch_timer_interval,
chan_param->read_timer_interval,
- &chan_param->shm_fd,
- &chan_param->wait_fd,
- &chan_param->memory_map_size,
+ &uargs->channel.shm_fd,
+ &uargs->channel.wait_fd,
+ &uargs->channel.memory_map_size,
&chan_priv_init);
if (!chan) {
ret = -EINVAL;
* @obj: the object
* @cmd: the command
* @arg: command arg
+ * @uargs: UST arguments (internal)
*
* This descriptor implements lttng commands:
* LTTNG_UST_CHANNEL
* The returned channel will be deleted when its file descriptor is closed.
*/
static
-long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg)
+long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg,
+ union ust_args *uargs)
{
struct ltt_session *session = objd_private(objd);
case LTTNG_UST_CHANNEL:
return lttng_abi_create_channel(objd,
(struct lttng_ust_channel *) arg,
- PER_CPU_CHANNEL);
+ PER_CPU_CHANNEL, uargs);
case LTTNG_UST_SESSION_START:
case LTTNG_UST_ENABLE:
return ltt_session_enable(session);
case LTTNG_UST_METADATA:
return lttng_abi_create_channel(objd,
(struct lttng_ust_channel *) arg,
- METADATA_CHANNEL);
+ METADATA_CHANNEL, uargs);
default:
return -EINVAL;
}
};
static
-long lttng_tracepoint_list_cmd(int objd, unsigned int cmd, unsigned long arg)
+long lttng_tracepoint_list_cmd(int objd, unsigned int cmd, unsigned long arg,
+ union ust_args *uargs)
{
struct lttng_ust_tracepoint_list *list = objd_private(objd);
struct lttng_ust_tracepoint_iter *tp =
};
static
-int lttng_abi_open_stream(int channel_objd, struct lttng_ust_stream *info)
+int lttng_abi_open_stream(int channel_objd, struct lttng_ust_stream *info,
+ union ust_args *uargs)
{
struct ltt_channel *channel = objd_private(channel_objd);
struct lttng_ust_lib_ring_buffer *buf;
int stream_objd, ret;
buf = channel->ops->buffer_read_open(channel->chan, channel->handle,
- &info->shm_fd, &info->wait_fd, &info->memory_map_size);
+ &uargs->stream.shm_fd,
+ &uargs->stream.wait_fd,
+ &uargs->stream.memory_map_size);
if (!buf)
return -ENOENT;
* @objd: the object descriptor
* @cmd: the command
* @arg: command arg
+ * @uargs: UST arguments (internal)
*
* This object descriptor implements lttng commands:
* LTTNG_UST_STREAM
* Channel and event file descriptors also hold a reference on the session.
*/
static
-long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg)
+long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg,
+ union ust_args *uargs)
{
struct ltt_channel *channel = objd_private(objd);
stream = (struct lttng_ust_stream *) arg;
/* stream used as output */
- return lttng_abi_open_stream(objd, stream);
+ return lttng_abi_open_stream(objd, stream, uargs);
}
case LTTNG_UST_EVENT:
{
* @objd: the object descriptor
* @cmd: the command
* @arg: command arg
+ * @uargs: UST arguments (internal)
*
* This object descriptor implements lttng commands:
* LTTNG_UST_STREAM
* Channel and event file descriptors also hold a reference on the session.
*/
static
-long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg)
+long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg,
+ union ust_args *uargs)
{
struct ltt_channel *channel = objd_private(objd);
stream = (struct lttng_ust_stream *) arg;
/* stream used as output */
- return lttng_abi_open_stream(objd, stream);
+ return lttng_abi_open_stream(objd, stream, uargs);
}
case LTTNG_UST_FLUSH_BUFFER:
return channel->ops->flush_buffer(channel->chan, channel->handle);
* @objd: the object descriptor
* @cmd: the command
* @arg: command arg
+ * @uargs: UST arguments (internal)
*
* This object descriptor implements lttng commands:
* (None for now. Access is done directly though shm.)
*/
static
-long lttng_rb_cmd(int objd, unsigned int cmd, unsigned long arg)
+long lttng_rb_cmd(int objd, unsigned int cmd, unsigned long arg,
+ union ust_args *uargs)
{
switch (cmd) {
default:
* @objd: the object descriptor
* @cmd: the command
* @arg: command arg
+ * @uargs: UST arguments (internal)
*
* This object descriptor implements lttng commands:
* LTTNG_UST_CONTEXT
* Disable recording for this event (strong disable)
*/
static
-long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg)
+long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg,
+ union ust_args *uargs)
{
struct ltt_event *event = objd_private(objd);
* @objd: the object descriptor
* @cmd: the command
* @arg: command arg
+ * @uargs: UST arguments (internal)
*
* This object descriptor implements lttng commands:
* LTTNG_UST_CONTEXT
* Disable recording for these loglevel events (strong disable)
*/
static
-long lttng_loglevel_cmd(int objd, unsigned int cmd, unsigned long arg)
+long lttng_loglevel_cmd(int objd, unsigned int cmd, unsigned long arg,
+ union ust_args *uargs)
{
struct session_loglevel *loglevel = objd_private(objd);
* @objd: the object descriptor
* @cmd: the command
* @arg: command arg
+ * @uargs: UST arguments (internal)
*
* This object descriptor implements lttng commands:
* LTTNG_UST_CONTEXT
* Disable recording for these wildcard events (strong disable)
*/
static
-long lttng_wildcard_cmd(int objd, unsigned int cmd, unsigned long arg)
+long lttng_wildcard_cmd(int objd, unsigned int cmd, unsigned long arg,
+ union ust_args *uargs)
{
struct session_wildcard *wildcard = objd_private(objd);
const struct lttng_ust_objd_ops *ops;
struct ustcomm_ust_reply lur;
int shm_fd, wait_fd;
+ union ust_args args;
ust_lock();
default:
if (ops->cmd)
ret = ops->cmd(lum->handle, lum->cmd,
- (unsigned long) &lum->u);
+ (unsigned long) &lum->u,
+ &args);
else
ret = -ENOSYS;
break;
* Special-case reply to send stream info.
* Use lum.u output.
*/
- lur.u.stream.memory_map_size = lum->u.stream.memory_map_size;
- shm_fd = lum->u.stream.shm_fd;
- wait_fd = lum->u.stream.wait_fd;
+ lur.u.stream.memory_map_size = *args.stream.memory_map_size;
+ shm_fd = *args.stream.shm_fd;
+ wait_fd = *args.stream.wait_fd;
break;
case LTTNG_UST_METADATA:
case LTTNG_UST_CHANNEL:
- lur.u.channel.memory_map_size = lum->u.channel.memory_map_size;
- shm_fd = lum->u.channel.shm_fd;
- wait_fd = lum->u.channel.wait_fd;
+ lur.u.channel.memory_map_size = *args.channel.memory_map_size;
+ shm_fd = *args.channel.shm_fd;
+ wait_fd = *args.channel.wait_fd;
break;
case LTTNG_UST_TRACER_VERSION:
lur.u.version = lum->u.version;
goto error;
}
}
+ /*
+ * We still have the memory map reference, and the fds have been
+ * sent to the sessiond. We can therefore close those fds.
+ */
+ if (lur.ret_code == USTCOMM_OK) {
+ switch (lum->cmd) {
+ case LTTNG_UST_STREAM:
+ if (shm_fd >= 0) {
+ ret = close(shm_fd);
+ if (ret) {
+ PERROR("Error closing stream shm_fd");
+ }
+ *args.stream.shm_fd = -1;
+ }
+ if (wait_fd >= 0) {
+ ret = close(wait_fd);
+ if (ret) {
+ PERROR("Error closing stream wait_fd");
+ }
+ *args.stream.wait_fd = -1;
+ }
+ break;
+ case LTTNG_UST_METADATA:
+ case LTTNG_UST_CHANNEL:
+ if (shm_fd >= 0) {
+ ret = close(shm_fd);
+ if (ret) {
+ PERROR("Error closing channel shm_fd");
+ }
+ *args.channel.shm_fd = -1;
+ }
+ if (wait_fd >= 0) {
+ ret = close(wait_fd);
+ if (ret) {
+ PERROR("Error closing channel wait_fd");
+ }
+ *args.channel.wait_fd = -1;
+ }
+ break;
+ }
+ }
+
error:
ust_unlock();
return ret;
size_t subbuf_size, size_t num_subbuf,
unsigned int switch_timer_interval,
unsigned int read_timer_interval,
- int *shm_fd, int *wait_fd,
- uint64_t *memory_map_size);
+ int **shm_fd, int **wait_fd,
+ uint64_t **memory_map_size);
/* channel_handle_create - for consumer. */
extern
const struct lttng_ust_lib_ring_buffer_config *config,
struct channel *chan, int cpu,
struct lttng_ust_shm_handle *handle,
- int *shm_fd, int *wait_fd,
- uint64_t *memory_map_size);
+ int **shm_fd, int **wait_fd,
+ uint64_t **memory_map_size);
extern int lib_ring_buffer_open_read(struct lttng_ust_lib_ring_buffer *buf,
struct lttng_ust_shm_handle *handle,
int shadow);
void *buf_addr, size_t subbuf_size,
size_t num_subbuf, unsigned int switch_timer_interval,
unsigned int read_timer_interval,
- int *shm_fd, int *wait_fd, uint64_t *memory_map_size)
+ int **shm_fd, int **wait_fd, uint64_t **memory_map_size)
{
int ret, cpu;
size_t shmsize, chansize;
const struct lttng_ust_lib_ring_buffer_config *config,
struct channel *chan, int cpu,
struct lttng_ust_shm_handle *handle,
- int *shm_fd, int *wait_fd,
- uint64_t *memory_map_size)
+ int **shm_fd, int **wait_fd,
+ uint64_t **memory_map_size)
{
struct shm_ref *ref;
assert(0);
}
}
- ret = close(obj->shm_fd);
- if (ret) {
- PERROR("close");
- assert(0);
+ if (obj->shm_fd >= 0) {
+ ret = close(obj->shm_fd);
+ if (ret) {
+ PERROR("close");
+ assert(0);
+ }
}
for (i = 0; i < 2; i++) {
if (obj->wait_fd[i] < 0)
static inline
int shm_get_object_data(struct lttng_ust_shm_handle *handle, struct shm_ref *ref,
- int *shm_fd, int *wait_fd, uint64_t *memory_map_size)
+ int **shm_fd, int **wait_fd, uint64_t **memory_map_size)
{
struct shm_object_table *table = handle->table;
struct shm_object *obj;
if (caa_unlikely(index >= table->allocated_len))
return -EPERM;
obj = &table->objects[index];
- *shm_fd = obj->shm_fd;
- *wait_fd = obj->wait_fd[0];
- *memory_map_size = obj->allocated_len;
+ *shm_fd = &obj->shm_fd;
+ *wait_fd = &obj->wait_fd[0];
+ *memory_map_size = &obj->allocated_len;
return 0;
}
struct channel *chan;
struct lttng_ust_lib_ring_buffer *buf;
int outfd, ret;
- int shm_fd, wait_fd;
- uint64_t memory_map_size;
+ int *shm_fd, *wait_fd;
+ uint64_t *memory_map_size;
chan = shmp(handle, handle->chan);
struct channel *chan;
struct lttng_ust_lib_ring_buffer *buf;
int outfd, ret;
- int shm_fd, wait_fd;
- uint64_t memory_map_size;
+ int *shm_fd, *wait_fd;
+ uint64_t *memory_map_size;
chan = shmp(handle, handle->chan);