goto file_error;
}
fd_install(stream_fd, stream_file);
- /* The stream holds a reference on the channel */
- atomic_long_inc(&channel_file->f_count);
+ /*
+ * The stream holds a reference to the channel within the generic ring
+ * buffer library, so no need to hold a refcount on the channel and
+ * session files here.
+ */
return stream_fd;
file_error:
struct lttng_event event_param;
int event_fd, ret;
struct file *event_file;
+ void *probe;
if (copy_from_user(&event_param, uevent_param, sizeof(event_param)))
return -EFAULT;
goto name_error;
}
event_name[PATH_MAX - 1] = '\0';
+
+ probe = ltt_probe_get(event_name);
+ if (!probe) {
+ ret = -ENOENT;
+ goto probe_error;
+ }
event_fd = get_unused_fd();
if (event_fd < 0) {
ret = event_fd;
* invariant for the rest of the session.
*/
event = ltt_event_create(channel, event_name, event_param.itype,
- (void *) 0x1, NULL); /* TODO connect real probe */
+ probe, NULL);
if (!event) {
goto event_error;
ret = -EEXIST;
file_error:
put_unused_fd(event_fd);
fd_error:
+ ltt_probe_put(probe);
+probe_error:
name_error:
kfree(event_name);
return ret;
{
struct ltt_channel *chan, *tmpchan;
struct ltt_event *event, *tmpevent;
+ int ret;
mutex_lock(&sessions_mutex);
session->active = 0;
+ list_for_each_entry(event, &session->events, list) {
+ ret = _ltt_event_unregister(event);
+ WARN_ON(ret);
+ }
synchronize_trace(); /* Wait for in-flight events to complete */
list_for_each_entry_safe(event, tmpevent, &session->events, list)
_ltt_event_destroy(event);
if (chan->free_event_id == -1UL)
goto full;
/*
- * This is O(n^2) (for each event loop called at event creation).
- * Might require a hash if we have lots of events.
+ * This is O(n^2) (for each event, the loop is called at event
+ * creation). Might require a hash if we have lots of events.
*/
list_for_each_entry(event, &chan->session->events, list)
if (!strcmp(event->name, name))
default:
WARN_ON_ONCE(1);
}
+ list_add(&event->list, &chan->session->events);
mutex_unlock(&sessions_mutex);
return event;
/*
* Only used internally at session destruction.
*/
-int _ltt_event_destroy(struct ltt_event *event)
+int _ltt_event_unregister(struct ltt_event *event)
{
int ret = -EINVAL;
default:
WARN_ON_ONCE(1);
}
+ return ret;
+}
+
+/*
+ * Only used internally at session destruction.
+ */
+void _ltt_event_destroy(struct ltt_event *event)
+{
kfree(event->name);
+ list_del(&event->list);
kmem_cache_free(event_cache, event);
- return ret;
}
/**
char *name,
enum instrum_type itype,
void *probe, void *filter);
-int _ltt_event_destroy(struct ltt_event *event);
+int _ltt_event_unregister(struct ltt_event *event);
+void _ltt_event_destroy(struct ltt_event *event);
void ltt_transport_register(struct ltt_transport *transport);
void ltt_transport_unregister(struct ltt_transport *transport);
static DEFINE_MUTEX(probe_mutex);
static struct kmem_cache *probe_cache;
-static void *find_probe(const char *name)
+static struct ltt_probe *find_probe(const char *name)
{
struct ltt_probe *probe;
list_for_each_entry(probe, &probe_list, list) {
if (!strcmp(probe->name, name))
- return probe->cb;
+ return probe;
}
return NULL;
}