From 03037b98a2469aac6977126bb44ea443634e2ec8 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 24 Nov 2010 21:19:06 -0500 Subject: [PATCH] Implement ABI release fops and teardown paths Signed-off-by: Mathieu Desnoyers --- ltt-debugfs-abi.c | 123 +++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 67 deletions(-) diff --git a/ltt-debugfs-abi.c b/ltt-debugfs-abi.c index d9d93ac4..1e3adfa1 100644 --- a/ltt-debugfs-abi.c +++ b/ltt-debugfs-abi.c @@ -56,7 +56,7 @@ static int lttng_abi_create_session(void) { struct ltt_session *session; - struct file *session_file; + struct file *session_filp; int session_fd; session = ltt_session_create(); @@ -67,14 +67,14 @@ int lttng_abi_create_session(void) ret = session_fd; goto fd_error; } - session_file = anon_inode_getfile("[lttng_session]", + session_filp = anon_inode_getfile("[lttng_session]", <tng_session_fops, session, O_RDWR); - if (IS_ERR(session_file)) { - ret = PTR_ERR(session_file); + if (IS_ERR(session_filp)) { + ret = PTR_ERR(session_filp); goto file_error; } - fd_install(session_fd, session_file); + fd_install(session_fd, session_filp); return session_fd; file_error: @@ -108,23 +108,10 @@ long lttng_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } -#ifdef CONFIG_COMPAT -static -long lttng_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case LTTNG_SESSION: - return lttng_abi_create_session(); - default: - return -ENOIOCTLCMD; - } -} -#endif - static const struct file_operations lttng_fops = { .unlocked_ioctl = lttng_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = lttng_compat_ioctl, + .compat_ioctl = lttng_ioctl, #endif } @@ -140,15 +127,6 @@ int lttng_abi_create_channel(struct file *session_filp, if (copy_from_user(&chan_param, uchan_param, sizeof(chan_param))) return -EFAULT; - chan = ltt_channel_create(session, chan_param->overwrite, NULL, - chan_param->subbuf_size, - chan_param->num_subbuf, - chan_param->switch_timer_interval, - chan_param->read_timer_interval); - if (!chan) { - ret = -ENOMEM; - goto chan_error; - } chan_fd = get_unused_fd_flags(O_RDWR); if (chan_fd < 0) { ret = chan_fd; @@ -156,22 +134,36 @@ int lttng_abi_create_channel(struct file *session_filp, } chan_filp = anon_inode_getfile("[lttng_channel]", <tng_channel_fops, - chan, O_RDWR); + NULL, O_RDWR); if (IS_ERR(chan_filp)) { ret = PTR_ERR(chan_filp); goto file_error; } - + /* + * We tolerate no failure path after channel creation. It will stay + * invariant for the rest of the session. + */ + chan = ltt_channel_create(session, chan_param->overwrite, NULL, + chan_param->subbuf_size, + chan_param->num_subbuf, + chan_param->switch_timer_interval, + chan_param->read_timer_interval); + if (!chan) { + ret = -ENOMEM; + goto chan_error; + } + chan_filp->private_data = chan; + fd_install(chan_fd, chan_filp); /* The channel created holds a reference on the session */ atomic_inc(&session_filp->f_count); return chan_fd; +chan_error: + fput(chan_filp); file_error: put_unused_fd(chan_fd); fd_error: - ltt_channel_destroy(chan); -chan_error: return ret; } @@ -199,23 +191,26 @@ long lttng_session_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } -#ifdef CONFIG_COMPAT +/* + * Called when the last file reference is dropped. + * + * Big fat note: channels and events are invariant for the whole session after + * their creation. So this session destruction also destroys all channel and + * event structures specific to this session (they are not destroyed when their + * individual file is released). + */ static -long lttng_session_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +int lttng_session_release(struct inode *inode, struct file *file) { - switch (cmd) { - case LTTNG_CHANNEL: - return lttng_abi_create_channel(filp, (struct lttng_channel __user *)arg); - default: - return -ENOIOCTLCMD; - } + struct ltt_session *session = file->private_data; + return ltt_session_destroy(session); } -#endif static const struct file_operations lttng_session_fops = { + .release = lttng_session_release, .unlocked_ioctl = lttng_session_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = lttng_session_compat_ioctl, + .compat_ioctl = lttng_session_ioctl, #endif } @@ -242,7 +237,7 @@ int lttng_abi_open_stream(struct file *channel_filp) ret = PTR_ERR(stream_filp); goto file_error; } - + fd_install(stream_fd, stream_filp); /* The stream holds a reference on the channel */ atomic_inc(&channel_filp->f_count); return stream_fd; @@ -274,31 +269,39 @@ int lttng_abi_create_event(struct file *channel_filp, 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); + <tng_event_fops, + NULL, O_RDWR); if (IS_ERR(event_filp)) { ret = PTR_ERR(event_filp); 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_param->itype, event_name, NULL); + if (!event) { + goto event_error; + ret = -EEXIST; + } + event_filp->private_data = event; + fd_install(event_fd, event_filp); /* The event holds a reference on the channel */ atomic_inc(&channel_filp->f_count); + kfree(event_name); return event_fd; +event_error: + fput(event_filp); file_error: put_unused_fd(event_fd); fd_error: - ltt_event_destroy(event); name_error: kfree(event_name); return ret; @@ -334,21 +337,6 @@ long lttng_channel_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } -#ifdef CONFIG_COMPAT -static -long lttng_channel_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case LTTNG_STREAM: - return lttng_abi_open_stream(filp); - case LTTNG_EVENT: - return lttng_abi_create_event(filp, (struct lttng_event __user *)arg); - default: - return -ENOIOCTLCMD; - } -} -#endif - /** * lttng_channel_poll - lttng stream addition/removal monitoring * @@ -375,10 +363,11 @@ unsigned int lttng_channel_poll(struct file *filp, poll_table *wait) } static const struct file_operations lttng_channel_fops = { + .release = lttng_channel_release, .poll = lttng_channel_poll, .unlocked_ioctl = lttng_channel_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = lttng_channel_compat_ioctl, + .compat_ioctl = lttng_channel_ioctl, #endif } -- 2.34.1