+static
+int lttng_abi_create_event(struct file *channel_filp,
+ struct lttng_event __user *uevent_param)
+{
+ struct ltt_channel *channel = channel_filp->private_data;
+ struct ltt_event *event;
+ char *event_name;
+ struct lttng_event event_param;
+ int event_fd, ret;
+
+ 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)) {
+ ret = -EFAULT;
+ goto name_error;
+ }
+ event_name[PATH_MAX - 1] = '\0';
+ event = ltt_event_create(channel, event_param->itype, event_name, NULL);
+ if (!event)
+ return -EEXIST;
+
+ event_fd = get_unused_fd_flags(O_RDWR);
+ if (event_fd < 0) {
+ ret = event_fd;
+ goto fd_error;
+ }
+ event_filp = anon_inode_getfile("[lttng_event]",
+ <tng_event_fops,
+ event, O_RDWR);
+ if (IS_ERR(event_filp)) {
+ ret = PTR_ERR(event_filp);
+ goto file_error;
+ }
+
+ /* The event holds a reference on the channel */
+ atomic_inc(&channel_filp->f_count);
+ return event_fd;
+
+file_error:
+ put_unused_fd(event_fd);
+fd_error:
+ ltt_event_destroy(event);
+name_error:
+ kfree(event_name);
+ return ret;
+}