+static
+int lttng_abi_create_event(struct file *channel_file,
+ struct lttng_event __user *uevent_param)
+{
+ struct ltt_channel *channel = channel_file->private_data;
+ struct ltt_event *event;
+ char *event_name;
+ 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;
+ event_name = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!event_name)
+ return -ENOMEM;
+ if (strncpy_from_user(event_name, uevent_param->name, PATH_MAX) < 0) {
+ ret = -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;
+ goto fd_error;
+ }
+ event_file = anon_inode_getfile("[lttng_event]",
+ <tng_event_fops,
+ NULL, O_RDWR);
+ if (IS_ERR(event_file)) {
+ ret = PTR_ERR(event_file);
+ goto file_error;
+ }
+ /*
+ * We tolerate no failure path after event creation. It will stay
+ * invariant for the rest of the session.
+ */
+ event = ltt_event_create(channel, event_name, event_param.itype,
+ probe, NULL);
+ if (!event) {
+ goto event_error;
+ ret = -EEXIST;
+ }
+ event_file->private_data = event;
+ fd_install(event_fd, event_file);
+ /* The event holds a reference on the channel */
+ atomic_long_inc(&channel_file->f_count);
+ kfree(event_name);
+ return event_fd;
+
+event_error:
+ fput(event_file);
+file_error:
+ put_unused_fd(event_fd);
+fd_error:
+ ltt_probe_put(probe);
+probe_error:
+name_error:
+ kfree(event_name);
+ return ret;
+}